From 063424c4908a1f1cd81efb77ed3d003f467eb2f3 Mon Sep 17 00:00:00 2001 From: Aere Network Date: Thu, 1 Oct 2026 15:21:46 +0300 Subject: [PATCH] Patch 0008: AIP-22 stages 1 to 3 and the rest of the chain-2800 fleet distribution of 2026-09-29; run-node.sh applies it, passes the stage-3 properties, ships the registry v3 epoch and rebuilds when the patch set changes --- README.md | 8 + RUN-A-NODE.md | 35 + SPEC.md | 4 + patches/0008-aere-pq-aip22.patch | 22825 +++++++++++++++++++++++ registries/SHA256SUMS | 1 + registries/epoca-v3-2800-20836228.json | 187 + run-node.sh | 17 +- 7 files changed, 23074 insertions(+), 3 deletions(-) create mode 100644 patches/0008-aere-pq-aip22.patch create mode 100644 registries/epoca-v3-2800-20836228.json diff --git a/README.md b/README.md index 92b81ea..36526c2 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,14 @@ Both patches target upstream commit `d2032017bb3b8cb215a97303980a1e4a643f7180`, | `patches/0001-aere-pqc-precompiles-mainnet.patch` | `0x0AE1` to `0x0AE5`, the five live on mainnet | pristine upstream `d2032017` | | `patches/0002-aere-pqc-precompiles-testnet.patch` | `0x0AE6` and `0x0AE7`, testnet only | the tree after 0001 | | `patches/0003-aere-pq-anchor.patch` | the post-quantum certificate anchor for QBFT | pristine upstream `d2032017` | +| `patches/0004-aere-basefee-floor.patch` | the 1 Gwei base-fee floor live from block 10,141,734 | the tree after 0001 and 0003 | +| `patches/0005-aere-eip2935-futureeips.patch` | EIP-2935 in the futureEips milestone, Osaka block format kept | the tree after 0004 | +| `patches/0006-aere-pq-transactions.patch` | AIP-20, transaction type `0x50` authorized by ML-DSA | the tree after 0005 | +| `patches/0007-aere-pq-finality.patch` | AIP-21, `aere_getPqFinality` and the on-disk seal window | the tree after 0006 | +| `patches/0008-aere-pq-aip22.patch` | AIP-22 stages 1 to 3 (post-quantum validator ids from block 20,836,228) and the rest of the fleet distribution of 2026-09-29 | the tree after 0007 | + +`run-node.sh` applies 0001 and 0003 to 0008, in that order; 0002 is for the testnet only. A node +built without 0008 stops at block 20,836,227. Patch 0003 is a different kind of thing from the first two and is described in `anchor/README.md`. It changes twenty upstream files and adds fifty-five, and it changes one build file by one line. diff --git a/RUN-A-NODE.md b/RUN-A-NODE.md index 7e46eb6..0d0ae23 100644 --- a/RUN-A-NODE.md +++ b/RUN-A-NODE.md @@ -232,6 +232,37 @@ patch message; the in-file "Modifications Copyright" blocks for those files are the delta (it is exact to the fleet sources) and enter the production sources with the next fleet distribution. +## Patch 0008: AIP-22 stages 1 to 3 (2026-10-01) + +**A node built from patches 0001 and 0003 to 0007 stops at block 20,836,227.** From block +20,836,228 (AIP-22 stage 3, 2026-09-30) the header of every chain-2800 block names the validators by +post-quantum ids from the registry v3 epoch, and such a node refuses the block with +`Invalid block header: Incorrect validators`. Measured: a follower built from patches 0001 and 0003 +to 0007 refuses block 20,836,228 with exactly that message. + +`patches/0008-aere-pq-aip22.patch` brings the recipe to the exact source tree of the chain-2800 fleet +distribution of 2026-09-29: AIP-22 stages 1 to 3 (and the code of stages 4 and 5, inactive unless +their own activation properties are set, which `run-node.sh` does not do), and the rest of what the +fleet runs (see the patch message). `run-node.sh` applies it, passes the four stage-3 properties +(`aere.pq.identityBlock`, `aere.pq.registryV3`, `aere.pq.registryV3.hashes`, +`aere.pq.registryV3.keysFrom`) and verifies the registry v3 epoch file in `registries/` against +`SHA256SUMS`. **If you built a node before, `run-node.sh` now rebuilds it**: the patch set is +fingerprinted, and a binary built from another patch set is no longer reused. + +Measured 2026-10-01: patches 0001 and 0003 to 0008 applied with plain `git apply` on a pristine +`d2032017` checkout reproduce the patch generator's tree with zero differences; the build has the +same 3,554 classes as the fleet distribution, none only on one side, and **no class with different +code** (`javap -p -c` on the 45 pairs whose bytes differ: they differ only in the line-number table, +because of the in-file licence notices). The same comparison on the build without 0008 finds 51 +classes missing and 56 with different code, so the comparison can tell them apart. A follower built +from this recipe, started on a database that ended at block 20,836,227, imported block 20,836,228 and +went on with ten peers and no refusal (20,840,327 within two minutes). + +A follower started with `run-node.sh` logs `AERE-PQC-EMG-CEILING-01` at ERROR level while it +imports: that is the emergency seal-count ceiling the script sets for followers (see the comment +above `ANCHOR_MIN_SEALS_CEILING` in the script), not a refusal. A refusal names the block and the +rule that refused it. + --- ## Sizing the JVM heap: bigger is not faster @@ -324,6 +355,10 @@ export BESU_OPTS="\ -Daere.pq.anchorV2Block=17047600 \ -Daere.pq.chainId=2800 \ -Daere.pq.hybridRegistry=$REG/hibrid-10.properties \ +-Daere.pq.identityBlock=20836228 \ +-Daere.pq.registryV3.hashes=20836228:0x5c6f09a44f1b6cc0e2264c9beaf4496e5fdd5bf8ee0dc6571fb5616c80a2e900 \ +-Daere.pq.registryV3.keysFrom=20836228 \ +-Daere.pq.registryV3=$REG/epoca-v3-2800-20836228.json \ -Daere.pq.schemeSchedule=17047568:falcon-512+slh-dsa-sha2-128s,20746736:falcon-512/32+slh-dsa-sha2-128s/128 \ -Daere.pqtx.forkBlock=19900000 \ -Daere.pq.anchor.minSealsCeiling=1" diff --git a/SPEC.md b/SPEC.md index 0bc042b..3615485 100644 --- a/SPEC.md +++ b/SPEC.md @@ -494,6 +494,10 @@ passes"): -Daere.pq.anchorV2Block=17047600 -Daere.pq.chainId=2800 -Daere.pq.hybridRegistry=/hibrid-10.properties +-Daere.pq.identityBlock=20836228 +-Daere.pq.registryV3.hashes=20836228:0x5c6f09a44f1b6cc0e2264c9beaf4496e5fdd5bf8ee0dc6571fb5616c80a2e900 +-Daere.pq.registryV3.keysFrom=20836228 +-Daere.pq.registryV3=/epoca-v3-2800-20836228.json -Daere.pq.schemeSchedule=17047568:falcon-512+slh-dsa-sha2-128s,20746736:falcon-512/32+slh-dsa-sha2-128s/128 -Daere.pqtx.forkBlock=19900000 -Daere.pq.anchor.minSealsCeiling=1 diff --git a/patches/0008-aere-pq-aip22.patch b/patches/0008-aere-pq-aip22.patch new file mode 100644 index 0000000..75381d3 --- /dev/null +++ b/patches/0008-aere-pq-aip22.patch @@ -0,0 +1,22825 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aere Network +Date: Thu, 01 Oct 2026 12:18:51 +0000 +Subject: [PATCH] Aere Network: AIP-22 stages 1 to 3 and the rest of the chain-2800 fleet distribution of 2026-09-29 + +AERE patch 0008: AIP-22 stages 1 to 3, and everything else the chain-2800 fleet runs + +Why this patch exists: from block 20,836,228 (AIP-22 stage 3, 2026-09-30) the header +of every chain-2800 block and qbft_getValidatorsByBlockNumber name the validators by +post-quantum ids (registry v3) instead of ECDSA addresses. A node built from patches +0001 to 0007 cannot read that list and stops at block 20,836,227. This patch brings +the recipe to the exact source tree the chain-2800 fleet distribution of 2026-09-29 +was built from, so that a node built from it follows the chain past that height. + +What it changes, as one delta over the tree produced by patches 0001 and 0003 to 0007: +- AIP-22 stage 1 (anchor threshold schedule, at least seven of ten seals per scheme + from block 20,715,632; a configuration value, read by code already in 0003) and + stage 2 (a per-scheme anchor interval in aere.pq.schemeSchedule: Falcon-512 at every + 32nd block and SLH-DSA-SHA2-128s at every 128th from block 20,746,736); +- AIP-22 stage 3: the registry v3 format and its loader (PqRegistryV3, with its + conformance vectors), post-quantum validator ids in the header, the vote tally and + the validator peers (AerePqIdentity), read through aere.pq.identityBlock, + aere.pq.registryV3, aere.pq.registryV3.hashes and aere.pq.registryV3.keysFrom; +- the code of AIP-22 stages 4 and 5 (AerePqFinality, PqHeaderSealRule, AerePqHeaderSeal, + PqCheckpointRule, the finalized tag AerePqFinalityTags). It is inactive unless its + own activation properties are set; run-node.sh does not set them and chain 2800 has + not activated those stages; +- SLH-DSA-SHA2-128s signing split across threads and done once per round, with the + same signature bytes; +- blocks that carry withdrawals are rejected on BFT chains (QBFT/IBFT2 have no + withdrawals); tighter bounds on consensus message lists and rounds; a gas-cap check; +- the optional Block-STM parallel block processor and its wiring in + MainnetProtocolSpecs, and the JSON-RPC read path that reports an unavailable state + as an error instead of resolving "latest" to a null state during import. These two + were the known differences between this recipe and the fleet before this revision; + they are now in the recipe as well. + +Files that are only backups or notes in the fleet tree (*.bak-*, BAZA.txt) are not in +this patch. Nothing else is left out: patches 0001 and 0003 to 0008 applied on a +pristine d2032017 checkout reproduce the fleet source tree file for file, apart from +the in-file licence notices described below and three lines where the fleet sources +named internal machines: one comment in QbftRound (rewritten with the same number of +lines, so the compiled class is identical) and the report path and header line of a +benchmark test, which is not part of the distribution; and one line added to a test +vector file, declaring that the 32-byte value in it is the public key of a test +vector (no private key is in this patch). + +The upstream copyright header ("Copyright contributors to Besu" or the ConsenSys +header) of every modified file is kept unchanged, per Apache License 2.0 section 4(c). +Every upstream Java file this patch modifies for the first time receives, in this diff, +the in-file modification notice that section 4(b) requires, naming this patch; files +already modified by patches 0003 to 0007 keep the notice naming the patch that first +modified them (the fleet sources of 2026-09-29 do not carry those notices; the recipe +does, and this diff leaves them in place). The changed files are also listed above +the diff, which is the statement of modification that section 4(b) requires. +--- + app/src/main/java/org/hyperledger/besu/controller/PqTipAdoptionGate.java | 278 +++++++++++ + .../java/org/hyperledger/besu/controller/QbftBesuControllerBuilder.java | 110 ++++ + .../java/org/hyperledger/besu/controller/PqTipAdoptionGateModeTest.java | 180 +++++++ + .../main/java/org/hyperledger/besu/consensus/common/bft/AerePqFinality.java | 194 ++++++++ + .../java/org/hyperledger/besu/consensus/common/bft/AerePqFinalityTags.java | 202 ++++++++ + .../java/org/hyperledger/besu/consensus/common/bft/AerePqHeaderSeal.java | 95 ++++ + .../main/java/org/hyperledger/besu/consensus/common/bft/AerePqIdentity.java | 561 +++++++++++++++++++++ + .../java/org/hyperledger/besu/consensus/common/bft/BftBlockHashing.java | 8 +- + .../java/org/hyperledger/besu/consensus/common/bft/BftBlockInterface.java | 7 +- + .../main/java/org/hyperledger/besu/consensus/common/bft/BftExtraData.java | 58 +++ + .../java/org/hyperledger/besu/consensus/common/bft/FalconSealSupport.java | 206 +++++++- + .../java/org/hyperledger/besu/consensus/common/bft/HybridSealProducer.java | 109 +++- + .../java/org/hyperledger/besu/consensus/common/bft/HybridSealSupport.java | 90 +++- + .../src/main/java/org/hyperledger/besu/consensus/common/bft/PqAnchor.java | 5 +- + .../main/java/org/hyperledger/besu/consensus/common/bft/PqAnchorLapse.java | 24 +- + .../java/org/hyperledger/besu/consensus/common/bft/PqRegistryHashTool.java | 14 +- + .../main/java/org/hyperledger/besu/consensus/common/bft/PqRegistryV3.java | 963 ++++++++++++++++++++++++++++++++++++ + .../java/org/hyperledger/besu/consensus/common/bft/PqSchemeSchedule.java | 134 ++++- + .../src/main/java/org/hyperledger/besu/consensus/common/bft/PqSealed.java | 61 +++ + .../besu/consensus/common/bft/blockcreation/BftBlockCreator.java | 23 +- + .../besu/consensus/common/bft/blockcreation/BftBlockCreatorFactory.java | 9 +- + .../besu/consensus/common/bft/blockcreation/BftMiningCoordinator.java | 14 +- + .../besu/consensus/common/bft/blockcreation/PqAnchorProducer.java | 18 +- + .../hyperledger/besu/consensus/common/bft/messagewrappers/BftMessage.java | 12 + + .../org/hyperledger/besu/consensus/common/bft/network/ValidatorPeers.java | 18 +- + .../java/org/hyperledger/besu/consensus/common/bft/payload/SignedData.java | 19 +- + .../main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/ADRS.java | 10 +- + .../main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/Fors.java | 10 +- + .../src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/HT.java | 22 +- + .../org/hyperledger/besu/consensus/common/bft/slhdsa/IndexedDigest.java | 10 +- + .../java/org/hyperledger/besu/consensus/common/bft/slhdsa/JdkDigest.java | 10 +- + .../java/org/hyperledger/besu/consensus/common/bft/slhdsa/NodeEntry.java | 10 +- + .../src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/PK.java | 10 +- + .../org/hyperledger/besu/consensus/common/bft/slhdsa/ParallelSigning.java | 257 ++++++++++ + .../src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SIG.java | 10 +- + .../java/org/hyperledger/besu/consensus/common/bft/slhdsa/SIG_FORS.java | 10 +- + .../java/org/hyperledger/besu/consensus/common/bft/slhdsa/SIG_XMSS.java | 10 +- + .../src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SK.java | 10 +- + .../java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAEngine.java | 10 +- + .../hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAEngineProvider.java | 10 +- + .../besu/consensus/common/bft/slhdsa/SLHDSAKeyGenerationParameters.java | 10 +- + .../besu/consensus/common/bft/slhdsa/SLHDSAKeyPairGenerator.java | 10 +- + .../hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAKeyParameters.java | 10 +- + .../org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAParameters.java | 10 +- + .../besu/consensus/common/bft/slhdsa/SLHDSAPrivateKeyParameters.java | 10 +- + .../besu/consensus/common/bft/slhdsa/SLHDSAPublicKeyParameters.java | 10 +- + .../java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSASigner.java | 17 +- + .../java/org/hyperledger/besu/consensus/common/bft/slhdsa/WotsPlus.java | 10 +- + .../org/hyperledger/besu/consensus/common/bft/tools/PqRegistryV3Tool.java | 288 +++++++++++ + .../hyperledger/besu/consensus/common/validator/blockbased/VoteTally.java | 25 + + .../besu/consensus/common/validator/blockbased/VoteTallyUpdater.java | 18 +- + .../java/org/hyperledger/besu/consensus/common/bft/AereKeysFromV3Test.java | 192 +++++++ + .../java/org/hyperledger/besu/consensus/common/bft/AereLocalKeysV3Test.java | 164 ++++++ + .../org/hyperledger/besu/consensus/common/bft/AerePqFinalityAuthorTest.java | 243 +++++++++ + .../org/hyperledger/besu/consensus/common/bft/AerePqFinalityTagsTest.java | 235 +++++++++ + .../java/org/hyperledger/besu/consensus/common/bft/AerePqIdentityTest.java | 135 +++++ + .../org/hyperledger/besu/consensus/common/bft/HybridSealProducerTest.java | 29 ++ + .../org/hyperledger/besu/consensus/common/bft/HybridSignerRegistryTest.java | 8 +- + .../java/org/hyperledger/besu/consensus/common/bft/PqAnchorLapseTest.java | 64 +-- + .../test/java/org/hyperledger/besu/consensus/common/bft/PqAnchorTest.java | 28 +- + .../java/org/hyperledger/besu/consensus/common/bft/PqRegistryV3Test.java | 509 +++++++++++++++++++ + .../org/hyperledger/besu/consensus/common/bft/PqSchemeScheduleTest.java | 56 ++- + .../besu/consensus/common/bft/slhdsa/SlhDsaParallelSigningTest.java | 137 +++++ + .../besu/consensus/common/validator/blockbased/VoteTallyIdentityTest.java | 75 +++ + consensus/common/src/test/resources/aere/registry-v3/n01-format.json | 62 +++ + consensus/common/src/test/resources/aere/registry-v3/n02-chain.json | 62 +++ + consensus/common/src/test/resources/aere/registry-v3/n03-extra-field.json | 63 +++ + .../common/src/test/resources/aere/registry-v3/n05-unknown-scheme.json | 64 +++ + .../common/src/test/resources/aere/registry-v3/n06-required-scheme.json | 60 +++ + consensus/common/src/test/resources/aere/registry-v3/n07-falcon-header.json | 62 +++ + consensus/common/src/test/resources/aere/registry-v3/n08-pop.json | 62 +++ + consensus/common/src/test/resources/aere/registry-v3/n09-id-derivation.json | 62 +++ + consensus/common/src/test/resources/aere/registry-v3/n10-duplicate-id.json | 62 +++ + consensus/common/src/test/resources/aere/registry-v3/n11-duplicate-key.json | 62 +++ + .../common/src/test/resources/aere/registry-v3/n12-rotation-one-key.json | 50 ++ + .../common/src/test/resources/aere/registry-v3/n12b-rotation-wrong-key.json | 51 ++ + .../common/src/test/resources/aere/registry-v3/n13-rotation-unchanged.json | 55 ++ + .../common/src/test/resources/aere/registry-v3/n14-ecdsa-wrong-key.json | 62 +++ + .../common/src/test/resources/aere/registry-v3/n14b-ecdsa-missing.json | 58 +++ + consensus/common/src/test/resources/aere/registry-v3/n15-transport.json | 62 +++ + consensus/common/src/test/resources/aere/registry-v3/n16-declared-hash.json | 63 +++ + consensus/common/src/test/resources/aere/registry-v3/ok-epoch-a.json | 71 +++ + .../common/src/test/resources/aere/registry-v3/ok-epoch-b-rotation.json | 60 +++ + consensus/common/src/test/resources/vector-slh-dsa-noble-2026-09-03.json | 10 + + .../org/hyperledger/besu/consensus/qbft/core/messagewrappers/Proposal.java | 10 +- + .../hyperledger/besu/consensus/qbft/core/messagewrappers/RoundChange.java | 8 +- + .../besu/consensus/qbft/core/network/QbftMessageTransmitter.java | 4 +- + .../org/hyperledger/besu/consensus/qbft/core/payload/CommitPayload.java | 16 +- + .../org/hyperledger/besu/consensus/qbft/core/payload/MessageFactory.java | 8 +- + .../org/hyperledger/besu/consensus/qbft/core/payload/PreparePayload.java | 17 +- + .../org/hyperledger/besu/consensus/qbft/core/payload/ProposalPayload.java | 17 +- + .../hyperledger/besu/consensus/qbft/core/payload/RoundChangePayload.java | 22 +- + .../org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRound.java | 100 +++- + .../hyperledger/besu/consensus/qbft/core/statemachine/QbftRoundFactory.java | 9 +- + .../org/hyperledger/besu/consensus/qbft/core/statemachine/RoundState.java | 10 + + .../org/hyperledger/besu/consensus/qbft/core/types/QbftBlockCreator.java | 16 + + .../hyperledger/besu/consensus/qbft/core/validation/CommitValidator.java | 5 +- + .../besu/consensus/qbft/core/validation/PqCommitEnforcement.java | 55 +- + .../besu/consensus/qbft/core/validation/PqFinalityLayersGuard.java | 181 +++++++ + .../besu/consensus/qbft/core/validation/RoundChangePayloadValidator.java | 7 +- + .../besu/consensus/qbft/core/messagewrappers/AereD434ListBoundsTest.java | 73 +++ + .../besu/consensus/qbft/core/statemachine/PqCommitSealsSignedOnceTest.java | 210 ++++++++ + .../besu/consensus/qbft/core/validation/AereD434RoundCapTest.java | 61 +++ + .../besu/consensus/qbft/core/validation/AereFinalityMessageTest.java | 204 ++++++++ + .../besu/consensus/qbft/core/validation/AereFinalityVectorsWriter.java | 206 ++++++++ + .../besu/consensus/qbft/core/validation/AereIdentityMessageTest.java | 165 ++++++ + .../besu/consensus/qbft/core/validation/PqFinalityLayersGuardTest.java | 130 +++++ + .../besu/consensus/qbft/core/validation/PqHybridEnforcementTest.java | 39 ++ + .../besu/consensus/qbft/core/validation/PqHybridRotationV3Test.java | 171 +++++++ + .../besu/consensus/qbft/QbftBlockHeaderValidationRulesetFactory.java | 13 +- + .../main/java/org/hyperledger/besu/consensus/qbft/QbftExtraDataCodec.java | 40 +- + .../hyperledger/besu/consensus/qbft/adaptor/QbftBlockCreatorAdaptor.java | 32 ++ + .../org/hyperledger/besu/consensus/qbft/adaptor/QbftFinalStateImpl.java | 12 +- + .../besu/consensus/qbft/headervalidationrules/PqAnchorDigestRule.java | 8 +- + .../besu/consensus/qbft/headervalidationrules/PqAnchorSealsRule.java | 42 +- + .../besu/consensus/qbft/headervalidationrules/PqCheckpointRule.java | 133 +++++ + .../besu/consensus/qbft/headervalidationrules/PqHeaderSealRule.java | 259 ++++++++++ + .../java/org/hyperledger/besu/consensus/qbft/AereIdentityHeaderTest.java | 144 ++++++ + .../consensus/qbft/headervalidationrules/PqAnchorDisarmedWindowTest.java | 92 +++- + .../besu/consensus/qbft/headervalidationrules/PqAnchorV2RulesTest.java | 34 ++ + .../besu/consensus/qbft/headervalidationrules/PqCheckpointRuleTest.java | 75 +++ + .../besu/consensus/qbft/headervalidationrules/PqHeaderSealStage5Test.java | 478 ++++++++++++++++++ + .../besu/ethereum/api/jsonrpc/internal/methods/EthGetBalance.java | 20 +- + .../hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetCode.java | 23 +- + .../besu/ethereum/api/jsonrpc/internal/methods/EthGetStorageAt.java | 20 +- + .../besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionCount.java | 27 +- + .../java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java | 82 ++- + .../api/jsonrpc/internal/methods/AereStateUnavailableIsAnErrorTest.java | 138 ++++++ + .../org/hyperledger/besu/ethereum/api/query/AereHeadStateRetryTest.java | 140 ++++++ + .../java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java | 28 +- + .../org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java | 6 +- + .../java/org/hyperledger/besu/ethereum/mainnet/WithdrawalsValidator.java | 37 ++ + .../org/hyperledger/besu/ethereum/mainnet/blockstm/AereBlockStmEngine.java | 528 ++++++++++++++++++++ + .../besu/ethereum/mainnet/blockstm/AereBlockStmPreprocessing.java | 119 +++++ + .../hyperledger/besu/ethereum/mainnet/blockstm/AereBlockStmProcessor.java | 160 ++++++ + .../java/org/hyperledger/besu/ethereum/mainnet/blockstm/BaseReader.java | 67 +++ + .../java/org/hyperledger/besu/ethereum/mainnet/blockstm/BlockStmStats.java | 38 ++ + .../org/hyperledger/besu/ethereum/mainnet/blockstm/FlatBaseSnapshot.java | 165 ++++++ + .../main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/MvAccount.java | 82 +++ + .../java/org/hyperledger/besu/ethereum/mainnet/blockstm/MvBaseLayer.java | 149 ++++++ + .../main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/MvContext.java | 55 ++ + .../src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/MvKey.java | 156 ++++++ + .../main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/MvMemory.java | 266 ++++++++++ + .../main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/Scheduler.java | 390 +++++++++++++++ + .../org/hyperledger/besu/ethereum/mainnet/AereD432GasCapUnsignedTest.java | 103 ++++ + .../org/hyperledger/besu/ethereum/mainnet/AereD433BftWithdrawalsTest.java | 75 +++ + .../besu/ethereum/mainnet/feemarket/LondonFeeMarketAereFloorTest.java | 129 +++++ + .../besu/ethereum/mainnet/parallelization/AereBlockStmBenchmarkTest.java | 620 +++++++++++++++++++++++ + .../besu/ethereum/mainnet/parallelization/AereBlockStmSmokeTest.java | 130 +++++ + .../src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthPeers.java | 100 +++- + .../org/hyperledger/besu/ethereum/eth/sync/BlockPropagationManager.java | 19 + + .../org/hyperledger/besu/ethereum/eth/sync/PropagatedBlockAdoptionGate.java | 103 ++++ + .../main/java/org/hyperledger/besu/ethereum/eth/sync/state/SyncState.java | 47 +- + .../java/org/hyperledger/besu/ethereum/eth/sync/state/SyncStateTest.java | 88 ++++ + ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/RLPInput.java | 26 + + evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java | 10 +- + evm/src/main/java/org/hyperledger/besu/evm/frame/TxValues.java | 18 +- + .../org/hyperledger/besu/evm/precompile/P256VerifyPrecompiledContract.java | 8 +- + 158 files changed, 14209 insertions(+), 336 deletions(-) + +diff --git a/app/src/main/java/org/hyperledger/besu/controller/PqTipAdoptionGate.java b/app/src/main/java/org/hyperledger/besu/controller/PqTipAdoptionGate.java +new file mode 100644 +index 0000000000..5daabf7a6a +--- /dev/null ++++ b/app/src/main/java/org/hyperledger/besu/controller/PqTipAdoptionGate.java +@@ -0,0 +1,278 @@ ++/* ++ * Copyright contributors to Besu / AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.controller; ++ ++import org.hyperledger.besu.consensus.common.bft.AerePqHeaderSeal; ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; ++import org.hyperledger.besu.consensus.common.bft.BftHelpers; ++import org.hyperledger.besu.consensus.common.bft.FalconSeal; ++import org.hyperledger.besu.consensus.common.bft.PqAnchor; ++import org.hyperledger.besu.consensus.common.bft.PqSealCache; ++import org.hyperledger.besu.consensus.common.bft.PqSignerRegistry; ++import org.hyperledger.besu.consensus.common.validator.ValidatorProvider; ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.ethereum.core.BlockHeader; ++import org.hyperledger.besu.ethereum.eth.sync.PropagatedBlockAdoptionGate; ++ ++import java.util.Collection; ++import java.util.HashSet; ++import java.util.List; ++import java.util.Set; ++ ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.bytes.Bytes32; ++import org.slf4j.Logger; ++import org.slf4j.LoggerFactory; ++ ++/** ++ * AERE D-412 (2026-09-26), Rule C, the consensus-aware implementation of {@link ++ * PropagatedBlockAdoptionGate.Gate}. ++ * ++ *

A validator does not ADOPT, as the new canonical head, a block that arrived by propagation at the ++ * tip of its own consensus height unless it holds a post-quantum COMMIT quorum for that exact block ++ * hash - the Falcon-512 commit seals it heard on AIP-21 Commit messages, re-verified now against the ++ * anchored registry. From H_hdr the header carries only the proposer's single seal, so a valid header no ++ * longer proves quorum agreement; that agreement lives in the seal cache, and a single-key forgery has ++ * none. The block stays VALID (this is fork choice, not validation), so: ++ * ++ *

    ++ *
  • Below H_hdr the gate is inert (the header's ECDSA committed-seals rule already proves a quorum). ++ *
  • A reader (not in the validator set) is not gated: it hears no commit seals, so it could never ++ * clear the gate and would stall; its canonicity is Rule B, out of this milestone's scope. ++ *
  • The sync downloader is a different code path and does not consult this gate, so a validator that ++ * fell behind catches up freely and only rejoins the gated tip once it hears commits again. ++ *
++ * ++ *

The quorum proof is cryptographic: each cached seal is re-verified with Falcon over {@link ++ * PqAnchor#commitMessage} (the exact message a commit seal signs from the anchor form, which holds at ++ * every height at or above H_hdr), and only distinct verified signer indexes are counted, so junk in the ++ * cache cannot forge the proof. To clear the gate an adversary would need the commit quorum's distinct ++ * Falcon signatures over the block's commit message - which is exactly the agreement D-412 shows a single ++ * key cannot produce. ++ * ++ *

OBSERVE by default, since D-419 (2026-09-27). Measured on testnet 28001: validator ++ * aere-testnet@1 spent five seconds importing its own 3,366-transaction block, missed the commit messages of ++ * the next height, and this gate then refused the block the other four had decided - 226 times over 1 h 45 ++ * min - while its own consensus climbed to round 10 and could never decide that height again, and the sync ++ * downloader never engaged ({@code eth_syncing=false} 4,000 blocks behind). The third bullet above was the ++ * premise, and it did not hold. Meanwhile the one scenario the gate was written for had been measured on ++ * 2026-09-26 WITHOUT the gate: honest validators holding the honest block at the tip did not adopt the forged ++ * one (0 of 3), because the honest block wins the race; the real D-412 exposure is readers and catch-up, ++ * which Rule B1 (finality tags) and the anchor bound (PqAnchorSealsRule) cover. So the gate now defaults to ++ * OBSERVE: it computes exactly the same verdict and logs every block it WOULD refuse ({@value ++ * #OBSERVE_MARKER}), and adopts it. ENFORCE ({@value #PROPERTY_MODE}=enforce or {@value #ENV_MODE}=enforce) ++ * keeps the old behaviour and must be asked for; it has no release condition yet, so it can wedge a validator ++ * that missed a height. A safe release needs evidence one key cannot forge (a certified anchor above the ++ * refused block), not a timeout: a proposer that stays silent and waits for the timeout is the D-412 attack. ++ */ ++public class PqTipAdoptionGate implements PropagatedBlockAdoptionGate.Gate { ++ ++ private static final Logger LOG = LoggerFactory.getLogger(PqTipAdoptionGate.class); ++ ++ /** System property selecting the gate mode: {@code enforce} or {@code observe} (the default). */ ++ public static final String PROPERTY_MODE = "aere.d412.adoptionGate"; ++ ++ /** Environment twin of {@link #PROPERTY_MODE}. */ ++ public static final String ENV_MODE = "AERE_D412_ADOPTION_GATE"; ++ ++ /** Logged, in observe mode, for every propagated block the enforce mode would have refused. */ ++ public static final String OBSERVE_MARKER = "AERE D-412 OBSERVE: would NOT adopt"; ++ ++ /** ++ * Whether the configuration asks for ENFORCE. Anything other than {@code enforce} (after trimming, any ++ * case), including nothing at all, is OBSERVE: enforcing must be an explicit request. ++ * ++ * @param property the system property value, possibly null ++ * @param env the environment value, possibly null ++ * @return true only for an explicit enforce ++ */ ++ static boolean enforceRequested(final String property, final String env) { ++ final String v = property != null && !property.isBlank() ? property : env; ++ if (v == null || v.isBlank()) { ++ return false; ++ } ++ final String m = v.trim().toLowerCase(java.util.Locale.ROOT); ++ if (!m.equals("enforce") && !m.equals("observe")) { ++ LOG.warn( ++ "AERE D-412: unknown adoption gate mode '{}' ({} / {}); using OBSERVE", m, PROPERTY_MODE, ENV_MODE); ++ } ++ return m.equals("enforce"); ++ } ++ ++ /** Verifies one Falcon seal over the commit message of a block; injectable for tests. */ ++ @FunctionalInterface ++ public interface SealVerifier { ++ /** ++ * Verify. ++ * ++ * @param blockNumber the height ++ * @param validatorIndex the signer index in the anchored registry ++ * @param message the commit message that was signed ++ * @param signature the Falcon signature ++ * @return true iff it verifies against the key bound at that height ++ */ ++ boolean verify(long blockNumber, int validatorIndex, Bytes message, Bytes signature); ++ } ++ ++ private final ValidatorProvider validatorProvider; ++ private final Address localEcdsaAddress; ++ private final long chainId; ++ private final PqSealCache cache; ++ private final SealVerifier verifier; ++ private final boolean enforce; ++ private final java.util.function.LongPredicate stage5Active; ++ private final java.util.concurrent.atomic.AtomicLong wouldRefuse = ++ new java.util.concurrent.atomic.AtomicLong(); ++ ++ /** ++ * Production wiring; the mode comes from {@link #PROPERTY_MODE} / {@link #ENV_MODE} (OBSERVE unless ++ * enforce is asked for). ++ * ++ * @param validatorProvider the validator provider (the set at a height; ids from H_id, addresses below) ++ * @param localEcdsaAddress this node's ECDSA address (from its node key) ++ * @param chainId the chain id every commit message carries ++ */ ++ public PqTipAdoptionGate( ++ final ValidatorProvider validatorProvider, final Address localEcdsaAddress, final long chainId) { ++ this( ++ validatorProvider, ++ localEcdsaAddress, ++ chainId, ++ PqSealCache.instance(), ++ (n, i, m, s) -> PqSignerRegistry.falconSealSupport().verifyAtHistoric(n, i, m, s), ++ enforceRequested(System.getProperty(PROPERTY_MODE), System.getenv(ENV_MODE)), ++ AerePqHeaderSeal::active); ++ } ++ ++ /** ++ * Full wiring, for tests. ++ * ++ * @param validatorProvider the validator provider ++ * @param localEcdsaAddress this node's ECDSA address ++ * @param chainId the chain id ++ * @param cache the seal cache to read ++ * @param verifier the seal verifier ++ * @param enforce true to refuse (ENFORCE), false to log and adopt (OBSERVE) ++ * @param stage5Active whether a height is at or above H_hdr (production: {@link AerePqHeaderSeal#active}) ++ */ ++ PqTipAdoptionGate( ++ final ValidatorProvider validatorProvider, ++ final Address localEcdsaAddress, ++ final long chainId, ++ final PqSealCache cache, ++ final SealVerifier verifier, ++ final boolean enforce, ++ final java.util.function.LongPredicate stage5Active) { ++ this.validatorProvider = validatorProvider; ++ this.localEcdsaAddress = localEcdsaAddress; ++ this.chainId = chainId; ++ this.cache = cache; ++ this.verifier = verifier; ++ this.enforce = enforce; ++ this.stage5Active = stage5Active; ++ } ++ ++ /** ++ * Whether this gate refuses (ENFORCE) or only logs (OBSERVE). ++ * ++ * @return true in ENFORCE mode ++ */ ++ public boolean isEnforcing() { ++ return enforce; ++ } ++ ++ /** ++ * How many propagated blocks this gate judged without a post-quantum commit quorum (refused in ENFORCE, ++ * logged and adopted in OBSERVE). ++ * ++ * @return the count since start ++ */ ++ public long wouldRefuseCount() { ++ return wouldRefuse.get(); ++ } ++ ++ @Override ++ public boolean mayAdopt(final BlockHeader header, final BlockHeader parent) { ++ final long h = header.getNumber(); ++ // Below H_hdr the header still carries a quorum of ECDSA committed seals, whose upstream rule ++ // already refuses a single-key block; nothing to add here. ++ if (!stage5Active.test(h)) { ++ return true; ++ } ++ final Collection

validators = validatorProvider.getValidatorsForBlock(parent); ++ if (validators == null || validators.isEmpty()) { ++ return true; ++ } ++ // Only a validator hears commit seals; a reader would never clear the gate, so it is not gated ++ // (its canonicity is Rule B). isLocal matches this node as an ECDSA address OR its v3 id, so it is ++ // correct below H_id (addresses) and from stage 5 (ids), where the set carries ids. ++ boolean localIsValidator = false; ++ for (final Address v : validators) { ++ if (AerePqIdentity.isLocal(v, localEcdsaAddress)) { ++ localIsValidator = true; ++ break; ++ } ++ } ++ if (!localIsValidator) { ++ return true; ++ } ++ final int quorum = BftHelpers.calculateRequiredValidatorQuorum(validators.size()); ++ if (quorum <= 0) { ++ return true; ++ } ++ final Bytes32 message = PqAnchor.commitMessage(chainId, h, header.getHash().getBytes()); ++ final List heard = cache.sealsFor(h, header.getHash()); ++ final Set verified = new HashSet<>(); ++ for (final FalconSeal seal : heard) { ++ if (seal == null || seal.getValidatorIndex() < 0 || seal.getSignature() == null) { ++ continue; ++ } ++ try { ++ if (verifier.verify(h, seal.getValidatorIndex(), message, seal.getSignature())) { ++ verified.add(seal.getValidatorIndex()); ++ } ++ } catch (final RuntimeException e) { ++ // a seal this node cannot judge is not counted; never a pass ++ LOG.debug("AERE D-412: seal of index {} for block {} could not be verified ({})", seal.getValidatorIndex(), h, e.toString()); ++ } ++ } ++ final boolean ok = verified.size() >= quorum; ++ if (ok) { ++ return true; ++ } ++ wouldRefuse.incrementAndGet(); ++ if (!enforce) { ++ // D-419: OBSERVE. Same verdict, recorded, and the block is adopted as before the gate existed. ++ LOG.info( ++ "{} propagated block {} at tip height {}: it holds {} verified post-quantum commit seal(s), " ++ + "quorum is {}; adopting it (observe mode, D-419).", ++ OBSERVE_MARKER, ++ header.getHash(), ++ h, ++ verified.size(), ++ quorum); ++ return true; ++ } ++ LOG.info( ++ "AERE D-412: propagated block {} at tip height {} holds {} verified post-quantum commit " ++ + "seal(s), quorum is {}; NOT adopting it via propagation - this node's own consensus " ++ + "decides this height.", ++ header.getHash(), ++ h, ++ verified.size(), ++ quorum); ++ return false; ++ } ++} +diff --git a/app/src/main/java/org/hyperledger/besu/controller/QbftBesuControllerBuilder.java b/app/src/main/java/org/hyperledger/besu/controller/QbftBesuControllerBuilder.java +index 252f655834..afca7aca58 100644 +--- a/app/src/main/java/org/hyperledger/besu/controller/QbftBesuControllerBuilder.java ++++ b/app/src/main/java/org/hyperledger/besu/controller/QbftBesuControllerBuilder.java +@@ -13,40 +13,44 @@ + * SPDX-License-Identifier: Apache-2.0 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0003-aere-pq-anchor.patch. + */ + package org.hyperledger.besu.controller; + + import static com.google.common.base.Preconditions.checkNotNull; + + import org.hyperledger.besu.config.BftConfigOptions; + import org.hyperledger.besu.config.BftFork; + import org.hyperledger.besu.config.JsonGenesisConfigOptions; + import org.hyperledger.besu.config.QbftConfigOptions; + import org.hyperledger.besu.config.QbftFork; + import org.hyperledger.besu.consensus.common.BftValidatorOverrides; + import org.hyperledger.besu.consensus.common.EpochManager; + import org.hyperledger.besu.consensus.common.ForksSchedule; ++import org.hyperledger.besu.consensus.common.bft.AerePqFinality; ++import org.hyperledger.besu.consensus.common.bft.AerePqFinalityTags; ++import org.hyperledger.besu.consensus.common.bft.AerePqHeaderSeal; ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; + import org.hyperledger.besu.consensus.common.bft.BftBlockInterface; + import org.hyperledger.besu.consensus.common.bft.BftContext; + import org.hyperledger.besu.consensus.common.bft.BftEventQueue; + import org.hyperledger.besu.consensus.common.bft.BftExecutors; + import org.hyperledger.besu.consensus.common.bft.BftProcessor; + import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule; + import org.hyperledger.besu.consensus.common.bft.BftRoundExpiryTimeCalculator; + import org.hyperledger.besu.consensus.common.bft.BlockTimer; + import org.hyperledger.besu.consensus.common.bft.EthSynchronizerUpdater; + import org.hyperledger.besu.consensus.common.bft.EventMultiplexer; + import org.hyperledger.besu.consensus.common.bft.FalconSealSupport; + import org.hyperledger.besu.consensus.common.bft.HybridSealSupport; + import org.hyperledger.besu.consensus.common.bft.MessageTracker; + import org.hyperledger.besu.consensus.common.bft.PqAnchorConfig; + import org.hyperledger.besu.consensus.common.bft.PqAnchorSyncModeGuard; + import org.hyperledger.besu.consensus.common.bft.PqAnchorThresholdGuard; + import org.hyperledger.besu.consensus.common.bft.PqRegistryHash; + import org.hyperledger.besu.consensus.common.bft.PqSealCache; + import org.hyperledger.besu.consensus.common.bft.PqSignerRegistry; + import org.hyperledger.besu.consensus.common.bft.RoundTimer; +@@ -71,61 +75,63 @@ import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockCreatorFactoryAdapto + import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockInterfaceAdaptor; + import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockchainAdaptor; + import org.hyperledger.besu.consensus.qbft.adaptor.QbftFinalStateImpl; + import org.hyperledger.besu.consensus.qbft.adaptor.QbftProtocolScheduleAdaptor; + import org.hyperledger.besu.consensus.qbft.adaptor.QbftValidatorModeTransitionLoggerAdaptor; + import org.hyperledger.besu.consensus.qbft.adaptor.QbftValidatorProviderAdaptor; + import org.hyperledger.besu.consensus.qbft.blockcreation.QbftBlockCreatorFactory; + import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; + import org.hyperledger.besu.consensus.qbft.core.statemachine.QbftBlockHeightManagerFactory; + import org.hyperledger.besu.consensus.qbft.core.statemachine.QbftController; + import org.hyperledger.besu.consensus.qbft.core.statemachine.QbftRoundFactory; + import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec; + import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockInterface; + import org.hyperledger.besu.consensus.qbft.core.types.QbftEventHandler; + import org.hyperledger.besu.consensus.qbft.core.types.QbftFinalState; + import org.hyperledger.besu.consensus.qbft.core.types.QbftMessage; + import org.hyperledger.besu.consensus.qbft.core.types.QbftMinedBlockObserver; + import org.hyperledger.besu.consensus.qbft.core.types.QbftProtocolSchedule; + import org.hyperledger.besu.consensus.qbft.core.types.QbftValidatorProvider; + import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidatorFactory; ++import org.hyperledger.besu.consensus.qbft.core.validation.PqFinalityLayersGuard; + import org.hyperledger.besu.consensus.qbft.jsonrpc.QbftJsonRpcMethods; + import org.hyperledger.besu.consensus.qbft.network.QbftGossiperImpl; + import org.hyperledger.besu.consensus.qbft.protocol.Istanbul100SubProtocol; + import org.hyperledger.besu.consensus.qbft.validator.ForkingValidatorProvider; + import org.hyperledger.besu.consensus.qbft.validator.TransactionValidatorProvider; + import org.hyperledger.besu.consensus.qbft.validator.ValidatorContractController; + import org.hyperledger.besu.consensus.qbft.validator.ValidatorModeTransitionLogger; + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.ethereum.ProtocolContext; + import org.hyperledger.besu.ethereum.api.jsonrpc.methods.JsonRpcMethods; + import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; + import org.hyperledger.besu.ethereum.chain.Blockchain; + import org.hyperledger.besu.ethereum.chain.MinedBlockObserver; + import org.hyperledger.besu.ethereum.chain.MutableBlockchain; + import org.hyperledger.besu.ethereum.core.BlockHeader; + import org.hyperledger.besu.ethereum.core.MiningConfiguration; + import org.hyperledger.besu.ethereum.core.Util; + import org.hyperledger.besu.ethereum.eth.EthProtocol; + import org.hyperledger.besu.ethereum.eth.SnapProtocol; + import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; + import org.hyperledger.besu.ethereum.eth.manager.snap.SnapProtocolManager; ++import org.hyperledger.besu.ethereum.eth.sync.PropagatedBlockAdoptionGate; + import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; + import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; + import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; + import org.hyperledger.besu.ethereum.p2p.config.SubProtocolConfiguration; + import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; + import org.hyperledger.besu.util.Subscribers; + + import java.time.Duration; + import java.util.HashMap; + import java.util.List; + import java.util.Map; + import java.util.Optional; + import java.util.stream.Collectors; + + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + + /** The Qbft Besu controller builder. */ + public class QbftBesuControllerBuilder extends BesuControllerBuilder { + +@@ -416,40 +422,101 @@ public class QbftBesuControllerBuilder extends BesuControllerBuilder { + .getChainId() + .map(java.math.BigInteger::longValue) + .orElse(0L), + pqRegistrySchedule); + + // AERE SINCRONIZARE (2026-08-02): the anchor is only a defence if it applies to the history this + // node ACCEPTS, and not only to the blocks it is offered as proposals. Outside FULL sync the + // header import path never instantiates a header validator at all, so both anchor rules would be + // skipped for the entire span between checkpoint and pivot. Refuse to start rather than run a + // node that believes it is protected and is not. + // + // Placed with the other two startup guards and for the same reason: a chain head exists here, the + // network is not up and the QBFT state machine has not been created, so this is a clean refusal + // to start. Inert when aere.pq.anchorBlock is unset, which is chain 2800 as it stands today. + // AERE GARDA-PRAG (2026-08-02): read the anchor configuration ONCE, here, and hand the SAME + // object to every guard that needs it. Two calls to fromSystemConfiguration would print the + // ARMED banner twice and, worse, would give two guards two independent chances to disagree + // about what is actually configured on this node. + final PqAnchorConfig aereAnchorConfig = PqAnchorConfig.fromSystemConfiguration(); + ++ // AERE AIP-22 stage 3: the post-quantum identity switch, read ONCE here beside the anchor ++ // configuration; the schemes every v3 row must carry are the ones the scheme schedule names at ++ // H_id. Inert when aere.pq.identityBlock is unset. ++ AerePqIdentity.installFromSystemProperties( ++ aereAnchorConfig.chainId(), ++ hId -> ++ HybridSealSupport.instance() ++ .schedule() ++ .map(s -> (java.util.List) new java.util.ArrayList<>(s.schemesAt(hId))) ++ .orElse(java.util.List.of("falcon-512"))); ++ // AERE AIP-22 stage 3b: at H_k the SOURCE of the keys that seal moves to the v3 epochs; the continuity ++ // guard proves, before the node joins anything, that no key moves with it (every key of the epoch at ++ // H_k equals the key the existing registries give at H_k - 1). Inert when H_k is not configured. ++ AerePqIdentity.verifyKeyContinuity( ++ (index, scheme) -> { ++ final long before = ++ AerePqIdentity.installed() ++ .map(c -> c.keysFrom() - 1L) ++ .orElseThrow(() -> new IllegalStateException("identity not installed")); ++ return "falcon-512".equals(scheme) ++ ? FalconSealSupport.instance().publicKeyBytesAtHistoric(before, index) ++ : HybridSealSupport.instance().registry().flatMap(r -> r.publicKey(index, scheme)); ++ }); ++ // AERE AIP-22 stage 3b-ii: in every v3 epoch from H_k where this node is a registered validator it must ++ // hold its row's keys, or it would go mute at that epoch; refuse to start instead. Inert without H_k. ++ FalconSealSupport.instance() ++ .verifyLocalKeysCoverV3EpochsOrAbort(Util.publicKeyToAddress(nodeKey.getPublicKey())); ++ HybridSealSupport.instance() ++ .verifyLocalKeysCoverV3EpochsOrAbort(Util.publicKeyToAddress(nodeKey.getPublicKey())); ++ // AERE AIP-22 stage 4: H_fin (aere.pq.finalityBlock), from which a message's author is the id of its post-quantum seal's ++ // index once that seal verifies, and the envelope's ECDSA is not read; refuses unless the keys are read from the v3 epochs ++ // at or below it (AERE-PQC-FIN-01). Inert when unset, which is every chain today. ++ AerePqFinality.installFromSystemProperties(aereAnchorConfig.chainId()); ++ // ...and the four seal layers must be armed at or below it (AERE-PQC-FIN-02): the commit layer is the one that judges a ++ // COMMIT's seal (its author is bound to the commit seal's signer), and the layers stay the second judge of the rest. ++ PqFinalityLayersGuard.verifyOrAbort(AerePqFinality.finalityBlock()); ++ // ...and a node that seals must seal all four messages from H_fin, or it would be mute there (AERE-PQC-FIN-03) ++ PqFinalityLayersGuard.verifyEmissionOrAbort( ++ AerePqFinality.finalityBlock(), ++ FalconSealSupport.instance().signingEnabled(), ++ FalconSealSupport.instance().attachBlock(), ++ FalconSealSupport.proposalAttachBlock(), ++ FalconSealSupport.prepareAttachBlock(), ++ FalconSealSupport.roundChangeAttachBlock()); ++ // AERE AIP-22 stage 5: H_hdr (aere.pq.headerBlock), from which a header carries the proposer's post-quantum seal ++ // and no ECDSA committed seal; refuses unless H_fin is at or below it (AERE-PQC-HDR-01). Inert when unset. ++ AerePqHeaderSeal.installFromSystemProperties(); ++ if (AerePqHeaderSeal.headerBlock() != AerePqIdentity.NEVER) { ++ LOG.info( ++ "AERE PQ HEADER: H_hdr armed at {}; from it a header carries the proposer's post-quantum seal and NO ECDSA" ++ + " committed seal", ++ AerePqHeaderSeal.headerBlock()); ++ } ++ if (AerePqFinality.finalityBlock() != AerePqIdentity.NEVER) { ++ LOG.info( ++ "AERE PQ FINALITY: H_fin armed at {}; from it a message's author is the id of its VERIFIED post-quantum seal and the" ++ + " envelope's ECDSA is not read (four seal layers armed at or below it, this node seals: {})", ++ AerePqFinality.finalityBlock(), ++ FalconSealSupport.instance().signingEnabled()); ++ } ++ + PqAnchorSyncModeGuard.verifySyncModeOrAbort( + syncConfig == null || syncConfig.getSyncMode() == null + ? null + : syncConfig.getSyncMode().name(), + aereAnchorConfig); + + // AERE PERSISTENTA-SIGILII (2026-08-05): THE SECOND HALF of the chain death on a whole-fleet + // restart. The first half is repaired above (BLOCAJ-REPORNIRE): the registry now arms at startup + // from the chain head state, and all seven nodes reported SUCCEEDED. The chain died anyway, the + // refusal only changing shape: "registry address-bound=TRUE ... Heard 0 seal(s)", frozen 150 s + // on the first restart and 298 s on the second. + // + // WHY. Falcon seals over M(head) travel ONLY on the Commit messages of the head block. Those + // messages are never repeated after a restart, and they exist nowhere else: the head block + // carries in element 6 the certificate over its PARENT, not over itself. So every node started + // with zero seals, nobody reached K, nobody could propose, and so nobody sent another Commit. + // The same circular deadlock, one level down. + // + // WHY THIS IS NOT A8 IN NEW CLOTHES, and this is the whole security argument: the seal is + // SELF-VERIFYING. Every seal read from the file is cryptographically verified again against the +@@ -526,40 +593,83 @@ public class QbftBesuControllerBuilder extends BesuControllerBuilder { + transactionPool, + protocolContext, + bftProtocolSchedule, + qbftForksSchedule, + miningConfiguration, + localAddress, + qbftExtraDataCodec, + ethProtocolManager.ethContext().getScheduler()); + + final ValidatorProvider validatorProvider; + if (qbftConfig.getStartBlock().isPresent()) { + validatorProvider = + protocolContext + .getConsensusContext(BftContext.class, qbftConfig.getStartBlock().getAsLong()) + .getValidatorProvider(); + } else { + validatorProvider = + protocolContext.getConsensusContext(BftContext.class).getValidatorProvider(); + } + ++ // AERE D-412 (2026-09-26), Rule C: arm the propagation adoption gate. From AIP-22 stage 5 a valid ++ // header carries only the proposer's single Falcon seal, so it no longer proves a quorum agreed the ++ // block; a single key could forge one and, until this gate, honest validators adopted it via NewBlock ++ // and built on top (measured on rep28098). The gate lets this node refuse to ADOPT such a propagated ++ // block at the tip of its own consensus height unless it holds a post-quantum commit quorum for it ++ // (heard on AIP-21 Commit seals). Block VALIDITY is unchanged (sync still imports it); only ++ // ADOPTION-at-the-tip is gated, only for a validator, only from H_hdr. Inert here on any chain whose ++ // H_hdr is unset, which is chain 2800 today. Placed after the validator set is resolved (localAddress ++ // and validatorProvider both exist) and before the network and the QBFT machine start. ++ // D-419 (2026-09-27): the gate defaults to OBSERVE (logs every block it would refuse, adopts it); ENFORCE ++ // wedged a validator that missed one height's commits on testnet 28001 and must be asked for explicitly. ++ if (aereAnchorConfig.everActive()) { ++ final PqTipAdoptionGate tipGate = ++ new PqTipAdoptionGate(validatorProvider, localAddress, aereAnchorConfig.chainId()); ++ PropagatedBlockAdoptionGate.install(tipGate); ++ LOG.info( ++ "AERE D-412: propagation adoption gate armed in {} mode; a propagated block at the tip {} " ++ + "without a post-quantum commit quorum from H_hdr={} (unset means never on this node).", ++ tipGate.isEnforcing() ? "ENFORCE" : "OBSERVE", ++ tipGate.isEnforcing() ? "is NOT adopted" : "is adopted and logged", ++ AerePqHeaderSeal.headerBlock()); ++ } ++ ++ // AERE D-412 (2026-09-26), Rule B1: post-quantum FINALITY TAGS (see AerePqFinalityTags). finalized/safe = the parent of the ++ // last canonical anchor that carries a certificate (v1 Falcon list OR v2 scheme-tagged certificate); monotonic; never moved ++ // back by a reorg (AERE-PQC-FIN-01). No validity, fork-choice or import is touched. Proven live on rep28098 2026-09-26. ++ if (aereAnchorConfig.everActive()) { ++ final QbftExtraDataCodec codecForTags = qbftExtraDataCodec; ++ AerePqFinalityTags.install( ++ aereAnchorConfig, ++ blockchain, ++ h -> { ++ try { ++ return AerePqFinalityTags.carriesCertificate(codecForTags.decodeRaw(h.getExtraData())); ++ } catch (final RuntimeException e) { ++ return false; // an undecodable header carries nothing this rule can rely on ++ } ++ }); ++ LOG.info( ++ "AERE D-412 B1: finalized/safe tags follow the last certified anchor's parent (interval {} at the head).", ++ aereAnchorConfig.intervalAt(blockchain.getChainHeadBlockNumber())); ++ } ++ + // AERE GARDA-PRAG (2026-08-02): refuse to start on a seal threshold that STOPS the chain. + // + // Measured before this line was written: nothing anywhere refused a threshold value. Searched + // the whole fork tree for any occurrence of minSeals near quorum, throw, refuse, abort or + // Illegal, and there were ZERO. PqAnchorConfig rejects a negative K and a step scheduled below + // the activation height, and nothing else; the only other check, PqAnchorProducer's + // warnIfActivationHeightCanRefuse, writes one LOG.error and returns. So a value at or above the + // QBFT quorum was a configuration a node accepted in silence and then halted on. + // + // Placed here rather than beside the other three startup guards because this is the FIRST point + // at which the validator set is resolved, and the bound is a function of its size. It is still + // before the network exists (ValidatorPeers is built below) and before the QBFT state machine is + // created, so a refusal here is a clean refusal to start rather than a mid-flight halt. + PqAnchorThresholdGuard.verifyThresholdAgainstQuorumOrAbort( + aereAnchorConfig, validatorProvider.getValidatorsAtHead().size()); + final QbftValidatorProvider qbftValidatorProvider = + new QbftValidatorProviderAdaptor(validatorProvider); + + final QbftBlockInterface qbftBlockInterface = new QbftBlockInterfaceAdaptor(bftBlockInterface); + +diff --git a/app/src/test/java/org/hyperledger/besu/controller/PqTipAdoptionGateModeTest.java b/app/src/test/java/org/hyperledger/besu/controller/PqTipAdoptionGateModeTest.java +new file mode 100644 +index 0000000000..1e87f3b984 +--- /dev/null ++++ b/app/src/test/java/org/hyperledger/besu/controller/PqTipAdoptionGateModeTest.java +@@ -0,0 +1,180 @@ ++/* ++ * Copyright contributors to Besu / AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.controller; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++import static org.mockito.ArgumentMatchers.any; ++import static org.mockito.Mockito.mock; ++import static org.mockito.Mockito.when; ++ ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; ++import org.hyperledger.besu.consensus.common.bft.FalconSeal; ++import org.hyperledger.besu.consensus.common.bft.PqSealCache; ++import org.hyperledger.besu.consensus.common.validator.ValidatorProvider; ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.ethereum.core.BlockHeader; ++import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; ++ ++import java.util.List; ++import java.util.concurrent.atomic.AtomicLong; ++ ++import org.apache.tuweni.bytes.Bytes; ++import org.junit.jupiter.api.AfterEach; ++import org.junit.jupiter.api.BeforeEach; ++import org.junit.jupiter.api.Test; ++ ++/** ++ * D-419 (2026-09-27): the Rule C tip adoption gate in its two modes. OBSERVE (the default) computes the same ++ * verdict as ENFORCE, counts the blocks it would refuse, and adopts them; ENFORCE refuses. Every case has its ++ * opposite: the same block without a quorum is refused under ENFORCE and adopted under OBSERVE, and a quorum of ++ * seals that do NOT verify is refused under ENFORCE, so the gate verifies seals and does not merely count them. ++ */ ++class PqTipAdoptionGateModeTest { ++ ++ private static final long H_HDR = 100L; ++ private static final long CHAIN_ID = 28098L; ++ private static final Address LOCAL = Address.fromHexString("0x00000000000000000000000000000000000000a1"); ++ private static final List
SET = ++ List.of( ++ LOCAL, ++ Address.fromHexString("0x00000000000000000000000000000000000000a2"), ++ Address.fromHexString("0x00000000000000000000000000000000000000a3"), ++ Address.fromHexString("0x00000000000000000000000000000000000000a4")); ++ // a distinct timestamp per header, so every test reads its own seal-cache entry from the shared singleton ++ private static final AtomicLong TS = new AtomicLong(1_900_000_000L); ++ ++ private ValidatorProvider provider; ++ ++ @BeforeEach ++ void setUp() { ++ // no v3 identity installed: isLocal falls back to address equality, which is what this set uses ++ AerePqIdentity.uninstall(); ++ provider = mock(ValidatorProvider.class); ++ when(provider.getValidatorsForBlock(any())).thenReturn(SET); ++ } ++ ++ @AfterEach ++ void tearDown() { ++ AerePqIdentity.uninstall(); ++ } ++ ++ private static BlockHeader header(final long number) { ++ return new BlockHeaderTestFixture().number(number).timestamp(TS.incrementAndGet()).buildHeader(); ++ } ++ ++ private PqTipAdoptionGate gate(final boolean enforce, final boolean sealsVerify) { ++ return new PqTipAdoptionGate( ++ provider, ++ LOCAL, ++ CHAIN_ID, ++ PqSealCache.instance(), ++ (n, i, m, s) -> sealsVerify, ++ enforce, ++ h -> h >= H_HDR); ++ } ++ ++ private static void recordSeals(final BlockHeader h, final int count) { ++ final List seals = ++ java.util.stream.IntStream.range(0, count) ++ .mapToObj(i -> new FalconSeal(i, Bytes.of(i + 1))) ++ .toList(); ++ PqSealCache.instance().record(h.getNumber(), h.getHash(), seals); ++ } ++ ++ @Test ++ void enforceRefusesATipBlockWithoutAQuorum() { ++ final BlockHeader h = header(150); ++ final PqTipAdoptionGate g = gate(true, true); ++ assertThat(g.mayAdopt(h, header(149))).isFalse(); ++ assertThat(g.wouldRefuseCount()).isEqualTo(1); ++ } ++ ++ @Test ++ void observeAdoptsTheSameBlockAndCountsIt() { ++ final BlockHeader h = header(150); ++ final PqTipAdoptionGate g = gate(false, true); ++ assertThat(g.mayAdopt(h, header(149))).isTrue(); ++ assertThat(g.wouldRefuseCount()).isEqualTo(1); ++ } ++ ++ @Test ++ void enforceAdoptsWithAVerifiedQuorum() { ++ final BlockHeader h = header(151); ++ recordSeals(h, 3); // quorum of 4 validators is 3 ++ final PqTipAdoptionGate g = gate(true, true); ++ assertThat(g.mayAdopt(h, header(150))).isTrue(); ++ assertThat(g.wouldRefuseCount()).isZero(); ++ } ++ ++ @Test ++ void enforceRefusesAQuorumOfSealsThatDoNotVerify() { ++ final BlockHeader h = header(152); ++ recordSeals(h, 4); ++ final PqTipAdoptionGate g = gate(true, false); ++ assertThat(g.mayAdopt(h, header(151))).isFalse(); ++ assertThat(g.wouldRefuseCount()).isEqualTo(1); ++ } ++ ++ @Test ++ void belowHdrNeitherModeGatesOrCounts() { ++ final BlockHeader h = header(H_HDR - 1); ++ final PqTipAdoptionGate e = gate(true, true); ++ final PqTipAdoptionGate o = gate(false, true); ++ assertThat(e.mayAdopt(h, header(H_HDR - 2))).isTrue(); ++ assertThat(o.mayAdopt(h, header(H_HDR - 2))).isTrue(); ++ assertThat(e.wouldRefuseCount()).isZero(); ++ assertThat(o.wouldRefuseCount()).isZero(); ++ } ++ ++ @Test ++ void aNodeOutsideTheSetIsNotGatedEvenInEnforce() { ++ when(provider.getValidatorsForBlock(any())).thenReturn(SET.subList(1, 4)); ++ final PqTipAdoptionGate g = gate(true, true); ++ assertThat(g.mayAdopt(header(153), header(152))).isTrue(); ++ assertThat(g.wouldRefuseCount()).isZero(); ++ } ++ ++ @Test ++ void enforceMustBeAskedForExplicitly() { ++ assertThat(PqTipAdoptionGate.enforceRequested(null, null)).isFalse(); ++ assertThat(PqTipAdoptionGate.enforceRequested("", " ")).isFalse(); ++ assertThat(PqTipAdoptionGate.enforceRequested("observe", null)).isFalse(); ++ assertThat(PqTipAdoptionGate.enforceRequested("bogus", null)).isFalse(); ++ assertThat(PqTipAdoptionGate.enforceRequested("enforce", null)).isTrue(); ++ assertThat(PqTipAdoptionGate.enforceRequested(" ENFORCE ", null)).isTrue(); ++ assertThat(PqTipAdoptionGate.enforceRequested(null, "enforce")).isTrue(); ++ // the system property wins over the environment when both are set ++ assertThat(PqTipAdoptionGate.enforceRequested("observe", "enforce")).isFalse(); ++ } ++ ++ @Test ++ void theProductionConstructorDefaultsToObserve() { ++ final String before = System.getProperty(PqTipAdoptionGate.PROPERTY_MODE); ++ try { ++ System.clearProperty(PqTipAdoptionGate.PROPERTY_MODE); ++ if (System.getenv(PqTipAdoptionGate.ENV_MODE) == null) { ++ assertThat(new PqTipAdoptionGate(provider, LOCAL, CHAIN_ID).isEnforcing()).isFalse(); ++ } ++ System.setProperty(PqTipAdoptionGate.PROPERTY_MODE, "enforce"); ++ assertThat(new PqTipAdoptionGate(provider, LOCAL, CHAIN_ID).isEnforcing()).isTrue(); ++ } finally { ++ if (before == null) { ++ System.clearProperty(PqTipAdoptionGate.PROPERTY_MODE); ++ } else { ++ System.setProperty(PqTipAdoptionGate.PROPERTY_MODE, before); ++ } ++ } ++ } ++} +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/AerePqFinality.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/AerePqFinality.java +new file mode 100644 +index 0000000000..64dec0d1e1 +--- /dev/null ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/AerePqFinality.java +@@ -0,0 +1,194 @@ ++/* ++ * Copyright contributors to Besu / AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.consensus.common.bft; ++ ++import org.hyperledger.besu.consensus.common.bft.payload.Payload; ++import org.hyperledger.besu.datatypes.Address; ++ ++import java.util.Optional; ++ ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.bytes.Bytes32; ++ ++/** ++ * AERE AIP-22 stage 4 (plan 9.6.8): from H_fin ({@code aere.pq.finalityBlock}) the ECDSA signature of a ++ * consensus message's envelope is no longer a criterion. The author of a message is the post-quantum id ++ * of the row its seal's index names in the v3 epoch in force at the message's height, and ONLY once that ++ * seal VERIFIES: a PROPOSAL, PREPARE or ROUND-CHANGE seal over its own domain, through the same verifier ++ * the seal layers use; a COMMIT's index only when it names the id of the commit seal's signer (the commit ++ * layer, armed at or below H_fin by AERE-PQC-FIN-02, judges the seal itself). The envelope's recovered ++ * ECDSA address is not read for authorship, so a validator may sign the envelope with any secp256k1 key. ++ * Anything else at or above H_fin has no author ({@link #NO_AUTHOR}, never in a set). ++ * ++ *

WHY HERE AND NOT ONLY IN THE LAYERS (read in the code 2026-09-23 ~18:02Z): QbftController relays a message ++ * as soon as its author is in the set, BEFORE the layers judge it. An author read from an unverified ++ * index would let anyone make every validator relay garbage in any validator's name; before H_fin that ++ * needed a validator's ECDSA key. The layers keep judging exactly as before. ++ * ++ *

Requires the post-quantum identity (stage 3) and the keys read from the v3 epochs (stage 3b): ++ * H_fin must be at or above H_k, else startup is refused (AERE-PQC-FIN-01). Unset: never, which is ++ * every chain today. ++ */ ++public final class AerePqFinality { ++ ++ /** The system property naming H_fin. */ ++ public static final String PROPERTY = "aere.pq.finalityBlock"; ++ ++ /** The author of a message that cannot have one from H_fin (no seal, or an index with no row). */ ++ public static final Address NO_AUTHOR = Address.ZERO; ++ ++ /** Verifies a Falcon seal of a registry index at a height (the seal layers' verifier in production). */ ++ @FunctionalInterface ++ public interface SealVerifier { ++ /** ++ * Whether the seal verifies. ++ * ++ * @param height the message's height ++ * @param index the seal's registry index ++ * @param message the message the seal signs ++ * @param signature the seal's signature ++ * @return true when it verifies under that index's key ++ */ ++ boolean verify(long height, int index, Bytes message, Bytes signature); ++ } ++ ++ private static volatile long finalityBlock = AerePqIdentity.NEVER; ++ private static volatile long chainId; ++ private static volatile SealVerifier verifier = (h, i, m, s) -> false; ++ ++ private AerePqFinality() {} ++ ++ /** ++ * Arms H_fin (tests and the startup path). ++ * ++ * @param hFin H_fin, or {@link AerePqIdentity#NEVER} ++ * @param chain the chain id every seal message carries ++ * @param sealVerifier the verifier of the seal layers ++ */ ++ public static void install(final long hFin, final long chain, final SealVerifier sealVerifier) { ++ if (hFin != AerePqIdentity.NEVER) { ++ final long keysFrom = ++ AerePqIdentity.installed().map(AerePqIdentity.Config::keysFrom).orElse(AerePqIdentity.NEVER); ++ if (keysFrom == AerePqIdentity.NEVER || hFin < keysFrom) { ++ throw new IllegalStateException( ++ "AERE-PQC-FIN-01: " ++ + PROPERTY ++ + "=" ++ + hFin ++ + " needs the post-quantum identity and the keys read from the v3 epochs (aere.pq.registryV3.keysFrom)" ++ + " at or below it (keysFrom " ++ + (keysFrom == AerePqIdentity.NEVER ? "unset" : Long.toString(keysFrom)) ++ + ")"); ++ } ++ if (chain <= 0 || sealVerifier == null) { ++ throw new IllegalStateException( ++ "AERE-PQC-FIN-01: " ++ + PROPERTY ++ + "=" ++ + hFin ++ + " needs the chain id (aere.pq.chainId) and a seal verifier: every author it gives is a verified seal"); ++ } ++ } ++ finalityBlock = hFin; ++ chainId = chain; ++ verifier = sealVerifier == null ? (h, i, m, s) -> false : sealVerifier; ++ } ++ ++ /** ++ * H_fin as armed on this node. ++ * ++ * @return H_fin, or {@link AerePqIdentity#NEVER} when unset ++ */ ++ public static long finalityBlock() { ++ return finalityBlock; ++ } ++ ++ /** Disarms (tests). */ ++ public static void uninstall() { ++ finalityBlock = AerePqIdentity.NEVER; ++ chainId = 0; ++ verifier = (h, i, m, s) -> false; ++ } ++ ++ /** ++ * Arms from {@link #PROPERTY}; unset means never. Call after the identity is installed. ++ * ++ * @param chain the chain id of the anchor configuration (aere.pq.chainId) ++ */ ++ public static void installFromSystemProperties(final long chain) { ++ final String v = System.getProperty(PROPERTY); ++ if (v == null || v.isBlank()) { ++ uninstall(); ++ return; ++ } ++ final long h; ++ try { ++ h = Long.parseLong(v.trim()); ++ } catch (final NumberFormatException e) { ++ throw new IllegalStateException("AERE-PQC-FIN-01: " + PROPERTY + "='" + v + "' is not a height", e); ++ } ++ final PqSignerRegistry layers = PqSignerRegistry.falconSealSupport(); ++ install(h, chain, layers::verifyAtOwnHead); ++ } ++ ++ /** ++ * Whether the post-quantum seal is the author of messages at this height. ++ * ++ * @param height the message's height ++ * @return true from H_fin when armed ++ */ ++ public static boolean active(final long height) { ++ return height >= finalityBlock; ++ } ++ ++ /** ++ * The author of a message from H_fin: the id of its seal's index at the message's height, once the ++ * seal verifies (a COMMIT: once the index names the commit seal signer's id). ++ * ++ * @param payload the message payload ++ * @param height the message's height ++ * @return the id, or {@link #NO_AUTHOR} ++ */ ++ public static Address authorFromSeal(final Payload payload, final long height) { ++ if (!(payload instanceof PqSealed sealed)) { ++ return NO_AUTHOR; ++ } ++ final Optional seal = sealed.getFalconSeal(); ++ if (seal.isEmpty()) { ++ return NO_AUTHOR; ++ } ++ final int index = seal.get().getValidatorIndex(); ++ final Optional

id = AerePqIdentity.v3IdAt(height, index); ++ if (id.isEmpty()) { ++ return NO_AUTHOR; ++ } ++ try { ++ final Optional
commitSigner = sealed.commitSealSigner(); ++ if (commitSigner.isPresent()) { ++ return id.get().equals(AerePqIdentity.author(commitSigner.get(), height)) ? id.get() : NO_AUTHOR; ++ } ++ final Optional message = sealed.pqSealMessage(chainId); ++ if (message.isEmpty()) { ++ return NO_AUTHOR; ++ } ++ return verifier.verify(height, index, message.get(), seal.get().getSignature()) ++ ? id.get() ++ : NO_AUTHOR; ++ } catch (final RuntimeException e) { ++ // a seal we cannot judge authors nothing: "cannot judge" is never a pass ++ return NO_AUTHOR; ++ } ++ } ++} +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/AerePqFinalityTags.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/AerePqFinalityTags.java +new file mode 100755 +index 0000000000..e5e11c939f +--- /dev/null ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/AerePqFinalityTags.java +@@ -0,0 +1,202 @@ ++/* ++ * Copyright contributors to Besu / AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.consensus.common.bft; ++ ++import org.hyperledger.besu.datatypes.Hash; ++import org.hyperledger.besu.ethereum.chain.BlockAddedEvent; ++import org.hyperledger.besu.ethereum.chain.MutableBlockchain; ++import org.hyperledger.besu.ethereum.core.BlockHeader; ++// in this Besu base (26.4.0-dev, d2032017b) the event type enum lives in the plugin API, not nested in BlockAddedEvent ++// (measured 2026-09-26: "cannot find symbol EventType in class BlockAddedEvent" on the first harness run) ++import org.hyperledger.besu.plugin.data.AddedBlockContext.EventType; ++ ++import java.util.Optional; ++import java.util.concurrent.atomic.AtomicLong; ++import java.util.function.Predicate; ++ ++import org.slf4j.Logger; ++import org.slf4j.LoggerFactory; ++ ++/** ++ * AERE D-412 Rule B1 (2026-09-26): the post-quantum FINALITY TAGS. ++ * ++ *

What this closes, read in the code and measured on the chain. From AIP-22 stage 5 a valid ++ * between-anchor header carries only the proposer's Falcon-512 seal, so a single validator key can ++ * forge a header a reader imports as valid and, if that reader is syncing or eclipsed, adopts as its ++ * canonical tip (D-412, corrected severity). Such a forged tail is bounded: at the next anchor height ++ * {@code PqAnchorSealsRule} (R2, FULL validation, which {@code PqAnchorSyncModeGuard} makes the only ++ * sync mode) requires K distinct valid Falcon-512 seals over the parent's commit message, which one key ++ * cannot produce, so the tail dies within one anchor interval. What remains is that the reader's ++ * {@code latest} can transiently name a forged block, and a consumer who asks for {@code finalized} or ++ * {@code safe} - the tags bridges, exchanges and rollups use - received, on every node of chain 2800 and ++ * 28001 measured 2026-09-26, the error {@code Unknown block}: QBFT never sets them. ++ * ++ *

The rule. {@code finalized} and {@code safe} name the last block COVERED BY A VALID ANCHOR ++ * CERTIFICATE: when a canonical head at an anchor height carries a certificate, the anchor's PARENT ++ * becomes finalized (the certificate's K seals sign the parent's commit message, AIP-15, and R1/R2 have ++ * already refused the header if that certificate does not bind or does not verify). Between anchors ++ * the tags do not move. A forged between-anchor block can therefore never be reported final: it is ++ * never an anchor's certified parent. This is exactly the finality AIP-22 section 1 defines ("the ++ * finality of the block is established only by the covering anchor"), exposed on the API the world ++ * already reads. ++ * ++ *

What it deliberately does NOT do. It does not touch fork-choice, block validity or import: ++ * nothing here can stop the chain or refuse a block, and a node that lags still catches up exactly as ++ * before. It only writes the two tags, monotonically: a later event can only move them forward. If a ++ * canonical reorg ever drops below the finalized block (which would mean K validators signed two ++ * conflicting anchors, outside this rule's adversary), it is logged as {@code AERE-PQC-FIN-01} at ++ * ERROR and the tags are left where they were, never moved back in silence. ++ * ++ *

At startup the tags are initialised by scanning back from the head to the most recent ++ * anchor height that carries a certificate (at most two intervals), so a freshly started node answers ++ * {@code finalized} before it imports its next anchor. ++ * ++ *

Inert on a chain where the anchor was never active (the node never installs it); inert below ++ * the activation height (no anchor height applies there). Stated, not measured here: the behaviour on ++ * the live fleet, which is the rehearsal's job. ++ */ ++public final class AerePqFinalityTags { ++ ++ private static final Logger LOG = LoggerFactory.getLogger(AerePqFinalityTags.class); ++ ++ /** Logged when a canonical reorg would move finality backwards; the tags are not moved. */ ++ public static final String CODE_REORG_BELOW_FINALIZED = "AERE-PQC-FIN-01"; ++ ++ private final PqAnchorConfig config; ++ private final MutableBlockchain blockchain; ++ private final Predicate carriesCertificate; ++ private final AtomicLong finalizedNumber = new AtomicLong(-1L); ++ ++ AerePqFinalityTags( ++ final PqAnchorConfig config, ++ final MutableBlockchain blockchain, ++ final Predicate carriesCertificate) { ++ this.config = config; ++ this.blockchain = blockchain; ++ this.carriesCertificate = carriesCertificate; ++ } ++ ++ /** ++ * Install the tags on a blockchain: initialise from the current head, then follow every block added. ++ * ++ * @param config the anchor configuration (activation height, interval schedule) ++ * @param blockchain the chain whose finalized/safe tags are written ++ * @param carriesCertificate whether a header carries a (validated) anchor certificate ++ * @return the installed instance, for inspection ++ */ ++ public static AerePqFinalityTags install( ++ final PqAnchorConfig config, ++ final MutableBlockchain blockchain, ++ final Predicate carriesCertificate) { ++ final AerePqFinalityTags tags = new AerePqFinalityTags(config, blockchain, carriesCertificate); ++ tags.initialiseFromHead(); ++ blockchain.observeBlockAdded(tags::onBlockAdded); ++ return tags; ++ } ++ ++ /** The height currently reported as finalized, or -1 when none has been set by this rule. */ ++ public long finalizedNumber() { ++ return finalizedNumber.get(); ++ } ++ ++ /** ++ * Whether a decoded header carries an anchor certificate. A header carries the v1 Falcon list OR ++ * the v2 scheme-tagged certificate, never both ({@link BftExtraData}), and from AIP-22 stage 5 ++ * every anchor carries the v2 certificate while {@code getFalconSeals()} is empty. So a predicate ++ * that only looked at the v1 list ({@code getFalconSeals()}) never fired on a stage-5 chain - ++ * measured 2026-09-26 on the rep28098 rehearsal, where {@code finalized} stayed 0 while the chain ++ * ran past certified anchors 1920 and 1952. Both fields are checked here, in one place both the ++ * controller and the test read, so the two cannot drift. ++ * ++ * @param extraData the decoded BFT extra data of the header ++ * @return true when the header carries a (v1 or v2) anchor certificate ++ */ ++ public static boolean carriesCertificate(final BftExtraData extraData) { ++ return !extraData.getFalconSeals().isEmpty() || !extraData.getHybridSeals().isEmpty(); ++ } ++ ++ /** Scan back from the head, at most two anchor intervals, to the last certified anchor. */ ++ void initialiseFromHead() { ++ final BlockHeader head = blockchain.getChainHeadHeader(); ++ if (head == null) { ++ return; ++ } ++ final long top = head.getNumber(); ++ final long floor = Math.max(0L, top - 2L * Math.max(1, config.intervalAt(top))); ++ for (long h = top; h >= floor; h--) { ++ if (!config.anchorAppliesAt(h)) { ++ continue; ++ } ++ final Optional header = blockchain.getBlockHeader(h); ++ if (header.isPresent() && carriesCertificate.test(header.get())) { ++ set(header.get().getParentHash(), h - 1L, "startup scan"); ++ return; ++ } ++ } ++ LOG.info( ++ "AERE PQ FINALITY (B1): no certified anchor between {} and the head {}; finalized/safe stay " ++ + "unset until the next anchor is imported.", ++ floor, ++ top); ++ } ++ ++ /** ++ * Follow a block added to the chain. ++ * ++ * @param event the event ++ */ ++ void onBlockAdded(final BlockAddedEvent event) { ++ if (event == null || !event.isNewCanonicalHead()) { ++ return; ++ } ++ final BlockHeader header = event.getHeader(); ++ if (header == null) { ++ return; ++ } ++ if (event.getEventType() == EventType.CHAIN_REORG && finalizedNumber.get() >= 0) { ++ final Hash ancestorHash = event.getCommonAncestorHash(); ++ final Optional ancestor = ++ ancestorHash == null ? Optional.empty() : blockchain.getBlockHeader(ancestorHash); ++ if (ancestor.isPresent() && ancestor.get().getNumber() < finalizedNumber.get()) { ++ LOG.error( ++ "{}: a canonical reorg to {} (common ancestor {}) went BELOW the finalized block {}. " ++ + "Finality tags are NOT moved back. Under the anchor rules this needs K validators to " ++ + "have certified two conflicting anchors; investigate before anything else.", ++ CODE_REORG_BELOW_FINALIZED, ++ header.getNumber(), ++ ancestor.get().getNumber(), ++ finalizedNumber.get()); ++ } ++ } ++ final long h = header.getNumber(); ++ if (config.anchorAppliesAt(h) && carriesCertificate.test(header)) { ++ set(header.getParentHash(), h - 1L, "anchor " + h); ++ } ++ } ++ ++ private void set(final Hash finalHash, final long finalNumber, final String why) { ++ if (finalNumber <= finalizedNumber.get()) { ++ return; // monotonic: never backwards, never twice for the same height ++ } ++ blockchain.setFinalized(finalHash); ++ blockchain.setSafeBlock(finalHash); ++ finalizedNumber.set(finalNumber); ++ LOG.info( ++ "AERE PQ FINALITY (B1): finalized/safe = {} ({}), covered by the certificate of {}.", ++ finalNumber, ++ finalHash, ++ why); ++ } ++} +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/AerePqHeaderSeal.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/AerePqHeaderSeal.java +new file mode 100644 +index 0000000000..4f3a7c76c0 +--- /dev/null ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/AerePqHeaderSeal.java +@@ -0,0 +1,95 @@ ++/* ++ * Copyright contributors to Besu / AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.consensus.common.bft; ++ ++/** ++ * AERE AIP-22 stage 5 (plan 9.7): from H_hdr ({@code aere.pq.headerBlock}) a header carries no ECDSA ++ * committed seal; its seventh extraData element is the proposer's Falcon-512 seal, the PROPOSAL layer's ++ * seal over the proposal digest, and a header is admitted between anchors iff that seal verifies for ++ * its {@code coinbase} (an id) at its height. Finality stays with the anchors (stage 4). H_hdr must be ++ * at or above H_fin, because the seal it relies on is only an AUTHOR from H_fin (AERE-PQC-HDR-01). ++ * Unset: never, which is every chain today. ++ */ ++public final class AerePqHeaderSeal { ++ ++ /** The system property naming H_hdr. */ ++ public static final String PROPERTY = "aere.pq.headerBlock"; ++ ++ private static volatile long headerBlock = AerePqIdentity.NEVER; ++ ++ private AerePqHeaderSeal() {} ++ ++ /** ++ * Arms H_hdr. ++ * ++ * @param hHdr H_hdr, or {@link AerePqIdentity#NEVER} ++ */ ++ public static void install(final long hHdr) { ++ if (hHdr != AerePqIdentity.NEVER) { ++ final long hFin = AerePqFinality.finalityBlock(); ++ if (hFin == AerePqIdentity.NEVER || hHdr < hFin) { ++ throw new IllegalStateException( ++ "AERE-PQC-HDR-01: " ++ + PROPERTY ++ + "=" ++ + hHdr ++ + " needs H_fin (aere.pq.finalityBlock) armed at or below it (H_fin " ++ + (hFin == AerePqIdentity.NEVER ? "unset" : Long.toString(hFin)) ++ + "): the proposer's seal in the header is an author only from H_fin"); ++ } ++ } ++ headerBlock = hHdr; ++ } ++ ++ /** Disarms (tests). */ ++ public static void uninstall() { ++ headerBlock = AerePqIdentity.NEVER; ++ } ++ ++ /** ++ * H_hdr as armed. ++ * ++ * @return H_hdr, or {@link AerePqIdentity#NEVER} ++ */ ++ public static long headerBlock() { ++ return headerBlock; ++ } ++ ++ /** Arms from {@link #PROPERTY}; unset means never. Call after H_fin is installed. */ ++ public static void installFromSystemProperties() { ++ final String v = System.getProperty(PROPERTY); ++ if (v == null || v.isBlank()) { ++ uninstall(); ++ return; ++ } ++ final long h; ++ try { ++ h = Long.parseLong(v.trim()); ++ } catch (final NumberFormatException e) { ++ throw new IllegalStateException("AERE-PQC-HDR-01: " + PROPERTY + "='" + v + "' is not a height", e); ++ } ++ install(h); ++ } ++ ++ /** ++ * Whether a header at this height carries the proposer's seal instead of ECDSA committed seals. ++ * ++ * @param height the header's height ++ * @return true from H_hdr ++ */ ++ public static boolean active(final long height) { ++ return height >= headerBlock; ++ } ++} +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/AerePqIdentity.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/AerePqIdentity.java +new file mode 100644 +index 0000000000..99778b62ab +--- /dev/null ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/AerePqIdentity.java +@@ -0,0 +1,561 @@ ++/* ++ * AERE AIP-22 stage 3: the post-quantum validator identity, in ONE place. ++ * ++ * WHAT IT DOES. From the activation height H_id, a validator is its 20-byte id (PqRegistryV3), not its ++ * ECDSA address. Upstream QBFT works entirely on two 20-byte things - the AUTHOR of a signed message and ++ * the validator LIST - so the switch is a TRANSLATION applied at the few places where an ECDSA address ++ * is born, and nowhere else (the choke points are listed in the AIP-22 plan, section 9.4): ++ * ++ * author(recovered, h) the author of a message or commit seal at height h: the id of the v3 row ++ * whose ecdsa.addr is the recovered address when h >= H_id, the address itself ++ * otherwise (an address with no row is then simply not in the set, and its ++ * message does not count - the upstream checks already say so) ++ * translateSet(set, b) the validator set after block b = H_id - 1 becomes the sorted ids of its ++ * members (VoteTallyUpdater), so extraData(H_id) carries ids and H_id is the ++ * first block sealed by ids; a member without a v3 row is a configuration ++ * FAULT that throws, never a silent drop ++ * local(address, h) this node's own identity at height h (coinbase, proposer check) ++ * isLocal(candidate, a) whether a 20-byte value is this node, in either form ++ * transportTargets(ids) the RLPx node-key addresses to send consensus messages to, from the rows' ++ * transport field; empty when some id lists none (send to every peer then) ++ * ++ * DISARMED unless installed: with no configuration every function is the identity, so a build that ++ * carries this class and is never configured behaves exactly as before, byte for byte. ++ * ++ * Configuration (system properties, like every AERE rule, read once at startup): ++ * aere.pq.identityBlock H_id ++ * aere.pq.registryV3 comma list of v3 manifests (JSON), each bound at its own bindHeight ++ * aere.pq.registryV3.hashes comma list "bindHeight:0xhash" - the pinned hash of every epoch; an ++ * epoch without a pin refuses startup (a registry nobody pinned is a file) ++ * ++ * NOT here (stated): the PQ seal registry lookups (index -> address) move to ids through the v3 epoch ++ * entering the registry schedule; the per-message PQ seal authorship check (SPEC 2.6 rule 2) then ++ * compares id with id. ++ */ ++package org.hyperledger.besu.consensus.common.bft; ++ ++import org.hyperledger.besu.datatypes.Address; ++ ++import java.io.IOException; ++import java.nio.file.Files; ++import java.nio.file.Path; ++import java.util.ArrayList; ++import java.util.Collection; ++import java.util.Collections; ++import java.util.List; ++import java.util.NavigableMap; ++import java.util.Optional; ++import java.util.TreeMap; ++import java.util.TreeSet; ++ ++import com.fasterxml.jackson.databind.ObjectMapper; ++import com.google.common.base.Splitter; ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.bytes.Bytes32; ++import org.slf4j.Logger; ++import org.slf4j.LoggerFactory; ++ ++/** The AIP-22 identity translation. */ ++public final class AerePqIdentity { ++ ++ private static final Logger LOG = LoggerFactory.getLogger(AerePqIdentity.class); ++ ++ /** H_id. */ ++ public static final String PROPERTY_BLOCK = "aere.pq.identityBlock"; ++ ++ /** The v3 manifests. */ ++ public static final String PROPERTY_REGISTRIES = "aere.pq.registryV3"; ++ ++ /** The pinned hashes of the v3 manifests. */ ++ public static final String PROPERTY_HASHES = "aere.pq.registryV3.hashes"; ++ ++ /** ++ * AIP-22 stage 3b: H_k, the height from which the keys that SEAL come from the v3 epoch in force ++ * (instead of the Falcon registry schedule and the hybrid registry). Must be the bindHeight of a v3 ++ * epoch and at or above H_id. Unset: the keys stay where they are (stage 3a). ++ */ ++ public static final String PROPERTY_KEYS_FROM = "aere.pq.registryV3.keysFrom"; ++ ++ /** No H_k: the v3 epochs never supply keys. */ ++ public static final long NEVER = Long.MAX_VALUE; ++ ++ /** ++ * An installed configuration. ++ * ++ * @param identityBlock H_id ++ * @param epochs v3 epochs by bindHeight ++ * @param keysFrom H_k, or {@link #NEVER} ++ */ ++ public record Config( ++ long identityBlock, NavigableMap epochs, long keysFrom) { ++ ++ /** ++ * A stage-3a configuration: identity only, keys stay in the existing registries. ++ * ++ * @param identityBlock H_id ++ * @param epochs v3 epochs by bindHeight ++ */ ++ public Config(final long identityBlock, final NavigableMap epochs) { ++ this(identityBlock, epochs, NEVER); ++ } ++ } ++ ++ /** A configuration fault of the identity switch. */ ++ public static final class IdentityException extends RuntimeException { ++ private static final long serialVersionUID = 1L; ++ ++ /** ++ * A fault. ++ * ++ * @param message what is wrong ++ */ ++ public IdentityException(final String message) { ++ super("AERE-PQC-ID: " + message); ++ } ++ } ++ ++ private static volatile Config config; ++ ++ private AerePqIdentity() {} ++ ++ /** ++ * Installs a configuration (startup, or a test). Checks that H_id has an epoch bound at or below it. ++ * ++ * @param c the configuration, or null to disarm ++ */ ++ public static void install(final Config c) { ++ if (c != null && c.epochs().floorEntry(c.identityBlock()) == null) { ++ throw new IdentityException( ++ "no v3 registry epoch is bound at or below the identity height " + c.identityBlock()); ++ } ++ if (c != null && c.keysFrom() != NEVER) { ++ // H_k switches where the keys come FROM; it must fall on an epoch boundary at or after H_id, so ++ // the epoch that starts supplying keys is a whole epoch, verified and pinned like every other ++ if (c.keysFrom() < c.identityBlock() || !c.epochs().containsKey(c.keysFrom())) { ++ throw new IdentityException( ++ PROPERTY_KEYS_FROM ++ + "=" ++ + c.keysFrom() ++ + " must be the bindHeight of a v3 epoch at or above the identity height " ++ + c.identityBlock() ++ + " (epochs " ++ + c.epochs().keySet() ++ + ")"); ++ } ++ } ++ config = c; ++ if (c != null) { ++ LOG.info( ++ "AERE PQ IDENTITY: ARMED - validators are post-quantum ids from height {}; v3 epochs {}{}", ++ c.identityBlock(), ++ c.epochs().keySet(), ++ c.keysFrom() == NEVER ++ ? "" ++ : "; the keys that seal come from the v3 epoch in force from height " + c.keysFrom()); ++ } ++ } ++ ++ /** Disarms (tests). */ ++ public static void uninstall() { ++ config = null; ++ } ++ ++ /** ++ * The installed configuration. ++ * ++ * @return it, if armed ++ */ ++ public static Optional installed() { ++ return Optional.ofNullable(config); ++ } ++ ++ /** ++ * Reads the configuration from the system properties and installs it. No property: stays disarmed. ++ * ++ * @param chainId the chain ++ * @param requiredAt the schemes every row must carry, as the scheme schedule names them at a height ++ */ ++ public static void installFromSystemProperties( ++ final long chainId, final java.util.function.LongFunction> requiredAt) { ++ final String block = System.getProperty(PROPERTY_BLOCK); ++ if (block == null || block.isBlank()) { ++ return; ++ } ++ final long h = Long.parseLong(block.trim()); ++ final List requiredSchemes = requiredAt.apply(h); ++ final String files = System.getProperty(PROPERTY_REGISTRIES, ""); ++ final String hashes = System.getProperty(PROPERTY_HASHES, ""); ++ final TreeMap pins = new TreeMap<>(); ++ for (final String p : Splitter.on(',').omitEmptyStrings().trimResults().split(hashes)) { ++ final int i = p.indexOf(':'); ++ if (i < 0) { ++ throw new IdentityException(PROPERTY_HASHES + " entry '" + p + "' is not bindHeight:0xhash"); ++ } ++ pins.put(Long.parseLong(p.substring(0, i)), Bytes32.fromHexString(p.substring(i + 1))); ++ } ++ final ObjectMapper m = new ObjectMapper(); ++ final List loaded = new ArrayList<>(); ++ PqRegistryV3.Registry previous = null; ++ final List paths = new ArrayList<>(); ++ for (final String f : Splitter.on(',').omitEmptyStrings().trimResults().split(files)) { ++ paths.add(Path.of(f)); ++ } ++ // epochs are loaded in bindHeight order, each against the one before it (rotations) ++ final TreeMap byHeight = new TreeMap<>(); ++ for (final Path p : paths) { ++ try { ++ final com.fasterxml.jackson.databind.JsonNode j = m.readTree(Files.readString(p)); ++ byHeight.put(j.path("bindHeight").asLong(-1), j); ++ } catch (final IOException e) { ++ throw new IdentityException("cannot read v3 manifest " + p + ": " + e.getMessage()); ++ } ++ } ++ for (final var e : byHeight.entrySet()) { ++ final Bytes32 pin = pins.get(e.getKey()); ++ if (pin == null) { ++ throw new IdentityException( ++ "the v3 epoch bound at " + e.getKey() + " has no pinned hash in " + PROPERTY_HASHES); ++ } ++ final boolean switchEpoch = previous == null; ++ final PqRegistryV3.Registry r = ++ PqRegistryV3.loadPinned(e.getValue(), chainId, requiredSchemes, previous, switchEpoch, pin); ++ loaded.add(r); ++ previous = r; ++ } ++ final TreeMap epochs = new TreeMap<>(); ++ for (final PqRegistryV3.Registry r : loaded) { ++ epochs.put(r.bindHeight(), r); ++ } ++ final String keysFrom = System.getProperty(PROPERTY_KEYS_FROM); ++ install( ++ new Config( ++ h, ++ Collections.unmodifiableNavigableMap(epochs), ++ keysFrom == null || keysFrom.isBlank() ? NEVER : Long.parseLong(keysFrom.trim()))); ++ } ++ ++ // --------------------------------------------------------------------------------------------- ++ // AIP-22 stage 3b: the keys that seal, from the v3 epoch in force ++ ++ /** ++ * Whether the keys that seal at this height come from the v3 epoch in force (at or above H_k). ++ * Every key lookup asks this first; below H_k (and disarmed) it answers false and the caller uses ++ * its existing registry, untouched. ++ * ++ * @param height the height the key is asked for, in the caller's own convention (the parent of an ++ * anchor for a certificate seal) ++ * @return true from H_k when armed ++ */ ++ public static boolean keysFromV3(final long height) { ++ final Config c = config; ++ return c != null && height >= c.keysFrom(); ++ } ++ ++ /** ++ * The public key of a registry index for a scheme at a height, from the v3 epoch in force, in the ++ * form the existing registries carry it: Falcon-512 WITHOUT the 0x09 header byte (the 896-byte h ++ * that {@code FalconPublicKeyParameters} takes), SLH-DSA-SHA2-128s as its 32 bytes. Empty when the ++ * epoch has no such row or key: the caller then has NO key (fail closed), it never falls back to ++ * the old registries, because above H_k they are no longer the key set the chain requires. ++ * ++ * @param height the height (see {@link #keysFromV3}) ++ * @param index the registry index carried by the seal ++ * @param schemeId e.g. "falcon-512" ++ * @return the key, or empty ++ */ ++ public static Optional v3KeyAt(final long height, final int index, final String schemeId) { ++ return epochAt(height) ++ .filter(r -> index >= 0 && index < r.rows().size()) ++ .map(r -> r.rows().get(index)) ++ .flatMap(row -> row.key(schemeId)) ++ .map( ++ k -> ++ "falcon-512".equals(schemeId) ++ ? java.util.Arrays.copyOfRange(k.publicKey(), 1, k.publicKey().length) ++ : k.publicKey().clone()); ++ } ++ ++ /** ++ * AIP-22 stage 3b-ii: the index of the row of the v3 epoch in force that carries a given public key ++ * for a scheme (the key in the registry form of {@link #v3KeyAt}). How a node finds, per epoch, ++ * which row is its own: indices move between epochs, so a key file's index cannot say it. ++ * ++ * @param height the height ++ * @param schemeId e.g. "falcon-512" ++ * @param publicKey the key, registry form ++ * @return the row index, or empty when no row of that epoch carries the key ++ */ ++ public static Optional v3IndexOfKey( ++ final long height, final String schemeId, final byte[] publicKey) { ++ final Optional r = epochAt(height); ++ if (r.isEmpty() || publicKey == null) { ++ return Optional.empty(); ++ } ++ for (final PqRegistryV3.Row row : r.get().rows()) { ++ final Optional k = v3KeyAt(height, row.index(), schemeId); ++ if (k.isPresent() && java.util.Arrays.equals(k.get(), publicKey)) { ++ return Optional.of(row.index()); ++ } ++ } ++ return Optional.empty(); ++ } ++ ++ /** ++ * The id of a registry index at a height, from the v3 epoch in force (stage 3b: the index names ++ * the v3 row directly, from H_k). ++ * ++ * @param height the height ++ * @param index the registry index ++ * @return the 20-byte id as an address, or empty when the epoch has no such row ++ */ ++ public static Optional

v3IdAt(final long height, final int index) { ++ return epochAt(height) ++ .filter(r -> index >= 0 && index < r.rows().size()) ++ .map(r -> Address.wrap(Bytes.wrap(r.rows().get(index).id()))); ++ } ++ ++ /** ++ * THE CONTINUITY GUARD, run once at startup when H_k is configured: switching the SOURCE of the ++ * keys at H_k must not change any key. Every key of every row of the epoch in force at H_k must be ++ * exactly the key the existing registries give that index just below H_k; only a LATER epoch may ++ * rotate, and only through the rotation signatures of the old keys, which the v3 loader verifies. ++ * A mismatch, or a key the existing registries cannot produce, refuses startup (fail closed): a ++ * node that swapped keys at H_k would accept seals no other node accepts. ++ * ++ * @param keysBefore (index, schemeId) to the key the existing registries give at H_k - 1, in the ++ * registry form (see {@link #v3KeyAt}) ++ */ ++ public static void verifyKeyContinuity( ++ final java.util.function.BiFunction> keysBefore) { ++ final Config c = config; ++ if (c == null || c.keysFrom() == NEVER) { ++ return; ++ } ++ final PqRegistryV3.Registry r = c.epochs().get(c.keysFrom()); ++ int checked = 0; ++ for (final PqRegistryV3.Row row : r.rows()) { ++ for (final PqRegistryV3.Key k : row.keys().values()) { ++ final String scheme = k.scheme().id(); ++ final byte[] v3 = v3KeyAt(c.keysFrom(), row.index(), scheme).orElseThrow(); ++ final Optional before = keysBefore.apply(row.index(), scheme); ++ if (before.isEmpty() || !java.util.Arrays.equals(before.get(), v3)) { ++ throw new IdentityException( ++ "continuity at " ++ + PROPERTY_KEYS_FROM ++ + "=" ++ + c.keysFrom() ++ + ": row " ++ + row.index() ++ + " " ++ + scheme ++ + (before.isEmpty() ++ ? " has no key in the existing registries at " + (c.keysFrom() - 1) ++ : " differs from the key the existing registries give at " + (c.keysFrom() - 1)) ++ + "; switching the key source must not change a key (a rotation belongs in a later" ++ + " epoch, signed by the old keys)"); ++ } ++ checked++; ++ } ++ } ++ LOG.info( ++ "AERE PQ IDENTITY: key continuity at {} verified, {} keys of {} rows equal the existing" ++ + " registries at {}", ++ c.keysFrom(), ++ checked, ++ r.rows().size(), ++ c.keysFrom() - 1); ++ } ++ ++ // --------------------------------------------------------------------------------------------- ++ ++ /** ++ * Whether ids are the identity at this height. ++ * ++ * @param height the height ++ * @return true from H_id when armed ++ */ ++ public static boolean active(final long height) { ++ final Config c = config; ++ return c != null && height >= c.identityBlock(); ++ } ++ ++ /** ++ * The v3 epoch in force at a height. ++ * ++ * @param height the height ++ * @return the epoch, if armed and one is bound at or below it ++ */ ++ public static Optional epochAt(final long height) { ++ final Config c = config; ++ if (c == null) { ++ return Optional.empty(); ++ } ++ final var e = c.epochs().floorEntry(height); ++ return e == null ? Optional.empty() : Optional.of(e.getValue()); ++ } ++ ++ /** ++ * The author of a message or commit seal whose ECDSA signature recovered to this address. ++ * ++ * @param recovered the recovered address ++ * @param height the height the message or seal is for ++ * @return the id from H_id (when a row links the address), the address otherwise ++ */ ++ public static Address author(final Address recovered, final long height) { ++ if (!active(height)) { ++ return recovered; ++ } ++ return idOfEcdsa(recovered.getBytes().toArrayUnsafe(), height) ++ .map(i -> Address.wrap(Bytes.wrap(i))) ++ .orElse(recovered); ++ } ++ ++ /** ++ * The id an ECDSA address links to at a height. The ecdsa link is required only in the switch epoch ++ * (AIP-22 3.2) and a later epoch may omit it, while messages still travel with an ECDSA signature ++ * until stage 4; so the link is INHERITED by id: the most recent epoch at or below the height that ++ * links this address names the id, and that id must still be registered in the epoch in force (a ++ * removed id's old link means nothing). A new id that never carried a link has no ECDSA author, so ++ * its classical messages cannot count before stage 4: stated in the plan (9.5), not hidden. ++ */ ++ private static Optional idOfEcdsa(final byte[] address, final long height) { ++ final Config c = config; ++ if (c == null) { ++ return Optional.empty(); ++ } ++ final var head = c.epochs().floorEntry(height); ++ if (head == null) { ++ return Optional.empty(); ++ } ++ // ids that a NEWER epoch already links to some address: an older link of another address to such an ++ // id is superseded (the id moved its ECDSA key), so that older address no longer authors as the id ++ final java.util.Set relinked = new java.util.HashSet<>(); ++ for (final PqRegistryV3.Registry e : c.epochs().headMap(height, true).descendingMap().values()) { ++ final Optional linked = e.rowOfEcdsa(address); ++ if (linked.isPresent()) { ++ final byte[] i = linked.get().id(); ++ return !relinked.contains(Bytes.wrap(i)) && head.getValue().rowOf(i).isPresent() ++ ? Optional.of(i) ++ : Optional.empty(); ++ } ++ for (final PqRegistryV3.Row r : e.rows()) { ++ if (r.ecdsaAddress() != null) { ++ relinked.add(Bytes.wrap(r.id())); ++ } ++ } ++ } ++ return Optional.empty(); ++ } ++ ++ /** ++ * This node's identity at a height. ++ * ++ * @param localEcdsa the node's ECDSA address ++ * @param height the height ++ * @return the id from H_id when the node has a row, the address otherwise ++ */ ++ public static Address local(final Address localEcdsa, final long height) { ++ return author(localEcdsa, height); ++ } ++ ++ /** ++ * Whether a 20-byte value is this node, as an address or as its id in any epoch. ++ * ++ * @param candidate the value ++ * @param localEcdsa the node's ECDSA address ++ * @return whether it is this node ++ */ ++ public static boolean isLocal(final Address candidate, final Address localEcdsa) { ++ if (candidate.equals(localEcdsa)) { ++ return true; ++ } ++ final Config c = config; ++ if (c == null) { ++ return false; ++ } ++ for (final PqRegistryV3.Registry r : c.epochs().values()) { ++ final Optional row = r.rowOfEcdsa(localEcdsa.getBytes().toArrayUnsafe()); ++ if (row.isPresent() && candidate.equals(Address.wrap(Bytes.wrap(row.get().id())))) { ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ /** ++ * Whether the set after this block changes form (armed, and the block is H_id - 1). Callers ask ++ * first so that, disarmed or at any other block, the upstream code path is untouched - not even an ++ * extra call on the tally (upstream VoteTallyUpdaterTest asserts exactly that). ++ * ++ * @param blockNumber the block ++ * @return true only at H_id - 1 when armed ++ */ ++ public static boolean translatesAfter(final long blockNumber) { ++ final Config c = config; ++ return c != null && blockNumber == c.identityBlock() - 1L; ++ } ++ ++ /** ++ * The validator set after block {@code blockNumber}, translated when that block is H_id - 1. ++ * ++ * @param set the set after the block, as upstream computed it ++ * @param blockNumber the block ++ * @return the same set, or its sorted ids at H_id - 1 ++ */ ++ public static Collection
translateSetAfter( ++ final Collection
set, final long blockNumber) { ++ final Config c = config; ++ if (c == null || blockNumber != c.identityBlock() - 1L) { ++ return set; ++ } ++ final PqRegistryV3.Registry r = ++ epochAt(c.identityBlock()) ++ .orElseThrow(() -> new IdentityException("no v3 epoch at " + c.identityBlock())); ++ final TreeSet
ids = new TreeSet<>(); ++ for (final Address a : set) { ++ final Optional row = r.rowOfEcdsa(a.getBytes().toArrayUnsafe()); ++ if (row.isEmpty()) { ++ throw new IdentityException( ++ "validator " ++ + a ++ + " is in the set after block " ++ + blockNumber ++ + " and has no row in the v3 epoch bound at " ++ + r.bindHeight() ++ + "; the identity switch refuses rather than dropping a validator"); ++ } ++ ids.add(Address.wrap(Bytes.wrap(row.get().id()))); ++ } ++ LOG.info( ++ "AERE PQ IDENTITY: the set after block {} is translated to {} post-quantum ids", ++ blockNumber, ++ ids.size()); ++ return ids; ++ } ++ ++ /** ++ * The RLPx node-key addresses consensus messages for these recipients go to. ++ * ++ * @param recipients validator identities (ids or addresses) ++ * @return the transport addresses; EMPTY when some id lists no transport, meaning "every peer" ++ */ ++ public static Optional> transportTargets(final Collection
recipients) { ++ final Config c = config; ++ if (c == null) { ++ return Optional.of(recipients); ++ } ++ final PqRegistryV3.Registry head = c.epochs().lastEntry().getValue(); ++ final List
out = new ArrayList<>(); ++ for (final Address a : recipients) { ++ final Optional row = head.rowOf(a.getBytes().toArrayUnsafe()); ++ if (row.isEmpty()) { ++ out.add(a); // a classical address (below H_id), sent to as before ++ } else if (row.get().transport() == null) { ++ return Optional.empty(); ++ } else { ++ out.add(Address.wrap(Bytes.wrap(row.get().transport()))); ++ } ++ } ++ return Optional.of(out); ++ } ++} +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/BftBlockHashing.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/BftBlockHashing.java +index 94dc41b354..06cb610099 100644 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/BftBlockHashing.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/BftBlockHashing.java +@@ -1,33 +1,39 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/0008-aere-pq-aip22.patch. + */ + package org.hyperledger.besu.consensus.common.bft; + + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.datatypes.Hash; + import org.hyperledger.besu.ethereum.core.BlockHeader; + import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder; + import org.hyperledger.besu.ethereum.core.Util; + import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; + + import java.util.List; + import java.util.function.Supplier; + import java.util.stream.Collectors; + + import org.apache.tuweni.bytes.Bytes; + + /** The Bft block hashing. */ + public class BftBlockHashing { + private final BftExtraDataCodec bftExtraDataCodec; + +@@ -85,41 +91,41 @@ public class BftBlockHashing { + final BftExtraData bftExtraData = bftExtraDataCodec.decode(header); + return Hash.hash( + serializeHeader( + header, + () -> bftExtraDataCodec.encodeWithoutCommitSealsAndRoundNumber(bftExtraData), + bftExtraDataCodec)); + } + + /** + * Recovers the {@link Address} for each validator that contributed a committed seal to the block. + * + * @param header the block header that was signed by the committed seals + * @param bftExtraData the parsed {@link BftExtraData} from the header + * @return the addresses of validators that provided a committed seal + */ + public List
recoverCommitterAddresses( + final BlockHeader header, final BftExtraData bftExtraData) { + final Hash committerHash = calculateDataHashForCommittedSeal(header, bftExtraData); + + return bftExtraData.getSeals().stream() +- .map(p -> Util.signatureToAddress(p, committerHash)) ++ .map(p -> AerePqIdentity.author(Util.signatureToAddress(p, committerHash), header.getNumber())) + .collect(Collectors.toList()); + } + + /** + * Serialize header bytes. + * + * @param header the header + * @param extraDataSerializer the extra data serializer + * @param bftExtraDataCodec the bft extra data codec + * @return the bytes + */ + public static Bytes serializeHeader( + final BlockHeader header, + final Supplier extraDataSerializer, + final BftExtraDataCodec bftExtraDataCodec) { + + // create a block header which is a copy of the header supplied as parameter except of the + // extraData field + final BlockHeaderBuilder builder = BlockHeaderBuilder.fromHeader(header); + builder.blockHeaderFunctions(BftBlockHeaderFunctions.forOnchainBlock(bftExtraDataCodec)); +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/BftBlockInterface.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/BftBlockInterface.java +index 77af53d688..acefe61665 100644 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/BftBlockInterface.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/BftBlockInterface.java +@@ -100,63 +100,66 @@ public class BftBlockInterface implements BlockInterface { + * + * @param block the block + * @param round the round + * @param blockHeaderFunctions the block header functions + * @return the block + */ + public Block replaceRoundInBlock( + final Block block, final int round, final BlockHeaderFunctions blockHeaderFunctions) { + final BftExtraData prevExtraData = bftExtraDataCodec.decode(block.getHeader()); + final BftExtraData substituteExtraData = + new BftExtraData( + prevExtraData.getVanityData(), + prevExtraData.getSeals(), + prevExtraData.getVote(), + round, + prevExtraData.getValidators(), + prevExtraData.getFalconSeals(), + // AERE ANCHOR V2 (2026-09-03, D-328): the scheme-tagged certificate rides along too. Without + // this line every v2 header lost its certificate at the round substitution and the fleet + // refused its own first v2 anchor (testnet 28001, block 168032, 3 hours stalled). +- prevExtraData.getHybridSeals()); ++ prevExtraData.getHybridSeals(), ++ // AERE AIP-22 stage 5: and the proposer's seal (element 6), for the same reason; it sits outside ++ // both hash pre-images, so carrying it changes no hash ++ prevExtraData.getPqProposerSeal()); + + final BlockHeaderBuilder headerBuilder = BlockHeaderBuilder.fromHeader(block.getHeader()); + headerBuilder + .extraData(bftExtraDataCodec.encode(substituteExtraData)) + .blockHeaderFunctions(blockHeaderFunctions); + + final BlockHeader newHeader = headerBuilder.buildBlockHeader(); + + return new Block(newHeader, block.getBody()); + } + + /** + * Gets extra data. + * + * @param header the header + * @return the extra data + */ + public BftExtraData getExtraData(final BlockHeader header) { + return bftExtraDataCodec.decode(header); + } + + /** + * Gets committers. + * + * @param header the header + * @return the committers + */ + public List
getCommitters(final BlockHeader header) { + final BftExtraData bftExtraData = bftExtraDataCodec.decode(header); + + final Hash committerHash = + Hash.hash( + BftBlockHashing.serializeHeader( + header, + () -> bftExtraDataCodec.encodeWithoutCommitSeals(bftExtraData), + bftExtraDataCodec)); + + return bftExtraData.getSeals().stream() +- .map(p -> Util.signatureToAddress(p, committerHash)) ++ .map(p -> AerePqIdentity.author(Util.signatureToAddress(p, committerHash), header.getNumber())) + .collect(Collectors.toList()); + } + } +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/BftExtraData.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/BftExtraData.java +index c444a1514d..4e9ea6f783 100644 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/BftExtraData.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/BftExtraData.java +@@ -32,40 +32,46 @@ import java.util.List; + import java.util.Optional; + + import org.apache.tuweni.bytes.Bytes; + + /** The Bft extra data. */ + public class BftExtraData implements ParsedExtraData { + private final Bytes vanityData; + private final Collection seals; + private final Collection
validators; + private final Optional vote; + private final int round; + + /** + * Parallel, ADDITIVE post-quantum (Falcon-512) seals. These sit alongside the decisive ECDSA + * {@link #seals} and are excluded from every signed pre-image, so they never disturb the ECDSA + * committed seals or the block/header hash. + */ + private final Collection falconSeals; + /** AERE ANCHOR V2: the scheme-tagged certificate; empty on every header below the v2 height. */ + private final List hybridSeals; ++ /** ++ * AERE AIP-22 stage 5: the proposer's post-quantum seal (element 6 of the stored extraData, from ++ * H_hdr), the PROPOSAL layer's seal over the proposal digest; outside every hash, like the ++ * certificate. Empty on every header below H_hdr. ++ */ ++ private final Optional proposerSeal; + + /** + * Instantiates a new Bft extra data (no Falcon seals). Retained for callers, notably the IBFT + * codec, that never carry a parallel post-quantum seal. + * + * @param vanityData the vanity data + * @param seals the seals + * @param vote the vote + * @param round the round + * @param validators the validators + */ + public BftExtraData( + final Bytes vanityData, + final Collection seals, + final Optional vote, + final int round, + final Collection
validators) { + this(vanityData, seals, vote, round, validators, Collections.emptyList()); + } + +@@ -86,41 +92,67 @@ public class BftExtraData implements ParsedExtraData { + final int round, + final Collection
validators, + final Collection falconSeals) { + this(vanityData, seals, vote, round, validators, falconSeals, Collections.emptyList()); + } + + /** + * Full constructor. + * + * @param hybridSeals the scheme-tagged (v2) certificate, or empty; a header carries the v1 Falcon + * list OR the v2 certificate, never both + */ + public BftExtraData( + final Bytes vanityData, + final Collection seals, + final Optional vote, + final int round, + final Collection
validators, + final Collection falconSeals, + final List hybridSeals) { ++ this(vanityData, seals, vote, round, validators, falconSeals, hybridSeals, Optional.empty()); ++ } ++ ++ /** ++ * Full constructor with the proposer's post-quantum seal (AIP-22 stage 5). ++ * ++ * @param vanityData the vanity data ++ * @param seals the ECDSA committed seals (from H_hdr: empty) ++ * @param vote the vote ++ * @param round the round ++ * @param validators the validators ++ * @param falconSeals the v1 Falcon certificate, or empty ++ * @param hybridSeals the v2 certificate, or empty ++ * @param proposerSeal the proposer's seal (element 6), or empty ++ */ ++ public BftExtraData( ++ final Bytes vanityData, ++ final Collection seals, ++ final Optional vote, ++ final int round, ++ final Collection
validators, ++ final Collection falconSeals, ++ final List hybridSeals, ++ final Optional proposerSeal) { + checkNotNull(vanityData); ++ checkNotNull(proposerSeal); ++ this.proposerSeal = proposerSeal; + checkNotNull(hybridSeals); + if (!hybridSeals.isEmpty() && falconSeals != null && !falconSeals.isEmpty()) { + throw new IllegalArgumentException( + "AERE ANCHOR V2: a header carries the v1 Falcon list OR the v2 certificate, not both"); + } + this.hybridSeals = List.copyOf(hybridSeals); + checkNotNull(seals); + checkNotNull(validators); + checkNotNull(falconSeals); + this.vanityData = vanityData; + this.seals = seals; + this.validators = validators; + this.vote = vote; + this.round = round; + this.falconSeals = falconSeals; + } + + /** + * Gets vanity data. + * +@@ -167,40 +199,66 @@ public class BftExtraData implements ParsedExtraData { + } + + /** + * Gets the parallel post-quantum Falcon seals. + * + * @return the Falcon seals (possibly empty, never null) + */ + public Collection getFalconSeals() { + return falconSeals; + } + + /** + * The scheme-tagged (v2) certificate. + * + * @return the v2 seals, canonical order; empty below the v2 height + */ + public List getHybridSeals() { + return hybridSeals; + } + ++ /** ++ * The proposer's post-quantum seal (AIP-22 stage 5, element 6). ++ * ++ * @return the seal, or empty below H_hdr ++ */ ++ public Optional getPqProposerSeal() { ++ return proposerSeal; ++ } ++ ++ /** ++ * The same extra data with another proposer seal and ECDSA seals, everything else carried over ++ * (the certificate included): the one way to seal a stage-5 header, so no caller can drop the ++ * certificate while adding the seal (the lesson of 2026-09-03, D-328). ++ * ++ * @param newSeals the ECDSA committed seals (from H_hdr: empty) ++ * @param newProposerSeal the proposer's seal ++ * @return the new extra data ++ */ ++ public BftExtraData withSeals( ++ final Collection newSeals, final Optional newProposerSeal) { ++ return new BftExtraData( ++ vanityData, newSeals, vote, round, validators, falconSeals, hybridSeals, newProposerSeal); ++ } ++ + @Override + public String toString() { + return "BftExtraData{" + + "vanityData=" + + vanityData + + ", seals=" + + seals + + ", validators=" + + validators + + ", vote=" + + vote + + ", round=" + + round + + ", falconSeals=" + + falconSeals + + ", hybridSeals=" + + hybridSeals ++ + ", proposerSeal=" ++ + proposerSeal + + '}'; + } + } +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/FalconSealSupport.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/FalconSealSupport.java +index 7049b84147..8482c3d47e 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/FalconSealSupport.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/FalconSealSupport.java +@@ -134,40 +134,61 @@ public final class FalconSealSupport { + + /** Storage slot (0) at the anchor address holding the manifest hash. 64-hex, no 0x prefix. */ + private static final String ANCHOR_SLOT = + "0000000000000000000000000000000000000000000000000000000000000000"; + + /** How many seals this node emitted on its own PREPAREs. See {@link #preparesSealed()}. */ + private final java.util.concurrent.atomic.AtomicLong preparesSealed = + new java.util.concurrent.atomic.AtomicLong(); + + /** How many seals this node emitted on its own PROPOSALs since startup. */ + private final java.util.concurrent.atomic.AtomicLong proposalsSealed = + new java.util.concurrent.atomic.AtomicLong(); + + /** How many seals this node emitted on its own ROUND-CHANGEs since startup. */ + private final java.util.concurrent.atomic.AtomicLong roundChangesSealed = + new java.util.concurrent.atomic.AtomicLong(); + + private final boolean signingEnabled; + private final int localIndex; + private final FalconPrivateKeyParameters localPrivateKey; ++ ++ /** ++ * AERE AIP-22 stage 3b-ii: this node's NEXT Falcon keys ({@code aere.falcon.keys.next} / ++ * {@code AERE_FALCON_KEYS_NEXT}, comma list of key files in the same format as {@code ++ * aere.falcon.key}), for the v3 epochs that rotate its key. From H_k the key and the index this node ++ * signs with at a height are the ones of the v3 row that carries one of its keys (see {@link ++ * #localAt}); the file's "index" property then means nothing, because indices move between epochs. ++ */ ++ private final java.util.List nextPrivateKeys; ++ ++ /** The local key and index resolved per v3 epoch (bindHeight), from H_k. */ ++ private final Map> localByEpoch = new ConcurrentHashMap<>(); ++ ++ /** ++ * A local signing key with the registry index it signs as. ++ * ++ * @param key the private key ++ * @param index the registry index at the height it was resolved for ++ */ ++ private record LocalKey(FalconPrivateKeyParameters key, int index) {} ++ + private final Map registry; + + /** + * Validator ADDRESS bound to each registry index (AUD-CONSENSUS-1 fix). Populated in lockstep + * with {@link #registry} from an address-bound manifest; empty for the legacy pubkey-only source. + * This is the map that makes {@code currentValidators INTERSECT registry} computable. + */ + private final Map indexToAddress; + + private final boolean genesisAnchored; + + /** + * AERE A8: the registry file this node ACTUALLY used, and which of the three sources it came from. + * Recorded so the consensus-binding guard can re-read exactly that file and hash it, rather than + * hashing something adjacent to it. Null when no registry is configured at all. + */ + private final String registrySourcePath; + + private final PqRegistryHash.SourceKind registrySourceKind; + +@@ -573,40 +594,70 @@ public final class FalconSealSupport { + try (InputStream in = new FileInputStream(keyPath)) { + final Properties p = new Properties(); + p.load(in); + idx = Integer.parseInt(p.getProperty("index").trim()); + final byte[] f = Bytes.fromHexStringLenient(p.getProperty("f").trim()).toArray(); + final byte[] g = Bytes.fromHexStringLenient(p.getProperty("g").trim()).toArray(); + final byte[] bigF = Bytes.fromHexStringLenient(p.getProperty("F").trim()).toArray(); + final byte[] pk = Bytes.fromHexStringLenient(p.getProperty("pk").trim()).toArray(); + priv = new FalconPrivateKeyParameters(FalconParameters.falcon_512, f, g, bigF, pk); + LOG.info( + "AERE PQC: loaded local Falcon signing key for validator index {} from {}", + idx, + keyPath); + } catch (final Exception e) { + LOG.warn("AERE PQC: failed to load Falcon signing key from {}: {}", keyPath, e.toString()); + idx = -1; + priv = null; + } + } + ++ // AERE AIP-22 stage 3b-ii: the next keys, same file format; a file that does not load refuses ++ // startup, because a validator that silently lacks its rotated key goes mute at the rotation epoch ++ final java.util.List next = new java.util.ArrayList<>(); ++ final String nextPaths = resolve("aere.falcon.keys.next", "AERE_FALCON_KEYS_NEXT"); ++ if (nextPaths != null) { ++ for (final String np : com.google.common.base.Splitter.on(',').omitEmptyStrings().trimResults().split(nextPaths)) { ++ if (np.isBlank()) { ++ continue; ++ } ++ try (InputStream in = new FileInputStream(np.trim())) { ++ final Properties p = new Properties(); ++ p.load(in); ++ next.add( ++ new FalconPrivateKeyParameters( ++ FalconParameters.falcon_512, ++ Bytes.fromHexStringLenient(p.getProperty("f").trim()).toArray(), ++ Bytes.fromHexStringLenient(p.getProperty("g").trim()).toArray(), ++ Bytes.fromHexStringLenient(p.getProperty("F").trim()).toArray(), ++ Bytes.fromHexStringLenient(p.getProperty("pk").trim()).toArray())); ++ LOG.info("AERE PQC: loaded a NEXT Falcon signing key from {} (AIP-22 stage 3b-ii)", np.trim()); ++ } catch (final Exception e) { ++ throw new IllegalStateException( ++ "AERE-PQC-KEY-NEXT-01: cannot load the next Falcon key from '" ++ + np.trim() ++ + "': " ++ + e.getMessage()); ++ } ++ } ++ } ++ this.nextPrivateKeys = java.util.List.copyOf(next); + this.registry = reg; + this.indexToAddress = regAddr; + this.localIndex = idx; + this.localPrivateKey = priv; + this.signingEnabled = priv != null && idx >= 0; + this.manifestHash = mHash; + this.genesisAnchored = anchored; + this.pendingLate = late; + this.pendingLateAddresses = lateAddr; + this.pendingLateHash = lateHash; + this.anchorContractAddress = anchorAddr; + + // AERE A8: remember WHICH file the registry came from, so the consensus-binding guard hashes + // the file this node is really running on and not a different one that happens to be nearby. + if (genesisPath != null) { + this.registrySourcePath = genesisPath; + this.registrySourceKind = PqRegistryHash.SourceKind.GENESIS_MANIFEST; + } else if (manifestPath != null && anchorProp != null) { + this.registrySourcePath = manifestPath; + this.registrySourceKind = PqRegistryHash.SourceKind.MANIFEST_JSON; +@@ -2507,40 +2558,123 @@ public final class FalconSealSupport { + "AERE PQC: LATE-ANCHOR ACTIVATED - Falcon registry ({} entries, address-bound={}) is now " + + "live; keccak256(manifest)=0x{} MATCHES the on-chain anchor at contract {} slot 0 " + + "(readable via eth_getStorageAt). Hybrid PQC certificate can now be verified on an " + + "already-live chain with NO re-genesis.", + registry.size(), + addressBound(), + pendingLateHash, + anchorContractAddress); + return true; + } + + /** + * Whether this node holds a Falcon signing key and should attach a parallel seal. + * + * @return true if signing is enabled + */ + public boolean signingEnabled() { + return signingEnabled; + } + ++ /** ++ * AERE AIP-22 stage 3b-ii. The key this node signs with at a height, and the index it signs as. ++ * Below H_k (and disarmed): the key of aere.falcon.key and its file index, exactly as before. From ++ * H_k: the v3 row of the epoch in force whose Falcon key is the public key of one of this node's ++ * keys (the base key or a next key); indices move between epochs, so the index is that row's. No ++ * row carries any of this node's keys: null, so nothing is signed (the startup guard {@link ++ * #verifyLocalKeysCoverV3EpochsOrAbort} refuses a validator that would end up there). ++ */ ++ private LocalKey localAt(final long height) { ++ if (!AerePqIdentity.keysFromV3(height)) { ++ return localPrivateKey == null ? null : new LocalKey(localPrivateKey, localIndex); ++ } ++ final long bind = ++ AerePqIdentity.epochAt(height).map(PqRegistryV3.Registry::bindHeight).orElse(-1L); ++ return localByEpoch ++ .computeIfAbsent( ++ bind, ++ b -> { ++ final java.util.List mine = new java.util.ArrayList<>(); ++ if (localPrivateKey != null) { ++ mine.add(localPrivateKey); ++ } ++ mine.addAll(nextPrivateKeys); ++ for (final FalconPrivateKeyParameters k : mine) { ++ final java.util.Optional i = ++ AerePqIdentity.v3IndexOfKey(height, "falcon-512", k.getPublicKey()); ++ if (i.isPresent()) { ++ return java.util.Optional.of(new LocalKey(k, i.get())); ++ } ++ } ++ return java.util.Optional.empty(); ++ }) ++ .orElse(null); ++ } ++ ++ /** ++ * AERE AIP-22 stage 3b-ii. The registry index this node signs as at a height (the index of every ++ * other scheme's seal of this node too: an SLH-DSA seal must sit at the index of its Falcon seal). ++ * ++ * @param height the height ++ * @return the index, or -1 when this node holds no key of that height ++ */ ++ public int localIndexAt(final long height) { ++ final LocalKey lk = localAt(height); ++ return lk == null ? -1 : lk.index(); ++ } ++ ++ /** ++ * AERE AIP-22 stage 3b-ii, THE STARTUP GUARD of the local keys: in every v3 epoch from H_k in which ++ * this node's identity is registered, this node must hold the Falcon key of its row, otherwise it ++ * refuses to start. A validator whose rotated key is missing would sign nothing from the rotation ++ * epoch on: mute, while every gate that asks "is it configured?" stays green (D-307). ++ * ++ * @param thisNodeAddress this node's own validator (ECDSA) address ++ */ ++ public void verifyLocalKeysCoverV3EpochsOrAbort(final Address thisNodeAddress) { ++ final java.util.Optional c = AerePqIdentity.installed(); ++ if (c.isEmpty() || c.get().keysFrom() == AerePqIdentity.NEVER || thisNodeAddress == null) { ++ return; ++ } ++ for (final PqRegistryV3.Registry e : c.get().epochs().tailMap(c.get().keysFrom(), true).values()) { ++ final Address me = AerePqIdentity.author(thisNodeAddress, e.bindHeight()); ++ if (e.rowOf(me.getBytes().toArrayUnsafe()).isEmpty()) { ++ continue; // this node is not a registered validator in this epoch: nothing to sign ++ } ++ if (localAt(e.bindHeight()) == null) { ++ throw new IllegalStateException( ++ "AERE-PQC-KEY-NEXT-02: REFUSING TO START. This node (" ++ + thisNodeAddress ++ + ", id " ++ + me ++ + ") is registered in the v3 epoch bound at " ++ + e.bindHeight() ++ + " but holds no Falcon key of its row there (aere.falcon.key / aere.falcon.keys.next);" ++ + " from that height it would sign nothing."); ++ } ++ LOG.info( ++ "AERE PQC: local Falcon key covers the v3 epoch bound at {} (index {}).", ++ e.bindHeight(), ++ localAt(e.bindHeight()).index()); ++ } ++ } ++ + /** + * This node's validator index in the Falcon registry. + * + * @return the local validator index, or -1 if signing is disabled + */ + public int localIndex() { + return localIndex; + } + + /** + * Number of validators in the Falcon registry. + * + * @return the registry size + */ + public int registrySize() { + return registry.size(); + } + + // ---- AERE audit fix (AUD-CONSENSUS-1 / -2): address binding + eligible-signer set ---- + +@@ -3443,47 +3577,51 @@ public final class FalconSealSupport { + * Falcon-sign a commit hash with this node's Falcon key, producing a parallel seal. Never throws. + * + *

AERE FIX-OPRIRE-CONSENS (b): the block number is MANDATORY and the attachment gate is + * checked here, at the single point where a seal can be produced. There is deliberately no + * height-less overload, so no call site can attach a seal without passing the gate. + * + * @param blockNumber the number of the block whose commit is being sealed + * @param commitHash the same 32-byte commit hash the ECDSA committed seal signs + * @return the Falcon seal, or empty if signing is disabled, gated off, or failed + */ + public Optional sign(final long blockNumber, final Bytes32 commitHash) { + if (!signingEnabled) { + return Optional.empty(); + } + if (!attachmentArmed(blockNumber)) { + return Optional.empty(); + } + // AERE AGILITY step 4 (2026-08-24): signing goes through the scheme layer. The same + // FalconSigner underneath, but the path is now the one the hybrid will use too; the 751 + // baseline tests prove the equivalence. ++ final LocalKey lk = localAt(blockNumber); // AERE AIP-22 stage 3b-ii ++ if (lk == null) { ++ return Optional.empty(); ++ } + final java.util.Optional sig = +- ((FalconSealScheme) SealSchemes.FALCON_512).signWithParams(localPrivateKey, commitHash.toArray()); ++ ((FalconSealScheme) SealSchemes.FALCON_512).signWithParams(lk.key(), commitHash.toArray()); + if (sig.isEmpty()) { + LOG.warn("AERE PQC: Falcon signing failed (ECDSA seal unaffected)"); + return Optional.empty(); + } +- return Optional.of(new FalconSeal(localIndex, Bytes.wrap(sig.get()))); ++ return Optional.of(new FalconSeal(lk.index(), Bytes.wrap(sig.get()))); + } + + /** + * Property naming the first height at which this node ATTACHES a post-quantum seal to its own + * PREPARE messages. Absent = never, which is the configuration of every node today. + * + *

SEPARATE from {@code aere.falcon.attachBlock}, and the separation is mandatory: if PREPARE + * emission started together with commit emission, rolling the binary onto the fleet would become + * a flag day. This way the binary can sit on every node for months before any of them emits + * anything new. + */ + public static final String PREPARE_ATTACH_PROPERTY = "aere.pq.preparePq.attachBlock"; + + /** Environment fallback for {@link #PREPARE_ATTACH_PROPERTY}. */ + public static final String PREPARE_ATTACH_ENV = "AERE_PQ_PREPAREPQ_ATTACHBLOCK"; + + /** + * The configured PREPARE attachment height, read fresh on every call. + * + *

Absent = {@link Long#MAX_VALUE}, i.e. never. A value that is PRESENT but unreadable REFUSES +@@ -3531,63 +3669,67 @@ public final class FalconSealSupport { + *

  • its own height, above. + * + * + *

    NEVER THROWS except for the strict configuration case above: a signing failure is a log line + * and an empty value, exactly as at commit, because the ECDSA path must not be disturbed. + * + * @param blockNumber the height being prepared + * @param message the domain-separated PREPARE message (see PqAnchor.prepareMessage) + * @return the seal, or empty when any gate is shut + */ + public Optional signPrepare(final long blockNumber, final Bytes32 message) { + if (!signingEnabled) { + return Optional.empty(); + } + if (!attachmentArmed(blockNumber)) { + return Optional.empty(); + } + if (blockNumber < prepareAttachBlock()) { + return Optional.empty(); + } ++ final LocalKey lk = localAt(blockNumber); // AERE AIP-22 stage 3b-ii ++ if (lk == null) { ++ return Optional.empty(); ++ } + final java.util.Optional sig = +- ((FalconSealScheme) SealSchemes.FALCON_512).signWithParams(localPrivateKey, message.toArray()); ++ ((FalconSealScheme) SealSchemes.FALCON_512).signWithParams(lk.key(), message.toArray()); + if (sig.isEmpty()) { + LOG.warn("AERE PQ PREPARE: Falcon signing failed (ECDSA path unaffected)"); + return Optional.empty(); + } + final long n = preparesSealed.incrementAndGet(); + // LOG VOLUME IS A DECISION, not an oversight. One line per PREPARE would be two lines per + // second per node, which is exactly the kind of log that gets trained away (see D-153, where a + // permanent ERROR made an entire log worthless). The first emission is worth a line, because it + // is the moment the node starts doing something new; after that, one line every 500, so a + // testnet still has a number to count. + if (n == 1L) { + LOG.info( + "AERE PQ PREPARE: this node EMITTED its first post-quantum seal on a PREPARE, at " + + "height {} (gate {}={}). From here on its PREPAREs carry a seal.", + blockNumber, + PREPARE_ATTACH_PROPERTY, + prepareAttachBlock()); + } else if (n % 500L == 0L) { + LOG.info("AERE PQ PREPARE: {} seals emitted on PREPAREs since startup.", n); + } +- return Optional.of(new FalconSeal(localIndex, Bytes.wrap(sig.get()))); ++ return Optional.of(new FalconSeal(lk.index(), Bytes.wrap(sig.get()))); + } + + /** + * How many seals this node has emitted on PREPAREs since startup. + * + *

    It exists so that the COVERAGE step can be measured: without a number, arming enforcement + * would be a bet. Read from the log on a testnet, and from this value in tests. + * + * @return the count + */ + public long preparesSealed() { + return preparesSealed.get(); + } + + /** + * Property naming the first height at which this node ATTACHES a post-quantum seal to its own + * PROPOSAL messages. Absent = never, which is the configuration of every node today. + * + *

    SEPARATE from both the commit and the PREPARE gates, same reason: three layers that arm on + * three independent decisions must not share a switch, or the day one is turned on becomes a flag +@@ -3636,60 +3778,64 @@ public final class FalconSealSupport { + * + *

    Same three requirements as {@link #signPrepare}, for the same three reasons: a key, the + * commit-layer coverage conditions, and its own height. NEVER throws except for the strict + * configuration case: a signing failure is a log line and an empty value, because the ECDSA path + * must not be disturbed. + * + * @param blockNumber the height being proposed + * @param message the domain-separated PROPOSAL message (see PqAnchor.proposalMessage) + * @return the seal, or empty when any gate is shut + */ + public Optional signProposal(final long blockNumber, final Bytes32 message) { + if (!signingEnabled) { + return Optional.empty(); + } + if (!attachmentArmed(blockNumber)) { + return Optional.empty(); + } + if (blockNumber < proposalAttachBlock()) { + return Optional.empty(); + } ++ final LocalKey lk = localAt(blockNumber); // AERE AIP-22 stage 3b-ii ++ if (lk == null) { ++ return Optional.empty(); ++ } + final java.util.Optional sig = +- ((FalconSealScheme) SealSchemes.FALCON_512).signWithParams(localPrivateKey, message.toArray()); ++ ((FalconSealScheme) SealSchemes.FALCON_512).signWithParams(lk.key(), message.toArray()); + if (sig.isEmpty()) { + LOG.warn("AERE PQ PROPOSAL: Falcon signing failed (ECDSA path unaffected)"); + return Optional.empty(); + } + final long n = proposalsSealed.incrementAndGet(); + // Same log-volume decision as at PREPARE: a proposal is at most one per round per proposer, so + // this is quieter by nature, but the counter still steps so a testnet has a number to count. + if (n == 1L) { + LOG.info( + "AERE PQ PROPOSAL: this node EMITTED its first post-quantum seal on a PROPOSAL, at " + + "height {} (gate {}={}). From here on its proposals carry a seal.", + blockNumber, + PROPOSAL_ATTACH_PROPERTY, + proposalAttachBlock()); + } else if (n % 500L == 0L) { + LOG.info("AERE PQ PROPOSAL: {} seals emitted on PROPOSALs since startup.", n); + } +- return Optional.of(new FalconSeal(localIndex, Bytes.wrap(sig.get()))); ++ return Optional.of(new FalconSeal(lk.index(), Bytes.wrap(sig.get()))); + } + + /** + * How many seals this node has emitted on its own PROPOSALs since startup. Exists so the + * coverage step can be measured, exactly as at PREPARE. + * + * @return the count + */ + public long proposalsSealed() { + return proposalsSealed.get(); + } + + /** + * The property that opens the ROUND-CHANGE attachment gate: from this height on, this node's own + * round-changes carry a Falcon seal. Emission only - enforcement is {@code + * aere.pq.roundChangePq.forkBlock}, deliberately separate so the fleet can emit long before any + * node refuses, exactly as at PREPARE and PROPOSAL. + */ + public static final String ROUNDCHANGE_ATTACH_PROPERTY = "aere.pq.roundChangePq.attachBlock"; + +@@ -3735,60 +3881,64 @@ public final class FalconSealSupport { + * + *

    Same three requirements as {@link #signPrepare} and {@link #signProposal}, for the same + * three reasons: a key, the commit-layer coverage conditions, and its own height. NEVER throws + * except for the strict configuration case: a signing failure is a log line and an empty value, + * because the ECDSA path must not be disturbed. + * + * @param blockNumber the height the round-change targets + * @param message the domain-separated ROUND-CHANGE message (see PqAnchor.roundChangeMessage) + * @return the seal, or empty when any gate is shut + */ + public Optional signRoundChange(final long blockNumber, final Bytes32 message) { + if (!signingEnabled) { + return Optional.empty(); + } + if (!attachmentArmed(blockNumber)) { + return Optional.empty(); + } + if (blockNumber < roundChangeAttachBlock()) { + return Optional.empty(); + } ++ final LocalKey lk = localAt(blockNumber); // AERE AIP-22 stage 3b-ii ++ if (lk == null) { ++ return Optional.empty(); ++ } + final java.util.Optional sig = +- ((FalconSealScheme) SealSchemes.FALCON_512).signWithParams(localPrivateKey, message.toArray()); ++ ((FalconSealScheme) SealSchemes.FALCON_512).signWithParams(lk.key(), message.toArray()); + if (sig.isEmpty()) { + LOG.warn("AERE PQ ROUNDCHANGE: Falcon signing failed (ECDSA path unaffected)"); + return Optional.empty(); + } + final long n = roundChangesSealed.incrementAndGet(); + // Round-changes only exist when rounds FAIL, so on a healthy chain this counter barely moves; + // it still steps so a testnet that forces round-changes has a number to count. + if (n == 1L) { + LOG.info( + "AERE PQ ROUNDCHANGE: this node EMITTED its first post-quantum seal on a ROUND-CHANGE, " + + "at height {} (gate {}={}). From here on its round-changes carry a seal.", + blockNumber, + ROUNDCHANGE_ATTACH_PROPERTY, + roundChangeAttachBlock()); + } else if (n % 100L == 0L) { + LOG.info("AERE PQ ROUNDCHANGE: {} seals emitted on ROUND-CHANGEs since startup.", n); + } +- return Optional.of(new FalconSeal(localIndex, Bytes.wrap(sig.get()))); ++ return Optional.of(new FalconSeal(lk.index(), Bytes.wrap(sig.get()))); + } + + /** + * How many seals this node has emitted on its own ROUND-CHANGEs since startup. Exists so the + * coverage step can be measured, exactly as at PREPARE and PROPOSAL. + * + * @return the count + */ + public long roundChangesSealed() { + return roundChangesSealed.get(); + } + + /** + * Verify a Falcon seal against the registry public key for its validator index. Never throws. + * + * @param validatorIndex the signer index + * @param commitHash the commit hash that was signed + * @param signature the Falcon signature bytes + * @return true iff a registry public key exists for the index and the signature verifies + */ +@@ -3796,40 +3946,49 @@ public final class FalconSealSupport { + return verifyWithKey(registry.get(validatorIndex), validatorIndex, commitHash, signature); + } + + /** + * D-081. The Falcon public key registered for an index AT A HEIGHT: the one carried by the + * registry the chain's schedule makes active there. + * + *

    WHY A HEIGHT IS NEEDED AT ALL. A certificate inside a block at height h was produced under + * the key set the chain required at h. After a rotation the node's own head registry is a + * different key set, so checking an old block against it fails for a reason that has nothing to do + * with the block. Cosmos ADR-016 states the same requirement for the same reason and keeps a + * height-to-key mapping; the only difference here is that ours is never pruned, because this chain + * has no unbonding period and a node syncing from genesis verifies every block ever produced. + * + *

    Returns the head registry's key when no binding is active at that height, which is every + * height below the schedule's first entry and every height on a chain with no schedule at all. So + * a node on chain 2800 as it stands today gets exactly what it got before D-081. + */ + private FalconPublicKeyParameters keyAt( + final long blockNumber, final int validatorIndex, final boolean historic) { ++ // AERE AIP-22 stage 3b: from H_k the key of an index is the one of the v3 epoch in force at this ++ // SAME height (the caller's convention is kept: the parent of an anchor for its certificate). No ++ // row or no key there means no key: never a fall-back to the registries below, which above H_k ++ // are no longer the key set the chain requires. Below H_k (and disarmed) nothing changes. ++ if (AerePqIdentity.keysFromV3(blockNumber)) { ++ return AerePqIdentity.v3KeyAt(blockNumber, validatorIndex, "falcon-512") ++ .map(pk -> new FalconPublicKeyParameters(FalconParameters.falcon_512, pk)) ++ .orElse(null); ++ } + final PqRegistryHash.Schedule schedule = this.registryBindingSchedule; + final PqRegistryHash.RegistrySet set = this.registryBindingSet; + if (schedule == null || set == null) { + return headRegistryKeyOrRefuse( + blockNumber, validatorIndex, "no schedule was ever loaded", historic); + } + final Optional required = + PqRegistryHash.requiredHashAt(schedule, blockNumber); + if (required.isEmpty()) { + // D-228. The only historical question ever asked one block below the schedule's first entry + // is about the certificate carried by the block at blockNumber+1, whose governing registry + // is the one bound EXACTLY at blockNumber+1. Answer it from that entry's VERIFIED bound + // registry, never from the unverified head file. Exactly one block: at blockNumber+2 below + // the schedule nothing changes. + final Optional nextEntry = + PqRegistryHash.requiredHashAt(schedule, blockNumber + 1); + if (nextEntry.isPresent() && nextEntry.get().block() == blockNumber + 1) { + final Optional boundNext = + PqRegistryHash.registryAt(schedule, set, blockNumber + 1); + if (boundNext.isPresent()) { +@@ -3851,40 +4010,54 @@ public final class FalconSealSupport { + } + final Optional active = + PqRegistryHash.registryAt(schedule, set, blockNumber); + if (active.isEmpty()) { + // The entry active here is covered by nothing this node holds. Fail closed: no key, so no + // seal verifies, and the per-block binding rule has already refused the header for the same + // reason. Silence here would be the node deciding a question it cannot answer. + return null; + } + for (final PqRegistryHash.Entry e : active.get().entries()) { + if (e.index() == validatorIndex) { + final FalconPublicKeyParameters pub = + new FalconPublicKeyParameters(FalconParameters.falcon_512, e.publicKey()); + historicalKeys.put(cacheKey, pub); + return pub; + } + } + return null; + } + ++ /** ++ * AERE AIP-22 stage 3b. The Falcon-512 public key (the 896-byte h, as the registries carry it) that ++ * the chain's registries give an index at a height, through the same history door as a received ++ * header. Used by the continuity guard at H_k - 1, where the v3 epochs do not yet supply keys. ++ * ++ * @param blockNumber the height ++ * @param validatorIndex the registry index ++ * @return the key, or empty when the registries give none there ++ */ ++ public Optional publicKeyBytesAtHistoric(final long blockNumber, final int validatorIndex) { ++ final FalconPublicKeyParameters k = keyAt(blockNumber, validatorIndex, true); ++ return k == null ? Optional.empty() : Optional.of(k.getH().clone()); ++ } ++ + /** + * D-081. The validator ADDRESS bound to a registry index at a height. + * + *

    D2 HARDENING (b-v2): PRIVATE, with the caller's motive as an argument. The two public + * doors are {@link #addressForIndexAtHistoric} and {@link #addressForIndexAtOwnHead}, each of + * which passes a constant. Nothing outside this file can choose the value, so the one shared + * resolution body cannot drift between the two paths and no caller can pick the wrong flag. + * + * @param blockNumber the height of the header being validated + * @param validatorIndex the registry index carried by a Falcon seal + * @param historic true when the subject is a header this node received, false when it is this + * node's own head or the block it is building + * @return the bound address, or null when the index is unregistered at that height or the + * registry active there is not address-bound + */ + private Address addressAt( + final long blockNumber, final int validatorIndex, final boolean historic) { + final PqRegistryHash.Schedule schedule = this.registryBindingSchedule; + final PqRegistryHash.RegistrySet set = this.registryBindingSet; + if (schedule == null || set == null) { +@@ -3983,52 +4156,65 @@ public final class FalconSealSupport { + * @param signature the Falcon signature bytes + * @return true iff a key exists for the index there and the signature verifies + */ + public boolean verifyAtOwnHead( + final long blockNumber, + final int validatorIndex, + final Bytes commitHash, + final Bytes signature) { + return verifyWithKey( + keyAt(blockNumber, validatorIndex, false), validatorIndex, commitHash, signature); + } + + /** + * D-081 / D2 HARDENING (b-v2). THE HISTORY DOOR, address half. See {@link #verifyAtHistoric}. + * + * @param blockNumber the height of the header being validated + * @param validatorIndex the registry index carried by a Falcon seal + * @return the bound address, or null when nothing binds that index at that height + */ + public Address addressForIndexAtHistoric(final long blockNumber, final int validatorIndex) { +- return addressAt(blockNumber, validatorIndex, true); ++ // AERE AIP-22 stage 3b: from H_k the index names the v3 row directly (its id), like its key ++ if (AerePqIdentity.keysFromV3(blockNumber)) { ++ return AerePqIdentity.v3IdAt(blockNumber, validatorIndex).orElse(null); ++ } ++ return identityOf(addressAt(blockNumber, validatorIndex, true), blockNumber); + } + + /** + * D2 HARDENING (b-v2). THE OWN-HEAD DOOR, address half. See {@link #verifyAtOwnHead}. + * + * @param blockNumber this node's own head, or the block it is building + * @param validatorIndex the registry index + * @return the bound address, or null + */ + public Address addressForIndexAtOwnHead(final long blockNumber, final int validatorIndex) { +- return addressAt(blockNumber, validatorIndex, false); ++ // AERE AIP-22 stage 3b: from H_k the index names the v3 row directly (its id), like its key ++ if (AerePqIdentity.keysFromV3(blockNumber)) { ++ return AerePqIdentity.v3IdAt(blockNumber, validatorIndex).orElse(null); ++ } ++ return identityOf(addressAt(blockNumber, validatorIndex, false), blockNumber); ++ } ++ ++ /** AERE AIP-22 stage 3: the registry's classical address for an index, as the identity of the height. */ ++ private static Address identityOf(final Address registryAddress, final long blockNumber) { ++ return registryAddress == null ? null : AerePqIdentity.author(registryAddress, blockNumber); + } + + /** + * D2 HARDENING (b). The one decision the whole hardening turns on, isolated so that removing it is + * a one-line edit and the negative control can prove the D2 test goes red without it. + * + *

    THE MEASURED DEFECT. Both height-resolved lookups used to answer a height they had no binding + * for by returning the HEAD registry - the key set in force right now. Below the arming height + * that is correct and costs nothing: no certificate is being judged there. At and above it, it is + * D2/T2 verbatim: "an armed node verifies a year-old header against the keys it holds today", so + * one rotation makes every block between the arming height and the rotation unverifiable, and the + * node reports success while doing it. Refusing is the only answer that does not assert a check + * that was not performed. + * + *

    WHAT A REFUSAL COSTS AND WHY IT IS THE CHEAPER FAILURE. A null key makes every seal fail, so + * {@code PqAnchorSealsRule} refuses the header and the node stops at the first block at or above + * the arming height. It stops; it does not fork. A node that cannot say which keys were in force + * cannot forge a competing history either, and the repair is to configure {@code + * config.pqRegistryHash} plus {@code aere.falcon.registry.history} and restart. Compare the + * silence this replaces, where the same node imports the whole chain and calls it verified. +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/HybridSealProducer.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/HybridSealProducer.java +index 591ede15ed..8fd27c7a77 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/HybridSealProducer.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/HybridSealProducer.java +@@ -26,115 +26,218 @@ import java.util.List; + import java.util.Map; + import java.util.Optional; + import java.util.Set; + + import org.apache.tuweni.bytes.Bytes; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + + /** Produces the non-Falcon scheme seals a hybrid commit carries, gated on height. */ + public final class HybridSealProducer { + + private static final Logger LOG = LoggerFactory.getLogger(HybridSealProducer.class); + + /** The disarmed attachment height: no block ever reaches it, so nothing is ever emitted. */ + public static final long NEVER = Long.MAX_VALUE; + + private final long attachFromBlock; + private final PqSchemeSchedule schedule; + private final int validatorIndex; + private final Map localKeys; ++ // AERE AIP-22 stage 3b-ii: this node's NEXT keys per scheme (rotations), and its local index by height (from H_k the index of ++ // its Falcon seal at that height, since an extra seal must sit at the index of its Falcon seal) ++ private final Map> nextKeys; ++ private final java.util.function.LongToIntFunction localIndexAt; ++ private final Map> v3KeyByEpoch = new java.util.concurrent.ConcurrentHashMap<>(); ++ // the origin of every anchor grid of the chain (AIP-22 stage 2: per-scheme intervals count from it) ++ private final long anchorBlock; + // one shout per missing scheme, not one per block: a permanent alarm is learned and ignored + private final Set alreadyShouted = new java.util.HashSet<>(); + + /** ++ * A producer for schedules WITHOUT per-scheme intervals (every named scheme at every anchor), ++ * which is every schedule written before AIP-22 stage 2; the grid origin is irrelevant then. ++ * + * @param attachFromBlock first height at which extras may be emitted; {@link #NEVER} to disarm + * @param schedule which schemes are required at which height; null disarms as well + * @param validatorIndex this node's index, written into every seal it produces + * @param localKeys the private handles this node holds, per scheme id + */ + public HybridSealProducer( + final long attachFromBlock, + final PqSchemeSchedule schedule, + final int validatorIndex, + final Map localKeys) { ++ this(attachFromBlock, schedule, validatorIndex, localKeys, 0L); ++ } ++ ++ /** ++ * @param attachFromBlock first height at which extras may be emitted; {@link #NEVER} to disarm ++ * @param schedule which schemes are required at which height; null disarms as well ++ * @param validatorIndex this node's index, written into every seal it produces ++ * @param localKeys the private handles this node holds, per scheme id ++ * @param anchorBlock the chain's anchor activation height, origin of the per-scheme grids ++ */ ++ public HybridSealProducer( ++ final long attachFromBlock, ++ final PqSchemeSchedule schedule, ++ final int validatorIndex, ++ final Map localKeys, ++ final long anchorBlock) { ++ this.attachFromBlock = schedule == null ? NEVER : attachFromBlock; ++ this.schedule = schedule; ++ this.validatorIndex = validatorIndex; ++ this.localKeys = localKeys == null ? Map.of() : Map.copyOf(localKeys); ++ this.anchorBlock = anchorBlock; ++ this.nextKeys = Map.of(); ++ this.localIndexAt = h -> FalconSealSupport.instance().localIndexAt(h); ++ } ++ ++ /** ++ * AERE AIP-22 stage 3b-ii: a producer that also holds NEXT keys and resolves its index by height. ++ * ++ * @param attachFromBlock first height at which extras may be emitted; {@link #NEVER} to disarm ++ * @param schedule which schemes are required at which height; null disarms as well ++ * @param validatorIndex this node's index below H_k ++ * @param localKeys the private handles this node holds, per scheme id ++ * @param anchorBlock the chain's anchor activation height, origin of the per-scheme grids ++ * @param nextKeys the next private handles per scheme id, for v3 epochs that rotate this node's keys ++ * @param localIndexAt this node's index at a height (from H_k: the index of its Falcon seal there) ++ */ ++ public HybridSealProducer( ++ final long attachFromBlock, ++ final PqSchemeSchedule schedule, ++ final int validatorIndex, ++ final Map localKeys, ++ final long anchorBlock, ++ final Map> nextKeys, ++ final java.util.function.LongToIntFunction localIndexAt) { + this.attachFromBlock = schedule == null ? NEVER : attachFromBlock; + this.schedule = schedule; + this.validatorIndex = validatorIndex; + this.localKeys = localKeys == null ? Map.of() : Map.copyOf(localKeys); ++ this.anchorBlock = anchorBlock; ++ this.nextKeys = nextKeys == null ? Map.of() : Map.copyOf(nextKeys); ++ this.localIndexAt = localIndexAt; ++ } ++ ++ /** ++ * AERE AIP-22 stage 3b-ii: the key of a scheme this node signs with at a height from H_k, and the index it signs as: the local ++ * handle (base or next) whose probe signature verifies under the key of this node's row in the v3 epoch in force. ++ * ++ * @param scheme the scheme ++ * @param height the height ++ * @return the handle, or empty when this node holds no key of its row there (or has no row) ++ */ ++ public Optional v3KeyAt(final SealScheme scheme, final long height) { ++ final int index = localIndexAt.applyAsInt(height); ++ if (index < 0) { ++ return Optional.empty(); ++ } ++ final long bind = AerePqIdentity.epochAt(height).map(PqRegistryV3.Registry::bindHeight).orElse(-1L); ++ return v3KeyByEpoch.computeIfAbsent( ++ bind + ":" + index + ":" + scheme.id(), ++ k -> { ++ final Optional rowKey = AerePqIdentity.v3KeyAt(height, index, scheme.id()); ++ if (rowKey.isEmpty()) { ++ return Optional.empty(); ++ } ++ final List mine = new ArrayList<>(); ++ if (localKeys.get(scheme.id()) != null) { ++ mine.add(localKeys.get(scheme.id())); ++ } ++ mine.addAll(nextKeys.getOrDefault(scheme.id(), List.of())); ++ final byte[] probe = ("AERE-HYBRID-KEY-PROBE-V3:" + bind + ":" + index).getBytes(java.nio.charset.StandardCharsets.UTF_8); ++ for (final SealScheme.PrivateHandle h : mine) { ++ final Optional sig = scheme.sign(h, probe); ++ if (sig.isPresent() && scheme.verifyRaw(rowKey.get(), probe, sig.get())) { ++ return Optional.of(h); ++ } ++ } ++ return Optional.empty(); ++ }); + } + + /** A producer that never emits anything: the configuration of every node today. */ + public static HybridSealProducer disarmed() { + return new HybridSealProducer(NEVER, null, -1, Map.of()); + } + + /** + * Whether extras may be emitted at this height at all. + * + * @param blockNumber the height + * @return true when the attachment gate is open + */ + public boolean attachmentArmedAt(final long blockNumber) { + return schedule != null && blockNumber >= attachFromBlock; + } + + /** + * The extra scheme seals for this block, or an empty list. + * + *

    Never throws: a producer fault must never take down the ECDSA commit path. Every refusal + * is a logged reason plus an empty list, exactly the stance of the Falcon signer. + * ++ *

    The block being committed is the PARENT of the anchor the seals serve (the caller only asks ++ * at anchor parents, D-329), so the schemes are those the anchor at {@code blockNumber + 1} ++ * requires: with per-scheme intervals (AIP-22 stage 2) a scheme on a coarser grid is not ++ * signed at the parent of an anchor that does not demand it. ++ * + * @param blockNumber the height of the block being committed + * @param message the very bytes the Falcon seal of this commit signs + * @return the seals, or empty when the gate is shut, a key is missing, or signing failed + */ + public List sealsFor(final long blockNumber, final Bytes message) { + if (!attachmentArmedAt(blockNumber) || message == null) { + return List.of(); + } + try { +- final Set required = schedule.schemesAt(blockNumber); ++ final Set required = schedule.schemesRequiredForAnchor(blockNumber + 1L, anchorBlock); + final List produced = new ArrayList<>(); + for (final String schemeId : required) { + if (SealSchemes.FALCON_512.id().equals(schemeId)) { + continue; // Falcon has its own slot and its own signer; never duplicated here + } + final Optional scheme = SealSchemes.byId(schemeId); + if (scheme.isEmpty()) { + shoutOnce(schemeId, "the schedule names scheme '" + schemeId + + "' which this binary does not implement"); + return List.of(); + } +- final SealScheme.PrivateHandle key = localKeys.get(schemeId); ++ // AERE AIP-22 stage 3b-ii: from H_k the key of this node's row in the v3 epoch in force, at its Falcon index there ++ final boolean v3 = AerePqIdentity.keysFromV3(blockNumber); ++ final SealScheme.PrivateHandle key = ++ v3 ? v3KeyAt(scheme.get(), blockNumber).orElse(null) : localKeys.get(schemeId); ++ final int index = v3 ? localIndexAt.applyAsInt(blockNumber) : validatorIndex; + if (key == null) { + shoutOnce(schemeId, "this node holds NO " + schemeId + + " signing key, so it cannot produce the certificate the schedule requires from" + + " height " + blockNumber + " onwards"); + return List.of(); + } + final Optional signature = scheme.get().sign(key, message.toArray()); + if (signature.isEmpty()) { + shoutOnce(schemeId, "signing with the local " + schemeId + " key FAILED"); + return List.of(); + } + produced.add( +- new SchemeSeal(scheme.get().wireId(), validatorIndex, Bytes.wrap(signature.get()))); ++ new SchemeSeal(scheme.get().wireId(), index, Bytes.wrap(signature.get()))); + } + // Canonical order, so two honest nodes signing the same block emit identical bytes and the + // certificate cannot become a source of gratuitous divergence. + produced.sort(PqAnchorV2.CANONICAL); + return List.copyOf(produced); + } catch (final RuntimeException e) { + LOG.warn("AERE HIBRID: producer fault at block {}, emitting nothing: {}", + blockNumber, e.getMessage()); + return List.of(); + } + } + + private void shoutOnce(final String schemeId, final String what) { + if (alreadyShouted.add(schemeId)) { + LOG.error("AERE HIBRID: {} - NO hybrid certificate will be emitted by this node." + + " Fix this BEFORE the enforcement height, not on the day.", what); + } + } + } +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/HybridSealSupport.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/HybridSealSupport.java +index 34f362d8d6..2bb8679682 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/HybridSealSupport.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/HybridSealSupport.java +@@ -147,40 +147,60 @@ public final class HybridSealSupport { + "AERE-PQC-COMMIT-CONF-03: " + PROPERTY_SCHEDULE + " and " + PROPERTY_REGISTRY + + " are a PAIR; configure both or neither. Half a hybrid configuration must" + + " refuse at startup, never run half-armed in silence."); + } + if (rawSchedule == null) { + if (rawAttach != null) { + throw new IllegalStateException( + "AERE-PQC-HYBRID-CONF-04: " + PROPERTY_ATTACH_BLOCK + " is set but the schedule and" + + " registry are not: this node would EMIT seals nobody can verify."); + } + return new HybridSealSupport(null, null, HybridSealProducer.disarmed()); + } + + final PqSchemeSchedule schedule; + try { + schedule = PqSchemeSchedule.parse(rawSchedule); + } catch (final RuntimeException e) { + throw new IllegalStateException( + "AERE-PQC-HYBRID-CONF-04: unparseable " + PROPERTY_SCHEDULE + ": " + e.getMessage()); + } ++ // AIP-22 stage 2: a per-scheme interval must be a multiple of the anchor interval this node ++ // runs, otherwise the scheme would be demanded at heights that are not anchors at all, and ++ // the two grids are only known together here. Refuse at startup, never run half-armed. ++ final PqAnchorConfig anchorConfig = ++ org.hyperledger.besu.consensus.common.bft.blockcreation.PqAnchorProducer.config(); ++ if (schedule.hasIntervals() && anchorConfig.anchorInterval().isPresent()) { ++ final int base = anchorConfig.anchorInterval().getAsInt(); ++ for (final PqSchemeSchedule.Step step : schedule.steps()) { ++ for (final Map.Entry e : step.intervals().entrySet()) { ++ if (e.getValue() % base != 0) { ++ throw new IllegalStateException( ++ "AERE-PQC-HYBRID-CONF-06: " + PROPERTY_SCHEDULE + " gives scheme '" + e.getKey() ++ + "' the interval " + e.getValue() + " at " + step.fromBlock() ++ + ", which is not a multiple of this node's anchor interval " + base ++ + " (" + PqAnchorConfig.PROPERTY_ANCHOR_INTERVAL + "); the scheme would be" ++ + " demanded at heights that carry no certificate. Refusing to start."); ++ } ++ } ++ } ++ } + final HybridSignerRegistry registry; + try { + final Properties p = new Properties(); + p.load( + new java.io.StringReader( + new String(reader.file(rawRegistry), StandardCharsets.UTF_8))); + registry = HybridSignerRegistry.fromProperties(p, rawRegistry); + } catch (final IOException e) { + throw new IllegalStateException( + "AERE-PQC-HYBRID-CONF-04: cannot read " + PROPERTY_REGISTRY + " '" + rawRegistry + + "': " + e.getMessage()); + } + + long attachFrom = HybridSealProducer.NEVER; + if (rawAttach != null) { + try { + attachFrom = Long.parseLong(rawAttach.trim()); + if (attachFrom < 0) { + throw new NumberFormatException("negative"); + } +@@ -236,60 +256,128 @@ public final class HybridSealSupport { + if (sig.isEmpty() || !scheme.verifyRaw(pub.get(), probe, sig.get())) { + throw new IllegalStateException( + "AERE-PQC-HYBRID-CONF-05: the local " + scheme.id() + " key at index " + index + + " does NOT verify against the registry's public key. Wrong key, wrong index," + + " or wrong registry; refusing to start half-armed."); + } + if (boundIndex != null && boundIndex != index) { + throw new IllegalStateException( + "AERE-PQC-HYBRID-CONF-05: local hybrid keys disagree on the validator index (" + + boundIndex + " vs " + index + "). One node, one identity."); + } + boundIndex = index; + keys.put(scheme.id(), handle); + LOG.info( + "AERE HIBRID: loaded local {} signing key for validator index {} (probe verified" + + " against the registry)", + scheme.id(), + index); + } + ++ // AERE AIP-22 stage 3b-ii: this node's NEXT keys per scheme (aere.pq.hybrid.key..next, comma list, same file ++ // format). They belong to later v3 epochs, so no registry probe here: the startup guard checks each against its v3 row. ++ final Map> next = new HashMap<>(); ++ for (final SealScheme scheme : SealSchemes.all()) { ++ if (scheme.id().equals(SealSchemes.FALCON_512.id())) { ++ continue; ++ } ++ final String paths = reader.property(PROPERTY_KEY_PREFIX + scheme.id() + ".next"); ++ if (paths == null) { ++ continue; ++ } ++ for (final String np : com.google.common.base.Splitter.on(',').omitEmptyStrings().trimResults().split(paths)) { ++ if (np.isBlank()) { ++ continue; ++ } ++ try { ++ final Properties kp = new Properties(); ++ kp.load(new java.io.StringReader(new String(reader.file(np.trim()), StandardCharsets.UTF_8))); ++ final byte[] sk = Bytes.fromHexStringLenient(kp.getProperty("sk", "").trim()).toArray(); ++ next.computeIfAbsent(scheme.id(), x -> new java.util.ArrayList<>()) ++ .add(scheme.parsePrivateKey(sk).orElseThrow(() -> new IllegalStateException("bytes do not parse as a private key"))); ++ LOG.info("AERE HIBRID: loaded a NEXT {} signing key from {} (AIP-22 stage 3b-ii)", scheme.id(), np.trim()); ++ } catch (final IOException | RuntimeException e) { ++ throw new IllegalStateException( ++ "AERE-PQC-KEY-NEXT-01: cannot load the next " + scheme.id() + " key from '" + np.trim() + "': " + e.getMessage()); ++ } ++ } ++ } ++ + if (attachFrom != HybridSealProducer.NEVER && keys.isEmpty()) { + throw new IllegalStateException( + "AERE-PQC-HYBRID-CONF-04: emission is armed from " + attachFrom + " but this node" + + " holds no local hybrid key (" + PROPERTY_KEY_PREFIX + " unset)." + + " It would promise a certificate it cannot produce."); + } + + final HybridSealProducer producer = + keys.isEmpty() + ? HybridSealProducer.disarmed() +- : new HybridSealProducer(attachFrom, schedule, boundIndex, keys); ++ : new HybridSealProducer( ++ attachFrom, ++ schedule, ++ boundIndex, ++ keys, ++ anchorConfig.anchorBlock(), ++ next, ++ h -> FalconSealSupport.instance().localIndexAt(h)); + return new HybridSealSupport(schedule, registry, producer); + } + + private static String firstOf(final ConfigReader r, final String prop, final String env) { + final String p = r.property(prop); + return p != null ? p : r.environment(env); + } + + /** Returns the schedule, when the hybrid pair is configured. + * + * @return the schedule, or empty */ + public Optional schedule() { + return Optional.ofNullable(schedule); + } + + /** Returns the registry, when the hybrid pair is configured. + * + * @return the registry, or empty */ + public Optional registry() { + return Optional.ofNullable(registry); + } + + /** Returns the producer; disarmed (never emits) when nothing is configured. + * + * @return the producer */ + public HybridSealProducer producer() { + return producer; + } ++ ++ /** ++ * AERE AIP-22 stage 3b-ii, THE STARTUP GUARD of the local hybrid keys: in every v3 epoch from H_k where this node's identity is ++ * registered, it must hold, for every non-Falcon scheme the schedule names at that epoch, the key of its row. Otherwise it would ++ * produce no hybrid seal from that epoch on while every configuration gate stays green; refuse to start instead. ++ * ++ * @param thisNodeAddress this node's own validator (ECDSA) address ++ */ ++ public void verifyLocalKeysCoverV3EpochsOrAbort(final org.hyperledger.besu.datatypes.Address thisNodeAddress) { ++ final Optional c = AerePqIdentity.installed(); ++ if (schedule == null || c.isEmpty() || c.get().keysFrom() == AerePqIdentity.NEVER || thisNodeAddress == null) { ++ return; ++ } ++ for (final PqRegistryV3.Registry e : c.get().epochs().tailMap(c.get().keysFrom(), true).values()) { ++ final org.hyperledger.besu.datatypes.Address me = AerePqIdentity.author(thisNodeAddress, e.bindHeight()); ++ if (e.rowOf(me.getBytes().toArrayUnsafe()).isEmpty()) { ++ continue; ++ } ++ for (final String schemeId : schedule.schemesAt(e.bindHeight())) { ++ if (schemeId.equals(SealSchemes.FALCON_512.id())) { ++ continue; ++ } ++ final Optional scheme = SealSchemes.byId(schemeId); ++ if (scheme.isEmpty() || producer.v3KeyAt(scheme.get(), e.bindHeight()).isEmpty()) { ++ throw new IllegalStateException( ++ "AERE-PQC-KEY-NEXT-02: REFUSING TO START. This node (id " + me + ") is registered in the v3 epoch bound at " ++ + e.bindHeight() + " but holds no " + schemeId + " key of its row there (aere.pq.hybrid.key." + schemeId ++ + "[.next]); from that height it would produce no hybrid seal."); ++ } ++ } ++ } ++ } + } +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqAnchor.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqAnchor.java +old mode 100755 +new mode 100644 +index 32c634ee85..5524158c03 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqAnchor.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqAnchor.java +@@ -503,45 +503,46 @@ public final class PqAnchor { + * commits in a {@code LinkedHashMap} keyed on author and {@code values()} yields arrival order, so + * a producer that skips {@link #sortedByIndex(Collection)} writes an unsorted certificate and + * nothing downstream notices: the anchor digest is taken IN THE ORDER GIVEN, so those headers' + * digests are perfectly consistent with their own bytes. 36 such headers are canonical today. + * + *

    Nodes already holding the chain never revalidate them, which is exactly why this was invisible + * for a day. A node syncing from genesis under the plain rule would reject header 13,267,824 and + * stop there forever. That is the same shape as the base-fee floor episode: the history is what it + * is, and the exception belongs at VALIDATION, where a header is accepted as written, not in any + * recomputation. A patch anywhere else moves the error instead of ending it. + * + *

    What the exception does NOT relax. Inside the window the certificate must still have + * non-negative and pairwise distinct indices. Measured 2026-08-11 on all 36 headers: distinct in + * every one, no negative index in any. So this accepts exactly the history that exists and nothing + * weaker, and the "repeat one seal to inflate k" attack stays unrepresentable at every height. + * + *

    Producers must not call this. {@code PqAnchorProducer} keeps requiring strict + * sortedness, so no new unsorted header can ever be written, at any height. The window is closed by + * construction: it is bounded above by a measured constant, so it cannot grow. + * ++ * @param chainId the chain of the header; the unordered exception exists on chain 2800 only (D-428) + * @param certificate the carried certificate + * @param blockNumber the number of the header carrying it + * @return true iff the ordering is acceptable for a header at that height + */ + public static boolean hasAcceptableIndices( +- final Collection certificate, final long blockNumber) { ++ final long chainId, final Collection certificate, final long blockNumber) { + if (hasStrictlyIncreasingIndices(certificate)) { + return true; + } +- return PqAnchorLapse.isDisarmed(blockNumber) && hasDistinctNonNegativeIndices(certificate); ++ return PqAnchorLapse.isDisarmed(chainId, blockNumber) && hasDistinctNonNegativeIndices(certificate); + } + + /** + * Return the certificate sorted by validator index, ascending. Producers use this before writing + * the certificate into extraData; validators never sort, they require sortedness. + * + * @param certificate the seals in any order + * @return a new list sorted by validator index + */ + public static List sortedByIndex(final Collection certificate) { + final List sorted = new ArrayList<>(certificate); + sorted.sort(BY_INDEX); + return sorted; + } + } +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqAnchorLapse.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqAnchorLapse.java +index a7c8c9bf1a..0c4cc207f8 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqAnchorLapse.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqAnchorLapse.java +@@ -303,73 +303,89 @@ public final class PqAnchorLapse { + private PqAnchorLapse() {} + + /** + * Every named range, ordered by first height. + * + * @return an unmodifiable list, never null, possibly empty + */ + public static List windows() { + return WINDOWS; + } + + /** + * Whether the anchor rules were out of force ENTIRELY at this height. + * + *

    This is the single question both anchor rules ask before they judge anything. They ask it + * through this one method, for the same reason they share {@code anchorAppliesAt}: two rules that + * each decided the boundary their own way could disagree about one header, and a header accepted + * by one rule and refused by the other is a chain break. + * + *

    It is deliberately FALSE inside a threshold-only range. There the digest binding and the +- * ordering did hold and are still required; only {@link #historicMinSeals(long)} moves. ++ * ordering did hold and are still required; only {@link #historicMinSeals(long, long)} moves. + * ++ *

    AERE D-428 (2026-09-28): the ranges are facts about chain {@value #CHAIN_ID} and about no other chain. Before this the ++ * predicates did not take the chain, so a node of ANY other network built from this source turned the anchor rules off over ++ * the same heights, while the second client (PqAnchorLapse.cs) never did: two clients judging one header differently. ++ * ++ * @param chainId the chain of the header being judged + * @param blockNumber the height being judged + * @return true iff the height falls inside a range where nothing was in force + */ +- public static boolean isDisarmed(final long blockNumber) { ++ public static boolean isDisarmed(final long chainId, final long blockNumber) { ++ if (chainId != CHAIN_ID) { ++ return false; ++ } + for (final Window window : WINDOWS) { + if (window.covers(blockNumber) && window.relaxation() == Relaxation.EVERYTHING) { + return true; + } + } + return false; + } + + /** + * The seal threshold that was actually in force at this height, when it was lower than the + * configured schedule. + * + *

    This is the same lever the fleet itself used at the time, the emergency ceiling, replayed + * from a fixed range instead of from a runtime option. A node validating history therefore asks + * the certificate for what was asked of the proposer that wrote it, and nothing more. + * ++ * @param chainId the chain of the header being judged; any chain but {@value #CHAIN_ID} gets empty (D-428) + * @param blockNumber the height being judged + * @return the threshold in force, or empty when the configured schedule applies unchanged + */ +- public static OptionalInt historicMinSeals(final long blockNumber) { ++ public static OptionalInt historicMinSeals(final long chainId, final long blockNumber) { ++ if (chainId != CHAIN_ID) { ++ return OptionalInt.empty(); ++ } + for (final Window window : WINDOWS) { + if (window.covers(blockNumber) && window.relaxation() == Relaxation.THRESHOLD_ONLY) { + return OptionalInt.of(window.effectiveMinSeals()); + } + } + return OptionalInt.empty(); + } + + /** + * The range covering a height, when there is one. + * ++ * @param chainId the chain of the header being judged; any chain but {@value #CHAIN_ID} gets empty (D-428) + * @param blockNumber the height being judged + * @return the range, or empty + */ +- public static Optional windowCovering(final long blockNumber) { ++ public static Optional windowCovering(final long chainId, final long blockNumber) { ++ if (chainId != CHAIN_ID) { ++ return Optional.empty(); ++ } + return WINDOWS.stream().filter(w -> w.covers(blockNumber)).findFirst(); + } + + /** + * The first height of the earliest named range, or empty when there is none. + * + * @return the earliest affected height + */ + public static Optional earliestAffectedBlock() { + return WINDOWS.stream().map(Window::firstBlock).min(Comparator.naturalOrder()); + } + } +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqRegistryHashTool.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqRegistryHashTool.java +index 14071c5e4e..3617715f3e 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqRegistryHashTool.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqRegistryHashTool.java +@@ -151,95 +151,95 @@ public final class PqRegistryHashTool { + return 2; + } + final long h = Long.parseLong(armingHeightRaw); + final List files = files(o, "registry"); + if (files.isEmpty()) { + System.out.println("NOT MEASURED: --registry is missing"); + return 2; + } + // The epochs: the first at the arming height, then one per --rotation =. + final Map epoci = new LinkedHashMap<>(); + epoci.put(h, files.get(0)); + for (final String rot : list(o.get("rotation"))) { + final int eq = rot.indexOf('='); + if (eq < 0) { + System.out.println("NOT MEASURED: --rotation is written =, got: " + rot); + return 2; + } + epoci.put(Long.parseLong(rot.substring(0, eq).trim()), Path.of(rot.substring(eq + 1).trim())); + } + +- final List inaltimi = new ArrayList<>(epoci.keySet()); +- inaltimi.sort(Long::compare); +- if (inaltimi.get(0) != h) { +- System.out.println("RED: the first epoch is at " + inaltimi.get(0) + ", not at the arming height " + h); ++ final List epochHeights = new ArrayList<>(epoci.keySet()); ++ epochHeights.sort(Long::compare); ++ if (epochHeights.get(0) != h) { ++ System.out.println("RED: the first epoch is at " + epochHeights.get(0) + ", not at the arming height " + h); + return 1; + } + + // NO COMMENT INSIDE THE FRAGMENT, and that is a measurement, not a matter of taste. The first + // form of this method put the file path after every entry, as `// /path/registry.json`. + // The fragment LOOKS fine and CANNOT BE USED: genesis is read with Jackson without + // ALLOW_COMMENTS, so a node handed one of those refuses to start with + // [AERE-PQC-REG-LOAD-13] "Unexpected character ('/')", and it then refuses EVERY header from + // the arming height upwards. Measured 2026-08-06, cases U3/U4 in d2-v2/dovezi/controale/. + // Whatever is explanation is printed outside the JSON, on lines beginning with #. + final StringBuilder json = new StringBuilder(); + json.append(" \"pqRegistryHash\": [\n"); + final StringBuilder history = new StringBuilder(); + final StringBuilder harta = new StringBuilder(); +- for (int i = 0; i < inaltimi.size(); i++) { +- final long b = inaltimi.get(i); ++ for (int i = 0; i < epochHeights.size(); i++) { ++ final long b = epochHeights.get(i); + final Path p = epoci.get(b); + final PqRegistryHash.Registry reg = PqRegistryHash.loadAuto(p); + // AERE D-C (2026-08-06). THIS IS THE DANGEROUS VERB: what is printed here gets pasted into + // genesis, and genesis is the document all seven nodes hold identical. hashV1 next to a + // registry that carries proofs writes into genesis a number the node's guard (hashFor) never + // produces, so all seven nodes start, all report the registry loaded, and the chain stops at + // H-1. A wrong indication is more dangerous than a missing one. + final String hash = PqRegistryHash.hashFor(reg, chainId); + // AERE D-B (2026-08-06). The recipe we print has to be the one the NEW code accepts. Since + // 2026-08-06 the node refuses to start (AERE-PQC-REG-BIND-08) on a registry forced in at a + // height its proofs did not sign. If the tool printed that recipe, it would manufacture + // exactly the configuration the node rejects, and it would do so in a file that reaches all + // seven at once. + if (reg.proofBound() && reg.bindHeight() != b) { + System.out.println( + "RED: registry " + + p + + " has bind height " + + reg.bindHeight() + + ", while here it is scheduled from block " + + b + + ". The two numbers must be EQUAL: every row of the registry carries a proof of " + + "possession and a claim, and both sign the bind height. A registry forced in from " + + "another block is an activation day no validator signed, and the node refuses to " + + "start on it with AERE-PQC-REG-BIND-08. It is not repaired by editing the " + + "bindHeight field: the proofs are over it, and the file would no longer load at " + + "all (AERE-PQC-REG-BIND-03). It is repaired either by scheduling the epoch at " + + reg.bindHeight() + + ", or by re-signing the registry for " + + b + + ", which means the key ceremony and a NEW hash."); + return 1; + } + json.append(" {\"block\": ").append(b).append(", \"hash\": \"0x").append(hash).append("\"}"); +- if (i < inaltimi.size() - 1) { ++ if (i < epochHeights.size() - 1) { + json.append(','); + } + json.append('\n'); + harta.append("# block ").append(b).append(" -> ").append(p.toAbsolutePath()).append('\n'); + if (history.length() > 0) { + history.append(','); + } + history.append(p.toAbsolutePath()); + } + json.append(" ]"); + + System.out.println("# 1. In the genesis of chain " + chainId + ", inside the \"config\" object:"); + System.out.println("# The fragment below is VALID JSON and is pasted as it stands. No comments"); + System.out.println("# are added to it: genesis is read WITHOUT ALLOW_COMMENTS and the node refuses to start."); + System.out.println(json); + System.out.println("# Which registry file stands behind each epoch:"); + System.out.print(harta); + System.out.println(); + System.out.println("# 2. On EVERY node, the second client included, in BESU_OPTS:"); + System.out.println("-Daere.falcon.registry.history=" + history); +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqRegistryV3.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqRegistryV3.java +new file mode 100644 +index 0000000000..3fb8a5c543 +--- /dev/null ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqRegistryV3.java +@@ -0,0 +1,963 @@ ++/* ++ * AERE AIP-22 stage 3: the validator registry v3 (post-quantum identity). ++ * ++ * WHAT IT IS. One registry epoch as a JSON manifest: rows keyed "0".."count-1" plus formatVersion 3, ++ * chainId, bindHeight and count at top level. Each row names a validator by a 20-byte `id` derived ++ * from its Falcon-512 key (AIP-22 section 3.1, the AIP-20 sender derivation with alg id 0x20): ++ * ++ * id = keccak256(0x50 || 0x20 || falcon512_public_key_897)[12:32] ++ * ++ * and binds to it one public key per seal scheme, each with a proof of possession. The id is taken ++ * at the first registration and KEPT through key rotations: a later epoch may change a row's keys ++ * only with a rotation signature by EVERY key the previous epoch bound to that id. The `ecdsa` ++ * field ({addr, claim}) is the verifiable link from a classical validator address to the id, and is ++ * required in the epoch that performs the switch at H_id. `transport` names the RLPx node key a ++ * validator's client uses, for the peer-forwarding predicate (AIP-22 section 3.4). ++ * ++ * THE CANONICAL FORMS, pinned here and in the conformance vectors (AIP-22 section 3.2 names them; ++ * this class is where their bytes are fixed, and the Nethermind port and the public JS tool must ++ * produce the same bytes from the same vector files): ++ * ++ * row pre-image = "AERE-PQ-ROW-3" || u8(3) || u64be(chainId) || u64be(bindHeight) || u32be(count) ++ * || u32be(index) || id(20) || u8(nKeys) ++ * || for each key in ascending wire id: u8(wireId) || u32be(len pk) || pk ++ * || u32be(len pop) || pop ++ * || u8(hasTransport) [|| transport(20)] ++ * row hash = keccak256(row pre-image) (rotation and ecdsa are NOT in it) ++ * Merkle root = binary tree over the row hashes in index order; node = keccak256(0x01 || l || r); ++ * an odd node at any level is paired with itself; one row: the root is its hash ++ * registry hash = keccak256("AERE-PQ-REGISTRY-3" || u64be(chainId) || u64be(bindHeight) ++ * || u32be(count) || root) ++ * pop message = keccak256("AERE-PQ-POP-3" || u8(3) || u64be(chainId) || u64be(bindHeight) ++ * || u32be(count) || u32be(index) || id(20) || u8(wireId) || u32be(len pk) || pk) ++ * rotate message = keccak256("AERE-PQ-ROTATE-3" || new row hash) ++ * claim digest = keccak256(0x19 || 0x00 || context || new row hash), context = the low 20 bytes ++ * of keccak256("AERE-PQ-CLAIM-1" || u64be(chainId)), the EIP-191 envelope of v2 ++ * ++ * The public key in the pre-images is the STANDARD encoding: Falcon-512 897 bytes (header 0x09 + ++ * the 896-byte h polynomial the v1/v2 registries store), SLH-DSA-SHA2-128s 32 bytes. Every field ++ * of the pop message earns its place for the reason given in PqRegistryBinding (domain tag against ++ * seal replay, key in the message against Falcon's missing exclusive ownership, chainId, index, ++ * bindHeight and count against lifting and truncation); the wire id keeps one scheme's proof from ++ * standing in for another's. The Merkle node tag 0x01 keeps an inner node from ever being read as ++ * a row hash, and the count bound into the registry hash keeps a duplicated odd leaf from making a ++ * tree of count+1 rows hash like one of count. ++ * ++ * LOADING IS STRICT, as for v1/v2: an ambiguous or incomplete file REFUSES with a named code, never ++ * hashes. Refusal codes AERE-PQC-REG3-01..16, listed at {@link Code}. ++ * ++ * WHAT IT DOES NOT DO (stated): it does not wire the ids into QBFT (the set translation at H_id, ++ * message authorship, coinbase, votes and peer forwarding are later parts of stage 3), and it ++ * does not pin the registry hash on chain (the anchor-contract slot or genesis pqRegistryHash ++ * does that, as today; {@link #loadPinned} compares against the pinned value). ++ */ ++package org.hyperledger.besu.consensus.common.bft; ++ ++import org.hyperledger.besu.crypto.SECPSignature; ++import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.datatypes.Hash; ++import org.hyperledger.besu.ethereum.core.Util; ++ ++import java.io.ByteArrayOutputStream; ++import java.nio.charset.StandardCharsets; ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.Collections; ++import java.util.HashSet; ++import java.util.Iterator; ++import java.util.LinkedHashMap; ++import java.util.List; ++import java.util.Locale; ++import java.util.Map; ++import java.util.Optional; ++import java.util.Set; ++import java.util.TreeMap; ++ ++import com.fasterxml.jackson.databind.JsonNode; ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.bytes.Bytes32; ++import org.bouncycastle.crypto.digests.KeccakDigest; ++ ++/** The v3 validator registry: canonical forms, strict loader, Merkle membership. */ ++public final class PqRegistryV3 { ++ ++ /** Format version of this registry. */ ++ public static final int FORMAT_VERSION = 3; ++ ++ /** Domain tag of the row pre-image. */ ++ public static final String DOMAIN_ROW = "AERE-PQ-ROW-3"; ++ ++ /** Domain tag of the registry hash. */ ++ public static final String DOMAIN_REGISTRY = "AERE-PQ-REGISTRY-3"; ++ ++ /** Domain tag of the proof-of-possession message. */ ++ public static final String DOMAIN_POP = "AERE-PQ-POP-3"; ++ ++ /** Domain tag of the rotation message. */ ++ public static final String DOMAIN_ROTATE = "AERE-PQ-ROTATE-3"; ++ ++ /** Tag byte of an inner Merkle node. */ ++ public static final byte MERKLE_NODE_TAG = 0x01; ++ ++ /** First byte of the id pre-image: the AIP-20 transaction type. */ ++ public static final byte ID_TX_TYPE = 0x50; ++ ++ /** Second byte of the id pre-image: the algorithm id AIP-20 reserves for Falcon-512. */ ++ public static final byte ID_ALG_FALCON_512 = 0x20; ++ ++ /** Header byte of the standard Falcon-512 public key encoding. */ ++ public static final byte FALCON_512_PK_HEADER = 0x09; ++ ++ /** Standard Falcon-512 public key length (header + 896-byte h). */ ++ public static final int FALCON_512_PK_LENGTH = 897; ++ ++ private static final int ECDSA_SIGNATURE_LENGTH = 65; ++ ++ /** The named refusals of the strict loader. */ ++ public enum Code { ++ /** formatVersion missing or not 3. */ ++ REG3_01_FORMAT("AERE-PQC-REG3-01"), ++ /** chainId missing or not the node's chain. */ ++ REG3_02_CHAIN("AERE-PQC-REG3-02"), ++ /** count missing, rows not exactly "0".."count-1", or an unknown top-level or row field. */ ++ REG3_03_SHAPE("AERE-PQC-REG3-03"), ++ /** id missing, not hex, or not 20 bytes. */ ++ REG3_04_ID("AERE-PQC-REG3-04"), ++ /** a key names a scheme this build does not know. */ ++ REG3_05_UNKNOWN_SCHEME("AERE-PQC-REG3-05"), ++ /** a scheme the schedule requires has no key on a row. */ ++ REG3_06_REQUIRED_SCHEME("AERE-PQC-REG3-06"), ++ /** a public key is not in its scheme's standard encoding. */ ++ REG3_07_KEY_ENCODING("AERE-PQC-REG3-07"), ++ /** a proof of possession is missing or does not verify. */ ++ REG3_08_POP("AERE-PQC-REG3-08"), ++ /** a NEW id is not the derivation of the row's Falcon-512 key. */ ++ REG3_09_ID_DERIVATION("AERE-PQC-REG3-09"), ++ /** two rows carry the same id. */ ++ REG3_10_DUPLICATE_ID("AERE-PQC-REG3-10"), ++ /** two rows carry the same public key. */ ++ REG3_11_DUPLICATE_KEY("AERE-PQC-REG3-11"), ++ /** a changed row lacks a verifying rotation signature by every previous key of its id. */ ++ REG3_12_ROTATION_MISSING("AERE-PQC-REG3-12"), ++ /** a rotation is present where none belongs (unchanged row, or a new id). */ ++ REG3_13_ROTATION_UNEXPECTED("AERE-PQC-REG3-13"), ++ /** the ecdsa link is required and missing, does not recover to its address, or repeats one. */ ++ REG3_14_ECDSA("AERE-PQC-REG3-14"), ++ /** transport is malformed. */ ++ REG3_15_TRANSPORT("AERE-PQC-REG3-15"), ++ /** the computed registry hash is not the pinned (or the file's own declared) hash. */ ++ REG3_16_HASH("AERE-PQC-REG3-16"); ++ ++ private final String text; ++ ++ Code(final String text) { ++ this.text = text; ++ } ++ ++ /** ++ * The refusal code as printed. ++ * ++ * @return e.g. AERE-PQC-REG3-08 ++ */ ++ public String text() { ++ return text; ++ } ++ } ++ ++ /** A refusal of the strict loader, carrying its named code. */ ++ public static final class RegistryV3Exception extends RuntimeException { ++ private static final long serialVersionUID = 1L; ++ ++ /** The named refusal. */ ++ private final transient Code code; ++ ++ /** ++ * A refusal. ++ * ++ * @param code the named code ++ * @param message what was wrong, in words ++ */ ++ public RegistryV3Exception(final Code code, final String message) { ++ super(code.text() + ": " + message); ++ this.code = code; ++ } ++ ++ /** ++ * The named code. ++ * ++ * @return the code ++ */ ++ public Code code() { ++ return code; ++ } ++ } ++ ++ /** ++ * One key of a row. ++ * ++ * @param scheme the seal scheme ++ * @param publicKey the standard encoding (Falcon-512 897 bytes, SLH-DSA-SHA2-128s 32 bytes) ++ * @param pop the proof of possession by that key ++ */ ++ public record Key(SealScheme scheme, byte[] publicKey, byte[] pop) {} ++ ++ /** ++ * One row. ++ * ++ * @param index the row index ++ * @param id the 20-byte validator id ++ * @param keys the keys by wire id, ascending ++ * @param transport the RLPx node-key address, or null ++ * @param rotation scheme id to rotation signature (by the previous epoch's key of that scheme) ++ * @param ecdsaAddress the classical validator address, or null ++ * @param ecdsaClaim the EIP-191 claim by that address over the row hash, or null ++ */ ++ public record Row( ++ int index, ++ byte[] id, ++ TreeMap keys, ++ byte[] transport, ++ Map rotation, ++ byte[] ecdsaAddress, ++ byte[] ecdsaClaim) { ++ ++ /** ++ * The key of a scheme on this row. ++ * ++ * @param schemeId e.g. "falcon-512" ++ * @return the key, if the row carries one ++ */ ++ public Optional key(final String schemeId) { ++ for (final Key k : keys.values()) { ++ if (k.scheme().id().equals(schemeId)) { ++ return Optional.of(k); ++ } ++ } ++ return Optional.empty(); ++ } ++ } ++ ++ /** ++ * A loaded, verified epoch. ++ * ++ * @param chainId the chain ++ * @param bindHeight the activation height of this epoch ++ * @param count the number of rows ++ * @param rows the rows in index order ++ * @param rowHashes the row hashes in index order ++ * @param root the Merkle root over the row hashes ++ * @param hash the registry hash (what the chain pins) ++ */ ++ public record Registry( ++ long chainId, ++ long bindHeight, ++ int count, ++ List rows, ++ List rowHashes, ++ Bytes32 root, ++ Bytes32 hash) { ++ ++ /** ++ * The row of an id. ++ * ++ * @param id the 20-byte id ++ * @return the row, if the id is registered in this epoch ++ */ ++ public Optional rowOf(final byte[] id) { ++ for (final Row r : rows) { ++ if (Arrays.equals(r.id(), id)) { ++ return Optional.of(r); ++ } ++ } ++ return Optional.empty(); ++ } ++ ++ /** ++ * The row whose ecdsa link names this classical address. ++ * ++ * @param address the 20-byte address ++ * @return the row, if one links it ++ */ ++ public Optional rowOfEcdsa(final byte[] address) { ++ for (final Row r : rows) { ++ if (r.ecdsaAddress() != null && Arrays.equals(r.ecdsaAddress(), address)) { ++ return Optional.of(r); ++ } ++ } ++ return Optional.empty(); ++ } ++ } ++ ++ private PqRegistryV3() {} ++ ++ // ============================================================================================= ++ // Canonical forms ++ // ============================================================================================= ++ ++ /** ++ * The validator id of a Falcon-512 key (AIP-22 section 3.1). ++ * ++ * @param falconStandard897 the 897-byte standard encoding ++ * @return the 20-byte id ++ */ ++ public static byte[] idOf(final byte[] falconStandard897) { ++ final byte[] in = new byte[2 + falconStandard897.length]; ++ in[0] = ID_TX_TYPE; ++ in[1] = ID_ALG_FALCON_512; ++ System.arraycopy(falconStandard897, 0, in, 2, falconStandard897.length); ++ return Arrays.copyOfRange(keccak(in), 12, 32); ++ } ++ ++ /** ++ * The message a row key signs to prove possession. ++ * ++ * @param chainId the chain ++ * @param bindHeight the epoch's activation height ++ * @param count the number of rows ++ * @param index the row index ++ * @param id the row id ++ * @param wireId the scheme wire id ++ * @param publicKey the standard encoding of the key ++ * @return the 32-byte message ++ */ ++ public static Bytes32 popMessage( ++ final long chainId, ++ final long bindHeight, ++ final int count, ++ final int index, ++ final byte[] id, ++ final byte wireId, ++ final byte[] publicKey) { ++ final ByteArrayOutputStream out = new ByteArrayOutputStream(); ++ writeAll(out, DOMAIN_POP.getBytes(StandardCharsets.US_ASCII)); ++ out.write(FORMAT_VERSION); ++ writeAll(out, uint64be(chainId)); ++ writeAll(out, uint64be(bindHeight)); ++ writeAll(out, uint32be(count)); ++ writeAll(out, uint32be(index)); ++ writeAll(out, id); ++ out.write(wireId); ++ writeAll(out, uint32be(publicKey.length)); ++ writeAll(out, publicKey); ++ return Bytes32.wrap(keccak(out.toByteArray())); ++ } ++ ++ /** ++ * The canonical pre-image of a row (without rotation and ecdsa). ++ * ++ * @param chainId the chain ++ * @param bindHeight the epoch's activation height ++ * @param count the number of rows ++ * @param row the row ++ * @return the pre-image ++ */ ++ public static byte[] rowPreimage( ++ final long chainId, final long bindHeight, final int count, final Row row) { ++ final ByteArrayOutputStream out = new ByteArrayOutputStream(); ++ writeAll(out, DOMAIN_ROW.getBytes(StandardCharsets.US_ASCII)); ++ out.write(FORMAT_VERSION); ++ writeAll(out, uint64be(chainId)); ++ writeAll(out, uint64be(bindHeight)); ++ writeAll(out, uint32be(count)); ++ writeAll(out, uint32be(row.index())); ++ writeAll(out, row.id()); ++ out.write(row.keys().size()); ++ for (final Map.Entry e : row.keys().entrySet()) { ++ out.write(e.getKey()); ++ writeAll(out, uint32be(e.getValue().publicKey().length)); ++ writeAll(out, e.getValue().publicKey()); ++ writeAll(out, uint32be(e.getValue().pop().length)); ++ writeAll(out, e.getValue().pop()); ++ } ++ if (row.transport() == null) { ++ out.write(0); ++ } else { ++ out.write(1); ++ writeAll(out, row.transport()); ++ } ++ return out.toByteArray(); ++ } ++ ++ /** ++ * The row hash. ++ * ++ * @param chainId the chain ++ * @param bindHeight the epoch's activation height ++ * @param count the number of rows ++ * @param row the row ++ * @return keccak256 of the row pre-image ++ */ ++ public static Bytes32 rowHash( ++ final long chainId, final long bindHeight, final int count, final Row row) { ++ return Bytes32.wrap(keccak(rowPreimage(chainId, bindHeight, count, row))); ++ } ++ ++ /** ++ * The Merkle root over row hashes in index order. ++ * ++ * @param leaves the row hashes ++ * @return the root ++ */ ++ public static Bytes32 merkleRoot(final List leaves) { ++ if (leaves.isEmpty()) { ++ throw new IllegalArgumentException("a registry has at least one row"); ++ } ++ List level = leaves; ++ while (level.size() > 1) { ++ final List next = new ArrayList<>(); ++ for (int i = 0; i < level.size(); i += 2) { ++ final Bytes32 l = level.get(i); ++ final Bytes32 r = i + 1 < level.size() ? level.get(i + 1) : l; ++ next.add(node(l, r)); ++ } ++ level = next; ++ } ++ return level.get(0); ++ } ++ ++ /** ++ * The sibling path of one leaf, bottom-up. ++ * ++ * @param leaves the row hashes ++ * @param index the leaf index ++ * @return the siblings from the leaf level up ++ */ ++ public static List merkleProof(final List leaves, final int index) { ++ if (index < 0 || index >= leaves.size()) { ++ throw new IllegalArgumentException("index " + index + " is not a row of " + leaves.size()); ++ } ++ final List proof = new ArrayList<>(); ++ List level = leaves; ++ int i = index; ++ while (level.size() > 1) { ++ final int sib = (i % 2 == 0) ? i + 1 : i - 1; ++ proof.add(sib < level.size() ? level.get(sib) : level.get(i)); ++ final List next = new ArrayList<>(); ++ for (int j = 0; j < level.size(); j += 2) { ++ final Bytes32 l = level.get(j); ++ final Bytes32 r = j + 1 < level.size() ? level.get(j + 1) : l; ++ next.add(node(l, r)); ++ } ++ level = next; ++ i /= 2; ++ } ++ return proof; ++ } ++ ++ /** ++ * Checks a membership proof. The index MUST be below count: with the odd leaf paired with ++ * itself, a path for index == count would otherwise verify against a count-row tree. ++ * ++ * @param leaf the row hash ++ * @param index the claimed index ++ * @param count the number of rows ++ * @param proof the siblings, bottom-up ++ * @param root the root ++ * @return whether the leaf is row {@code index} of the tree with that root ++ */ ++ public static boolean verifyMerkleProof( ++ final Bytes32 leaf, ++ final int index, ++ final int count, ++ final List proof, ++ final Bytes32 root) { ++ if (index < 0 || index >= count || count < 1) { ++ return false; ++ } ++ int depth = 0; ++ for (int n = count; n > 1; n = (n + 1) / 2) { ++ depth++; ++ } ++ if (proof.size() != depth) { ++ return false; ++ } ++ Bytes32 acc = leaf; ++ int i = index; ++ for (final Bytes32 sib : proof) { ++ acc = (i % 2 == 0) ? node(acc, sib) : node(sib, acc); ++ i /= 2; ++ } ++ return acc.equals(root); ++ } ++ ++ /** ++ * The registry hash the chain pins. ++ * ++ * @param chainId the chain ++ * @param bindHeight the epoch's activation height ++ * @param count the number of rows ++ * @param root the Merkle root ++ * @return the hash ++ */ ++ public static Bytes32 registryHash( ++ final long chainId, final long bindHeight, final int count, final Bytes32 root) { ++ final ByteArrayOutputStream out = new ByteArrayOutputStream(); ++ writeAll(out, DOMAIN_REGISTRY.getBytes(StandardCharsets.US_ASCII)); ++ writeAll(out, uint64be(chainId)); ++ writeAll(out, uint64be(bindHeight)); ++ writeAll(out, uint32be(count)); ++ writeAll(out, root.toArrayUnsafe()); ++ return Bytes32.wrap(keccak(out.toByteArray())); ++ } ++ ++ /** ++ * The message every previous key of an id signs to authorise a changed row. ++ * ++ * @param newRowHash the hash of the new row ++ * @return the 32-byte message ++ */ ++ public static Bytes32 rotateMessage(final Bytes32 newRowHash) { ++ final ByteArrayOutputStream out = new ByteArrayOutputStream(); ++ writeAll(out, DOMAIN_ROTATE.getBytes(StandardCharsets.US_ASCII)); ++ writeAll(out, newRowHash.toArrayUnsafe()); ++ return Bytes32.wrap(keccak(out.toByteArray())); ++ } ++ ++ /** ++ * The digest the classical validator key signs to link its address to the row. ++ * ++ * @param chainId the chain ++ * @param rowHash the row hash ++ * @return the EIP-191 version-0 digest ++ */ ++ public static Bytes32 claimDigest(final long chainId, final Bytes32 rowHash) { ++ final ByteArrayOutputStream out = new ByteArrayOutputStream(); ++ out.write(0x19); ++ out.write(0x00); ++ writeAll(out, PqRegistryBinding.claimContext(chainId)); ++ writeAll(out, rowHash.toArrayUnsafe()); ++ return Bytes32.wrap(keccak(out.toByteArray())); ++ } ++ ++ // ============================================================================================= ++ // The strict loader ++ // ============================================================================================= ++ ++ /** ++ * Loads and verifies an epoch and compares its hash with the pinned one. ++ * ++ * @param json the manifest ++ * @param chainId the node's chain ++ * @param requiredSchemes the scheme ids every row must carry ++ * @param previous the previous v3 epoch (for rotations), or null for the first ++ * @param ecdsaRequired whether every row must carry the ecdsa link (the switch epoch) ++ * @param pinnedHash the hash the chain pins ++ * @return the verified epoch ++ */ ++ public static Registry loadPinned( ++ final JsonNode json, ++ final long chainId, ++ final List requiredSchemes, ++ final Registry previous, ++ final boolean ecdsaRequired, ++ final Bytes32 pinnedHash) { ++ final Registry r = load(json, chainId, requiredSchemes, previous, ecdsaRequired); ++ if (!r.hash().equals(pinnedHash)) { ++ throw new RegistryV3Exception( ++ Code.REG3_16_HASH, ++ "the registry hashes to " + r.hash() + ", the chain pins " + pinnedHash + "; refusing"); ++ } ++ return r; ++ } ++ ++ /** ++ * Loads and verifies an epoch (every proof, every uniqueness rule, every rotation). ++ * ++ * @param json the manifest ++ * @param chainId the node's chain ++ * @param requiredSchemes the scheme ids every row must carry ++ * @param previous the previous v3 epoch (for rotations), or null for the first ++ * @param ecdsaRequired whether every row must carry the ecdsa link ++ * @return the verified epoch ++ */ ++ public static Registry load( ++ final JsonNode json, ++ final long chainId, ++ final List requiredSchemes, ++ final Registry previous, ++ final boolean ecdsaRequired) { ++ if (json == null || !json.isObject()) { ++ throw new RegistryV3Exception(Code.REG3_03_SHAPE, "the manifest is not a JSON object"); ++ } ++ if (!json.has("formatVersion") || json.get("formatVersion").asInt(-1) != FORMAT_VERSION ++ || !json.get("formatVersion").isIntegralNumber()) { ++ throw new RegistryV3Exception(Code.REG3_01_FORMAT, "formatVersion must be the number 3"); ++ } ++ if (!json.has("chainId") || !json.get("chainId").isIntegralNumber() ++ || json.get("chainId").asLong() != chainId) { ++ throw new RegistryV3Exception( ++ Code.REG3_02_CHAIN, "chainId must be the number " + chainId + " (this node's chain)"); ++ } ++ if (!json.has("bindHeight") || !json.get("bindHeight").isIntegralNumber() ++ || json.get("bindHeight").asLong() < 0) { ++ throw new RegistryV3Exception(Code.REG3_03_SHAPE, "bindHeight must be a number >= 0"); ++ } ++ if (!json.has("count") || !json.get("count").isIntegralNumber() ++ || json.get("count").asInt() < 1) { ++ throw new RegistryV3Exception(Code.REG3_03_SHAPE, "count must be a number >= 1"); ++ } ++ final long bindHeight = json.get("bindHeight").asLong(); ++ final int count = json.get("count").asInt(); ++ final Set allowedTop = new HashSet<>(); ++ Collections.addAll(allowedTop, "formatVersion", "chainId", "bindHeight", "count", "registryHash"); ++ for (int i = 0; i < count; i++) { ++ allowedTop.add(Integer.toString(i)); ++ } ++ final Iterator names = json.fieldNames(); ++ while (names.hasNext()) { ++ final String n = names.next(); ++ if (!allowedTop.contains(n)) { ++ throw new RegistryV3Exception( ++ Code.REG3_03_SHAPE, ++ "unexpected top-level field '" + n + "' (rows are exactly \"0\"..\"" + (count - 1) ++ + "\")"); ++ } ++ } ++ final List rows = new ArrayList<>(); ++ for (int i = 0; i < count; i++) { ++ final JsonNode e = json.get(Integer.toString(i)); ++ if (e == null || !e.isObject()) { ++ throw new RegistryV3Exception(Code.REG3_03_SHAPE, "row " + i + " is missing"); ++ } ++ rows.add(parseRow(i, e)); ++ } ++ // required schemes, key encodings, possession proofs ++ for (final Row row : rows) { ++ for (final String s : requiredSchemes) { ++ if (row.key(s).isEmpty()) { ++ throw new RegistryV3Exception( ++ Code.REG3_06_REQUIRED_SCHEME, "row " + row.index() + " has no " + s + " key"); ++ } ++ } ++ if (row.key(SealSchemes.FALCON_512.id()).isEmpty()) { ++ throw new RegistryV3Exception( ++ Code.REG3_06_REQUIRED_SCHEME, ++ "row " + row.index() + " has no falcon-512 key; the id is derived from it"); ++ } ++ for (final Key k : row.keys().values()) { ++ final byte[] registryForm = registryForm(row.index(), k); ++ final Bytes32 msg = ++ popMessage( ++ chainId, bindHeight, count, row.index(), row.id(), k.scheme().wireId(), ++ k.publicKey()); ++ if (k.pop() == null || k.pop().length == 0 ++ || !k.scheme().verifyRaw(registryForm, msg.toArrayUnsafe(), k.pop())) { ++ throw new RegistryV3Exception( ++ Code.REG3_08_POP, ++ "row " + row.index() + " " + k.scheme().id() ++ + ": the proof of possession does not verify for chainId=" + chainId ++ + " bindHeight=" + bindHeight + " count=" + count + " index=" + row.index()); ++ } ++ } ++ } ++ // uniqueness of ids and of every public key ++ final Set ids = new HashSet<>(); ++ final Set keys = new HashSet<>(); ++ for (final Row row : rows) { ++ if (!ids.add(Bytes.wrap(row.id()))) { ++ throw new RegistryV3Exception( ++ Code.REG3_10_DUPLICATE_ID, "id 0x" + hex(row.id()) + " appears on two rows"); ++ } ++ for (final Key k : row.keys().values()) { ++ if (!keys.add(Bytes.wrap(k.publicKey()))) { ++ throw new RegistryV3Exception( ++ Code.REG3_11_DUPLICATE_KEY, ++ "row " + row.index() + " " + k.scheme().id() + ": the key appears on another row"); ++ } ++ } ++ } ++ // row hashes, then ids and rotations against the previous epoch ++ final List hashes = new ArrayList<>(); ++ for (final Row row : rows) { ++ hashes.add(rowHash(chainId, bindHeight, count, row)); ++ } ++ for (final Row row : rows) { ++ final Optional prev = previous == null ? Optional.empty() : previous.rowOf(row.id()); ++ if (prev.isEmpty()) { ++ final byte[] derived = idOf(row.key(SealSchemes.FALCON_512.id()).orElseThrow().publicKey()); ++ if (!Arrays.equals(derived, row.id())) { ++ throw new RegistryV3Exception( ++ Code.REG3_09_ID_DERIVATION, ++ "row " + row.index() + ": a new id must be keccak256(0x50||0x20||falcon)[12:32] = 0x" ++ + hex(derived) + ", the row says 0x" + hex(row.id())); ++ } ++ if (!row.rotation().isEmpty()) { ++ throw new RegistryV3Exception( ++ Code.REG3_13_ROTATION_UNEXPECTED, ++ "row " + row.index() + " is a new id and carries a rotation"); ++ } ++ continue; ++ } ++ final boolean changed = !sameKeys(prev.get(), row); ++ if (!changed) { ++ if (!row.rotation().isEmpty()) { ++ throw new RegistryV3Exception( ++ Code.REG3_13_ROTATION_UNEXPECTED, ++ "row " + row.index() + " did not change its keys and carries a rotation"); ++ } ++ continue; ++ } ++ final Bytes32 rot = rotateMessage(hashes.get(row.index())); ++ for (final Key old : prev.get().keys().values()) { ++ final byte[] sig = row.rotation().get(old.scheme().id()); ++ if (sig == null ++ || !old.scheme() ++ .verifyRaw(registryForm(prev.get().index(), old), rot.toArrayUnsafe(), sig)) { ++ throw new RegistryV3Exception( ++ Code.REG3_12_ROTATION_MISSING, ++ "row " + row.index() + " changed its keys; the previous " + old.scheme().id() ++ + " key of id 0x" + hex(row.id()) + " did not sign the new row (every previous" ++ + " key must)"); ++ } ++ } ++ if (row.rotation().size() != prev.get().keys().size()) { ++ throw new RegistryV3Exception( ++ Code.REG3_13_ROTATION_UNEXPECTED, ++ "row " + row.index() + " carries a rotation signature for a scheme the previous row" ++ + " did not bind"); ++ } ++ } ++ // the ecdsa link ++ final Set ecdsa = new HashSet<>(); ++ for (final Row row : rows) { ++ if (row.ecdsaAddress() == null) { ++ if (ecdsaRequired) { ++ throw new RegistryV3Exception( ++ Code.REG3_14_ECDSA, ++ "row " + row.index() + " has no ecdsa link; this epoch performs the switch and" ++ + " every row must carry one"); ++ } ++ continue; ++ } ++ final Address rec = recover(claimDigest(chainId, hashes.get(row.index())), row.ecdsaClaim()); ++ if (rec == null || !Arrays.equals(rec.getBytes().toArrayUnsafe(), row.ecdsaAddress())) { ++ throw new RegistryV3Exception( ++ Code.REG3_14_ECDSA, ++ "row " + row.index() + ": the ecdsa claim does not recover to 0x" ++ + hex(row.ecdsaAddress())); ++ } ++ if (!ecdsa.add(Bytes.wrap(row.ecdsaAddress()))) { ++ throw new RegistryV3Exception( ++ Code.REG3_14_ECDSA, "row " + row.index() + ": the ecdsa address appears on two rows"); ++ } ++ } ++ final Bytes32 root = merkleRoot(hashes); ++ final Bytes32 hash = registryHash(chainId, bindHeight, count, root); ++ if (json.has("registryHash")) { ++ final Bytes32 declared = parseBytes32(json.get("registryHash"), "registryHash"); ++ if (!declared.equals(hash)) { ++ throw new RegistryV3Exception( ++ Code.REG3_16_HASH, ++ "the file declares registryHash " + declared + " and hashes to " + hash); ++ } ++ } ++ return new Registry( ++ chainId, ++ bindHeight, ++ count, ++ Collections.unmodifiableList(rows), ++ Collections.unmodifiableList(hashes), ++ root, ++ hash); ++ } ++ ++ // ============================================================================================= ++ // Parsing ++ // ============================================================================================= ++ ++ private static Row parseRow(final int index, final JsonNode e) { ++ final Set allowed = Set.of("id", "keys", "pop", "rotation", "ecdsa", "transport"); ++ final Iterator fields = e.fieldNames(); ++ while (fields.hasNext()) { ++ final String f = fields.next(); ++ if (!allowed.contains(f)) { ++ throw new RegistryV3Exception( ++ Code.REG3_03_SHAPE, "row " + index + " has an unknown field '" + f + "'"); ++ } ++ } ++ final byte[] id = parseHex(e.get("id"), 20, Code.REG3_04_ID, "row " + index + " id"); ++ final JsonNode keysNode = e.get("keys"); ++ final JsonNode popNode = e.get("pop"); ++ if (keysNode == null || !keysNode.isObject() || keysNode.size() == 0) { ++ throw new RegistryV3Exception(Code.REG3_03_SHAPE, "row " + index + " has no keys"); ++ } ++ if (popNode == null || !popNode.isObject()) { ++ throw new RegistryV3Exception(Code.REG3_08_POP, "row " + index + " has no pop object"); ++ } ++ final TreeMap keys = new TreeMap<>(); ++ final Iterator> it = keysNode.fields(); ++ while (it.hasNext()) { ++ final Map.Entry k = it.next(); ++ final SealScheme scheme = ++ SealSchemes.byId(k.getKey()) ++ .orElseThrow( ++ () -> ++ new RegistryV3Exception( ++ Code.REG3_05_UNKNOWN_SCHEME, ++ "row " + index + " names the unknown scheme '" + k.getKey() + "'")); ++ final int len = ++ scheme == SealSchemes.FALCON_512 ? FALCON_512_PK_LENGTH : scheme.publicKeyLength(); ++ final byte[] pk = ++ parseHex(k.getValue(), len, Code.REG3_07_KEY_ENCODING, "row " + index + " " + k.getKey()); ++ if (scheme == SealSchemes.FALCON_512 && pk[0] != FALCON_512_PK_HEADER) { ++ throw new RegistryV3Exception( ++ Code.REG3_07_KEY_ENCODING, ++ "row " + index + " falcon-512: the standard encoding starts with 0x09"); ++ } ++ final JsonNode p = popNode.get(k.getKey()); ++ if (p == null) { ++ throw new RegistryV3Exception( ++ Code.REG3_08_POP, "row " + index + " " + k.getKey() + " has no proof of possession"); ++ } ++ final byte[] pop = parseHex(p, -1, Code.REG3_08_POP, "row " + index + " pop " + k.getKey()); ++ keys.put(scheme.wireId() & 0xff, new Key(scheme, pk, pop)); ++ } ++ if (popNode.size() != keysNode.size()) { ++ throw new RegistryV3Exception( ++ Code.REG3_08_POP, "row " + index + " carries a proof for a scheme it has no key for"); ++ } ++ byte[] transport = null; ++ final JsonNode t = e.get("transport"); ++ if (t != null) { ++ if (!t.isObject() || t.size() != 1 || !t.has("secp256k1Address")) { ++ throw new RegistryV3Exception( ++ Code.REG3_15_TRANSPORT, "row " + index + " transport must be {secp256k1Address}"); ++ } ++ transport = ++ parseHex(t.get("secp256k1Address"), 20, Code.REG3_15_TRANSPORT, "row " + index + " transport"); ++ } ++ final Map rotation = new LinkedHashMap<>(); ++ final JsonNode rot = e.get("rotation"); ++ if (rot != null) { ++ if (!rot.isObject() || rot.size() == 0) { ++ throw new RegistryV3Exception( ++ Code.REG3_13_ROTATION_UNEXPECTED, "row " + index + " rotation must be a non-empty map"); ++ } ++ final Iterator> ri = rot.fields(); ++ while (ri.hasNext()) { ++ final Map.Entry r = ri.next(); ++ if (SealSchemes.byId(r.getKey()).isEmpty()) { ++ throw new RegistryV3Exception( ++ Code.REG3_05_UNKNOWN_SCHEME, ++ "row " + index + " rotation names the unknown scheme '" + r.getKey() + "'"); ++ } ++ rotation.put( ++ r.getKey(), ++ parseHex(r.getValue(), -1, Code.REG3_12_ROTATION_MISSING, "row " + index + " rotation")); ++ } ++ } ++ byte[] ecdsaAddress = null; ++ byte[] ecdsaClaim = null; ++ final JsonNode ec = e.get("ecdsa"); ++ if (ec != null) { ++ if (!ec.isObject() || ec.size() != 2 || !ec.has("addr") || !ec.has("claim")) { ++ throw new RegistryV3Exception( ++ Code.REG3_14_ECDSA, "row " + index + " ecdsa must be {addr, claim}"); ++ } ++ ecdsaAddress = parseHex(ec.get("addr"), 20, Code.REG3_14_ECDSA, "row " + index + " ecdsa.addr"); ++ ecdsaClaim = ++ parseHex( ++ ec.get("claim"), ECDSA_SIGNATURE_LENGTH, Code.REG3_14_ECDSA, "row " + index + " claim"); ++ } ++ return new Row(index, id, keys, transport, rotation, ecdsaAddress, ecdsaClaim); ++ } ++ ++ /** The form a scheme's parser takes: Falcon without the header byte, others as stored. */ ++ private static byte[] registryForm(final int index, final Key k) { ++ if (k.scheme() == SealSchemes.FALCON_512) { ++ if (k.publicKey().length != FALCON_512_PK_LENGTH) { ++ throw new RegistryV3Exception( ++ Code.REG3_07_KEY_ENCODING, "row " + index + " falcon-512 key is not 897 bytes"); ++ } ++ return Arrays.copyOfRange(k.publicKey(), 1, FALCON_512_PK_LENGTH); ++ } ++ return k.publicKey(); ++ } ++ ++ private static boolean sameKeys(final Row a, final Row b) { ++ if (a.keys().size() != b.keys().size()) { ++ return false; ++ } ++ for (final Map.Entry e : a.keys().entrySet()) { ++ final Key other = b.keys().get(e.getKey()); ++ if (other == null || !Arrays.equals(other.publicKey(), e.getValue().publicKey())) { ++ return false; ++ } ++ } ++ return true; ++ } ++ ++ private static Address recover(final Bytes32 digest, final byte[] signature) { ++ if (signature == null || signature.length != ECDSA_SIGNATURE_LENGTH) { ++ return null; ++ } ++ try { ++ final SECPSignature s = ++ SignatureAlgorithmFactory.getInstance().decodeSignature(Bytes.wrap(signature)); ++ return Util.signatureToAddress(s, Hash.wrap(digest)); ++ } catch (final RuntimeException ex) { ++ return null; ++ } ++ } ++ ++ private static byte[] parseHex( ++ final JsonNode n, final int len, final Code code, final String what) { ++ if (n == null || !n.isTextual()) { ++ throw new RegistryV3Exception(code, what + " must be a 0x-prefixed hex string"); ++ } ++ final String s = n.asText(); ++ if (!s.startsWith("0x") || (s.length() % 2) != 0 || !s.substring(2).matches("[0-9a-f]*")) { ++ throw new RegistryV3Exception(code, what + " is not lowercase 0x-hex of even length"); ++ } ++ final byte[] b = Bytes.fromHexString(s).toArrayUnsafe(); ++ if (len >= 0 && b.length != len) { ++ throw new RegistryV3Exception(code, what + " is " + b.length + " bytes, expected " + len); ++ } ++ return b; ++ } ++ ++ private static Bytes32 parseBytes32(final JsonNode n, final String what) { ++ return Bytes32.wrap(parseHex(n, 32, Code.REG3_16_HASH, what)); ++ } ++ ++ private static Bytes32 node(final Bytes32 l, final Bytes32 r) { ++ final byte[] in = new byte[65]; ++ in[0] = MERKLE_NODE_TAG; ++ System.arraycopy(l.toArrayUnsafe(), 0, in, 1, 32); ++ System.arraycopy(r.toArrayUnsafe(), 0, in, 33, 32); ++ return Bytes32.wrap(keccak(in)); ++ } ++ ++ private static void writeAll(final ByteArrayOutputStream out, final byte[] b) { ++ out.write(b, 0, b.length); ++ } ++ ++ private static byte[] uint32be(final int v) { ++ return new byte[] {(byte) (v >>> 24), (byte) (v >>> 16), (byte) (v >>> 8), (byte) v}; ++ } ++ ++ private static byte[] uint64be(final long v) { ++ final byte[] b = new byte[8]; ++ for (int i = 0; i < 8; i++) { ++ b[i] = (byte) (v >>> (56 - 8 * i)); ++ } ++ return b; ++ } ++ ++ private static byte[] keccak(final byte[] input) { ++ final KeccakDigest d = new KeccakDigest(256); ++ d.update(input, 0, input.length); ++ final byte[] out = new byte[32]; ++ d.doFinal(out, 0); ++ return out; ++ } ++ ++ private static String hex(final byte[] b) { ++ final StringBuilder sb = new StringBuilder(b.length * 2); ++ for (final byte x : b) { ++ sb.append(String.format(Locale.ROOT, "%02x", x & 0xff)); ++ } ++ return sb.toString(); ++ } ++} +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqSchemeSchedule.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqSchemeSchedule.java +index a4d1bd43e3..6a706ed712 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqSchemeSchedule.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqSchemeSchedule.java +@@ -1,135 +1,245 @@ + /* + * AERE crypto-agility, step 5: the height-indexed scheme schedule. + * + * WHAT IT IS. The same shape as aere.pq.anchorMinSeals ("H:K,H:K,..."), but the value at each + * step is a SET of scheme ids: "14000000:falcon-512,15500000:falcon-512+slh-dsa-128s" reads + * "from 14,000,000 anchors carry Falcon; from 15,500,000 they carry Falcon AND SLH-DSA". + * Changing the mathematics of the chain becomes one property plus keys, never a code edit - + * that is the whole point of the abstraction layer. + * ++ * PER-SCHEME INTERVALS (AIP-22 stage 2, 2026-09-23). A scheme in a step may carry its own anchor ++ * interval, "scheme/interval": "H:falcon-512/32+slh-dsa-sha2-128s/128" reads "from H, Falcon-512 ++ * is required at every anchor height on the 32 grid and SLH-DSA-SHA2-128s only at the anchor ++ * heights on the 128 grid", both grids counted from the chain's anchor activation height H0 (the ++ * one every anchor grid of this chain is counted from, so an anchor of the coarse grid is always ++ * an anchor of the fine one). A scheme without "/interval" is required at EVERY anchor height, ++ * which is exactly the behaviour before this change, so an existing schedule keeps its meaning ++ * byte for byte. The intervals are validated as positive multiples of the anchor grid unit; the ++ * cross-check against the interval the node actually runs is done where both are known ++ * (HybridSealSupport at load), never assumed here. ++ * + * THE D-147 LESSON, APPLIED AT THE LOADER. The min-seals schedule once accepted a shape whose + * DANGEROUS step was later in the schedule, because validation looked only at the first step. + * Here every rule runs over the WHOLE schedule at parse time, and the armability gate + * (firstUnsatisfied) walks every step against the registry's per-scheme coverage: arming a + * threshold K under a scheme whose coverage is below K is a chain stop, so it must be refused + * at configuration time, loudly, before any node boots with it. + * + * SEMANTICS OF "BEFORE THE FIRST STEP": schemesAt returns the empty set, which callers read as + * "the v2 scheme world is not armed here" (the legacy untagged Falcon certificate governs). + * Empty is never a default INSIDE the schedule: a step with zero schemes is a parse refusal. + */ + package org.hyperledger.besu.consensus.common.bft; + + import com.google.common.base.Splitter; + + import java.util.ArrayList; ++import java.util.LinkedHashMap; + import java.util.LinkedHashSet; + import java.util.List; ++import java.util.Map; + import java.util.Optional; + import java.util.Set; + + /** Immutable, validated height-to-scheme-set schedule. */ + public final class PqSchemeSchedule { + +- /** One step: from {@code fromBlock} (inclusive) the anchor carries {@code schemeIds}. */ +- public record Step(long fromBlock, Set schemeIds) {} ++ /** ++ * The unit every anchor grid of an Aere chain is a multiple of (the base anchor interval of both ++ * chain 2800 and testnet 28001). A per-scheme interval that is not a multiple of it could never ++ * land on anchor heights, so it is refused at parse time. ++ */ ++ public static final int GRID_UNIT = 32; ++ ++ /** ++ * One step: from {@code fromBlock} (inclusive) the anchor carries {@code schemeIds}; a scheme ++ * present in {@code intervals} is required only at anchor heights on that interval's grid, ++ * a scheme absent from it at every anchor height. ++ */ ++ public record Step(long fromBlock, Set schemeIds, Map intervals) { ++ /** Canonical form: defensive copies, never null. */ ++ public Step( ++ final long fromBlock, final Set schemeIds, final Map intervals) { ++ this.fromBlock = fromBlock; ++ this.schemeIds = Set.copyOf(schemeIds); ++ this.intervals = intervals == null ? Map.of() : Map.copyOf(intervals); ++ } ++ ++ /** A step whose schemes are all required at every anchor height (the pre-AIP-22 form). */ ++ public Step(final long fromBlock, final Set schemeIds) { ++ this(fromBlock, schemeIds, Map.of()); ++ } ++ } + + private final List steps; + + private PqSchemeSchedule(final List steps) { + this.steps = steps; + } + +- /** Parse "H:scheme[+scheme...],H:...". Refuses the WHOLE schedule on any defect: unknown or +- * repeated scheme in a step, empty step, non-increasing heights, negative height, garbage. */ ++ /** Parse "H:scheme[/interval][+scheme[/interval]...],H:...". Refuses the WHOLE schedule on any ++ * defect: unknown or repeated scheme in a step, empty step, non-increasing heights, negative ++ * height, an interval that is not a positive multiple of {@link #GRID_UNIT}, garbage. */ + public static PqSchemeSchedule parse(final String raw) { + if (raw == null || raw.isBlank()) { + throw new IllegalArgumentException("AERE PQ ORAR-SCHEME: empty schedule"); + } + final List steps = new ArrayList<>(); + long lastHeight = -1; + for (final String piesa : Splitter.on(',').split(raw)) { + final List parti = Splitter.on(':').splitToList(piesa.trim()); + if (parti.size() != 2) { + throw new IllegalArgumentException( + "AERE PQ ORAR-SCHEME: step '" + piesa.trim() + "' is not H:schemes"); + } + final long h; + try { + h = Long.parseLong(parti.get(0).trim()); + } catch (final NumberFormatException e) { + throw new IllegalArgumentException( + "AERE PQ ORAR-SCHEME: height '" + parti.get(0).trim() + "' is not a number"); + } + if (h < 0) { + throw new IllegalArgumentException("AERE PQ ORAR-SCHEME: negative height " + h); + } + if (h <= lastHeight) { + throw new IllegalArgumentException( + "AERE PQ ORAR-SCHEME: heights must strictly increase (" + + lastHeight + + " then " + + h + + ") - a schedule read out of order would arm the wrong mathematics"); + } + lastHeight = h; + final Set schemes = new LinkedHashSet<>(); ++ final Map intervals = new LinkedHashMap<>(); + for (final String id : Splitter.on('+').split(parti.get(1))) { +- final String curat = id.trim(); +- if (curat.isEmpty()) { ++ final String piece = id.trim(); ++ if (piece.isEmpty()) { + throw new IllegalArgumentException( + "AERE PQ ORAR-SCHEME: step at " + h + " carries an empty scheme name"); + } ++ final int slash = piece.indexOf('/'); ++ final String curat = slash < 0 ? piece : piece.substring(0, slash).trim(); + if (SealSchemes.byId(curat).isEmpty()) { + throw new IllegalArgumentException( + "AERE PQ ORAR-SCHEME: step at " + h + " names UNKNOWN scheme '" + curat + + "' - refusing the whole schedule"); + } + if (!schemes.add(curat)) { + throw new IllegalArgumentException( + "AERE PQ ORAR-SCHEME: step at " + h + " repeats scheme '" + curat + "'"); + } ++ if (slash >= 0) { ++ final String rawInterval = piece.substring(slash + 1).trim(); ++ final int interval; ++ try { ++ interval = Integer.parseInt(rawInterval); ++ } catch (final NumberFormatException e) { ++ throw new IllegalArgumentException( ++ "AERE PQ ORAR-SCHEME: step at " + h + " gives scheme '" + curat ++ + "' the interval '" + rawInterval + "', which is not a number"); ++ } ++ if (interval <= 0 || interval % GRID_UNIT != 0) { ++ throw new IllegalArgumentException( ++ "AERE PQ ORAR-SCHEME: step at " + h + " gives scheme '" + curat ++ + "' the interval " + interval + ", which is not a positive multiple of the" ++ + " anchor grid unit " + GRID_UNIT + " - such a scheme could never land on an" ++ + " anchor height"); ++ } ++ intervals.put(curat, interval); ++ } + } + if (schemes.isEmpty()) { + throw new IllegalArgumentException( + "AERE PQ ORAR-SCHEME: step at " + h + " has no schemes at all"); + } +- steps.add(new Step(h, Set.copyOf(schemes))); ++ steps.add(new Step(h, schemes, intervals)); + } + return new PqSchemeSchedule(List.copyOf(steps)); + } + +- /** The scheme set in force at {@code height}: the last step at or below it, or the empty set +- * when the schedule has not started yet (= v2 not armed, legacy governs). */ +- public Set schemesAt(final long height) { +- Set inForce = Set.of(); ++ /** The step in force at {@code height}, or null before the first one. */ ++ private Step stepAt(final long height) { ++ Step inForce = null; + for (final Step s : steps) { + if (s.fromBlock() <= height) { +- inForce = s.schemeIds(); ++ inForce = s; + } else { + break; + } + } + return inForce; + } + ++ /** The scheme set in force at {@code height}: the last step at or below it, or the empty set ++ * when the schedule has not started yet (= v2 not armed, legacy governs). This is the set a ++ * node must hold KEYS for and the set the armability gate checks; which of them an anchor ++ * actually demands is {@link #schemesRequiredForAnchor}. */ ++ public Set schemesAt(final long height) { ++ final Step s = stepAt(height); ++ return s == null ? Set.of() : s.schemeIds(); ++ } ++ ++ /** ++ * The schemes an anchor at {@code anchorHeight} must carry, given that its scheme step is read ++ * at the PARENT height (the seals of a certificate are made when the parent is committed, so ++ * every consumer of this schedule already indexes it by the parent), and that a scheme with a ++ * per-scheme interval is required only when {@code (anchorHeight - anchorBlock)} is a multiple ++ * of that interval. Without per-scheme intervals this is exactly {@code schemesAt(anchorHeight ++ * - 1)}. ++ * ++ * @param anchorHeight the anchor height being produced, enforced or validated ++ * @param anchorBlock the chain's anchor activation height, the origin of every anchor grid ++ * @return the required scheme ids, possibly a strict subset of the step's schemes ++ */ ++ public Set schemesRequiredForAnchor(final long anchorHeight, final long anchorBlock) { ++ final Step s = stepAt(anchorHeight - 1); ++ if (s == null) { ++ return Set.of(); ++ } ++ if (s.intervals().isEmpty()) { ++ return s.schemeIds(); ++ } ++ final Set required = new LinkedHashSet<>(); ++ for (final String id : s.schemeIds()) { ++ final Integer interval = s.intervals().get(id); ++ if (interval == null || onGrid(anchorHeight, anchorBlock, interval)) { ++ required.add(id); ++ } ++ } ++ return Set.copyOf(required); ++ } ++ ++ private static boolean onGrid(final long height, final long origin, final int interval) { ++ if (height < origin) { ++ return false; ++ } ++ return (height - origin) % interval == 0; ++ } ++ ++ /** Whether any step carries a per-scheme interval (then the grid cross-check applies). */ ++ public boolean hasIntervals() { ++ return steps.stream().anyMatch(s -> !s.intervals().isEmpty()); ++ } ++ + /** All steps, ascending. */ + public List steps() { + return steps; + } + + /** The armability gate: walk EVERY step and every scheme in it against the registry's + * per-scheme coverage; the first (height, scheme) whose coverage is below {@code minSeals} + * is returned as the refusal, with numbers. Empty means the whole schedule is armable. + * This is the D-147 discipline: the dangerous step may be the LAST one, so all are walked. */ + public Optional firstUnsatisfied(final HybridSignerRegistry registry, final int minSeals) { + for (final Step s : steps) { + for (final String scheme : s.schemeIds()) { + final int acoperire = registry.coverage(scheme); + if (acoperire < minSeals) { + return Optional.of( + "step at height " + s.fromBlock() + " arms scheme '" + scheme + + "' with required seals " + minSeals + " but the registry covers only " + + acoperire + " validator(s) - arming this would stop the chain"); + } + } +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqSealed.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqSealed.java +new file mode 100644 +index 0000000000..34049da6fc +--- /dev/null ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/PqSealed.java +@@ -0,0 +1,61 @@ ++/* ++ * Copyright contributors to Besu / AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.consensus.common.bft; ++ ++import org.hyperledger.besu.datatypes.Address; ++ ++import java.util.Optional; ++ ++import org.apache.tuweni.bytes.Bytes32; ++ ++/** ++ * AERE AIP-22 stage 4: a consensus payload that carries a post-quantum seal {@code (index, signature)}. ++ * The four QBFT payloads (proposal, prepare, commit, round-change) implement it; from H_fin the author ++ * of a message is the id of its seal's index, and only once the seal is VERIFIED ++ * ({@link AerePqFinality#authorFromSeal}): the author decides whether a message is even relayed, which ++ * happens before the layers judge it. ++ */ ++public interface PqSealed { ++ ++ /** ++ * The post-quantum seal this payload carries, if any. ++ * ++ * @return the seal ++ */ ++ Optional getFalconSeal(); ++ ++ /** ++ * The message this payload's seal signs over a chain, as the seal layer that judges it builds it ++ * (PREPARE, PROPOSAL and ROUND-CHANGE carry every field of it). Empty when the payload alone does not ++ * determine it (a COMMIT's seal signs the block's on-chain hash). ++ * ++ * @param chainId the chain id that goes into the message ++ * @return the message, or empty ++ */ ++ default Optional pqSealMessage(final long chainId) { ++ return Optional.empty(); ++ } ++ ++ /** ++ * For a COMMIT, the address that signed its commit seal; empty for every other payload. From H_fin a ++ * COMMIT's author is its seal index's id only when that is this signer's id (the binding its seal ++ * layer checks), and the seal itself is judged by the commit layer, armed at or below H_fin. ++ * ++ * @return the commit seal's signer, or empty ++ */ ++ default Optional

    commitSealSigner() { ++ return Optional.empty(); ++ } ++} +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreator.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreator.java +index 82d86d5359..e43afaca83 100644 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreator.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreator.java +@@ -1,57 +1,65 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/aere-bft-prevrandao-block-creation.patch. + */ + package org.hyperledger.besu.consensus.common.bft.blockcreation; + + import org.hyperledger.besu.config.BftConfigOptions; + import org.hyperledger.besu.consensus.common.ForksSchedule; + import org.hyperledger.besu.consensus.common.bft.BftBlockHeaderFunctions; + import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; + import org.hyperledger.besu.consensus.common.bft.BftHelpers; + import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule; + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.ethereum.ProtocolContext; + import org.hyperledger.besu.ethereum.blockcreation.AbstractBlockCreator; + import org.hyperledger.besu.ethereum.core.BlockHeader; + import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder; + import org.hyperledger.besu.ethereum.core.MiningConfiguration; + import org.hyperledger.besu.ethereum.core.SealableBlockHeader; + import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; + import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; + import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; + import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; + + import java.util.Collections; + import java.util.Optional; + ++import org.apache.tuweni.bytes.Bytes32; ++ + /** The Bft block creator. */ + // This class is responsible for creating a block without committer seals (basically it was just + // too hard to coordinate with the state machine). + public class BftBlockCreator extends AbstractBlockCreator { + + private final BftExtraDataCodec bftExtraDataCodec; + + /** + * Instantiates a new Bft block creator. + * + * @param miningConfiguration the mining parameters + * @param forksSchedule the forks schedule + * @param localAddress the local address + * @param extraDataCalculator the extra data calculator + * @param transactionPool the pending transactions + * @param protocolContext the protocol context + * @param protocolSchedule the protocol schedule + * @param bftExtraDataCodec the bft extra data codec + * @param ethScheduler the scheduler for asynchronous block creation tasks + */ +@@ -68,67 +76,80 @@ public class BftBlockCreator extends AbstractBlockCreator { + super( + miningConfiguration.setCoinbase(localAddress), + miningBeneficiaryCalculator(protocolSchedule), + extraDataCalculator, + transactionPool, + protocolContext, + protocolSchedule, + ethScheduler); + this.bftExtraDataCodec = bftExtraDataCodec; + } + + @Override + public BlockCreationResult createBlock(final long timestamp, final BlockHeader parentHeader) { + ProtocolSpec protocolSpec = + ((BftProtocolSchedule) protocolSchedule) + .getByBlockNumberOrTimestamp(parentHeader.getNumber() + 1, timestamp); + + if (protocolSpec.getWithdrawalsProcessor().isPresent()) { + return createEmptyWithdrawalsBlock(timestamp, parentHeader); + } else { +- return createBlock(Optional.empty(), Optional.empty(), timestamp, parentHeader); ++ return createBlock( ++ Optional.empty(), ++ Optional.empty(), ++ Optional.empty(), ++ Optional.of(Bytes32.wrap(BftHelpers.EXPECTED_MIX_HASH.getBytes())), ++ Optional.empty(), ++ Optional.empty(), ++ timestamp, ++ true, ++ parentHeader); + } + } + + /** + * Construct a mining beneficiary calculator using the given protocolSchedule + * + * @param protocolSchedule protocol schedule + * @return mining beneficiary calculator + */ + public static MiningBeneficiaryCalculator miningBeneficiaryCalculator( + final ProtocolSchedule protocolSchedule) { + return (blockTimestamp, pendingHeader) -> { + BlockHeader newBlockHeader = + BlockHeaderBuilder.createDefault() + .coinbase(pendingHeader.getCoinbase()) + .buildBlockHeader(); + ProtocolSpec protocolSpec = + ((BftProtocolSchedule) protocolSchedule) + .getByBlockNumberOrTimestamp(pendingHeader.getNumber(), blockTimestamp); + return protocolSpec.getMiningBeneficiaryCalculator().calculateBeneficiary(newBlockHeader); + }; + } + + @Override + public BlockCreationResult createEmptyWithdrawalsBlock( + final long timestamp, final BlockHeader parentHeader) { + return createBlock( + Optional.empty(), + Optional.empty(), + Optional.of(Collections.emptyList()), ++ Optional.of(Bytes32.wrap(BftHelpers.EXPECTED_MIX_HASH.getBytes())), ++ Optional.empty(), ++ Optional.empty(), + timestamp, ++ true, + parentHeader); + } + + @Override + protected BlockHeader createFinalBlockHeader(final SealableBlockHeader sealableBlockHeader) { + final BlockHeaderBuilder builder = + BlockHeaderBuilder.create() + .populateFrom(sealableBlockHeader) + .mixHash(BftHelpers.EXPECTED_MIX_HASH) + .nonce(0L) + .blockHeaderFunctions(BftBlockHeaderFunctions.forCommittedSeal(bftExtraDataCodec)); + + return builder.buildBlockHeader(); + } + } +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreatorFactory.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreatorFactory.java +index 1ecdcbf34e..cefa0a039f 100644 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreatorFactory.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreatorFactory.java +@@ -6,40 +6,41 @@ + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0003-aere-pq-anchor.patch. + */ + package org.hyperledger.besu.consensus.common.bft.blockcreation; + + import static com.google.common.base.Preconditions.checkState; + + import org.hyperledger.besu.config.BftConfigOptions; ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; + import org.hyperledger.besu.consensus.common.ConsensusHelpers; + import org.hyperledger.besu.consensus.common.ForksSchedule; + import org.hyperledger.besu.consensus.common.bft.BftContext; + import org.hyperledger.besu.consensus.common.bft.BftExtraData; + import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; + import org.hyperledger.besu.consensus.common.bft.Vote; + import org.hyperledger.besu.consensus.common.validator.ValidatorProvider; + import org.hyperledger.besu.consensus.common.validator.ValidatorVote; + import org.hyperledger.besu.consensus.common.validator.VoteProvider; + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.datatypes.Wei; + import org.hyperledger.besu.ethereum.ProtocolContext; + import org.hyperledger.besu.ethereum.blockcreation.BlockCreator; + import org.hyperledger.besu.ethereum.core.BlockHeader; + import org.hyperledger.besu.ethereum.core.MiningConfiguration; + import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; + import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; + import org.hyperledger.besu.ethereum.mainnet.AbstractGasLimitSpecification; + import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; + +@@ -102,41 +103,42 @@ public class BftBlockCreatorFactory { + this.transactionPool = transactionPool; + this.protocolContext = protocolContext; + this.protocolSchedule = protocolSchedule; + this.forksSchedule = forksSchedule; + this.localAddress = localAddress; + this.miningConfiguration = miningParams; + this.bftExtraDataCodec = bftExtraDataCodec; + this.ethScheduler = ethScheduler; + } + + /** + * Create block creator. + * + * @param round the round + * @return the block creator + */ + public BlockCreator create(final int round) { + return new BftBlockCreator( + miningConfiguration, + forksSchedule, +- localAddress, ++ AerePqIdentity.local( ++ localAddress, protocolContext.getBlockchain().getChainHeadBlockNumber() + 1L), + ph -> createExtraData(round, ph), + transactionPool, + protocolContext, + protocolSchedule, + bftExtraDataCodec, + ethScheduler); + } + + /** + * Sets min transaction gas price. + * + * @param minTransactionGasPrice the min transaction gas price + */ + public void setMinTransactionGasPrice(final Wei minTransactionGasPrice) { + miningConfiguration.setMinTransactionGasPrice(minTransactionGasPrice); + } + + /** + * Gets min transaction gas price. + * +@@ -169,41 +171,44 @@ public class BftBlockCreatorFactory { + /** + * Build the extra data VALUE for a block on this parent, before it is encoded. + * + *

    AERE ANCHOR V2: split out of {@link #createExtraData(int, BlockHeader)} with NO behaviour + * change, so a subclass can post-process the value (QBFT rewrites vanityData with the anchor + * digest and fills element 6 with the parent's certificate) without decoding and + * re-encoding bytes it just produced. IBFT, which shares this class, keeps the old path exactly: + * it never overrides this and never sees the anchor. + * + * @param round the round + * @param parentHeader the parent header + * @return the extra data value + */ + protected BftExtraData buildExtraData(final int round, final BlockHeader parentHeader) { + final BftContext bftContext = protocolContext.getConsensusContext(BftContext.class); + final ValidatorProvider validatorProvider = bftContext.getValidatorProvider(); + Optional voteProviderAfterBlock = + validatorProvider.getVoteProviderAfterBlock(parentHeader); + checkState(voteProviderAfterBlock.isPresent(), "Bft requires a vote provider"); + final Optional proposal = +- voteProviderAfterBlock.get().getVoteAfterBlock(parentHeader, localAddress); ++ voteProviderAfterBlock ++ .get() ++ .getVoteAfterBlock( ++ parentHeader, AerePqIdentity.local(localAddress, parentHeader.getNumber() + 1L)); + + final List

    validators = + new ArrayList<>(validatorProvider.getValidatorsAfterBlock(parentHeader)); + + final BftExtraData extraData = + new BftExtraData( + ConsensusHelpers.zeroLeftPad( + miningConfiguration.getExtraData(), BftExtraDataCodec.EXTRA_VANITY_LENGTH), + Collections.emptyList(), + toVote(proposal), + round, + validators); + + return extraData; + } + + /** + * Change target gas limit. + * + * @param newTargetGasLimit the new target gas limit +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftMiningCoordinator.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftMiningCoordinator.java +index 25474631c8..da4eeecd8c 100644 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftMiningCoordinator.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftMiningCoordinator.java +@@ -1,33 +1,39 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/aere-bft-coordinator-lifecycle-sync.patch. + */ + package org.hyperledger.besu.consensus.common.bft.blockcreation; + + import org.hyperledger.besu.consensus.common.bft.BftEventQueue; + import org.hyperledger.besu.consensus.common.bft.BftExecutors; + import org.hyperledger.besu.consensus.common.bft.BftProcessor; + import org.hyperledger.besu.consensus.common.bft.events.NewChainHead; + import org.hyperledger.besu.consensus.common.bft.statemachine.BftEventHandler; + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.datatypes.Wei; + import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; + import org.hyperledger.besu.ethereum.chain.BlockAddedEvent; + import org.hyperledger.besu.ethereum.chain.BlockAddedObserver; + import org.hyperledger.besu.ethereum.chain.Blockchain; + import org.hyperledger.besu.ethereum.core.Block; + import org.hyperledger.besu.ethereum.core.BlockHeader; + import org.hyperledger.besu.ethereum.core.Transaction; + import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; + import org.hyperledger.besu.plugin.services.BesuEvents; + +@@ -177,52 +183,56 @@ public class BftMiningCoordinator implements MiningCoordinator, BlockAddedObserv + public void onInitialSyncCompleted() { + LOG.info("Starting BFT mining coordinator following initial sync"); + enable(); + start(); + } + + @Override + public void onInitialSyncRestart() { + // Nothing to do. The mining coordinator won't be started until + // sync has completed. + } + }); + } + + @Override + public void awaitStop() throws InterruptedException { + bftExecutors.awaitStop(); + } + + @Override +- public boolean enable() { ++ public synchronized boolean enable() { ++ // AERE D-434 (81a600236a, issue #10877): synchronized with start()/stop() so the multi-step ++ // state checks below cannot interleave with a concurrent lifecycle transition. + // Return true if we're already running or idle, or successfully switch to idle + if (state.get() == State.RUNNING + || state.get() == State.IDLE + || state.compareAndSet(State.PAUSED, State.IDLE)) { + return true; + } + return false; + } + + @Override +- public boolean disable() { ++ public synchronized boolean disable() { ++ // AERE D-434 (81a600236a, issue #10877): synchronized with start()/stop() so the multi-step ++ // state checks below cannot interleave with a concurrent lifecycle transition. + if (state.get() == State.PAUSED + || state.compareAndSet(State.IDLE, State.PAUSED) + || state.compareAndSet(State.RUNNING, State.PAUSED)) { + return true; + } + return false; + } + + @Override + public boolean isMining() { + return state.get() == State.RUNNING; + } + + @Override + public Wei getMinTransactionGasPrice() { + return blockCreatorFactory.getMinTransactionGasPrice(); + } + + @Override + public Wei getMinPriorityFeePerGas() { +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/PqAnchorProducer.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/PqAnchorProducer.java +index a46b7d8874..e8fc683458 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/PqAnchorProducer.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/PqAnchorProducer.java +@@ -1,38 +1,39 @@ + /* + * Copyright contributors to Besu / AERE Network. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + package org.hyperledger.besu.consensus.common.bft.blockcreation; + + import org.apache.tuweni.bytes.Bytes; + import org.hyperledger.besu.datatypes.Hash; ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; + import org.hyperledger.besu.consensus.common.bft.BftContext; + import org.hyperledger.besu.consensus.common.bft.BftExtraData; + import org.hyperledger.besu.consensus.common.bft.FalconSeal; + import org.hyperledger.besu.consensus.common.bft.FalconSealSupport; + import org.hyperledger.besu.consensus.common.bft.HybridSealSupport; + import org.hyperledger.besu.consensus.common.bft.HybridSignerRegistry; + import org.hyperledger.besu.consensus.common.bft.PqAnchor; + import org.hyperledger.besu.consensus.common.bft.PqAnchorConfig; + import org.hyperledger.besu.consensus.common.bft.PqAnchorNotReadyException; + import org.hyperledger.besu.consensus.common.bft.PqAnchorV2; + import org.hyperledger.besu.consensus.common.bft.PqSealCache; + import org.hyperledger.besu.consensus.common.bft.PqSignerRegistry; + import org.hyperledger.besu.consensus.common.bft.SchemeSeal; + import org.hyperledger.besu.consensus.common.bft.SealScheme; + import org.hyperledger.besu.consensus.common.bft.SealSchemes; + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.ethereum.ProtocolContext; + import org.hyperledger.besu.ethereum.core.BlockHeader; + + import java.util.ArrayList; +@@ -363,75 +364,86 @@ public final class PqAnchorProducer { + * Falcon. vanityData becomes the v2 digest under "AERE-PQ-ANCHOR-2". Refuses, through the same + * not-ready exception the v1 path uses, rather than writing a certificate short of a scheme. + */ + private static BftExtraData applyV2( + final PqAnchorConfig cfg, + final long blockNumber, + final BlockHeader parentHeader, + final BftExtraData base, + final List falconCertificate, + final Bytes32 message, + final int required, + final int sealCap) { + final long parentNumber = parentHeader.getNumber(); + final List v2 = new ArrayList<>(); + final Set falconIndices = new LinkedHashSet<>(); + for (final FalconSeal f : falconCertificate) { + v2.add(new SchemeSeal(SealSchemes.FALCON_512.wireId(), f.getValidatorIndex(), f.getSignature())); + falconIndices.add(f.getValidatorIndex()); + } + final HybridSealSupport hybrid = HybridSealSupport.instance(); ++ // AIP-22 stage 2: only the schemes THIS anchor height demands (per-scheme grids counted from ++ // the activation height); at a Falcon-only anchor no SLH-DSA seal is gathered or written, which ++ // is the whole disk saving of the two-grid design + final Set schemes = +- hybrid.schedule().map(sch -> sch.schemesAt(parentNumber)).orElse(Set.of()); ++ hybrid ++ .schedule() ++ .map(sch -> sch.schemesRequiredForAnchor(blockNumber, cfg.anchorBlock())) ++ .orElse(Set.of()); + final List heard = + PqSealCache.instance().extrasFor(parentNumber, parentHeader.getHash()); + for (final String schemeId : schemes) { + if (SealSchemes.FALCON_512.id().equals(schemeId)) { + continue; + } + final Optional scheme = SealSchemes.byId(schemeId); + if (scheme.isEmpty()) { + throw new PqAnchorNotReadyException( + parentNumber, + 0, + required, + "the scheme schedule names '" + schemeId + "', which this binary does not implement"); + } + final Optional registry = hybrid.registry(); +- if (registry.isEmpty()) { ++ // AERE AIP-22 stage 3b: from H_k the keys come from the v3 epoch in force at the parent ++ final boolean v3Keys = AerePqIdentity.keysFromV3(parentNumber); ++ if (registry.isEmpty() && !v3Keys) { + throw new PqAnchorNotReadyException( + parentNumber, + 0, + required, + "no hybrid registry is loaded on this node, so no " + schemeId + " seal can be verified"); + } + int kept = 0; + int rejected = 0; + for (final SchemeSeal s : heard) { + if (s.getSchemeWireId() != scheme.get().wireId()) { + continue; + } + if (!falconIndices.contains(s.getValidatorIndex())) { + rejected++; + continue; + } +- final Optional pk = registry.get().publicKey(s.getValidatorIndex(), schemeId); ++ final Optional pk = ++ v3Keys ++ ? AerePqIdentity.v3KeyAt(parentNumber, s.getValidatorIndex(), schemeId) ++ : registry.get().publicKey(s.getValidatorIndex(), schemeId); + if (pk.isEmpty() + || !scheme.get().verifyRaw(pk.get(), message.toArray(), s.getSignature().toArray())) { + rejected++; + continue; + } + v2.add(s); + kept++; + if (kept >= sealCap) { + break; + } + } + if (kept < required) { + throw new PqAnchorNotReadyException( + parentNumber, + kept, + required, + "V2: heard " + + heard.size() + + " extra seal(s) for parent hash " + + parentHeader.getHash() +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/messagewrappers/BftMessage.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/messagewrappers/BftMessage.java +index 0a88b579fd..e52c52905e 100644 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/messagewrappers/BftMessage.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/messagewrappers/BftMessage.java +@@ -1,60 +1,72 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/aere-bft-bounded-message-lists.patch. + */ + package org.hyperledger.besu.consensus.common.bft.messagewrappers; + + import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; + import org.hyperledger.besu.consensus.common.bft.payload.Authored; + import org.hyperledger.besu.consensus.common.bft.payload.Payload; + import org.hyperledger.besu.consensus.common.bft.payload.RoundSpecific; + import org.hyperledger.besu.consensus.common.bft.payload.SignedData; + import org.hyperledger.besu.crypto.SECPSignature; + import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; + import org.hyperledger.besu.ethereum.rlp.RLPInput; + + import java.util.Objects; + import java.util.StringJoiner; + import java.util.function.Function; + + import org.apache.tuweni.bytes.Bytes; + + /** + * The Bft message. + * + * @param

    the type of Payload + */ + public class BftMessage

    implements Authored, RoundSpecific { + ++ /** ++ * Maximum number of entries permitted in any embedded list (round-changes, prepares) when ++ * decoding a BFT message. AERE D-434: ported from upstream hyperledger/besu dd4101c9ec. ++ */ ++ public static final int MAX_LIST_ENTRIES = 512; ++ + private final SignedData

    payload; + + /** + * Instantiates a new Bft message. + * + * @param payload the payload + */ + public BftMessage(final SignedData

    payload) { + this.payload = payload; + } + + @Override + public Address getAuthor() { + return payload.getAuthor(); + } + + @Override + public ConsensusRoundIdentifier getRoundIdentifier() { + return payload.getPayload().getRoundIdentifier(); + } +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/network/ValidatorPeers.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/network/ValidatorPeers.java +index f4fccecf3c..649fa75cf4 100644 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/network/ValidatorPeers.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/network/ValidatorPeers.java +@@ -1,36 +1,43 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/0008-aere-pq-aip22.patch. + */ + package org.hyperledger.besu.consensus.common.bft.network; + ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; + import org.hyperledger.besu.consensus.common.validator.ValidatorProvider; + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection; + import org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection.PeerNotConnected; + import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData; + + import java.util.Collection; + import java.util.Collections; + import java.util.Map; + import java.util.Objects; + import java.util.Set; + import java.util.concurrent.ConcurrentHashMap; + import java.util.stream.Collectors; + + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + + /** + * Responsible for tracking the network peers which have a connection to this node, then + * multicasting packets to ONLY the peers which have been identified as being validators. +@@ -76,41 +83,46 @@ public class ValidatorPeers implements ValidatorMulticaster, PeerConnectionTrack + } + + @Override + public void send(final MessageData message) { + sendMessageToSpecificAddresses(getLatestValidators(), message); + } + + @Override + public void send(final MessageData message, final Collection

    denylist) { + final Collection
    includedValidators = + getLatestValidators().stream() + .filter(a -> !denylist.contains(a)) + .collect(Collectors.toSet()); + sendMessageToSpecificAddresses(includedValidators, message); + } + + private void sendMessageToSpecificAddresses( + final Collection
    recipients, final MessageData message) { + LOG.trace( + "Sending message to peers messageCode={} recipients={}", message.getCode(), recipients); +- recipients.stream() +- .map(connectionsByAddress::get) +- .filter(Objects::nonNull) ++ // AERE AIP-22 stage 3: from H_id the recipients are ids; they are reached through the node-key ++ // address their v3 row lists as transport, or through every peer when a row lists none ++ final java.util.Optional> targets = ++ AerePqIdentity.transportTargets(recipients); ++ (targets.isPresent() ++ ? targets.get().stream().map(connectionsByAddress::get).filter(Objects::nonNull) ++ : connectionsByAddress.values().stream()) + .flatMap(Set::stream) ++ .distinct() + .forEach( + connection -> { + try { + connection.sendForProtocol(protocolName, message); + } catch (final PeerNotConnected peerNotConnected) { + LOG.trace( + "Lost connection to a validator. remoteAddress={} peerInfo={}", + connection.getRemoteAddress(), + connection.getPeerInfo()); + } + }); + } + + private Collection
    getLatestValidators() { + return validatorProvider.getValidatorsAtHead(); + } + } +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/payload/SignedData.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/payload/SignedData.java +index 00326eec42..2c59e698b6 100644 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/payload/SignedData.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/payload/SignedData.java +@@ -1,77 +1,94 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/0008-aere-pq-aip22.patch. + */ + package org.hyperledger.besu.consensus.common.bft.payload; + ++import org.hyperledger.besu.consensus.common.bft.AerePqFinality; ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; + import org.hyperledger.besu.crypto.SECPSignature; + import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.datatypes.Hash; + import org.hyperledger.besu.ethereum.core.Util; + import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; + import org.hyperledger.besu.ethereum.rlp.RLPOutput; + + import java.math.BigInteger; + import java.util.Objects; + import java.util.StringJoiner; + + import org.apache.tuweni.bytes.Bytes; + + /** + * The type Signed data. + * + * @param the type parameter of Payload + */ + public class SignedData implements Authored { + + private static final BigInteger HALF_CURVE_ORDER = + SignatureAlgorithmFactory.getInstance().getHalfCurveOrder(); + + private final Address sender; + private final SECPSignature signature; + private final M unsignedPayload; + + /** + * Create signed data. + * + * @param the type parameter + * @param payload the payload + * @param signature the signature + * @return the signed data + * @throws IllegalArgumentException if the signature is invalid + */ + public static SignedData create( + final T payload, final SECPSignature signature) { + final Hash msgHash = payload.hashForSignature(); +- return new SignedData<>(payload, Util.signatureToAddress(signature, msgHash), signature); ++ // AERE AIP-22 stage 3: from H_id the author is the post-quantum id of the signer's v3 row ++ // AERE AIP-22 stage 4: from H_fin the author is the id of the row the message's post-quantum seal index names, and the ++ // envelope's ECDSA signature is not read for authorship (a message without a post-quantum seal has no author then) ++ final long aereHeight = payload.getRoundIdentifier().getSequenceNumber(); ++ return new SignedData<>( ++ payload, ++ AerePqFinality.active(aereHeight) ++ ? AerePqFinality.authorFromSeal(payload, aereHeight) ++ : AerePqIdentity.author(Util.signatureToAddress(signature, msgHash), aereHeight), ++ signature); + } + + private SignedData(final M unsignedPayload, final Address sender, final SECPSignature signature) { + if (!(signature.getS().compareTo(HALF_CURVE_ORDER) <= 0)) { + throw new IllegalArgumentException("Signature is invalid"); + } + this.unsignedPayload = unsignedPayload; + this.sender = sender; + this.signature = signature; + } + + @Override + public Address getAuthor() { + return sender; + } + + /** + * Gets payload. + * + * @return the payload +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/ADRS.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/ADRS.java +index 7610cf8762..ca87df83d3 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/ADRS.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/ADRS.java +@@ -1,28 +1,30 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + import org.bouncycastle.util.Arrays; + import org.bouncycastle.util.Pack; + + @SuppressWarnings("all") + class ADRS + { + static final int WOTS_HASH = 0; + static final int WOTS_PK = 1; + static final int TREE = 2; + static final int FORS_TREE = 3; + static final int FORS_PK = 4; + static final int WOTS_PRF = 5; + static final int FORS_PRF = 6; + + static final int OFFSET_LAYER = 0; + static final int OFFSET_TREE = 4; +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/Fors.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/Fors.java +index d89d83af86..803fca98b4 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/Fors.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/Fors.java +@@ -1,28 +1,30 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + import java.math.BigInteger; + import java.util.LinkedList; + + import org.bouncycastle.util.Arrays; + + @SuppressWarnings("all") + class Fors + { + SLHDSAEngine engine; + + public Fors(SLHDSAEngine engine) + { + this.engine = engine; + } + + // Input: Secret seed SK.seed, start index s, target node height z, public seed PK.seed, address ADRS +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/HT.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/HT.java +index b7d96c16f8..88ff081efe 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/HT.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/HT.java +@@ -1,46 +1,60 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + import java.util.LinkedList; + + import org.bouncycastle.util.Arrays; + + @SuppressWarnings("all") + class HT + { + private final byte[] skSeed; + private final byte[] pkSeed; + SLHDSAEngine engine; + WotsPlus wots; + + final byte[] htPubKey; + ++ // AERE (D-337, 2026-09-26): the same object without htPubKey. The constructor below computes the ++ // top-layer public key (a full treehash of 2^H' WOTS+ leaves) on every signature, and signing never ++ // reads it. Used by ParallelSigning; key generation keeps the constructor below. ++ HT(SLHDSAEngine engine, byte[] skSeed, byte[] pkSeed, boolean withoutPublicKey) ++ { ++ this.skSeed = skSeed; ++ this.pkSeed = pkSeed; ++ this.engine = engine; ++ this.wots = new WotsPlus(engine); ++ this.htPubKey = null; ++ } ++ + public HT(SLHDSAEngine engine, byte[] skSeed, byte[] pkSeed) + { + this.skSeed = skSeed; + this.pkSeed = pkSeed; + + this.engine = engine; + this.wots = new WotsPlus(engine); + + ADRS adrs = new ADRS(); + adrs.setLayerAddress(engine.D - 1); + adrs.setTreeAddress(0); + + if (skSeed != null) + { + htPubKey = xmss_PKgen(skSeed, pkSeed, adrs); + } + else + { + htPubKey = null; + } +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/IndexedDigest.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/IndexedDigest.java +index 8ff076d70d..49bf358925 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/IndexedDigest.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/IndexedDigest.java +@@ -1,26 +1,28 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + @SuppressWarnings("all") + class IndexedDigest + { + final long idx_tree; + final int idx_leaf; + final byte[] digest; + + IndexedDigest(long idx_tree, int idx_leaf, byte[] digest) + { + this.idx_tree = idx_tree; + this.idx_leaf = idx_leaf; + this.digest = digest; + } + } +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/JdkDigest.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/JdkDigest.java +index c7a8e86fae..7edcab834a 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/JdkDigest.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/JdkDigest.java +@@ -1,28 +1,30 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + import java.security.DigestException; + import java.security.MessageDigest; + import java.security.NoSuchAlgorithmException; + import org.bouncycastle.crypto.ExtendedDigest; + import org.bouncycastle.util.Memoable; + + /** + * A Bouncy Castle {@link ExtendedDigest} backed by the JDK's {@link MessageDigest}, so SLH-DSA's + * millions of short hashes run on the SHA-NI intrinsics. Measured 2026-09-04 on an EPYC host: 3M + * SHA-256 of 64 bytes, Bouncy Castle 2533 ms, JDK 335 ms; one sha2_128s signature 1364 ms before, + * 325 ms after. {@link Memoable} is how the SLH-DSA engine keeps the pk-seed prefix state: it is + * implemented here with {@link MessageDigest#clone()}, which the SUN provider supports for SHA-2. + */ + @SuppressWarnings("all") + final class JdkDigest implements ExtendedDigest, Memoable { + private final String algorithm; +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/NodeEntry.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/NodeEntry.java +index 4cd30cfff7..adaa9abe3e 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/NodeEntry.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/NodeEntry.java +@@ -1,24 +1,26 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + @SuppressWarnings("all") + class NodeEntry + { + final byte[] nodeValue; + final int nodeHeight; + + NodeEntry(byte[] nodeValue, int nodeHeight) + { + this.nodeValue = nodeValue; + this.nodeHeight = nodeHeight; + } + } +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/PK.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/PK.java +index 4d0ef5fe2b..8e4b32ee25 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/PK.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/PK.java +@@ -1,24 +1,26 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + @SuppressWarnings("all") + class PK + { + final byte[] seed; + final byte[] root; + + PK(byte[] seed, byte[] root) + { + this.seed = seed; + this.root = root; + } + } +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/ParallelSigning.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/ParallelSigning.java +new file mode 100755 +index 0000000000..2a1505ddcb +--- /dev/null ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/ParallelSigning.java +@@ -0,0 +1,257 @@ ++/* ++ * Copyright contributors to Besu / AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Written by AERE Network (not derived from Bouncy Castle); emitted into this package by ++ * consensus-pqc/slhdsa-fork/genereaza-motorul.py from ParallelSigning.java.sablon. DO NOT EDIT BY HAND. ++ */ ++package org.hyperledger.besu.consensus.common.bft.slhdsa; ++ ++import java.util.ArrayList; ++import java.util.List; ++import java.util.concurrent.Callable; ++import java.util.concurrent.ExecutionException; ++import java.util.concurrent.ExecutorService; ++import java.util.concurrent.Executors; ++import java.util.concurrent.Future; ++import java.util.concurrent.atomic.AtomicInteger; ++ ++import org.bouncycastle.util.Arrays; ++ ++/** ++ * SLH-DSA signing with the message-independent work spread over the cores; the SAME bytes as the ++ * sequential signer, which remains the fallback. ++ * ++ *

    D-337, measured 2026-09-26 on chain 2800: the parent of every anchor took 1.69 s against 0.60 s ++ * for an ordinary block (import times on two validators, fifteen anchors each), because each ++ * validator signs its Commit with SLH-DSA-SHA2-128s there, on the QBFT thread, on one core. One ++ * signature on a validator's CPU (EPYC-Rome, one core): 0.47 s warm, 0.88-1.02 s cold, and a ++ * validator signs once every ~77 s. Almost all of it is message-independent: the authentication ++ * path of each of the D hypertree layers (2^H' - 1 WOTS+ leaves each) and the k FORS trees. Only ++ * the WOTS+ signature of each layer depends on the root of the layer below, and that chain is cheap. ++ * So the auth paths and FORS run as separate tasks on a small daemon pool, each with its own engine ++ * (the engines hold digest state and are not thread-safe), and the chain is then walked in order. ++ * ++ *

    Also dropped: the HT constructor used by the sequential signer computes the top layer's public ++ * key (a full 2^H'-leaf treehash) on every signature, and signing never reads it. ++ * ++ *

    Taken only with more than one core and unless {@code -Daere.pq.slhdsa.parallel=false}; any ++ * failure returns null and the caller runs the original Bouncy Castle code unchanged. ++ */ ++@SuppressWarnings("all") ++final class ParallelSigning { ++ ++ static final String SWITCH_PROPERTY = "aere.pq.slhdsa.parallel"; ++ ++ private static final int THREADS = ++ Math.max(1, Math.min(8, Runtime.getRuntime().availableProcessors())); ++ ++ // counts tasks executed on the pool; the proof reads it to show the parallel path was the one taken ++ private static final AtomicInteger TASKS_RUN = new AtomicInteger(); ++ ++ private static volatile ExecutorService pool; ++ ++ private ParallelSigning() {} ++ ++ static boolean enabled() { ++ return THREADS > 1 ++ && !"false".equalsIgnoreCase(System.getProperty(SWITCH_PROPERTY, "true").trim()); ++ } ++ ++ static int tasksRun() { ++ return TASKS_RUN.get(); ++ } ++ ++ static int tasksPerSignature(final SLHDSAParameters params) { ++ return 1 + 2 * params.getEngine().D; ++ } ++ ++ private static ExecutorService pool() { ++ ExecutorService p = pool; ++ if (p == null) { ++ synchronized (ParallelSigning.class) { ++ p = pool; ++ if (p == null) { ++ final AtomicInteger n = new AtomicInteger(); ++ p = ++ Executors.newFixedThreadPool( ++ THREADS, ++ r -> { ++ final Thread t = new Thread(r, "aere-slhdsa-sign-" + n.incrementAndGet()); ++ t.setDaemon(true); ++ return t; ++ }); ++ pool = p; ++ } ++ } ++ } ++ return p; ++ } ++ ++ /** The signature, or null when this path is not taken; the caller then runs the original code. */ ++ static byte[] trySign( ++ final SLHDSAPrivateKeyParameters privKey, ++ final byte[] msgPrefix, ++ final byte[] msg, ++ final byte[] optRand) { ++ if (!enabled()) { ++ return null; ++ } ++ try { ++ return sign(privKey, msgPrefix, msg, optRand); ++ } catch (final InterruptedException e) { ++ Thread.currentThread().interrupt(); ++ return null; ++ } catch (final ExecutionException | RuntimeException e) { ++ return null; ++ } ++ } ++ ++ static byte[] sign( ++ final SLHDSAPrivateKeyParameters privKey, ++ final byte[] msgPrefix, ++ final byte[] msg, ++ final byte[] optRand) ++ throws InterruptedException, ExecutionException { ++ final SLHDSAParameters params = privKey.getParameters(); ++ final byte[] skSeed = privKey.sk.seed; ++ final byte[] pkSeed = privKey.pk.seed; ++ final SLHDSAEngine engine = params.getEngine(); ++ engine.init(pkSeed); ++ ++ // the randomiser and the message digest, exactly as SLHDSASigner.internalGenerateSignature ++ final byte[] r = engine.PRF_msg(privKey.sk.prf, optRand, msgPrefix, msg); ++ final IndexedDigest idxDigest = engine.H_msg(r, pkSeed, privKey.pk.root, msgPrefix, msg); ++ final byte[] mHash = idxDigest.digest; ++ final long idxTree = idxDigest.idx_tree; ++ final int idxLeaf = idxDigest.idx_leaf; ++ final int d = engine.D; ++ final int hPrime = engine.H_PRIME; ++ ++ // the (tree, leaf) each layer signs with: the walk HT.sign does, layer 0 first ++ final long[] tree = new long[d]; ++ final int[] leaf = new int[d]; ++ long t = idxTree; ++ int l = idxLeaf; ++ for (int j = 0; j < d; j++) { ++ if (j > 0) { ++ l = (int) (t & ((1 << hPrime) - 1)); ++ t >>>= hPrime; ++ } ++ tree[j] = t; ++ leaf[j] = l; ++ } ++ ++ final List> tasks = new ArrayList>(); ++ tasks.add(forsTask(params, skSeed, pkSeed, mHash, idxTree, idxLeaf)); ++ final byte[][][] auth = new byte[d][hPrime][]; ++ for (int j = 0; j < d; j++) { ++ // two halves per layer: the top auth node alone is half of the tree's leaves, the rest the other half ++ tasks.add(authTask(params, skSeed, pkSeed, j, tree[j], leaf[j], hPrime - 1, hPrime, auth)); ++ tasks.add(authTask(params, skSeed, pkSeed, j, tree[j], leaf[j], 0, hPrime - 1, auth)); ++ } ++ final List> done = pool().invokeAll(tasks); ++ final Object[] fors = (Object[]) done.get(0).get(); ++ for (int i = 1; i < done.size(); i++) { ++ done.get(i).get(); // surfaces a failed task, which sends the caller to the original code ++ } ++ for (int j = 0; j < d; j++) { ++ for (int h = 0; h < hPrime; h++) { ++ if (auth[j][h] == null) { ++ throw new IllegalStateException("auth path of layer " + j + " height " + h + " missing"); ++ } ++ } ++ } ++ final SIG_FORS[] sigFors = (SIG_FORS[]) fors[0]; ++ final byte[] pkFors = (byte[]) fors[1]; ++ ++ // the hypertree chain, in order: each layer's WOTS+ signs the root of the layer below (FORS for layer 0) ++ final HT ht = new HT(engine, skSeed, pkSeed, true); ++ byte[] m = pkFors; ++ final byte[][] htParts = new byte[d][]; ++ for (int j = 0; j < d; j++) { ++ final ADRS adrs = new ADRS(); ++ adrs.setLayerAddress(j); ++ adrs.setTreeAddress(tree[j]); ++ final ADRS wotsAdrs = new ADRS(adrs); ++ wotsAdrs.setTypeAndClear(ADRS.WOTS_HASH); ++ wotsAdrs.setKeyPairAddress(leaf[j]); ++ final SIG_XMSS xmss = new SIG_XMSS(ht.wots.sign(m, skSeed, pkSeed, wotsAdrs), auth[j]); ++ htParts[j] = Arrays.concatenate(xmss.sig, Arrays.concatenate(xmss.auth)); ++ if (j < d - 1) { ++ m = ht.xmss_pkFromSig(leaf[j], xmss, m, pkSeed, adrs); ++ } ++ } ++ ++ final byte[][] parts = new byte[sigFors.length + 2][]; ++ parts[0] = r; ++ for (int i = 0; i != sigFors.length; i++) { ++ parts[1 + i] = Arrays.concatenate(sigFors[i].sk, Arrays.concatenate(sigFors[i].authPath)); ++ } ++ parts[parts.length - 1] = Arrays.concatenate(htParts); ++ return Arrays.concatenate(parts); ++ } ++ ++ private static Callable forsTask( ++ final SLHDSAParameters params, ++ final byte[] skSeed, ++ final byte[] pkSeed, ++ final byte[] mHash, ++ final long idxTree, ++ final int idxLeaf) { ++ return () -> { ++ TASKS_RUN.incrementAndGet(); ++ final SLHDSAEngine e = params.getEngine(); ++ e.init(pkSeed); ++ final Fors fors = new Fors(e); ++ ADRS adrs = new ADRS(); ++ adrs.setTypeAndClear(ADRS.FORS_TREE); ++ adrs.setTreeAddress(idxTree); ++ adrs.setKeyPairAddress(idxLeaf); ++ final SIG_FORS[] sigFors = fors.sign(mHash, skSeed, pkSeed, adrs); ++ adrs = new ADRS(); ++ adrs.setTypeAndClear(ADRS.FORS_TREE); ++ adrs.setTreeAddress(idxTree); ++ adrs.setKeyPairAddress(idxLeaf); ++ return new Object[] {sigFors, fors.pkFromSig(sigFors, mHash, pkSeed, adrs)}; ++ }; ++ } ++ ++ // the auth-path loop of HT.xmss_sign, for heights [fromHeight, toHeight) of one layer's tree ++ private static Callable authTask( ++ final SLHDSAParameters params, ++ final byte[] skSeed, ++ final byte[] pkSeed, ++ final int layer, ++ final long treeAddress, ++ final int idx, ++ final int fromHeight, ++ final int toHeight, ++ final byte[][][] auth) { ++ return () -> { ++ TASKS_RUN.incrementAndGet(); ++ final SLHDSAEngine e = params.getEngine(); ++ e.init(pkSeed); ++ final HT ht = new HT(e, skSeed, pkSeed, true); ++ final ADRS a = new ADRS(); ++ a.setTypeAndClear(ADRS.TREE); ++ a.setLayerAddress(layer); ++ a.setTreeAddress(treeAddress); ++ for (int j = fromHeight; j < toHeight; j++) { ++ final int k = (idx >>> j) ^ 1; ++ auth[layer][j] = ht.treehash(skSeed, k << j, j, pkSeed, a); ++ } ++ return null; ++ }; ++ } ++} +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SIG.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SIG.java +index fb6d817027..d9a4c3c79c 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SIG.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SIG.java +@@ -1,28 +1,30 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + @SuppressWarnings("all") + class SIG + { + private final byte[] r; + private final SIG_FORS[] sig_fors; + private final SIG_XMSS[] sig_ht; + + public SIG(int n, int k, int a, int d, int hPrime, int wots_len, byte[] signature) + { + this.r = new byte[n]; + System.arraycopy(signature, 0, r, 0, n); + + this.sig_fors = new SIG_FORS[k]; + int offset = n; + for (int i = 0; i != k; i++) + { +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SIG_FORS.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SIG_FORS.java +index 7c00647622..5d3c5dcff0 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SIG_FORS.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SIG_FORS.java +@@ -1,28 +1,30 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + @SuppressWarnings("all") + class SIG_FORS + { + final byte[][] authPath; + final byte[] sk; + + SIG_FORS(byte[] sk, byte[][] authPath) + { + this.authPath = authPath; + this.sk = sk; + } + + byte[] getSK() + { + return sk; + } +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SIG_XMSS.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SIG_XMSS.java +index f77ffaf1cb..0d64d2a7d9 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SIG_XMSS.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SIG_XMSS.java +@@ -1,28 +1,30 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + @SuppressWarnings("all") + class SIG_XMSS + { + final byte[] sig; + final byte[][] auth; + + public SIG_XMSS(byte[] sig, byte[][] auth) + { + this.sig = sig; + this.auth = auth; + } + + public byte[] getWOTSSig() + { + return sig; + } +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SK.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SK.java +index 8040421b15..4ea009d94d 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SK.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SK.java +@@ -1,24 +1,26 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + @SuppressWarnings("all") + class SK + { + final byte[] seed; + final byte[] prf; + + SK(byte[] seed, byte[] prf) + { + this.seed = seed; + this.prf = prf; + } + } +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAEngine.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAEngine.java +index bf7b40087f..69fcce3dea 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAEngine.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAEngine.java +@@ -1,28 +1,30 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + import org.bouncycastle.crypto.Digest; + import org.bouncycastle.crypto.Xof; + import org.bouncycastle.crypto.digests.SHAKEDigest; + import org.bouncycastle.crypto.generators.MGF1BytesGenerator; + import org.bouncycastle.crypto.macs.HMac; + import org.bouncycastle.crypto.params.KeyParameter; + import org.bouncycastle.crypto.params.MGFParameters; + import org.bouncycastle.util.Arrays; + import org.bouncycastle.util.Bytes; + import org.bouncycastle.util.Memoable; + import org.bouncycastle.util.Pack; + + @SuppressWarnings("all") + abstract class SLHDSAEngine + { + final int N; +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAEngineProvider.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAEngineProvider.java +index 791705d9ad..b15b4c7ae9 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAEngineProvider.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAEngineProvider.java +@@ -1,19 +1,21 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + @SuppressWarnings("all") + interface SLHDSAEngineProvider + { + int getN(); + + SLHDSAEngine get(); + } +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAKeyGenerationParameters.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAKeyGenerationParameters.java +index b3daec9773..12b23ac26a 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAKeyGenerationParameters.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAKeyGenerationParameters.java +@@ -1,28 +1,30 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + import java.security.SecureRandom; + + import org.bouncycastle.crypto.KeyGenerationParameters; + + @SuppressWarnings("all") + public class SLHDSAKeyGenerationParameters + extends KeyGenerationParameters + { + private final SLHDSAParameters parameters; + + public SLHDSAKeyGenerationParameters(SecureRandom random, SLHDSAParameters parameters) + { + super(random, -1); + this.parameters = parameters; + } + +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAKeyPairGenerator.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAKeyPairGenerator.java +index 58a32e8ea9..32879f8331 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAKeyPairGenerator.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAKeyPairGenerator.java +@@ -1,28 +1,30 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + import java.security.SecureRandom; + + import org.bouncycastle.crypto.AsymmetricCipherKeyPair; + import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator; + import org.bouncycastle.crypto.KeyGenerationParameters; + + @SuppressWarnings("all") + public class SLHDSAKeyPairGenerator + implements AsymmetricCipherKeyPairGenerator + { + private SecureRandom random; + private SLHDSAParameters parameters; + + public void init(KeyGenerationParameters param) + { + random = param.getRandom(); +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAKeyParameters.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAKeyParameters.java +index 2999c4cac5..d13985c1d7 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAKeyParameters.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAKeyParameters.java +@@ -1,28 +1,30 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + import org.bouncycastle.crypto.params.AsymmetricKeyParameter; + + @SuppressWarnings("all") + public class SLHDSAKeyParameters + extends AsymmetricKeyParameter + { + private final SLHDSAParameters parameters; + + protected SLHDSAKeyParameters(boolean isPrivate, SLHDSAParameters parameters) + { + super(isPrivate); + this.parameters = parameters; + } + + public SLHDSAParameters getParameters() + { +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAParameters.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAParameters.java +index 4a5e422c8c..1d14c94d73 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAParameters.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAParameters.java +@@ -1,28 +1,30 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + @SuppressWarnings("all") + public class SLHDSAParameters + { + public static final int TYPE_PURE = 0; + public static final int TYPE_SHA2_256 = 1; + public static final int TYPE_SHA2_512 = 2; + public static final int TYPE_SHAKE128 = 3; + public static final int TYPE_SHAKE256 = 4; + + // "Pure" SLH-DSA Parameters + // SHA-2 + public static final SLHDSAParameters sha2_128f = new SLHDSAParameters( + "sha2-128f", new Sha2EngineProvider(16, 16, 22, 6, 33, 66), TYPE_PURE); + public static final SLHDSAParameters sha2_128s = new SLHDSAParameters( + "sha2-128s", new Sha2EngineProvider(16, 16, 7, 12, 14, 63), TYPE_PURE); + +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAPrivateKeyParameters.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAPrivateKeyParameters.java +index da9c060bb4..64e42635c8 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAPrivateKeyParameters.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAPrivateKeyParameters.java +@@ -1,28 +1,30 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + import org.bouncycastle.util.Arrays; + + @SuppressWarnings("all") + public class SLHDSAPrivateKeyParameters + extends SLHDSAKeyParameters + { + final SK sk; + final PK pk; + + public SLHDSAPrivateKeyParameters(SLHDSAParameters parameters, byte[] skpkEncoded) + { + super(true, parameters); + int n = parameters.getN(); + if (skpkEncoded.length != 4 * n) + { + throw new IllegalArgumentException("private key encoding does not match parameters"); +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAPublicKeyParameters.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAPublicKeyParameters.java +index 544156c66c..5492012f73 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAPublicKeyParameters.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSAPublicKeyParameters.java +@@ -1,28 +1,30 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + import org.bouncycastle.util.Arrays; + + @SuppressWarnings("all") + public class SLHDSAPublicKeyParameters + extends SLHDSAKeyParameters + { + private final PK pk; + + public SLHDSAPublicKeyParameters(SLHDSAParameters parameters, byte[] pkValues) + { + super(false, parameters); + int n = parameters.getN(); + if (pkValues.length != 2 * n) + { + throw new IllegalArgumentException("public key encoding does not match parameters"); + } +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSASigner.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSASigner.java +index 91fdef108b..720e4f2414 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSASigner.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SLHDSASigner.java +@@ -1,28 +1,30 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + import java.security.SecureRandom; + + import org.bouncycastle.crypto.CipherParameters; + import org.bouncycastle.crypto.params.ParametersWithContext; + import org.bouncycastle.crypto.params.ParametersWithRandom; + import org.bouncycastle.pqc.crypto.MessageSigner; + import org.bouncycastle.util.Arrays; + + /** + * SLH-DA signer. + *

    + * This version is based on the 3rd submission with deference to the updated reference + * implementation on github as at November 9th 2021. This version includes the changes + * for the countermeasure for the long-message second preimage attack - see + * "https://github.com/sphincs/sphincsplus/commit/61cd2695c6f984b4f4d6ed675378ed9a486cbede" + * for further details. +@@ -174,40 +176,47 @@ public class SLHDSASigner + adrs.setKeyPairAddress(idx_leaf); + byte[] PK_FORS = new Fors(engine).pkFromSig(sig_fors, mHash, pubKey.getSeed(), adrs); + // verify HT signature + adrs.setTypeAndClear(ADRS.TREE); + adrs.setLayerAddress(0); + adrs.setTreeAddress(idx_tree); + adrs.setKeyPairAddress(idx_leaf); + HT ht = new HT(engine, null, pubKey.getSeed()); + return ht.verify(PK_FORS, SIG_HT, pubKey.getSeed(), idx_tree, idx_leaf, pubKey.getRoot()); + } + + protected byte[] internalGenerateSignature(byte[] message, byte[] optRand) + { + return internalGenerateSignature(privKey, null, message, optRand); + } + + private static byte[] internalGenerateSignature(SLHDSAPrivateKeyParameters privKey, byte[] msgPrefix, byte[] msg, + byte[] optRand) + { + // TODO Check init via privKey != null ++ // AERE (D-337, 2026-09-26): the same signature, bit for bit, with the message-independent work on ++ // the free cores (ParallelSigning). null = not taken, and the original code below runs unchanged. ++ byte[] aere = ParallelSigning.trySign(privKey, msgPrefix, msg, optRand); ++ if (aere != null) ++ { ++ return aere; ++ } + + SLHDSAEngine engine = privKey.getParameters().getEngine(); + engine.init(privKey.pk.seed); + + Fors fors = new Fors(engine); + byte[] R = engine.PRF_msg(privKey.sk.prf, optRand, msgPrefix, msg); + + IndexedDigest idxDigest = engine.H_msg(R, privKey.pk.seed, privKey.pk.root, msgPrefix, msg); + byte[] mHash = idxDigest.digest; + long idx_tree = idxDigest.idx_tree; + int idx_leaf = idxDigest.idx_leaf; + // FORS sign + ADRS adrs = new ADRS(); + adrs.setTypeAndClear(ADRS.FORS_TREE); + adrs.setTreeAddress(idx_tree); + adrs.setKeyPairAddress(idx_leaf); + SIG_FORS[] sig_fors = fors.sign(mHash, privKey.sk.seed, privKey.pk.seed, adrs); + // get FORS public key - spec shows M? + adrs = new ADRS(); + adrs.setTypeAndClear(ADRS.FORS_TREE); +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/WotsPlus.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/WotsPlus.java +index fe1a94e580..47600d14d3 100755 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/WotsPlus.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/slhdsa/WotsPlus.java +@@ -1,28 +1,30 @@ + /* + * Derived from Bouncy Castle 1.80, package org.bouncycastle.pqc.crypto.slhdsa (MIT licence, + * Copyright (c) 2000-2025 The Legion of the Bouncy Castle Inc., see LICENTA-BOUNCYCASTLE.txt), + * regenerated into Aere Network by consensus-pqc/slhdsa-fork/genereaza-motorul.py on 2026-09-04 (D-337). +- * The ONLY change of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI +- * intrinsics) instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature +- * cost seconds on the QBFT thread at every anchor parent. Algorithm, key formats and signature bytes are +- * FIPS 205 as before; SlhDsaFastEngineTest pins that against the original, in both directions. ++ * Changes of substance: the SHA-2 engine hashes through the JDK's MessageDigest (SHA-NI intrinsics) ++ * instead of Bouncy Castle's pure-Java digests, which made one SLH-DSA-SHA2-128s signature cost seconds on ++ * the QBFT thread at every anchor parent; and (2026-09-26) signing first tries ParallelSigning, which ++ * spreads the message-independent work over the cores and gives the same bytes (HT gains a constructor ++ * without the unused top-layer public key). Algorithm, key formats and signature bytes are FIPS 205 as ++ * before; SlhDsaFastEngineTest and SlhDsaParallelSigningTest pin that against the original. + * DO NOT EDIT BY HAND: regenerate with the script above. + */ + package org.hyperledger.besu.consensus.common.bft.slhdsa; + + import org.bouncycastle.util.Arrays; + import org.bouncycastle.util.Pack; + + @SuppressWarnings("all") + class WotsPlus + { + private final SLHDSAEngine engine; + private final int w; + + WotsPlus(SLHDSAEngine engine) + { + this.engine = engine; + this.w = this.engine.WOTS_W; + } + + byte[] pkGen(byte[] skSeed, byte[] pkSeed, ADRS paramAdrs) +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/tools/PqRegistryV3Tool.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/tools/PqRegistryV3Tool.java +new file mode 100644 +index 0000000000..ec81e7d03f +--- /dev/null ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/tools/PqRegistryV3Tool.java +@@ -0,0 +1,288 @@ ++/* ++ * AERE AIP-22 stage 3: the tool that makes a registry v3 epoch FROM THE KEYS ALREADY ON THE VALIDATORS. ++ * ++ * Two commands, and the split is the security property: ++ * ++ * row runs ON THE HOST that holds a validator's keys. It reads that validator's Falcon-512 key ++ * file (the same "index, f, g, F, pk" properties the node loads through aere.falcon.key), ++ * its SLH-DSA-SHA2-128s key file (the same "index, sk" the hybrid loader reads) and its ECDSA ++ * validator key (a file holding the 32-byte hex), and prints ONE row: the id derived from the ++ * Falcon key, both public keys in their standard encodings, a proof of possession by each, and ++ * the ecdsa link signed by the validator key. It prints no private key, nor any part of one. ++ * assemble runs anywhere (the laptop): it takes the rows, builds the manifest, LOADS it through the ++ * strict loader (every proof and claim is verified again) and prints the manifest and its ++ * registry hash - the value the chain pins. ++ * ++ * Nothing leaves a host but signatures and public keys, which is what "no new key material and nothing ++ * out of the vault" means for this ceremony (AIP-22 section 3.2, the plan's stage 3). ++ * ++ * java -cp '/*' org.hyperledger.besu.consensus.common.bft.tools.PqRegistryV3Tool row \ ++ * --chain-id 28001 --bind H --count N --index i --falcon-key F --slh-key S --slh-pub HEX \ ++ * --ecdsa-key-file K [--transport] ++ * java -cp '/*' ...PqRegistryV3Tool assemble --chain-id 28001 --bind H --count N \ ++ * --required falcon-512,slh-dsa-sha2-128s row0.json row1.json ... ++ */ ++package org.hyperledger.besu.consensus.common.bft.tools; ++ ++import org.hyperledger.besu.consensus.common.bft.FalconSealScheme; ++import org.hyperledger.besu.consensus.common.bft.PqRegistryV3; ++import org.hyperledger.besu.consensus.common.bft.SealScheme; ++import org.hyperledger.besu.consensus.common.bft.SealSchemes; ++import org.hyperledger.besu.crypto.KeyPair; ++import org.hyperledger.besu.crypto.SECPPrivateKey; ++import org.hyperledger.besu.crypto.SignatureAlgorithm; ++import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; ++import org.hyperledger.besu.ethereum.core.Util; ++ ++import java.io.IOException; ++import java.io.StringReader; ++import java.nio.charset.StandardCharsets; ++import java.nio.file.Files; ++import java.nio.file.Path; ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.HashMap; ++import java.util.List; ++import java.util.Locale; ++import java.util.Map; ++import java.util.Properties; ++import java.util.TreeMap; ++ ++import com.fasterxml.jackson.databind.JsonNode; ++import com.fasterxml.jackson.databind.ObjectMapper; ++import com.fasterxml.jackson.databind.SerializationFeature; ++import com.fasterxml.jackson.databind.node.ObjectNode; ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.bytes.Bytes32; ++import org.bouncycastle.pqc.crypto.falcon.FalconParameters; ++import org.bouncycastle.pqc.crypto.falcon.FalconPrivateKeyParameters; ++ ++/** The registry v3 ceremony tool. */ ++public final class PqRegistryV3Tool { ++ ++ private static final ObjectMapper M = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT); ++ ++ private PqRegistryV3Tool() {} ++ ++ /** ++ * Entry point. ++ * ++ * @param args the command and its options ++ * @throws IOException on unreadable input ++ */ ++ public static void main(final String[] args) throws IOException { ++ if (args.length == 0) { ++ usage(); ++ System.exit(2); ++ } ++ final Map o = new HashMap<>(); ++ final List files = new ArrayList<>(); ++ for (int i = 1; i < args.length; i++) { ++ if (args[i].startsWith("--")) { ++ if (args[i].equals("--transport")) { ++ o.put("transport", "1"); ++ } else if (i + 1 < args.length) { ++ o.put(args[i].substring(2), args[++i]); ++ } else { ++ usage(); ++ System.exit(2); ++ } ++ } else { ++ files.add(args[i]); ++ } ++ } ++ switch (args[0]) { ++ case "keygen" -> keygen(o); ++ case "row" -> row(o); ++ case "assemble" -> assemble(o, files); ++ default -> { ++ usage(); ++ System.exit(2); ++ } ++ } ++ } ++ ++ /** ++ * AIP-22 stage 3b: a NEW key pair for a validator, generated ON THE HOST that will hold it (a rotation). Writes the Falcon-512 ++ * key file (index, f, g, F, pk - the format aere.falcon.key and aere.falcon.keys.next read) and the SLH-DSA-SHA2-128s key file ++ * (index, alg, sk, pk - the format the hybrid loaders read), owner-only, refusing to overwrite anything; prints only the public ++ * keys. ++ */ ++ private static void keygen(final Map o) throws IOException { ++ final int index = Integer.parseInt(need(o, "index")); ++ final Path fOut = Path.of(need(o, "out-falcon")); ++ final Path sOut = Path.of(need(o, "out-slh")); ++ if (Files.exists(fOut) || Files.exists(sOut)) { ++ throw new IllegalStateException("refusing to overwrite an existing key file"); ++ } ++ final java.security.SecureRandom rng = ++ org.hyperledger.besu.crypto.SecureRandomProvider.createSecureRandom(); ++ final org.bouncycastle.pqc.crypto.falcon.FalconKeyPairGenerator g = ++ new org.bouncycastle.pqc.crypto.falcon.FalconKeyPairGenerator(); ++ g.init(new org.bouncycastle.pqc.crypto.falcon.FalconKeyGenerationParameters(rng, FalconParameters.falcon_512)); ++ final FalconPrivateKeyParameters fk = (FalconPrivateKeyParameters) g.generateKeyPair().getPrivate(); ++ final SealScheme slh = SealSchemes.SLH_DSA_128S; ++ final SealScheme.GeneratedPair sp = slh.generate(rng); ++ final byte[] slhSk = slh.serializePrivateKey(sp.privateKey()).orElseThrow(); ++ final String falconFile = ++ "index=" + index + "\nf=" + hx(fk.getSpolyf()).substring(2) + "\ng=" + hx(fk.getG()).substring(2) ++ + "\nF=" + hx(fk.getSpolyF()).substring(2) + "\npk=" + hx(fk.getPublicKey()).substring(2) + "\n"; ++ final String slhFile = ++ "index=" + index + "\nalg=slh-dsa-sha2-128s\nsk=" + hx(slhSk).substring(2) + "\npk=" ++ + hx(sp.publicRegistryForm()).substring(2) + "\n"; ++ final java.nio.file.attribute.FileAttribute ownerOnly = ++ java.nio.file.attribute.PosixFilePermissions.asFileAttribute( ++ java.nio.file.attribute.PosixFilePermissions.fromString("rw-------")); ++ Files.writeString(Files.createFile(fOut, ownerOnly), falconFile, StandardCharsets.UTF_8); ++ Files.writeString(Files.createFile(sOut, ownerOnly), slhFile, StandardCharsets.UTF_8); ++ final ObjectNode out = M.createObjectNode(); ++ out.put("index", index); ++ out.put("falconPk", hx(fk.getPublicKey())); ++ out.put("slhPub", hx(sp.publicRegistryForm())); ++ System.out.println(M.writeValueAsString(out)); ++ } ++ ++ private static void row(final Map o) throws IOException { ++ final long chain = Long.parseLong(need(o, "chain-id")); ++ final long bind = Long.parseLong(need(o, "bind")); ++ final int count = Integer.parseInt(need(o, "count")); ++ final int index = Integer.parseInt(need(o, "index")); ++ // Falcon: the node's own key file; the index inside must be the index asked for ++ final Properties fp = new Properties(); ++ fp.load(new StringReader(Files.readString(Path.of(need(o, "falcon-key")), StandardCharsets.UTF_8))); ++ if (Integer.parseInt(fp.getProperty("index").trim()) != index) { ++ throw new IllegalArgumentException("the Falcon key file is for index " + fp.getProperty("index")); ++ } ++ final byte[] h = hex(fp.getProperty("pk")); ++ final FalconPrivateKeyParameters fsk = ++ new FalconPrivateKeyParameters( ++ FalconParameters.falcon_512, hex(fp.getProperty("f")), hex(fp.getProperty("g")), ++ hex(fp.getProperty("F")), h); ++ final byte[] falconStd = new byte[PqRegistryV3.FALCON_512_PK_LENGTH]; ++ falconStd[0] = PqRegistryV3.FALCON_512_PK_HEADER; ++ System.arraycopy(h, 0, falconStd, 1, h.length); ++ // AIP-22 stage 3b: a ROTATED row keeps the id of its first registration (--id); a new row's id is its Falcon key's derivation ++ final byte[] id = o.containsKey("id") ? hex(o.get("id")) : PqRegistryV3.idOf(falconStd); ++ final byte[] falconPop = ++ falconSign(fsk, PqRegistryV3.popMessage(chain, bind, count, index, id, SealSchemes.FALCON_512.wireId(), falconStd)); ++ // SLH-DSA: the hybrid key file; the public key is given (it is the registry's), and the private key ++ // must sign a probe that verifies under it before anything is printed ++ final Properties sp = new Properties(); ++ sp.load(new StringReader(Files.readString(Path.of(need(o, "slh-key")), StandardCharsets.UTF_8))); ++ if (Integer.parseInt(sp.getProperty("index").trim()) != index) { ++ throw new IllegalArgumentException("the SLH-DSA key file is for index " + sp.getProperty("index")); ++ } ++ final SealScheme slh = SealSchemes.SLH_DSA_128S; ++ final SealScheme.PrivateHandle ssk = ++ slh.parsePrivateKey(hex(sp.getProperty("sk"))).orElseThrow( ++ () -> new IllegalArgumentException("the SLH-DSA key does not parse")); ++ final byte[] slhPub = hex(need(o, "slh-pub")); ++ final byte[] slhPop = ++ slh.sign(ssk, PqRegistryV3.popMessage(chain, bind, count, index, id, slh.wireId(), slhPub).toArrayUnsafe()) ++ .orElseThrow(); ++ if (!slh.verifyRaw(slhPub, PqRegistryV3.popMessage(chain, bind, count, index, id, slh.wireId(), slhPub).toArrayUnsafe(), slhPop)) { ++ throw new IllegalStateException("the SLH-DSA key file does not match the public key given; refusing"); ++ } ++ // the ECDSA validator key: signs the link from its address to the row ++ final SignatureAlgorithm ec = SignatureAlgorithmFactory.getInstance(); ++ final String ecHex = Files.readString(Path.of(need(o, "ecdsa-key-file")), StandardCharsets.UTF_8).trim(); ++ final SECPPrivateKey ecsk = ec.createPrivateKey(Bytes32.fromHexString(ecHex)); ++ final KeyPair kp = ec.createKeyPair(ecsk); ++ final byte[] addr = Util.publicKeyToAddress(kp.getPublicKey()).getBytes().toArrayUnsafe(); ++ final TreeMap keys = new TreeMap<>(); ++ keys.put(SealSchemes.FALCON_512.wireId() & 0xff, new PqRegistryV3.Key(SealSchemes.FALCON_512, falconStd, falconPop)); ++ keys.put(slh.wireId() & 0xff, new PqRegistryV3.Key(slh, slhPub, slhPop)); ++ final byte[] transport = o.containsKey("transport") ? addr : null; ++ final Bytes32 rh = ++ PqRegistryV3.rowHash(chain, bind, count, new PqRegistryV3.Row(index, id, keys, transport, Map.of(), null, null)); ++ final byte[] claim = ec.sign(PqRegistryV3.claimDigest(chain, rh), kp).encodedBytes().toArrayUnsafe(); ++ final ObjectNode row = M.createObjectNode(); ++ row.put("id", hx(id)); ++ row.putObject("keys").put("falcon-512", hx(falconStd)).put("slh-dsa-sha2-128s", hx(slhPub)); ++ row.putObject("pop").put("falcon-512", hx(falconPop)).put("slh-dsa-sha2-128s", hx(slhPop)); ++ if (transport != null) { ++ row.putObject("transport").put("secp256k1Address", hx(transport)); ++ } ++ row.putObject("ecdsa").put("addr", hx(addr)).put("claim", hx(claim)); ++ // AIP-22 stage 3b: a rotation - EACH old key of the row signs the new row's hash (AERE-PQ-ROTATE-3); the loader requires ++ // one signature per scheme the previous epoch bound, by exactly that previous key ++ if (o.containsKey("old-falcon-key") || o.containsKey("old-slh-key")) { ++ final Bytes32 rot = PqRegistryV3.rotateMessage(rh); ++ final Properties of = new Properties(); ++ of.load(new StringReader(Files.readString(Path.of(need(o, "old-falcon-key")), StandardCharsets.UTF_8))); ++ final FalconPrivateKeyParameters oldF = ++ new FalconPrivateKeyParameters( ++ FalconParameters.falcon_512, hex(of.getProperty("f")), hex(of.getProperty("g")), ++ hex(of.getProperty("F")), hex(of.getProperty("pk"))); ++ final Properties os = new Properties(); ++ os.load(new StringReader(Files.readString(Path.of(need(o, "old-slh-key")), StandardCharsets.UTF_8))); ++ final SealScheme.PrivateHandle oldS = ++ slh.parsePrivateKey(hex(os.getProperty("sk"))).orElseThrow( ++ () -> new IllegalArgumentException("the old SLH-DSA key does not parse")); ++ row.putObject("rotation") ++ .put("falcon-512", hx(falconSign(oldF, rot))) ++ .put("slh-dsa-sha2-128s", hx(slh.sign(oldS, rot.toArrayUnsafe()).orElseThrow())); ++ } ++ final ObjectNode out = M.createObjectNode(); ++ out.put("index", index); ++ out.set("row", row); ++ System.out.println(M.writeValueAsString(out)); ++ } ++ ++ private static void assemble(final Map o, final List files) throws IOException { ++ final long chain = Long.parseLong(need(o, "chain-id")); ++ final long bind = Long.parseLong(need(o, "bind")); ++ final int count = Integer.parseInt(need(o, "count")); ++ final List required = Arrays.asList(o.getOrDefault("required", "falcon-512").split(",")); ++ final ObjectNode m = M.createObjectNode(); ++ m.put("formatVersion", PqRegistryV3.FORMAT_VERSION); ++ m.put("chainId", chain); ++ m.put("bindHeight", bind); ++ m.put("count", count); ++ for (final String f : files) { ++ final JsonNode r = M.readTree(Files.readString(Path.of(f), StandardCharsets.UTF_8)); ++ m.set(Integer.toString(r.get("index").asInt()), r.get("row")); ++ } ++ // AIP-22 stage 3b: an epoch after the switch epoch is loaded AGAINST the one before it (--previous), so every rotation it ++ // carries is verified; the switch epoch itself (no --previous) must carry every ecdsa link ++ PqRegistryV3.Registry previous = null; ++ if (o.containsKey("previous")) { ++ final JsonNode pj = M.readTree(Files.readString(Path.of(o.get("previous")), StandardCharsets.UTF_8)); ++ previous = PqRegistryV3.load(pj, chain, required, null, true); ++ } ++ final PqRegistryV3.Registry reg = PqRegistryV3.load(m, chain, required, previous, previous == null); ++ m.put("registryHash", reg.hash().toHexString()); ++ System.out.println(M.writeValueAsString(m)); ++ System.err.println("registryHash " + reg.hash().toHexString() + " (" + count + " rows, bound at " + bind + ")"); ++ } ++ ++ private static byte[] falconSign(final FalconPrivateKeyParameters sk, final Bytes32 message) { ++ return ((FalconSealScheme) SealSchemes.FALCON_512) ++ .signWithParams(sk, message.toArrayUnsafe()) ++ .orElseThrow(() -> new IllegalStateException("the Falcon key did not sign")); ++ } ++ ++ private static String need(final Map o, final String k) { ++ final String v = o.get(k); ++ if (v == null) { ++ throw new IllegalArgumentException("missing --" + k); ++ } ++ return v; ++ } ++ ++ private static byte[] hex(final String s) { ++ return Bytes.fromHexStringLenient(s.trim()).toArrayUnsafe(); ++ } ++ ++ private static String hx(final byte[] b) { ++ final StringBuilder sb = new StringBuilder("0x"); ++ for (final byte x : b) { ++ sb.append(String.format(Locale.ROOT, "%02x", x & 0xff)); ++ } ++ return sb.toString(); ++ } ++ ++ private static void usage() { ++ System.err.println("usage: PqRegistryV3Tool row|assemble ... (see the class comment)"); ++ } ++} +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/validator/blockbased/VoteTally.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/validator/blockbased/VoteTally.java +index 8251f5c94b..fed8a2a5a7 100644 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/validator/blockbased/VoteTally.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/validator/blockbased/VoteTally.java +@@ -1,36 +1,43 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/0008-aere-pq-aip22.patch. + */ + package org.hyperledger.besu.consensus.common.validator.blockbased; + ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; + import org.hyperledger.besu.consensus.common.validator.ValidatorVote; + import org.hyperledger.besu.datatypes.Address; + + import java.util.Collection; + import java.util.Collections; + import java.util.HashMap; + import java.util.HashSet; + import java.util.Map; + import java.util.NavigableSet; + import java.util.Optional; + import java.util.Set; + import java.util.TreeSet; + + import com.google.common.collect.Maps; + + /** Tracks the current list of validators and votes to add or drop validators. */ + class VoteTally { + + private final NavigableSet

    currentValidators; + +@@ -93,40 +100,58 @@ class VoteTally { + return Optional.ofNullable(addVotesBySubject.get(subject)).orElse(Collections.emptySet()); + } + + Set
    getOutstandingRemoveVotesFor(final Address subject) { + return Optional.ofNullable(removeVotesBySubject.get(subject)).orElse(Collections.emptySet()); + } + + private int validatorLimit() { + return (currentValidators.size() / 2) + 1; + } + + /** + * Reset the outstanding vote tallies as required at each epoch. The current validator list is + * unaffected. + */ + void discardOutstandingVotes() { + addVotesBySubject.clear(); + removeVotesBySubject.clear(); + } + ++ /** ++ * AERE AIP-22 stage 3: after block H_id - 1 the validators become the sorted post-quantum ids of the ++ * same members, and votes still open on classical addresses are discarded (they name addresses the ++ * id space no longer contains). Anywhere else, and when the identity switch is not armed, nothing ++ * changes. ++ * ++ * @param blockNumber the block whose effects this tally now includes ++ */ ++ void translateToIds(final long blockNumber) { ++ final Collection
    translated = ++ AerePqIdentity.translateSetAfter(currentValidators, blockNumber); ++ if (translated != currentValidators) { ++ currentValidators.clear(); ++ currentValidators.addAll(translated); ++ discardOutstandingVotes(); ++ } ++ } ++ + /** + * The validator addresses + * + * @return The collection of validators after the voting at the most recent block has been + * finalised. + */ + Collection
    getValidators() { + return currentValidators; + } + + VoteTally copy() { + final Map> addVotesBySubject = Maps.newHashMap(); + final Map> removeVotesBySubject = Maps.newHashMap(); + + this.addVotesBySubject.forEach( + (key, value) -> addVotesBySubject.put(key, new TreeSet<>(value))); + this.removeVotesBySubject.forEach( + (key, value) -> removeVotesBySubject.put(key, new TreeSet<>(value))); + + return new VoteTally( +diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/validator/blockbased/VoteTallyUpdater.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/validator/blockbased/VoteTallyUpdater.java +index bae5540aad..0da2c63f55 100644 +--- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/validator/blockbased/VoteTallyUpdater.java ++++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/validator/blockbased/VoteTallyUpdater.java +@@ -1,38 +1,45 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/0008-aere-pq-aip22.patch. + */ + package org.hyperledger.besu.consensus.common.validator.blockbased; + + import org.hyperledger.besu.consensus.common.BlockInterface; + import org.hyperledger.besu.consensus.common.EpochManager; ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; + import org.hyperledger.besu.consensus.common.validator.ValidatorVote; + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.ethereum.chain.Blockchain; + import org.hyperledger.besu.ethereum.core.BlockHeader; + + import java.util.Collection; + import java.util.Optional; + + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + + /** + * Provides the logic to extract vote tally state from the blockchain and update it as blocks are + * added. + */ + class VoteTallyUpdater { + + private static final Logger LOG = LoggerFactory.getLogger(VoteTallyUpdater.class); + + private final EpochManager epochManager; +@@ -56,26 +63,31 @@ class VoteTallyUpdater { + final BlockHeader epochBlock = blockchain.getBlockHeader(epochBlockNumber).get(); + final Collection
    initialValidators = blockInterface.validatorsInBlock(epochBlock); + final VoteTally voteTally = new VoteTally(initialValidators); + for (long blockNumber = epochBlockNumber + 1; + blockNumber <= chainHeadBlockNumber; + blockNumber++) { + updateForBlock(blockchain.getBlockHeader(blockNumber).get(), voteTally); + } + return voteTally; + } + + /** + * Update the vote tally to reflect changes caused by appending a new block to the chain. + * + * @param header the header of the block being added + * @param voteTally the vote tally to update + */ + void updateForBlock(final BlockHeader header, final VoteTally voteTally) { + if (epochManager.isEpochBlock(header.getNumber())) { + voteTally.discardOutstandingVotes(); +- return; ++ } else { ++ final Optional vote = blockInterface.extractVoteFromHeader(header); ++ vote.ifPresent(voteTally::addVote); ++ } ++ // AERE AIP-22 stage 3: after block H_id - 1 the set becomes the post-quantum ids of its members; ++ // asked first, so that disarmed (or at any other block) the tally sees no extra call at all ++ if (AerePqIdentity.translatesAfter(header.getNumber())) { ++ voteTally.translateToIds(header.getNumber()); + } +- final Optional vote = blockInterface.extractVoteFromHeader(header); +- vote.ifPresent(voteTally::addVote); + } + } +diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/AereKeysFromV3Test.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/AereKeysFromV3Test.java +new file mode 100644 +index 0000000000..ba91cd1b81 +--- /dev/null ++++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/AereKeysFromV3Test.java +@@ -0,0 +1,192 @@ ++/* ++ * AERE AIP-22 stage 3b: probes of the keys that seal coming from the v3 epoch in force (AerePqIdentity ++ * keysFromV3 / v3KeyAt / v3IdAt / verifyKeyContinuity) and of the ecdsa link inherited by id, on the two ++ * shared registry v3 conformance vectors: ok-epoch-a (bound at 1000, three rows, each with its ecdsa link) ++ * and ok-epoch-b-rotation (bound at 2000: index 1 rotates both keys under its id, the id of A's index 2 ++ * moves to index 0, A's index 0 leaves, a new id joins at index 2; no ecdsa links). ++ * ++ * What must hold, each with its negative: H_k falls on an epoch boundary at or above H_id or the node ++ * refuses to arm; below H_k nothing comes from v3; from H_k the key of an index is the key of THAT index in ++ * the epoch in force (Falcon without its 0x09 header, SLH-DSA as its 32 bytes), so the rotated key replaces ++ * the old one exactly at the rotation epoch and an index the epoch does not have gives NO key; the ++ * continuity guard accepts the same keys and refuses one changed byte or a missing key; and an author keeps ++ * its id across an epoch that omits the ecdsa links, but a removed id's address authors as nothing. ++ */ ++package org.hyperledger.besu.consensus.common.bft; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++import static org.assertj.core.api.Assertions.assertThatThrownBy; ++ ++import org.hyperledger.besu.datatypes.Address; ++ ++import java.io.IOException; ++import java.io.InputStream; ++import java.util.Arrays; ++import java.util.List; ++import java.util.Optional; ++import java.util.TreeMap; ++ ++import com.fasterxml.jackson.databind.JsonNode; ++import com.fasterxml.jackson.databind.ObjectMapper; ++import org.apache.tuweni.bytes.Bytes; ++import org.junit.jupiter.api.AfterEach; ++import org.junit.jupiter.api.BeforeEach; ++import org.junit.jupiter.api.Test; ++ ++public class AereKeysFromV3Test { ++ ++ private static final List SCHEMES = List.of("falcon-512", "slh-dsa-sha2-128s"); ++ private PqRegistryV3.Registry a; ++ private PqRegistryV3.Registry b; ++ private TreeMap epochs; ++ ++ private JsonNode vector(final String name) throws IOException { ++ try (InputStream in = getClass().getResourceAsStream("/aere/registry-v3/" + name + ".json")) { ++ assertThat(in).isNotNull(); ++ return new ObjectMapper().readTree(in); ++ } ++ } ++ ++ @BeforeEach ++ public void load() throws IOException { ++ final JsonNode va = vector("ok-epoch-a"); ++ final JsonNode vb = vector("ok-epoch-b-rotation"); ++ a = PqRegistryV3.load(va.get("manifest"), va.get("chainId").asLong(), SCHEMES, null, true); ++ b = PqRegistryV3.load(vb.get("manifest"), vb.get("chainId").asLong(), SCHEMES, a, false); ++ assertThat(a.bindHeight()).isEqualTo(1000L); ++ assertThat(b.bindHeight()).isEqualTo(2000L); ++ epochs = new TreeMap<>(); ++ epochs.put(a.bindHeight(), a); ++ epochs.put(b.bindHeight(), b); ++ AerePqIdentity.uninstall(); ++ } ++ ++ @AfterEach ++ public void disarm() { ++ AerePqIdentity.uninstall(); ++ } ++ ++ private static byte[] key(final PqRegistryV3.Registry r, final int index, final String scheme) { ++ return r.rows().get(index).key(scheme).orElseThrow().publicKey(); ++ } ++ ++ private static Address id(final PqRegistryV3.Registry r, final int index) { ++ return Address.wrap(Bytes.wrap(r.rows().get(index).id())); ++ } ++ ++ private static Address ecdsa(final PqRegistryV3.Registry r, final int index) { ++ return Address.wrap(Bytes.wrap(r.rows().get(index).ecdsaAddress())); ++ } ++ ++ @Test ++ public void keysFromMustBeAnEpochBoundaryAtOrAboveTheIdentityHeight() { ++ assertThatThrownBy(() -> AerePqIdentity.install(new AerePqIdentity.Config(1000, epochs, 1999))) ++ .isInstanceOf(AerePqIdentity.IdentityException.class) ++ .hasMessageContaining("must be the bindHeight of a v3 epoch"); ++ assertThatThrownBy(() -> AerePqIdentity.install(new AerePqIdentity.Config(2000, epochs, 1000))) ++ .isInstanceOf(AerePqIdentity.IdentityException.class); ++ AerePqIdentity.install(new AerePqIdentity.Config(1000, epochs, 2000)); ++ assertThat(AerePqIdentity.installed().orElseThrow().keysFrom()).isEqualTo(2000L); ++ } ++ ++ @Test ++ public void belowHkNothingComesFromV3AndStage3aNeverDoes() { ++ AerePqIdentity.install(new AerePqIdentity.Config(1000, epochs, 2000)); ++ assertThat(AerePqIdentity.keysFromV3(1999)).isFalse(); ++ assertThat(AerePqIdentity.keysFromV3(2000)).isTrue(); ++ AerePqIdentity.install(new AerePqIdentity.Config(1000, epochs)); ++ assertThat(AerePqIdentity.keysFromV3(Long.MAX_VALUE - 1)).isFalse(); ++ AerePqIdentity.uninstall(); ++ assertThat(AerePqIdentity.keysFromV3(5000)).isFalse(); ++ } ++ ++ @Test ++ public void theKeyIsThatIndexOfTheEpochInForceAndTheRotationTakesOverAtItsEpoch() { ++ AerePqIdentity.install(new AerePqIdentity.Config(1000, epochs, 1000)); ++ final byte[] fa1 = AerePqIdentity.v3KeyAt(1999, 1, "falcon-512").orElseThrow(); ++ final byte[] fb1 = AerePqIdentity.v3KeyAt(2000, 1, "falcon-512").orElseThrow(); ++ // the registry form: 896 bytes, the 0x09 header dropped ++ assertThat(fa1).hasSize(896); ++ assertThat(fa1).isEqualTo(Arrays.copyOfRange(key(a, 1, "falcon-512"), 1, 897)); ++ assertThat(fb1).isEqualTo(Arrays.copyOfRange(key(b, 1, "falcon-512"), 1, 897)); ++ assertThat(fb1).isNotEqualTo(fa1); ++ final byte[] sa1 = AerePqIdentity.v3KeyAt(1999, 1, "slh-dsa-sha2-128s").orElseThrow(); ++ assertThat(sa1).hasSize(32).isEqualTo(key(a, 1, "slh-dsa-sha2-128s")); ++ assertThat(AerePqIdentity.v3KeyAt(2000, 1, "slh-dsa-sha2-128s").orElseThrow()) ++ .isEqualTo(key(b, 1, "slh-dsa-sha2-128s")) ++ .isNotEqualTo(sa1); ++ // indices belong to the epoch: at 2000 index 0 is the validator that was index 2 in epoch A ++ assertThat(AerePqIdentity.v3KeyAt(2000, 0, "falcon-512").orElseThrow()) ++ .isEqualTo(Arrays.copyOfRange(key(a, 2, "falcon-512"), 1, 897)); ++ assertThat(AerePqIdentity.v3IdAt(2000, 0)).contains(id(a, 2)); ++ assertThat(AerePqIdentity.v3IdAt(2000, 2)).contains(id(b, 2)); ++ // an index the epoch does not have: NO key (fail closed), never a fall-back ++ assertThat(AerePqIdentity.v3KeyAt(2000, 3, "falcon-512")).isEmpty(); ++ assertThat(AerePqIdentity.v3KeyAt(2000, -1, "falcon-512")).isEmpty(); ++ assertThat(AerePqIdentity.v3IdAt(2000, 3)).isEmpty(); ++ } ++ ++ @Test ++ public void theContinuityGuardAcceptsTheSameKeysAndRefusesAnyOther() { ++ AerePqIdentity.install(new AerePqIdentity.Config(1000, epochs, 1000)); ++ // the existing registries give exactly the keys of epoch A: accepted ++ AerePqIdentity.verifyKeyContinuity( ++ (i, s) -> AerePqIdentity.v3KeyAt(1000, i, s).map(byte[]::clone)); ++ // one byte of one SLH-DSA key differs: refused, naming the row and the scheme ++ assertThatThrownBy( ++ () -> ++ AerePqIdentity.verifyKeyContinuity( ++ (i, s) -> { ++ final byte[] k = AerePqIdentity.v3KeyAt(1000, i, s).orElseThrow().clone(); ++ if (i == 2 && s.equals("slh-dsa-sha2-128s")) { ++ k[5] ^= 1; ++ } ++ return Optional.of(k); ++ })) ++ .isInstanceOf(AerePqIdentity.IdentityException.class) ++ .hasMessageContaining("row 2 slh-dsa-sha2-128s differs"); ++ // a key the existing registries cannot produce: refused ++ assertThatThrownBy( ++ () -> ++ AerePqIdentity.verifyKeyContinuity( ++ (i, s) -> i == 0 ? Optional.empty() : AerePqIdentity.v3KeyAt(1000, i, s))) ++ .isInstanceOf(AerePqIdentity.IdentityException.class) ++ .hasMessageContaining("row 0"); ++ // no H_k configured: the guard is inert even with a function that has no keys at all ++ AerePqIdentity.install(new AerePqIdentity.Config(1000, epochs)); ++ AerePqIdentity.verifyKeyContinuity((i, s) -> Optional.empty()); ++ } ++ ++ @Test ++ public void theFalconSealSupportDoorsTakeTheirKeyAndIdFromV3FromHk() { ++ // the WIRING, not only the helper: FalconSealSupport.keyAt (behind every Falcon verification) and the index -> identity doors ++ // must answer from the v3 epoch in force from H_k. This node has no registry schedule at all, so any answer from H_k on can ++ // only come from v3; below H_k the doors fall back to the (absent) registries and answer nothing. ++ AerePqIdentity.install(new AerePqIdentity.Config(1000, epochs, 2000)); ++ final FalconSealSupport fs = FalconSealSupport.instance(); ++ assertThat(fs.publicKeyBytesAtHistoric(2000, 1)) ++ .contains(Arrays.copyOfRange(key(b, 1, "falcon-512"), 1, 897)); ++ assertThat(fs.publicKeyBytesAtHistoric(2000, 0)) ++ .contains(Arrays.copyOfRange(key(a, 2, "falcon-512"), 1, 897)); ++ assertThat(fs.publicKeyBytesAtHistoric(2000, 3)).isEmpty(); ++ assertThat(fs.addressForIndexAtHistoric(2000, 2)).isEqualTo(id(b, 2)); ++ assertThat(fs.addressForIndexAtOwnHead(2000, 0)).isEqualTo(id(a, 2)); ++ assertThat(fs.addressForIndexAtHistoric(2000, 3)).isNull(); ++ // below H_k: not from v3 (a v3 answer here would be the rotation taking effect early) ++ assertThat(fs.publicKeyBytesAtHistoric(1999, 1)) ++ .isNotEqualTo(Optional.of(Arrays.copyOfRange(key(a, 1, "falcon-512"), 1, 897))); ++ } ++ ++ @Test ++ public void anAuthorKeepsItsIdAcrossAnEpochWithoutLinksAndARemovedIdAuthorsNothing() { ++ AerePqIdentity.install(new AerePqIdentity.Config(1000, epochs, 1000)); ++ // epoch B carries no ecdsa links; the id of A's index 1 is still registered, so its address keeps it ++ assertThat(b.rows().get(1).ecdsaAddress()).isNull(); ++ assertThat(AerePqIdentity.author(ecdsa(a, 1), 1999)).isEqualTo(id(a, 1)); ++ assertThat(AerePqIdentity.author(ecdsa(a, 1), 2000)).isEqualTo(id(a, 1)); ++ assertThat(AerePqIdentity.author(ecdsa(a, 2), 2500)).isEqualTo(id(a, 2)); ++ // A's index 0 left in B: its address is itself again, which is not in the set ++ assertThat(AerePqIdentity.author(ecdsa(a, 0), 1999)).isEqualTo(id(a, 0)); ++ assertThat(AerePqIdentity.author(ecdsa(a, 0), 2000)).isEqualTo(ecdsa(a, 0)); ++ } ++} +diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/AereLocalKeysV3Test.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/AereLocalKeysV3Test.java +new file mode 100644 +index 0000000000..e67a5bf730 +--- /dev/null ++++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/AereLocalKeysV3Test.java +@@ -0,0 +1,164 @@ ++/* ++ * AERE AIP-22 stage 3b-ii: probes of the LOCAL keys by height - a node signs, from H_k, with the key of its own row in the v3 ++ * epoch in force and at that row's index - on two epochs built here with PROBA keys this test holds (the shared vectors carry no ++ * private keys): epoch A bound at 1000 (v0, v1, v2 at indices 0, 1, 2, the switch epoch) and epoch B bound at 2000 (v2 MOVED to ++ * index 0, v1 ROTATED both keys under its id at index 1 with the rotation signed by its old keys, v0 left, a new v3 at index 2). ++ * ++ * What must hold, each with its negative: a node finds its row by its key and the index moves with the epoch (a key that no row ++ * of the epoch carries finds nothing); the hybrid producer of a rotating node signs with its OLD key up to the rotation epoch and ++ * with its NEXT key from it, at the right index, each seal verifying under exactly one of the two keys; a moved node signs at its ++ * new index; and a node that lacks its rotated key produces nothing from the rotation epoch (the fact the startup guard refuses on). ++ */ ++package org.hyperledger.besu.consensus.common.bft; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++ ++import java.util.List; ++import java.util.Map; ++import java.util.Optional; ++import java.util.TreeMap; ++import java.util.function.LongToIntFunction; ++ ++import com.fasterxml.jackson.databind.node.ObjectNode; ++import org.apache.tuweni.bytes.Bytes; ++import org.junit.jupiter.api.AfterEach; ++import org.junit.jupiter.api.BeforeEach; ++import org.junit.jupiter.api.Test; ++ ++public class AereLocalKeysV3Test { ++ ++ private static final List SCHEMES = List.of("falcon-512", "slh-dsa-sha2-128s"); ++ private static final String SLH = "slh-dsa-sha2-128s"; ++ private PqRegistryV3Test.Proba v0; ++ private PqRegistryV3Test.Proba v1; ++ private PqRegistryV3Test.Proba v2; ++ private PqRegistryV3Test.Proba v1b; ++ private PqRegistryV3Test.Proba v3; ++ ++ @BeforeEach ++ public void build() { ++ v0 = PqRegistryV3Test.proba(); ++ v1 = PqRegistryV3Test.proba(); ++ v2 = PqRegistryV3Test.proba(); ++ v1b = PqRegistryV3Test.proba(); ++ v3 = PqRegistryV3Test.proba(); ++ final var d0 = new PqRegistryV3Test.Draft(PqRegistryV3.idOf(v0.falconStd()), PqRegistryV3Test.both(v0), v0); ++ final var d1 = new PqRegistryV3Test.Draft(PqRegistryV3.idOf(v1.falconStd()), PqRegistryV3Test.both(v1), v1); ++ final var d2 = new PqRegistryV3Test.Draft(PqRegistryV3.idOf(v2.falconStd()), PqRegistryV3Test.both(v2), v2); ++ final ObjectNode ma = ++ PqRegistryV3Test.manifest( ++ 1000, ++ List.of( ++ PqRegistryV3Test.rowJson(1000, 3, 0, d0, true, true), ++ PqRegistryV3Test.rowJson(1000, 3, 1, d1, true, false), ++ PqRegistryV3Test.rowJson(1000, 3, 2, d2, true, false))); ++ final PqRegistryV3.Registry a = PqRegistryV3.load(ma, PqRegistryV3Test.CHAIN, SCHEMES, null, true); ++ final var d1b = new PqRegistryV3Test.Draft(d1.id(), PqRegistryV3Test.both(v1b), v1); ++ final var d3 = new PqRegistryV3Test.Draft(PqRegistryV3.idOf(v3.falconStd()), PqRegistryV3Test.both(v3), v3); ++ final ObjectNode r1b = PqRegistryV3Test.rowJson(2000, 3, 1, d1b, false, false); ++ PqRegistryV3Test.rotate(r1b, 2000, 3, 1, List.of(v1.falcon(), v1.slh())); ++ final ObjectNode mb = ++ PqRegistryV3Test.manifest( ++ 2000, ++ List.of( ++ PqRegistryV3Test.rowJson(2000, 3, 0, d2, false, false), ++ r1b, ++ PqRegistryV3Test.rowJson(2000, 3, 2, d3, false, false))); ++ final PqRegistryV3.Registry b = PqRegistryV3.load(mb, PqRegistryV3Test.CHAIN, SCHEMES, a, false); ++ final TreeMap epochs = new TreeMap<>(); ++ epochs.put(1000L, a); ++ epochs.put(2000L, b); ++ AerePqIdentity.uninstall(); ++ AerePqIdentity.install(new AerePqIdentity.Config(1000, epochs, 1000)); ++ } ++ ++ @AfterEach ++ public void disarm() { ++ AerePqIdentity.uninstall(); ++ } ++ ++ private static byte[] falcon(final PqRegistryV3Test.Proba p) { ++ return p.falcon().publicRegistryForm(); ++ } ++ ++ /** The local index a node holding these Falcon keys signs as at a height (what FalconSealSupport.localAt resolves). */ ++ private static LongToIntFunction indexOf(final PqRegistryV3Test.Proba... keys) { ++ return h -> { ++ for (final PqRegistryV3Test.Proba k : keys) { ++ final Optional i = AerePqIdentity.v3IndexOfKey(h, "falcon-512", falcon(k)); ++ if (i.isPresent()) { ++ return i.get(); ++ } ++ } ++ return -1; ++ }; ++ } ++ ++ private static HybridSealProducer producer( ++ final PqRegistryV3Test.Proba base, final List next, final LongToIntFunction idx) { ++ return new HybridSealProducer( ++ 0L, ++ PqSchemeSchedule.parse("0:falcon-512+" + SLH), ++ -1, ++ Map.of(SLH, base.slh().privateKey()), ++ 0L, ++ next.isEmpty() ? Map.of() : Map.of(SLH, next.stream().map(p -> p.slh().privateKey()).toList()), ++ idx); ++ } ++ ++ private static boolean verifies(final SchemeSeal s, final PqRegistryV3Test.Proba key, final Bytes msg) { ++ return SealSchemes.SLH_DSA_128S.verifyRaw( ++ key.slh().publicRegistryForm(), msg.toArrayUnsafe(), s.getSignature().toArrayUnsafe()); ++ } ++ ++ @Test ++ public void aNodeFindsItsRowByItsKeyAndTheIndexMovesWithTheEpoch() { ++ assertThat(AerePqIdentity.v3IndexOfKey(1999, "falcon-512", falcon(v2))).contains(2); ++ assertThat(AerePqIdentity.v3IndexOfKey(2000, "falcon-512", falcon(v2))).contains(0); ++ assertThat(AerePqIdentity.v3IndexOfKey(1999, "falcon-512", falcon(v1))).contains(1); ++ assertThat(AerePqIdentity.v3IndexOfKey(2000, "falcon-512", falcon(v1))).isEmpty(); ++ assertThat(AerePqIdentity.v3IndexOfKey(2000, "falcon-512", falcon(v1b))).contains(1); ++ assertThat(AerePqIdentity.v3IndexOfKey(1999, "falcon-512", falcon(v1b))).isEmpty(); ++ assertThat(AerePqIdentity.v3IndexOfKey(2000, "falcon-512", falcon(v0))).isEmpty(); ++ } ++ ++ @Test ++ public void aRotatingNodeSignsWithItsOldKeyUpToTheRotationEpochAndItsNextKeyFromIt() { ++ final HybridSealProducer p = producer(v1, List.of(v1b), indexOf(v1, v1b)); ++ final Bytes msg = Bytes.wrap("AERE-TEST-COMMIT".getBytes(java.nio.charset.StandardCharsets.UTF_8)); ++ final List before = p.sealsFor(1999, msg); ++ assertThat(before).hasSize(1); ++ assertThat(before.get(0).getValidatorIndex()).isEqualTo(1); ++ assertThat(verifies(before.get(0), v1, msg)).isTrue(); ++ assertThat(verifies(before.get(0), v1b, msg)).isFalse(); ++ final List after = p.sealsFor(2000, msg); ++ assertThat(after).hasSize(1); ++ assertThat(after.get(0).getValidatorIndex()).isEqualTo(1); ++ assertThat(verifies(after.get(0), v1b, msg)).isTrue(); ++ assertThat(verifies(after.get(0), v1, msg)).isFalse(); ++ } ++ ++ @Test ++ public void aMovedNodeSignsAtItsNewIndex() { ++ final HybridSealProducer p = producer(v2, List.of(), indexOf(v2)); ++ final Bytes msg = Bytes.wrap("AERE-TEST-COMMIT".getBytes(java.nio.charset.StandardCharsets.UTF_8)); ++ assertThat(p.sealsFor(1999, msg).get(0).getValidatorIndex()).isEqualTo(2); ++ final List after = p.sealsFor(2000, msg); ++ assertThat(after.get(0).getValidatorIndex()).isEqualTo(0); ++ assertThat(verifies(after.get(0), v2, msg)).isTrue(); ++ } ++ ++ @Test ++ public void aNodeWithoutItsRotatedKeyProducesNothingFromTheRotationEpoch() { ++ final HybridSealProducer p = producer(v1, List.of(), indexOf(v1, v1b)); ++ final Bytes msg = Bytes.wrap("AERE-TEST-COMMIT".getBytes(java.nio.charset.StandardCharsets.UTF_8)); ++ assertThat(p.sealsFor(1999, msg)).hasSize(1); ++ // its Falcon index is resolvable only through v1b, which this node does not hold: nothing, and the guard's basis is empty ++ final HybridSealProducer onlyOld = producer(v1, List.of(), indexOf(v1)); ++ assertThat(onlyOld.sealsFor(2000, msg)).isEmpty(); ++ assertThat(onlyOld.v3KeyAt(SealSchemes.SLH_DSA_128S, 2000)).isEmpty(); ++ // holding the rotated Falcon key but not the rotated SLH-DSA key: the row's SLH key has no local match either ++ assertThat(p.v3KeyAt(SealSchemes.SLH_DSA_128S, 2000)).isEmpty(); ++ assertThat(p.sealsFor(2000, msg)).isEmpty(); ++ } ++} +diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/AerePqFinalityAuthorTest.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/AerePqFinalityAuthorTest.java +new file mode 100644 +index 0000000000..4b875f937b +--- /dev/null ++++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/AerePqFinalityAuthorTest.java +@@ -0,0 +1,243 @@ ++/* ++ * Copyright contributors to Besu / AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.consensus.common.bft; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++import static org.assertj.core.api.Assertions.assertThatThrownBy; ++ ++import org.hyperledger.besu.consensus.common.bft.payload.Payload; ++import org.hyperledger.besu.consensus.common.bft.payload.SignedData; ++import org.hyperledger.besu.crypto.Hash; ++import org.hyperledger.besu.crypto.KeyPair; ++import org.hyperledger.besu.crypto.SignatureAlgorithm; ++import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.ethereum.core.Util; ++import org.hyperledger.besu.ethereum.rlp.RLPOutput; ++ ++import java.io.IOException; ++import java.io.InputStream; ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Optional; ++import java.util.TreeMap; ++ ++import com.fasterxml.jackson.databind.JsonNode; ++import com.fasterxml.jackson.databind.ObjectMapper; ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.bytes.Bytes32; ++import org.junit.jupiter.api.AfterEach; ++import org.junit.jupiter.api.BeforeEach; ++import org.junit.jupiter.api.Test; ++ ++/** ++ * AIP-22 stage 4 (iii): from H_fin the author of a message is the id of its post-quantum seal's index, ++ * ONCE THE SEAL VERIFIES, and the ECDSA signature of the envelope is not read. Every message here is ++ * signed by a FOREIGN key (not any validator's), so a validator's id can only come from the seal. The ++ * verifier is injected with the seal layers' contract (height, index, message, signature): it accepts ++ * exactly the signature {@code keccak(index || message)}, so a seal of another index, over another ++ * message, or of any other bytes does not verify. A COMMIT's author is its index's id only when that is ++ * the commit seal signer's id. Below H_fin, and with H_fin unset, the author is the (translated) ECDSA ++ * signer, as in stage 3. The runner's negative controls plant "H_fin never active" and "every seal ++ * verifies" at run time and these probes turn red. ++ */ ++public class AerePqFinalityAuthorTest { ++ ++ private static final SignatureAlgorithm ALG = SignatureAlgorithmFactory.getInstance(); ++ private static final long CHAIN = 28001L; ++ private static final AerePqFinality.SealVerifier V = ++ (h, i, m, s) -> s.equals(sigFor(i, m)); ++ ++ private long hId; ++ private final List
    id = new ArrayList<>(); ++ private final List
    ecdsa = new ArrayList<>(); ++ private final KeyPair foreign = ALG.generateKeyPair(); ++ ++ private static Bytes sigFor(final int index, final Bytes message) { ++ // the index as its 32 bits (a negative index has a signature too, it just names no row) ++ return Hash.keccak256(Bytes.concatenate(Bytes.ofUnsignedLong(Integer.toUnsignedLong(index)), message)); ++ } ++ ++ private static Bytes32 messageAt(final long height) { ++ return Hash.keccak256(Bytes.concatenate(Bytes.wrap("t4-msg".getBytes(java.nio.charset.StandardCharsets.US_ASCII)), Bytes.ofUnsignedLong(height))); ++ } ++ ++ /** A PREPARE-like payload: its seal signs {@link #messageAt}(height); a COMMIT-like one names a commit seal signer. */ ++ private static final class Sealed implements Payload, PqSealed { ++ private final long height; ++ private final Optional seal; ++ private final Optional
    commitSigner; ++ private final boolean messageThrows; ++ ++ Sealed(final long height, final Optional seal, final Optional
    commitSigner, final boolean messageThrows) { ++ this.height = height; ++ this.seal = seal; ++ this.commitSigner = commitSigner; ++ this.messageThrows = messageThrows; ++ } ++ ++ @Override ++ public void writeTo(final RLPOutput out) { ++ out.startList(); ++ out.writeLongScalar(height); ++ out.endList(); ++ } ++ ++ @Override ++ public int getMessageType() { ++ return 0x12; ++ } ++ ++ @Override ++ public org.hyperledger.besu.datatypes.Hash hashForSignature() { ++ return org.hyperledger.besu.datatypes.Hash.hash(Bytes.ofUnsignedLong(height)); ++ } ++ ++ @Override ++ public ConsensusRoundIdentifier getRoundIdentifier() { ++ return new ConsensusRoundIdentifier(height, 0); ++ } ++ ++ @Override ++ public Optional getFalconSeal() { ++ return seal; ++ } ++ ++ @Override ++ public Optional pqSealMessage(final long chainId) { ++ if (messageThrows) { ++ throw new IllegalArgumentException("cannot build"); ++ } ++ return commitSigner.isPresent() || chainId != CHAIN ? Optional.empty() : Optional.of(messageAt(height)); ++ } ++ ++ @Override ++ public Optional
    commitSealSigner() { ++ return commitSigner; ++ } ++ } ++ ++ private Address signed(final Sealed p) { ++ return SignedData.create(p, ALG.sign(Bytes32.wrap(p.hashForSignature().getBytes()), foreign)).getAuthor(); ++ } ++ ++ private static Sealed prepare(final long height, final Optional seal) { ++ return new Sealed(height, seal, Optional.empty(), false); ++ } ++ ++ /** A seal of index {@code index} that verifies over the message of {@code signedHeight}. */ ++ private static Optional good(final int index, final long signedHeight) { ++ return Optional.of(new FalconSeal(index, sigFor(index, messageAt(signedHeight)))); ++ } ++ ++ @BeforeEach ++ public void arm() throws IOException { ++ final JsonNode v; ++ try (InputStream in = getClass().getResourceAsStream("/aere/registry-v3/ok-epoch-a.json")) { ++ assertThat(in).isNotNull(); ++ v = new ObjectMapper().readTree(in); ++ } ++ final PqRegistryV3.Registry epoch = ++ PqRegistryV3.load( ++ v.get("manifest"), v.get("chainId").asLong(), ++ List.of("falcon-512", "slh-dsa-sha2-128s"), null, true); ++ for (final PqRegistryV3.Row r : epoch.rows()) { ++ id.add(Address.wrap(Bytes.wrap(r.id()))); ++ ecdsa.add(Address.wrap(Bytes.wrap(r.ecdsaAddress()))); ++ } ++ hId = epoch.bindHeight(); ++ final TreeMap epochs = new TreeMap<>(); ++ epochs.put(hId, epoch); ++ AerePqFinality.uninstall(); ++ AerePqIdentity.uninstall(); ++ AerePqIdentity.install(new AerePqIdentity.Config(hId, epochs, hId)); ++ } ++ ++ @AfterEach ++ public void disarm() { ++ AerePqFinality.uninstall(); ++ AerePqIdentity.uninstall(); ++ } ++ ++ @Test ++ public void fromHfinTheAuthorIsTheIdOfAVerifiedSealWhateverKeySignedTheEnvelope() { ++ final long hFin = hId + 100; ++ AerePqFinality.install(hFin, CHAIN, V); ++ final Address foreignAddr = Util.publicKeyToAddress(foreign.getPublicKey()); ++ assertThat(id).doesNotContain(foreignAddr); ++ for (int i = 0; i < id.size(); i++) { ++ assertThat(signed(prepare(hFin, good(i, hFin)))).as("index %s at H_fin", i).isEqualTo(id.get(i)); ++ assertThat(signed(prepare(hFin + 500, good(i, hFin + 500)))).isEqualTo(id.get(i)); ++ } ++ // one block below H_fin the envelope's signer is still the author: a foreign key authors nothing of the set ++ assertThat(signed(prepare(hFin - 1, good(0, hFin - 1)))).isEqualTo(foreignAddr); ++ } ++ ++ @Test ++ public void fromHfinASealThatDoesNotVerifyAuthorsNothing() { ++ final long hFin = hId + 100; ++ AerePqFinality.install(hFin, CHAIN, V); ++ // the fixture can express the defect: the same index with its own seal IS an author ++ assertThat(signed(prepare(hFin, good(0, hFin)))).isEqualTo(id.get(0)); ++ // index 0 carrying index 1's seal ++ assertThat(signed(prepare(hFin, Optional.of(new FalconSeal(0, sigFor(1, messageAt(hFin))))))) ++ .isEqualTo(AerePqFinality.NO_AUTHOR); ++ // index 0's seal over another height's message ++ assertThat(signed(prepare(hFin, good(0, hFin + 1)))).isEqualTo(AerePqFinality.NO_AUTHOR); ++ // any other bytes ++ assertThat(signed(prepare(hFin, Optional.of(new FalconSeal(0, Bytes.of(1, 2, 3)))))) ++ .isEqualTo(AerePqFinality.NO_AUTHOR); ++ // no seal, an index outside the epoch, a negative index, a message that cannot be built ++ assertThat(signed(prepare(hFin, Optional.empty()))).isEqualTo(AerePqFinality.NO_AUTHOR); ++ assertThat(signed(prepare(hFin, good(id.size(), hFin)))).isEqualTo(AerePqFinality.NO_AUTHOR); ++ assertThat(signed(prepare(hFin, good(-1, hFin)))).isEqualTo(AerePqFinality.NO_AUTHOR); ++ assertThat(signed(new Sealed(hFin, good(0, hFin), Optional.empty(), true))) ++ .isEqualTo(AerePqFinality.NO_AUTHOR); ++ } ++ ++ @Test ++ public void fromHfinACommitsAuthorIsItsIndexOnlyWhenThatIsTheCommitSealSigner() { ++ final long hFin = hId + 100; ++ AerePqFinality.install(hFin, CHAIN, V); ++ final Optional anySeal = Optional.of(new FalconSeal(0, Bytes.of(9))); ++ assertThat(signed(new Sealed(hFin, anySeal, Optional.of(ecdsa.get(0)), false))).isEqualTo(id.get(0)); ++ assertThat(signed(new Sealed(hFin, anySeal, Optional.of(ecdsa.get(1)), false))) ++ .isEqualTo(AerePqFinality.NO_AUTHOR); ++ assertThat( ++ signed( ++ new Sealed( ++ hFin, anySeal, Optional.of(Util.publicKeyToAddress(foreign.getPublicKey())), false))) ++ .isEqualTo(AerePqFinality.NO_AUTHOR); ++ assertThat(signed(new Sealed(hFin, Optional.empty(), Optional.of(ecdsa.get(0)), false))) ++ .isEqualTo(AerePqFinality.NO_AUTHOR); ++ } ++ ++ @Test ++ public void unsetHfinLeavesTheEcdsaSignerAsTheAuthorAndHfinNeedsKeysFromV3AndAChain() { ++ final Address foreignAddr = Util.publicKeyToAddress(foreign.getPublicKey()); ++ assertThat(signed(prepare(hId + 100, good(0, hId + 100)))).isEqualTo(foreignAddr); ++ // H_fin below H_k, without a chain id, or without keys read from the v3 epochs refuses to arm ++ assertThatThrownBy(() -> AerePqFinality.install(hId - 1, CHAIN, V)) ++ .isInstanceOf(IllegalStateException.class) ++ .hasMessageStartingWith("AERE-PQC-FIN-01"); ++ assertThatThrownBy(() -> AerePqFinality.install(hId + 100, 0, V)) ++ .isInstanceOf(IllegalStateException.class) ++ .hasMessageStartingWith("AERE-PQC-FIN-01"); ++ AerePqIdentity.uninstall(); ++ assertThatThrownBy(() -> AerePqFinality.install(hId + 100, CHAIN, V)) ++ .isInstanceOf(IllegalStateException.class) ++ .hasMessageStartingWith("AERE-PQC-FIN-01"); ++ } ++} +diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/AerePqFinalityTagsTest.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/AerePqFinalityTagsTest.java +new file mode 100755 +index 0000000000..f171b392e0 +--- /dev/null ++++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/AerePqFinalityTagsTest.java +@@ -0,0 +1,235 @@ ++/* ++ * Copyright contributors to Besu / AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.consensus.common.bft; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++import static org.mockito.ArgumentMatchers.any; ++import static org.mockito.ArgumentMatchers.anyLong; ++import static org.mockito.Mockito.mock; ++import static org.mockito.Mockito.never; ++import static org.mockito.Mockito.times; ++import static org.mockito.Mockito.verify; ++import static org.mockito.Mockito.when; ++ ++import org.hyperledger.besu.datatypes.Hash; ++import org.hyperledger.besu.ethereum.chain.BlockAddedEvent; ++import org.hyperledger.besu.ethereum.chain.MutableBlockchain; ++import org.hyperledger.besu.ethereum.core.BlockHeader; ++import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; ++import org.hyperledger.besu.plugin.data.AddedBlockContext.EventType; ++ ++import java.util.Collections; ++import java.util.HashMap; ++import java.util.HashSet; ++import java.util.List; ++import java.util.Map; ++import java.util.Optional; ++import java.util.OptionalInt; ++import java.util.Set; ++ ++import org.apache.tuweni.bytes.Bytes; ++ ++import org.junit.jupiter.api.BeforeEach; ++import org.junit.jupiter.api.Test; ++ ++/** ++ * AERE D-412 Rule B1: finalized/safe follow the last certified anchor's parent, monotonically, and a ++ * forged between-anchor block can never be reported final. Anchors every 32 from 96 (K=3); the ++ * certificate predicate is a set of heights that "carry" one, so a planted defect in the rule (an ++ * anchor without certificate moving the tag, a lower height moving it back, a non-anchor moving it) ++ * turns exactly one of these red. ++ */ ++class AerePqFinalityTagsTest { ++ ++ private static final long ANCHOR_BLOCK = 96L; ++ private static final int INTERVAL = 32; ++ ++ private PqAnchorConfig config; ++ private MutableBlockchain blockchain; ++ private final Map byNumber = new HashMap<>(); ++ private final Map byHash = new HashMap<>(); ++ private final Set certified = new HashSet<>(); ++ ++ @BeforeEach ++ void setUp() { ++ config = ++ new PqAnchorConfig(2800L, ANCHOR_BLOCK, Map.of(ANCHOR_BLOCK, 3), OptionalInt.empty(), false) ++ .withAnchorInterval(OptionalInt.of(INTERVAL)); ++ blockchain = mock(MutableBlockchain.class); ++ // a linear chain 0..200 with deterministic hashes; header(n).parentHash == hash(header(n-1)) ++ Hash prev = Hash.ZERO; ++ for (long n = 0; n <= 200; n++) { ++ final BlockHeader h = new BlockHeaderTestFixture().number(n).parentHash(prev).buildHeader(); ++ byNumber.put(n, h); ++ byHash.put(h.getHash(), h); ++ prev = h.getHash(); ++ } ++ when(blockchain.getBlockHeader(anyLong())).thenAnswer(i -> Optional.ofNullable(byNumber.get(i.getArgument(0, Long.class)))); ++ when(blockchain.getBlockHeader(any(Hash.class))).thenAnswer(i -> Optional.ofNullable(byHash.get(i.getArgument(0, Hash.class)))); ++ } ++ ++ private AerePqFinalityTags tagsWithHead(final long head) { ++ when(blockchain.getChainHeadHeader()).thenReturn(byNumber.get(head)); ++ return AerePqFinalityTags.install(config, blockchain, h -> certified.contains(h.getNumber())); ++ } ++ ++ private BlockAddedEvent headAdvanced(final long n) { ++ final BlockAddedEvent e = mock(BlockAddedEvent.class); ++ when(e.isNewCanonicalHead()).thenReturn(true); ++ when(e.getHeader()).thenReturn(byNumber.get(n)); ++ when(e.getEventType()).thenReturn(EventType.HEAD_ADVANCED); ++ return e; ++ } ++ ++ private BlockAddedEvent reorgTo(final long n, final long commonAncestor) { ++ final BlockAddedEvent e = mock(BlockAddedEvent.class); ++ when(e.isNewCanonicalHead()).thenReturn(true); ++ when(e.getHeader()).thenReturn(byNumber.get(n)); ++ when(e.getEventType()).thenReturn(EventType.CHAIN_REORG); ++ when(e.getCommonAncestorHash()).thenReturn(byNumber.get(commonAncestor).getHash()); ++ return e; ++ } ++ ++ @Test ++ void theConfigurationUnderTestHasAnchorsEveryThirtyTwoFromNinetySix() { ++ assertThat(config.anchorAppliesAt(96)).isTrue(); ++ assertThat(config.anchorAppliesAt(128)).isTrue(); ++ assertThat(config.anchorAppliesAt(129)).isFalse(); ++ assertThat(config.anchorAppliesAt(95)).isFalse(); ++ } ++ ++ @Test ++ void startupScanFinalizesTheParentOfTheLastCertifiedAnchorBelowTheHead() { ++ certified.add(96L); ++ certified.add(128L); ++ final AerePqFinalityTags tags = tagsWithHead(140); ++ verify(blockchain, times(1)).setFinalized(byNumber.get(127L).getHash()); ++ verify(blockchain, times(1)).setSafeBlock(byNumber.get(127L).getHash()); ++ assertThat(tags.finalizedNumber()).isEqualTo(127L); ++ } ++ ++ @Test ++ void startupWithNoCertifiedAnchorInTwoIntervalsSetsNothing() { ++ final AerePqFinalityTags tags = tagsWithHead(140); // 96 and 128 are anchor heights, none certified ++ verify(blockchain, never()).setFinalized(any()); ++ assertThat(tags.finalizedNumber()).isEqualTo(-1L); ++ } ++ ++ @Test ++ void aCertifiedAnchorAtTheHeadFinalizesItsParent() { ++ certified.add(96L); ++ final AerePqFinalityTags tags = tagsWithHead(100); // finalized 95 ++ certified.add(128L); ++ tags.onBlockAdded(headAdvanced(128)); ++ verify(blockchain).setFinalized(byNumber.get(127L).getHash()); ++ verify(blockchain).setSafeBlock(byNumber.get(127L).getHash()); ++ assertThat(tags.finalizedNumber()).isEqualTo(127L); ++ } ++ ++ @Test ++ void aBetweenAnchorHeadNeverMovesTheTags_thisIsWhatKeepsAForgedTailOutOfFinalized() { ++ certified.add(96L); ++ final AerePqFinalityTags tags = tagsWithHead(100); ++ for (long n = 101; n < 128; n++) { ++ certified.add(n); // even if a between-anchor header somehow "carried" a certificate ++ tags.onBlockAdded(headAdvanced(n)); ++ } ++ verify(blockchain, times(1)).setFinalized(any()); // only the startup one (95) ++ assertThat(tags.finalizedNumber()).isEqualTo(95L); ++ } ++ ++ @Test ++ void anAnchorHeightWithoutACertificateDoesNotMoveTheTags() { ++ certified.add(96L); ++ final AerePqFinalityTags tags = tagsWithHead(100); ++ tags.onBlockAdded(headAdvanced(128)); // 128 not certified ++ verify(blockchain, times(1)).setFinalized(any()); ++ assertThat(tags.finalizedNumber()).isEqualTo(95L); ++ } ++ ++ @Test ++ void theTagsAreMonotonic_aLowerCertifiedAnchorNeverMovesThemBack() { ++ certified.add(96L); ++ certified.add(128L); ++ final AerePqFinalityTags tags = tagsWithHead(140); // finalized 127 ++ tags.onBlockAdded(headAdvanced(96)); // certified, but lower ++ verify(blockchain, times(1)).setFinalized(any()); ++ assertThat(tags.finalizedNumber()).isEqualTo(127L); ++ } ++ ++ @Test ++ void aReorgBelowTheFinalizedBlockIsNotFollowedBackwards() { ++ certified.add(96L); ++ certified.add(128L); ++ final AerePqFinalityTags tags = tagsWithHead(140); // finalized 127 ++ tags.onBlockAdded(reorgTo(130, 100)); // common ancestor 100 < 127: logged, not moved ++ verify(blockchain, times(1)).setFinalized(any()); ++ assertThat(tags.finalizedNumber()).isEqualTo(127L); ++ } ++ ++ @Test ++ void aNonCanonicalEventIsIgnored() { ++ certified.add(96L); ++ certified.add(128L); ++ final AerePqFinalityTags tags = tagsWithHead(100); // finalized 95 ++ final BlockAddedEvent fork = mock(BlockAddedEvent.class); ++ when(fork.isNewCanonicalHead()).thenReturn(false); ++ when(fork.getHeader()).thenReturn(byNumber.get(128L)); ++ tags.onBlockAdded(fork); ++ assertThat(tags.finalizedNumber()).isEqualTo(95L); ++ } ++ ++ @Test ++ void headersAreLinkedByParentHashInTheFixture() { ++ assertThat(byNumber.get(128L).getParentHash()).isEqualTo(byNumber.get(127L).getHash()); ++ assertThat(byNumber.get(127L).getHash().size()).isEqualTo(32); ++ } ++ ++ // --- the certificate predicate: the controller feeds carriesCertificate(decode(header)) into install(), ++ // so it decides which anchors move the tags. On a stage-5 chain the certificate is the v2 (hybrid) list ++ // and getFalconSeals() is empty; a predicate that read only the v1 list never fired (rep28098 rehearsal, ++ // 2026-09-26). These three cases are the control that both fields are read. ++ ++ private static BftExtraData extraWith(final List v1, final List v2) { ++ return new BftExtraData( ++ Bytes.EMPTY, Collections.emptyList(), Optional.empty(), 0, Collections.emptyList(), v1, v2); ++ } ++ ++ @Test ++ void carriesCertificate_trueForAV1FalconList() { ++ assertThat( ++ AerePqFinalityTags.carriesCertificate( ++ extraWith(List.of(new FalconSeal(0, Bytes.of(1, 2, 3))), Collections.emptyList()))) ++ .isTrue(); ++ } ++ ++ @Test ++ void carriesCertificate_trueForAV2HybridCertificate_thisIsTheStage5AnchorThatWasBeingMissed() { ++ assertThat( ++ AerePqFinalityTags.carriesCertificate( ++ extraWith( ++ Collections.emptyList(), ++ List.of(new SchemeSeal((byte) 1, 0, Bytes.of(1, 2, 3)))))) ++ .isTrue(); ++ } ++ ++ @Test ++ void carriesCertificate_falseWhenNeitherListIsPresent() { ++ assertThat( ++ AerePqFinalityTags.carriesCertificate( ++ extraWith(Collections.emptyList(), Collections.emptyList()))) ++ .isFalse(); ++ } ++} +diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/AerePqIdentityTest.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/AerePqIdentityTest.java +new file mode 100644 +index 0000000000..a375f42609 +--- /dev/null ++++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/AerePqIdentityTest.java +@@ -0,0 +1,135 @@ ++/* ++ * AERE AIP-22 stage 3: probes of the identity translation (AerePqIdentity), on the registry v3 ++ * conformance vector ok-epoch-a (three rows, each with its ecdsa link, row 0 with a transport). ++ * ++ * What must hold, each with its negative: disarmed, every function is the identity (the build that ++ * carries the class and is never configured is byte for byte the old one); armed, an address becomes ++ * its id exactly from H_id and not one block earlier; an address without a row stays itself (so its ++ * message is simply not in the set); the set after H_id - 1 becomes the sorted ids and a member ++ * without a row REFUSES instead of being dropped; the local node is recognised in both forms and only ++ * its own; ids reach peers through their transport, and an id with no transport means "every peer". ++ */ ++package org.hyperledger.besu.consensus.common.bft; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++import static org.assertj.core.api.Assertions.assertThatThrownBy; ++ ++import org.hyperledger.besu.datatypes.Address; ++ ++import java.io.IOException; ++import java.io.InputStream; ++import java.util.ArrayList; ++import java.util.Collection; ++import java.util.List; ++import java.util.Optional; ++import java.util.TreeMap; ++ ++import com.fasterxml.jackson.databind.JsonNode; ++import com.fasterxml.jackson.databind.ObjectMapper; ++import org.apache.tuweni.bytes.Bytes; ++import org.junit.jupiter.api.AfterEach; ++import org.junit.jupiter.api.BeforeEach; ++import org.junit.jupiter.api.Test; ++ ++public class AerePqIdentityTest { ++ ++ private static final long H_ID = 1500; ++ private PqRegistryV3.Registry epoch; ++ private final List
    addr = new ArrayList<>(); ++ private final List
    id = new ArrayList<>(); ++ ++ @BeforeEach ++ public void armOnTheVector() throws IOException { ++ final JsonNode v; ++ try (InputStream in = getClass().getResourceAsStream("/aere/registry-v3/ok-epoch-a.json")) { ++ assertThat(in).isNotNull(); ++ v = new ObjectMapper().readTree(in); ++ } ++ epoch = ++ PqRegistryV3.load( ++ v.get("manifest"), v.get("chainId").asLong(), ++ List.of("falcon-512", "slh-dsa-sha2-128s"), null, true); ++ for (final PqRegistryV3.Row r : epoch.rows()) { ++ addr.add(Address.wrap(Bytes.wrap(r.ecdsaAddress()))); ++ id.add(Address.wrap(Bytes.wrap(r.id()))); ++ } ++ final TreeMap epochs = new TreeMap<>(); ++ epochs.put(epoch.bindHeight(), epoch); ++ AerePqIdentity.uninstall(); ++ assertThat(epoch.bindHeight()).isLessThanOrEqualTo(H_ID); ++ AerePqIdentity.install(new AerePqIdentity.Config(H_ID, epochs)); ++ } ++ ++ @AfterEach ++ public void disarm() { ++ AerePqIdentity.uninstall(); ++ } ++ ++ @Test ++ public void disarmedEverythingIsTheIdentity() { ++ AerePqIdentity.uninstall(); ++ assertThat(AerePqIdentity.author(addr.get(0), H_ID + 10)).isEqualTo(addr.get(0)); ++ final Collection
    set = new java.util.TreeSet<>(addr); ++ assertThat(AerePqIdentity.translateSetAfter(set, H_ID - 1)).isSameAs(set); ++ assertThat(AerePqIdentity.isLocal(id.get(0), addr.get(0))).isFalse(); ++ assertThat(AerePqIdentity.transportTargets(addr)).contains(addr); ++ } ++ ++ @Test ++ public void anAddressBecomesItsIdExactlyFromHid() { ++ assertThat(AerePqIdentity.author(addr.get(1), H_ID - 1)).isEqualTo(addr.get(1)); ++ assertThat(AerePqIdentity.author(addr.get(1), H_ID)).isEqualTo(id.get(1)); ++ assertThat(AerePqIdentity.author(addr.get(2), H_ID + 1000)).isEqualTo(id.get(2)); ++ // an address the registry does not link stays itself: its message is then not in the set ++ final Address stranger = Address.fromHexString("0x00000000000000000000000000000000000000aa"); ++ assertThat(AerePqIdentity.author(stranger, H_ID + 5)).isEqualTo(stranger); ++ } ++ ++ @Test ++ public void theSetAfterHidMinusOneBecomesTheSortedIdsAndNowhereElse() { ++ final Collection
    set = new java.util.TreeSet<>(addr); ++ assertThat(AerePqIdentity.translateSetAfter(set, H_ID - 2)).isSameAs(set); ++ assertThat(AerePqIdentity.translateSetAfter(set, H_ID)).isSameAs(set); ++ final Collection
    t = AerePqIdentity.translateSetAfter(set, H_ID - 1); ++ assertThat(t).containsExactlyElementsOf(new java.util.TreeSet<>(id)); ++ } ++ ++ @Test ++ public void aMemberWithoutARowRefusesInsteadOfBeingDropped() { ++ final Collection
    set = new java.util.TreeSet<>(addr); ++ set.add(Address.fromHexString("0x00000000000000000000000000000000000000bb")); ++ assertThatThrownBy(() -> AerePqIdentity.translateSetAfter(set, H_ID - 1)) ++ .isInstanceOf(AerePqIdentity.IdentityException.class) ++ .hasMessageContaining("has no row"); ++ } ++ ++ @Test ++ public void theLocalNodeIsRecognisedInBothFormsAndOnlyItsOwn() { ++ assertThat(AerePqIdentity.isLocal(addr.get(0), addr.get(0))).isTrue(); ++ assertThat(AerePqIdentity.isLocal(id.get(0), addr.get(0))).isTrue(); ++ assertThat(AerePqIdentity.isLocal(id.get(1), addr.get(0))).isFalse(); ++ assertThat(AerePqIdentity.local(addr.get(0), H_ID - 1)).isEqualTo(addr.get(0)); ++ assertThat(AerePqIdentity.local(addr.get(0), H_ID)).isEqualTo(id.get(0)); ++ } ++ ++ @Test ++ public void idsReachPeersThroughTheirTransportOrEveryPeer() { ++ final byte[] t0 = epoch.rows().get(0).transport(); ++ assertThat(t0).isNotNull(); ++ assertThat(AerePqIdentity.transportTargets(List.of(id.get(0)))) ++ .contains(List.of(Address.wrap(Bytes.wrap(t0)))); ++ assertThat(epoch.rows().get(1).transport()).isNull(); ++ assertThat(AerePqIdentity.transportTargets(List.of(id.get(0), id.get(1)))).isEqualTo(Optional.empty()); ++ // below H_id the recipients are addresses and go out as before ++ assertThat(AerePqIdentity.transportTargets(addr)).contains(addr); ++ } ++ ++ @Test ++ public void anIdentityHeightWithNoEpochAtOrBelowItRefusesToArm() { ++ final TreeMap epochs = new TreeMap<>(); ++ epochs.put(epoch.bindHeight(), epoch); ++ assertThatThrownBy( ++ () -> AerePqIdentity.install(new AerePqIdentity.Config(epoch.bindHeight() - 1, epochs))) ++ .isInstanceOf(AerePqIdentity.IdentityException.class); ++ } ++} +diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/HybridSealProducerTest.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/HybridSealProducerTest.java +index 5569abeb7b..6dfa922ba4 100755 +--- a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/HybridSealProducerTest.java ++++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/HybridSealProducerTest.java +@@ -75,40 +75,69 @@ class HybridSealProducerTest { + @Test + void theGateAloneSuppressesEmissionEvenWhenTheScheduleDemandsIt() { + final HybridSealProducer poartaInchisa = + new HybridSealProducer( + H_HIBRID + 100, + orar, + INDEX, + Map.of(SealSchemes.SLH_DSA_128S.id(), slh.privateKey())); + assertThat(poartaInchisa.sealsFor(H_HIBRID, MESSAGE)).isEmpty(); + assertThat(poartaInchisa.sealsFor(H_HIBRID + 100, MESSAGE)).hasSize(1); + } + + @Test + void atTheHybridStepTheExtraSealIsProduced() { + final List seals = producator().sealsFor(H_HIBRID, MESSAGE); + assertThat(seals).hasSize(1); + assertThat(seals.get(0).getSchemeWireId()).isEqualTo(SealSchemes.SLH_DSA_128S.wireId()); + assertThat(seals.get(0).getValidatorIndex()).isEqualTo(INDEX); + } + ++ // ------------------------------------------- intervale per schema (AIP-22 treapta 2) ++ ++ /** ++ * With SLH-DSA on the 128 grid and the anchor grids counted from H0 = 64, the producer signs the ++ * SLH-DSA seal only at the parent of an anchor on that grid; at the parent of a Falcon-only ++ * anchor (32 grid) it emits nothing, although the key is there and the gate is open. The two ++ * heights differ in nothing but the grid, which is the only thing this proof is about. ++ */ ++ @Test ++ void theSlhDsaSealIsProducedOnlyAtParentsOfAnchorsOnItsOwnGrid() { ++ final long h0 = 64L; ++ final PqSchemeSchedule cuIntervale = ++ PqSchemeSchedule.parse( ++ "0:" + SealSchemes.FALCON_512.id() + "/32+" + SealSchemes.SLH_DSA_128S.id() + "/128"); ++ final HybridSealProducer p = ++ new HybridSealProducer( ++ H_ATASARE, cuIntervale, INDEX, Map.of(SealSchemes.SLH_DSA_128S.id(), slh.privateKey()), h0); ++ final long ancoraHibrida = h0 + 128L * 10; // 1344: pe grila 128 ++ final long ancoraDoarFalcon = ancoraHibrida + 32L; // 1376: pe grila 32, nu pe 128 ++ assertThat(p.sealsFor(ancoraHibrida - 1, MESSAGE)).hasSize(1); ++ assertThat(p.sealsFor(ancoraDoarFalcon - 1, MESSAGE)).isEmpty(); ++ // the negative control of the grid origin: the same heights read against another origin flip ++ final HybridSealProducer altaOrigine = ++ new HybridSealProducer( ++ H_ATASARE, cuIntervale, INDEX, Map.of(SealSchemes.SLH_DSA_128S.id(), slh.privateKey()), h0 + 32); ++ assertThat(altaOrigine.sealsFor(ancoraHibrida - 1, MESSAGE)).isEmpty(); ++ assertThat(altaOrigine.sealsFor(ancoraDoarFalcon - 1, MESSAGE)).hasSize(1); ++ } ++ + // ---------------------------------------------------------------- jumatatea de certificat + + @Test + void aMissingKeyEmitsNothingAtAllRatherThanAStubCertificate() { + final HybridSealProducer withoutKey = + new HybridSealProducer(H_ATASARE, orar, INDEX, Map.of()); + assertThat(withoutKey.sealsFor(H_HIBRID, MESSAGE)).isEmpty(); + } + + @Test + void aNullMessageIsRefusedWithoutThrowing() { + assertThat(producator().sealsFor(H_HIBRID, null)).isEmpty(); + } + + // ---------------------------------------------------------------- dus-intorsul cheii + + @Test + void theSlhDsaPrivateKeySurvivesSerializationAndStillSigns() { + final byte[] encoded = + SealSchemes.SLH_DSA_128S.serializePrivateKey(slh.privateKey()).orElseThrow(); +diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/HybridSignerRegistryTest.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/HybridSignerRegistryTest.java +index 87bca049e7..e2e7be5948 100755 +--- a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/HybridSignerRegistryTest.java ++++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/HybridSignerRegistryTest.java +@@ -117,64 +117,64 @@ class HybridSignerRegistryTest { + p.setProperty( + "7.key." + FALCON, + Bytes.wrap(SealSchemes.FALCON_512.generate(random).publicRegistryForm()).toHexString()); + assertThatThrownBy(() -> HybridSignerRegistry.fromProperties(p, "test")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("beyond count"); + } + + @Test + void wrongFormatVersionRefuses() { + final Properties p = sanatos(); + p.setProperty("formatVersion", "hybrid-9"); + assertThatThrownBy(() -> HybridSignerRegistry.fromProperties(p, "test")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("hybrid-1"); + } + + @Test + void unrecognisedEntryRefuses() { + final Properties p = sanatos(); +- p.setProperty("1.cheie", "0x1234"); // aproape corect, dar nu e nici addr nici key. ++ p.setProperty("1.cheie", "0x1234"); // almost right, but it is neither addr nor key. + assertThatThrownBy(() -> HybridSignerRegistry.fromProperties(p, "test")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("unrecognised"); + } + + // ------------------------------------------------------------------ the canonical hash + + @Test + void hashIsDeterministicAndMovesWithEveryBoundThing() { + final Properties p = sanatos(); + final HybridSignerRegistry a = HybridSignerRegistry.fromProperties(p, "a"); + final HybridSignerRegistry b = HybridSignerRegistry.fromProperties(p, "b"); + assertThat(a.canonicalHash()).isEqualTo(b.canonicalHash()); // determinist + +- // schimb O cheie: hash-ul se misca ++ // change ONE key: the hash moves + final Properties altKey = sanatos(); + altKey.setProperty( + "2.key." + SLHDSA, + Bytes.wrap(SealSchemes.SLH_DSA_128S.generate(random).publicRegistryForm()).toHexString()); + assertThat(HybridSignerRegistry.fromProperties(altKey, "c").canonicalHash()) + .isNotEqualTo(a.canonicalHash()); + +- // scot o schema de la un validator: hash-ul se misca ++ // remove one scheme from a validator: the hash moves + final Properties altScheme = sanatos(); + altScheme.remove("2.key." + SLHDSA); + assertThat(HybridSignerRegistry.fromProperties(altScheme, "d").canonicalHash()) + .isNotEqualTo(a.canonicalHash()); + + // alt chainId: hash-ul se misca + final Properties altChain = sanatos(); + altChain.setProperty("chainId", "2801"); + assertThat(HybridSignerRegistry.fromProperties(altChain, "e").canonicalHash()) + .isNotEqualTo(a.canonicalHash()); + } + + @Test + void hashDomainCanNeverCollideWithTheFalconOnlyRegistryFamily() { + // the domain is part of the preimage; if someone aligned it with the old family, a hybrid + // registry could pass itself off as the genesis-bound v1 registry. The constant is + // verified here so it cannot drift silently. + assertThat(HybridSignerRegistry.HASH_DOMAIN).isEqualTo("AERE-PQ-HYBRID-REGISTRY-1"); + assertThat(HybridSignerRegistry.HASH_DOMAIN).isNotEqualTo(PqRegistryHash.DOMAIN_V1); + assertThat(HybridSignerRegistry.HASH_DOMAIN).isNotEqualTo(PqRegistryHash.DOMAIN_V2); +@@ -183,41 +183,41 @@ class HybridSignerRegistryTest { + // --------------------------------------------- the registry + the v2 certificate, together + + @Test + void endToEndCertificateVerifiesAgainstRegistryKeysPerScheme() { + final byte[] message = "commit hash stand-in, 32 bytes!!".getBytes(java.nio.charset.StandardCharsets.UTF_8); + // build the registry and KEEP the private test handles so I can sign + final Properties p = new Properties(); + p.setProperty("formatVersion", "hybrid-1"); + p.setProperty("chainId", "2800"); + p.setProperty("count", "2"); + final SealScheme.GeneratedPair f0 = SealSchemes.FALCON_512.generate(random); + final SealScheme.GeneratedPair s0 = SealSchemes.SLH_DSA_128S.generate(random); + final SealScheme.GeneratedPair f1 = SealSchemes.FALCON_512.generate(random); + p.setProperty("0.addr", "0x" + "aa".repeat(20)); + p.setProperty("1.addr", "0x" + "bb".repeat(20)); + p.setProperty("0.key." + FALCON, Bytes.wrap(f0.publicRegistryForm()).toHexString()); + p.setProperty("0.key." + SLHDSA, Bytes.wrap(s0.publicRegistryForm()).toHexString()); + p.setProperty("1.key." + FALCON, Bytes.wrap(f1.publicRegistryForm()).toHexString()); + final HybridSignerRegistry reg = HybridSignerRegistry.fromProperties(p, "test"); + +- // certificatul hibrid: validatorul 0 cu amandoua schemele, 1 doar Falcon ++ // the hybrid certificate: validator 0 with both schemes, 1 with Falcon only + final java.util.List cert = + java.util.List.of( + new SchemeSeal((byte) 0x01, 0, Bytes.wrap( + SealSchemes.FALCON_512.sign(f0.privateKey(), message).orElseThrow())), + new SchemeSeal((byte) 0x02, 0, Bytes.wrap( + SealSchemes.SLH_DSA_128S.sign(s0.privateKey(), message).orElseThrow())), + new SchemeSeal((byte) 0x01, 1, Bytes.wrap( + SealSchemes.FALCON_512.sign(f1.privateKey(), message).orElseThrow()))); + + // round-trip through the v2 format, then EACH seal against ITS OWN key from the registry + for (final SchemeSeal seal : PqAnchorV2.decode(PqAnchorV2.encode(cert))) { + final SealScheme scheme = SealSchemes.byWireId(seal.getSchemeWireId()).orElseThrow(); + final byte[] key = reg.publicKey(seal.getValidatorIndex(), scheme.id()).orElseThrow(); + assertThat(scheme.verifyRaw(key, message, seal.getSignature().toArray())) + .as("sigiliul %s contra cheii lui din registru", seal) + .isTrue(); + } + // the per-scheme threshold, on the same certificate: 2 Falcon validators, 1 SLH-DSA + assertThat(PqAnchorV2.distinctValidatorsWith(cert, (byte) 0x01)).isEqualTo(2); + assertThat(PqAnchorV2.distinctValidatorsWith(cert, (byte) 0x02)).isEqualTo(1); +diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/PqAnchorLapseTest.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/PqAnchorLapseTest.java +old mode 100755 +new mode 100644 +index 038d862876..2bd1894938 +--- a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/PqAnchorLapseTest.java ++++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/PqAnchorLapseTest.java +@@ -76,121 +76,121 @@ public class PqAnchorLapseTest { + } + + @Test + public void theStatedSpansAgreeWithTheBounds() { + // 36, not 37: (13,268,944 - 13,267,824) / 32 + 1 = 36. And 19,425 for the second range. The + // span is carried in each entry so the two cannot drift apart in silence; this asserts the + // arithmetic from the outside as well. + for (final PqAnchorLapse.Window window : PqAnchorLapse.windows()) { + assertThat((window.lastBlock() - window.firstBlock()) % PqAnchorLapse.ANCHOR_SPACING).isZero(); + assertThat((window.lastBlock() - window.firstBlock()) / PqAnchorLapse.ANCHOR_SPACING + 1L) + .isEqualTo(window.anchorHeights()); + } + } + + // ----------------------------------------------------------------------------------------------- + // isDisarmed: TRUE only in the first range, and deliberately FALSE in the second. + // ----------------------------------------------------------------------------------------------- + + @Test + public void isDisarmedIsTrueOnlyWhereNothingWasInForce() { +- assertThat(PqAnchorLapse.isDisarmed(DISARMED_FIRST)).isTrue(); +- assertThat(PqAnchorLapse.isDisarmed(DISARMED_LAST)).isTrue(); ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, DISARMED_FIRST)).isTrue(); ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, DISARMED_LAST)).isTrue(); + + // The neighbouring anchor heights, both measured to carry a digest, stay under the strict rules. +- assertThat(PqAnchorLapse.isDisarmed(LAST_ENFORCED_BEFORE)).isFalse(); +- assertThat(PqAnchorLapse.isDisarmed(DISARMED_FIRST - 1L)).isFalse(); +- assertThat(PqAnchorLapse.isDisarmed(DISARMED_LAST + 1L)).isFalse(); ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, LAST_ENFORCED_BEFORE)).isFalse(); ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, DISARMED_FIRST - 1L)).isFalse(); ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, DISARMED_LAST + 1L)).isFalse(); + + // And FALSE across the whole second range: there the digest and the ordering did hold, and a + // relaxation that leaked into it would throw away the binding on 19,425 anchor heights. +- assertThat(PqAnchorLapse.isDisarmed(LOWERED_FIRST)).isFalse(); +- assertThat(PqAnchorLapse.isDisarmed(13_500_016L)).isFalse(); +- assertThat(PqAnchorLapse.isDisarmed(LOWERED_LAST)).isFalse(); +- assertThat(PqAnchorLapse.isDisarmed(FIRST_FULLY_ENFORCED_AFTER)).isFalse(); ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, LOWERED_FIRST)).isFalse(); ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, 13_500_016L)).isFalse(); ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, LOWERED_LAST)).isFalse(); ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, FIRST_FULLY_ENFORCED_AFTER)).isFalse(); + } + + @Test + public void everyAnchorHeightOfTheDisarmedRangeIsCovered() { + long covered = 0L; + for (long height = DISARMED_FIRST; + height <= DISARMED_LAST; + height += PqAnchorLapse.ANCHOR_SPACING) { +- assertThat(PqAnchorLapse.isDisarmed(height)) ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, height)) + .describedAs("anchor height %d of the disarmed range", height) + .isTrue(); + covered++; + } + assertThat(covered).isEqualTo(36L); + + // The rest of the chain is untouched. +- assertThat(PqAnchorLapse.isDisarmed(0L)).isFalse(); +- assertThat(PqAnchorLapse.isDisarmed(13_014_000L)).isFalse(); +- assertThat(PqAnchorLapse.isDisarmed(13_000_000L)).isFalse(); +- assertThat(PqAnchorLapse.isDisarmed(14_077_000L)).isFalse(); +- assertThat(PqAnchorLapse.isDisarmed(Long.MAX_VALUE)).isFalse(); ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, 0L)).isFalse(); ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, 13_014_000L)).isFalse(); ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, 13_000_000L)).isFalse(); ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, 14_077_000L)).isFalse(); ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, Long.MAX_VALUE)).isFalse(); + } + + // ----------------------------------------------------------------------------------------------- + // historicMinSeals: the threshold that was really in force, and only where it was lower. + // ----------------------------------------------------------------------------------------------- + + @Test + public void historicMinSealsAnswersOnlyInsideTheLoweredRange() { +- assertThat(PqAnchorLapse.historicMinSeals(LOWERED_FIRST)).hasValue(1); +- assertThat(PqAnchorLapse.historicMinSeals(13_500_016L)).hasValue(1); +- assertThat(PqAnchorLapse.historicMinSeals(LOWERED_LAST)).hasValue(1); ++ assertThat(PqAnchorLapse.historicMinSeals(PqAnchorLapse.CHAIN_ID, LOWERED_FIRST)).hasValue(1); ++ assertThat(PqAnchorLapse.historicMinSeals(PqAnchorLapse.CHAIN_ID, 13_500_016L)).hasValue(1); ++ assertThat(PqAnchorLapse.historicMinSeals(PqAnchorLapse.CHAIN_ID, LOWERED_LAST)).hasValue(1); + + // One anchor step past the end and the configured schedule applies again, unchanged. This is + // the assertion that stops the lowered threshold from becoming permanent. +- assertThat(PqAnchorLapse.historicMinSeals(FIRST_FULLY_ENFORCED_AFTER)).isEmpty(); +- assertThat(PqAnchorLapse.historicMinSeals(LOWERED_LAST + 1L)).isEmpty(); +- assertThat(PqAnchorLapse.historicMinSeals(LOWERED_FIRST - 1L)).isEmpty(); +- assertThat(PqAnchorLapse.historicMinSeals(LAST_ENFORCED_BEFORE)).isEmpty(); +- assertThat(PqAnchorLapse.historicMinSeals(14_077_000L)).isEmpty(); +- assertThat(PqAnchorLapse.historicMinSeals(Long.MAX_VALUE)).isEmpty(); ++ assertThat(PqAnchorLapse.historicMinSeals(PqAnchorLapse.CHAIN_ID, FIRST_FULLY_ENFORCED_AFTER)).isEmpty(); ++ assertThat(PqAnchorLapse.historicMinSeals(PqAnchorLapse.CHAIN_ID, LOWERED_LAST + 1L)).isEmpty(); ++ assertThat(PqAnchorLapse.historicMinSeals(PqAnchorLapse.CHAIN_ID, LOWERED_FIRST - 1L)).isEmpty(); ++ assertThat(PqAnchorLapse.historicMinSeals(PqAnchorLapse.CHAIN_ID, LAST_ENFORCED_BEFORE)).isEmpty(); ++ assertThat(PqAnchorLapse.historicMinSeals(PqAnchorLapse.CHAIN_ID, 14_077_000L)).isEmpty(); ++ assertThat(PqAnchorLapse.historicMinSeals(PqAnchorLapse.CHAIN_ID, Long.MAX_VALUE)).isEmpty(); + + // And it does NOT answer inside the disarmed range: there the rules are skipped whole, so a + // threshold would be a second, contradictory way of saying the same thing. +- assertThat(PqAnchorLapse.historicMinSeals(DISARMED_FIRST)).isEmpty(); +- assertThat(PqAnchorLapse.historicMinSeals(DISARMED_LAST)).isEmpty(); ++ assertThat(PqAnchorLapse.historicMinSeals(PqAnchorLapse.CHAIN_ID, DISARMED_FIRST)).isEmpty(); ++ assertThat(PqAnchorLapse.historicMinSeals(PqAnchorLapse.CHAIN_ID, DISARMED_LAST)).isEmpty(); + } + + @Test + public void theFloorInsideTheLoweredRangeIsOneAndNotZero() { + // Measured: 2,926 of the 19,425 anchor heights in that range carry fewer seals than the + // schedule asks, the counts seen are 1 and 2, and NOT ONE carries zero. A floor of zero would + // therefore accept an empty certificate at a height where a certificate was in fact required, + // which is weaker than the history needs. +- assertThat(PqAnchorLapse.historicMinSeals(LOWERED_FIRST)).hasValue(1); ++ assertThat(PqAnchorLapse.historicMinSeals(PqAnchorLapse.CHAIN_ID, LOWERED_FIRST)).hasValue(1); + assertThat(PqAnchorLapse.windows().get(1).effectiveMinSeals()).isPositive(); + } + + @Test + public void windowCoveringNamesTheRangeOrNothing() { +- assertThat(PqAnchorLapse.windowCovering(DISARMED_FIRST)).isPresent(); +- assertThat(PqAnchorLapse.windowCovering(DISARMED_FIRST).get().lastBlock()) ++ assertThat(PqAnchorLapse.windowCovering(PqAnchorLapse.CHAIN_ID, DISARMED_FIRST)).isPresent(); ++ assertThat(PqAnchorLapse.windowCovering(PqAnchorLapse.CHAIN_ID, DISARMED_FIRST).get().lastBlock()) + .isEqualTo(DISARMED_LAST); +- assertThat(PqAnchorLapse.windowCovering(LOWERED_FIRST)).isPresent(); +- assertThat(PqAnchorLapse.windowCovering(LOWERED_FIRST).get().relaxation()) ++ assertThat(PqAnchorLapse.windowCovering(PqAnchorLapse.CHAIN_ID, LOWERED_FIRST)).isPresent(); ++ assertThat(PqAnchorLapse.windowCovering(PqAnchorLapse.CHAIN_ID, LOWERED_FIRST).get().relaxation()) + .isEqualTo(PqAnchorLapse.Relaxation.THRESHOLD_ONLY); +- assertThat(PqAnchorLapse.windowCovering(FIRST_FULLY_ENFORCED_AFTER)).isEmpty(); ++ assertThat(PqAnchorLapse.windowCovering(PqAnchorLapse.CHAIN_ID, FIRST_FULLY_ENFORCED_AFTER)).isEmpty(); + assertThat(PqAnchorLapse.earliestAffectedBlock()).contains(DISARMED_FIRST); + } + + @Test + public void theDisarmedRangeIsTheSameOBJECTTheOrderingExceptionUses() { + // A second copy of these bounds anywhere else is a value that diverges. PqAnchor used to carry + // them as its own literals; it now derives them, and this is the assertion that says so. + assertThat(PqAnchor.UNORDERED_WINDOW_FIRST).isEqualTo(DISARMED_FIRST); + assertThat(PqAnchor.UNORDERED_WINDOW_LAST).isEqualTo(DISARMED_LAST); + } + + // ----------------------------------------------------------------------------------------------- + // The self-checks can say no. A guard that has never refused anything cannot be believed. + // ----------------------------------------------------------------------------------------------- + + @Test + public void aRangeThatContradictsItselfIsRefusedRatherThanAccepted() { + assertThatThrownBy( + () -> + new PqAnchorLapse.Window( +diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/PqAnchorTest.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/PqAnchorTest.java +old mode 100755 +new mode 100644 +index 5bea4d37e3..aabecee7c2 +--- a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/PqAnchorTest.java ++++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/PqAnchorTest.java +@@ -162,78 +162,78 @@ public class PqAnchorTest { + // Attack A4: the same index twice to inflate k. Unrepresentable, not filtered afterwards. + assertThat(PqAnchor.hasStrictlyIncreasingIndices(Arrays.asList(seal(2), seal(2)))).isFalse(); + assertThat( + PqAnchor.hasStrictlyIncreasingIndices( + Arrays.asList(new FalconSeal(2, signatureFor(2, 0)), new FalconSeal(2, signatureFor(2, 1))))) + .isFalse(); + assertThat(PqAnchor.hasStrictlyIncreasingIndices(List.of(new FalconSeal(-1, Bytes.of(1))))) + .isFalse(); + assertThat(PqAnchor.hasStrictlyIncreasingIndices(List.of(new FalconSeal(1, null)))).isFalse(); + } + + @Test + public void historicalUnorderedWindowIsAcceptedAndOnlyThere() { + // The 36 canonical headers written unsorted during the 2026-08-10 interruption. Two real index + // sequences, decoded off the public endpoint on 2026-08-11: block 13,267,824 lists 2, 6, 1 and + // block 13,268,944 lists 5, 6, 1, 0. + final List real1 = Arrays.asList(seal(2), seal(6), seal(1)); + final List real2 = Arrays.asList(seal(5), seal(6), seal(1), seal(0)); + + // Inside the window: accepted, at both edges and in the middle. +- assertThat(PqAnchor.hasAcceptableIndices(real1, PqAnchor.UNORDERED_WINDOW_FIRST)).isTrue(); +- assertThat(PqAnchor.hasAcceptableIndices(real2, PqAnchor.UNORDERED_WINDOW_LAST)).isTrue(); +- assertThat(PqAnchor.hasAcceptableIndices(real1, PqAnchor.UNORDERED_WINDOW_FIRST + 32L)).isTrue(); ++ assertThat(PqAnchor.hasAcceptableIndices(PqAnchorLapse.CHAIN_ID, real1, PqAnchor.UNORDERED_WINDOW_FIRST)).isTrue(); ++ assertThat(PqAnchor.hasAcceptableIndices(PqAnchorLapse.CHAIN_ID, real2, PqAnchor.UNORDERED_WINDOW_LAST)).isTrue(); ++ assertThat(PqAnchor.hasAcceptableIndices(PqAnchorLapse.CHAIN_ID, real1, PqAnchor.UNORDERED_WINDOW_FIRST + 32L)).isTrue(); + + // NEGATIVE CONTROL, and it is the whole point: one block on either side of the window and the + // very same certificate is rejected. If these two ever pass, the exception has stopped being an + // exception and has become the rule. +- assertThat(PqAnchor.hasAcceptableIndices(real1, PqAnchor.UNORDERED_WINDOW_FIRST - 1L)).isFalse(); +- assertThat(PqAnchor.hasAcceptableIndices(real1, PqAnchor.UNORDERED_WINDOW_LAST + 1L)).isFalse(); +- assertThat(PqAnchor.hasAcceptableIndices(real2, 1L)).isFalse(); +- assertThat(PqAnchor.hasAcceptableIndices(real2, Long.MAX_VALUE)).isFalse(); ++ assertThat(PqAnchor.hasAcceptableIndices(PqAnchorLapse.CHAIN_ID, real1, PqAnchor.UNORDERED_WINDOW_FIRST - 1L)).isFalse(); ++ assertThat(PqAnchor.hasAcceptableIndices(PqAnchorLapse.CHAIN_ID, real1, PqAnchor.UNORDERED_WINDOW_LAST + 1L)).isFalse(); ++ assertThat(PqAnchor.hasAcceptableIndices(PqAnchorLapse.CHAIN_ID, real2, 1L)).isFalse(); ++ assertThat(PqAnchor.hasAcceptableIndices(PqAnchorLapse.CHAIN_ID, real2, Long.MAX_VALUE)).isFalse(); + } + + @Test + public void historicalWindowDoesNotRelaxDistinctness() { + // Attack A4 inside the window: repeating one seal to inflate k. Sortedness is relaxed there, + // distinctness is NOT, at any height. A certificate that repeats an index is still + // unrepresentable, which is the only part of the ordering rule that an attacker cares about. + final List repetat = + Arrays.asList(new FalconSeal(2, signatureFor(2, 0)), new FalconSeal(2, signatureFor(2, 1))); +- assertThat(PqAnchor.hasAcceptableIndices(repetat, PqAnchor.UNORDERED_WINDOW_FIRST)).isFalse(); +- assertThat(PqAnchor.hasAcceptableIndices(repetat, PqAnchor.UNORDERED_WINDOW_LAST)).isFalse(); ++ assertThat(PqAnchor.hasAcceptableIndices(PqAnchorLapse.CHAIN_ID, repetat, PqAnchor.UNORDERED_WINDOW_FIRST)).isFalse(); ++ assertThat(PqAnchor.hasAcceptableIndices(PqAnchorLapse.CHAIN_ID, repetat, PqAnchor.UNORDERED_WINDOW_LAST)).isFalse(); + + // Negative indices and null signatures stay rejected inside the window too. + assertThat( +- PqAnchor.hasAcceptableIndices( ++ PqAnchor.hasAcceptableIndices(PqAnchorLapse.CHAIN_ID, + List.of(new FalconSeal(-1, Bytes.of(1))), PqAnchor.UNORDERED_WINDOW_FIRST)) + .isFalse(); + assertThat( +- PqAnchor.hasAcceptableIndices( ++ PqAnchor.hasAcceptableIndices(PqAnchorLapse.CHAIN_ID, + List.of(new FalconSeal(1, null)), PqAnchor.UNORDERED_WINDOW_FIRST)) + .isFalse(); + + // And a sorted certificate is accepted everywhere, window or not: the exception only ever adds. + final List sortat = Arrays.asList(seal(0), seal(3), seal(6)); +- assertThat(PqAnchor.hasAcceptableIndices(sortat, 1L)).isTrue(); +- assertThat(PqAnchor.hasAcceptableIndices(sortat, PqAnchor.UNORDERED_WINDOW_FIRST)).isTrue(); +- assertThat(PqAnchor.hasAcceptableIndices(sortat, Long.MAX_VALUE)).isTrue(); ++ assertThat(PqAnchor.hasAcceptableIndices(PqAnchorLapse.CHAIN_ID, sortat, 1L)).isTrue(); ++ assertThat(PqAnchor.hasAcceptableIndices(PqAnchorLapse.CHAIN_ID, sortat, PqAnchor.UNORDERED_WINDOW_FIRST)).isTrue(); ++ assertThat(PqAnchor.hasAcceptableIndices(PqAnchorLapse.CHAIN_ID, sortat, Long.MAX_VALUE)).isTrue(); + } + + @Test + public void historicalWindowIsClosedAndAnchorAligned() { + // The window cannot grow: it is bounded above by a measured constant. And both bounds must sit on + // the 32-block anchor spacing, because only anchor heights carry certificates. A window whose + // bounds are off the spacing would be evidence that the measurement, not the chain, was wrong. + assertThat(PqAnchor.UNORDERED_WINDOW_LAST).isGreaterThan(PqAnchor.UNORDERED_WINDOW_FIRST); + assertThat((PqAnchor.UNORDERED_WINDOW_LAST - PqAnchor.UNORDERED_WINDOW_FIRST) % 32L).isZero(); + // 36 anchor headers, measured contiguous on 2026-08-11. + assertThat((PqAnchor.UNORDERED_WINDOW_LAST - PqAnchor.UNORDERED_WINDOW_FIRST) / 32L + 1L) + .isEqualTo(36L); + } + + @Test + public void sortedByIndexOrdersAscending() { + final List sorted = PqAnchor.sortedByIndex(Arrays.asList(seal(5), seal(1), seal(3))); + assertThat(sorted.stream().map(FalconSeal::getValidatorIndex)).containsExactly(1, 3, 5); + assertThat(PqAnchor.hasStrictlyIncreasingIndices(sorted)).isTrue(); + } +diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/PqRegistryV3Test.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/PqRegistryV3Test.java +new file mode 100644 +index 0000000000..e5538e1c61 +--- /dev/null ++++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/PqRegistryV3Test.java +@@ -0,0 +1,509 @@ ++/* ++ * AERE AIP-22 stage 3: probes of the v3 registry, and the writer of its conformance vectors. ++ * ++ * TWO MODES. With the environment variable AERE_REG3_VECTORS_OUT set to a directory, the vector ++ * writer generates PROBA keys (its helpers are package-visible since 2026-09-23: AereLocalKeysV3Test builds its own epochs with ++ * private keys it holds) (Falcon-512, SLH-DSA-SHA2-128s, secp256k1), builds two epochs and one ++ * negative vector per refusal code, and writes them as JSON; each negative differs from a valid ++ * manifest in ONE field (the lesson of AIP-20: a negative that differs in two places measures which ++ * check the validator reaches first, not the one it names), and where a field feeds a signed ++ * message the signatures are re-made over the changed field so that only the named rule can fail. ++ * Without the variable, every test reads the checked-in vectors from test resources ++ * (aere/registry-v3/) and requires the outcome each vector names: "ok" with the stated registry hash ++ * and row hashes, or the exact refusal code. The same files are read by the Nethermind port and by ++ * the public JS tool, which is what makes them conformance vectors and not just fixtures. ++ */ ++package org.hyperledger.besu.consensus.common.bft; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++import static org.assertj.core.api.Assertions.assertThatThrownBy; ++ ++import org.hyperledger.besu.crypto.KeyPair; ++import org.hyperledger.besu.crypto.SecureRandomProvider; ++import org.hyperledger.besu.crypto.SignatureAlgorithm; ++import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; ++import org.hyperledger.besu.ethereum.core.Util; ++ ++import java.io.IOException; ++import java.io.InputStream; ++import java.nio.charset.StandardCharsets; ++import java.nio.file.Files; ++import java.nio.file.Path; ++import java.security.SecureRandom; ++import java.util.ArrayList; ++import java.util.Iterator; ++import java.util.List; ++import java.util.Locale; ++import java.util.Map; ++import java.util.TreeMap; ++ ++import com.fasterxml.jackson.databind.JsonNode; ++import com.fasterxml.jackson.databind.ObjectMapper; ++import com.fasterxml.jackson.databind.SerializationFeature; ++import com.fasterxml.jackson.databind.node.ArrayNode; ++import com.fasterxml.jackson.databind.node.ObjectNode; ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.bytes.Bytes32; ++import org.junit.jupiter.api.Test; ++import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; ++ ++public class PqRegistryV3Test { ++ ++ private static final ObjectMapper M = ++ new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT); ++ private static final String RES = "/aere/registry-v3/"; ++ private static final List VECTORS = ++ List.of( ++ "ok-epoch-a", "ok-epoch-b-rotation", "n01-format", "n02-chain", "n03-extra-field", ++ "n05-unknown-scheme", "n06-required-scheme", "n07-falcon-header", "n08-pop", ++ "n09-id-derivation", "n10-duplicate-id", "n11-duplicate-key", "n12-rotation-one-key", ++ "n12b-rotation-wrong-key", "n13-rotation-unchanged", "n14-ecdsa-wrong-key", ++ "n14b-ecdsa-missing", "n15-transport", "n16-declared-hash"); ++ ++ // ------------------------------------------------------------------------------------------ ++ // The conformance vectors ++ // ------------------------------------------------------------------------------------------ ++ ++ @Test ++ public void everyVectorHasTheOutcomeItNames() throws IOException { ++ int ok = 0; ++ int refused = 0; ++ for (final String name : VECTORS) { ++ final JsonNode v = vector(name); ++ final PqRegistryV3.Registry prev = ++ v.hasNonNull("previous") ++ ? loadVector(vector(v.get("previous").asText()), null) ++ : null; ++ final String expect = v.get("expect").asText(); ++ if ("ok".equals(expect)) { ++ final PqRegistryV3.Registry r = loadVector(v, prev); ++ assertThat(r.hash().toHexString()).as(name).isEqualTo(v.get("registryHash").asText()); ++ final ArrayNode rh = (ArrayNode) v.get("rowHashes"); ++ assertThat(r.rowHashes()).as(name).hasSize(rh.size()); ++ for (int i = 0; i < rh.size(); i++) { ++ assertThat(r.rowHashes().get(i).toHexString()).as(name + " row " + i) ++ .isEqualTo(rh.get(i).asText()); ++ } ++ ok++; ++ } else { ++ final PqRegistryV3.Registry prevF = prev; ++ assertThatThrownBy(() -> loadVector(v, prevF)) ++ .as(name) ++ .isInstanceOf(PqRegistryV3.RegistryV3Exception.class) ++ .hasMessageStartingWith(expect + ":"); ++ refused++; ++ } ++ } ++ assertThat(ok).isEqualTo(2); ++ assertThat(refused).isEqualTo(VECTORS.size() - 2); ++ } ++ ++ @Test ++ public void merkleProofsVerifyForEveryRowAndNotOneRowPastTheEnd() throws IOException { ++ final JsonNode v = vector("ok-epoch-a"); ++ final PqRegistryV3.Registry r = loadVector(v, null); ++ for (int i = 0; i < r.count(); i++) { ++ final List p = PqRegistryV3.merkleProof(r.rowHashes(), i); ++ assertThat(PqRegistryV3.verifyMerkleProof(r.rowHashes().get(i), i, r.count(), p, r.root())) ++ .as("row " + i) ++ .isTrue(); ++ } ++ // three rows: the last leaf is paired with itself, so its path also "proves" index 3 unless the ++ // count bound refuses it - that refusal is the whole point of the bound ++ final int last = r.count() - 1; ++ final List p = PqRegistryV3.merkleProof(r.rowHashes(), last); ++ assertThat(r.count() % 2).isEqualTo(1); ++ assertThat( ++ PqRegistryV3.verifyMerkleProof(r.rowHashes().get(last), last + 1, r.count(), p, r.root())) ++ .isFalse(); ++ // and a leaf that is not a row never verifies ++ assertThat( ++ PqRegistryV3.verifyMerkleProof( ++ Bytes32.fromHexStringLenient("0x01"), 0, r.count(), ++ PqRegistryV3.merkleProof(r.rowHashes(), 0), r.root())) ++ .isFalse(); ++ } ++ ++ @Test ++ public void theIdIsTheAip20SenderDerivationOfTheFalconKey() throws IOException { ++ final JsonNode v = vector("ok-epoch-a"); ++ final PqRegistryV3.Registry r = loadVector(v, null); ++ for (final PqRegistryV3.Row row : r.rows()) { ++ final byte[] pk = row.key("falcon-512").orElseThrow().publicKey(); ++ assertThat(pk).hasSize(897); ++ assertThat(pk[0]).isEqualTo((byte) 0x09); ++ assertThat(PqRegistryV3.idOf(pk)).isEqualTo(row.id()); ++ } ++ } ++ ++ @Test ++ public void theRegistryHashCommitsToChainHeightAndCount() throws IOException { ++ final JsonNode v = vector("ok-epoch-a"); ++ final PqRegistryV3.Registry r = loadVector(v, null); ++ final Bytes32 h = PqRegistryV3.registryHash(r.chainId(), r.bindHeight(), r.count(), r.root()); ++ assertThat(h).isEqualTo(r.hash()); ++ assertThat(PqRegistryV3.registryHash(r.chainId() + 1, r.bindHeight(), r.count(), r.root())) ++ .isNotEqualTo(h); ++ assertThat(PqRegistryV3.registryHash(r.chainId(), r.bindHeight() + 1, r.count(), r.root())) ++ .isNotEqualTo(h); ++ assertThat(PqRegistryV3.registryHash(r.chainId(), r.bindHeight(), r.count() + 1, r.root())) ++ .isNotEqualTo(h); ++ } ++ ++ @Test ++ public void thePinnedHashIsCompared() throws IOException { ++ final JsonNode v = vector("ok-epoch-a"); ++ final Bytes32 good = Bytes32.fromHexString(v.get("registryHash").asText()); ++ final PqRegistryV3.Registry r = ++ PqRegistryV3.loadPinned( ++ v.get("manifest"), v.get("chainId").asLong(), required(v), null, ++ v.get("ecdsaRequired").asBoolean(), good); ++ assertThat(r.hash()).isEqualTo(good); ++ assertThatThrownBy( ++ () -> ++ PqRegistryV3.loadPinned( ++ v.get("manifest"), v.get("chainId").asLong(), required(v), null, ++ v.get("ecdsaRequired").asBoolean(), Bytes32.ZERO)) ++ .isInstanceOf(PqRegistryV3.RegistryV3Exception.class) ++ .hasMessageStartingWith("AERE-PQC-REG3-16:"); ++ } ++ ++ private static PqRegistryV3.Registry loadVector(final JsonNode v, final PqRegistryV3.Registry prev) { ++ return PqRegistryV3.load( ++ v.get("manifest"), v.get("chainId").asLong(), required(v), prev, ++ v.get("ecdsaRequired").asBoolean()); ++ } ++ ++ private static List required(final JsonNode v) { ++ final List out = new ArrayList<>(); ++ v.get("requiredSchemes").forEach(n -> out.add(n.asText())); ++ return out; ++ } ++ ++ private static JsonNode vector(final String name) throws IOException { ++ try (InputStream in = PqRegistryV3Test.class.getResourceAsStream(RES + name + ".json")) { ++ assertThat(in).as("vector " + name + " is on the test classpath").isNotNull(); ++ return M.readTree(in); ++ } ++ } ++ ++ // ------------------------------------------------------------------------------------------ ++ // The vector writer (runs only with AERE_REG3_VECTORS_OUT) ++ // ------------------------------------------------------------------------------------------ ++ ++ static final long CHAIN = 28001; ++ private static final SecureRandom RNG = SecureRandomProvider.createSecureRandom(); ++ private static final SignatureAlgorithm EC = SignatureAlgorithmFactory.getInstance(); ++ ++ /** One validator's PROBA keys. */ ++ record Proba( ++ SealScheme.GeneratedPair falcon, SealScheme.GeneratedPair slh, KeyPair ecdsa, byte[] node) { ++ byte[] falconStd() { ++ final byte[] h = falcon.publicRegistryForm(); ++ final byte[] s = new byte[897]; ++ s[0] = 0x09; ++ System.arraycopy(h, 0, s, 1, 896); ++ return s; ++ } ++ ++ byte[] address() { ++ return Util.publicKeyToAddress(ecdsa.getPublicKey()).getBytes().toArrayUnsafe(); ++ } ++ } ++ ++ static Proba proba() { ++ final KeyPair node = EC.generateKeyPair(); ++ return new Proba( ++ SealSchemes.FALCON_512.generate(RNG), ++ SealSchemes.SLH_DSA_128S.generate(RNG), ++ EC.generateKeyPair(), ++ Util.publicKeyToAddress(node.getPublicKey()).getBytes().toArrayUnsafe()); ++ } ++ ++ /** A row under construction: keys (scheme id to pair) with the id they are filed under. */ ++ record Draft(byte[] id, Map keys, Proba owner) {} ++ ++ static ObjectNode rowJson( ++ final long bind, final int count, final int index, final Draft d, final boolean ecdsa, ++ final boolean transport) { ++ final ObjectNode row = M.createObjectNode(); ++ row.put("id", hx(d.id())); ++ final ObjectNode keys = row.putObject("keys"); ++ final ObjectNode pop = row.putObject("pop"); ++ for (final Map.Entry e : d.keys().entrySet()) { ++ final SealScheme s = SealSchemes.byId(e.getKey()).orElseThrow(); ++ final byte[] std = standard(s, e.getValue()); ++ keys.put(e.getKey(), hx(std)); ++ final Bytes32 msg = PqRegistryV3.popMessage(CHAIN, bind, count, index, d.id(), s.wireId(), std); ++ pop.put(e.getKey(), hx(s.sign(e.getValue().privateKey(), msg.toArrayUnsafe()).orElseThrow())); ++ } ++ if (transport) { ++ row.putObject("transport").put("secp256k1Address", hx(d.owner().node())); ++ } ++ if (ecdsa) { ++ claim(row, bind, count, index, d.owner().ecdsa()); ++ } ++ return row; ++ } ++ ++ /** (Re)computes the ecdsa claim of a row from its current JSON, with the given key. */ ++ private static void claim( ++ final ObjectNode row, final long bind, final int count, final int index, final KeyPair kp) { ++ final Bytes32 rh = rowHashOf(row, bind, count, index); ++ final Bytes32 d = PqRegistryV3.claimDigest(CHAIN, rh); ++ final ObjectNode ec = row.putObject("ecdsa"); ++ ec.put("addr", hx(Util.publicKeyToAddress(kp.getPublicKey()).getBytes().toArrayUnsafe())); ++ ec.put("claim", hx(EC.sign(d, kp).encodedBytes().toArrayUnsafe())); ++ } ++ ++ /** The row hash of a row as written in JSON (reusing the loader's own parser via a 1-row load ++ * is impossible here, so the pre-image is rebuilt from the JSON fields). */ ++ private static Bytes32 rowHashOf(final ObjectNode row, final long bind, final int count, final int index) { ++ final TreeMap keys = new TreeMap<>(); ++ final Iterator> it = row.get("keys").fields(); ++ while (it.hasNext()) { ++ final Map.Entry e = it.next(); ++ final SealScheme s = SealSchemes.byId(e.getKey()).orElseThrow(); ++ keys.put( ++ s.wireId() & 0xff, ++ new PqRegistryV3.Key( ++ s, Bytes.fromHexString(e.getValue().asText()).toArrayUnsafe(), ++ Bytes.fromHexString(row.get("pop").get(e.getKey()).asText()).toArrayUnsafe())); ++ } ++ final byte[] transport = ++ row.has("transport") ++ ? Bytes.fromHexString(row.get("transport").get("secp256k1Address").asText()).toArrayUnsafe() ++ : null; ++ final PqRegistryV3.Row r = ++ new PqRegistryV3.Row( ++ index, Bytes.fromHexString(row.get("id").asText()).toArrayUnsafe(), keys, transport, ++ Map.of(), null, null); ++ return PqRegistryV3.rowHash(CHAIN, bind, count, r); ++ } ++ ++ private static byte[] standard(final SealScheme s, final SealScheme.GeneratedPair p) { ++ if (s == SealSchemes.FALCON_512) { ++ final byte[] h = p.publicRegistryForm(); ++ final byte[] std = new byte[897]; ++ std[0] = 0x09; ++ System.arraycopy(h, 0, std, 1, 896); ++ return std; ++ } ++ return p.publicRegistryForm(); ++ } ++ ++ static ObjectNode manifest(final long bind, final List rows) { ++ final ObjectNode m = M.createObjectNode(); ++ m.put("formatVersion", 3); ++ m.put("chainId", CHAIN); ++ m.put("bindHeight", bind); ++ m.put("count", rows.size()); ++ for (int i = 0; i < rows.size(); i++) { ++ m.set(Integer.toString(i), rows.get(i)); ++ } ++ return m; ++ } ++ ++ private static ObjectNode wrap( ++ final String description, final ObjectNode manifest, final boolean ecdsaRequired, ++ final String previous, final String expect) { ++ final ObjectNode v = M.createObjectNode(); ++ v.put("description", description); ++ v.put("chainId", CHAIN); ++ final ArrayNode req = v.putArray("requiredSchemes"); ++ req.add("falcon-512"); ++ req.add("slh-dsa-sha2-128s"); ++ v.put("ecdsaRequired", ecdsaRequired); ++ if (previous == null) { ++ v.putNull("previous"); ++ } else { ++ v.put("previous", previous); ++ } ++ v.put("expect", expect); ++ v.set("manifest", manifest); ++ return v; ++ } ++ ++ static Map both(final Proba p) { ++ final Map m = new java.util.LinkedHashMap<>(); ++ m.put("falcon-512", p.falcon()); ++ m.put("slh-dsa-sha2-128s", p.slh()); ++ return m; ++ } ++ ++ @Test ++ @EnabledIfEnvironmentVariable(named = "AERE_REG3_VECTORS_OUT", matches = ".+") ++ public void writeTheConformanceVectors() throws IOException { ++ final Path out = Path.of(System.getenv("AERE_REG3_VECTORS_OUT")); ++ Files.createDirectories(out); ++ final Proba v0 = proba(); ++ final Proba v1 = proba(); ++ final Proba v2 = proba(); ++ final Proba v3 = proba(); ++ final long bindA = 1000; ++ final long bindB = 2000; ++ final Draft d0 = new Draft(PqRegistryV3.idOf(v0.falconStd()), both(v0), v0); ++ final Draft d1 = new Draft(PqRegistryV3.idOf(v1.falconStd()), both(v1), v1); ++ final Draft d2 = new Draft(PqRegistryV3.idOf(v2.falconStd()), both(v2), v2); ++ ++ // epoch A: three rows, the switch epoch (ecdsa on every row), transport on row 0 ++ final List a = new ArrayList<>(); ++ a.add(rowJson(bindA, 3, 0, d0, true, true)); ++ a.add(rowJson(bindA, 3, 1, d1, true, false)); ++ a.add(rowJson(bindA, 3, 2, d2, true, false)); ++ final ObjectNode ma = manifest(bindA, a); ++ final ObjectNode okA = wrap("epoch A: 3 rows, falcon-512 + slh-dsa-sha2-128s, the switch epoch", ma, true, null, "ok"); ++ final PqRegistryV3.Registry ra = PqRegistryV3.load(ma, CHAIN, List.of("falcon-512", "slh-dsa-sha2-128s"), null, true); ++ addHashes(okA, ra); ++ write(out, "ok-epoch-a", okA); ++ ++ // epoch B: row 1 ROTATES both keys (keeps its id), row 2 unchanged, a new validator joins, v0 leaves ++ final Proba v1b = proba(); ++ final Draft d1b = new Draft(d1.id(), both(v1b), v1); ++ final Draft d3 = new Draft(PqRegistryV3.idOf(v3.falconStd()), both(v3), v3); ++ final List b = new ArrayList<>(); ++ b.add(rowJson(bindB, 3, 0, d2, false, false)); ++ final ObjectNode r1b = rowJson(bindB, 3, 1, d1b, false, false); ++ rotate(r1b, bindB, 3, 1, List.of(v1.falcon(), v1.slh())); ++ b.add(r1b); ++ b.add(rowJson(bindB, 3, 2, d3, false, false)); ++ final ObjectNode mb = manifest(bindB, b); ++ final ObjectNode okB = wrap("epoch B after A: index 1 rotates both keys under its id, index 0 unchanged (moved), a new id joins", mb, false, "ok-epoch-a", "ok"); ++ final PqRegistryV3.Registry rb = PqRegistryV3.load(mb, CHAIN, List.of("falcon-512", "slh-dsa-sha2-128s"), ra, false); ++ addHashes(okB, rb); ++ write(out, "ok-epoch-b-rotation", okB); ++ ++ // negatives on epoch A, one field each ++ ObjectNode m = ma.deepCopy(); ++ m.put("formatVersion", 2); ++ write(out, "n01-format", wrap("formatVersion 2", m, true, null, "AERE-PQC-REG3-01")); ++ m = ma.deepCopy(); ++ m.put("chainId", 2800); ++ write(out, "n02-chain", wrap("chainId of another chain", m, true, null, "AERE-PQC-REG3-02")); ++ m = ma.deepCopy(); ++ m.put("3", M.createObjectNode()); ++ write(out, "n03-extra-field", wrap("a row \"3\" beyond count 3", m, true, null, "AERE-PQC-REG3-03")); ++ m = ma.deepCopy(); ++ ((ObjectNode) m.get("1").get("keys")).put("ml-dsa-65", "0x00"); ++ ((ObjectNode) m.get("1").get("pop")).put("ml-dsa-65", "0x00"); ++ write(out, "n05-unknown-scheme", wrap("a key of a scheme this build does not know", m, true, null, "AERE-PQC-REG3-05")); ++ // n06: row 2 without its SLH-DSA key; pop and claim re-made so only the missing scheme can fail ++ { ++ final Map onlyF = new java.util.LinkedHashMap<>(); ++ onlyF.put("falcon-512", v2.falcon()); ++ final List x = new ArrayList<>(a); ++ x.set(2, rowJson(bindA, 3, 2, new Draft(d2.id(), onlyF, v2), true, false)); ++ write(out, "n06-required-scheme", wrap("row 2 carries no slh-dsa key", manifest(bindA, x), true, null, "AERE-PQC-REG3-06")); ++ } ++ m = ma.deepCopy(); ++ final String fk = m.get("0").get("keys").get("falcon-512").asText(); ++ ((ObjectNode) m.get("0").get("keys")).put("falcon-512", "0x0a" + fk.substring(4)); ++ write(out, "n07-falcon-header", wrap("row 0 falcon key with header 0x0a instead of 0x09", m, true, null, "AERE-PQC-REG3-07")); ++ m = ma.deepCopy(); ++ ((ObjectNode) m.get("1").get("pop")).put("falcon-512", m.get("0").get("pop").get("falcon-512").asText()); ++ write(out, "n08-pop", wrap("row 1 carries row 0's falcon possession proof", m, true, null, "AERE-PQC-REG3-08")); ++ // n09: row 1 filed under an id that is not its derivation; every proof re-made over that id ++ { ++ final byte[] wrongId = new byte[20]; ++ RNG.nextBytes(wrongId); ++ final List x = new ArrayList<>(a); ++ x.set(1, rowJson(bindA, 3, 1, new Draft(wrongId, both(v1), v1), true, false)); ++ write(out, "n09-id-derivation", wrap("row 1 id is not keccak(0x50||0x20||falcon)[12:]", manifest(bindA, x), true, null, "AERE-PQC-REG3-09")); ++ } ++ // n10: row 2 filed under row 1's id; proofs re-made ++ { ++ final List x = new ArrayList<>(a); ++ x.set(2, rowJson(bindA, 3, 2, new Draft(d1.id(), both(v2), v2), true, false)); ++ write(out, "n10-duplicate-id", wrap("row 2 carries row 1's id", manifest(bindA, x), true, null, "AERE-PQC-REG3-10")); ++ } ++ // n11: row 2 carries row 1's SLH-DSA key (its proof made by that key, over row 2) ++ { ++ final Map k = new java.util.LinkedHashMap<>(); ++ k.put("falcon-512", v2.falcon()); ++ k.put("slh-dsa-sha2-128s", v1.slh()); ++ final List x = new ArrayList<>(a); ++ x.set(2, rowJson(bindA, 3, 2, new Draft(d2.id(), k, v2), true, false)); ++ write(out, "n11-duplicate-key", wrap("row 2 carries row 1's slh-dsa key", manifest(bindA, x), true, null, "AERE-PQC-REG3-11")); ++ } ++ // n15: transport of 19 bytes (claim re-made over the row as written is impossible: the loader ++ // refuses the field before hashing, which is the point) ++ m = ma.deepCopy(); ++ ((ObjectNode) m.get("0").get("transport")).put("secp256k1Address", "0x" + "11".repeat(19)); ++ write(out, "n15-transport", wrap("row 0 transport is 19 bytes", m, true, null, "AERE-PQC-REG3-15")); ++ // n14: row 1's claim made by row 2's classical key; n14b: row 1 without the link in the switch epoch ++ { ++ final ObjectNode x1 = a.get(1).deepCopy(); ++ claim(x1, bindA, 3, 1, v2.ecdsa()); ++ ((ObjectNode) x1.get("ecdsa")).put("addr", hx(v1.address())); ++ final List x = new ArrayList<>(a); ++ x.set(1, x1); ++ write(out, "n14-ecdsa-wrong-key", wrap("row 1 claim signed by another validator's key", manifest(bindA, x), true, null, "AERE-PQC-REG3-14")); ++ final ObjectNode y1 = a.get(1).deepCopy(); ++ y1.remove("ecdsa"); ++ final List y = new ArrayList<>(a); ++ y.set(1, y1); ++ write(out, "n14b-ecdsa-missing", wrap("row 1 has no ecdsa link in the switch epoch", manifest(bindA, y), true, null, "AERE-PQC-REG3-14")); ++ } ++ m = ma.deepCopy(); ++ m.put("registryHash", "0x" + "00".repeat(32)); ++ write(out, "n16-declared-hash", wrap("the file declares a registry hash it does not have", m, true, null, "AERE-PQC-REG3-16")); ++ ++ // negatives on epoch B ++ { ++ final ObjectNode x1 = rowJson(bindB, 3, 1, d1b, false, false); ++ rotate(x1, bindB, 3, 1, List.of(v1.falcon())); ++ final List x = new ArrayList<>(b); ++ x.set(1, x1); ++ write(out, "n12-rotation-one-key", wrap("index 1 rotates with the old falcon key only (slh missing)", manifest(bindB, x), false, "ok-epoch-a", "AERE-PQC-REG3-12")); ++ final ObjectNode z1 = rowJson(bindB, 3, 1, d1b, false, false); ++ rotate(z1, bindB, 3, 1, List.of(v3.falcon(), v1.slh())); ++ final List z = new ArrayList<>(b); ++ z.set(1, z1); ++ write(out, "n12b-rotation-wrong-key", wrap("index 1 rotation's falcon signature is by another validator's key", manifest(bindB, z), false, "ok-epoch-a", "AERE-PQC-REG3-12")); ++ final ObjectNode u0 = rowJson(bindB, 3, 0, d2, false, false); ++ rotate(u0, bindB, 3, 0, List.of(v2.falcon(), v2.slh())); ++ final List u = new ArrayList<>(b); ++ u.set(0, u0); ++ write(out, "n13-rotation-unchanged", wrap("index 0 did not change its keys and carries a rotation", manifest(bindB, u), false, "ok-epoch-a", "AERE-PQC-REG3-13")); ++ } ++ } ++ ++ /** Adds rotation signatures over the row's current hash, one per given old key, in scheme order. */ ++ static void rotate( ++ final ObjectNode row, final long bind, final int count, final int index, ++ final List oldKeys) { ++ final Bytes32 msg = PqRegistryV3.rotateMessage(rowHashOf(row, bind, count, index)); ++ final ObjectNode rot = row.putObject("rotation"); ++ final String[] names = {"falcon-512", "slh-dsa-sha2-128s"}; ++ for (int i = 0; i < oldKeys.size(); i++) { ++ final SealScheme s = SealSchemes.byId(names[i]).orElseThrow(); ++ rot.put(names[i], hx(s.sign(oldKeys.get(i).privateKey(), msg.toArrayUnsafe()).orElseThrow())); ++ } ++ } ++ ++ private static void addHashes(final ObjectNode v, final PqRegistryV3.Registry r) { ++ v.put("registryHash", r.hash().toHexString()); ++ v.put("root", r.root().toHexString()); ++ final ArrayNode rh = v.putArray("rowHashes"); ++ r.rowHashes().forEach(h -> rh.add(h.toHexString())); ++ final ObjectNode proofs = v.putObject("merkleProofs"); ++ for (int i = 0; i < r.count(); i++) { ++ final ArrayNode p = proofs.putArray(Integer.toString(i)); ++ PqRegistryV3.merkleProof(r.rowHashes(), i).forEach(h -> p.add(h.toHexString())); ++ } ++ final ArrayNode ids = v.putArray("ids"); ++ r.rows().forEach(row -> ids.add(hx(row.id()))); ++ } ++ ++ private static void write(final Path dir, final String name, final JsonNode v) throws IOException { ++ Files.writeString(dir.resolve(name + ".json"), M.writeValueAsString(v) + "\n", StandardCharsets.UTF_8); ++ } ++ ++ private static String hx(final byte[] b) { ++ final StringBuilder sb = new StringBuilder("0x"); ++ for (final byte x : b) { ++ sb.append(String.format(Locale.ROOT, "%02x", x & 0xff)); ++ } ++ return sb.toString(); ++ } ++} +diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/PqSchemeScheduleTest.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/PqSchemeScheduleTest.java +index 41e03e825e..41f03ceda2 100755 +--- a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/PqSchemeScheduleTest.java ++++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/PqSchemeScheduleTest.java +@@ -60,68 +60,120 @@ class PqSchemeScheduleTest { + .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> PqSchemeSchedule.parse("100:")) + .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> PqSchemeSchedule.parse("100:falcon-512+falcon-512")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("repeats"); + assertThatThrownBy(() -> PqSchemeSchedule.parse("-5:falcon-512")) + .isInstanceOf(IllegalArgumentException.class); + } + + // ------------------------------------------------------------- poarta de armare (D-147) + + private HybridSignerRegistry registruCuAcoperire(final int falconi, final int slhuri) { + final Properties p = new Properties(); + final int count = Math.max(falconi, Math.max(slhuri, 1)); + p.setProperty("formatVersion", "hybrid-1"); + p.setProperty("chainId", "2800"); + p.setProperty("count", String.valueOf(count)); + for (int i = 0; i < count; i++) { + p.setProperty(i + ".addr", "0x" + String.format("%040x", 0xB0 + i)); +- // fiecare index primeste macar o cheie; acoperirea per schema e controlata mai jos ++ // every index gets at least one key; per-scheme coverage is controlled below + if (i < falconi) { + p.setProperty(i + ".key." + FALCON, + Bytes.wrap(SealSchemes.FALCON_512.generate(random).publicRegistryForm()).toHexString()); + } + if (i < slhuri) { + p.setProperty(i + ".key." + SLHDSA, + Bytes.wrap(SealSchemes.SLH_DSA_128S.generate(random).publicRegistryForm()).toHexString()); + } + if (i >= falconi && i >= slhuri) { + p.setProperty(i + ".key." + FALCON, + Bytes.wrap(SealSchemes.FALCON_512.generate(random).publicRegistryForm()).toHexString()); + } + } + return HybridSignerRegistry.fromProperties(p, "test"); + } + + @Test + void armabilityGateWalksTheWholeScheduleNotJustTheFirstStep() { + // the registry: 3 validators with Falcon, only 1 with SLH-DSA + final HybridSignerRegistry reg = registruCuAcoperire(3, 1); +- // treapta PERICULOASA e ULTIMA: hibridul cere SLH-DSA cu acoperire 1 < K=3 ++ // the DANGEROUS step is the LAST: the hybrid requires SLH-DSA with coverage 1 < K=3 + final PqSchemeSchedule orar = + PqSchemeSchedule.parse("100:falcon-512,999999:falcon-512+slh-dsa-128s"); + final var refusal = orar.firstUnsatisfied(reg, 3); + assertThat(refusal).isPresent(); + assertThat(refusal.get()).contains("999999").contains(SLHDSA).contains("covers only 1"); + } + + @Test + void armabilityPassesWhenEverySchemeHasCoverage() { + final HybridSignerRegistry reg = registruCuAcoperire(3, 3); + final PqSchemeSchedule orar = + PqSchemeSchedule.parse("100:falcon-512,200:falcon-512+slh-dsa-128s"); + assertThat(orar.firstUnsatisfied(reg, 3)).isEmpty(); + // and the same gate's negative control: an impossible threshold must refuse + assertThat(orar.firstUnsatisfied(reg, 4)).isPresent(); + } + ++ // ------------------------------------------------- intervale per schema (AIP-22 treapta 2) ++ ++ private static final String SLHDSA_CANONIC = "slh-dsa-sha2-128s"; ++ ++ @Test ++ void perSchemeIntervalsParseAndOnlyBiteOnTheirOwnGrid() { ++ // Falcon every 32nd block, SLH-DSA only every 128th, grids counted from H0=64 ++ final PqSchemeSchedule orar = ++ PqSchemeSchedule.parse("1000:" + FALCON + "/32+" + SLHDSA_CANONIC + "/128"); ++ assertThat(orar.hasIntervals()).isTrue(); ++ // schemesAt ramane setul intreg: cheile si armabilitatea privesc toate schemele ++ assertThat(orar.schemesAt(1000)).containsExactlyInAnyOrder(FALCON, SLHDSA_CANONIC); ++ // 64 + 32k but not 64 + 128k: Falcon only ++ assertThat(orar.schemesRequiredForAnchor(1056, 64)).containsExactly(FALCON); // 1056-64 = 992 = 31*32 ++ assertThat(orar.schemesRequiredForAnchor(1120, 64)).containsExactly(FALCON); // 1056 = 33*32, not a multiple of 128 ++ // 64 + 128k: amandoua ++ assertThat(orar.schemesRequiredForAnchor(1216, 64)).containsExactlyInAnyOrder(FALCON, SLHDSA_CANONIC); // 1152 = 9*128 ++ // sub prima treapta (parintele 999 e sub 1000): nimic ++ assertThat(orar.schemesRequiredForAnchor(1000, 64)).isEmpty(); ++ // at the boundary: the step is read at the PARENT (1000), the anchor is 1001... which is not on the 32 grid from 64 ++ assertThat(orar.schemesRequiredForAnchor(1001, 64)).isEmpty(); ++ } ++ ++ @Test ++ void withoutIntervalsEveryNamedSchemeIsRequiredAtEveryAnchorExactlyAsBefore() { ++ final PqSchemeSchedule orar = PqSchemeSchedule.parse("100:" + FALCON + "+" + SLHDSA); ++ assertThat(orar.hasIntervals()).isFalse(); ++ for (final long h : new long[] {101, 133, 200, 999_999}) { ++ assertThat(orar.schemesRequiredForAnchor(h, 64)).isEqualTo(orar.schemesAt(h - 1)); ++ } ++ // and a scheme WITHOUT an interval next to one WITH: the first at every anchor, the second on its grid ++ final PqSchemeSchedule mixt = PqSchemeSchedule.parse("100:" + FALCON + "+" + SLHDSA_CANONIC + "/128"); ++ assertThat(mixt.schemesRequiredForAnchor(96 + 32, 96)).containsExactly(FALCON); ++ assertThat(mixt.schemesRequiredForAnchor(96 + 128, 96)).containsExactlyInAnyOrder(FALCON, SLHDSA_CANONIC); ++ } ++ ++ @Test ++ void intervalsThatCannotLandOnAnchorsRefuseTheWholeSchedule() { ++ assertThatThrownBy(() -> PqSchemeSchedule.parse("100:" + FALCON + "/0")) ++ .isInstanceOf(IllegalArgumentException.class) ++ .hasMessageContaining("positive multiple"); ++ assertThatThrownBy(() -> PqSchemeSchedule.parse("100:" + FALCON + "/48")) ++ .isInstanceOf(IllegalArgumentException.class) ++ .hasMessageContaining("48"); ++ assertThatThrownBy(() -> PqSchemeSchedule.parse("100:" + FALCON + "/abc")) ++ .isInstanceOf(IllegalArgumentException.class) ++ .hasMessageContaining("not a number"); ++ assertThatThrownBy(() -> PqSchemeSchedule.parse("100:" + FALCON + "/32+" + FALCON + "/64")) ++ .isInstanceOf(IllegalArgumentException.class) ++ .hasMessageContaining("repeats"); ++ } ++ + @Test + void beforeTheFirstStepMeansLegacyNotSomeDefaultScheme() { + final PqSchemeSchedule orar = PqSchemeSchedule.parse("500:falcon-512"); + assertThat(orar.schemesAt(0)).isEmpty(); + assertThat(orar.schemesAt(499)).isEmpty(); + assertThat(orar.steps()).hasSize(1); + assertThat(orar.steps().get(0).schemeIds()).isEqualTo(Set.of(FALCON)); + } + } +diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SlhDsaParallelSigningTest.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SlhDsaParallelSigningTest.java +new file mode 100755 +index 0000000000..d4f0726a0f +--- /dev/null ++++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/slhdsa/SlhDsaParallelSigningTest.java +@@ -0,0 +1,137 @@ ++/* ++ * Copyright contributors to Besu / AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.consensus.common.bft.slhdsa; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++import static org.assertj.core.api.Assumptions.assumeThat; ++ ++import java.nio.charset.StandardCharsets; ++import org.bouncycastle.crypto.AsymmetricCipherKeyPair; ++import org.bouncycastle.crypto.params.ParametersWithRandom; ++import org.hyperledger.besu.crypto.SecureRandomProvider; ++import org.junit.jupiter.api.Test; ++ ++/** ++ * D-337 (2026-09-26): the parallel SLH-DSA signer must be the SAME signature as the Bouncy Castle ++ * original, bit for bit, and must actually be the path taken. Otherwise the anchor certificate would ++ * carry a different SLH-DSA seal than the second client and the public verifier expect, or the ++ * speed-up would be claimed while the sequential code still ran. Pinned: deterministic signing over ++ * several keys and message lengths equals the original; every signature ran exactly 1 + 2D tasks on ++ * the pool; the kill switch falls back to the original code with the same bytes and no task; and a ++ * randomised signature from the parallel path verifies under the original. ++ */ ++class SlhDsaParallelSigningTest { ++ ++ private static final org.bouncycastle.pqc.crypto.slhdsa.SLHDSAParameters ORIGINAL = ++ org.bouncycastle.pqc.crypto.slhdsa.SLHDSAParameters.sha2_128s; ++ ++ private static AsymmetricCipherKeyPair keyPair() { ++ final SLHDSAKeyPairGenerator gen = new SLHDSAKeyPairGenerator(); ++ gen.init( ++ new SLHDSAKeyGenerationParameters( ++ SecureRandomProvider.createSecureRandom(), SLHDSAParameters.sha2_128s)); ++ return gen.generateKeyPair(); ++ } ++ ++ private static org.bouncycastle.pqc.crypto.slhdsa.SLHDSASigner original( ++ final AsymmetricCipherKeyPair kp, final boolean forSigning) { ++ final org.bouncycastle.pqc.crypto.slhdsa.SLHDSASigner s = ++ new org.bouncycastle.pqc.crypto.slhdsa.SLHDSASigner(); ++ if (forSigning) { ++ s.init( ++ true, ++ new org.bouncycastle.pqc.crypto.slhdsa.SLHDSAPrivateKeyParameters( ++ ORIGINAL, ((SLHDSAPrivateKeyParameters) kp.getPrivate()).getEncoded())); ++ } else { ++ s.init( ++ false, ++ new org.bouncycastle.pqc.crypto.slhdsa.SLHDSAPublicKeyParameters( ++ ORIGINAL, ((SLHDSAPublicKeyParameters) kp.getPublic()).getEncoded())); ++ } ++ return s; ++ } ++ ++ private static byte[] ours(final AsymmetricCipherKeyPair kp, final byte[] msg) { ++ final SLHDSASigner s = new SLHDSASigner(); ++ s.init(true, kp.getPrivate()); ++ return s.generateSignature(msg); ++ } ++ ++ @Test ++ void parallelSignaturesAreBitIdenticalToTheOriginalAndTakeTheParallelPath() throws Exception { ++ assumeThat(ParallelSigning.enabled()).as("needs more than one core").isTrue(); ++ final int perSignature = ParallelSigning.tasksPerSignature(SLHDSAParameters.sha2_128s); ++ assertThat(perSignature).isEqualTo(15); // FORS + two halves of each of the 7 hypertree layers ++ final byte[][] messages = { ++ new byte[0], ++ "a".getBytes(StandardCharsets.UTF_8), ++ new byte[32], ++ "anchor parent 20333167 on chain 2800, a longer message".getBytes(StandardCharsets.UTF_8) ++ }; ++ int signatures = 0; ++ for (int key = 0; key < 3; key++) { ++ final AsymmetricCipherKeyPair kp = keyPair(); ++ for (final byte[] msg : messages) { ++ final int before = ParallelSigning.tasksRun(); ++ final byte[] fast = ours(kp, msg); ++ final int ran = ParallelSigning.tasksRun() - before; ++ assertThat(ran).as("tasks run on the pool for one signature").isEqualTo(perSignature); ++ assertThat(fast).hasSize(7856); ++ assertThat(fast).isEqualTo(original(kp, true).generateSignature(msg)); ++ assertThat(original(kp, false).verifySignature(msg, fast)).isTrue(); ++ signatures++; ++ } ++ } ++ assertThat(signatures).isEqualTo(12); ++ } ++ ++ @Test ++ void theKillSwitchRunsTheOriginalCodeWithTheSameBytes() throws Exception { ++ final AsymmetricCipherKeyPair kp = keyPair(); ++ final byte[] msg = "kill switch".getBytes(StandardCharsets.UTF_8); ++ final String before = System.getProperty(ParallelSigning.SWITCH_PROPERTY); ++ System.setProperty(ParallelSigning.SWITCH_PROPERTY, "false"); ++ try { ++ assertThat(ParallelSigning.enabled()).isFalse(); ++ final int tasksBefore = ParallelSigning.tasksRun(); ++ final byte[] sig = ours(kp, msg); ++ assertThat(ParallelSigning.tasksRun()).as("no task on the pool").isEqualTo(tasksBefore); ++ assertThat(sig).isEqualTo(original(kp, true).generateSignature(msg)); ++ } finally { ++ if (before == null) { ++ System.clearProperty(ParallelSigning.SWITCH_PROPERTY); ++ } else { ++ System.setProperty(ParallelSigning.SWITCH_PROPERTY, before); ++ } ++ } ++ } ++ ++ @Test ++ void aRandomisedParallelSignatureVerifiesUnderTheOriginalAndATamperedOneDoesNot() ++ throws Exception { ++ assumeThat(ParallelSigning.enabled()).as("needs more than one core").isTrue(); ++ final AsymmetricCipherKeyPair kp = keyPair(); ++ final byte[] msg = "randomised".getBytes(StandardCharsets.UTF_8); ++ final SLHDSASigner s = new SLHDSASigner(); ++ s.init(true, new ParametersWithRandom(kp.getPrivate(), SecureRandomProvider.createSecureRandom())); ++ final int before = ParallelSigning.tasksRun(); ++ final byte[] sig = s.generateSignature(msg); ++ assertThat(ParallelSigning.tasksRun() - before).isEqualTo(15); ++ assertThat(original(kp, false).verifySignature(msg, sig)).isTrue(); ++ final byte[] bad = sig.clone(); ++ bad[4000] ^= 0x01; ++ assertThat(original(kp, false).verifySignature(msg, bad)).isFalse(); ++ } ++} +diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/validator/blockbased/VoteTallyIdentityTest.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/validator/blockbased/VoteTallyIdentityTest.java +new file mode 100644 +index 0000000000..44a80d34f2 +--- /dev/null ++++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/validator/blockbased/VoteTallyIdentityTest.java +@@ -0,0 +1,75 @@ ++/* ++ * AERE AIP-22 stage 3: the ONE place the validator set changes form. After block H_id - 1 the vote ++ * tally holds the sorted post-quantum ids of the same members and open votes on addresses are gone; ++ * at every other block (and disarmed) the tally is untouched. ++ */ ++package org.hyperledger.besu.consensus.common.validator.blockbased; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++ ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; ++import org.hyperledger.besu.consensus.common.bft.PqRegistryV3; ++import org.hyperledger.besu.consensus.common.validator.ValidatorVote; ++import org.hyperledger.besu.consensus.common.validator.VoteType; ++import org.hyperledger.besu.datatypes.Address; ++ ++import java.io.InputStream; ++import java.util.ArrayList; ++import java.util.List; ++import java.util.TreeMap; ++import java.util.TreeSet; ++ ++import com.fasterxml.jackson.databind.JsonNode; ++import com.fasterxml.jackson.databind.ObjectMapper; ++import org.apache.tuweni.bytes.Bytes; ++import org.junit.jupiter.api.AfterEach; ++import org.junit.jupiter.api.Test; ++ ++public class VoteTallyIdentityTest { ++ ++ private static final long H_ID = 1500; ++ ++ @AfterEach ++ public void disarm() { ++ AerePqIdentity.uninstall(); ++ } ++ ++ @Test ++ public void theTallyTurnsIntoIdsAfterHidMinusOneAndDropsOpenVotes() throws Exception { ++ final JsonNode v; ++ try (InputStream in = getClass().getResourceAsStream("/aere/registry-v3/ok-epoch-a.json")) { ++ v = new ObjectMapper().readTree(in); ++ } ++ final PqRegistryV3.Registry epoch = ++ PqRegistryV3.load(v.get("manifest"), v.get("chainId").asLong(), ++ List.of("falcon-512", "slh-dsa-sha2-128s"), null, true); ++ final List
    addr = new ArrayList<>(); ++ final List
    id = new ArrayList<>(); ++ for (final PqRegistryV3.Row r : epoch.rows()) { ++ addr.add(Address.wrap(Bytes.wrap(r.ecdsaAddress()))); ++ id.add(Address.wrap(Bytes.wrap(r.id()))); ++ } ++ final TreeMap epochs = new TreeMap<>(); ++ epochs.put(epoch.bindHeight(), epoch); ++ ++ // disarmed: nothing happens at any block ++ final VoteTally before = new VoteTally(addr); ++ before.translateToIds(H_ID - 1); ++ assertThat(before.getValidators()).containsExactlyElementsOf(new TreeSet<>(addr)); ++ ++ AerePqIdentity.install(new AerePqIdentity.Config(H_ID, epochs)); ++ final VoteTally t = new VoteTally(addr); ++ final Address newcomer = Address.fromHexString("0x00000000000000000000000000000000000000cc"); ++ t.addVote(new ValidatorVote(VoteType.ADD, addr.get(0), newcomer)); ++ t.translateToIds(H_ID - 2); ++ assertThat(t.getValidators()).containsExactlyElementsOf(new TreeSet<>(addr)); ++ t.translateToIds(H_ID - 1); ++ assertThat(t.getValidators()).containsExactlyElementsOf(new TreeSet<>(id)); ++ // the open vote on an address is gone: two more votes for the newcomer would have reached the ++ // majority of three with it; after the switch they do not ++ t.addVote(new ValidatorVote(VoteType.ADD, id.get(1), newcomer)); ++ assertThat(t.getValidators()).doesNotContain(newcomer); ++ t.translateToIds(H_ID); ++ assertThat(t.getValidators()).hasSize(3); ++ } ++} +diff --git a/consensus/common/src/test/resources/aere/registry-v3/n01-format.json b/consensus/common/src/test/resources/aere/registry-v3/n01-format.json +new file mode 100644 +index 0000000000..24631f15c0 +--- /dev/null ++++ b/consensus/common/src/test/resources/aere/registry-v3/n01-format.json +@@ -0,0 +1,62 @@ ++{ ++ "description" : "formatVersion 2", ++ "chainId" : 28001, ++ "requiredSchemes" : [ "falcon-512", "slh-dsa-sha2-128s" ], ++ "ecdsaRequired" : true, ++ "previous" : null, ++ "expect" : "AERE-PQC-REG3-01", ++ "manifest" : { ++ "formatVersion" : 2, ++ "chainId" : 28001, ++ "bindHeight" : 1000, ++ "count" : 3, ++ "0" : { ++ "id" : "0xaaddb4dde09de5718a906d83be7db3d58e0ae32a", ++ "keys" : { ++ "falcon-512" : "0x09501c96d2f5cf0b28fa00c726e5359c5d36a1fa069971f854b7d914fb2f1295e68b2c6fa91d82f7d287f55ad493c87320bf7ca2a5d5e79d7212e8a540c166b588dc03f73b83be060525b367d9f40f5e77e7798c60b6499767586770722820b3b9e6013cad3eab5fe5de96089a29f34919a2e9ebcb3fa03a3e714593b7a3356d11ffb3441ab40ad94474da662a71aa2419dcd50668cd5d8a9017662cb60998b34ab5b7929c58a94d5e133ebbdadb2b0279543067f76bcc4cb6d7e0a5edb7625467e3ddc92a01206e1b8dce69be31928687d8af4d26633a07e73c2830d5299b878977691cf65700b65b6ea2463e51b6136888c544545e59fe8cf190a7944e215a785b682623c95a79eda28e25e0e1b91b49ac89deaec3b14a3c431d9046a663170111ee541d81b43aa91f29dc147c6fc97739b3a63fad1ca84843d0a65b8d9396f28e9b11f9a41453ab18a2309ae8db03253a09fac8f0cd634c76a5e938a44719660944a95dff056cee43ea99592c3899c2880d7181ee3dd5c04baeb60e1369a69430a66031e3cb10e392622f5246a71761760cf417dcb40ad65f60704fb74ad26f26c3af7513a42f806895e0298c25c049187aa536e0eba21998912e621846c2ca0e323744ba930a29850fdb385c8241382296ba28dd4df05ddb1e61fe525949034b59929a784406de240f8086b4074825f419d5472a28a0b157500be37e9f64897db2b645d3807c48dc143266c99e7cc1638ae278772493a2a4ecf74e526a514bc9119d7129c5a0d115a450ccf4dce05b76d4b6149fdab028006df7ec2209923117abf7578a082128cad42aa66b69eb63acee4456bebeb537ca57bb3d3487f95e4f06c5cb29f292d3b6284e5a162cb83151cd9ae56aebbfda150b7edd5065302ccab70892733a1e096ba0da5f51b42764ad23060eb197d5460425fd9c7a26e7dc3cfd40eac3643539feea72c9ed41569111a7976d2c345ac2183fa2271b424526709fd9aae558a23a5cca29f4e2f31629746a71d904612e95ad9977bbe74fa32e90fac62625838cac49f50e5aed4e8879e2ce2e5651c4f4ba0c96583af9e1612b5ff1a6fac5027c0a308815e592308170b915b4a2de1e8d48e9a5730680ea9db8f3326c430241153b3b218d5347d5c843570cf80ee813871ae10f6b8ce4ab7e4c5197045e85b1cb4977f44c33eb85894b6555b4bd288a50c1b656936841048983c00a01631f10a84522cd613fed0d4beaa4aa4b3e9f30c324108d909e59a80150", ++ "slh-dsa-sha2-128s" : "0x47a0b70170dda85f843607f6c6fcbe6e6acc7c22980c108996a3fe72dc9f61a6" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39c8813cd3b34be58eaab900555a67486034b1923e0b00e435661230cab85f07690a5958a5f5e9c84f033a3dc2039a5296443093fb7fe8d41895fa73be3fb34cefc6cc36750d534e6a3c47307294694729d6cdedb633e8efe8979a9aee486eaa66136e342c578761241192610185feb2d3c196bea0e79222437b6a8e08cb09778d053b29552df96507b1cdaede8e9aa7abc18902f29937f30e7cee6868f349f7ae33738237dcaf86b8e8e01238f3d8ea6fd4090a8161db65dabeb5ded5499e8cc8a5b32607abc291b36a4b34b327d30cdef18c1825232e69a2b09d539ed84dd2a4756efa64f864c563943b3db825824f294c1bbfa2157347b0fb0e7f8a56ec253b39ca9b6cb1ef7d3d7c93a6cb220a7dc50c365905ea5a71575c3aeab25b33523e4fefbaf66137f45c3d96db719a12d2e2d42fbd6cdda58c5a1b958b28c2a8f2cca297871a147dda92a7f008a359027a9288e42ebcd6ea9542f10b66dbbce6e7bb914206122f866d9adc1c89cbf8bbad9bc9517c2ea9018b61d4d2df9abff1dd9f3a0a6faa72a449af9c97e8c4090f3bbd9824298e61599c13c7eb89677c0e845ca2907c728d9296c24e96b6a348dbea7cac62671c9a78a531463614ce321e28ca2f093094ba5f69881e6cd766874622ca769ea556ae757cb7f9546d99f5c90c25e7b8e14f3b7f270861398800b0604ec2a3374659277a23cf6131c63148a41b05b3c06e2a98a268f1b9f0df7969addef17179ca2261d3c229ae3db0c490834564c45f7b8ff6d3bf70784779d75915fb2e2d5bc147bc941b9e249af188f63f39b028547cf080b7674b228e20a600e3b167610f814daf105226f3c1ce5e07834fd33dfe46315546e926fd5be83fd4d47ccd5bb8ae736ac745daabb59c87b9edf9a45c9a1d1617ee84e588f27d12235c59ffd9", ++ "slh-dsa-sha2-128s" : "0x0e8f9bdc22cad3613ed07fba30ed04219b9528f9b657119e2f0886dc71cda4afa7d462fe8bb108feb58d998b370b2f7e162390713d1a17eb7de781a604041cbed13d00effd3b24f2ff87cac74f61e7b7f7aa6a259dc283485179ab4bb966793be018c4bbf4475bf7a69e600a37246908f662813813d4b0f4f83757f4064c5c0713870a0b98b5bb99025dace06100497fda8c73d7385d123afd4953961066e7c8544de3fb620ef5e23174327c2b64089b3fe6df3eb86e83b12634a0c9cc0d7844c894ba6d83afed6becb6f5abcfff397c5cea8064e5e153ea4253abe599dec1614b449329ebb25861b69a9b22228d1a03ba51532ea64ebe7603474a15a2806d3dafa29d57d27c5fa894da673b85b4674ce835fcfbd391d328ef83504101432bbb0c83d7be462b265911aad862118af6f4cea4df0f1dd38969c69428fe438d59d22736fbc7dd5faf6758905b26ec4c99d71e4b8fcc562a694ead91569c9a916df5ad693cb2ad0b7ae4c4f3c5b7322f56612c5449e0339dbd367460c76ab89b6f44942cd33f35eaf33c2ddc0c6af793556d5202fd1fb0f9fa1b7ed45c6ca68d904e476477b71a0bc6ebe248c9b4585da0c7bb186600691269bb4c836667a6d73a455b97127d898b7fae17e1acc6dcc3bac3ecb14da131d5f8adaa64b054e2f569d9bdb164792038e107848882de9bbeff295905c2af68d4c6dcc8cf718c2de872ab6b3d18e00d527166f8ced642281302e2acf4cf4489072a2dc3d55ff8716619cde494be1763dce925438b33ff1b91b35eb511645832720ed92552d4880ae53ff6516cfaeb1d48c923648e502e4038676f7c82e532ea713c6b9348c80ce3c5735f437491d3a8b1765294868c14123af2e9ff61e394216e630c71ff976072d2a1c50cfd8ee1ce27aba5bcf9aaed4a51521bad5e5d5e66abc7a95b215fc8004364aa4df2b8b97b14e3950f521b6327a55fdff9139fb0bd35237b022e3aa128d36c8a60f4621d25d28c59a97418c7dbfc15d900ba626d283632732631ec4a948f66dd9db3bee8c2cf60dfdacbb5ad4c0b2b31f8428868cca035e79c95bcacaba40a9351b2b44cb29753b6b9da0a751bd5af84c9094d5fe91e97501d4f075392290e8516ed5e41b41b00e09793353707fe5c1d942395074637f3ee0a0f105876d6f28a74f9558c5f360e98f047a99af35ccedef8d5cd299365e81e7e91f28a01eb265219e21aa7f7ce56b62f9d2a61560f9fa39f2765f5b50920658100a638aad03482a687905cd27dca02f1deffd1bc49a1be1ea7ff1a505da74fd932937d8f6a8bd75ef456d5f7b71ca5357bc66db6cf14368c4faddf4996363251e6a6113ec64d642c319dd85830d8b4c7ee1437ebfefe01f27709ba0c412c266530f5b6bbb005994774e8935f1d91069f9e7a8cd2bb7ad6527768473affe24709c10294eb588aafca85b379bedf0b142b109e1b186e635b0625c4e59576266acb5f71040c44035fc9480b13932bc657cf332b12da1cd7d5c3977f51d5fa742974cd256e8e3662dc698e0516d615d0a05ea9caf12338d0dcb6151e07f184c9cbd5e59bc40b12ed6372e2d6bd42aa0eb6c3c888f264a8c0d3332631d4919c921cdada6bffbd01ca5445de0779f9723577ebd7e33ab0e5f577843aaa6cb8cb5f0508c33b63913a44d02b76bbb1eabae325581738fbddb5d4fdef8dcb8597bd29c6ecc631839118c44f66ef8dedeca65e58941c30e0423c40bf064b8d19d28dab3787238781d492720236a7ae0695ccc867fbb1cf207ebecc64f84daea66b6745515b9ac9b725061bb9958ed79ad6161318a262528004401633d47a023c645683e36413b8653fa4864fe98c501197c10226b1732337842a1322bb788a00a0de86758139c2d9ea3c5b26bf5d7a4a92cab4cb686c580e3e6cca488136f0da9279073b3dbef9519168ba02588fa29cc60d02273805b425b919a7e2e89c9086609982163e09d5f6eb9c66267ac7be363aadd4617d398d4bdeca37a838d650b0919faf13b78642a058b1bb96b2ed1482cef9bc6e8b2e061e6815936e15a9c754353aaa786ab141e95e5f6c464a41b8bf29e28e764abd638abcfb342b54d08c15ba7e24e6fcb69b844e16cdb5cf4f50db60ff0699f969d8e68511fcc9e16a58e100f80671af6b04ff3edda3a4f05f9183c0c3bb7c1061fee2d3f04e33fe75f1354e6de54f582da914da0138e8565ff45ef52f638cbc33a24bae863fe91e58d7c5da34273438f15e10d4f59db16e505620d97d3fa4862a4097a659925d0e5f4e073103ed29a600b051b83b1f3a21381f4b871c18d262d7e43842c34ed80661438c064aa2fd858a8f3bcb035b5e942baace7b50e4de5a73d5c51fc0843cdc163958a62d333078f4c7d883bd7055a602e04c853f9215c9d7f798403c007fcee124cf6099322629c449ad4ef84b7356110798dd87aa4d98ebb47abc6cc8748dd381d588b77db7f4e7550f6ee1ef4360dac6d6c7037a65297d4a0ea7999a5632b90ad48fba0a916846a216941fbd13d62ab36e1066e24990c19592944078435c52d7717b3556595b645cd2359ad151dbb67e92b14168cac12fb2cc5422582a50bf6e99f116751171c9b78744ef719282f1b84bf95b4092514f4c68fb82a1526e0942ca50e186632cd9b0b8b8d91e84f85e35f30f815601798fcae676da6a2d38eab62f22445099694804a36a34142150fb795afb445e78c241f0b645209037a8871cb5487c975975ac997a540b709e3df6bf208d9d8017f9688b152c9ee2b934f65393de8403244b7437108e6d8c973aa723285555d9eb92509b1747977105cbac7fc33e658fd51cd374d21fc2bf229928948292c1698db7934d0f9be44b137514d0a5fbb659bba83861931e03698a61cd20a449d0358a5fce7f288e18bb3eb62b7ba0ae75feeec634fc90fc45ce45239c5e3179309f0c202cfc53d9f42a617f7aaae586e7161a0723ccebb7e8586cd40e1fa12d3ee89b400dba8073b0080ffaab1182e8243afd93318df15bbf3ce179f21804fbb8882e855ef9e0739ce1536d8ebfe9856aefa9874b4e102e705a40ca4c3ab0ab7df63ba525189b518796590035ca780d348de49f0ba8f28456ca6f3e3cff7e761d961ad98b8cf01e855797c88fe2f811e41e787f3e4becb0ef42ca3b9979356020b447294ef295543e0ef512a247e4d356bfe3deacca8ddc5255e6ad047121eaeafe61d71e7f31395cf78890add4f8c688e4eb065479a63ccb3d0c09028bf60c700fe9d19195c26fcbd4130e6feceb52e192a2aa2343c05b43b276f51a7c55dff7233ea512942291900d93315438a96af08e25ea5b9ce656c54e71ed60d1eeb1665ddaa9e42378c930e21d93484b9a4099b7ddd71d983b4c42c6b1f62907ce84b24321422b08b847f1ea97befaa4ec30a794ad7f340210c800cf185ee2c6c72e844cc5671964e1e1ec58953500f149f0f0f25c34d5592de421c2e31535040020237b907e86d753094dd4532e1ab9d821e7583d4a21e1041fa7ad711f29ee3721a2aec6b0c46866a2de71ee850d8122f722898e533848e2bb851ed24cff9ca83badcfad88a171b4be064007aef4d759d93ae9b67b446f3c6fe504f5b4fe851b8312fec86b46ec3cfcb36e0f682e65e117702b888ab8566c9cc716a3a86106d2323c0f7f20fbc1fcd110bed4492a750befbfcbbe16820077dee281bcdf14509b93137a3998b2fdabc2a375b38857bed12bb8a9c67bcae7934d02d6ff89620fa8946c8aa524fde99c12fec0e25bd79788e2c15fc31fa3f27502cb952b9f9482580cf18ecabd92c55113ec4c4470c4dc06d8ca27a10474594eff708209e8f376b6f17915c2966dbeb0e35ac2f02419692c0d232e133b3907059d3a56ff169e7e61915c8b1067e183337b40bc1136241e862eb3ab3f2c6a72b18511c4107ed063d1e2303d0fe6842fb01c204d1bffad7e90bb44a365e62945a7f631811c9c37ffa5ac39c16b4835798686da5baa8e1eb6aa76b42f6b86863c30669486a175d6b3bc5bc47c5eb05b240bd921007fa39506c6605bfbefc9c8c493973bf3f0767817fd8ce126a301c5b8fba79628a9b3a03cad0c491a5f487dc5e89269e5d3bcdc2998a136a012486c5bce2e6c6dc595aeee2ebd5a36dd06919396184aafb2301d1889b668c4d701c7ca01b95f9508f47d4c411cc0397c244ed4e3e3ad7f97d86b6f8834b13b1b2df0625e6b4eae9e439815e65baf2da767d3b1700fc461fad6297fe4e8ed02bfb65b750c2d2801b7308aba9657df3c3ed7d548687f55e85c22343d1db343bc2dbe222fb76fbb3cf490cee7a99ab3a337c626a148fb303b2f8651651588dd4859fd65c95820ee2af85adf4e8fc2c03828ea7427e7c6b0d4a1b0ccd424df6d1450ee436c01351d8b6bffd4ba072756315968845ab7976813d93d0f0f2be1c00faab3ccafa71cd26c5837e87292870cf768c7837e18ddc3c513820c660870b339fc42c5211d33d892ef22b475cea3be20f5e47206efbfdbeac208e26e97c400edfd41f063aaa6b85a0cf86e23fb11274b405f4f796eb10cb97e70783909ad492ad9207ae7b3d204e59d69c886f91bc82a107d0be3ae85797a7cba747b8e2640ec49384f53c785a84cf8de37dd4048dd4b879c58768bd131ad7226506113c446fbf13d769794f1535d58e9c52e23c1bd55e13c647d304e297d968c759a378f1d594897a026e3271aa6b4daabe174d6a35665b35193379f0ee465df7827299c18e1012ac69913a0a5bb5142e99b051763de3e98d5af8b62133e25b32f4f12b787bef7e21dec42de8e4d99a0adc8f365d8cd3e6a5ff3064ca18965ffdc6b383f7ad08186d735a099bb0ee14506388c1a37f7a766d286d748d404457226b952ca6cb3f317b0f4399006b5b8c6eb89f6b8cfa023cec4d2dedde3e31b9a633c0888989b44ab182a5aba30ba78640f477ef1202f6496fafc2a18e283b2e4e8bc60415a1c9a7fd68f15cc1ea0299e3b26f5755ad9f13481a0563a524c6735942f5069dc1d6a070b3c3698e9c503f67a11efe59413e937062668d3439a5dbef197d24ebdc79944b17c549b0648af9b1349cad83c2a0a9e55fd893cffe2aff4626662ebc5014e70baaf7cdbbdfd3f92fcc5eed863fa8afd87f88873f726a0a2eafe41fa81edd5833f5520cf93b0fbf0660e48eb0258d313bafb87dc9b0d0d9349f22fa2d960238f67457ad644bdc60fb5eafd1c88dd2a74db4da0f723a03df08af6c64883f275395020341d9dd3c7fa049ab2bebb4d8af2bb8dc1340d1a80088c4b2c26bfe7314926ee64bf239306c05dc2ec6e6c5e0ed4f6dbe51f5ee09533f558d29ca6fd27092c20dd892c89c83223752006b23e5abecfdc733aaa59c8549e89e5ab0eae1b44189f58cf9cc18de0c2a2f46a9235fbe42c641a890039cf6aad820f1f844edc24e69bc3bd0c22cfad3804d876edf5491e88cf891c347ed5f24464f2df439bb30742e1f9a4a7eabd9346c6a5f93af22e67becc494cadac82cf9cb693acf44560672cb9227eea2575f90b0e28431684ae12ff2e86fded0be3a099f9ddd32a7285531de8963c9a03355f1d9cef88d7ed9b842d0066ccacdb698d42ff9f8a4f000b9764a9aab1f3146f9f95e6636fdfc9ef91c4d060a54ed7f32167e7ac50590dae3a2904d5d2eeaeff2930bd4cad7166fc17edd2c30e6738157eeb0b441491e5dfdc17a7fbb2bdc6426b2cfb26cf2a7e20013f1b3e33a6d6821928443cc7893f7e4a5268a8b94a6ca6097d25be17b214ea4301e9a723194983bbce286f4363a53afd9e94dda9c761481d9d20c7687a2ff85d42436b9d557d5dc6c5e24ea21d5231487df9fc7986100664edbbc51ad4921c5ec9fbb407ab33ef5c3b3bc81f113e68f38d73f0db0261b656fc344d2d23b93446845d69cee1704834d98737848d405f52f5a7bda3dbdfcd3af3881484579d2d2f3ef976cb35c9cbb76252f2e00019363273489b39943d212ccecc647413c56de69e0087532223cf9b28ce3f77fed30bc3ae6a0842b546e0e1a8b6f6ee1ca0ef1b78c3ed829af817099426f94a447f67229cbca3c07b7a8ce547c5eebcf168248e0a0b9fbeb398e5ed2d0dcacb441f95f9e30c108c725507e459d34c1ec01b67065e5e202d685502d6ff015d46c20bbeef1db38c29df7df585b95d79f5687474e71fff162c0ec0c96c94c507f8a0292a8c32168dacd2fff78b5c7dc145e10fee1b25c478172af8f3ea132fdcad75dc22856deb2576a5ff3e8911842c811d1d57ec203c77b82da3658cbfee18d140ac341d38a30f1af298cf60f2a88d0dfbd3e079ae64a07abb4947cc042925fd5c64bb5d4467589f8c495b0097073c081517bc4504dcd7442bad7e7acafc894fcf34f535979364cf5e908a84e0e141ae47e2ae4dc95462b4f345b12b0629502c7bd65579ec66b2d0a951302ba6da1d1176db6aa0c0ea1fa88195dd2248990fa4aba88490b1da4ea405649203f6ff6f734693f40deabdad59ac62e3296cdcbd74061474dd7b63c46bcfe6ea2b0ddb0f7e77fcff3599892c82425b05ae7aa1a2ac1dfddfc67e11921ff4f2c8f6297881dd5e38ccc4076cac8015c59cdd6023ffbd62b887b33ef8d917446a8941d9563acb66a6226fa4d3f2cc21604c080b3f83e73c093d8f2f7067c392671020c7a7eb6fd0d97af0d63032a3116c408b708d4b2f711c1134b88a91aa359608550f0049af2bb97688afc4352a45c4f6d30d4634e70e82515ff1d5f77851ee857e42b486d5e1f3e0406227dded6c5f47eda30d94f44d978322891dc729eb6ae95d29d22c8a5d649193d5d2aaba782fa16ae488f645a7ed90a566e182f97bc62049724f4cb5fc71f6bc7be57f07a7afb9933f6706cc83483cd7dc4182768cd35bc42f1e9b54d5454d3a17e734475ff58fc66d75419d3d122eff05f7b0548188682f1318ec32c5bbea87c8624cc1e548bf18a6b102e7a43e6bafb579e4e84275fe07d8c63ace449a44cace5d9305ff756cbf40e5a6a20334d5b4a74ab0483e31593f2277e90341fa8036496c2bc6d2b7b10b0b354c86d666d65cacc593d1d7349e71b0360d823453011ee16b6280f5c048111b99b185af99e9d901d4eaffd8a96b1ff394b66208ddc1e7e53420fa965bfc4e630d73ad97b9c5c6ea884c619bc24ac3f46234e7d8d35a12b0cad7220d7a0945cdc64fee9d8852bff872c43f359e7aadf8fa3de3551fb716704af68a18f79d03b3c7d90cf21eb4bbdcbb4004f8ba15ff0bbd2d0918ee78e9bde980e4f3cc13558e6fdb40ca71ad2c10f5e5587784bacc6b925f72da12528216895e0ca4b350d078fdf534fe01bc86b45e0c8e2b35799d268a457f8768ed782dfb56abecfd2b9db00cd10e189c6164f82f5ccab423277e3465ec72d76b696cafc1cfa9a7fe47d142fd6672d9c5b77751b40801af07fc53b1c9da0fe6981ea75e066572f7272baef8fc54bfa7cd71cd0fbc5d6cd717e9aa07808496ad2b4b4005a320c9312c73385afd61193581dbae99df6c25f1b9da17093ccfb108b0a26c5ae4963183533ce2f0ade01bf5e818af613416433578522b1b1e5aa7c791570c8c8b26ded266399116f5789a8233fee128e54ca8ce63fd56c1a146c3006316d200e05715993d1d97907ca83d7fd42ef7e7222eebd74f9c86b6cefc82e614a53976272c8801bdcfd882e34d86b39142ac05088a4c47010a71107bc72a380bb3e5122981d1795256beec20a0fe568002d79a4b1577903fe8682f268eeeed0a97861337ffb6861bf378eba1e0957111c7f9fcfeb55a95238005b40e13ce40efe846ddb86d14c9ad2c46cca74baa364ed08da3a3079fae3a36346ac949e2174c661b8801a051423e95dcab6a0f9c965e8744bdd0e629bd3c1a1241e99951ddde184eb8f354209f24c04fcf10fa8f4e43cb55c922c28be041213ddcfad65c86e1ab9b615f91d5fb11e4cdec5b7e25f8e9811c82c2ed457d012e4967b555f228baf4f1648854c624e0525e36e5f4d1961bfbbc3621d79bd6bea72924d8e0146d0965c239a768b417ea4c33237a60fff2760a9dbfb1113a37b01b598f3e06987d99518bd9f1ec96cd7050863898c8664f793ef29114bbeeb9afab8ed09358d1227d7de2aaac0ab2391cb2013028ca5f4d1de6425ec5feb17d95df358572fa27fcd51d14c363a36bc37c7497a0f964a6c004561f68349f828d30d4633e87bdce6b6d92384c9c1c540c8295ea621e9a8006a8d7c163b988853071e06c78f1b9a0246db052e8484a65cbdced3a587e45d9e2b49a5501590cf768d08b6a043971110e9c9dc96abe855abbb7aee2c38bbb77e5c68d61f01f2376b6122450117240532c7c840e3739395dd6c9e80a432423fc5e3a6dce9dcd58eb418e16d7aa507b4d67dd6fe2af4042a5c7398ba4f87c650926084efbfdc9430a4bc2be544880ecdf7361aea06a25e4f592104b0d74312f2729a4db5876b675bc0fa68f6e41e014b7caaf6f49b8ef704b6243df410dce94ad2c51d328fb90b9cf2f5df645015f489a262f57a5aceba40a56d343403b660928cd7a9d165f4a5bc289c0d28f33dac85c9c2a5c79b5ddd22c744a0388a5daf4bab84d7c77685053c912c9a24b5a0664c6253febbcf552c4ff38bbaf2f7e0c9f06e69a91cff9138c2745b99367e00ff6b6a920b1812e17ba44175c033df0e58d1b5c0b7d146f861b62e812ecbe99d638219e0dba4dd88089005977bcc90634c4dfa95f87370d905d32f613358fba2efcface0b9a414ce33b09e271a647b911843933c5d1008fb0717ab59739eb8eb844a4b34bb1a8f635c5895afa285ddc43720e78dc81eee7db822896bd9bd6ae3e7fe2988ba560d58f02592870647b94aad1dbb0d0cb60e28135ceb72e0a6f4b7893a56eae83f9d9a4c549d53d17c6a00f5d6c266d23e7a1d13e22a5fede3a7082dffb34296f8fe9f3bfe525ee1da81efde3aef9b6de8457a10fd4340809e1dafbfb9e2719c327a3c3a4c51d4d5600e8a01ebd5c537a4cd7c4519e963de06de6c83a9b968b01f79e08b5415c5a9d6a92a633d6ae969b80cbb2cf4d6d1ab2c3b94e7c12df27ea89bff4014d92add41a3e961006a194ae3ea4a6b38c2827f6185ae636f6846b1c8401289696fb10c765fa93e58d068bdcd8c9dc95df572f096d65f5de42bae639d41ce7e1ee0f48ba4faf856c0cdd728956d7e4babd6d9d6389ff41d76c5fbd6380f351b05a37022dbce0a6a47ab7168c82c77a2810c80b1882f825ebf86cb7f6d0f54025fddc9b9120802514c797d1d3968631dae95297a857890ff1dee408909223d012925dc08b7d1119fefca7466392a019d4121ea76c8b4c3bd103a820557e4b2283e262af32f1edbffaa253c47d5873bfd0219b8be86c7e64ada2d87ab6b7f428a7d8fb3ae09b05aee71054355eb83ad76c05d836a9f1a65511b1553927ef1b19ab1576d7185af61be6104de1df218918179c6321846085a83bd1217aa63d0b03996ac1fb4018a8ab54fcf635f7d5a8ade95894f0d407e5d4691920f21094c6f632f1661402a0b3351f168f16a13d3a31ad48e89230cffad272926487f36c7a2584c9387623df6227be8c96088db4a21c93b1c88ee756e960f60e614b30bb6ff757c20f3674a7ae7f6ff6a9115a0a6d444513ccc0be5dcd557430e0ee8db3ed5b3e8c405110500b9bf7f6eb7748de4988a1db94bcb16fe33479f64762c53a1e2965363452063d7bc14386ca7b4d46ebcf08489c64ab413ec0f1ddee8719f5fe978d38438ca3059961ecc8480908cfaf139d88db2facb5e7a88a43a67dcb0f97a17f9bd5b09b8369803ccc7ab6d41238e59e43762965814c10c36fa4b6e61bf2e83c0243f20ee8aab62dfa9827aec06f99c5c565c1bc75291292d3113503a202851c26d1a8bde54bb30f0301e555374b71e278925a2afb29b0209c08ecb89601bf612ce811a493abe2bff78e7fd02ee13c5db6b3edce7c87559410b9be3be95465468e33af224d6508a44728cdffde4cb14fb96a0d2ab9c7f597541f9963775c32ac613af9beab89e0ff7a5e35613751061b0511532b10b3947802901505c8e33bae67ce0e28da760af7e80b730811bdf17abfce39d35def51d73a084119449038c2b0f1c86d844123c6e71f28b7038053e279dd11c088dfa11c547a4ce13b19453e88e5b74962101412490cfb68e21d8952db509cd3a814387b67339fd04ddd2163177589146409934f0eceb10db2d90a9e3f6691eb75e84d5e66bc3228baeadcba200f3d11e0cae090ffbb800f5da7032c35ab572de55beea37258bee6f191addf01739a26efaa612991cb2a3c6d1bbb03de0ee1fcf9b7f6c51e452b21c0819a9aad93162eb2dcc189bf355ecd2c3e504713dab24bfe3ed86a4194611029f7f6216cd469fe1f7d35d56b6c8c2045011e238f9cbc0a19b8914d74329e2472f15d0b7d60511814ad2736d6be168aac01868c2a675549c849fe05e05a76f077130b46896735db5490277b76bba43545de6b8ecb53fd20398eb94dd884951fb48d5690ce4bcd0b836615cd9340ff0cdee1122743accfef343811a71c7d14d1369fa49ce47784a6ff8adc26c151edd4969dba513ade6a9b1f009e57c3d6aa845ddee275169ce58e1f04b564ffb6d0eec75f7172e5e8fb814cd702c9fbea8a783bff637db8667d4b6b48a264135bf60acf335936105abacff0351ba9aeac88e9522cf7ed80069822a7db1a5d8221d9492e02ca893e1f15965fb82a80ee2ec491027bbc8906e71cf931fc21e1c0865ee06a79c023929625b4d232c7b3e2e4a4e5dde28fab675391befe583c95dadae71dbaa43e09d8d65ba36d148aa85d1a2a35dc51719ac0311ea72c1237c78a8b1542c59de3b743087245e54d3111c585b5e5e7642f625c8d44c6d9cff50d8d071f6fa573df937d9e7457302d8b293d8fd94ebd3023c55f8b260c3454e93f58f16d0f451189bf41c9f9b91d3c3918adbf98e4ca5aa0eb6314041521ef880ce18f0ce296721a06b329bb5fbb3024e424b46400e03caf0105877465285fcb41a93844fb90b7fc1924883ace6ca8a37c9905068c633761163affae39d0ba55b67fdc6bcf0908ee3a42af286c" ++ }, ++ "transport" : { ++ "secp256k1Address" : "0xe23c5bba38d809fcb2d3384f210e9a6405beb498" ++ }, ++ "ecdsa" : { ++ "addr" : "0x48fcd978ac4d42ff52dd81fcd17e93190f35e5e0", ++ "claim" : "0x2dee91bd2cbfa906aefa3a8ae6e2de773f55dbd28e77bc329d28215183068585601ab9a7f9ff0c48095407474d502a3af3f059a666e5ed1e27468466d69914e801" ++ } ++ }, ++ "1" : { ++ "id" : "0x690a7fd66157e5b777256ea5214f634f61b3a72d", ++ "keys" : { ++ "falcon-512" : "0x09a6d094d9a3a0865864e9a16b477236f1ca26c888fd0c918db331c87a478519c41085cdac7e6cd0d89190a41a3bd6f4d6300995d591f5e22a7b7147caab1f9c7a85a4ba74d47c7b227326ac17535de039a7e604225d3daac7f75b9544654b73f79f5825825ad6e6c45d13e6d385a644633e1c8806d3a0a551c98f032583c95fb13997e52a6b02192d26b5a47fb22ee52999ec92b75c70774a4ae0481a79113ac72346263e53d5dcde708668d317dd00552d5a40ad47e59a501b10a50bdc52c5c2b2c920fa0e3dc9b8eca54b10aa5ab1168c88287dcf80ecd880a8fdec85b6d63a15b9f453845421a5d9b898e6149b60454828eb9dad6442ec62ad27ed72215014f3d17539085ea3f668b0a9183ab96e9db996801c72a0920b02a249911924f181e8dda515d114beb83b075ce7e7a0902a6971e31420ee4921f5cfc123f29dc7775017aefe99a7e326119cb925f6f603ac3bb137313609498d5a2000c426cb332c82500dcfd80d70a5e2d156844a683b313266af6d60216bd9e9998bda53c0028f387ebd21a5fca6c0607d54b1e95724746d15f25f16e45845926a83c7598646a0a0d3a8f8307c1a401b823f1656ca41e5499684150a954318da076af9131fcc93361d9bf0ae035f617e02cb5e1224a982b3591b24013ff80dbb61160d2ba4ce85a4260c8a3a3218e0ec869796b1b04a82079cfc0ac26da03b04a11950b2a3331ecd0026ea9737bd20e6ea3045b56e3c71278d2a8c72c8014b769da9319e19dbe762b1943e5a4be15aa84d0da831eddbb10bd05f35d55b6211d02a61c5d9247e69cab6c112acb568ea51f345a5bf16f84782e04220e217722da71d634e1a68b796376c8a49a965c592b87d06702fe42dac12da108d24ee42a109e8e4cfd3bed6ada5e3de50301696bab0564292864f1b9f47d5a53cc0c5f9cc3d57051065fd57064d08764892ef4c4a92b475184a4cb4ce1f3a0e6da0402414db5a9db34632b9717586e799b06e870b81a330da7be6a45ddfb000fd337a24a29e164449f96be015818c53aaaf09b9a565d7d9d735b9493885e7cb49a5f1985977cd6824fd62f51d2a1e60289dbaeaea148a44dd8876cb58b8ca2f29f6455f354e4e76aa13290f2979b78b22afa0e65c696c21497e94bf0141ac6298aac70b5ea843848a2264fc057abd3593cb17465e06d41731b7153b71f8f0f7a06d362fbd09845f0815794050460b41ad003c9396a86eaab240555ac8c75f85c0ab972c1a0b94b67b1aee2fa3", ++ "slh-dsa-sha2-128s" : "0x2b2fea4a0edd5dcc2f653eb2dd000aecd87deffbce8818aae72d7862b506bac7" ++ }, ++ "pop" : { ++ "falcon-512" : "0x3968f2999d69a9c28ae792a90a47363e689bd4b349e75c5f837181fc7b16d3d04489bbc32252d750d750417770630c5b65b88cef918ad23e33892a58458e9e63ea591596d3b898f65e1a5be3d36650c3d9834e1ec725426960d337b8f25878525ee3c3798b5afc9add5bec82c8e139c59738aba9ed5f42d11c886472e81cedfdb5b910eb73e884e0d4cc218b87cd9bcc0bc107af586c65b3949460a25892d9607efa341f232e478f3c9fc2d05f324ee6eb7bcddb72af371d47c36856f488872249ffdd322d3de7d12b62b1ec595187b5b363e36cc714b765f0ad5616488300f6e56811e88e359365d5698ab123b917bb32f56566958b154f6fe052b894ccc1fcd99d65d19e8117a8ca4887e01f36f181461a433fb9bbc1790d8b14e34a097b149f0c5c075ecae3501944935f3caa76f0b9370ebe6b90390b4d059f9029ee4af98dad33b9050877d49c3d4f2beaa4b5861a21af95b8c52f9ab4b0eb115357f5b1d25fb66a36b9baaa4d6cc5a4f5fb5462432bd82734d7393cd22c68f52493eb3434c3b88fa255baae5c46c650cae17ebe59827cd6645c6d377b3cdee3aa6a758ad3a96d103bf6ab8ae03b72b53f3aebdda359288c32ff5461a158962924a97a24af29f6c976762e8de9363485ada49c445566e71ac75379aaf7bf190a81c671115e842b5280a05bfb2ef3724bb74487068d5b5ab2d089ebea7ffb4381a7e96233f0915f295d3b71db872393bb990b9c74717bc3d72f6271bc248e54828a1e090f6da56de3643b083e9695db7d0a32bb42355e245e5cc2ed57354d82220b449e10cca1cbf6fbe796d141591d6f71e4eb6770a3c7dfcee509c3c28f2f1988eeca61833b6681e6766790c2a6f043b4f67e145b908ba7f03361cd9d435d054e11edd9667e4f9d12c2d74f2832b619", ++ "slh-dsa-sha2-128s" : "0x39254afc16b1dd8d4fbfff766819460253653dfc6a8e29abed55ffe91325afd578ebfa2dbe74d46b48b381e69d269b5bbe24ca1b85767bd71c744065fa47c646e3603b44261731b50f2d20a7a327e98b84c5ece73697739c8057f99d6ecbc54cf891649fa78b7bcd824972f3b27820ffda3629f481b1193b922cefc907bde3ab1c78b5ac97ff26986f3a553556d0b158e936450b4f41bf006c90a9758e0efb327f67408a7b803ede993522cd9042db4a672c89d4765a0fff8c6e8bf6882a8de432229dee08ae13def90f9fd0a40c99f3d93873a41d74871aaf407b0927a817b476eb93c645254bbc77d131e0bd35a2541248172993b1064d5b26b921396c8c1664178051810961039b15790862415338806329a45a266aece5904312afb1cfbeac1e816fb96256fc6e2b059c25af1966b0bf261bfb72afd8652feaedd6e0e4bf829a75188708ac9c623d4d6699281913bb563b96818f9307b66f7cf4aa9591e30c65a0b0885c22b5d17ff610f40bf2e0a9a32173b2fa7d66c14784402885d84f33fc75afd8f743cd10f5ad6dcce5b33a8f0c0365de2ce1b69aa86df2482a2c2d3746c6f0ee4e6fdbeef5738d809f6b0ef3cc703b0d29e93e198b68d62a5be657e69c33459fe4b163a5ecd72a90f1e53fc00bc8c698af7ae3cc5b07e36cb74088066a54138d6df4ef6e159ce5924b6903346a5fe115272cc951e8713d4b6f96f78d67a542c3bb402e69bdb3c2b06e189186c227927b2aba52b29c14e837b37798321fd000ed3bc0e386ad6e5d3a48494f57109322f0a87f7dd752d862dbf772498154804b09eca84c305595cc1e6654b1b2e94d5b88feda176aa144d3895a249754bb2ea99b2efb4f61b828f265638866a49dd3437c70016347d5aae64c79957ed394a85cfe06b10b98b6e83801728645529537a1102bb04ada4226688594cc28aefb24fbb0d1a60c7b826dadd23f301517e862c67fd88d0f6a5ac08e7f966ae375b468e57f01521b43fc24c761838c174ac106c4e1f435b7ead5e79aa1b303222f6b45c5515d497d8e7b05901bee96945652d304ad9ebae2153321885f19e7ad08c9da73ccc22a66c26c4cdc9360c36e307310714ac44c80887f42a2575305ef649378d76d297dc6faa904377b2037618f23b8be496fbc680645dfb80a76bfc060c6b2aee4ac5537e79b7dc7deeca0ca38041dc877b875cab1a297190269c987dcc46ff34e5bc154e2572695e463542be79d61fd5e96a4be2b07f5beb71b882f99de317116fd0b36131a88ff9707eb25594fec74cf76c2859ba6ba2b968d41479adf8857f4b0f4a26f49f0f04fbae0e2f3c2ab6aefdf01855a7a5a4b8bf516f4551a393a33d3920ca3ec403b4d37c2106d777e3d5dfa768614513885d857ce95b9bc3b992808e7ad71575e5e91b8107c5802043b221c74d73c7bbfa7a191945bbc5ed69e20016b16e2e2987818cfa80695e58950b0c1bbb8c474f861d1447161744c75d99dc8240338c43a5c19a8a9f46d80f6b4b6c1cb57f5a3350bfc35a0522f89e3470ccd71a458968c629c93336af6b5b091f569d1fc9492eb6b976376b8ff19ad9318f5cb1361954a0471419b4207dd9dace8c0545e74dfbb19ce3fdb5d456a1c1bff7383c6fd96dde3a92daf0ff5a315714c74711e3c05e0c59ba525c64ebd17fa20f8e143c5931b3c77da193415e6506c2db27e0e773a6a5b5d47ad95760b8d471d06d5dfe000a2d47e6e4e6abe7219750f1f7892f4e09fe88d13c2e3b53dc904ad58eaed856a4abb0c10830b96bfc1b5764f9e4b34b0072be314608fdea8c5005d40ef99806d4d3edb72e73541fb828d4b2adc38855e09e974293de25da6907f5ea97810eff1be37f88ea879e545bb5a70d2187edec81bd57a95c0314df4ad08a864156579d50826d0cfa511d335ff722e246151a7afce94126232f6bac89b13c142d29e7521479866e35b17c15f16ee89d798ee8bfac5868e505031586b81bfadef4aafc2ecdbde649f63e07eb6026d09910d9d3613a9871b5d1523cf5958124f96b5304d5225b4bbb03aeeef87753d0b6ab51a287df1e9031f56f755d3fe5a20f79b7f0f467fa97eac5bc09a1adc6ec285c8f80ec5c184b8b5eae326300a5bce0b1d757c8e4f27ca2822e73745009291f0d9032051e15b567511908f3ec68840cb6ec6018a9a0e30f2e34759743ef0bc9e12c9b32f29f4b70a998cb8893af2dcf17e0eb4f48e7ba367f68aea5516e7248c8be1d1f896d7e8446fadd9603012dc13126878300f0868bc512221154a5104882621f831e60b49d04fa8a701256b3a413b9db4abc5af10a3f8f4c26cd0b3c2f55a58c9380143d835b759bac7fef824515a18d79b6dbd361541047c79653ab4af5473b7b7e67a6755add78d5c14c0a9edc6c7dd42c3d0359d9f2f6961f8930458a34c4f12478ae45c20969c4c18654d31a7ae73902757b3b8a4eedfd16d6c0d22548d7b8ba77aeb4c1e3f3766b6ea802ee9bd92c5f98d00be80c15e7e3a82eb0d100436c398781607dacbefa98c87b3558f363b3ecb1ff313655838f864c1b2e0f6d6369bae4eb8cef98f564108ab2f763e590a9e9201f4e28ef1971438c30f4376c55cfce9b9910f448e31d06c2e456eb798476d56a890660e45616840377ea0574d1c066ae2fcc46f41cfbb511e5efc4b5c60e00e4846e157bbee5fe3bcd77408e3bf721bf871c05971a70cf7a13c782bb4afbdb1ef800a414260243fd828b67f49007eaf60b3e32f4e2b8186291075a0b1c0a528abb9da7974b3b1e8b20d337161ce234db66ce82a88ae1dc880933343961267cb4932b36aacc5f136cb474bbdb5e4c4be4cd74868775d80317bfba00ca4e58a39d04e63bb797de366c45efe2e356672f567ed1f7b2741df7543d6faa7227601eb7cff367d5a1ff320ca71fa2a1a42866239cc3fa5eba400ee4060266a05b8fe1e729908b95ba6aff8fd76b5e7df547df62cb89f0605c1207c869d7214e4e6972ea6e47b18235855d6f28265a737b4f64f0d215943f13d219292036c1cfc46bc61679f034919e4fea80d882a5121cb3096a50f2112eab265ebf75b607b93e14ceda4e08152221bd368cd1503ce375188d23514dd0936bf980d4282eaa6fe8f38f5eb00c34e3557ae363538a2c15b560b9f9322d1f17446e8f3fd317126986afc2c5e9fbb96f8ca7148f53cd75a4b845a28034c8679baf1f5406564b6e4b8fa8e681b5a9d208f3a1b28e84d6d52d4baa152524908d50d71d9c0d11bb5665c8a6bad669dbf303027bd0d534434f9e76f2c300326e25d00bd8d3bb1debe1c3984961c0ea8dc547e8cb83a8f3b044b673f4a08882d103d6eb143a9645a9a00fab6f1167a2c09015d6ff2dbe4aa4025f604a63eb32330f832162b6dd9364f4ad6afbd86c8d26f56d7d9028dbb3051c85a0c86ec0d7961fd6008f87dbe8347fd5ed1dc4c27285364f63650f161321daa83ad41fbc3412bff800c062a78cc5caea330cd58e63ea9a9d6de2ee069732799f52f49d513c658a44a2122b8427a405d706f740600f855130a0ea720f76b3111dafddf0e2ebbd13f60640379993889089ce508b1343f485457cb8e0c09760d3199b4ea940d584417259e41f2c66853ae4235b6f010cceca3859952b3daaab55da14adff0e421e862f138872c2577637b3e12b00384cd32fb3b9c97b0d59e51f2488e379065d79f5a834b076ab5b35fe4c47f2c4c4f43e622527abb8f682fe9f262d2883fce5c9f16b7566c4e078b67611abf72cb8a0263ba12a6c23b1a04458c759f2bdf6dbcc460bc5df48146468073b61aa5ab4a9c5f6c006f54f1bfdd85373f33af29d68580eba4cb6dd88054c81b3bb7f2be8186e380bee0b32a1b84ef6319798079828080361bcc27473a9634c23652ed6b2b2c8f8d5a6721551c780870f1787726b121263e74c9464a76282dca27249b4532e49455a7485e2cda4ccca823f62d3b2869602197a6f1ecfc9d92ab6e231996e603e81e3dc648aebdfb900a3d929502ff0bbb3dff813660c9d5a417d857c19754ee04e50f1241831517fc2d2a71c5e238a944992cc50b7106aabb5482fc7e0a2e6b5b11bb6845f34ede98a18d5f07759e61603de502b5eaabe59a4d2c69f4b0f8e73a9bc85b8950a54bd91bcd0366dffaa0df736dbbbc35d6accb5ab8b22a870374521f2035c1878718d7d3b025838da75d8bfa3ff36b2a10a3cdef1b150abf3b6be95a5c096a921a3eced20f509dac4ba43f2f515af2b65d3b2ebd0da2d7a58500157a666b387b1814d0a3e84f64d0fc44507b0b6792c0c6bd90ab62e0f75b66d50b6f842cfdbecf1fd043d642c5d5b5fe5cb68af62e6e23cc6f0f9b1cf3cbd0233ce48a996296b6609be1c9e7a027cf76615dd11208f1fde119099352cc17e1c9a22f4b71c3e628d72b620f3cb4bd40e4294ff8dfe19480b5b758b874a737e6092254638a222c83aac52fe0f66670454c313adb0dba2b4e95741d27104bbff159e999e23103c00470a7feee6f4a35f764ec81a8ef520cf1e8623fed3c06b63c022e40e7638db269b8add119fec50456b33224c14486f705e5b3339c6f38aa4ba6dec8b098c27447185ca50cd70772e5389ba703a4a9f8649946671a238e1f005aba0b3a18c8ceda9daf4cede6782d27931c638af3f6083b2bf10ff0a632ebd4dd528da3aa2b7a8bddff2901d902b26d518a058921eb0178ef08e24f7075f77ea0c0d0e72f29847ac7826230c0ddb5e7fc8552ff92c007e9141f51384a12e218da4fbfa9a7a4a1bf266aa975949e120db1b6755ff04adb07c66ba9619b40396072e7cc01dc3dd56f7a2f928a82c8906be416f6d5c41354881f9a6c66a927292f8cc2887aee86e90da32fa3bd9d72bc26dfd334f943305fbe4b645df83fb72c565f61860a480dc0f2f3360368ec3715c2c4a312bd2653051c8f29fc14e0c3d1f515e04b75ec02cac2aad8d411306969d9a8da08c3477eb6201bd54c6ee643d87a89c78a5c8ad48590b7a499cc44ccb812866a4c48ec2da5f1e0aac741464b26988459f3724ea4cf103c27e4a43e5a5fbbf94908878894f8b62995aebc20e632d924c82d9669f64b2093cfe023cdd1542c8f9d19e5e7ad6ed7920ba6834cb0cb91bce48fa94be47c1833c6ada4090509ba38defab7d56dde8168bac8021fb5a2aead00809f1881d53d26fa9cbc824488e16062fd9f68726c837234a82d518e3d10c9931295d20d9affa5fd18c0b2dda299cf1d6fe0c6e6959440af9b397f3441bb9881ba1d2df295d12686ef6b0bfe52fb2bef06620721374328551040d2fa434b161648b058b74df2a7ccacd7609b93421f44a136079c79a3e63bd3b4f79717f3c121ceec2c3918464f5619b1a2e83a7709fdf6d1004b0ee51c73e740b20e329847304a82802e02170db386e360dc6027aa7ba1ee35d7eeddb41ffde093073d92899d568bedee914627c8c48427376e7b5d5ebdab30e58147dac5638090e9c71921431f025f1d4e3ba3c68437555357c651336b326c9c519544363d5f4faa91914195314cc873ef97068d928a6b4e5c6ad70ea7a7b09b3108fd5696aaab800eafe463ee52a3f29e1bbe8a968e84b762484a13714ee260759b4492b749c46ab6603c13ece34e301c13bea57d9de706edc839f55b432b9299d2d6643817cd9d32d0d9ddbdbb23acef51992b62db024365ac2db4c432c531cc1ad18c807cf1ee39dcd842aa9a09b232cfd09bfce33277a8ed09953ab3b5d24e5a8a02fb4a02ceed705185880ecc47cb245665cf640ded4015b4afda053a5d1dff77e390c8105961cb3a954c28ddbb9efd759080dea99e94e69b03b928c8667fa4797dbb3cc6ed093bed107c817780f60729036f13346f05491fb837ef1ffc61be7b61d0b7f8dabfd49ec24cfcee088de38daaae6b4e740ab4faf16eaebf89962331a99f17ca5955b15dd1fa493b91e7cd218aebbfaa7d348b1ceea26951209137448caa93fa466ca32eda497a5b9a4fdbd23a10d9742e74c511a1648d00bca3ca23abcd4f18b7cdeb362e020c73888b76b83e70d26ee358c06933f77d1221a8ff0647200e451e971fe45c23aff60a88baf46f59a0bf94e99ab9337b0336ffacf8e79db92067d2b744134cefac1241dfda288f5c6ab293df7469ae0926c166e999ac99c8871e571eab03f82de73e9de2d8f4deea3724f795480cd47e304f27f2567cd94cbed52e06f1f1cf7af2feaeba8b95927eff950bfc26aa0cc3e46ec7bd5d4aa43374500f8cad4f153cb586620b9a0deeec2cb12ba48bbc8655c7fa70ccf94aa6891b5cc8a3c98b482d906d72e9d425301d0cc6fb4ec9c4a5bcdfdd74fdcef68f05fdb78f2a1c5ae32c28c43ee900738f31ac1fd337ce95966b3f557a727e0c3ada6c6aa61219d92fd5cf68fcd9b444f6b4fb6178b9c74238d2575f442a298127f282b5ad416cf6a365a214048489139918f93ec07f2cd864f5482c418c7336ca4590a7da8a20d33ffb7be19934c80b64f4b982a55b129f4896685534b83251d54e46a2971c0bf49ded9b13a77ade3de9a61f2204a46ed9cd7bc444801381994c8ca5a66abd70936f8d11e2a2fed78fe9fe8889dfcb979c9a3f11f2c2c1aa371d1e98c4fbdaa95d58c6b22410c0d3d3460077dce654a1decfc829f117bc407d06ad9ee6aa06bf818ea2f25312b1cbbb5de527ce9b5c5ddcb0df21e3442ffd149b24af5e59eb4d7e18f68b02b26e57fdf23e7af4fde3e672990295c37186ca67b2abdff6b46e1ff106f041279b61560ea2eae64649c65be22f9070c3239b0cf7929b0778c43dae5391d8d3b8c335ceac672376588a34d3b9c61833578e8d5a9e6e9f72748d860d7af98f7616431d1ae1ca20db3db6ec99d59fa98c25a1cf478e1b4a643c2fc9d3e482d56bedb1b7a1fc9c3e788d9de281c7356b82e3c9e1c9414a0d14cd07fea5364b6a22dcb3b69b6f447343822098548e3ca7e88a83187db145bda17f7c48cb00e6ce36d53e2d1e4c169569ee3fa03620a7131bd5c033062bb82cedd0d0ebc1025937b2d85a3cbcf6ef4458a57525a66244be3a62b582bf2b88549431cdce09f6407e1bee83d3fbe205f585cc7cf9c1eaba047a01f51e13bbe0715a9112c451f1daf6074a1af051d8b98863b6fd03238ebe295995d60e7a26d2f95a2b4b0d617af299133bf357518b84e942bc36a88b4030d91a7067e7a2ed7bbf4e9abda8c6887ecdfebda04dedabb9ea833123507835e0357ca1513b471da73102605ed03297b5e3eb7d3bd01c670f992a7f19962b706e8d0ae0f073638d633b34a1229b6979b8e90f2a536cb6024c644e1f7ef211451dc509e061b294c28be188c96246614a1fbf52db8d9a99f7100c878c1b9da98ee9e9eddf7fcb386061ddf46807c60b24d665f0fe7fde205f91021bfb87c8f4c89b5da254d185bda9cc2f48303b483ecbf934575aa45d0d58cea64662f0fda4d97790bbcfa237984cfb45a9cd611b533dc0ea997d191d14d307c68db318aee8f99544fd48fb86f041fe249a14263e6657a5ee732f7c5c9c97a8924bfdddfd75dc67da65042e711a3cc144f46d10a1a9fdac1b1b321eacd235299a1fab390df24acb739d61bd60c6907b9a3827958198e6e2b5a1c90cb9b44cf8db9b6e45f710d7a39c230ec9cd855af797555fb1d73492e29d17da0b6dac59c2ccde0715565efa1f62898c9b26438c60fc3b9f859bbd33a8e05e1d3d5a762bf19bc7c32cf7d4c6bce26fec6e5c8c537608a1c2aea2e1e5cca5bdbb45a8ed048514ef3d298e7dfb9c5408d941ded6220a44c184dc90c922a3ae31c9248c5f31627389770a59f9431fd0139c5ac0f08f69151a75a5a6a0355b7beab6be9829146ada371aa5791c861dc77598f09448af20deca73cf98a399f35c36f1167ba426c6cf4b8b9b8a22b961bca83e45bade098e20782a9f70bd54fb8eb6eda3acd3a5bbb553438cfe37e1f7fabf15729d6bd562cfe379d586181b71b3d3c4b360852003c4363a8d473198130642972eb3434c3a5ca9b497ec7000e821c3419aae75866496bb1b0a9ac6cf92f799071e06809f1f3f904cd18f32629e2093664755803f62f45942f5a358cb1e925a8694998cb14cfc52733c356cfd739c3976712ca7b007e08841639da14e429c102a8fba3191cd36c1c56eb06bf69afe3f2afc4ebf137c617faacda6baf5cfdcc6462ad02f63e8a5375288d0de5700d0f9f4ca82a65bfdc405d3f96fc663658f0aad91305b86ead3b21bd6561a40db0f2c5b0937ba5e1ecbe91e9c50b1dd6bd83a8145b033a7bb6a4ad4896e0ab160e8a52d39d2756b1c8d8570f7081ba217fd8803954290788882befde24b4971723b0ecbeea14d23c92eb6a0d7022a84aca072729d7ab1a88927a25f19a2086f846a44a2726ea26cf1b69c58243e219c756d06c361e1e161bdff0eca10bd30d23782b3374ed421f50cb66c9ee063ca622fa78c8cede932848f0f8f91bd7a0eaa324377c109808bd66ff463a72389c4b49f2e349be70d07fcb56b28549fca65ad853d70df66b587390febdf6b1881cce6c1ca9e9fdbc9f1ad68ccaff97234325d3c972b57ae5723fd73f975ba640f90e717e9284c111b76367c6797399452d37df6b8b8d22ed5e7dc1481a415fadc06673ce4eb6435d31acb6af68775436629a57db7a0aa192310e8427468e8e310bd3426b7ffab00110324c0c7e04ac6649b6f167fa8b928b3fe12ac162db3f2bc355295650fa2d976c64df69a8017034683bb4bd4baacf1cd8502dff20430d48c907107acfc4e29c584cb497b7a471fbde90aabab25290d853b8ebd2c0d49c2c201eca42a68a15879cf391671946319427b237472cd35431128ea7ab6d545617321592c07b09fff93e71596da30689b3c15368a1c3a57890e0ee5752bb4356290024fd1bd2ebfa19f7f3ca57c36d296ae61ec5581ceb77618dde2821460553ba0dd6dd68026b911f4af1be3986198966f90ab757aca2f5143f1937d09c3a08047b797781d1639db4030f9e59f8c5b71a71787cc84ade5a385ebceb1946177a056179aefb49e1f69ed0aa67901b2d6b2152b6c1fd1db67f358093180fcb8f96483fd35a87fa14825d3849dbf479be493bb2d1c639674bd195b5ea3caf49c2b78eb0e953dbf8fb909910c87efc6f9b6592c020333e00f83bea4bdebef4e107798f9a8e89fa5d063d69f88f31a53548ba2406407251f18c3d1ca6e392fb81a46107191e6d906b487469d0002afdb0f32c39873872a49eee649250d4d5d3a7687fde2952291c8ba78fd9b962060df12d212033303691b05eef0ae0e7f31b7e395576708d211d70281e9501618673afac20a93e82f060135e51b29132a0c9244551814bdf399b746651279ed135d162e366f39d40e3a49e907f72bf7c66fcb4ba75b1f447fbc3ae3f390ab4c10963d755ee188a9b0129416161995adcab12177976208e1c93ef48d3ef55ad22bbd97781dc7035c9f5fe25f47b703b1ed50dba311d24154ab05dd88ccbb5a8cd96d4665829c4dca5d5b22affbfd7e842ffe5e87bf4326f957392229bbc893b1fde9e4b2191a3345490d418e9298179661104f70bf6cf9a0094f9d37be98b82d98497573512d8f6fb4b0b0aa334a9120a5afef20e0379197ac7ec78da3688d2c9b590e40fcf866acbd1d857546522788d1f3ae73f330aad045c5bfd59b8a399ae626fd67d9797b32d6a279d42eec3ec8a2888258728f7c329c4efd0f71b730e57f9bd87204d40ac1ea6032a4b8ee3a338aad58c2f3c9795819af4cb652dedd475e5662d9c0cd23e72a8f4e86f1a63e5683c814a99a6595b779e5d715ac91ba62c1ae4ca1651581506ba80c2ee0d3f97b979758cfe93f373873f4775c882fb3b5815b9274595bf50488b935c82e0fb4ae4d078d30bf0843c89e484bf5a24d5de602649e336fb2b79da6131f96ef1b5f82cbd668f4599fc9a92b4e9ffe3468e39e4c8bd90531952327da74a522e479c66b7b1554c9a72a2e6db58fcd45588c9ff4f48be5ddc994913833b668c275174b9d862dbe8fd01535ff2bcff6ea030842ed3a4d105ba07feb0098e39f61a4cbc06bfa153c598c10c5de57caa413752878c7599e5db8482b6f275db2185c505bc0c9670fa0afe37031eab994120acb935bf9dbe6cee6ba336dce1b44732c4267ee77f5db890041e547bde486335b9a0b85d6640f6534d84b3729b3436ac1c0551d687ddd8da9abc18689e7e932d5d0e787ab5ee5f36eb53789b9ba2b71d7a4f7994e56b056d4a042bd2cac79ad12d87726ef8cb97342e616269e9f87493e95dcebdd91763b134019c0a76e8b12789b026ebd1d9caf1930010aa1a5c348ae2e6273c885ffdf8731b34d87c293e77e9ef14709c2e3b739dec85d5bdb8f5ebc9eb610240576435c8d222ae0c8ebe5844980560bcfd45cacff143a5c208add9011bf9770b7803fa90bbaa10f58d856250b37e481f325c538e473dee7863957121374bf12172321b9c99975078e43a0e1e40138f9c31d6dbe5e06fc881de840e64899c0cf342a806916147de3cc342832a9514eae9550d2cd1166e823f404a05b418e5f9ffa84352cba3007f9d37e5b00049d7c099346257fb53e86b919b45a9c6cd8b67cb3c4e383fcfd5789f2cc087d6b459e2a7dc96d08c826c43410b3df22021855c7d413d9cfe7ca79fa860918a74941e08511595fc9a3bec2e2e0c6dad05781c0a0d6b6609837ca8f78b0368b1217b121cd6ced8fa48dc131709434eed65523269abe95f338bc5e3fce0046ecb24dc1ad8c8fa68b5f9263361e4952ca1aee9229811a5ea85c9c4452235639d1eb8105ff88c048beddc0f7efd3690da8b9bbccbbcfeddcf3e3c9e3ea7b46a5b40098fb85a25842911e42a714c2dd0fab403340ddc1af9484843b33c7f5bed80fbecf68180c9b397ed85c51d39cf08c5c0336b149e6d1747360541e84a93224ae88c1b62384b938ae25ce17d656b9ae52fcd9100a40dd7793ca67357f3fb00621863a490373f0db49b1aebaff7284d450922f1e5243bb7fb5f7230dd7cb8db1e08893696908cad4a45711eadfce8b0b42a9aa937cd011bd5c4a8c3a2ec771b3ee4959eba5e4a17545d1c86acaa4805e4aad" ++ }, ++ "ecdsa" : { ++ "addr" : "0xa16c987b93f1b3c51fa8a9833c8932eeaa566ce0", ++ "claim" : "0xb0c578f123a8a0c96354a13f98c4c2cb8a67541f5ccecfdd0cb6e61aa77f7768157dfb3ba59aadbc03350577f6f31b4083bec30291a61ee98ecb3db2536f788e01" ++ } ++ }, ++ "2" : { ++ "id" : "0xa5ea2fcff9e3cf29d0c6f5f147b67ff24aec3bd4", ++ "keys" : { ++ "falcon-512" : "0x099202fa37d5e165b88428d963d2a224b8fc82ac0e4b3f6a02376f18218d1aa7d0e910e71586aeeaaddc2a557124d6ab4f9a44b9cad02166413cbeb14b364e13956ea326900eb2900802644167639045d76bbc4e051654cff404dccea94402141ad9fd992cef7a8fa6478b3e6f8912886e9edd1b34c29385b7e964f360e0fb1600787934486f461c95d577d2bc74c4dfeb969b4798565ce0225ad27aac052290a44f844ae233e082c97e4498a31117ac9d02f3605c856e2dde6f611812161f89cb3a54dc936ca1e740a6c659405ed586a9a963b11c89b01746325e39e645c72b0c7e4491b36a17d43ffe38d88c601a5976f5a9636c964a012bfbce5f9b371e7c3b38580d81c6e12b8e8f2aac219f96245d35b4f4afa6c94015b055703b8c4dabaea4ce2577482f5b34fa49e56a912dd58d74580b1f94e1d2056594ea64bcdb696b0baeb33c86b6544761a3ead9ba9888cb1ad51f7027ee52b21e46c5eeaf3f77bc0af7efdc87acbddda7dca00b6acc665002c26447e5b0e0bb5ba261717c68dea7f1576462776954d7249c2fd0886f615ad50d53960ca02d581a4a25517c050ed467c7a820bce6250a9ba2e44fd67fb21bac843bb134c95360dc1c50d54b7280a94440d018181a9d6374bc64d782c84471b47287d8ea748c36cb83cffe053cb89a9e4ae71df497871c2a728ef210903e5b7f39550d0331e15637be7e28b3a2fc05b0a9b0c5a06f9fe81263c3a94403d6c288a561288ebaf788bfe271a578a1a795a85e9d452b61ac204b297090617286922376bf0a8d67dd35fd705b81260b7aad30132b965e39bc3cd64d154c4175951704873992a814814dae5c6bc1e89a83dd91144cd1b88f6ce449900058afdc53bb44bcab63d30cbd6df115a5ee8f5380a127a160e922bebf7b408de82514b2e2550a0931e065565e8dfc389d454823a55b03e5c989b09e3791f656794e8379b7b4b1617aaa9770366d63a657f71ff40c69b1d5da518ef1e2aa42366cfa38e448563f6c2db5e3089bad5520ec26105fc885993630c10db357883f588a5a384cd6de688e1bc3b1200f87ed66ba3d4a4b671b2a500a0436e0955904030d76577aadddb8c1ed21b027f198c072f654c3abb086e7f185980f49d0e109c1a82741809f8afd15ee56a887b392c5b172ba659144a7e99e25ba19792d2a3c0ccb481822839c8c70c65c0943a2994ec9f6085b7ac64ce2b35489a72dd6693d25f2329264e063db26ad4495e3ad00f12df8cf914fd846", ++ "slh-dsa-sha2-128s" : "0x686b5dae4aecd5618b95c3b2a5792888513ba49dd366ac39b7431ef403e04963" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39cf29ab9b80215a9947b975d8c6097e53b39d1483c885ff7527d7fccdd2ca3dafc32bfbc0a19c857fa8be7e52e25064d69c3b7dde6e77eee96ec77011fee440c8bca99a45b432b5468715a0aeff9d61375393b3ca40b9140e1a2bc2a52c3c8a85292f4c9e87d1e0c12fbe4d7236ba7921b8b83bd10ad554179dcebf0791c4b593c8a1bae836883d5094499cf2ba41b00c8c36c77a83466c263a0b01e773f08ec66d46e97caf0f9785943f98e159e353f0d91d5ab526279477a5509129f7a1b8b07ba82a1ccb4acd5be5e40de088f2600e06a8bcf35f54663279f04c74838294048a8f8692904d4f9eaab49635068df74d1f5ed238f6b895acf1364544747bb10ce333a957599594d766ac5d1a3ceecf8a6696cdaa95f824ace18cc551e1f4ec12f345283b366314515849feb5bf81fd203a6c73b5bab7c01b5c1131d442dadcb6bce32d6e13c5a3e77b66eb8f5b2912c0938d89ed9e20a455066d151a973e4509b03f5d66ff7ffb8b362e0c09b969e21173693d9977ba06d48bd3b85657119f9dc3533c91965ed81d1eba72b46cfcff285131f84306fec7b271a02dd22982cb6399a9060d286aa18a3f97666810937f8a5667c94959a4c27299d55e94564dba27ea3d98cb3a9db6197c842eafb237649de3fab72a9d56098b5c1228e70dc062617a8a6b44d46b7899dc1e53a77b700925ed1b438c59458c15e9b91fa2c2164b9661a976720eee2864efc5363d90beea9789a6d3b0628bf4695a853251c7f70ba1ebcea06cb35cb47d72d2340bb9412edc49626d6c78be644c4ab1c539d1469d1cc63f092ccac45f66917d89274af9c84d7f1108b1bd738408e499efa63f1a87c8730400ec19f9a59d241032e9ab78670e85e8da24310b13e89ad521ad4fae3deb9d438dd7eac72b79496c7b65061314ae", ++ "slh-dsa-sha2-128s" : "0xb8f14bb6630512c51d227c12a04ce7b316bfc0d255f5a5d1dec3e1ce5f5cc92927070079430990b4364200dc6d389fde89c78649e21d8fd3a17dd2de7444e77ac3e8c70eda15f2247300fd8e37e1e3c2afcc3e8dd674823106b4297ecedc924ca948a9f80afd7ca1bb85dc0e60e1ccd5d97eb21062b2fabfe94827b4ce5f0e396e5a891fbfc61bb827cd305012515d0a182f163c1a5ee3827aff289ec526cdafd2874c457947e8a6c8332ee7172197cde7388303992be248892e727b559c0d74a2c65d46b6686a48f0b814bbf031d1bde17f55b888e7cbaa7fd6dcf428b13ca43f77d80c3804bd2840e5768c2aa17f6dc773b71f83eb7803fd9e1f1a2e3e158f7e823e9667cebe136d333316fc670442a8c662930a00f72dd2dbda9b19c3dcfdd09c60ba55d9ffb5d5b3384d719d153566bc0b6da89d8dd869fb8c4113258014cd48a67a3591d37f9ba767ad70a554ec98bb59275ce163364915051411db73833a88cab0d3fdb7c491b8580baca2bc44a7bcfc3a51c28ae0a1fc12bb53b2b948c571397a348e664522ea749890d1c7ea7e9561596a3e930bca68377e4d4c0e0301472c8017c1fd5702cd6dd4c3f5881ec4cafb98967a57837c3869720268b61f37836d0c9c5ddac850a835318b17758a6f97df4d4966d516ef100b7e61271c45aeb89242ac7d2b8ee45a08f4081727d54cc08ec0f8af9e16bdf6f6d6797b9f5fcff9686f15efc4e8e34b363d562dba239908a3992b3548566a30cf04c424383b5bea0a5011ac620ee384f6363fca87daa30fa88763146bcfe0a160c071d79dd8de0b11e034fddc032e522b7ee47f318cc6f3f2b6c9b6efa0aaa9b9a9c1243750ea31ac01f087d5f4f5fb97b8296b0953a606c49025f5bedba6773804b15fb3638e72ffffe38ac20486e18eb21059f419b0af9071be12e309a953ac82c0a5a620a7b5c850027b39cdeb5d728522a15c1557e4ebc3f4f09914b3a99e291a814504ff7171c23eb825d2df1bad1ff29144f8a3babcc882258e8a6060272e95c4393fed0ad86698554515e77340ae806746ed859ff9730cd718c767e320ef54fae5e0cb8ba331bdb920229d6047a6db8bad147b75d376c3e72e06fbc6a542f51a312ec831c704099b2eb0f801b68631b464ef484eee077cb7fd9ea951a0307e08dc5fb4ed5a6e62048b010ede39efc5462ccedef2a4c61ffdff63fb3aae19b28ca48593532f051c716835a61f2fbbd5c25883f4a85b48d81658b6d7cc4227f90a81e961c5fd8a388c9efb78da1c9bc50d53a41d2d336232e84e3eb3444389caa3457ef9e3560c25033ed45242d0b4bed69fda4a4f1695830c843e63147b6c2d3f9bc2608b0671e59d827dc1e3876e5fc6075bcdf95223f73dfd11d64399333f7bebdda7f5c2838c072f7baf753a36a1ae8987773fd0ae5acec41d7666c84c1125190f432a4d82ad9b78e22d6536a8135d80a3d1715d17a673033d37104857278a75c2cbcbfe0159343dad8e98e42874e2b001bdb469c9faf79759c4cb3e3f2ccaa16bb29d3e4dc81627441d07469dfb9f545ed83d9c20ce586370be092f3a90b18f30866336c6db9d53e2e0fe1f98c655f1961997e41c25089a518f05270ce06cc115b6c2e9c04f6ba9bf7ce3abfedfada8580ef89f2fea98e8a19c58a0f3ffb89dadb05dbdf05c44b79ad5e1d259d5aa6086cb295341dc40ff800b460a5ac602a687d6feaf66393dd2be22264498509c9d39033aaa22eb248780a3661ecf0a05cb6629ea3d91eb0f68465485e8fa3fad3fc4315a118e4eb2ebc6e9b07284697cacf0257edf67c20b7b0311d3094f4647da567385a508addc9b25a66db1f1544dbced87886946989682b2f2db1363dc635e4cc3c67ad83bd311437d22d8f60a2cb7833c952bab293c9e20ec2b44e1f1f42a797421eecb2e9e9f5e47105b9e7f5d7bd796c360ea39dab45ad701eef0a76b7773c55e7af7909d456c213b0db14f985d0f73652bdf39a6402cee104a168749466e477d8a399469992d65656b607fffbdf73ca1bf4976d3a0c0c64cf5d260d6d3e0198f0b86c451b9ff5840968a2b60a8ec286c81fb55741d7bc9714177c9a77219d3a39dc1d6d7adecb7f8f85af366ed653cd81408b509d0f56b5dccdcd1d982d115754364ca3f14a6f100c54ed8ebfce6b0dc3de4435507acb0c4d974ae3f2453867a70d5ba078a17db34844ea410af4f842dd4a9879a7706b18ddbf94c7b43ba137f7f9b8b3924b4d917f8e0262ad10d083c4dd3b99b70560377ad31784a587cf0ea1f99d6faf0f04a909179f3f93c96aaeae014ea1e74d9d7ccd0eb5ab466a6caf8ed0fae75cba902ae05244e0dde35b8c0bdbb3354ac60875c454ab11f49e47e2d180db319a113a5869bad3ef4580bc7402b0d6bac10a7a4e81403634fd1cd272076074e714b14a6efefc902126df6091330ae387e161789198680b0258c341b6f3ec0b09c7674e9ae8f88699fb7b2f88fdf2461e11ad483ee11fe4e3ddd48ede0ef0a1e54a318ae12473993a8456dbbe8b5ded40232b8d2474a90424281830da7bb36091ebcf591947b04739846d8a600946c2b892e2bf3353b09b08e3a141f33f6ef83d022666d380da43991d3eae4e62dd3f9432678e8be1cd4b9569fa2fa84e95195449716423688aa920e2ba1cd41cd5538907ebdf3ff15df27900ba7ee09f3e9194e1d8cdc0703d6f38b2b887a89b10787986013f688f9a355c6a362f4797576ba022e4f1d1d74e2e31dd98f1b617b99516c944bfa5bb474857fe74a09976cc29c71a7f5b6fa529f3e0c00c33c2f0700064fd507461535a35c0dbc5b69d413fd6ae9af49ccc5d02d7abac88ef02bbd40475595176fa3b68d602469a89afc03359b032fc1f0ae255d623fbf9525bfa36ef98467d5eb2f80cf7c72a04b557e40995471c7adb8701409830b232693bf2fe905ef8b1a32c4b8fe3300bfc5654acfcde685547d5c1b0c213294235b31417da91464619822f3535c93549ab4649a59dc3620e7f4a3327c0e421c5d1a28a2b4c3ba8ab02950631ed54690cee35bc4147aaa8477cae505a1d1757d85251bda5fc91cf65772e1b543bccee1a2cd0c26cd33015533a0e72c815be8634efbb50ceb0ec3c8a3bc6c84638ae371809ab87eec54b934343ee9ed1bebca488d9399a1e347b1647d108652243cf2531a4685c282e0b9e526688a3ae1d10060a78467e6804b705c143d073af664cb72ce657a7d210240011d539cb3144e9411758a211238a872eb4be615d4813b64b8df446d2741db7c9f0af2cc4dc83c0febc41adb5d8413b7ce54ed564e899c0a5a4abcd1cb44c84505915afaaf93751b11bc8e96610216f71cac8d3c9ddb7282f0f864400bdee42c3e5645aea1aa5649485435ffec9e43d43e4341d967c9a89eaaea9cca12e2089f3de222e1a5034baa32372582023b5564909fbb67acfd2a40d5ba40de2d7a31cddac717f5702648c0346e197f99598dc83edda7ad335f9e711a0835c75d4c32e3305e4db9dfafe171181551a8dd5bff89f8a9fb819eca7a171d1be47fbea0e2838a1f1d01f4e68c3d0045da0ed7d3689c17319ef5f5d178e6cf1628402c40d2095c91f7bfe6b837d8f86c5b2585653beb650fc29096f13617ce6d36fd6107ac83c7d7f5a8639e519b161581dd58018ace297bddc3421d358be70179b14bdff66f229a50a329bc30b054a95d0f43e7914a9137055f4dda000357fdb5e2afa3d61b9816c03697168cc022f0418ee5ad7aa71617103fe17e7f47ecf7ef9bf779f157eea74c3caf3821791ab628fe8cba64c12d3226877c48b746d725c46b0ccf5a18f869e6680f1e5ef3c5e7fc2a18915dfd8bc12676ab94ff4401ed22133ac1e1ba0c0352a30156bd80b63eed4a7fe9c948921e1a9843127f1191751312180b75f06e33694853a05a24ee30cae0b02a0be49db16f6f06630ced9b5e57cad548dcff70b1620ffb17e8bf8c247a962d6b2a6fbd4fb3c89e3aa4381e15b92f7245ea700e76ba99678f4b0c998ac90bf3e4b9ba5b52140e15e4b5a38e25462c1b61953cc2068d0b9ebe014db6b8fbdb2fc05751667659f40ba1cafcc2055c364116a058e286f084c2bb73096d46f6736de541b750ad437c27a92ea51baf3478837e99faee73f2a2745918f81547c45f2b7083befc6387a73366c175d2be22314a1fa73f11571395c7fe9df062740c58b56b4982240c63b8a0d5886a3ddbf6ffcbd705d3bf3713a0e1b74497b8c1f34e204ad81b63f27cfa5215d275597599f60d02bbf6cbb229088b56c96d73d09fb3c36fb3f05f4266221984fe8559619da67bb7314ca66405cef4bd3086940c4a7346243776a6fa128cd9b6181d8f584f482c502fce3339f87e4fc5e3593b7a0a64c19fe76c51a29ef776e478ecdd5e093b2aad0ab3cff0baf73f4e09d63e9ccfd4aeaaff147ddf2e9f1e3e6cb3bc9757c57072a1a8076e179e50b0a03dc94de86fbb99f0e92338f26b6ed7c863830f325d3606189b80c8df5a763f422f26436f753168b53bce965c562c2554081cb4eb42d48daf8573206f818ae66d62bafd151e9784d6a9304996b4b82cef081af9b106b42ca4b6b0b2401dc21d8875f9801591234dec266f1f218959af60351178049b487b2784183349e0a7ab361f575fd0237d9f483590a23401f9085b111ac3d740ff4c3eae0b7dca3d149243e3b1fbabdc7431a579652d522bef7023e1c6579d2f6852f1acb9b7f20e3956af8dfbf14617f14981f40b1b2430920be14284dd5f2771f73091adaf9179b8396c6ad2a3579befa1e323177fa2598a3ef80ff5785dc2677f87e9299c6bb16ef2b2080e91f6fcf1b9189e256985e631a05cbfb6427eac995e683f494751f7ae888bb0dfd23aad7fbe942b8100d4daf62b6b8e4d647c818ee7edf0d4d64293edc3b7b6e08a8b9b71a7c38f55ca76593d35770185637fb473da423069de005363ec25235ce816f4df3070ff567f919f47dc4fcf57c168032ef8d7e3fdc5a6a1dace2513fc24f0829e8e4b964d37333febb1eeaa7b81aafe30d16fe64b6ac037ddec2dd9b372c657120df4372504cd14be89d3719c5aa6d545030423fc50e277eaa401e8bb02d70b6614e9768a7e42ba9b35af8f9e3f7dcf175609f7b91a16fdcd65a151c0e85d92dc8a06cddd1ff77d150ccb62c612c90abdad156ced839e837c79b79f456156a28c45f3287cb86a9ca664a13313332a1ed9ef4b3a3df864eda7bd55a6d8705567bd8d1d732f65a324aa6c77f6dd82517d5274343a4e16fc8f41f5a3809e9f2cdec445b88309c9d1de684032a10f8944157a3dc3d4d8d59721f4f9cc0b0e1e7a97b7b066523f7498e0902ac5aa462d9bd096e13c14407bef96b59297391032a4aef8c543cc8b60217ddd5a5d815c4ea1e21625b52e2323b42b4851b0bbc461abad9b71805e8b1b2a16c811be69140d3a6d32d7aa9d5321adb57570fc2e62618cac60a4cce2b011a4c8ddd4dd521b6864c7c4562d8270dbbceec91bf1cd7be926d6b66bf370839bbb22856d1f0c7b2b7119ecea6278793186c50b045d09a1aae7c5bd2ec54df1087cbd1d8094293392605321bd39ffdbbe510f0e8760bd35074c4b0453604ca1f5bee056175ae7943183212ad527e125d2ae113d83c5a4ca1e63e8d89ba07ce8fac8257fe1c603031a1fe2e41bf922d7ffa0a610e0b91eb8c3147262fd228a4ab54fb520b49c91ca268d3954029be8677229af3ed232628e7d3a752e66c2171d1746b7e31d2dc8d1781af454822f36b3ff40f7683fcddc5aec46b13890a6c7c9531f30eeca923f198f4b57112a94e34673c88c70bcf80ee115de27ef5268a753c6f827e71254b5bea2a4f27c8e0e2d0c3f72d051558700196e80abbdf452bd70116c24f635d1850f9466282ae761f1a38a8a0fb5a02a9e1b99df55616f0a7c031fc34f190dfe5cdd4f2442d16ccb49187823fa90f3f87dc0966c4cebbb7472d8184e37522acb165f5d3b508f6a62623def48edddeff361d5ff37fdfddb2b324c4f545bfd5cb98d258edee6ee6170bd41135ddf4c9e358433330a5b590b25fbb276a2284b2df18550270b32b65d9b483fc42e9610537f27715e9f451bccb73e1ce017aaa39b65db4e86c86a50d0379398e57e0c34fa64f73acc0d2b4e953a89ca2f8c01b10135c2af5c234dfaa17ef97941aacb7cce96cd05fb246b76f15275e4d2a8545e52726a48f269d1a558aa12588cc78919a5edf6c0e9e576ed58c92b67d00e4197905d74dbdb3700fbde85d26de20cc652581608ce1d1084b507842a0373fd8830c8d3f68dabe93fb19e3189e486840715f92ae4d916a9ff3424b45ded24780b31fb7f76d506339d9f9a545fe0547c675bde44a3b490bd3b52e3b30842624ab5e8986161be4ef9da785bf537954d3c716da5597a859ef7adb40fd8030611d3ac6581e424ff636aff72f4dcd9f315744a3dae6cd386b2f9945140071a5a49f05e8f979115678eea7d6d884a92e4f14ff94dc102355c3aaa93e02723a92417ff49fe8cdbefee7e6c5e952ad240fa7eab4c7941f6ae8d2a1086e1f2ca73eb8ca5fbe3588ae51bdaf18646ed04bd185a19bdad69394ac15d130297c0fce9d8fce8ea2729dde117facb274f9865ffb4f2c7248102dbd96767483cb7fb764fe667d484a3143db514f08577cad8bcf695b0d953e2a3c8710d8979952929d59c8b8ae62ff678815130e68c85d4714e832733da40b933b7133725a40a12534753eb4877c65fe4c75542f28d6f9e805789995adaaff6fce3929e6027338281c6d0c33aac092fe0eb1797dcd953fc1f815df794249dad7b28407c50371a8c81625f6e7e08ed59a98758a9859c41f7436f937885ad35102b0eea85f3dc4bb9a6260f4e091ed983b1009275d43e4960f9422dddeddd09e9990d545cb67dc3f1061238dffec3ce01376259262b4c32c6173a6f1e239f4502cfb0900bbb7e3b4883ca3c64c8ba91cfd80b2bec6aea25b01124ae11a56ab3e4d448038795ff62e9d5ea5cfdb99c5901a8b8f8731c772690dd964cda343bfd020e920b32910a68b433ddd01d117a833242fd695a54f33fce28b506d931adba499373b0a6182e54323f032f1e7b8bad58dabcffdd1cae831c70e87b2c6fee3494dedaacccfdc93fa23ee1a4273f16adbbbcc21f5d02d8645951b93287732cbca4c61a0d0549345160537501b8c0dfc97128035875e73db7eebec24813d03d11cbcc089929b0f6e2440a26d90cffb6295e8fccf65b4d676abb8ff66709913775e611bc843302a475488c9a9310c0c8885b78d5db5cbb1a919683cfd9bd010cf2f1206ab327122ac87d8e2899cc1ac684e72c91f2d36c7bcc3491b768aac86e92aeb106d22b3e85112a2a871bb8c9d0a0dd15c89d113910f8babf15f27a13b10200ec7078d362773f17286228b0d5a58d6654b0fb4f60c81ee581e507f17a044e6bcad4bb6ddc66bdde7d311810d79ac031086d7b0c334cd3a8a496591aeda23b2c0097cefdb6894b352395dfc79b74a6e4d086656b0cd9c95a48640cc8b3d188189ec0b98c8618b0def4b0175f11369cb2f107e89c4a67a75396cfcbe899334a5d5df5927fef2eb8bd836a27a2834a7ab94813d30fa8431da3178da4ae56caaeeee66cf545537ea260ea6af56d4ba048076ace08ff2a446080a6b688a916a13b43b933e506ad187b1f829a1d54ae261651563874cae19c490004205765b43c3cca4cd8a309fb1bfd7520bcc07794cf7c03d9b1d1ae0cf646534f5a97106925ee96dcb7fc1f74e62c01d382fde19fe027a4b9b7627c08e690abe3ab076f184210acbb4229d483f7471ad551eb614c35e019a8a894b5f92f5371fd6c457f135ae8377c5781a8f3a6dadd2c00697bd8399b6f168dd64b2d2d66d5aebae90fa5f904af9f950f450d8be919ae3f02cb5c0be9687560cfab2d2161db61e978ef46304de248383dc3a99e30573bb66f873ef1e54f523ff8ff79e8c05e7f8143cebd1bdd9d2186ebdbd3b66a0a3dee79475cda2890720ac5bc33f8cd3e817d82bd7c52c34d491e1e9d1d307eec17c0c7679af3626e7b96bbe6ba2550f44de7d1d88b3e4c220b8f185b459f1f882a97248cdfc3d42209ff44806837750b3dd21ac5891254f6c7f6938aef3caca6c55b633770772c2c06734f84612a59aa8cfd4f347267e631658cfc4ff89cea84550bd43699c1d8840655f39e3449ea0d2abba1d81196413302719bc9b39cea85cb7db6ab7f00683842cc480503004c1c819ab80e121d9d21f46f362614a5f2cf80cb2c8d3fda82447cd0155fd7e0ec7589a6df2e6614671071f0f956143c762d51172da46e9f61e588fbf74cb3ceb74bf2ce4ec4ae26a28245f98ae91f09cae77c4660d6dabe7cad33ac506db3000d742f683e08bbd0a7cb9eec72a1a976546ec926b9faba5084e00d66475a514a73f01fbe1e79c0ee0066f4b724e4977f3c1518d28ddc918c573693e9b3fb69b426df0640c5ee42cd5533655f9a82c6843516298d05cd970f34dafa886995545c37b3b939e0dfa3647fb3f330bbd3e69307be3d469a99c24382acdcac76c6cb71decb4b7b11cb5f2e63d112767a7d6467c51f1c0c27900803180337f463e64f507ce245f606f8c1f1df836c7fd02502bd3127424804c69f1d066ec3acd9c4374e857c4607b711f532867cef2c1c8a7d7051a440eb7a8507500d86f11567e2fc812a27e63e5599059af1ee90444497f69add7862b93ea050f100e48df7a578d55b6d6321e70ef7a7625ed89054ab010850912088fdc21551b89397c35ab582aed6c215e00d398a857090e2f7cac21c7b51f34054a45f36157edc603b5d6e76ce20f2dfd2c20158943efd2349560666ca38505cc6af776e0720af2d5f6a7d98f385854700fc0c749dafb597e94d7ac54aedf34840ea778e8873d6f1fd7f53de7c06327d08d34a03b38315efd8eb52683ec1f9abbe2bcf096fa4f379f41e09b8bc67ae4685e68ce456465b38892a238b18358714fee41da0aac8dd729e2c3f17488470648df81040272b2e927e896a4eaf6a11c457938421288ff074da8db60d37c6d022e86952341f2b8d262cba0c5a6efb51925517a8c817a152499ae7ee56d36df86253e6b2d93079c89fc922014b03da3941509e979ff8dede44165ca4cb698924fd12bcb02a35deaad608ff3358d455a49e12e944dbb11ac7e9571476bfa856f3bcf90ca9bac6d57d5c1755104b348d2924ba9b14e9ffb750cafb6edeca6dfb79d73b9839092032035ea700d81f19d035e38bdde754a5098dae1c163f9c473b0681858004ab9d9c2c57282ebd7e57c474b8f7aa091d1048b95e7ef887767f49d2a7f6b410922da142ab8605e735ff6ea9e3f36a29380ec43dd009d98d8c20f4052d81fedfee6cb018b2da59d63b5fc153d5b0948d613415a6b8a2b7338897188582d2930480d897d55bec899723b285dec9abf819ac7e6f39d8c35c484ca13f129fa4b334979bac7715bbf5e52a9926568f359dd3e3e000958b561527bbd52025918ef75228c423da41861396be4f829aa4bb6f94f65e662e6ac91e828d721b741d7333a8e3050f136a463af537ee97af4b42456d65e1e2324f72267c07acb88c91d0cd602ef765f858f69fcd44ddc73dc7c5f8825f3fe04affee769f3ab5486232e35df8fdb75db79721906907ffad83c57a364ab85d93bc03ace8998ede749d88985ae41cef163a3d00f568d43115992362c581745f723a2955ed925cfc7c83c5b5188812fa2dc016dc21844f923b2362afa5ac5f2a6c9355b2eaf724606333f152a01c330ed88f7028e716043330a280c5ee458f2032c8163f5548428ce4c529d487a16ca0e58cbf41dc4dc802cc5ea7fad6a50de0c0f2c2be49c3dd2806911ab1322a30acd4fd8937b8930069fc1a6de86f9ef90f407b2563594adad581b49ad1d19b30ad13efb0ddd8e6f26dc43a36ff8d14d1c99b073f5f1ce8923d3100bb04488b86cd4e89f7b9f5b9cbbb3f86ee03b498ae255e09eeaaba3e4e4d68f1ee4d50f699e460a922e17ea8f0ceef9794e944f128efe835f281a7662f959054aa994afa3982f7a310f46f53d5ffc07884aa91bbdcb3f3779ebdd7f90801e96222f56df39ed9c2bff5d4a11be1da7482835e494b0856ea7c695cc1b53acf3b2e2d1846fff50bf55be65e16548c4fc436f20c50c119ca8eba4cdeda8c7e4d33734a0355586629ca5a7c3591ea4b15428a81b6d91529485004cbbf60e75208579ac354dc705edc7bccb32f23030e733d3f549fbb841329a01f5c5d263ce635a57aa9c69432e5213b155a07c34fe19cee737cb993fdc82ff38eafbeb734f04f58d367e34df15dd6044591983b9b45d4ffd87e2a6b478c7d1e86b4b974991b930370d5eaf5edbb53c3dcda643fb992b5fb0725a8aaf8a9e7c4012311f197179cf1293884e2356fc5b624cd46358d3c7bed1fed6b0305114cd11675aa49c1b9e6569817d34fd60c1105833d78dd00117284cd1722074a60655dfc428072b0d2eb881b93d6c367952a4bd59eb902032cfbf9189bf65f7bff592032c77d61dbf778986b491e297ad0da5b367c8a10c9071b8d509b246393fe04a290b3e2291f04eb750285674ae3e9c7b76a01b679787a4006836dcee956185d3b0ce16c4567fab862d3634b93079305008e2f99ed425489bcf5447699b7a7212fe2196d3999b39191e750fda742c6ffb5509e3806f38edccacbb8bc73c96cd46f0f400c4012f1205813d69a48bbd1f55724c7de917ab56d4188716b96653ebe4fd1b6d5d252f5599f9c53a4683ae60c8c31b86982f32bf73401a328891804daab93a155140fdd41ec87e392c8397c9ecbc48f26acee4e3cc279cfd67d75b5e0b6484274484c18f72c2532b4064cdcc309df796c802c17480428c3b5a5467b38aabce03de2a266c8a22d3b0158beb913d50615a1002fcbaf91edc529b0cd38f35138bd71dcfef1b6b90adb4e68a594de40199724c158db9c85ca78ce3a19378ee90dac98b23e1515324fe18472a4ca93b004295b7abd3c146109da707f5ef37886fe1a8966ff1e96375fd64536eece72ae3433a697492955cb182331ce72e8f1804efee93b1929338f" ++ }, ++ "ecdsa" : { ++ "addr" : "0x5e13d369c8adbd8079272b624343ee1edfa4a560", ++ "claim" : "0x197e55da82eb1daa23a5478ed230c6d0452d3c1920df15e10a8d37a7430a7f2b69eb474bfe0c44a6e4a55db9d5a0e0b74549c044ae22778ce30f47a9fd1eba4100" ++ } ++ } ++ } ++} +diff --git a/consensus/common/src/test/resources/aere/registry-v3/n02-chain.json b/consensus/common/src/test/resources/aere/registry-v3/n02-chain.json +new file mode 100644 +index 0000000000..9bca0b7f72 +--- /dev/null ++++ b/consensus/common/src/test/resources/aere/registry-v3/n02-chain.json +@@ -0,0 +1,62 @@ ++{ ++ "description" : "chainId of another chain", ++ "chainId" : 28001, ++ "requiredSchemes" : [ "falcon-512", "slh-dsa-sha2-128s" ], ++ "ecdsaRequired" : true, ++ "previous" : null, ++ "expect" : "AERE-PQC-REG3-02", ++ "manifest" : { ++ "formatVersion" : 3, ++ "chainId" : 2800, ++ "bindHeight" : 1000, ++ "count" : 3, ++ "0" : { ++ "id" : "0xaaddb4dde09de5718a906d83be7db3d58e0ae32a", ++ "keys" : { ++ "falcon-512" : "0x09501c96d2f5cf0b28fa00c726e5359c5d36a1fa069971f854b7d914fb2f1295e68b2c6fa91d82f7d287f55ad493c87320bf7ca2a5d5e79d7212e8a540c166b588dc03f73b83be060525b367d9f40f5e77e7798c60b6499767586770722820b3b9e6013cad3eab5fe5de96089a29f34919a2e9ebcb3fa03a3e714593b7a3356d11ffb3441ab40ad94474da662a71aa2419dcd50668cd5d8a9017662cb60998b34ab5b7929c58a94d5e133ebbdadb2b0279543067f76bcc4cb6d7e0a5edb7625467e3ddc92a01206e1b8dce69be31928687d8af4d26633a07e73c2830d5299b878977691cf65700b65b6ea2463e51b6136888c544545e59fe8cf190a7944e215a785b682623c95a79eda28e25e0e1b91b49ac89deaec3b14a3c431d9046a663170111ee541d81b43aa91f29dc147c6fc97739b3a63fad1ca84843d0a65b8d9396f28e9b11f9a41453ab18a2309ae8db03253a09fac8f0cd634c76a5e938a44719660944a95dff056cee43ea99592c3899c2880d7181ee3dd5c04baeb60e1369a69430a66031e3cb10e392622f5246a71761760cf417dcb40ad65f60704fb74ad26f26c3af7513a42f806895e0298c25c049187aa536e0eba21998912e621846c2ca0e323744ba930a29850fdb385c8241382296ba28dd4df05ddb1e61fe525949034b59929a784406de240f8086b4074825f419d5472a28a0b157500be37e9f64897db2b645d3807c48dc143266c99e7cc1638ae278772493a2a4ecf74e526a514bc9119d7129c5a0d115a450ccf4dce05b76d4b6149fdab028006df7ec2209923117abf7578a082128cad42aa66b69eb63acee4456bebeb537ca57bb3d3487f95e4f06c5cb29f292d3b6284e5a162cb83151cd9ae56aebbfda150b7edd5065302ccab70892733a1e096ba0da5f51b42764ad23060eb197d5460425fd9c7a26e7dc3cfd40eac3643539feea72c9ed41569111a7976d2c345ac2183fa2271b424526709fd9aae558a23a5cca29f4e2f31629746a71d904612e95ad9977bbe74fa32e90fac62625838cac49f50e5aed4e8879e2ce2e5651c4f4ba0c96583af9e1612b5ff1a6fac5027c0a308815e592308170b915b4a2de1e8d48e9a5730680ea9db8f3326c430241153b3b218d5347d5c843570cf80ee813871ae10f6b8ce4ab7e4c5197045e85b1cb4977f44c33eb85894b6555b4bd288a50c1b656936841048983c00a01631f10a84522cd613fed0d4beaa4aa4b3e9f30c324108d909e59a80150", ++ "slh-dsa-sha2-128s" : "0x47a0b70170dda85f843607f6c6fcbe6e6acc7c22980c108996a3fe72dc9f61a6" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39c8813cd3b34be58eaab900555a67486034b1923e0b00e435661230cab85f07690a5958a5f5e9c84f033a3dc2039a5296443093fb7fe8d41895fa73be3fb34cefc6cc36750d534e6a3c47307294694729d6cdedb633e8efe8979a9aee486eaa66136e342c578761241192610185feb2d3c196bea0e79222437b6a8e08cb09778d053b29552df96507b1cdaede8e9aa7abc18902f29937f30e7cee6868f349f7ae33738237dcaf86b8e8e01238f3d8ea6fd4090a8161db65dabeb5ded5499e8cc8a5b32607abc291b36a4b34b327d30cdef18c1825232e69a2b09d539ed84dd2a4756efa64f864c563943b3db825824f294c1bbfa2157347b0fb0e7f8a56ec253b39ca9b6cb1ef7d3d7c93a6cb220a7dc50c365905ea5a71575c3aeab25b33523e4fefbaf66137f45c3d96db719a12d2e2d42fbd6cdda58c5a1b958b28c2a8f2cca297871a147dda92a7f008a359027a9288e42ebcd6ea9542f10b66dbbce6e7bb914206122f866d9adc1c89cbf8bbad9bc9517c2ea9018b61d4d2df9abff1dd9f3a0a6faa72a449af9c97e8c4090f3bbd9824298e61599c13c7eb89677c0e845ca2907c728d9296c24e96b6a348dbea7cac62671c9a78a531463614ce321e28ca2f093094ba5f69881e6cd766874622ca769ea556ae757cb7f9546d99f5c90c25e7b8e14f3b7f270861398800b0604ec2a3374659277a23cf6131c63148a41b05b3c06e2a98a268f1b9f0df7969addef17179ca2261d3c229ae3db0c490834564c45f7b8ff6d3bf70784779d75915fb2e2d5bc147bc941b9e249af188f63f39b028547cf080b7674b228e20a600e3b167610f814daf105226f3c1ce5e07834fd33dfe46315546e926fd5be83fd4d47ccd5bb8ae736ac745daabb59c87b9edf9a45c9a1d1617ee84e588f27d12235c59ffd9", ++ "slh-dsa-sha2-128s" : "0x0e8f9bdc22cad3613ed07fba30ed04219b9528f9b657119e2f0886dc71cda4afa7d462fe8bb108feb58d998b370b2f7e162390713d1a17eb7de781a604041cbed13d00effd3b24f2ff87cac74f61e7b7f7aa6a259dc283485179ab4bb966793be018c4bbf4475bf7a69e600a37246908f662813813d4b0f4f83757f4064c5c0713870a0b98b5bb99025dace06100497fda8c73d7385d123afd4953961066e7c8544de3fb620ef5e23174327c2b64089b3fe6df3eb86e83b12634a0c9cc0d7844c894ba6d83afed6becb6f5abcfff397c5cea8064e5e153ea4253abe599dec1614b449329ebb25861b69a9b22228d1a03ba51532ea64ebe7603474a15a2806d3dafa29d57d27c5fa894da673b85b4674ce835fcfbd391d328ef83504101432bbb0c83d7be462b265911aad862118af6f4cea4df0f1dd38969c69428fe438d59d22736fbc7dd5faf6758905b26ec4c99d71e4b8fcc562a694ead91569c9a916df5ad693cb2ad0b7ae4c4f3c5b7322f56612c5449e0339dbd367460c76ab89b6f44942cd33f35eaf33c2ddc0c6af793556d5202fd1fb0f9fa1b7ed45c6ca68d904e476477b71a0bc6ebe248c9b4585da0c7bb186600691269bb4c836667a6d73a455b97127d898b7fae17e1acc6dcc3bac3ecb14da131d5f8adaa64b054e2f569d9bdb164792038e107848882de9bbeff295905c2af68d4c6dcc8cf718c2de872ab6b3d18e00d527166f8ced642281302e2acf4cf4489072a2dc3d55ff8716619cde494be1763dce925438b33ff1b91b35eb511645832720ed92552d4880ae53ff6516cfaeb1d48c923648e502e4038676f7c82e532ea713c6b9348c80ce3c5735f437491d3a8b1765294868c14123af2e9ff61e394216e630c71ff976072d2a1c50cfd8ee1ce27aba5bcf9aaed4a51521bad5e5d5e66abc7a95b215fc8004364aa4df2b8b97b14e3950f521b6327a55fdff9139fb0bd35237b022e3aa128d36c8a60f4621d25d28c59a97418c7dbfc15d900ba626d283632732631ec4a948f66dd9db3bee8c2cf60dfdacbb5ad4c0b2b31f8428868cca035e79c95bcacaba40a9351b2b44cb29753b6b9da0a751bd5af84c9094d5fe91e97501d4f075392290e8516ed5e41b41b00e09793353707fe5c1d942395074637f3ee0a0f105876d6f28a74f9558c5f360e98f047a99af35ccedef8d5cd299365e81e7e91f28a01eb265219e21aa7f7ce56b62f9d2a61560f9fa39f2765f5b50920658100a638aad03482a687905cd27dca02f1deffd1bc49a1be1ea7ff1a505da74fd932937d8f6a8bd75ef456d5f7b71ca5357bc66db6cf14368c4faddf4996363251e6a6113ec64d642c319dd85830d8b4c7ee1437ebfefe01f27709ba0c412c266530f5b6bbb005994774e8935f1d91069f9e7a8cd2bb7ad6527768473affe24709c10294eb588aafca85b379bedf0b142b109e1b186e635b0625c4e59576266acb5f71040c44035fc9480b13932bc657cf332b12da1cd7d5c3977f51d5fa742974cd256e8e3662dc698e0516d615d0a05ea9caf12338d0dcb6151e07f184c9cbd5e59bc40b12ed6372e2d6bd42aa0eb6c3c888f264a8c0d3332631d4919c921cdada6bffbd01ca5445de0779f9723577ebd7e33ab0e5f577843aaa6cb8cb5f0508c33b63913a44d02b76bbb1eabae325581738fbddb5d4fdef8dcb8597bd29c6ecc631839118c44f66ef8dedeca65e58941c30e0423c40bf064b8d19d28dab3787238781d492720236a7ae0695ccc867fbb1cf207ebecc64f84daea66b6745515b9ac9b725061bb9958ed79ad6161318a262528004401633d47a023c645683e36413b8653fa4864fe98c501197c10226b1732337842a1322bb788a00a0de86758139c2d9ea3c5b26bf5d7a4a92cab4cb686c580e3e6cca488136f0da9279073b3dbef9519168ba02588fa29cc60d02273805b425b919a7e2e89c9086609982163e09d5f6eb9c66267ac7be363aadd4617d398d4bdeca37a838d650b0919faf13b78642a058b1bb96b2ed1482cef9bc6e8b2e061e6815936e15a9c754353aaa786ab141e95e5f6c464a41b8bf29e28e764abd638abcfb342b54d08c15ba7e24e6fcb69b844e16cdb5cf4f50db60ff0699f969d8e68511fcc9e16a58e100f80671af6b04ff3edda3a4f05f9183c0c3bb7c1061fee2d3f04e33fe75f1354e6de54f582da914da0138e8565ff45ef52f638cbc33a24bae863fe91e58d7c5da34273438f15e10d4f59db16e505620d97d3fa4862a4097a659925d0e5f4e073103ed29a600b051b83b1f3a21381f4b871c18d262d7e43842c34ed80661438c064aa2fd858a8f3bcb035b5e942baace7b50e4de5a73d5c51fc0843cdc163958a62d333078f4c7d883bd7055a602e04c853f9215c9d7f798403c007fcee124cf6099322629c449ad4ef84b7356110798dd87aa4d98ebb47abc6cc8748dd381d588b77db7f4e7550f6ee1ef4360dac6d6c7037a65297d4a0ea7999a5632b90ad48fba0a916846a216941fbd13d62ab36e1066e24990c19592944078435c52d7717b3556595b645cd2359ad151dbb67e92b14168cac12fb2cc5422582a50bf6e99f116751171c9b78744ef719282f1b84bf95b4092514f4c68fb82a1526e0942ca50e186632cd9b0b8b8d91e84f85e35f30f815601798fcae676da6a2d38eab62f22445099694804a36a34142150fb795afb445e78c241f0b645209037a8871cb5487c975975ac997a540b709e3df6bf208d9d8017f9688b152c9ee2b934f65393de8403244b7437108e6d8c973aa723285555d9eb92509b1747977105cbac7fc33e658fd51cd374d21fc2bf229928948292c1698db7934d0f9be44b137514d0a5fbb659bba83861931e03698a61cd20a449d0358a5fce7f288e18bb3eb62b7ba0ae75feeec634fc90fc45ce45239c5e3179309f0c202cfc53d9f42a617f7aaae586e7161a0723ccebb7e8586cd40e1fa12d3ee89b400dba8073b0080ffaab1182e8243afd93318df15bbf3ce179f21804fbb8882e855ef9e0739ce1536d8ebfe9856aefa9874b4e102e705a40ca4c3ab0ab7df63ba525189b518796590035ca780d348de49f0ba8f28456ca6f3e3cff7e761d961ad98b8cf01e855797c88fe2f811e41e787f3e4becb0ef42ca3b9979356020b447294ef295543e0ef512a247e4d356bfe3deacca8ddc5255e6ad047121eaeafe61d71e7f31395cf78890add4f8c688e4eb065479a63ccb3d0c09028bf60c700fe9d19195c26fcbd4130e6feceb52e192a2aa2343c05b43b276f51a7c55dff7233ea512942291900d93315438a96af08e25ea5b9ce656c54e71ed60d1eeb1665ddaa9e42378c930e21d93484b9a4099b7ddd71d983b4c42c6b1f62907ce84b24321422b08b847f1ea97befaa4ec30a794ad7f340210c800cf185ee2c6c72e844cc5671964e1e1ec58953500f149f0f0f25c34d5592de421c2e31535040020237b907e86d753094dd4532e1ab9d821e7583d4a21e1041fa7ad711f29ee3721a2aec6b0c46866a2de71ee850d8122f722898e533848e2bb851ed24cff9ca83badcfad88a171b4be064007aef4d759d93ae9b67b446f3c6fe504f5b4fe851b8312fec86b46ec3cfcb36e0f682e65e117702b888ab8566c9cc716a3a86106d2323c0f7f20fbc1fcd110bed4492a750befbfcbbe16820077dee281bcdf14509b93137a3998b2fdabc2a375b38857bed12bb8a9c67bcae7934d02d6ff89620fa8946c8aa524fde99c12fec0e25bd79788e2c15fc31fa3f27502cb952b9f9482580cf18ecabd92c55113ec4c4470c4dc06d8ca27a10474594eff708209e8f376b6f17915c2966dbeb0e35ac2f02419692c0d232e133b3907059d3a56ff169e7e61915c8b1067e183337b40bc1136241e862eb3ab3f2c6a72b18511c4107ed063d1e2303d0fe6842fb01c204d1bffad7e90bb44a365e62945a7f631811c9c37ffa5ac39c16b4835798686da5baa8e1eb6aa76b42f6b86863c30669486a175d6b3bc5bc47c5eb05b240bd921007fa39506c6605bfbefc9c8c493973bf3f0767817fd8ce126a301c5b8fba79628a9b3a03cad0c491a5f487dc5e89269e5d3bcdc2998a136a012486c5bce2e6c6dc595aeee2ebd5a36dd06919396184aafb2301d1889b668c4d701c7ca01b95f9508f47d4c411cc0397c244ed4e3e3ad7f97d86b6f8834b13b1b2df0625e6b4eae9e439815e65baf2da767d3b1700fc461fad6297fe4e8ed02bfb65b750c2d2801b7308aba9657df3c3ed7d548687f55e85c22343d1db343bc2dbe222fb76fbb3cf490cee7a99ab3a337c626a148fb303b2f8651651588dd4859fd65c95820ee2af85adf4e8fc2c03828ea7427e7c6b0d4a1b0ccd424df6d1450ee436c01351d8b6bffd4ba072756315968845ab7976813d93d0f0f2be1c00faab3ccafa71cd26c5837e87292870cf768c7837e18ddc3c513820c660870b339fc42c5211d33d892ef22b475cea3be20f5e47206efbfdbeac208e26e97c400edfd41f063aaa6b85a0cf86e23fb11274b405f4f796eb10cb97e70783909ad492ad9207ae7b3d204e59d69c886f91bc82a107d0be3ae85797a7cba747b8e2640ec49384f53c785a84cf8de37dd4048dd4b879c58768bd131ad7226506113c446fbf13d769794f1535d58e9c52e23c1bd55e13c647d304e297d968c759a378f1d594897a026e3271aa6b4daabe174d6a35665b35193379f0ee465df7827299c18e1012ac69913a0a5bb5142e99b051763de3e98d5af8b62133e25b32f4f12b787bef7e21dec42de8e4d99a0adc8f365d8cd3e6a5ff3064ca18965ffdc6b383f7ad08186d735a099bb0ee14506388c1a37f7a766d286d748d404457226b952ca6cb3f317b0f4399006b5b8c6eb89f6b8cfa023cec4d2dedde3e31b9a633c0888989b44ab182a5aba30ba78640f477ef1202f6496fafc2a18e283b2e4e8bc60415a1c9a7fd68f15cc1ea0299e3b26f5755ad9f13481a0563a524c6735942f5069dc1d6a070b3c3698e9c503f67a11efe59413e937062668d3439a5dbef197d24ebdc79944b17c549b0648af9b1349cad83c2a0a9e55fd893cffe2aff4626662ebc5014e70baaf7cdbbdfd3f92fcc5eed863fa8afd87f88873f726a0a2eafe41fa81edd5833f5520cf93b0fbf0660e48eb0258d313bafb87dc9b0d0d9349f22fa2d960238f67457ad644bdc60fb5eafd1c88dd2a74db4da0f723a03df08af6c64883f275395020341d9dd3c7fa049ab2bebb4d8af2bb8dc1340d1a80088c4b2c26bfe7314926ee64bf239306c05dc2ec6e6c5e0ed4f6dbe51f5ee09533f558d29ca6fd27092c20dd892c89c83223752006b23e5abecfdc733aaa59c8549e89e5ab0eae1b44189f58cf9cc18de0c2a2f46a9235fbe42c641a890039cf6aad820f1f844edc24e69bc3bd0c22cfad3804d876edf5491e88cf891c347ed5f24464f2df439bb30742e1f9a4a7eabd9346c6a5f93af22e67becc494cadac82cf9cb693acf44560672cb9227eea2575f90b0e28431684ae12ff2e86fded0be3a099f9ddd32a7285531de8963c9a03355f1d9cef88d7ed9b842d0066ccacdb698d42ff9f8a4f000b9764a9aab1f3146f9f95e6636fdfc9ef91c4d060a54ed7f32167e7ac50590dae3a2904d5d2eeaeff2930bd4cad7166fc17edd2c30e6738157eeb0b441491e5dfdc17a7fbb2bdc6426b2cfb26cf2a7e20013f1b3e33a6d6821928443cc7893f7e4a5268a8b94a6ca6097d25be17b214ea4301e9a723194983bbce286f4363a53afd9e94dda9c761481d9d20c7687a2ff85d42436b9d557d5dc6c5e24ea21d5231487df9fc7986100664edbbc51ad4921c5ec9fbb407ab33ef5c3b3bc81f113e68f38d73f0db0261b656fc344d2d23b93446845d69cee1704834d98737848d405f52f5a7bda3dbdfcd3af3881484579d2d2f3ef976cb35c9cbb76252f2e00019363273489b39943d212ccecc647413c56de69e0087532223cf9b28ce3f77fed30bc3ae6a0842b546e0e1a8b6f6ee1ca0ef1b78c3ed829af817099426f94a447f67229cbca3c07b7a8ce547c5eebcf168248e0a0b9fbeb398e5ed2d0dcacb441f95f9e30c108c725507e459d34c1ec01b67065e5e202d685502d6ff015d46c20bbeef1db38c29df7df585b95d79f5687474e71fff162c0ec0c96c94c507f8a0292a8c32168dacd2fff78b5c7dc145e10fee1b25c478172af8f3ea132fdcad75dc22856deb2576a5ff3e8911842c811d1d57ec203c77b82da3658cbfee18d140ac341d38a30f1af298cf60f2a88d0dfbd3e079ae64a07abb4947cc042925fd5c64bb5d4467589f8c495b0097073c081517bc4504dcd7442bad7e7acafc894fcf34f535979364cf5e908a84e0e141ae47e2ae4dc95462b4f345b12b0629502c7bd65579ec66b2d0a951302ba6da1d1176db6aa0c0ea1fa88195dd2248990fa4aba88490b1da4ea405649203f6ff6f734693f40deabdad59ac62e3296cdcbd74061474dd7b63c46bcfe6ea2b0ddb0f7e77fcff3599892c82425b05ae7aa1a2ac1dfddfc67e11921ff4f2c8f6297881dd5e38ccc4076cac8015c59cdd6023ffbd62b887b33ef8d917446a8941d9563acb66a6226fa4d3f2cc21604c080b3f83e73c093d8f2f7067c392671020c7a7eb6fd0d97af0d63032a3116c408b708d4b2f711c1134b88a91aa359608550f0049af2bb97688afc4352a45c4f6d30d4634e70e82515ff1d5f77851ee857e42b486d5e1f3e0406227dded6c5f47eda30d94f44d978322891dc729eb6ae95d29d22c8a5d649193d5d2aaba782fa16ae488f645a7ed90a566e182f97bc62049724f4cb5fc71f6bc7be57f07a7afb9933f6706cc83483cd7dc4182768cd35bc42f1e9b54d5454d3a17e734475ff58fc66d75419d3d122eff05f7b0548188682f1318ec32c5bbea87c8624cc1e548bf18a6b102e7a43e6bafb579e4e84275fe07d8c63ace449a44cace5d9305ff756cbf40e5a6a20334d5b4a74ab0483e31593f2277e90341fa8036496c2bc6d2b7b10b0b354c86d666d65cacc593d1d7349e71b0360d823453011ee16b6280f5c048111b99b185af99e9d901d4eaffd8a96b1ff394b66208ddc1e7e53420fa965bfc4e630d73ad97b9c5c6ea884c619bc24ac3f46234e7d8d35a12b0cad7220d7a0945cdc64fee9d8852bff872c43f359e7aadf8fa3de3551fb716704af68a18f79d03b3c7d90cf21eb4bbdcbb4004f8ba15ff0bbd2d0918ee78e9bde980e4f3cc13558e6fdb40ca71ad2c10f5e5587784bacc6b925f72da12528216895e0ca4b350d078fdf534fe01bc86b45e0c8e2b35799d268a457f8768ed782dfb56abecfd2b9db00cd10e189c6164f82f5ccab423277e3465ec72d76b696cafc1cfa9a7fe47d142fd6672d9c5b77751b40801af07fc53b1c9da0fe6981ea75e066572f7272baef8fc54bfa7cd71cd0fbc5d6cd717e9aa07808496ad2b4b4005a320c9312c73385afd61193581dbae99df6c25f1b9da17093ccfb108b0a26c5ae4963183533ce2f0ade01bf5e818af613416433578522b1b1e5aa7c791570c8c8b26ded266399116f5789a8233fee128e54ca8ce63fd56c1a146c3006316d200e05715993d1d97907ca83d7fd42ef7e7222eebd74f9c86b6cefc82e614a53976272c8801bdcfd882e34d86b39142ac05088a4c47010a71107bc72a380bb3e5122981d1795256beec20a0fe568002d79a4b1577903fe8682f268eeeed0a97861337ffb6861bf378eba1e0957111c7f9fcfeb55a95238005b40e13ce40efe846ddb86d14c9ad2c46cca74baa364ed08da3a3079fae3a36346ac949e2174c661b8801a051423e95dcab6a0f9c965e8744bdd0e629bd3c1a1241e99951ddde184eb8f354209f24c04fcf10fa8f4e43cb55c922c28be041213ddcfad65c86e1ab9b615f91d5fb11e4cdec5b7e25f8e9811c82c2ed457d012e4967b555f228baf4f1648854c624e0525e36e5f4d1961bfbbc3621d79bd6bea72924d8e0146d0965c239a768b417ea4c33237a60fff2760a9dbfb1113a37b01b598f3e06987d99518bd9f1ec96cd7050863898c8664f793ef29114bbeeb9afab8ed09358d1227d7de2aaac0ab2391cb2013028ca5f4d1de6425ec5feb17d95df358572fa27fcd51d14c363a36bc37c7497a0f964a6c004561f68349f828d30d4633e87bdce6b6d92384c9c1c540c8295ea621e9a8006a8d7c163b988853071e06c78f1b9a0246db052e8484a65cbdced3a587e45d9e2b49a5501590cf768d08b6a043971110e9c9dc96abe855abbb7aee2c38bbb77e5c68d61f01f2376b6122450117240532c7c840e3739395dd6c9e80a432423fc5e3a6dce9dcd58eb418e16d7aa507b4d67dd6fe2af4042a5c7398ba4f87c650926084efbfdc9430a4bc2be544880ecdf7361aea06a25e4f592104b0d74312f2729a4db5876b675bc0fa68f6e41e014b7caaf6f49b8ef704b6243df410dce94ad2c51d328fb90b9cf2f5df645015f489a262f57a5aceba40a56d343403b660928cd7a9d165f4a5bc289c0d28f33dac85c9c2a5c79b5ddd22c744a0388a5daf4bab84d7c77685053c912c9a24b5a0664c6253febbcf552c4ff38bbaf2f7e0c9f06e69a91cff9138c2745b99367e00ff6b6a920b1812e17ba44175c033df0e58d1b5c0b7d146f861b62e812ecbe99d638219e0dba4dd88089005977bcc90634c4dfa95f87370d905d32f613358fba2efcface0b9a414ce33b09e271a647b911843933c5d1008fb0717ab59739eb8eb844a4b34bb1a8f635c5895afa285ddc43720e78dc81eee7db822896bd9bd6ae3e7fe2988ba560d58f02592870647b94aad1dbb0d0cb60e28135ceb72e0a6f4b7893a56eae83f9d9a4c549d53d17c6a00f5d6c266d23e7a1d13e22a5fede3a7082dffb34296f8fe9f3bfe525ee1da81efde3aef9b6de8457a10fd4340809e1dafbfb9e2719c327a3c3a4c51d4d5600e8a01ebd5c537a4cd7c4519e963de06de6c83a9b968b01f79e08b5415c5a9d6a92a633d6ae969b80cbb2cf4d6d1ab2c3b94e7c12df27ea89bff4014d92add41a3e961006a194ae3ea4a6b38c2827f6185ae636f6846b1c8401289696fb10c765fa93e58d068bdcd8c9dc95df572f096d65f5de42bae639d41ce7e1ee0f48ba4faf856c0cdd728956d7e4babd6d9d6389ff41d76c5fbd6380f351b05a37022dbce0a6a47ab7168c82c77a2810c80b1882f825ebf86cb7f6d0f54025fddc9b9120802514c797d1d3968631dae95297a857890ff1dee408909223d012925dc08b7d1119fefca7466392a019d4121ea76c8b4c3bd103a820557e4b2283e262af32f1edbffaa253c47d5873bfd0219b8be86c7e64ada2d87ab6b7f428a7d8fb3ae09b05aee71054355eb83ad76c05d836a9f1a65511b1553927ef1b19ab1576d7185af61be6104de1df218918179c6321846085a83bd1217aa63d0b03996ac1fb4018a8ab54fcf635f7d5a8ade95894f0d407e5d4691920f21094c6f632f1661402a0b3351f168f16a13d3a31ad48e89230cffad272926487f36c7a2584c9387623df6227be8c96088db4a21c93b1c88ee756e960f60e614b30bb6ff757c20f3674a7ae7f6ff6a9115a0a6d444513ccc0be5dcd557430e0ee8db3ed5b3e8c405110500b9bf7f6eb7748de4988a1db94bcb16fe33479f64762c53a1e2965363452063d7bc14386ca7b4d46ebcf08489c64ab413ec0f1ddee8719f5fe978d38438ca3059961ecc8480908cfaf139d88db2facb5e7a88a43a67dcb0f97a17f9bd5b09b8369803ccc7ab6d41238e59e43762965814c10c36fa4b6e61bf2e83c0243f20ee8aab62dfa9827aec06f99c5c565c1bc75291292d3113503a202851c26d1a8bde54bb30f0301e555374b71e278925a2afb29b0209c08ecb89601bf612ce811a493abe2bff78e7fd02ee13c5db6b3edce7c87559410b9be3be95465468e33af224d6508a44728cdffde4cb14fb96a0d2ab9c7f597541f9963775c32ac613af9beab89e0ff7a5e35613751061b0511532b10b3947802901505c8e33bae67ce0e28da760af7e80b730811bdf17abfce39d35def51d73a084119449038c2b0f1c86d844123c6e71f28b7038053e279dd11c088dfa11c547a4ce13b19453e88e5b74962101412490cfb68e21d8952db509cd3a814387b67339fd04ddd2163177589146409934f0eceb10db2d90a9e3f6691eb75e84d5e66bc3228baeadcba200f3d11e0cae090ffbb800f5da7032c35ab572de55beea37258bee6f191addf01739a26efaa612991cb2a3c6d1bbb03de0ee1fcf9b7f6c51e452b21c0819a9aad93162eb2dcc189bf355ecd2c3e504713dab24bfe3ed86a4194611029f7f6216cd469fe1f7d35d56b6c8c2045011e238f9cbc0a19b8914d74329e2472f15d0b7d60511814ad2736d6be168aac01868c2a675549c849fe05e05a76f077130b46896735db5490277b76bba43545de6b8ecb53fd20398eb94dd884951fb48d5690ce4bcd0b836615cd9340ff0cdee1122743accfef343811a71c7d14d1369fa49ce47784a6ff8adc26c151edd4969dba513ade6a9b1f009e57c3d6aa845ddee275169ce58e1f04b564ffb6d0eec75f7172e5e8fb814cd702c9fbea8a783bff637db8667d4b6b48a264135bf60acf335936105abacff0351ba9aeac88e9522cf7ed80069822a7db1a5d8221d9492e02ca893e1f15965fb82a80ee2ec491027bbc8906e71cf931fc21e1c0865ee06a79c023929625b4d232c7b3e2e4a4e5dde28fab675391befe583c95dadae71dbaa43e09d8d65ba36d148aa85d1a2a35dc51719ac0311ea72c1237c78a8b1542c59de3b743087245e54d3111c585b5e5e7642f625c8d44c6d9cff50d8d071f6fa573df937d9e7457302d8b293d8fd94ebd3023c55f8b260c3454e93f58f16d0f451189bf41c9f9b91d3c3918adbf98e4ca5aa0eb6314041521ef880ce18f0ce296721a06b329bb5fbb3024e424b46400e03caf0105877465285fcb41a93844fb90b7fc1924883ace6ca8a37c9905068c633761163affae39d0ba55b67fdc6bcf0908ee3a42af286c" ++ }, ++ "transport" : { ++ "secp256k1Address" : "0xe23c5bba38d809fcb2d3384f210e9a6405beb498" ++ }, ++ "ecdsa" : { ++ "addr" : "0x48fcd978ac4d42ff52dd81fcd17e93190f35e5e0", ++ "claim" : "0x2dee91bd2cbfa906aefa3a8ae6e2de773f55dbd28e77bc329d28215183068585601ab9a7f9ff0c48095407474d502a3af3f059a666e5ed1e27468466d69914e801" ++ } ++ }, ++ "1" : { ++ "id" : "0x690a7fd66157e5b777256ea5214f634f61b3a72d", ++ "keys" : { ++ "falcon-512" : "0x09a6d094d9a3a0865864e9a16b477236f1ca26c888fd0c918db331c87a478519c41085cdac7e6cd0d89190a41a3bd6f4d6300995d591f5e22a7b7147caab1f9c7a85a4ba74d47c7b227326ac17535de039a7e604225d3daac7f75b9544654b73f79f5825825ad6e6c45d13e6d385a644633e1c8806d3a0a551c98f032583c95fb13997e52a6b02192d26b5a47fb22ee52999ec92b75c70774a4ae0481a79113ac72346263e53d5dcde708668d317dd00552d5a40ad47e59a501b10a50bdc52c5c2b2c920fa0e3dc9b8eca54b10aa5ab1168c88287dcf80ecd880a8fdec85b6d63a15b9f453845421a5d9b898e6149b60454828eb9dad6442ec62ad27ed72215014f3d17539085ea3f668b0a9183ab96e9db996801c72a0920b02a249911924f181e8dda515d114beb83b075ce7e7a0902a6971e31420ee4921f5cfc123f29dc7775017aefe99a7e326119cb925f6f603ac3bb137313609498d5a2000c426cb332c82500dcfd80d70a5e2d156844a683b313266af6d60216bd9e9998bda53c0028f387ebd21a5fca6c0607d54b1e95724746d15f25f16e45845926a83c7598646a0a0d3a8f8307c1a401b823f1656ca41e5499684150a954318da076af9131fcc93361d9bf0ae035f617e02cb5e1224a982b3591b24013ff80dbb61160d2ba4ce85a4260c8a3a3218e0ec869796b1b04a82079cfc0ac26da03b04a11950b2a3331ecd0026ea9737bd20e6ea3045b56e3c71278d2a8c72c8014b769da9319e19dbe762b1943e5a4be15aa84d0da831eddbb10bd05f35d55b6211d02a61c5d9247e69cab6c112acb568ea51f345a5bf16f84782e04220e217722da71d634e1a68b796376c8a49a965c592b87d06702fe42dac12da108d24ee42a109e8e4cfd3bed6ada5e3de50301696bab0564292864f1b9f47d5a53cc0c5f9cc3d57051065fd57064d08764892ef4c4a92b475184a4cb4ce1f3a0e6da0402414db5a9db34632b9717586e799b06e870b81a330da7be6a45ddfb000fd337a24a29e164449f96be015818c53aaaf09b9a565d7d9d735b9493885e7cb49a5f1985977cd6824fd62f51d2a1e60289dbaeaea148a44dd8876cb58b8ca2f29f6455f354e4e76aa13290f2979b78b22afa0e65c696c21497e94bf0141ac6298aac70b5ea843848a2264fc057abd3593cb17465e06d41731b7153b71f8f0f7a06d362fbd09845f0815794050460b41ad003c9396a86eaab240555ac8c75f85c0ab972c1a0b94b67b1aee2fa3", ++ "slh-dsa-sha2-128s" : "0x2b2fea4a0edd5dcc2f653eb2dd000aecd87deffbce8818aae72d7862b506bac7" ++ }, ++ "pop" : { ++ "falcon-512" : "0x3968f2999d69a9c28ae792a90a47363e689bd4b349e75c5f837181fc7b16d3d04489bbc32252d750d750417770630c5b65b88cef918ad23e33892a58458e9e63ea591596d3b898f65e1a5be3d36650c3d9834e1ec725426960d337b8f25878525ee3c3798b5afc9add5bec82c8e139c59738aba9ed5f42d11c886472e81cedfdb5b910eb73e884e0d4cc218b87cd9bcc0bc107af586c65b3949460a25892d9607efa341f232e478f3c9fc2d05f324ee6eb7bcddb72af371d47c36856f488872249ffdd322d3de7d12b62b1ec595187b5b363e36cc714b765f0ad5616488300f6e56811e88e359365d5698ab123b917bb32f56566958b154f6fe052b894ccc1fcd99d65d19e8117a8ca4887e01f36f181461a433fb9bbc1790d8b14e34a097b149f0c5c075ecae3501944935f3caa76f0b9370ebe6b90390b4d059f9029ee4af98dad33b9050877d49c3d4f2beaa4b5861a21af95b8c52f9ab4b0eb115357f5b1d25fb66a36b9baaa4d6cc5a4f5fb5462432bd82734d7393cd22c68f52493eb3434c3b88fa255baae5c46c650cae17ebe59827cd6645c6d377b3cdee3aa6a758ad3a96d103bf6ab8ae03b72b53f3aebdda359288c32ff5461a158962924a97a24af29f6c976762e8de9363485ada49c445566e71ac75379aaf7bf190a81c671115e842b5280a05bfb2ef3724bb74487068d5b5ab2d089ebea7ffb4381a7e96233f0915f295d3b71db872393bb990b9c74717bc3d72f6271bc248e54828a1e090f6da56de3643b083e9695db7d0a32bb42355e245e5cc2ed57354d82220b449e10cca1cbf6fbe796d141591d6f71e4eb6770a3c7dfcee509c3c28f2f1988eeca61833b6681e6766790c2a6f043b4f67e145b908ba7f03361cd9d435d054e11edd9667e4f9d12c2d74f2832b619", ++ "slh-dsa-sha2-128s" : "0x39254afc16b1dd8d4fbfff766819460253653dfc6a8e29abed55ffe91325afd578ebfa2dbe74d46b48b381e69d269b5bbe24ca1b85767bd71c744065fa47c646e3603b44261731b50f2d20a7a327e98b84c5ece73697739c8057f99d6ecbc54cf891649fa78b7bcd824972f3b27820ffda3629f481b1193b922cefc907bde3ab1c78b5ac97ff26986f3a553556d0b158e936450b4f41bf006c90a9758e0efb327f67408a7b803ede993522cd9042db4a672c89d4765a0fff8c6e8bf6882a8de432229dee08ae13def90f9fd0a40c99f3d93873a41d74871aaf407b0927a817b476eb93c645254bbc77d131e0bd35a2541248172993b1064d5b26b921396c8c1664178051810961039b15790862415338806329a45a266aece5904312afb1cfbeac1e816fb96256fc6e2b059c25af1966b0bf261bfb72afd8652feaedd6e0e4bf829a75188708ac9c623d4d6699281913bb563b96818f9307b66f7cf4aa9591e30c65a0b0885c22b5d17ff610f40bf2e0a9a32173b2fa7d66c14784402885d84f33fc75afd8f743cd10f5ad6dcce5b33a8f0c0365de2ce1b69aa86df2482a2c2d3746c6f0ee4e6fdbeef5738d809f6b0ef3cc703b0d29e93e198b68d62a5be657e69c33459fe4b163a5ecd72a90f1e53fc00bc8c698af7ae3cc5b07e36cb74088066a54138d6df4ef6e159ce5924b6903346a5fe115272cc951e8713d4b6f96f78d67a542c3bb402e69bdb3c2b06e189186c227927b2aba52b29c14e837b37798321fd000ed3bc0e386ad6e5d3a48494f57109322f0a87f7dd752d862dbf772498154804b09eca84c305595cc1e6654b1b2e94d5b88feda176aa144d3895a249754bb2ea99b2efb4f61b828f265638866a49dd3437c70016347d5aae64c79957ed394a85cfe06b10b98b6e83801728645529537a1102bb04ada4226688594cc28aefb24fbb0d1a60c7b826dadd23f301517e862c67fd88d0f6a5ac08e7f966ae375b468e57f01521b43fc24c761838c174ac106c4e1f435b7ead5e79aa1b303222f6b45c5515d497d8e7b05901bee96945652d304ad9ebae2153321885f19e7ad08c9da73ccc22a66c26c4cdc9360c36e307310714ac44c80887f42a2575305ef649378d76d297dc6faa904377b2037618f23b8be496fbc680645dfb80a76bfc060c6b2aee4ac5537e79b7dc7deeca0ca38041dc877b875cab1a297190269c987dcc46ff34e5bc154e2572695e463542be79d61fd5e96a4be2b07f5beb71b882f99de317116fd0b36131a88ff9707eb25594fec74cf76c2859ba6ba2b968d41479adf8857f4b0f4a26f49f0f04fbae0e2f3c2ab6aefdf01855a7a5a4b8bf516f4551a393a33d3920ca3ec403b4d37c2106d777e3d5dfa768614513885d857ce95b9bc3b992808e7ad71575e5e91b8107c5802043b221c74d73c7bbfa7a191945bbc5ed69e20016b16e2e2987818cfa80695e58950b0c1bbb8c474f861d1447161744c75d99dc8240338c43a5c19a8a9f46d80f6b4b6c1cb57f5a3350bfc35a0522f89e3470ccd71a458968c629c93336af6b5b091f569d1fc9492eb6b976376b8ff19ad9318f5cb1361954a0471419b4207dd9dace8c0545e74dfbb19ce3fdb5d456a1c1bff7383c6fd96dde3a92daf0ff5a315714c74711e3c05e0c59ba525c64ebd17fa20f8e143c5931b3c77da193415e6506c2db27e0e773a6a5b5d47ad95760b8d471d06d5dfe000a2d47e6e4e6abe7219750f1f7892f4e09fe88d13c2e3b53dc904ad58eaed856a4abb0c10830b96bfc1b5764f9e4b34b0072be314608fdea8c5005d40ef99806d4d3edb72e73541fb828d4b2adc38855e09e974293de25da6907f5ea97810eff1be37f88ea879e545bb5a70d2187edec81bd57a95c0314df4ad08a864156579d50826d0cfa511d335ff722e246151a7afce94126232f6bac89b13c142d29e7521479866e35b17c15f16ee89d798ee8bfac5868e505031586b81bfadef4aafc2ecdbde649f63e07eb6026d09910d9d3613a9871b5d1523cf5958124f96b5304d5225b4bbb03aeeef87753d0b6ab51a287df1e9031f56f755d3fe5a20f79b7f0f467fa97eac5bc09a1adc6ec285c8f80ec5c184b8b5eae326300a5bce0b1d757c8e4f27ca2822e73745009291f0d9032051e15b567511908f3ec68840cb6ec6018a9a0e30f2e34759743ef0bc9e12c9b32f29f4b70a998cb8893af2dcf17e0eb4f48e7ba367f68aea5516e7248c8be1d1f896d7e8446fadd9603012dc13126878300f0868bc512221154a5104882621f831e60b49d04fa8a701256b3a413b9db4abc5af10a3f8f4c26cd0b3c2f55a58c9380143d835b759bac7fef824515a18d79b6dbd361541047c79653ab4af5473b7b7e67a6755add78d5c14c0a9edc6c7dd42c3d0359d9f2f6961f8930458a34c4f12478ae45c20969c4c18654d31a7ae73902757b3b8a4eedfd16d6c0d22548d7b8ba77aeb4c1e3f3766b6ea802ee9bd92c5f98d00be80c15e7e3a82eb0d100436c398781607dacbefa98c87b3558f363b3ecb1ff313655838f864c1b2e0f6d6369bae4eb8cef98f564108ab2f763e590a9e9201f4e28ef1971438c30f4376c55cfce9b9910f448e31d06c2e456eb798476d56a890660e45616840377ea0574d1c066ae2fcc46f41cfbb511e5efc4b5c60e00e4846e157bbee5fe3bcd77408e3bf721bf871c05971a70cf7a13c782bb4afbdb1ef800a414260243fd828b67f49007eaf60b3e32f4e2b8186291075a0b1c0a528abb9da7974b3b1e8b20d337161ce234db66ce82a88ae1dc880933343961267cb4932b36aacc5f136cb474bbdb5e4c4be4cd74868775d80317bfba00ca4e58a39d04e63bb797de366c45efe2e356672f567ed1f7b2741df7543d6faa7227601eb7cff367d5a1ff320ca71fa2a1a42866239cc3fa5eba400ee4060266a05b8fe1e729908b95ba6aff8fd76b5e7df547df62cb89f0605c1207c869d7214e4e6972ea6e47b18235855d6f28265a737b4f64f0d215943f13d219292036c1cfc46bc61679f034919e4fea80d882a5121cb3096a50f2112eab265ebf75b607b93e14ceda4e08152221bd368cd1503ce375188d23514dd0936bf980d4282eaa6fe8f38f5eb00c34e3557ae363538a2c15b560b9f9322d1f17446e8f3fd317126986afc2c5e9fbb96f8ca7148f53cd75a4b845a28034c8679baf1f5406564b6e4b8fa8e681b5a9d208f3a1b28e84d6d52d4baa152524908d50d71d9c0d11bb5665c8a6bad669dbf303027bd0d534434f9e76f2c300326e25d00bd8d3bb1debe1c3984961c0ea8dc547e8cb83a8f3b044b673f4a08882d103d6eb143a9645a9a00fab6f1167a2c09015d6ff2dbe4aa4025f604a63eb32330f832162b6dd9364f4ad6afbd86c8d26f56d7d9028dbb3051c85a0c86ec0d7961fd6008f87dbe8347fd5ed1dc4c27285364f63650f161321daa83ad41fbc3412bff800c062a78cc5caea330cd58e63ea9a9d6de2ee069732799f52f49d513c658a44a2122b8427a405d706f740600f855130a0ea720f76b3111dafddf0e2ebbd13f60640379993889089ce508b1343f485457cb8e0c09760d3199b4ea940d584417259e41f2c66853ae4235b6f010cceca3859952b3daaab55da14adff0e421e862f138872c2577637b3e12b00384cd32fb3b9c97b0d59e51f2488e379065d79f5a834b076ab5b35fe4c47f2c4c4f43e622527abb8f682fe9f262d2883fce5c9f16b7566c4e078b67611abf72cb8a0263ba12a6c23b1a04458c759f2bdf6dbcc460bc5df48146468073b61aa5ab4a9c5f6c006f54f1bfdd85373f33af29d68580eba4cb6dd88054c81b3bb7f2be8186e380bee0b32a1b84ef6319798079828080361bcc27473a9634c23652ed6b2b2c8f8d5a6721551c780870f1787726b121263e74c9464a76282dca27249b4532e49455a7485e2cda4ccca823f62d3b2869602197a6f1ecfc9d92ab6e231996e603e81e3dc648aebdfb900a3d929502ff0bbb3dff813660c9d5a417d857c19754ee04e50f1241831517fc2d2a71c5e238a944992cc50b7106aabb5482fc7e0a2e6b5b11bb6845f34ede98a18d5f07759e61603de502b5eaabe59a4d2c69f4b0f8e73a9bc85b8950a54bd91bcd0366dffaa0df736dbbbc35d6accb5ab8b22a870374521f2035c1878718d7d3b025838da75d8bfa3ff36b2a10a3cdef1b150abf3b6be95a5c096a921a3eced20f509dac4ba43f2f515af2b65d3b2ebd0da2d7a58500157a666b387b1814d0a3e84f64d0fc44507b0b6792c0c6bd90ab62e0f75b66d50b6f842cfdbecf1fd043d642c5d5b5fe5cb68af62e6e23cc6f0f9b1cf3cbd0233ce48a996296b6609be1c9e7a027cf76615dd11208f1fde119099352cc17e1c9a22f4b71c3e628d72b620f3cb4bd40e4294ff8dfe19480b5b758b874a737e6092254638a222c83aac52fe0f66670454c313adb0dba2b4e95741d27104bbff159e999e23103c00470a7feee6f4a35f764ec81a8ef520cf1e8623fed3c06b63c022e40e7638db269b8add119fec50456b33224c14486f705e5b3339c6f38aa4ba6dec8b098c27447185ca50cd70772e5389ba703a4a9f8649946671a238e1f005aba0b3a18c8ceda9daf4cede6782d27931c638af3f6083b2bf10ff0a632ebd4dd528da3aa2b7a8bddff2901d902b26d518a058921eb0178ef08e24f7075f77ea0c0d0e72f29847ac7826230c0ddb5e7fc8552ff92c007e9141f51384a12e218da4fbfa9a7a4a1bf266aa975949e120db1b6755ff04adb07c66ba9619b40396072e7cc01dc3dd56f7a2f928a82c8906be416f6d5c41354881f9a6c66a927292f8cc2887aee86e90da32fa3bd9d72bc26dfd334f943305fbe4b645df83fb72c565f61860a480dc0f2f3360368ec3715c2c4a312bd2653051c8f29fc14e0c3d1f515e04b75ec02cac2aad8d411306969d9a8da08c3477eb6201bd54c6ee643d87a89c78a5c8ad48590b7a499cc44ccb812866a4c48ec2da5f1e0aac741464b26988459f3724ea4cf103c27e4a43e5a5fbbf94908878894f8b62995aebc20e632d924c82d9669f64b2093cfe023cdd1542c8f9d19e5e7ad6ed7920ba6834cb0cb91bce48fa94be47c1833c6ada4090509ba38defab7d56dde8168bac8021fb5a2aead00809f1881d53d26fa9cbc824488e16062fd9f68726c837234a82d518e3d10c9931295d20d9affa5fd18c0b2dda299cf1d6fe0c6e6959440af9b397f3441bb9881ba1d2df295d12686ef6b0bfe52fb2bef06620721374328551040d2fa434b161648b058b74df2a7ccacd7609b93421f44a136079c79a3e63bd3b4f79717f3c121ceec2c3918464f5619b1a2e83a7709fdf6d1004b0ee51c73e740b20e329847304a82802e02170db386e360dc6027aa7ba1ee35d7eeddb41ffde093073d92899d568bedee914627c8c48427376e7b5d5ebdab30e58147dac5638090e9c71921431f025f1d4e3ba3c68437555357c651336b326c9c519544363d5f4faa91914195314cc873ef97068d928a6b4e5c6ad70ea7a7b09b3108fd5696aaab800eafe463ee52a3f29e1bbe8a968e84b762484a13714ee260759b4492b749c46ab6603c13ece34e301c13bea57d9de706edc839f55b432b9299d2d6643817cd9d32d0d9ddbdbb23acef51992b62db024365ac2db4c432c531cc1ad18c807cf1ee39dcd842aa9a09b232cfd09bfce33277a8ed09953ab3b5d24e5a8a02fb4a02ceed705185880ecc47cb245665cf640ded4015b4afda053a5d1dff77e390c8105961cb3a954c28ddbb9efd759080dea99e94e69b03b928c8667fa4797dbb3cc6ed093bed107c817780f60729036f13346f05491fb837ef1ffc61be7b61d0b7f8dabfd49ec24cfcee088de38daaae6b4e740ab4faf16eaebf89962331a99f17ca5955b15dd1fa493b91e7cd218aebbfaa7d348b1ceea26951209137448caa93fa466ca32eda497a5b9a4fdbd23a10d9742e74c511a1648d00bca3ca23abcd4f18b7cdeb362e020c73888b76b83e70d26ee358c06933f77d1221a8ff0647200e451e971fe45c23aff60a88baf46f59a0bf94e99ab9337b0336ffacf8e79db92067d2b744134cefac1241dfda288f5c6ab293df7469ae0926c166e999ac99c8871e571eab03f82de73e9de2d8f4deea3724f795480cd47e304f27f2567cd94cbed52e06f1f1cf7af2feaeba8b95927eff950bfc26aa0cc3e46ec7bd5d4aa43374500f8cad4f153cb586620b9a0deeec2cb12ba48bbc8655c7fa70ccf94aa6891b5cc8a3c98b482d906d72e9d425301d0cc6fb4ec9c4a5bcdfdd74fdcef68f05fdb78f2a1c5ae32c28c43ee900738f31ac1fd337ce95966b3f557a727e0c3ada6c6aa61219d92fd5cf68fcd9b444f6b4fb6178b9c74238d2575f442a298127f282b5ad416cf6a365a214048489139918f93ec07f2cd864f5482c418c7336ca4590a7da8a20d33ffb7be19934c80b64f4b982a55b129f4896685534b83251d54e46a2971c0bf49ded9b13a77ade3de9a61f2204a46ed9cd7bc444801381994c8ca5a66abd70936f8d11e2a2fed78fe9fe8889dfcb979c9a3f11f2c2c1aa371d1e98c4fbdaa95d58c6b22410c0d3d3460077dce654a1decfc829f117bc407d06ad9ee6aa06bf818ea2f25312b1cbbb5de527ce9b5c5ddcb0df21e3442ffd149b24af5e59eb4d7e18f68b02b26e57fdf23e7af4fde3e672990295c37186ca67b2abdff6b46e1ff106f041279b61560ea2eae64649c65be22f9070c3239b0cf7929b0778c43dae5391d8d3b8c335ceac672376588a34d3b9c61833578e8d5a9e6e9f72748d860d7af98f7616431d1ae1ca20db3db6ec99d59fa98c25a1cf478e1b4a643c2fc9d3e482d56bedb1b7a1fc9c3e788d9de281c7356b82e3c9e1c9414a0d14cd07fea5364b6a22dcb3b69b6f447343822098548e3ca7e88a83187db145bda17f7c48cb00e6ce36d53e2d1e4c169569ee3fa03620a7131bd5c033062bb82cedd0d0ebc1025937b2d85a3cbcf6ef4458a57525a66244be3a62b582bf2b88549431cdce09f6407e1bee83d3fbe205f585cc7cf9c1eaba047a01f51e13bbe0715a9112c451f1daf6074a1af051d8b98863b6fd03238ebe295995d60e7a26d2f95a2b4b0d617af299133bf357518b84e942bc36a88b4030d91a7067e7a2ed7bbf4e9abda8c6887ecdfebda04dedabb9ea833123507835e0357ca1513b471da73102605ed03297b5e3eb7d3bd01c670f992a7f19962b706e8d0ae0f073638d633b34a1229b6979b8e90f2a536cb6024c644e1f7ef211451dc509e061b294c28be188c96246614a1fbf52db8d9a99f7100c878c1b9da98ee9e9eddf7fcb386061ddf46807c60b24d665f0fe7fde205f91021bfb87c8f4c89b5da254d185bda9cc2f48303b483ecbf934575aa45d0d58cea64662f0fda4d97790bbcfa237984cfb45a9cd611b533dc0ea997d191d14d307c68db318aee8f99544fd48fb86f041fe249a14263e6657a5ee732f7c5c9c97a8924bfdddfd75dc67da65042e711a3cc144f46d10a1a9fdac1b1b321eacd235299a1fab390df24acb739d61bd60c6907b9a3827958198e6e2b5a1c90cb9b44cf8db9b6e45f710d7a39c230ec9cd855af797555fb1d73492e29d17da0b6dac59c2ccde0715565efa1f62898c9b26438c60fc3b9f859bbd33a8e05e1d3d5a762bf19bc7c32cf7d4c6bce26fec6e5c8c537608a1c2aea2e1e5cca5bdbb45a8ed048514ef3d298e7dfb9c5408d941ded6220a44c184dc90c922a3ae31c9248c5f31627389770a59f9431fd0139c5ac0f08f69151a75a5a6a0355b7beab6be9829146ada371aa5791c861dc77598f09448af20deca73cf98a399f35c36f1167ba426c6cf4b8b9b8a22b961bca83e45bade098e20782a9f70bd54fb8eb6eda3acd3a5bbb553438cfe37e1f7fabf15729d6bd562cfe379d586181b71b3d3c4b360852003c4363a8d473198130642972eb3434c3a5ca9b497ec7000e821c3419aae75866496bb1b0a9ac6cf92f799071e06809f1f3f904cd18f32629e2093664755803f62f45942f5a358cb1e925a8694998cb14cfc52733c356cfd739c3976712ca7b007e08841639da14e429c102a8fba3191cd36c1c56eb06bf69afe3f2afc4ebf137c617faacda6baf5cfdcc6462ad02f63e8a5375288d0de5700d0f9f4ca82a65bfdc405d3f96fc663658f0aad91305b86ead3b21bd6561a40db0f2c5b0937ba5e1ecbe91e9c50b1dd6bd83a8145b033a7bb6a4ad4896e0ab160e8a52d39d2756b1c8d8570f7081ba217fd8803954290788882befde24b4971723b0ecbeea14d23c92eb6a0d7022a84aca072729d7ab1a88927a25f19a2086f846a44a2726ea26cf1b69c58243e219c756d06c361e1e161bdff0eca10bd30d23782b3374ed421f50cb66c9ee063ca622fa78c8cede932848f0f8f91bd7a0eaa324377c109808bd66ff463a72389c4b49f2e349be70d07fcb56b28549fca65ad853d70df66b587390febdf6b1881cce6c1ca9e9fdbc9f1ad68ccaff97234325d3c972b57ae5723fd73f975ba640f90e717e9284c111b76367c6797399452d37df6b8b8d22ed5e7dc1481a415fadc06673ce4eb6435d31acb6af68775436629a57db7a0aa192310e8427468e8e310bd3426b7ffab00110324c0c7e04ac6649b6f167fa8b928b3fe12ac162db3f2bc355295650fa2d976c64df69a8017034683bb4bd4baacf1cd8502dff20430d48c907107acfc4e29c584cb497b7a471fbde90aabab25290d853b8ebd2c0d49c2c201eca42a68a15879cf391671946319427b237472cd35431128ea7ab6d545617321592c07b09fff93e71596da30689b3c15368a1c3a57890e0ee5752bb4356290024fd1bd2ebfa19f7f3ca57c36d296ae61ec5581ceb77618dde2821460553ba0dd6dd68026b911f4af1be3986198966f90ab757aca2f5143f1937d09c3a08047b797781d1639db4030f9e59f8c5b71a71787cc84ade5a385ebceb1946177a056179aefb49e1f69ed0aa67901b2d6b2152b6c1fd1db67f358093180fcb8f96483fd35a87fa14825d3849dbf479be493bb2d1c639674bd195b5ea3caf49c2b78eb0e953dbf8fb909910c87efc6f9b6592c020333e00f83bea4bdebef4e107798f9a8e89fa5d063d69f88f31a53548ba2406407251f18c3d1ca6e392fb81a46107191e6d906b487469d0002afdb0f32c39873872a49eee649250d4d5d3a7687fde2952291c8ba78fd9b962060df12d212033303691b05eef0ae0e7f31b7e395576708d211d70281e9501618673afac20a93e82f060135e51b29132a0c9244551814bdf399b746651279ed135d162e366f39d40e3a49e907f72bf7c66fcb4ba75b1f447fbc3ae3f390ab4c10963d755ee188a9b0129416161995adcab12177976208e1c93ef48d3ef55ad22bbd97781dc7035c9f5fe25f47b703b1ed50dba311d24154ab05dd88ccbb5a8cd96d4665829c4dca5d5b22affbfd7e842ffe5e87bf4326f957392229bbc893b1fde9e4b2191a3345490d418e9298179661104f70bf6cf9a0094f9d37be98b82d98497573512d8f6fb4b0b0aa334a9120a5afef20e0379197ac7ec78da3688d2c9b590e40fcf866acbd1d857546522788d1f3ae73f330aad045c5bfd59b8a399ae626fd67d9797b32d6a279d42eec3ec8a2888258728f7c329c4efd0f71b730e57f9bd87204d40ac1ea6032a4b8ee3a338aad58c2f3c9795819af4cb652dedd475e5662d9c0cd23e72a8f4e86f1a63e5683c814a99a6595b779e5d715ac91ba62c1ae4ca1651581506ba80c2ee0d3f97b979758cfe93f373873f4775c882fb3b5815b9274595bf50488b935c82e0fb4ae4d078d30bf0843c89e484bf5a24d5de602649e336fb2b79da6131f96ef1b5f82cbd668f4599fc9a92b4e9ffe3468e39e4c8bd90531952327da74a522e479c66b7b1554c9a72a2e6db58fcd45588c9ff4f48be5ddc994913833b668c275174b9d862dbe8fd01535ff2bcff6ea030842ed3a4d105ba07feb0098e39f61a4cbc06bfa153c598c10c5de57caa413752878c7599e5db8482b6f275db2185c505bc0c9670fa0afe37031eab994120acb935bf9dbe6cee6ba336dce1b44732c4267ee77f5db890041e547bde486335b9a0b85d6640f6534d84b3729b3436ac1c0551d687ddd8da9abc18689e7e932d5d0e787ab5ee5f36eb53789b9ba2b71d7a4f7994e56b056d4a042bd2cac79ad12d87726ef8cb97342e616269e9f87493e95dcebdd91763b134019c0a76e8b12789b026ebd1d9caf1930010aa1a5c348ae2e6273c885ffdf8731b34d87c293e77e9ef14709c2e3b739dec85d5bdb8f5ebc9eb610240576435c8d222ae0c8ebe5844980560bcfd45cacff143a5c208add9011bf9770b7803fa90bbaa10f58d856250b37e481f325c538e473dee7863957121374bf12172321b9c99975078e43a0e1e40138f9c31d6dbe5e06fc881de840e64899c0cf342a806916147de3cc342832a9514eae9550d2cd1166e823f404a05b418e5f9ffa84352cba3007f9d37e5b00049d7c099346257fb53e86b919b45a9c6cd8b67cb3c4e383fcfd5789f2cc087d6b459e2a7dc96d08c826c43410b3df22021855c7d413d9cfe7ca79fa860918a74941e08511595fc9a3bec2e2e0c6dad05781c0a0d6b6609837ca8f78b0368b1217b121cd6ced8fa48dc131709434eed65523269abe95f338bc5e3fce0046ecb24dc1ad8c8fa68b5f9263361e4952ca1aee9229811a5ea85c9c4452235639d1eb8105ff88c048beddc0f7efd3690da8b9bbccbbcfeddcf3e3c9e3ea7b46a5b40098fb85a25842911e42a714c2dd0fab403340ddc1af9484843b33c7f5bed80fbecf68180c9b397ed85c51d39cf08c5c0336b149e6d1747360541e84a93224ae88c1b62384b938ae25ce17d656b9ae52fcd9100a40dd7793ca67357f3fb00621863a490373f0db49b1aebaff7284d450922f1e5243bb7fb5f7230dd7cb8db1e08893696908cad4a45711eadfce8b0b42a9aa937cd011bd5c4a8c3a2ec771b3ee4959eba5e4a17545d1c86acaa4805e4aad" ++ }, ++ "ecdsa" : { ++ "addr" : "0xa16c987b93f1b3c51fa8a9833c8932eeaa566ce0", ++ "claim" : "0xb0c578f123a8a0c96354a13f98c4c2cb8a67541f5ccecfdd0cb6e61aa77f7768157dfb3ba59aadbc03350577f6f31b4083bec30291a61ee98ecb3db2536f788e01" ++ } ++ }, ++ "2" : { ++ "id" : "0xa5ea2fcff9e3cf29d0c6f5f147b67ff24aec3bd4", ++ "keys" : { ++ "falcon-512" : "0x099202fa37d5e165b88428d963d2a224b8fc82ac0e4b3f6a02376f18218d1aa7d0e910e71586aeeaaddc2a557124d6ab4f9a44b9cad02166413cbeb14b364e13956ea326900eb2900802644167639045d76bbc4e051654cff404dccea94402141ad9fd992cef7a8fa6478b3e6f8912886e9edd1b34c29385b7e964f360e0fb1600787934486f461c95d577d2bc74c4dfeb969b4798565ce0225ad27aac052290a44f844ae233e082c97e4498a31117ac9d02f3605c856e2dde6f611812161f89cb3a54dc936ca1e740a6c659405ed586a9a963b11c89b01746325e39e645c72b0c7e4491b36a17d43ffe38d88c601a5976f5a9636c964a012bfbce5f9b371e7c3b38580d81c6e12b8e8f2aac219f96245d35b4f4afa6c94015b055703b8c4dabaea4ce2577482f5b34fa49e56a912dd58d74580b1f94e1d2056594ea64bcdb696b0baeb33c86b6544761a3ead9ba9888cb1ad51f7027ee52b21e46c5eeaf3f77bc0af7efdc87acbddda7dca00b6acc665002c26447e5b0e0bb5ba261717c68dea7f1576462776954d7249c2fd0886f615ad50d53960ca02d581a4a25517c050ed467c7a820bce6250a9ba2e44fd67fb21bac843bb134c95360dc1c50d54b7280a94440d018181a9d6374bc64d782c84471b47287d8ea748c36cb83cffe053cb89a9e4ae71df497871c2a728ef210903e5b7f39550d0331e15637be7e28b3a2fc05b0a9b0c5a06f9fe81263c3a94403d6c288a561288ebaf788bfe271a578a1a795a85e9d452b61ac204b297090617286922376bf0a8d67dd35fd705b81260b7aad30132b965e39bc3cd64d154c4175951704873992a814814dae5c6bc1e89a83dd91144cd1b88f6ce449900058afdc53bb44bcab63d30cbd6df115a5ee8f5380a127a160e922bebf7b408de82514b2e2550a0931e065565e8dfc389d454823a55b03e5c989b09e3791f656794e8379b7b4b1617aaa9770366d63a657f71ff40c69b1d5da518ef1e2aa42366cfa38e448563f6c2db5e3089bad5520ec26105fc885993630c10db357883f588a5a384cd6de688e1bc3b1200f87ed66ba3d4a4b671b2a500a0436e0955904030d76577aadddb8c1ed21b027f198c072f654c3abb086e7f185980f49d0e109c1a82741809f8afd15ee56a887b392c5b172ba659144a7e99e25ba19792d2a3c0ccb481822839c8c70c65c0943a2994ec9f6085b7ac64ce2b35489a72dd6693d25f2329264e063db26ad4495e3ad00f12df8cf914fd846", ++ "slh-dsa-sha2-128s" : "0x686b5dae4aecd5618b95c3b2a5792888513ba49dd366ac39b7431ef403e04963" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39cf29ab9b80215a9947b975d8c6097e53b39d1483c885ff7527d7fccdd2ca3dafc32bfbc0a19c857fa8be7e52e25064d69c3b7dde6e77eee96ec77011fee440c8bca99a45b432b5468715a0aeff9d61375393b3ca40b9140e1a2bc2a52c3c8a85292f4c9e87d1e0c12fbe4d7236ba7921b8b83bd10ad554179dcebf0791c4b593c8a1bae836883d5094499cf2ba41b00c8c36c77a83466c263a0b01e773f08ec66d46e97caf0f9785943f98e159e353f0d91d5ab526279477a5509129f7a1b8b07ba82a1ccb4acd5be5e40de088f2600e06a8bcf35f54663279f04c74838294048a8f8692904d4f9eaab49635068df74d1f5ed238f6b895acf1364544747bb10ce333a957599594d766ac5d1a3ceecf8a6696cdaa95f824ace18cc551e1f4ec12f345283b366314515849feb5bf81fd203a6c73b5bab7c01b5c1131d442dadcb6bce32d6e13c5a3e77b66eb8f5b2912c0938d89ed9e20a455066d151a973e4509b03f5d66ff7ffb8b362e0c09b969e21173693d9977ba06d48bd3b85657119f9dc3533c91965ed81d1eba72b46cfcff285131f84306fec7b271a02dd22982cb6399a9060d286aa18a3f97666810937f8a5667c94959a4c27299d55e94564dba27ea3d98cb3a9db6197c842eafb237649de3fab72a9d56098b5c1228e70dc062617a8a6b44d46b7899dc1e53a77b700925ed1b438c59458c15e9b91fa2c2164b9661a976720eee2864efc5363d90beea9789a6d3b0628bf4695a853251c7f70ba1ebcea06cb35cb47d72d2340bb9412edc49626d6c78be644c4ab1c539d1469d1cc63f092ccac45f66917d89274af9c84d7f1108b1bd738408e499efa63f1a87c8730400ec19f9a59d241032e9ab78670e85e8da24310b13e89ad521ad4fae3deb9d438dd7eac72b79496c7b65061314ae", ++ "slh-dsa-sha2-128s" : "0xb8f14bb6630512c51d227c12a04ce7b316bfc0d255f5a5d1dec3e1ce5f5cc92927070079430990b4364200dc6d389fde89c78649e21d8fd3a17dd2de7444e77ac3e8c70eda15f2247300fd8e37e1e3c2afcc3e8dd674823106b4297ecedc924ca948a9f80afd7ca1bb85dc0e60e1ccd5d97eb21062b2fabfe94827b4ce5f0e396e5a891fbfc61bb827cd305012515d0a182f163c1a5ee3827aff289ec526cdafd2874c457947e8a6c8332ee7172197cde7388303992be248892e727b559c0d74a2c65d46b6686a48f0b814bbf031d1bde17f55b888e7cbaa7fd6dcf428b13ca43f77d80c3804bd2840e5768c2aa17f6dc773b71f83eb7803fd9e1f1a2e3e158f7e823e9667cebe136d333316fc670442a8c662930a00f72dd2dbda9b19c3dcfdd09c60ba55d9ffb5d5b3384d719d153566bc0b6da89d8dd869fb8c4113258014cd48a67a3591d37f9ba767ad70a554ec98bb59275ce163364915051411db73833a88cab0d3fdb7c491b8580baca2bc44a7bcfc3a51c28ae0a1fc12bb53b2b948c571397a348e664522ea749890d1c7ea7e9561596a3e930bca68377e4d4c0e0301472c8017c1fd5702cd6dd4c3f5881ec4cafb98967a57837c3869720268b61f37836d0c9c5ddac850a835318b17758a6f97df4d4966d516ef100b7e61271c45aeb89242ac7d2b8ee45a08f4081727d54cc08ec0f8af9e16bdf6f6d6797b9f5fcff9686f15efc4e8e34b363d562dba239908a3992b3548566a30cf04c424383b5bea0a5011ac620ee384f6363fca87daa30fa88763146bcfe0a160c071d79dd8de0b11e034fddc032e522b7ee47f318cc6f3f2b6c9b6efa0aaa9b9a9c1243750ea31ac01f087d5f4f5fb97b8296b0953a606c49025f5bedba6773804b15fb3638e72ffffe38ac20486e18eb21059f419b0af9071be12e309a953ac82c0a5a620a7b5c850027b39cdeb5d728522a15c1557e4ebc3f4f09914b3a99e291a814504ff7171c23eb825d2df1bad1ff29144f8a3babcc882258e8a6060272e95c4393fed0ad86698554515e77340ae806746ed859ff9730cd718c767e320ef54fae5e0cb8ba331bdb920229d6047a6db8bad147b75d376c3e72e06fbc6a542f51a312ec831c704099b2eb0f801b68631b464ef484eee077cb7fd9ea951a0307e08dc5fb4ed5a6e62048b010ede39efc5462ccedef2a4c61ffdff63fb3aae19b28ca48593532f051c716835a61f2fbbd5c25883f4a85b48d81658b6d7cc4227f90a81e961c5fd8a388c9efb78da1c9bc50d53a41d2d336232e84e3eb3444389caa3457ef9e3560c25033ed45242d0b4bed69fda4a4f1695830c843e63147b6c2d3f9bc2608b0671e59d827dc1e3876e5fc6075bcdf95223f73dfd11d64399333f7bebdda7f5c2838c072f7baf753a36a1ae8987773fd0ae5acec41d7666c84c1125190f432a4d82ad9b78e22d6536a8135d80a3d1715d17a673033d37104857278a75c2cbcbfe0159343dad8e98e42874e2b001bdb469c9faf79759c4cb3e3f2ccaa16bb29d3e4dc81627441d07469dfb9f545ed83d9c20ce586370be092f3a90b18f30866336c6db9d53e2e0fe1f98c655f1961997e41c25089a518f05270ce06cc115b6c2e9c04f6ba9bf7ce3abfedfada8580ef89f2fea98e8a19c58a0f3ffb89dadb05dbdf05c44b79ad5e1d259d5aa6086cb295341dc40ff800b460a5ac602a687d6feaf66393dd2be22264498509c9d39033aaa22eb248780a3661ecf0a05cb6629ea3d91eb0f68465485e8fa3fad3fc4315a118e4eb2ebc6e9b07284697cacf0257edf67c20b7b0311d3094f4647da567385a508addc9b25a66db1f1544dbced87886946989682b2f2db1363dc635e4cc3c67ad83bd311437d22d8f60a2cb7833c952bab293c9e20ec2b44e1f1f42a797421eecb2e9e9f5e47105b9e7f5d7bd796c360ea39dab45ad701eef0a76b7773c55e7af7909d456c213b0db14f985d0f73652bdf39a6402cee104a168749466e477d8a399469992d65656b607fffbdf73ca1bf4976d3a0c0c64cf5d260d6d3e0198f0b86c451b9ff5840968a2b60a8ec286c81fb55741d7bc9714177c9a77219d3a39dc1d6d7adecb7f8f85af366ed653cd81408b509d0f56b5dccdcd1d982d115754364ca3f14a6f100c54ed8ebfce6b0dc3de4435507acb0c4d974ae3f2453867a70d5ba078a17db34844ea410af4f842dd4a9879a7706b18ddbf94c7b43ba137f7f9b8b3924b4d917f8e0262ad10d083c4dd3b99b70560377ad31784a587cf0ea1f99d6faf0f04a909179f3f93c96aaeae014ea1e74d9d7ccd0eb5ab466a6caf8ed0fae75cba902ae05244e0dde35b8c0bdbb3354ac60875c454ab11f49e47e2d180db319a113a5869bad3ef4580bc7402b0d6bac10a7a4e81403634fd1cd272076074e714b14a6efefc902126df6091330ae387e161789198680b0258c341b6f3ec0b09c7674e9ae8f88699fb7b2f88fdf2461e11ad483ee11fe4e3ddd48ede0ef0a1e54a318ae12473993a8456dbbe8b5ded40232b8d2474a90424281830da7bb36091ebcf591947b04739846d8a600946c2b892e2bf3353b09b08e3a141f33f6ef83d022666d380da43991d3eae4e62dd3f9432678e8be1cd4b9569fa2fa84e95195449716423688aa920e2ba1cd41cd5538907ebdf3ff15df27900ba7ee09f3e9194e1d8cdc0703d6f38b2b887a89b10787986013f688f9a355c6a362f4797576ba022e4f1d1d74e2e31dd98f1b617b99516c944bfa5bb474857fe74a09976cc29c71a7f5b6fa529f3e0c00c33c2f0700064fd507461535a35c0dbc5b69d413fd6ae9af49ccc5d02d7abac88ef02bbd40475595176fa3b68d602469a89afc03359b032fc1f0ae255d623fbf9525bfa36ef98467d5eb2f80cf7c72a04b557e40995471c7adb8701409830b232693bf2fe905ef8b1a32c4b8fe3300bfc5654acfcde685547d5c1b0c213294235b31417da91464619822f3535c93549ab4649a59dc3620e7f4a3327c0e421c5d1a28a2b4c3ba8ab02950631ed54690cee35bc4147aaa8477cae505a1d1757d85251bda5fc91cf65772e1b543bccee1a2cd0c26cd33015533a0e72c815be8634efbb50ceb0ec3c8a3bc6c84638ae371809ab87eec54b934343ee9ed1bebca488d9399a1e347b1647d108652243cf2531a4685c282e0b9e526688a3ae1d10060a78467e6804b705c143d073af664cb72ce657a7d210240011d539cb3144e9411758a211238a872eb4be615d4813b64b8df446d2741db7c9f0af2cc4dc83c0febc41adb5d8413b7ce54ed564e899c0a5a4abcd1cb44c84505915afaaf93751b11bc8e96610216f71cac8d3c9ddb7282f0f864400bdee42c3e5645aea1aa5649485435ffec9e43d43e4341d967c9a89eaaea9cca12e2089f3de222e1a5034baa32372582023b5564909fbb67acfd2a40d5ba40de2d7a31cddac717f5702648c0346e197f99598dc83edda7ad335f9e711a0835c75d4c32e3305e4db9dfafe171181551a8dd5bff89f8a9fb819eca7a171d1be47fbea0e2838a1f1d01f4e68c3d0045da0ed7d3689c17319ef5f5d178e6cf1628402c40d2095c91f7bfe6b837d8f86c5b2585653beb650fc29096f13617ce6d36fd6107ac83c7d7f5a8639e519b161581dd58018ace297bddc3421d358be70179b14bdff66f229a50a329bc30b054a95d0f43e7914a9137055f4dda000357fdb5e2afa3d61b9816c03697168cc022f0418ee5ad7aa71617103fe17e7f47ecf7ef9bf779f157eea74c3caf3821791ab628fe8cba64c12d3226877c48b746d725c46b0ccf5a18f869e6680f1e5ef3c5e7fc2a18915dfd8bc12676ab94ff4401ed22133ac1e1ba0c0352a30156bd80b63eed4a7fe9c948921e1a9843127f1191751312180b75f06e33694853a05a24ee30cae0b02a0be49db16f6f06630ced9b5e57cad548dcff70b1620ffb17e8bf8c247a962d6b2a6fbd4fb3c89e3aa4381e15b92f7245ea700e76ba99678f4b0c998ac90bf3e4b9ba5b52140e15e4b5a38e25462c1b61953cc2068d0b9ebe014db6b8fbdb2fc05751667659f40ba1cafcc2055c364116a058e286f084c2bb73096d46f6736de541b750ad437c27a92ea51baf3478837e99faee73f2a2745918f81547c45f2b7083befc6387a73366c175d2be22314a1fa73f11571395c7fe9df062740c58b56b4982240c63b8a0d5886a3ddbf6ffcbd705d3bf3713a0e1b74497b8c1f34e204ad81b63f27cfa5215d275597599f60d02bbf6cbb229088b56c96d73d09fb3c36fb3f05f4266221984fe8559619da67bb7314ca66405cef4bd3086940c4a7346243776a6fa128cd9b6181d8f584f482c502fce3339f87e4fc5e3593b7a0a64c19fe76c51a29ef776e478ecdd5e093b2aad0ab3cff0baf73f4e09d63e9ccfd4aeaaff147ddf2e9f1e3e6cb3bc9757c57072a1a8076e179e50b0a03dc94de86fbb99f0e92338f26b6ed7c863830f325d3606189b80c8df5a763f422f26436f753168b53bce965c562c2554081cb4eb42d48daf8573206f818ae66d62bafd151e9784d6a9304996b4b82cef081af9b106b42ca4b6b0b2401dc21d8875f9801591234dec266f1f218959af60351178049b487b2784183349e0a7ab361f575fd0237d9f483590a23401f9085b111ac3d740ff4c3eae0b7dca3d149243e3b1fbabdc7431a579652d522bef7023e1c6579d2f6852f1acb9b7f20e3956af8dfbf14617f14981f40b1b2430920be14284dd5f2771f73091adaf9179b8396c6ad2a3579befa1e323177fa2598a3ef80ff5785dc2677f87e9299c6bb16ef2b2080e91f6fcf1b9189e256985e631a05cbfb6427eac995e683f494751f7ae888bb0dfd23aad7fbe942b8100d4daf62b6b8e4d647c818ee7edf0d4d64293edc3b7b6e08a8b9b71a7c38f55ca76593d35770185637fb473da423069de005363ec25235ce816f4df3070ff567f919f47dc4fcf57c168032ef8d7e3fdc5a6a1dace2513fc24f0829e8e4b964d37333febb1eeaa7b81aafe30d16fe64b6ac037ddec2dd9b372c657120df4372504cd14be89d3719c5aa6d545030423fc50e277eaa401e8bb02d70b6614e9768a7e42ba9b35af8f9e3f7dcf175609f7b91a16fdcd65a151c0e85d92dc8a06cddd1ff77d150ccb62c612c90abdad156ced839e837c79b79f456156a28c45f3287cb86a9ca664a13313332a1ed9ef4b3a3df864eda7bd55a6d8705567bd8d1d732f65a324aa6c77f6dd82517d5274343a4e16fc8f41f5a3809e9f2cdec445b88309c9d1de684032a10f8944157a3dc3d4d8d59721f4f9cc0b0e1e7a97b7b066523f7498e0902ac5aa462d9bd096e13c14407bef96b59297391032a4aef8c543cc8b60217ddd5a5d815c4ea1e21625b52e2323b42b4851b0bbc461abad9b71805e8b1b2a16c811be69140d3a6d32d7aa9d5321adb57570fc2e62618cac60a4cce2b011a4c8ddd4dd521b6864c7c4562d8270dbbceec91bf1cd7be926d6b66bf370839bbb22856d1f0c7b2b7119ecea6278793186c50b045d09a1aae7c5bd2ec54df1087cbd1d8094293392605321bd39ffdbbe510f0e8760bd35074c4b0453604ca1f5bee056175ae7943183212ad527e125d2ae113d83c5a4ca1e63e8d89ba07ce8fac8257fe1c603031a1fe2e41bf922d7ffa0a610e0b91eb8c3147262fd228a4ab54fb520b49c91ca268d3954029be8677229af3ed232628e7d3a752e66c2171d1746b7e31d2dc8d1781af454822f36b3ff40f7683fcddc5aec46b13890a6c7c9531f30eeca923f198f4b57112a94e34673c88c70bcf80ee115de27ef5268a753c6f827e71254b5bea2a4f27c8e0e2d0c3f72d051558700196e80abbdf452bd70116c24f635d1850f9466282ae761f1a38a8a0fb5a02a9e1b99df55616f0a7c031fc34f190dfe5cdd4f2442d16ccb49187823fa90f3f87dc0966c4cebbb7472d8184e37522acb165f5d3b508f6a62623def48edddeff361d5ff37fdfddb2b324c4f545bfd5cb98d258edee6ee6170bd41135ddf4c9e358433330a5b590b25fbb276a2284b2df18550270b32b65d9b483fc42e9610537f27715e9f451bccb73e1ce017aaa39b65db4e86c86a50d0379398e57e0c34fa64f73acc0d2b4e953a89ca2f8c01b10135c2af5c234dfaa17ef97941aacb7cce96cd05fb246b76f15275e4d2a8545e52726a48f269d1a558aa12588cc78919a5edf6c0e9e576ed58c92b67d00e4197905d74dbdb3700fbde85d26de20cc652581608ce1d1084b507842a0373fd8830c8d3f68dabe93fb19e3189e486840715f92ae4d916a9ff3424b45ded24780b31fb7f76d506339d9f9a545fe0547c675bde44a3b490bd3b52e3b30842624ab5e8986161be4ef9da785bf537954d3c716da5597a859ef7adb40fd8030611d3ac6581e424ff636aff72f4dcd9f315744a3dae6cd386b2f9945140071a5a49f05e8f979115678eea7d6d884a92e4f14ff94dc102355c3aaa93e02723a92417ff49fe8cdbefee7e6c5e952ad240fa7eab4c7941f6ae8d2a1086e1f2ca73eb8ca5fbe3588ae51bdaf18646ed04bd185a19bdad69394ac15d130297c0fce9d8fce8ea2729dde117facb274f9865ffb4f2c7248102dbd96767483cb7fb764fe667d484a3143db514f08577cad8bcf695b0d953e2a3c8710d8979952929d59c8b8ae62ff678815130e68c85d4714e832733da40b933b7133725a40a12534753eb4877c65fe4c75542f28d6f9e805789995adaaff6fce3929e6027338281c6d0c33aac092fe0eb1797dcd953fc1f815df794249dad7b28407c50371a8c81625f6e7e08ed59a98758a9859c41f7436f937885ad35102b0eea85f3dc4bb9a6260f4e091ed983b1009275d43e4960f9422dddeddd09e9990d545cb67dc3f1061238dffec3ce01376259262b4c32c6173a6f1e239f4502cfb0900bbb7e3b4883ca3c64c8ba91cfd80b2bec6aea25b01124ae11a56ab3e4d448038795ff62e9d5ea5cfdb99c5901a8b8f8731c772690dd964cda343bfd020e920b32910a68b433ddd01d117a833242fd695a54f33fce28b506d931adba499373b0a6182e54323f032f1e7b8bad58dabcffdd1cae831c70e87b2c6fee3494dedaacccfdc93fa23ee1a4273f16adbbbcc21f5d02d8645951b93287732cbca4c61a0d0549345160537501b8c0dfc97128035875e73db7eebec24813d03d11cbcc089929b0f6e2440a26d90cffb6295e8fccf65b4d676abb8ff66709913775e611bc843302a475488c9a9310c0c8885b78d5db5cbb1a919683cfd9bd010cf2f1206ab327122ac87d8e2899cc1ac684e72c91f2d36c7bcc3491b768aac86e92aeb106d22b3e85112a2a871bb8c9d0a0dd15c89d113910f8babf15f27a13b10200ec7078d362773f17286228b0d5a58d6654b0fb4f60c81ee581e507f17a044e6bcad4bb6ddc66bdde7d311810d79ac031086d7b0c334cd3a8a496591aeda23b2c0097cefdb6894b352395dfc79b74a6e4d086656b0cd9c95a48640cc8b3d188189ec0b98c8618b0def4b0175f11369cb2f107e89c4a67a75396cfcbe899334a5d5df5927fef2eb8bd836a27a2834a7ab94813d30fa8431da3178da4ae56caaeeee66cf545537ea260ea6af56d4ba048076ace08ff2a446080a6b688a916a13b43b933e506ad187b1f829a1d54ae261651563874cae19c490004205765b43c3cca4cd8a309fb1bfd7520bcc07794cf7c03d9b1d1ae0cf646534f5a97106925ee96dcb7fc1f74e62c01d382fde19fe027a4b9b7627c08e690abe3ab076f184210acbb4229d483f7471ad551eb614c35e019a8a894b5f92f5371fd6c457f135ae8377c5781a8f3a6dadd2c00697bd8399b6f168dd64b2d2d66d5aebae90fa5f904af9f950f450d8be919ae3f02cb5c0be9687560cfab2d2161db61e978ef46304de248383dc3a99e30573bb66f873ef1e54f523ff8ff79e8c05e7f8143cebd1bdd9d2186ebdbd3b66a0a3dee79475cda2890720ac5bc33f8cd3e817d82bd7c52c34d491e1e9d1d307eec17c0c7679af3626e7b96bbe6ba2550f44de7d1d88b3e4c220b8f185b459f1f882a97248cdfc3d42209ff44806837750b3dd21ac5891254f6c7f6938aef3caca6c55b633770772c2c06734f84612a59aa8cfd4f347267e631658cfc4ff89cea84550bd43699c1d8840655f39e3449ea0d2abba1d81196413302719bc9b39cea85cb7db6ab7f00683842cc480503004c1c819ab80e121d9d21f46f362614a5f2cf80cb2c8d3fda82447cd0155fd7e0ec7589a6df2e6614671071f0f956143c762d51172da46e9f61e588fbf74cb3ceb74bf2ce4ec4ae26a28245f98ae91f09cae77c4660d6dabe7cad33ac506db3000d742f683e08bbd0a7cb9eec72a1a976546ec926b9faba5084e00d66475a514a73f01fbe1e79c0ee0066f4b724e4977f3c1518d28ddc918c573693e9b3fb69b426df0640c5ee42cd5533655f9a82c6843516298d05cd970f34dafa886995545c37b3b939e0dfa3647fb3f330bbd3e69307be3d469a99c24382acdcac76c6cb71decb4b7b11cb5f2e63d112767a7d6467c51f1c0c27900803180337f463e64f507ce245f606f8c1f1df836c7fd02502bd3127424804c69f1d066ec3acd9c4374e857c4607b711f532867cef2c1c8a7d7051a440eb7a8507500d86f11567e2fc812a27e63e5599059af1ee90444497f69add7862b93ea050f100e48df7a578d55b6d6321e70ef7a7625ed89054ab010850912088fdc21551b89397c35ab582aed6c215e00d398a857090e2f7cac21c7b51f34054a45f36157edc603b5d6e76ce20f2dfd2c20158943efd2349560666ca38505cc6af776e0720af2d5f6a7d98f385854700fc0c749dafb597e94d7ac54aedf34840ea778e8873d6f1fd7f53de7c06327d08d34a03b38315efd8eb52683ec1f9abbe2bcf096fa4f379f41e09b8bc67ae4685e68ce456465b38892a238b18358714fee41da0aac8dd729e2c3f17488470648df81040272b2e927e896a4eaf6a11c457938421288ff074da8db60d37c6d022e86952341f2b8d262cba0c5a6efb51925517a8c817a152499ae7ee56d36df86253e6b2d93079c89fc922014b03da3941509e979ff8dede44165ca4cb698924fd12bcb02a35deaad608ff3358d455a49e12e944dbb11ac7e9571476bfa856f3bcf90ca9bac6d57d5c1755104b348d2924ba9b14e9ffb750cafb6edeca6dfb79d73b9839092032035ea700d81f19d035e38bdde754a5098dae1c163f9c473b0681858004ab9d9c2c57282ebd7e57c474b8f7aa091d1048b95e7ef887767f49d2a7f6b410922da142ab8605e735ff6ea9e3f36a29380ec43dd009d98d8c20f4052d81fedfee6cb018b2da59d63b5fc153d5b0948d613415a6b8a2b7338897188582d2930480d897d55bec899723b285dec9abf819ac7e6f39d8c35c484ca13f129fa4b334979bac7715bbf5e52a9926568f359dd3e3e000958b561527bbd52025918ef75228c423da41861396be4f829aa4bb6f94f65e662e6ac91e828d721b741d7333a8e3050f136a463af537ee97af4b42456d65e1e2324f72267c07acb88c91d0cd602ef765f858f69fcd44ddc73dc7c5f8825f3fe04affee769f3ab5486232e35df8fdb75db79721906907ffad83c57a364ab85d93bc03ace8998ede749d88985ae41cef163a3d00f568d43115992362c581745f723a2955ed925cfc7c83c5b5188812fa2dc016dc21844f923b2362afa5ac5f2a6c9355b2eaf724606333f152a01c330ed88f7028e716043330a280c5ee458f2032c8163f5548428ce4c529d487a16ca0e58cbf41dc4dc802cc5ea7fad6a50de0c0f2c2be49c3dd2806911ab1322a30acd4fd8937b8930069fc1a6de86f9ef90f407b2563594adad581b49ad1d19b30ad13efb0ddd8e6f26dc43a36ff8d14d1c99b073f5f1ce8923d3100bb04488b86cd4e89f7b9f5b9cbbb3f86ee03b498ae255e09eeaaba3e4e4d68f1ee4d50f699e460a922e17ea8f0ceef9794e944f128efe835f281a7662f959054aa994afa3982f7a310f46f53d5ffc07884aa91bbdcb3f3779ebdd7f90801e96222f56df39ed9c2bff5d4a11be1da7482835e494b0856ea7c695cc1b53acf3b2e2d1846fff50bf55be65e16548c4fc436f20c50c119ca8eba4cdeda8c7e4d33734a0355586629ca5a7c3591ea4b15428a81b6d91529485004cbbf60e75208579ac354dc705edc7bccb32f23030e733d3f549fbb841329a01f5c5d263ce635a57aa9c69432e5213b155a07c34fe19cee737cb993fdc82ff38eafbeb734f04f58d367e34df15dd6044591983b9b45d4ffd87e2a6b478c7d1e86b4b974991b930370d5eaf5edbb53c3dcda643fb992b5fb0725a8aaf8a9e7c4012311f197179cf1293884e2356fc5b624cd46358d3c7bed1fed6b0305114cd11675aa49c1b9e6569817d34fd60c1105833d78dd00117284cd1722074a60655dfc428072b0d2eb881b93d6c367952a4bd59eb902032cfbf9189bf65f7bff592032c77d61dbf778986b491e297ad0da5b367c8a10c9071b8d509b246393fe04a290b3e2291f04eb750285674ae3e9c7b76a01b679787a4006836dcee956185d3b0ce16c4567fab862d3634b93079305008e2f99ed425489bcf5447699b7a7212fe2196d3999b39191e750fda742c6ffb5509e3806f38edccacbb8bc73c96cd46f0f400c4012f1205813d69a48bbd1f55724c7de917ab56d4188716b96653ebe4fd1b6d5d252f5599f9c53a4683ae60c8c31b86982f32bf73401a328891804daab93a155140fdd41ec87e392c8397c9ecbc48f26acee4e3cc279cfd67d75b5e0b6484274484c18f72c2532b4064cdcc309df796c802c17480428c3b5a5467b38aabce03de2a266c8a22d3b0158beb913d50615a1002fcbaf91edc529b0cd38f35138bd71dcfef1b6b90adb4e68a594de40199724c158db9c85ca78ce3a19378ee90dac98b23e1515324fe18472a4ca93b004295b7abd3c146109da707f5ef37886fe1a8966ff1e96375fd64536eece72ae3433a697492955cb182331ce72e8f1804efee93b1929338f" ++ }, ++ "ecdsa" : { ++ "addr" : "0x5e13d369c8adbd8079272b624343ee1edfa4a560", ++ "claim" : "0x197e55da82eb1daa23a5478ed230c6d0452d3c1920df15e10a8d37a7430a7f2b69eb474bfe0c44a6e4a55db9d5a0e0b74549c044ae22778ce30f47a9fd1eba4100" ++ } ++ } ++ } ++} +diff --git a/consensus/common/src/test/resources/aere/registry-v3/n03-extra-field.json b/consensus/common/src/test/resources/aere/registry-v3/n03-extra-field.json +new file mode 100644 +index 0000000000..ef96f09515 +--- /dev/null ++++ b/consensus/common/src/test/resources/aere/registry-v3/n03-extra-field.json +@@ -0,0 +1,63 @@ ++{ ++ "description" : "a row \"3\" beyond count 3", ++ "chainId" : 28001, ++ "requiredSchemes" : [ "falcon-512", "slh-dsa-sha2-128s" ], ++ "ecdsaRequired" : true, ++ "previous" : null, ++ "expect" : "AERE-PQC-REG3-03", ++ "manifest" : { ++ "formatVersion" : 3, ++ "chainId" : 28001, ++ "bindHeight" : 1000, ++ "count" : 3, ++ "0" : { ++ "id" : "0xaaddb4dde09de5718a906d83be7db3d58e0ae32a", ++ "keys" : { ++ "falcon-512" : "0x09501c96d2f5cf0b28fa00c726e5359c5d36a1fa069971f854b7d914fb2f1295e68b2c6fa91d82f7d287f55ad493c87320bf7ca2a5d5e79d7212e8a540c166b588dc03f73b83be060525b367d9f40f5e77e7798c60b6499767586770722820b3b9e6013cad3eab5fe5de96089a29f34919a2e9ebcb3fa03a3e714593b7a3356d11ffb3441ab40ad94474da662a71aa2419dcd50668cd5d8a9017662cb60998b34ab5b7929c58a94d5e133ebbdadb2b0279543067f76bcc4cb6d7e0a5edb7625467e3ddc92a01206e1b8dce69be31928687d8af4d26633a07e73c2830d5299b878977691cf65700b65b6ea2463e51b6136888c544545e59fe8cf190a7944e215a785b682623c95a79eda28e25e0e1b91b49ac89deaec3b14a3c431d9046a663170111ee541d81b43aa91f29dc147c6fc97739b3a63fad1ca84843d0a65b8d9396f28e9b11f9a41453ab18a2309ae8db03253a09fac8f0cd634c76a5e938a44719660944a95dff056cee43ea99592c3899c2880d7181ee3dd5c04baeb60e1369a69430a66031e3cb10e392622f5246a71761760cf417dcb40ad65f60704fb74ad26f26c3af7513a42f806895e0298c25c049187aa536e0eba21998912e621846c2ca0e323744ba930a29850fdb385c8241382296ba28dd4df05ddb1e61fe525949034b59929a784406de240f8086b4074825f419d5472a28a0b157500be37e9f64897db2b645d3807c48dc143266c99e7cc1638ae278772493a2a4ecf74e526a514bc9119d7129c5a0d115a450ccf4dce05b76d4b6149fdab028006df7ec2209923117abf7578a082128cad42aa66b69eb63acee4456bebeb537ca57bb3d3487f95e4f06c5cb29f292d3b6284e5a162cb83151cd9ae56aebbfda150b7edd5065302ccab70892733a1e096ba0da5f51b42764ad23060eb197d5460425fd9c7a26e7dc3cfd40eac3643539feea72c9ed41569111a7976d2c345ac2183fa2271b424526709fd9aae558a23a5cca29f4e2f31629746a71d904612e95ad9977bbe74fa32e90fac62625838cac49f50e5aed4e8879e2ce2e5651c4f4ba0c96583af9e1612b5ff1a6fac5027c0a308815e592308170b915b4a2de1e8d48e9a5730680ea9db8f3326c430241153b3b218d5347d5c843570cf80ee813871ae10f6b8ce4ab7e4c5197045e85b1cb4977f44c33eb85894b6555b4bd288a50c1b656936841048983c00a01631f10a84522cd613fed0d4beaa4aa4b3e9f30c324108d909e59a80150", ++ "slh-dsa-sha2-128s" : "0x47a0b70170dda85f843607f6c6fcbe6e6acc7c22980c108996a3fe72dc9f61a6" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39c8813cd3b34be58eaab900555a67486034b1923e0b00e435661230cab85f07690a5958a5f5e9c84f033a3dc2039a5296443093fb7fe8d41895fa73be3fb34cefc6cc36750d534e6a3c47307294694729d6cdedb633e8efe8979a9aee486eaa66136e342c578761241192610185feb2d3c196bea0e79222437b6a8e08cb09778d053b29552df96507b1cdaede8e9aa7abc18902f29937f30e7cee6868f349f7ae33738237dcaf86b8e8e01238f3d8ea6fd4090a8161db65dabeb5ded5499e8cc8a5b32607abc291b36a4b34b327d30cdef18c1825232e69a2b09d539ed84dd2a4756efa64f864c563943b3db825824f294c1bbfa2157347b0fb0e7f8a56ec253b39ca9b6cb1ef7d3d7c93a6cb220a7dc50c365905ea5a71575c3aeab25b33523e4fefbaf66137f45c3d96db719a12d2e2d42fbd6cdda58c5a1b958b28c2a8f2cca297871a147dda92a7f008a359027a9288e42ebcd6ea9542f10b66dbbce6e7bb914206122f866d9adc1c89cbf8bbad9bc9517c2ea9018b61d4d2df9abff1dd9f3a0a6faa72a449af9c97e8c4090f3bbd9824298e61599c13c7eb89677c0e845ca2907c728d9296c24e96b6a348dbea7cac62671c9a78a531463614ce321e28ca2f093094ba5f69881e6cd766874622ca769ea556ae757cb7f9546d99f5c90c25e7b8e14f3b7f270861398800b0604ec2a3374659277a23cf6131c63148a41b05b3c06e2a98a268f1b9f0df7969addef17179ca2261d3c229ae3db0c490834564c45f7b8ff6d3bf70784779d75915fb2e2d5bc147bc941b9e249af188f63f39b028547cf080b7674b228e20a600e3b167610f814daf105226f3c1ce5e07834fd33dfe46315546e926fd5be83fd4d47ccd5bb8ae736ac745daabb59c87b9edf9a45c9a1d1617ee84e588f27d12235c59ffd9", ++ "slh-dsa-sha2-128s" : "0x0e8f9bdc22cad3613ed07fba30ed04219b9528f9b657119e2f0886dc71cda4afa7d462fe8bb108feb58d998b370b2f7e162390713d1a17eb7de781a604041cbed13d00effd3b24f2ff87cac74f61e7b7f7aa6a259dc283485179ab4bb966793be018c4bbf4475bf7a69e600a37246908f662813813d4b0f4f83757f4064c5c0713870a0b98b5bb99025dace06100497fda8c73d7385d123afd4953961066e7c8544de3fb620ef5e23174327c2b64089b3fe6df3eb86e83b12634a0c9cc0d7844c894ba6d83afed6becb6f5abcfff397c5cea8064e5e153ea4253abe599dec1614b449329ebb25861b69a9b22228d1a03ba51532ea64ebe7603474a15a2806d3dafa29d57d27c5fa894da673b85b4674ce835fcfbd391d328ef83504101432bbb0c83d7be462b265911aad862118af6f4cea4df0f1dd38969c69428fe438d59d22736fbc7dd5faf6758905b26ec4c99d71e4b8fcc562a694ead91569c9a916df5ad693cb2ad0b7ae4c4f3c5b7322f56612c5449e0339dbd367460c76ab89b6f44942cd33f35eaf33c2ddc0c6af793556d5202fd1fb0f9fa1b7ed45c6ca68d904e476477b71a0bc6ebe248c9b4585da0c7bb186600691269bb4c836667a6d73a455b97127d898b7fae17e1acc6dcc3bac3ecb14da131d5f8adaa64b054e2f569d9bdb164792038e107848882de9bbeff295905c2af68d4c6dcc8cf718c2de872ab6b3d18e00d527166f8ced642281302e2acf4cf4489072a2dc3d55ff8716619cde494be1763dce925438b33ff1b91b35eb511645832720ed92552d4880ae53ff6516cfaeb1d48c923648e502e4038676f7c82e532ea713c6b9348c80ce3c5735f437491d3a8b1765294868c14123af2e9ff61e394216e630c71ff976072d2a1c50cfd8ee1ce27aba5bcf9aaed4a51521bad5e5d5e66abc7a95b215fc8004364aa4df2b8b97b14e3950f521b6327a55fdff9139fb0bd35237b022e3aa128d36c8a60f4621d25d28c59a97418c7dbfc15d900ba626d283632732631ec4a948f66dd9db3bee8c2cf60dfdacbb5ad4c0b2b31f8428868cca035e79c95bcacaba40a9351b2b44cb29753b6b9da0a751bd5af84c9094d5fe91e97501d4f075392290e8516ed5e41b41b00e09793353707fe5c1d942395074637f3ee0a0f105876d6f28a74f9558c5f360e98f047a99af35ccedef8d5cd299365e81e7e91f28a01eb265219e21aa7f7ce56b62f9d2a61560f9fa39f2765f5b50920658100a638aad03482a687905cd27dca02f1deffd1bc49a1be1ea7ff1a505da74fd932937d8f6a8bd75ef456d5f7b71ca5357bc66db6cf14368c4faddf4996363251e6a6113ec64d642c319dd85830d8b4c7ee1437ebfefe01f27709ba0c412c266530f5b6bbb005994774e8935f1d91069f9e7a8cd2bb7ad6527768473affe24709c10294eb588aafca85b379bedf0b142b109e1b186e635b0625c4e59576266acb5f71040c44035fc9480b13932bc657cf332b12da1cd7d5c3977f51d5fa742974cd256e8e3662dc698e0516d615d0a05ea9caf12338d0dcb6151e07f184c9cbd5e59bc40b12ed6372e2d6bd42aa0eb6c3c888f264a8c0d3332631d4919c921cdada6bffbd01ca5445de0779f9723577ebd7e33ab0e5f577843aaa6cb8cb5f0508c33b63913a44d02b76bbb1eabae325581738fbddb5d4fdef8dcb8597bd29c6ecc631839118c44f66ef8dedeca65e58941c30e0423c40bf064b8d19d28dab3787238781d492720236a7ae0695ccc867fbb1cf207ebecc64f84daea66b6745515b9ac9b725061bb9958ed79ad6161318a262528004401633d47a023c645683e36413b8653fa4864fe98c501197c10226b1732337842a1322bb788a00a0de86758139c2d9ea3c5b26bf5d7a4a92cab4cb686c580e3e6cca488136f0da9279073b3dbef9519168ba02588fa29cc60d02273805b425b919a7e2e89c9086609982163e09d5f6eb9c66267ac7be363aadd4617d398d4bdeca37a838d650b0919faf13b78642a058b1bb96b2ed1482cef9bc6e8b2e061e6815936e15a9c754353aaa786ab141e95e5f6c464a41b8bf29e28e764abd638abcfb342b54d08c15ba7e24e6fcb69b844e16cdb5cf4f50db60ff0699f969d8e68511fcc9e16a58e100f80671af6b04ff3edda3a4f05f9183c0c3bb7c1061fee2d3f04e33fe75f1354e6de54f582da914da0138e8565ff45ef52f638cbc33a24bae863fe91e58d7c5da34273438f15e10d4f59db16e505620d97d3fa4862a4097a659925d0e5f4e073103ed29a600b051b83b1f3a21381f4b871c18d262d7e43842c34ed80661438c064aa2fd858a8f3bcb035b5e942baace7b50e4de5a73d5c51fc0843cdc163958a62d333078f4c7d883bd7055a602e04c853f9215c9d7f798403c007fcee124cf6099322629c449ad4ef84b7356110798dd87aa4d98ebb47abc6cc8748dd381d588b77db7f4e7550f6ee1ef4360dac6d6c7037a65297d4a0ea7999a5632b90ad48fba0a916846a216941fbd13d62ab36e1066e24990c19592944078435c52d7717b3556595b645cd2359ad151dbb67e92b14168cac12fb2cc5422582a50bf6e99f116751171c9b78744ef719282f1b84bf95b4092514f4c68fb82a1526e0942ca50e186632cd9b0b8b8d91e84f85e35f30f815601798fcae676da6a2d38eab62f22445099694804a36a34142150fb795afb445e78c241f0b645209037a8871cb5487c975975ac997a540b709e3df6bf208d9d8017f9688b152c9ee2b934f65393de8403244b7437108e6d8c973aa723285555d9eb92509b1747977105cbac7fc33e658fd51cd374d21fc2bf229928948292c1698db7934d0f9be44b137514d0a5fbb659bba83861931e03698a61cd20a449d0358a5fce7f288e18bb3eb62b7ba0ae75feeec634fc90fc45ce45239c5e3179309f0c202cfc53d9f42a617f7aaae586e7161a0723ccebb7e8586cd40e1fa12d3ee89b400dba8073b0080ffaab1182e8243afd93318df15bbf3ce179f21804fbb8882e855ef9e0739ce1536d8ebfe9856aefa9874b4e102e705a40ca4c3ab0ab7df63ba525189b518796590035ca780d348de49f0ba8f28456ca6f3e3cff7e761d961ad98b8cf01e855797c88fe2f811e41e787f3e4becb0ef42ca3b9979356020b447294ef295543e0ef512a247e4d356bfe3deacca8ddc5255e6ad047121eaeafe61d71e7f31395cf78890add4f8c688e4eb065479a63ccb3d0c09028bf60c700fe9d19195c26fcbd4130e6feceb52e192a2aa2343c05b43b276f51a7c55dff7233ea512942291900d93315438a96af08e25ea5b9ce656c54e71ed60d1eeb1665ddaa9e42378c930e21d93484b9a4099b7ddd71d983b4c42c6b1f62907ce84b24321422b08b847f1ea97befaa4ec30a794ad7f340210c800cf185ee2c6c72e844cc5671964e1e1ec58953500f149f0f0f25c34d5592de421c2e31535040020237b907e86d753094dd4532e1ab9d821e7583d4a21e1041fa7ad711f29ee3721a2aec6b0c46866a2de71ee850d8122f722898e533848e2bb851ed24cff9ca83badcfad88a171b4be064007aef4d759d93ae9b67b446f3c6fe504f5b4fe851b8312fec86b46ec3cfcb36e0f682e65e117702b888ab8566c9cc716a3a86106d2323c0f7f20fbc1fcd110bed4492a750befbfcbbe16820077dee281bcdf14509b93137a3998b2fdabc2a375b38857bed12bb8a9c67bcae7934d02d6ff89620fa8946c8aa524fde99c12fec0e25bd79788e2c15fc31fa3f27502cb952b9f9482580cf18ecabd92c55113ec4c4470c4dc06d8ca27a10474594eff708209e8f376b6f17915c2966dbeb0e35ac2f02419692c0d232e133b3907059d3a56ff169e7e61915c8b1067e183337b40bc1136241e862eb3ab3f2c6a72b18511c4107ed063d1e2303d0fe6842fb01c204d1bffad7e90bb44a365e62945a7f631811c9c37ffa5ac39c16b4835798686da5baa8e1eb6aa76b42f6b86863c30669486a175d6b3bc5bc47c5eb05b240bd921007fa39506c6605bfbefc9c8c493973bf3f0767817fd8ce126a301c5b8fba79628a9b3a03cad0c491a5f487dc5e89269e5d3bcdc2998a136a012486c5bce2e6c6dc595aeee2ebd5a36dd06919396184aafb2301d1889b668c4d701c7ca01b95f9508f47d4c411cc0397c244ed4e3e3ad7f97d86b6f8834b13b1b2df0625e6b4eae9e439815e65baf2da767d3b1700fc461fad6297fe4e8ed02bfb65b750c2d2801b7308aba9657df3c3ed7d548687f55e85c22343d1db343bc2dbe222fb76fbb3cf490cee7a99ab3a337c626a148fb303b2f8651651588dd4859fd65c95820ee2af85adf4e8fc2c03828ea7427e7c6b0d4a1b0ccd424df6d1450ee436c01351d8b6bffd4ba072756315968845ab7976813d93d0f0f2be1c00faab3ccafa71cd26c5837e87292870cf768c7837e18ddc3c513820c660870b339fc42c5211d33d892ef22b475cea3be20f5e47206efbfdbeac208e26e97c400edfd41f063aaa6b85a0cf86e23fb11274b405f4f796eb10cb97e70783909ad492ad9207ae7b3d204e59d69c886f91bc82a107d0be3ae85797a7cba747b8e2640ec49384f53c785a84cf8de37dd4048dd4b879c58768bd131ad7226506113c446fbf13d769794f1535d58e9c52e23c1bd55e13c647d304e297d968c759a378f1d594897a026e3271aa6b4daabe174d6a35665b35193379f0ee465df7827299c18e1012ac69913a0a5bb5142e99b051763de3e98d5af8b62133e25b32f4f12b787bef7e21dec42de8e4d99a0adc8f365d8cd3e6a5ff3064ca18965ffdc6b383f7ad08186d735a099bb0ee14506388c1a37f7a766d286d748d404457226b952ca6cb3f317b0f4399006b5b8c6eb89f6b8cfa023cec4d2dedde3e31b9a633c0888989b44ab182a5aba30ba78640f477ef1202f6496fafc2a18e283b2e4e8bc60415a1c9a7fd68f15cc1ea0299e3b26f5755ad9f13481a0563a524c6735942f5069dc1d6a070b3c3698e9c503f67a11efe59413e937062668d3439a5dbef197d24ebdc79944b17c549b0648af9b1349cad83c2a0a9e55fd893cffe2aff4626662ebc5014e70baaf7cdbbdfd3f92fcc5eed863fa8afd87f88873f726a0a2eafe41fa81edd5833f5520cf93b0fbf0660e48eb0258d313bafb87dc9b0d0d9349f22fa2d960238f67457ad644bdc60fb5eafd1c88dd2a74db4da0f723a03df08af6c64883f275395020341d9dd3c7fa049ab2bebb4d8af2bb8dc1340d1a80088c4b2c26bfe7314926ee64bf239306c05dc2ec6e6c5e0ed4f6dbe51f5ee09533f558d29ca6fd27092c20dd892c89c83223752006b23e5abecfdc733aaa59c8549e89e5ab0eae1b44189f58cf9cc18de0c2a2f46a9235fbe42c641a890039cf6aad820f1f844edc24e69bc3bd0c22cfad3804d876edf5491e88cf891c347ed5f24464f2df439bb30742e1f9a4a7eabd9346c6a5f93af22e67becc494cadac82cf9cb693acf44560672cb9227eea2575f90b0e28431684ae12ff2e86fded0be3a099f9ddd32a7285531de8963c9a03355f1d9cef88d7ed9b842d0066ccacdb698d42ff9f8a4f000b9764a9aab1f3146f9f95e6636fdfc9ef91c4d060a54ed7f32167e7ac50590dae3a2904d5d2eeaeff2930bd4cad7166fc17edd2c30e6738157eeb0b441491e5dfdc17a7fbb2bdc6426b2cfb26cf2a7e20013f1b3e33a6d6821928443cc7893f7e4a5268a8b94a6ca6097d25be17b214ea4301e9a723194983bbce286f4363a53afd9e94dda9c761481d9d20c7687a2ff85d42436b9d557d5dc6c5e24ea21d5231487df9fc7986100664edbbc51ad4921c5ec9fbb407ab33ef5c3b3bc81f113e68f38d73f0db0261b656fc344d2d23b93446845d69cee1704834d98737848d405f52f5a7bda3dbdfcd3af3881484579d2d2f3ef976cb35c9cbb76252f2e00019363273489b39943d212ccecc647413c56de69e0087532223cf9b28ce3f77fed30bc3ae6a0842b546e0e1a8b6f6ee1ca0ef1b78c3ed829af817099426f94a447f67229cbca3c07b7a8ce547c5eebcf168248e0a0b9fbeb398e5ed2d0dcacb441f95f9e30c108c725507e459d34c1ec01b67065e5e202d685502d6ff015d46c20bbeef1db38c29df7df585b95d79f5687474e71fff162c0ec0c96c94c507f8a0292a8c32168dacd2fff78b5c7dc145e10fee1b25c478172af8f3ea132fdcad75dc22856deb2576a5ff3e8911842c811d1d57ec203c77b82da3658cbfee18d140ac341d38a30f1af298cf60f2a88d0dfbd3e079ae64a07abb4947cc042925fd5c64bb5d4467589f8c495b0097073c081517bc4504dcd7442bad7e7acafc894fcf34f535979364cf5e908a84e0e141ae47e2ae4dc95462b4f345b12b0629502c7bd65579ec66b2d0a951302ba6da1d1176db6aa0c0ea1fa88195dd2248990fa4aba88490b1da4ea405649203f6ff6f734693f40deabdad59ac62e3296cdcbd74061474dd7b63c46bcfe6ea2b0ddb0f7e77fcff3599892c82425b05ae7aa1a2ac1dfddfc67e11921ff4f2c8f6297881dd5e38ccc4076cac8015c59cdd6023ffbd62b887b33ef8d917446a8941d9563acb66a6226fa4d3f2cc21604c080b3f83e73c093d8f2f7067c392671020c7a7eb6fd0d97af0d63032a3116c408b708d4b2f711c1134b88a91aa359608550f0049af2bb97688afc4352a45c4f6d30d4634e70e82515ff1d5f77851ee857e42b486d5e1f3e0406227dded6c5f47eda30d94f44d978322891dc729eb6ae95d29d22c8a5d649193d5d2aaba782fa16ae488f645a7ed90a566e182f97bc62049724f4cb5fc71f6bc7be57f07a7afb9933f6706cc83483cd7dc4182768cd35bc42f1e9b54d5454d3a17e734475ff58fc66d75419d3d122eff05f7b0548188682f1318ec32c5bbea87c8624cc1e548bf18a6b102e7a43e6bafb579e4e84275fe07d8c63ace449a44cace5d9305ff756cbf40e5a6a20334d5b4a74ab0483e31593f2277e90341fa8036496c2bc6d2b7b10b0b354c86d666d65cacc593d1d7349e71b0360d823453011ee16b6280f5c048111b99b185af99e9d901d4eaffd8a96b1ff394b66208ddc1e7e53420fa965bfc4e630d73ad97b9c5c6ea884c619bc24ac3f46234e7d8d35a12b0cad7220d7a0945cdc64fee9d8852bff872c43f359e7aadf8fa3de3551fb716704af68a18f79d03b3c7d90cf21eb4bbdcbb4004f8ba15ff0bbd2d0918ee78e9bde980e4f3cc13558e6fdb40ca71ad2c10f5e5587784bacc6b925f72da12528216895e0ca4b350d078fdf534fe01bc86b45e0c8e2b35799d268a457f8768ed782dfb56abecfd2b9db00cd10e189c6164f82f5ccab423277e3465ec72d76b696cafc1cfa9a7fe47d142fd6672d9c5b77751b40801af07fc53b1c9da0fe6981ea75e066572f7272baef8fc54bfa7cd71cd0fbc5d6cd717e9aa07808496ad2b4b4005a320c9312c73385afd61193581dbae99df6c25f1b9da17093ccfb108b0a26c5ae4963183533ce2f0ade01bf5e818af613416433578522b1b1e5aa7c791570c8c8b26ded266399116f5789a8233fee128e54ca8ce63fd56c1a146c3006316d200e05715993d1d97907ca83d7fd42ef7e7222eebd74f9c86b6cefc82e614a53976272c8801bdcfd882e34d86b39142ac05088a4c47010a71107bc72a380bb3e5122981d1795256beec20a0fe568002d79a4b1577903fe8682f268eeeed0a97861337ffb6861bf378eba1e0957111c7f9fcfeb55a95238005b40e13ce40efe846ddb86d14c9ad2c46cca74baa364ed08da3a3079fae3a36346ac949e2174c661b8801a051423e95dcab6a0f9c965e8744bdd0e629bd3c1a1241e99951ddde184eb8f354209f24c04fcf10fa8f4e43cb55c922c28be041213ddcfad65c86e1ab9b615f91d5fb11e4cdec5b7e25f8e9811c82c2ed457d012e4967b555f228baf4f1648854c624e0525e36e5f4d1961bfbbc3621d79bd6bea72924d8e0146d0965c239a768b417ea4c33237a60fff2760a9dbfb1113a37b01b598f3e06987d99518bd9f1ec96cd7050863898c8664f793ef29114bbeeb9afab8ed09358d1227d7de2aaac0ab2391cb2013028ca5f4d1de6425ec5feb17d95df358572fa27fcd51d14c363a36bc37c7497a0f964a6c004561f68349f828d30d4633e87bdce6b6d92384c9c1c540c8295ea621e9a8006a8d7c163b988853071e06c78f1b9a0246db052e8484a65cbdced3a587e45d9e2b49a5501590cf768d08b6a043971110e9c9dc96abe855abbb7aee2c38bbb77e5c68d61f01f2376b6122450117240532c7c840e3739395dd6c9e80a432423fc5e3a6dce9dcd58eb418e16d7aa507b4d67dd6fe2af4042a5c7398ba4f87c650926084efbfdc9430a4bc2be544880ecdf7361aea06a25e4f592104b0d74312f2729a4db5876b675bc0fa68f6e41e014b7caaf6f49b8ef704b6243df410dce94ad2c51d328fb90b9cf2f5df645015f489a262f57a5aceba40a56d343403b660928cd7a9d165f4a5bc289c0d28f33dac85c9c2a5c79b5ddd22c744a0388a5daf4bab84d7c77685053c912c9a24b5a0664c6253febbcf552c4ff38bbaf2f7e0c9f06e69a91cff9138c2745b99367e00ff6b6a920b1812e17ba44175c033df0e58d1b5c0b7d146f861b62e812ecbe99d638219e0dba4dd88089005977bcc90634c4dfa95f87370d905d32f613358fba2efcface0b9a414ce33b09e271a647b911843933c5d1008fb0717ab59739eb8eb844a4b34bb1a8f635c5895afa285ddc43720e78dc81eee7db822896bd9bd6ae3e7fe2988ba560d58f02592870647b94aad1dbb0d0cb60e28135ceb72e0a6f4b7893a56eae83f9d9a4c549d53d17c6a00f5d6c266d23e7a1d13e22a5fede3a7082dffb34296f8fe9f3bfe525ee1da81efde3aef9b6de8457a10fd4340809e1dafbfb9e2719c327a3c3a4c51d4d5600e8a01ebd5c537a4cd7c4519e963de06de6c83a9b968b01f79e08b5415c5a9d6a92a633d6ae969b80cbb2cf4d6d1ab2c3b94e7c12df27ea89bff4014d92add41a3e961006a194ae3ea4a6b38c2827f6185ae636f6846b1c8401289696fb10c765fa93e58d068bdcd8c9dc95df572f096d65f5de42bae639d41ce7e1ee0f48ba4faf856c0cdd728956d7e4babd6d9d6389ff41d76c5fbd6380f351b05a37022dbce0a6a47ab7168c82c77a2810c80b1882f825ebf86cb7f6d0f54025fddc9b9120802514c797d1d3968631dae95297a857890ff1dee408909223d012925dc08b7d1119fefca7466392a019d4121ea76c8b4c3bd103a820557e4b2283e262af32f1edbffaa253c47d5873bfd0219b8be86c7e64ada2d87ab6b7f428a7d8fb3ae09b05aee71054355eb83ad76c05d836a9f1a65511b1553927ef1b19ab1576d7185af61be6104de1df218918179c6321846085a83bd1217aa63d0b03996ac1fb4018a8ab54fcf635f7d5a8ade95894f0d407e5d4691920f21094c6f632f1661402a0b3351f168f16a13d3a31ad48e89230cffad272926487f36c7a2584c9387623df6227be8c96088db4a21c93b1c88ee756e960f60e614b30bb6ff757c20f3674a7ae7f6ff6a9115a0a6d444513ccc0be5dcd557430e0ee8db3ed5b3e8c405110500b9bf7f6eb7748de4988a1db94bcb16fe33479f64762c53a1e2965363452063d7bc14386ca7b4d46ebcf08489c64ab413ec0f1ddee8719f5fe978d38438ca3059961ecc8480908cfaf139d88db2facb5e7a88a43a67dcb0f97a17f9bd5b09b8369803ccc7ab6d41238e59e43762965814c10c36fa4b6e61bf2e83c0243f20ee8aab62dfa9827aec06f99c5c565c1bc75291292d3113503a202851c26d1a8bde54bb30f0301e555374b71e278925a2afb29b0209c08ecb89601bf612ce811a493abe2bff78e7fd02ee13c5db6b3edce7c87559410b9be3be95465468e33af224d6508a44728cdffde4cb14fb96a0d2ab9c7f597541f9963775c32ac613af9beab89e0ff7a5e35613751061b0511532b10b3947802901505c8e33bae67ce0e28da760af7e80b730811bdf17abfce39d35def51d73a084119449038c2b0f1c86d844123c6e71f28b7038053e279dd11c088dfa11c547a4ce13b19453e88e5b74962101412490cfb68e21d8952db509cd3a814387b67339fd04ddd2163177589146409934f0eceb10db2d90a9e3f6691eb75e84d5e66bc3228baeadcba200f3d11e0cae090ffbb800f5da7032c35ab572de55beea37258bee6f191addf01739a26efaa612991cb2a3c6d1bbb03de0ee1fcf9b7f6c51e452b21c0819a9aad93162eb2dcc189bf355ecd2c3e504713dab24bfe3ed86a4194611029f7f6216cd469fe1f7d35d56b6c8c2045011e238f9cbc0a19b8914d74329e2472f15d0b7d60511814ad2736d6be168aac01868c2a675549c849fe05e05a76f077130b46896735db5490277b76bba43545de6b8ecb53fd20398eb94dd884951fb48d5690ce4bcd0b836615cd9340ff0cdee1122743accfef343811a71c7d14d1369fa49ce47784a6ff8adc26c151edd4969dba513ade6a9b1f009e57c3d6aa845ddee275169ce58e1f04b564ffb6d0eec75f7172e5e8fb814cd702c9fbea8a783bff637db8667d4b6b48a264135bf60acf335936105abacff0351ba9aeac88e9522cf7ed80069822a7db1a5d8221d9492e02ca893e1f15965fb82a80ee2ec491027bbc8906e71cf931fc21e1c0865ee06a79c023929625b4d232c7b3e2e4a4e5dde28fab675391befe583c95dadae71dbaa43e09d8d65ba36d148aa85d1a2a35dc51719ac0311ea72c1237c78a8b1542c59de3b743087245e54d3111c585b5e5e7642f625c8d44c6d9cff50d8d071f6fa573df937d9e7457302d8b293d8fd94ebd3023c55f8b260c3454e93f58f16d0f451189bf41c9f9b91d3c3918adbf98e4ca5aa0eb6314041521ef880ce18f0ce296721a06b329bb5fbb3024e424b46400e03caf0105877465285fcb41a93844fb90b7fc1924883ace6ca8a37c9905068c633761163affae39d0ba55b67fdc6bcf0908ee3a42af286c" ++ }, ++ "transport" : { ++ "secp256k1Address" : "0xe23c5bba38d809fcb2d3384f210e9a6405beb498" ++ }, ++ "ecdsa" : { ++ "addr" : "0x48fcd978ac4d42ff52dd81fcd17e93190f35e5e0", ++ "claim" : "0x2dee91bd2cbfa906aefa3a8ae6e2de773f55dbd28e77bc329d28215183068585601ab9a7f9ff0c48095407474d502a3af3f059a666e5ed1e27468466d69914e801" ++ } ++ }, ++ "1" : { ++ "id" : "0x690a7fd66157e5b777256ea5214f634f61b3a72d", ++ "keys" : { ++ "falcon-512" : "0x09a6d094d9a3a0865864e9a16b477236f1ca26c888fd0c918db331c87a478519c41085cdac7e6cd0d89190a41a3bd6f4d6300995d591f5e22a7b7147caab1f9c7a85a4ba74d47c7b227326ac17535de039a7e604225d3daac7f75b9544654b73f79f5825825ad6e6c45d13e6d385a644633e1c8806d3a0a551c98f032583c95fb13997e52a6b02192d26b5a47fb22ee52999ec92b75c70774a4ae0481a79113ac72346263e53d5dcde708668d317dd00552d5a40ad47e59a501b10a50bdc52c5c2b2c920fa0e3dc9b8eca54b10aa5ab1168c88287dcf80ecd880a8fdec85b6d63a15b9f453845421a5d9b898e6149b60454828eb9dad6442ec62ad27ed72215014f3d17539085ea3f668b0a9183ab96e9db996801c72a0920b02a249911924f181e8dda515d114beb83b075ce7e7a0902a6971e31420ee4921f5cfc123f29dc7775017aefe99a7e326119cb925f6f603ac3bb137313609498d5a2000c426cb332c82500dcfd80d70a5e2d156844a683b313266af6d60216bd9e9998bda53c0028f387ebd21a5fca6c0607d54b1e95724746d15f25f16e45845926a83c7598646a0a0d3a8f8307c1a401b823f1656ca41e5499684150a954318da076af9131fcc93361d9bf0ae035f617e02cb5e1224a982b3591b24013ff80dbb61160d2ba4ce85a4260c8a3a3218e0ec869796b1b04a82079cfc0ac26da03b04a11950b2a3331ecd0026ea9737bd20e6ea3045b56e3c71278d2a8c72c8014b769da9319e19dbe762b1943e5a4be15aa84d0da831eddbb10bd05f35d55b6211d02a61c5d9247e69cab6c112acb568ea51f345a5bf16f84782e04220e217722da71d634e1a68b796376c8a49a965c592b87d06702fe42dac12da108d24ee42a109e8e4cfd3bed6ada5e3de50301696bab0564292864f1b9f47d5a53cc0c5f9cc3d57051065fd57064d08764892ef4c4a92b475184a4cb4ce1f3a0e6da0402414db5a9db34632b9717586e799b06e870b81a330da7be6a45ddfb000fd337a24a29e164449f96be015818c53aaaf09b9a565d7d9d735b9493885e7cb49a5f1985977cd6824fd62f51d2a1e60289dbaeaea148a44dd8876cb58b8ca2f29f6455f354e4e76aa13290f2979b78b22afa0e65c696c21497e94bf0141ac6298aac70b5ea843848a2264fc057abd3593cb17465e06d41731b7153b71f8f0f7a06d362fbd09845f0815794050460b41ad003c9396a86eaab240555ac8c75f85c0ab972c1a0b94b67b1aee2fa3", ++ "slh-dsa-sha2-128s" : "0x2b2fea4a0edd5dcc2f653eb2dd000aecd87deffbce8818aae72d7862b506bac7" ++ }, ++ "pop" : { ++ "falcon-512" : "0x3968f2999d69a9c28ae792a90a47363e689bd4b349e75c5f837181fc7b16d3d04489bbc32252d750d750417770630c5b65b88cef918ad23e33892a58458e9e63ea591596d3b898f65e1a5be3d36650c3d9834e1ec725426960d337b8f25878525ee3c3798b5afc9add5bec82c8e139c59738aba9ed5f42d11c886472e81cedfdb5b910eb73e884e0d4cc218b87cd9bcc0bc107af586c65b3949460a25892d9607efa341f232e478f3c9fc2d05f324ee6eb7bcddb72af371d47c36856f488872249ffdd322d3de7d12b62b1ec595187b5b363e36cc714b765f0ad5616488300f6e56811e88e359365d5698ab123b917bb32f56566958b154f6fe052b894ccc1fcd99d65d19e8117a8ca4887e01f36f181461a433fb9bbc1790d8b14e34a097b149f0c5c075ecae3501944935f3caa76f0b9370ebe6b90390b4d059f9029ee4af98dad33b9050877d49c3d4f2beaa4b5861a21af95b8c52f9ab4b0eb115357f5b1d25fb66a36b9baaa4d6cc5a4f5fb5462432bd82734d7393cd22c68f52493eb3434c3b88fa255baae5c46c650cae17ebe59827cd6645c6d377b3cdee3aa6a758ad3a96d103bf6ab8ae03b72b53f3aebdda359288c32ff5461a158962924a97a24af29f6c976762e8de9363485ada49c445566e71ac75379aaf7bf190a81c671115e842b5280a05bfb2ef3724bb74487068d5b5ab2d089ebea7ffb4381a7e96233f0915f295d3b71db872393bb990b9c74717bc3d72f6271bc248e54828a1e090f6da56de3643b083e9695db7d0a32bb42355e245e5cc2ed57354d82220b449e10cca1cbf6fbe796d141591d6f71e4eb6770a3c7dfcee509c3c28f2f1988eeca61833b6681e6766790c2a6f043b4f67e145b908ba7f03361cd9d435d054e11edd9667e4f9d12c2d74f2832b619", ++ "slh-dsa-sha2-128s" : "0x39254afc16b1dd8d4fbfff766819460253653dfc6a8e29abed55ffe91325afd578ebfa2dbe74d46b48b381e69d269b5bbe24ca1b85767bd71c744065fa47c646e3603b44261731b50f2d20a7a327e98b84c5ece73697739c8057f99d6ecbc54cf891649fa78b7bcd824972f3b27820ffda3629f481b1193b922cefc907bde3ab1c78b5ac97ff26986f3a553556d0b158e936450b4f41bf006c90a9758e0efb327f67408a7b803ede993522cd9042db4a672c89d4765a0fff8c6e8bf6882a8de432229dee08ae13def90f9fd0a40c99f3d93873a41d74871aaf407b0927a817b476eb93c645254bbc77d131e0bd35a2541248172993b1064d5b26b921396c8c1664178051810961039b15790862415338806329a45a266aece5904312afb1cfbeac1e816fb96256fc6e2b059c25af1966b0bf261bfb72afd8652feaedd6e0e4bf829a75188708ac9c623d4d6699281913bb563b96818f9307b66f7cf4aa9591e30c65a0b0885c22b5d17ff610f40bf2e0a9a32173b2fa7d66c14784402885d84f33fc75afd8f743cd10f5ad6dcce5b33a8f0c0365de2ce1b69aa86df2482a2c2d3746c6f0ee4e6fdbeef5738d809f6b0ef3cc703b0d29e93e198b68d62a5be657e69c33459fe4b163a5ecd72a90f1e53fc00bc8c698af7ae3cc5b07e36cb74088066a54138d6df4ef6e159ce5924b6903346a5fe115272cc951e8713d4b6f96f78d67a542c3bb402e69bdb3c2b06e189186c227927b2aba52b29c14e837b37798321fd000ed3bc0e386ad6e5d3a48494f57109322f0a87f7dd752d862dbf772498154804b09eca84c305595cc1e6654b1b2e94d5b88feda176aa144d3895a249754bb2ea99b2efb4f61b828f265638866a49dd3437c70016347d5aae64c79957ed394a85cfe06b10b98b6e83801728645529537a1102bb04ada4226688594cc28aefb24fbb0d1a60c7b826dadd23f301517e862c67fd88d0f6a5ac08e7f966ae375b468e57f01521b43fc24c761838c174ac106c4e1f435b7ead5e79aa1b303222f6b45c5515d497d8e7b05901bee96945652d304ad9ebae2153321885f19e7ad08c9da73ccc22a66c26c4cdc9360c36e307310714ac44c80887f42a2575305ef649378d76d297dc6faa904377b2037618f23b8be496fbc680645dfb80a76bfc060c6b2aee4ac5537e79b7dc7deeca0ca38041dc877b875cab1a297190269c987dcc46ff34e5bc154e2572695e463542be79d61fd5e96a4be2b07f5beb71b882f99de317116fd0b36131a88ff9707eb25594fec74cf76c2859ba6ba2b968d41479adf8857f4b0f4a26f49f0f04fbae0e2f3c2ab6aefdf01855a7a5a4b8bf516f4551a393a33d3920ca3ec403b4d37c2106d777e3d5dfa768614513885d857ce95b9bc3b992808e7ad71575e5e91b8107c5802043b221c74d73c7bbfa7a191945bbc5ed69e20016b16e2e2987818cfa80695e58950b0c1bbb8c474f861d1447161744c75d99dc8240338c43a5c19a8a9f46d80f6b4b6c1cb57f5a3350bfc35a0522f89e3470ccd71a458968c629c93336af6b5b091f569d1fc9492eb6b976376b8ff19ad9318f5cb1361954a0471419b4207dd9dace8c0545e74dfbb19ce3fdb5d456a1c1bff7383c6fd96dde3a92daf0ff5a315714c74711e3c05e0c59ba525c64ebd17fa20f8e143c5931b3c77da193415e6506c2db27e0e773a6a5b5d47ad95760b8d471d06d5dfe000a2d47e6e4e6abe7219750f1f7892f4e09fe88d13c2e3b53dc904ad58eaed856a4abb0c10830b96bfc1b5764f9e4b34b0072be314608fdea8c5005d40ef99806d4d3edb72e73541fb828d4b2adc38855e09e974293de25da6907f5ea97810eff1be37f88ea879e545bb5a70d2187edec81bd57a95c0314df4ad08a864156579d50826d0cfa511d335ff722e246151a7afce94126232f6bac89b13c142d29e7521479866e35b17c15f16ee89d798ee8bfac5868e505031586b81bfadef4aafc2ecdbde649f63e07eb6026d09910d9d3613a9871b5d1523cf5958124f96b5304d5225b4bbb03aeeef87753d0b6ab51a287df1e9031f56f755d3fe5a20f79b7f0f467fa97eac5bc09a1adc6ec285c8f80ec5c184b8b5eae326300a5bce0b1d757c8e4f27ca2822e73745009291f0d9032051e15b567511908f3ec68840cb6ec6018a9a0e30f2e34759743ef0bc9e12c9b32f29f4b70a998cb8893af2dcf17e0eb4f48e7ba367f68aea5516e7248c8be1d1f896d7e8446fadd9603012dc13126878300f0868bc512221154a5104882621f831e60b49d04fa8a701256b3a413b9db4abc5af10a3f8f4c26cd0b3c2f55a58c9380143d835b759bac7fef824515a18d79b6dbd361541047c79653ab4af5473b7b7e67a6755add78d5c14c0a9edc6c7dd42c3d0359d9f2f6961f8930458a34c4f12478ae45c20969c4c18654d31a7ae73902757b3b8a4eedfd16d6c0d22548d7b8ba77aeb4c1e3f3766b6ea802ee9bd92c5f98d00be80c15e7e3a82eb0d100436c398781607dacbefa98c87b3558f363b3ecb1ff313655838f864c1b2e0f6d6369bae4eb8cef98f564108ab2f763e590a9e9201f4e28ef1971438c30f4376c55cfce9b9910f448e31d06c2e456eb798476d56a890660e45616840377ea0574d1c066ae2fcc46f41cfbb511e5efc4b5c60e00e4846e157bbee5fe3bcd77408e3bf721bf871c05971a70cf7a13c782bb4afbdb1ef800a414260243fd828b67f49007eaf60b3e32f4e2b8186291075a0b1c0a528abb9da7974b3b1e8b20d337161ce234db66ce82a88ae1dc880933343961267cb4932b36aacc5f136cb474bbdb5e4c4be4cd74868775d80317bfba00ca4e58a39d04e63bb797de366c45efe2e356672f567ed1f7b2741df7543d6faa7227601eb7cff367d5a1ff320ca71fa2a1a42866239cc3fa5eba400ee4060266a05b8fe1e729908b95ba6aff8fd76b5e7df547df62cb89f0605c1207c869d7214e4e6972ea6e47b18235855d6f28265a737b4f64f0d215943f13d219292036c1cfc46bc61679f034919e4fea80d882a5121cb3096a50f2112eab265ebf75b607b93e14ceda4e08152221bd368cd1503ce375188d23514dd0936bf980d4282eaa6fe8f38f5eb00c34e3557ae363538a2c15b560b9f9322d1f17446e8f3fd317126986afc2c5e9fbb96f8ca7148f53cd75a4b845a28034c8679baf1f5406564b6e4b8fa8e681b5a9d208f3a1b28e84d6d52d4baa152524908d50d71d9c0d11bb5665c8a6bad669dbf303027bd0d534434f9e76f2c300326e25d00bd8d3bb1debe1c3984961c0ea8dc547e8cb83a8f3b044b673f4a08882d103d6eb143a9645a9a00fab6f1167a2c09015d6ff2dbe4aa4025f604a63eb32330f832162b6dd9364f4ad6afbd86c8d26f56d7d9028dbb3051c85a0c86ec0d7961fd6008f87dbe8347fd5ed1dc4c27285364f63650f161321daa83ad41fbc3412bff800c062a78cc5caea330cd58e63ea9a9d6de2ee069732799f52f49d513c658a44a2122b8427a405d706f740600f855130a0ea720f76b3111dafddf0e2ebbd13f60640379993889089ce508b1343f485457cb8e0c09760d3199b4ea940d584417259e41f2c66853ae4235b6f010cceca3859952b3daaab55da14adff0e421e862f138872c2577637b3e12b00384cd32fb3b9c97b0d59e51f2488e379065d79f5a834b076ab5b35fe4c47f2c4c4f43e622527abb8f682fe9f262d2883fce5c9f16b7566c4e078b67611abf72cb8a0263ba12a6c23b1a04458c759f2bdf6dbcc460bc5df48146468073b61aa5ab4a9c5f6c006f54f1bfdd85373f33af29d68580eba4cb6dd88054c81b3bb7f2be8186e380bee0b32a1b84ef6319798079828080361bcc27473a9634c23652ed6b2b2c8f8d5a6721551c780870f1787726b121263e74c9464a76282dca27249b4532e49455a7485e2cda4ccca823f62d3b2869602197a6f1ecfc9d92ab6e231996e603e81e3dc648aebdfb900a3d929502ff0bbb3dff813660c9d5a417d857c19754ee04e50f1241831517fc2d2a71c5e238a944992cc50b7106aabb5482fc7e0a2e6b5b11bb6845f34ede98a18d5f07759e61603de502b5eaabe59a4d2c69f4b0f8e73a9bc85b8950a54bd91bcd0366dffaa0df736dbbbc35d6accb5ab8b22a870374521f2035c1878718d7d3b025838da75d8bfa3ff36b2a10a3cdef1b150abf3b6be95a5c096a921a3eced20f509dac4ba43f2f515af2b65d3b2ebd0da2d7a58500157a666b387b1814d0a3e84f64d0fc44507b0b6792c0c6bd90ab62e0f75b66d50b6f842cfdbecf1fd043d642c5d5b5fe5cb68af62e6e23cc6f0f9b1cf3cbd0233ce48a996296b6609be1c9e7a027cf76615dd11208f1fde119099352cc17e1c9a22f4b71c3e628d72b620f3cb4bd40e4294ff8dfe19480b5b758b874a737e6092254638a222c83aac52fe0f66670454c313adb0dba2b4e95741d27104bbff159e999e23103c00470a7feee6f4a35f764ec81a8ef520cf1e8623fed3c06b63c022e40e7638db269b8add119fec50456b33224c14486f705e5b3339c6f38aa4ba6dec8b098c27447185ca50cd70772e5389ba703a4a9f8649946671a238e1f005aba0b3a18c8ceda9daf4cede6782d27931c638af3f6083b2bf10ff0a632ebd4dd528da3aa2b7a8bddff2901d902b26d518a058921eb0178ef08e24f7075f77ea0c0d0e72f29847ac7826230c0ddb5e7fc8552ff92c007e9141f51384a12e218da4fbfa9a7a4a1bf266aa975949e120db1b6755ff04adb07c66ba9619b40396072e7cc01dc3dd56f7a2f928a82c8906be416f6d5c41354881f9a6c66a927292f8cc2887aee86e90da32fa3bd9d72bc26dfd334f943305fbe4b645df83fb72c565f61860a480dc0f2f3360368ec3715c2c4a312bd2653051c8f29fc14e0c3d1f515e04b75ec02cac2aad8d411306969d9a8da08c3477eb6201bd54c6ee643d87a89c78a5c8ad48590b7a499cc44ccb812866a4c48ec2da5f1e0aac741464b26988459f3724ea4cf103c27e4a43e5a5fbbf94908878894f8b62995aebc20e632d924c82d9669f64b2093cfe023cdd1542c8f9d19e5e7ad6ed7920ba6834cb0cb91bce48fa94be47c1833c6ada4090509ba38defab7d56dde8168bac8021fb5a2aead00809f1881d53d26fa9cbc824488e16062fd9f68726c837234a82d518e3d10c9931295d20d9affa5fd18c0b2dda299cf1d6fe0c6e6959440af9b397f3441bb9881ba1d2df295d12686ef6b0bfe52fb2bef06620721374328551040d2fa434b161648b058b74df2a7ccacd7609b93421f44a136079c79a3e63bd3b4f79717f3c121ceec2c3918464f5619b1a2e83a7709fdf6d1004b0ee51c73e740b20e329847304a82802e02170db386e360dc6027aa7ba1ee35d7eeddb41ffde093073d92899d568bedee914627c8c48427376e7b5d5ebdab30e58147dac5638090e9c71921431f025f1d4e3ba3c68437555357c651336b326c9c519544363d5f4faa91914195314cc873ef97068d928a6b4e5c6ad70ea7a7b09b3108fd5696aaab800eafe463ee52a3f29e1bbe8a968e84b762484a13714ee260759b4492b749c46ab6603c13ece34e301c13bea57d9de706edc839f55b432b9299d2d6643817cd9d32d0d9ddbdbb23acef51992b62db024365ac2db4c432c531cc1ad18c807cf1ee39dcd842aa9a09b232cfd09bfce33277a8ed09953ab3b5d24e5a8a02fb4a02ceed705185880ecc47cb245665cf640ded4015b4afda053a5d1dff77e390c8105961cb3a954c28ddbb9efd759080dea99e94e69b03b928c8667fa4797dbb3cc6ed093bed107c817780f60729036f13346f05491fb837ef1ffc61be7b61d0b7f8dabfd49ec24cfcee088de38daaae6b4e740ab4faf16eaebf89962331a99f17ca5955b15dd1fa493b91e7cd218aebbfaa7d348b1ceea26951209137448caa93fa466ca32eda497a5b9a4fdbd23a10d9742e74c511a1648d00bca3ca23abcd4f18b7cdeb362e020c73888b76b83e70d26ee358c06933f77d1221a8ff0647200e451e971fe45c23aff60a88baf46f59a0bf94e99ab9337b0336ffacf8e79db92067d2b744134cefac1241dfda288f5c6ab293df7469ae0926c166e999ac99c8871e571eab03f82de73e9de2d8f4deea3724f795480cd47e304f27f2567cd94cbed52e06f1f1cf7af2feaeba8b95927eff950bfc26aa0cc3e46ec7bd5d4aa43374500f8cad4f153cb586620b9a0deeec2cb12ba48bbc8655c7fa70ccf94aa6891b5cc8a3c98b482d906d72e9d425301d0cc6fb4ec9c4a5bcdfdd74fdcef68f05fdb78f2a1c5ae32c28c43ee900738f31ac1fd337ce95966b3f557a727e0c3ada6c6aa61219d92fd5cf68fcd9b444f6b4fb6178b9c74238d2575f442a298127f282b5ad416cf6a365a214048489139918f93ec07f2cd864f5482c418c7336ca4590a7da8a20d33ffb7be19934c80b64f4b982a55b129f4896685534b83251d54e46a2971c0bf49ded9b13a77ade3de9a61f2204a46ed9cd7bc444801381994c8ca5a66abd70936f8d11e2a2fed78fe9fe8889dfcb979c9a3f11f2c2c1aa371d1e98c4fbdaa95d58c6b22410c0d3d3460077dce654a1decfc829f117bc407d06ad9ee6aa06bf818ea2f25312b1cbbb5de527ce9b5c5ddcb0df21e3442ffd149b24af5e59eb4d7e18f68b02b26e57fdf23e7af4fde3e672990295c37186ca67b2abdff6b46e1ff106f041279b61560ea2eae64649c65be22f9070c3239b0cf7929b0778c43dae5391d8d3b8c335ceac672376588a34d3b9c61833578e8d5a9e6e9f72748d860d7af98f7616431d1ae1ca20db3db6ec99d59fa98c25a1cf478e1b4a643c2fc9d3e482d56bedb1b7a1fc9c3e788d9de281c7356b82e3c9e1c9414a0d14cd07fea5364b6a22dcb3b69b6f447343822098548e3ca7e88a83187db145bda17f7c48cb00e6ce36d53e2d1e4c169569ee3fa03620a7131bd5c033062bb82cedd0d0ebc1025937b2d85a3cbcf6ef4458a57525a66244be3a62b582bf2b88549431cdce09f6407e1bee83d3fbe205f585cc7cf9c1eaba047a01f51e13bbe0715a9112c451f1daf6074a1af051d8b98863b6fd03238ebe295995d60e7a26d2f95a2b4b0d617af299133bf357518b84e942bc36a88b4030d91a7067e7a2ed7bbf4e9abda8c6887ecdfebda04dedabb9ea833123507835e0357ca1513b471da73102605ed03297b5e3eb7d3bd01c670f992a7f19962b706e8d0ae0f073638d633b34a1229b6979b8e90f2a536cb6024c644e1f7ef211451dc509e061b294c28be188c96246614a1fbf52db8d9a99f7100c878c1b9da98ee9e9eddf7fcb386061ddf46807c60b24d665f0fe7fde205f91021bfb87c8f4c89b5da254d185bda9cc2f48303b483ecbf934575aa45d0d58cea64662f0fda4d97790bbcfa237984cfb45a9cd611b533dc0ea997d191d14d307c68db318aee8f99544fd48fb86f041fe249a14263e6657a5ee732f7c5c9c97a8924bfdddfd75dc67da65042e711a3cc144f46d10a1a9fdac1b1b321eacd235299a1fab390df24acb739d61bd60c6907b9a3827958198e6e2b5a1c90cb9b44cf8db9b6e45f710d7a39c230ec9cd855af797555fb1d73492e29d17da0b6dac59c2ccde0715565efa1f62898c9b26438c60fc3b9f859bbd33a8e05e1d3d5a762bf19bc7c32cf7d4c6bce26fec6e5c8c537608a1c2aea2e1e5cca5bdbb45a8ed048514ef3d298e7dfb9c5408d941ded6220a44c184dc90c922a3ae31c9248c5f31627389770a59f9431fd0139c5ac0f08f69151a75a5a6a0355b7beab6be9829146ada371aa5791c861dc77598f09448af20deca73cf98a399f35c36f1167ba426c6cf4b8b9b8a22b961bca83e45bade098e20782a9f70bd54fb8eb6eda3acd3a5bbb553438cfe37e1f7fabf15729d6bd562cfe379d586181b71b3d3c4b360852003c4363a8d473198130642972eb3434c3a5ca9b497ec7000e821c3419aae75866496bb1b0a9ac6cf92f799071e06809f1f3f904cd18f32629e2093664755803f62f45942f5a358cb1e925a8694998cb14cfc52733c356cfd739c3976712ca7b007e08841639da14e429c102a8fba3191cd36c1c56eb06bf69afe3f2afc4ebf137c617faacda6baf5cfdcc6462ad02f63e8a5375288d0de5700d0f9f4ca82a65bfdc405d3f96fc663658f0aad91305b86ead3b21bd6561a40db0f2c5b0937ba5e1ecbe91e9c50b1dd6bd83a8145b033a7bb6a4ad4896e0ab160e8a52d39d2756b1c8d8570f7081ba217fd8803954290788882befde24b4971723b0ecbeea14d23c92eb6a0d7022a84aca072729d7ab1a88927a25f19a2086f846a44a2726ea26cf1b69c58243e219c756d06c361e1e161bdff0eca10bd30d23782b3374ed421f50cb66c9ee063ca622fa78c8cede932848f0f8f91bd7a0eaa324377c109808bd66ff463a72389c4b49f2e349be70d07fcb56b28549fca65ad853d70df66b587390febdf6b1881cce6c1ca9e9fdbc9f1ad68ccaff97234325d3c972b57ae5723fd73f975ba640f90e717e9284c111b76367c6797399452d37df6b8b8d22ed5e7dc1481a415fadc06673ce4eb6435d31acb6af68775436629a57db7a0aa192310e8427468e8e310bd3426b7ffab00110324c0c7e04ac6649b6f167fa8b928b3fe12ac162db3f2bc355295650fa2d976c64df69a8017034683bb4bd4baacf1cd8502dff20430d48c907107acfc4e29c584cb497b7a471fbde90aabab25290d853b8ebd2c0d49c2c201eca42a68a15879cf391671946319427b237472cd35431128ea7ab6d545617321592c07b09fff93e71596da30689b3c15368a1c3a57890e0ee5752bb4356290024fd1bd2ebfa19f7f3ca57c36d296ae61ec5581ceb77618dde2821460553ba0dd6dd68026b911f4af1be3986198966f90ab757aca2f5143f1937d09c3a08047b797781d1639db4030f9e59f8c5b71a71787cc84ade5a385ebceb1946177a056179aefb49e1f69ed0aa67901b2d6b2152b6c1fd1db67f358093180fcb8f96483fd35a87fa14825d3849dbf479be493bb2d1c639674bd195b5ea3caf49c2b78eb0e953dbf8fb909910c87efc6f9b6592c020333e00f83bea4bdebef4e107798f9a8e89fa5d063d69f88f31a53548ba2406407251f18c3d1ca6e392fb81a46107191e6d906b487469d0002afdb0f32c39873872a49eee649250d4d5d3a7687fde2952291c8ba78fd9b962060df12d212033303691b05eef0ae0e7f31b7e395576708d211d70281e9501618673afac20a93e82f060135e51b29132a0c9244551814bdf399b746651279ed135d162e366f39d40e3a49e907f72bf7c66fcb4ba75b1f447fbc3ae3f390ab4c10963d755ee188a9b0129416161995adcab12177976208e1c93ef48d3ef55ad22bbd97781dc7035c9f5fe25f47b703b1ed50dba311d24154ab05dd88ccbb5a8cd96d4665829c4dca5d5b22affbfd7e842ffe5e87bf4326f957392229bbc893b1fde9e4b2191a3345490d418e9298179661104f70bf6cf9a0094f9d37be98b82d98497573512d8f6fb4b0b0aa334a9120a5afef20e0379197ac7ec78da3688d2c9b590e40fcf866acbd1d857546522788d1f3ae73f330aad045c5bfd59b8a399ae626fd67d9797b32d6a279d42eec3ec8a2888258728f7c329c4efd0f71b730e57f9bd87204d40ac1ea6032a4b8ee3a338aad58c2f3c9795819af4cb652dedd475e5662d9c0cd23e72a8f4e86f1a63e5683c814a99a6595b779e5d715ac91ba62c1ae4ca1651581506ba80c2ee0d3f97b979758cfe93f373873f4775c882fb3b5815b9274595bf50488b935c82e0fb4ae4d078d30bf0843c89e484bf5a24d5de602649e336fb2b79da6131f96ef1b5f82cbd668f4599fc9a92b4e9ffe3468e39e4c8bd90531952327da74a522e479c66b7b1554c9a72a2e6db58fcd45588c9ff4f48be5ddc994913833b668c275174b9d862dbe8fd01535ff2bcff6ea030842ed3a4d105ba07feb0098e39f61a4cbc06bfa153c598c10c5de57caa413752878c7599e5db8482b6f275db2185c505bc0c9670fa0afe37031eab994120acb935bf9dbe6cee6ba336dce1b44732c4267ee77f5db890041e547bde486335b9a0b85d6640f6534d84b3729b3436ac1c0551d687ddd8da9abc18689e7e932d5d0e787ab5ee5f36eb53789b9ba2b71d7a4f7994e56b056d4a042bd2cac79ad12d87726ef8cb97342e616269e9f87493e95dcebdd91763b134019c0a76e8b12789b026ebd1d9caf1930010aa1a5c348ae2e6273c885ffdf8731b34d87c293e77e9ef14709c2e3b739dec85d5bdb8f5ebc9eb610240576435c8d222ae0c8ebe5844980560bcfd45cacff143a5c208add9011bf9770b7803fa90bbaa10f58d856250b37e481f325c538e473dee7863957121374bf12172321b9c99975078e43a0e1e40138f9c31d6dbe5e06fc881de840e64899c0cf342a806916147de3cc342832a9514eae9550d2cd1166e823f404a05b418e5f9ffa84352cba3007f9d37e5b00049d7c099346257fb53e86b919b45a9c6cd8b67cb3c4e383fcfd5789f2cc087d6b459e2a7dc96d08c826c43410b3df22021855c7d413d9cfe7ca79fa860918a74941e08511595fc9a3bec2e2e0c6dad05781c0a0d6b6609837ca8f78b0368b1217b121cd6ced8fa48dc131709434eed65523269abe95f338bc5e3fce0046ecb24dc1ad8c8fa68b5f9263361e4952ca1aee9229811a5ea85c9c4452235639d1eb8105ff88c048beddc0f7efd3690da8b9bbccbbcfeddcf3e3c9e3ea7b46a5b40098fb85a25842911e42a714c2dd0fab403340ddc1af9484843b33c7f5bed80fbecf68180c9b397ed85c51d39cf08c5c0336b149e6d1747360541e84a93224ae88c1b62384b938ae25ce17d656b9ae52fcd9100a40dd7793ca67357f3fb00621863a490373f0db49b1aebaff7284d450922f1e5243bb7fb5f7230dd7cb8db1e08893696908cad4a45711eadfce8b0b42a9aa937cd011bd5c4a8c3a2ec771b3ee4959eba5e4a17545d1c86acaa4805e4aad" ++ }, ++ "ecdsa" : { ++ "addr" : "0xa16c987b93f1b3c51fa8a9833c8932eeaa566ce0", ++ "claim" : "0xb0c578f123a8a0c96354a13f98c4c2cb8a67541f5ccecfdd0cb6e61aa77f7768157dfb3ba59aadbc03350577f6f31b4083bec30291a61ee98ecb3db2536f788e01" ++ } ++ }, ++ "2" : { ++ "id" : "0xa5ea2fcff9e3cf29d0c6f5f147b67ff24aec3bd4", ++ "keys" : { ++ "falcon-512" : "0x099202fa37d5e165b88428d963d2a224b8fc82ac0e4b3f6a02376f18218d1aa7d0e910e71586aeeaaddc2a557124d6ab4f9a44b9cad02166413cbeb14b364e13956ea326900eb2900802644167639045d76bbc4e051654cff404dccea94402141ad9fd992cef7a8fa6478b3e6f8912886e9edd1b34c29385b7e964f360e0fb1600787934486f461c95d577d2bc74c4dfeb969b4798565ce0225ad27aac052290a44f844ae233e082c97e4498a31117ac9d02f3605c856e2dde6f611812161f89cb3a54dc936ca1e740a6c659405ed586a9a963b11c89b01746325e39e645c72b0c7e4491b36a17d43ffe38d88c601a5976f5a9636c964a012bfbce5f9b371e7c3b38580d81c6e12b8e8f2aac219f96245d35b4f4afa6c94015b055703b8c4dabaea4ce2577482f5b34fa49e56a912dd58d74580b1f94e1d2056594ea64bcdb696b0baeb33c86b6544761a3ead9ba9888cb1ad51f7027ee52b21e46c5eeaf3f77bc0af7efdc87acbddda7dca00b6acc665002c26447e5b0e0bb5ba261717c68dea7f1576462776954d7249c2fd0886f615ad50d53960ca02d581a4a25517c050ed467c7a820bce6250a9ba2e44fd67fb21bac843bb134c95360dc1c50d54b7280a94440d018181a9d6374bc64d782c84471b47287d8ea748c36cb83cffe053cb89a9e4ae71df497871c2a728ef210903e5b7f39550d0331e15637be7e28b3a2fc05b0a9b0c5a06f9fe81263c3a94403d6c288a561288ebaf788bfe271a578a1a795a85e9d452b61ac204b297090617286922376bf0a8d67dd35fd705b81260b7aad30132b965e39bc3cd64d154c4175951704873992a814814dae5c6bc1e89a83dd91144cd1b88f6ce449900058afdc53bb44bcab63d30cbd6df115a5ee8f5380a127a160e922bebf7b408de82514b2e2550a0931e065565e8dfc389d454823a55b03e5c989b09e3791f656794e8379b7b4b1617aaa9770366d63a657f71ff40c69b1d5da518ef1e2aa42366cfa38e448563f6c2db5e3089bad5520ec26105fc885993630c10db357883f588a5a384cd6de688e1bc3b1200f87ed66ba3d4a4b671b2a500a0436e0955904030d76577aadddb8c1ed21b027f198c072f654c3abb086e7f185980f49d0e109c1a82741809f8afd15ee56a887b392c5b172ba659144a7e99e25ba19792d2a3c0ccb481822839c8c70c65c0943a2994ec9f6085b7ac64ce2b35489a72dd6693d25f2329264e063db26ad4495e3ad00f12df8cf914fd846", ++ "slh-dsa-sha2-128s" : "0x686b5dae4aecd5618b95c3b2a5792888513ba49dd366ac39b7431ef403e04963" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39cf29ab9b80215a9947b975d8c6097e53b39d1483c885ff7527d7fccdd2ca3dafc32bfbc0a19c857fa8be7e52e25064d69c3b7dde6e77eee96ec77011fee440c8bca99a45b432b5468715a0aeff9d61375393b3ca40b9140e1a2bc2a52c3c8a85292f4c9e87d1e0c12fbe4d7236ba7921b8b83bd10ad554179dcebf0791c4b593c8a1bae836883d5094499cf2ba41b00c8c36c77a83466c263a0b01e773f08ec66d46e97caf0f9785943f98e159e353f0d91d5ab526279477a5509129f7a1b8b07ba82a1ccb4acd5be5e40de088f2600e06a8bcf35f54663279f04c74838294048a8f8692904d4f9eaab49635068df74d1f5ed238f6b895acf1364544747bb10ce333a957599594d766ac5d1a3ceecf8a6696cdaa95f824ace18cc551e1f4ec12f345283b366314515849feb5bf81fd203a6c73b5bab7c01b5c1131d442dadcb6bce32d6e13c5a3e77b66eb8f5b2912c0938d89ed9e20a455066d151a973e4509b03f5d66ff7ffb8b362e0c09b969e21173693d9977ba06d48bd3b85657119f9dc3533c91965ed81d1eba72b46cfcff285131f84306fec7b271a02dd22982cb6399a9060d286aa18a3f97666810937f8a5667c94959a4c27299d55e94564dba27ea3d98cb3a9db6197c842eafb237649de3fab72a9d56098b5c1228e70dc062617a8a6b44d46b7899dc1e53a77b700925ed1b438c59458c15e9b91fa2c2164b9661a976720eee2864efc5363d90beea9789a6d3b0628bf4695a853251c7f70ba1ebcea06cb35cb47d72d2340bb9412edc49626d6c78be644c4ab1c539d1469d1cc63f092ccac45f66917d89274af9c84d7f1108b1bd738408e499efa63f1a87c8730400ec19f9a59d241032e9ab78670e85e8da24310b13e89ad521ad4fae3deb9d438dd7eac72b79496c7b65061314ae", ++ "slh-dsa-sha2-128s" : "0xb8f14bb6630512c51d227c12a04ce7b316bfc0d255f5a5d1dec3e1ce5f5cc92927070079430990b4364200dc6d389fde89c78649e21d8fd3a17dd2de7444e77ac3e8c70eda15f2247300fd8e37e1e3c2afcc3e8dd674823106b4297ecedc924ca948a9f80afd7ca1bb85dc0e60e1ccd5d97eb21062b2fabfe94827b4ce5f0e396e5a891fbfc61bb827cd305012515d0a182f163c1a5ee3827aff289ec526cdafd2874c457947e8a6c8332ee7172197cde7388303992be248892e727b559c0d74a2c65d46b6686a48f0b814bbf031d1bde17f55b888e7cbaa7fd6dcf428b13ca43f77d80c3804bd2840e5768c2aa17f6dc773b71f83eb7803fd9e1f1a2e3e158f7e823e9667cebe136d333316fc670442a8c662930a00f72dd2dbda9b19c3dcfdd09c60ba55d9ffb5d5b3384d719d153566bc0b6da89d8dd869fb8c4113258014cd48a67a3591d37f9ba767ad70a554ec98bb59275ce163364915051411db73833a88cab0d3fdb7c491b8580baca2bc44a7bcfc3a51c28ae0a1fc12bb53b2b948c571397a348e664522ea749890d1c7ea7e9561596a3e930bca68377e4d4c0e0301472c8017c1fd5702cd6dd4c3f5881ec4cafb98967a57837c3869720268b61f37836d0c9c5ddac850a835318b17758a6f97df4d4966d516ef100b7e61271c45aeb89242ac7d2b8ee45a08f4081727d54cc08ec0f8af9e16bdf6f6d6797b9f5fcff9686f15efc4e8e34b363d562dba239908a3992b3548566a30cf04c424383b5bea0a5011ac620ee384f6363fca87daa30fa88763146bcfe0a160c071d79dd8de0b11e034fddc032e522b7ee47f318cc6f3f2b6c9b6efa0aaa9b9a9c1243750ea31ac01f087d5f4f5fb97b8296b0953a606c49025f5bedba6773804b15fb3638e72ffffe38ac20486e18eb21059f419b0af9071be12e309a953ac82c0a5a620a7b5c850027b39cdeb5d728522a15c1557e4ebc3f4f09914b3a99e291a814504ff7171c23eb825d2df1bad1ff29144f8a3babcc882258e8a6060272e95c4393fed0ad86698554515e77340ae806746ed859ff9730cd718c767e320ef54fae5e0cb8ba331bdb920229d6047a6db8bad147b75d376c3e72e06fbc6a542f51a312ec831c704099b2eb0f801b68631b464ef484eee077cb7fd9ea951a0307e08dc5fb4ed5a6e62048b010ede39efc5462ccedef2a4c61ffdff63fb3aae19b28ca48593532f051c716835a61f2fbbd5c25883f4a85b48d81658b6d7cc4227f90a81e961c5fd8a388c9efb78da1c9bc50d53a41d2d336232e84e3eb3444389caa3457ef9e3560c25033ed45242d0b4bed69fda4a4f1695830c843e63147b6c2d3f9bc2608b0671e59d827dc1e3876e5fc6075bcdf95223f73dfd11d64399333f7bebdda7f5c2838c072f7baf753a36a1ae8987773fd0ae5acec41d7666c84c1125190f432a4d82ad9b78e22d6536a8135d80a3d1715d17a673033d37104857278a75c2cbcbfe0159343dad8e98e42874e2b001bdb469c9faf79759c4cb3e3f2ccaa16bb29d3e4dc81627441d07469dfb9f545ed83d9c20ce586370be092f3a90b18f30866336c6db9d53e2e0fe1f98c655f1961997e41c25089a518f05270ce06cc115b6c2e9c04f6ba9bf7ce3abfedfada8580ef89f2fea98e8a19c58a0f3ffb89dadb05dbdf05c44b79ad5e1d259d5aa6086cb295341dc40ff800b460a5ac602a687d6feaf66393dd2be22264498509c9d39033aaa22eb248780a3661ecf0a05cb6629ea3d91eb0f68465485e8fa3fad3fc4315a118e4eb2ebc6e9b07284697cacf0257edf67c20b7b0311d3094f4647da567385a508addc9b25a66db1f1544dbced87886946989682b2f2db1363dc635e4cc3c67ad83bd311437d22d8f60a2cb7833c952bab293c9e20ec2b44e1f1f42a797421eecb2e9e9f5e47105b9e7f5d7bd796c360ea39dab45ad701eef0a76b7773c55e7af7909d456c213b0db14f985d0f73652bdf39a6402cee104a168749466e477d8a399469992d65656b607fffbdf73ca1bf4976d3a0c0c64cf5d260d6d3e0198f0b86c451b9ff5840968a2b60a8ec286c81fb55741d7bc9714177c9a77219d3a39dc1d6d7adecb7f8f85af366ed653cd81408b509d0f56b5dccdcd1d982d115754364ca3f14a6f100c54ed8ebfce6b0dc3de4435507acb0c4d974ae3f2453867a70d5ba078a17db34844ea410af4f842dd4a9879a7706b18ddbf94c7b43ba137f7f9b8b3924b4d917f8e0262ad10d083c4dd3b99b70560377ad31784a587cf0ea1f99d6faf0f04a909179f3f93c96aaeae014ea1e74d9d7ccd0eb5ab466a6caf8ed0fae75cba902ae05244e0dde35b8c0bdbb3354ac60875c454ab11f49e47e2d180db319a113a5869bad3ef4580bc7402b0d6bac10a7a4e81403634fd1cd272076074e714b14a6efefc902126df6091330ae387e161789198680b0258c341b6f3ec0b09c7674e9ae8f88699fb7b2f88fdf2461e11ad483ee11fe4e3ddd48ede0ef0a1e54a318ae12473993a8456dbbe8b5ded40232b8d2474a90424281830da7bb36091ebcf591947b04739846d8a600946c2b892e2bf3353b09b08e3a141f33f6ef83d022666d380da43991d3eae4e62dd3f9432678e8be1cd4b9569fa2fa84e95195449716423688aa920e2ba1cd41cd5538907ebdf3ff15df27900ba7ee09f3e9194e1d8cdc0703d6f38b2b887a89b10787986013f688f9a355c6a362f4797576ba022e4f1d1d74e2e31dd98f1b617b99516c944bfa5bb474857fe74a09976cc29c71a7f5b6fa529f3e0c00c33c2f0700064fd507461535a35c0dbc5b69d413fd6ae9af49ccc5d02d7abac88ef02bbd40475595176fa3b68d602469a89afc03359b032fc1f0ae255d623fbf9525bfa36ef98467d5eb2f80cf7c72a04b557e40995471c7adb8701409830b232693bf2fe905ef8b1a32c4b8fe3300bfc5654acfcde685547d5c1b0c213294235b31417da91464619822f3535c93549ab4649a59dc3620e7f4a3327c0e421c5d1a28a2b4c3ba8ab02950631ed54690cee35bc4147aaa8477cae505a1d1757d85251bda5fc91cf65772e1b543bccee1a2cd0c26cd33015533a0e72c815be8634efbb50ceb0ec3c8a3bc6c84638ae371809ab87eec54b934343ee9ed1bebca488d9399a1e347b1647d108652243cf2531a4685c282e0b9e526688a3ae1d10060a78467e6804b705c143d073af664cb72ce657a7d210240011d539cb3144e9411758a211238a872eb4be615d4813b64b8df446d2741db7c9f0af2cc4dc83c0febc41adb5d8413b7ce54ed564e899c0a5a4abcd1cb44c84505915afaaf93751b11bc8e96610216f71cac8d3c9ddb7282f0f864400bdee42c3e5645aea1aa5649485435ffec9e43d43e4341d967c9a89eaaea9cca12e2089f3de222e1a5034baa32372582023b5564909fbb67acfd2a40d5ba40de2d7a31cddac717f5702648c0346e197f99598dc83edda7ad335f9e711a0835c75d4c32e3305e4db9dfafe171181551a8dd5bff89f8a9fb819eca7a171d1be47fbea0e2838a1f1d01f4e68c3d0045da0ed7d3689c17319ef5f5d178e6cf1628402c40d2095c91f7bfe6b837d8f86c5b2585653beb650fc29096f13617ce6d36fd6107ac83c7d7f5a8639e519b161581dd58018ace297bddc3421d358be70179b14bdff66f229a50a329bc30b054a95d0f43e7914a9137055f4dda000357fdb5e2afa3d61b9816c03697168cc022f0418ee5ad7aa71617103fe17e7f47ecf7ef9bf779f157eea74c3caf3821791ab628fe8cba64c12d3226877c48b746d725c46b0ccf5a18f869e6680f1e5ef3c5e7fc2a18915dfd8bc12676ab94ff4401ed22133ac1e1ba0c0352a30156bd80b63eed4a7fe9c948921e1a9843127f1191751312180b75f06e33694853a05a24ee30cae0b02a0be49db16f6f06630ced9b5e57cad548dcff70b1620ffb17e8bf8c247a962d6b2a6fbd4fb3c89e3aa4381e15b92f7245ea700e76ba99678f4b0c998ac90bf3e4b9ba5b52140e15e4b5a38e25462c1b61953cc2068d0b9ebe014db6b8fbdb2fc05751667659f40ba1cafcc2055c364116a058e286f084c2bb73096d46f6736de541b750ad437c27a92ea51baf3478837e99faee73f2a2745918f81547c45f2b7083befc6387a73366c175d2be22314a1fa73f11571395c7fe9df062740c58b56b4982240c63b8a0d5886a3ddbf6ffcbd705d3bf3713a0e1b74497b8c1f34e204ad81b63f27cfa5215d275597599f60d02bbf6cbb229088b56c96d73d09fb3c36fb3f05f4266221984fe8559619da67bb7314ca66405cef4bd3086940c4a7346243776a6fa128cd9b6181d8f584f482c502fce3339f87e4fc5e3593b7a0a64c19fe76c51a29ef776e478ecdd5e093b2aad0ab3cff0baf73f4e09d63e9ccfd4aeaaff147ddf2e9f1e3e6cb3bc9757c57072a1a8076e179e50b0a03dc94de86fbb99f0e92338f26b6ed7c863830f325d3606189b80c8df5a763f422f26436f753168b53bce965c562c2554081cb4eb42d48daf8573206f818ae66d62bafd151e9784d6a9304996b4b82cef081af9b106b42ca4b6b0b2401dc21d8875f9801591234dec266f1f218959af60351178049b487b2784183349e0a7ab361f575fd0237d9f483590a23401f9085b111ac3d740ff4c3eae0b7dca3d149243e3b1fbabdc7431a579652d522bef7023e1c6579d2f6852f1acb9b7f20e3956af8dfbf14617f14981f40b1b2430920be14284dd5f2771f73091adaf9179b8396c6ad2a3579befa1e323177fa2598a3ef80ff5785dc2677f87e9299c6bb16ef2b2080e91f6fcf1b9189e256985e631a05cbfb6427eac995e683f494751f7ae888bb0dfd23aad7fbe942b8100d4daf62b6b8e4d647c818ee7edf0d4d64293edc3b7b6e08a8b9b71a7c38f55ca76593d35770185637fb473da423069de005363ec25235ce816f4df3070ff567f919f47dc4fcf57c168032ef8d7e3fdc5a6a1dace2513fc24f0829e8e4b964d37333febb1eeaa7b81aafe30d16fe64b6ac037ddec2dd9b372c657120df4372504cd14be89d3719c5aa6d545030423fc50e277eaa401e8bb02d70b6614e9768a7e42ba9b35af8f9e3f7dcf175609f7b91a16fdcd65a151c0e85d92dc8a06cddd1ff77d150ccb62c612c90abdad156ced839e837c79b79f456156a28c45f3287cb86a9ca664a13313332a1ed9ef4b3a3df864eda7bd55a6d8705567bd8d1d732f65a324aa6c77f6dd82517d5274343a4e16fc8f41f5a3809e9f2cdec445b88309c9d1de684032a10f8944157a3dc3d4d8d59721f4f9cc0b0e1e7a97b7b066523f7498e0902ac5aa462d9bd096e13c14407bef96b59297391032a4aef8c543cc8b60217ddd5a5d815c4ea1e21625b52e2323b42b4851b0bbc461abad9b71805e8b1b2a16c811be69140d3a6d32d7aa9d5321adb57570fc2e62618cac60a4cce2b011a4c8ddd4dd521b6864c7c4562d8270dbbceec91bf1cd7be926d6b66bf370839bbb22856d1f0c7b2b7119ecea6278793186c50b045d09a1aae7c5bd2ec54df1087cbd1d8094293392605321bd39ffdbbe510f0e8760bd35074c4b0453604ca1f5bee056175ae7943183212ad527e125d2ae113d83c5a4ca1e63e8d89ba07ce8fac8257fe1c603031a1fe2e41bf922d7ffa0a610e0b91eb8c3147262fd228a4ab54fb520b49c91ca268d3954029be8677229af3ed232628e7d3a752e66c2171d1746b7e31d2dc8d1781af454822f36b3ff40f7683fcddc5aec46b13890a6c7c9531f30eeca923f198f4b57112a94e34673c88c70bcf80ee115de27ef5268a753c6f827e71254b5bea2a4f27c8e0e2d0c3f72d051558700196e80abbdf452bd70116c24f635d1850f9466282ae761f1a38a8a0fb5a02a9e1b99df55616f0a7c031fc34f190dfe5cdd4f2442d16ccb49187823fa90f3f87dc0966c4cebbb7472d8184e37522acb165f5d3b508f6a62623def48edddeff361d5ff37fdfddb2b324c4f545bfd5cb98d258edee6ee6170bd41135ddf4c9e358433330a5b590b25fbb276a2284b2df18550270b32b65d9b483fc42e9610537f27715e9f451bccb73e1ce017aaa39b65db4e86c86a50d0379398e57e0c34fa64f73acc0d2b4e953a89ca2f8c01b10135c2af5c234dfaa17ef97941aacb7cce96cd05fb246b76f15275e4d2a8545e52726a48f269d1a558aa12588cc78919a5edf6c0e9e576ed58c92b67d00e4197905d74dbdb3700fbde85d26de20cc652581608ce1d1084b507842a0373fd8830c8d3f68dabe93fb19e3189e486840715f92ae4d916a9ff3424b45ded24780b31fb7f76d506339d9f9a545fe0547c675bde44a3b490bd3b52e3b30842624ab5e8986161be4ef9da785bf537954d3c716da5597a859ef7adb40fd8030611d3ac6581e424ff636aff72f4dcd9f315744a3dae6cd386b2f9945140071a5a49f05e8f979115678eea7d6d884a92e4f14ff94dc102355c3aaa93e02723a92417ff49fe8cdbefee7e6c5e952ad240fa7eab4c7941f6ae8d2a1086e1f2ca73eb8ca5fbe3588ae51bdaf18646ed04bd185a19bdad69394ac15d130297c0fce9d8fce8ea2729dde117facb274f9865ffb4f2c7248102dbd96767483cb7fb764fe667d484a3143db514f08577cad8bcf695b0d953e2a3c8710d8979952929d59c8b8ae62ff678815130e68c85d4714e832733da40b933b7133725a40a12534753eb4877c65fe4c75542f28d6f9e805789995adaaff6fce3929e6027338281c6d0c33aac092fe0eb1797dcd953fc1f815df794249dad7b28407c50371a8c81625f6e7e08ed59a98758a9859c41f7436f937885ad35102b0eea85f3dc4bb9a6260f4e091ed983b1009275d43e4960f9422dddeddd09e9990d545cb67dc3f1061238dffec3ce01376259262b4c32c6173a6f1e239f4502cfb0900bbb7e3b4883ca3c64c8ba91cfd80b2bec6aea25b01124ae11a56ab3e4d448038795ff62e9d5ea5cfdb99c5901a8b8f8731c772690dd964cda343bfd020e920b32910a68b433ddd01d117a833242fd695a54f33fce28b506d931adba499373b0a6182e54323f032f1e7b8bad58dabcffdd1cae831c70e87b2c6fee3494dedaacccfdc93fa23ee1a4273f16adbbbcc21f5d02d8645951b93287732cbca4c61a0d0549345160537501b8c0dfc97128035875e73db7eebec24813d03d11cbcc089929b0f6e2440a26d90cffb6295e8fccf65b4d676abb8ff66709913775e611bc843302a475488c9a9310c0c8885b78d5db5cbb1a919683cfd9bd010cf2f1206ab327122ac87d8e2899cc1ac684e72c91f2d36c7bcc3491b768aac86e92aeb106d22b3e85112a2a871bb8c9d0a0dd15c89d113910f8babf15f27a13b10200ec7078d362773f17286228b0d5a58d6654b0fb4f60c81ee581e507f17a044e6bcad4bb6ddc66bdde7d311810d79ac031086d7b0c334cd3a8a496591aeda23b2c0097cefdb6894b352395dfc79b74a6e4d086656b0cd9c95a48640cc8b3d188189ec0b98c8618b0def4b0175f11369cb2f107e89c4a67a75396cfcbe899334a5d5df5927fef2eb8bd836a27a2834a7ab94813d30fa8431da3178da4ae56caaeeee66cf545537ea260ea6af56d4ba048076ace08ff2a446080a6b688a916a13b43b933e506ad187b1f829a1d54ae261651563874cae19c490004205765b43c3cca4cd8a309fb1bfd7520bcc07794cf7c03d9b1d1ae0cf646534f5a97106925ee96dcb7fc1f74e62c01d382fde19fe027a4b9b7627c08e690abe3ab076f184210acbb4229d483f7471ad551eb614c35e019a8a894b5f92f5371fd6c457f135ae8377c5781a8f3a6dadd2c00697bd8399b6f168dd64b2d2d66d5aebae90fa5f904af9f950f450d8be919ae3f02cb5c0be9687560cfab2d2161db61e978ef46304de248383dc3a99e30573bb66f873ef1e54f523ff8ff79e8c05e7f8143cebd1bdd9d2186ebdbd3b66a0a3dee79475cda2890720ac5bc33f8cd3e817d82bd7c52c34d491e1e9d1d307eec17c0c7679af3626e7b96bbe6ba2550f44de7d1d88b3e4c220b8f185b459f1f882a97248cdfc3d42209ff44806837750b3dd21ac5891254f6c7f6938aef3caca6c55b633770772c2c06734f84612a59aa8cfd4f347267e631658cfc4ff89cea84550bd43699c1d8840655f39e3449ea0d2abba1d81196413302719bc9b39cea85cb7db6ab7f00683842cc480503004c1c819ab80e121d9d21f46f362614a5f2cf80cb2c8d3fda82447cd0155fd7e0ec7589a6df2e6614671071f0f956143c762d51172da46e9f61e588fbf74cb3ceb74bf2ce4ec4ae26a28245f98ae91f09cae77c4660d6dabe7cad33ac506db3000d742f683e08bbd0a7cb9eec72a1a976546ec926b9faba5084e00d66475a514a73f01fbe1e79c0ee0066f4b724e4977f3c1518d28ddc918c573693e9b3fb69b426df0640c5ee42cd5533655f9a82c6843516298d05cd970f34dafa886995545c37b3b939e0dfa3647fb3f330bbd3e69307be3d469a99c24382acdcac76c6cb71decb4b7b11cb5f2e63d112767a7d6467c51f1c0c27900803180337f463e64f507ce245f606f8c1f1df836c7fd02502bd3127424804c69f1d066ec3acd9c4374e857c4607b711f532867cef2c1c8a7d7051a440eb7a8507500d86f11567e2fc812a27e63e5599059af1ee90444497f69add7862b93ea050f100e48df7a578d55b6d6321e70ef7a7625ed89054ab010850912088fdc21551b89397c35ab582aed6c215e00d398a857090e2f7cac21c7b51f34054a45f36157edc603b5d6e76ce20f2dfd2c20158943efd2349560666ca38505cc6af776e0720af2d5f6a7d98f385854700fc0c749dafb597e94d7ac54aedf34840ea778e8873d6f1fd7f53de7c06327d08d34a03b38315efd8eb52683ec1f9abbe2bcf096fa4f379f41e09b8bc67ae4685e68ce456465b38892a238b18358714fee41da0aac8dd729e2c3f17488470648df81040272b2e927e896a4eaf6a11c457938421288ff074da8db60d37c6d022e86952341f2b8d262cba0c5a6efb51925517a8c817a152499ae7ee56d36df86253e6b2d93079c89fc922014b03da3941509e979ff8dede44165ca4cb698924fd12bcb02a35deaad608ff3358d455a49e12e944dbb11ac7e9571476bfa856f3bcf90ca9bac6d57d5c1755104b348d2924ba9b14e9ffb750cafb6edeca6dfb79d73b9839092032035ea700d81f19d035e38bdde754a5098dae1c163f9c473b0681858004ab9d9c2c57282ebd7e57c474b8f7aa091d1048b95e7ef887767f49d2a7f6b410922da142ab8605e735ff6ea9e3f36a29380ec43dd009d98d8c20f4052d81fedfee6cb018b2da59d63b5fc153d5b0948d613415a6b8a2b7338897188582d2930480d897d55bec899723b285dec9abf819ac7e6f39d8c35c484ca13f129fa4b334979bac7715bbf5e52a9926568f359dd3e3e000958b561527bbd52025918ef75228c423da41861396be4f829aa4bb6f94f65e662e6ac91e828d721b741d7333a8e3050f136a463af537ee97af4b42456d65e1e2324f72267c07acb88c91d0cd602ef765f858f69fcd44ddc73dc7c5f8825f3fe04affee769f3ab5486232e35df8fdb75db79721906907ffad83c57a364ab85d93bc03ace8998ede749d88985ae41cef163a3d00f568d43115992362c581745f723a2955ed925cfc7c83c5b5188812fa2dc016dc21844f923b2362afa5ac5f2a6c9355b2eaf724606333f152a01c330ed88f7028e716043330a280c5ee458f2032c8163f5548428ce4c529d487a16ca0e58cbf41dc4dc802cc5ea7fad6a50de0c0f2c2be49c3dd2806911ab1322a30acd4fd8937b8930069fc1a6de86f9ef90f407b2563594adad581b49ad1d19b30ad13efb0ddd8e6f26dc43a36ff8d14d1c99b073f5f1ce8923d3100bb04488b86cd4e89f7b9f5b9cbbb3f86ee03b498ae255e09eeaaba3e4e4d68f1ee4d50f699e460a922e17ea8f0ceef9794e944f128efe835f281a7662f959054aa994afa3982f7a310f46f53d5ffc07884aa91bbdcb3f3779ebdd7f90801e96222f56df39ed9c2bff5d4a11be1da7482835e494b0856ea7c695cc1b53acf3b2e2d1846fff50bf55be65e16548c4fc436f20c50c119ca8eba4cdeda8c7e4d33734a0355586629ca5a7c3591ea4b15428a81b6d91529485004cbbf60e75208579ac354dc705edc7bccb32f23030e733d3f549fbb841329a01f5c5d263ce635a57aa9c69432e5213b155a07c34fe19cee737cb993fdc82ff38eafbeb734f04f58d367e34df15dd6044591983b9b45d4ffd87e2a6b478c7d1e86b4b974991b930370d5eaf5edbb53c3dcda643fb992b5fb0725a8aaf8a9e7c4012311f197179cf1293884e2356fc5b624cd46358d3c7bed1fed6b0305114cd11675aa49c1b9e6569817d34fd60c1105833d78dd00117284cd1722074a60655dfc428072b0d2eb881b93d6c367952a4bd59eb902032cfbf9189bf65f7bff592032c77d61dbf778986b491e297ad0da5b367c8a10c9071b8d509b246393fe04a290b3e2291f04eb750285674ae3e9c7b76a01b679787a4006836dcee956185d3b0ce16c4567fab862d3634b93079305008e2f99ed425489bcf5447699b7a7212fe2196d3999b39191e750fda742c6ffb5509e3806f38edccacbb8bc73c96cd46f0f400c4012f1205813d69a48bbd1f55724c7de917ab56d4188716b96653ebe4fd1b6d5d252f5599f9c53a4683ae60c8c31b86982f32bf73401a328891804daab93a155140fdd41ec87e392c8397c9ecbc48f26acee4e3cc279cfd67d75b5e0b6484274484c18f72c2532b4064cdcc309df796c802c17480428c3b5a5467b38aabce03de2a266c8a22d3b0158beb913d50615a1002fcbaf91edc529b0cd38f35138bd71dcfef1b6b90adb4e68a594de40199724c158db9c85ca78ce3a19378ee90dac98b23e1515324fe18472a4ca93b004295b7abd3c146109da707f5ef37886fe1a8966ff1e96375fd64536eece72ae3433a697492955cb182331ce72e8f1804efee93b1929338f" ++ }, ++ "ecdsa" : { ++ "addr" : "0x5e13d369c8adbd8079272b624343ee1edfa4a560", ++ "claim" : "0x197e55da82eb1daa23a5478ed230c6d0452d3c1920df15e10a8d37a7430a7f2b69eb474bfe0c44a6e4a55db9d5a0e0b74549c044ae22778ce30f47a9fd1eba4100" ++ } ++ }, ++ "3" : { } ++ } ++} +diff --git a/consensus/common/src/test/resources/aere/registry-v3/n05-unknown-scheme.json b/consensus/common/src/test/resources/aere/registry-v3/n05-unknown-scheme.json +new file mode 100644 +index 0000000000..1ebe53acad +--- /dev/null ++++ b/consensus/common/src/test/resources/aere/registry-v3/n05-unknown-scheme.json +@@ -0,0 +1,64 @@ ++{ ++ "description" : "a key of a scheme this build does not know", ++ "chainId" : 28001, ++ "requiredSchemes" : [ "falcon-512", "slh-dsa-sha2-128s" ], ++ "ecdsaRequired" : true, ++ "previous" : null, ++ "expect" : "AERE-PQC-REG3-05", ++ "manifest" : { ++ "formatVersion" : 3, ++ "chainId" : 28001, ++ "bindHeight" : 1000, ++ "count" : 3, ++ "0" : { ++ "id" : "0xaaddb4dde09de5718a906d83be7db3d58e0ae32a", ++ "keys" : { ++ "falcon-512" : "0x09501c96d2f5cf0b28fa00c726e5359c5d36a1fa069971f854b7d914fb2f1295e68b2c6fa91d82f7d287f55ad493c87320bf7ca2a5d5e79d7212e8a540c166b588dc03f73b83be060525b367d9f40f5e77e7798c60b6499767586770722820b3b9e6013cad3eab5fe5de96089a29f34919a2e9ebcb3fa03a3e714593b7a3356d11ffb3441ab40ad94474da662a71aa2419dcd50668cd5d8a9017662cb60998b34ab5b7929c58a94d5e133ebbdadb2b0279543067f76bcc4cb6d7e0a5edb7625467e3ddc92a01206e1b8dce69be31928687d8af4d26633a07e73c2830d5299b878977691cf65700b65b6ea2463e51b6136888c544545e59fe8cf190a7944e215a785b682623c95a79eda28e25e0e1b91b49ac89deaec3b14a3c431d9046a663170111ee541d81b43aa91f29dc147c6fc97739b3a63fad1ca84843d0a65b8d9396f28e9b11f9a41453ab18a2309ae8db03253a09fac8f0cd634c76a5e938a44719660944a95dff056cee43ea99592c3899c2880d7181ee3dd5c04baeb60e1369a69430a66031e3cb10e392622f5246a71761760cf417dcb40ad65f60704fb74ad26f26c3af7513a42f806895e0298c25c049187aa536e0eba21998912e621846c2ca0e323744ba930a29850fdb385c8241382296ba28dd4df05ddb1e61fe525949034b59929a784406de240f8086b4074825f419d5472a28a0b157500be37e9f64897db2b645d3807c48dc143266c99e7cc1638ae278772493a2a4ecf74e526a514bc9119d7129c5a0d115a450ccf4dce05b76d4b6149fdab028006df7ec2209923117abf7578a082128cad42aa66b69eb63acee4456bebeb537ca57bb3d3487f95e4f06c5cb29f292d3b6284e5a162cb83151cd9ae56aebbfda150b7edd5065302ccab70892733a1e096ba0da5f51b42764ad23060eb197d5460425fd9c7a26e7dc3cfd40eac3643539feea72c9ed41569111a7976d2c345ac2183fa2271b424526709fd9aae558a23a5cca29f4e2f31629746a71d904612e95ad9977bbe74fa32e90fac62625838cac49f50e5aed4e8879e2ce2e5651c4f4ba0c96583af9e1612b5ff1a6fac5027c0a308815e592308170b915b4a2de1e8d48e9a5730680ea9db8f3326c430241153b3b218d5347d5c843570cf80ee813871ae10f6b8ce4ab7e4c5197045e85b1cb4977f44c33eb85894b6555b4bd288a50c1b656936841048983c00a01631f10a84522cd613fed0d4beaa4aa4b3e9f30c324108d909e59a80150", ++ "slh-dsa-sha2-128s" : "0x47a0b70170dda85f843607f6c6fcbe6e6acc7c22980c108996a3fe72dc9f61a6" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39c8813cd3b34be58eaab900555a67486034b1923e0b00e435661230cab85f07690a5958a5f5e9c84f033a3dc2039a5296443093fb7fe8d41895fa73be3fb34cefc6cc36750d534e6a3c47307294694729d6cdedb633e8efe8979a9aee486eaa66136e342c578761241192610185feb2d3c196bea0e79222437b6a8e08cb09778d053b29552df96507b1cdaede8e9aa7abc18902f29937f30e7cee6868f349f7ae33738237dcaf86b8e8e01238f3d8ea6fd4090a8161db65dabeb5ded5499e8cc8a5b32607abc291b36a4b34b327d30cdef18c1825232e69a2b09d539ed84dd2a4756efa64f864c563943b3db825824f294c1bbfa2157347b0fb0e7f8a56ec253b39ca9b6cb1ef7d3d7c93a6cb220a7dc50c365905ea5a71575c3aeab25b33523e4fefbaf66137f45c3d96db719a12d2e2d42fbd6cdda58c5a1b958b28c2a8f2cca297871a147dda92a7f008a359027a9288e42ebcd6ea9542f10b66dbbce6e7bb914206122f866d9adc1c89cbf8bbad9bc9517c2ea9018b61d4d2df9abff1dd9f3a0a6faa72a449af9c97e8c4090f3bbd9824298e61599c13c7eb89677c0e845ca2907c728d9296c24e96b6a348dbea7cac62671c9a78a531463614ce321e28ca2f093094ba5f69881e6cd766874622ca769ea556ae757cb7f9546d99f5c90c25e7b8e14f3b7f270861398800b0604ec2a3374659277a23cf6131c63148a41b05b3c06e2a98a268f1b9f0df7969addef17179ca2261d3c229ae3db0c490834564c45f7b8ff6d3bf70784779d75915fb2e2d5bc147bc941b9e249af188f63f39b028547cf080b7674b228e20a600e3b167610f814daf105226f3c1ce5e07834fd33dfe46315546e926fd5be83fd4d47ccd5bb8ae736ac745daabb59c87b9edf9a45c9a1d1617ee84e588f27d12235c59ffd9", ++ "slh-dsa-sha2-128s" : "0x0e8f9bdc22cad3613ed07fba30ed04219b9528f9b657119e2f0886dc71cda4afa7d462fe8bb108feb58d998b370b2f7e162390713d1a17eb7de781a604041cbed13d00effd3b24f2ff87cac74f61e7b7f7aa6a259dc283485179ab4bb966793be018c4bbf4475bf7a69e600a37246908f662813813d4b0f4f83757f4064c5c0713870a0b98b5bb99025dace06100497fda8c73d7385d123afd4953961066e7c8544de3fb620ef5e23174327c2b64089b3fe6df3eb86e83b12634a0c9cc0d7844c894ba6d83afed6becb6f5abcfff397c5cea8064e5e153ea4253abe599dec1614b449329ebb25861b69a9b22228d1a03ba51532ea64ebe7603474a15a2806d3dafa29d57d27c5fa894da673b85b4674ce835fcfbd391d328ef83504101432bbb0c83d7be462b265911aad862118af6f4cea4df0f1dd38969c69428fe438d59d22736fbc7dd5faf6758905b26ec4c99d71e4b8fcc562a694ead91569c9a916df5ad693cb2ad0b7ae4c4f3c5b7322f56612c5449e0339dbd367460c76ab89b6f44942cd33f35eaf33c2ddc0c6af793556d5202fd1fb0f9fa1b7ed45c6ca68d904e476477b71a0bc6ebe248c9b4585da0c7bb186600691269bb4c836667a6d73a455b97127d898b7fae17e1acc6dcc3bac3ecb14da131d5f8adaa64b054e2f569d9bdb164792038e107848882de9bbeff295905c2af68d4c6dcc8cf718c2de872ab6b3d18e00d527166f8ced642281302e2acf4cf4489072a2dc3d55ff8716619cde494be1763dce925438b33ff1b91b35eb511645832720ed92552d4880ae53ff6516cfaeb1d48c923648e502e4038676f7c82e532ea713c6b9348c80ce3c5735f437491d3a8b1765294868c14123af2e9ff61e394216e630c71ff976072d2a1c50cfd8ee1ce27aba5bcf9aaed4a51521bad5e5d5e66abc7a95b215fc8004364aa4df2b8b97b14e3950f521b6327a55fdff9139fb0bd35237b022e3aa128d36c8a60f4621d25d28c59a97418c7dbfc15d900ba626d283632732631ec4a948f66dd9db3bee8c2cf60dfdacbb5ad4c0b2b31f8428868cca035e79c95bcacaba40a9351b2b44cb29753b6b9da0a751bd5af84c9094d5fe91e97501d4f075392290e8516ed5e41b41b00e09793353707fe5c1d942395074637f3ee0a0f105876d6f28a74f9558c5f360e98f047a99af35ccedef8d5cd299365e81e7e91f28a01eb265219e21aa7f7ce56b62f9d2a61560f9fa39f2765f5b50920658100a638aad03482a687905cd27dca02f1deffd1bc49a1be1ea7ff1a505da74fd932937d8f6a8bd75ef456d5f7b71ca5357bc66db6cf14368c4faddf4996363251e6a6113ec64d642c319dd85830d8b4c7ee1437ebfefe01f27709ba0c412c266530f5b6bbb005994774e8935f1d91069f9e7a8cd2bb7ad6527768473affe24709c10294eb588aafca85b379bedf0b142b109e1b186e635b0625c4e59576266acb5f71040c44035fc9480b13932bc657cf332b12da1cd7d5c3977f51d5fa742974cd256e8e3662dc698e0516d615d0a05ea9caf12338d0dcb6151e07f184c9cbd5e59bc40b12ed6372e2d6bd42aa0eb6c3c888f264a8c0d3332631d4919c921cdada6bffbd01ca5445de0779f9723577ebd7e33ab0e5f577843aaa6cb8cb5f0508c33b63913a44d02b76bbb1eabae325581738fbddb5d4fdef8dcb8597bd29c6ecc631839118c44f66ef8dedeca65e58941c30e0423c40bf064b8d19d28dab3787238781d492720236a7ae0695ccc867fbb1cf207ebecc64f84daea66b6745515b9ac9b725061bb9958ed79ad6161318a262528004401633d47a023c645683e36413b8653fa4864fe98c501197c10226b1732337842a1322bb788a00a0de86758139c2d9ea3c5b26bf5d7a4a92cab4cb686c580e3e6cca488136f0da9279073b3dbef9519168ba02588fa29cc60d02273805b425b919a7e2e89c9086609982163e09d5f6eb9c66267ac7be363aadd4617d398d4bdeca37a838d650b0919faf13b78642a058b1bb96b2ed1482cef9bc6e8b2e061e6815936e15a9c754353aaa786ab141e95e5f6c464a41b8bf29e28e764abd638abcfb342b54d08c15ba7e24e6fcb69b844e16cdb5cf4f50db60ff0699f969d8e68511fcc9e16a58e100f80671af6b04ff3edda3a4f05f9183c0c3bb7c1061fee2d3f04e33fe75f1354e6de54f582da914da0138e8565ff45ef52f638cbc33a24bae863fe91e58d7c5da34273438f15e10d4f59db16e505620d97d3fa4862a4097a659925d0e5f4e073103ed29a600b051b83b1f3a21381f4b871c18d262d7e43842c34ed80661438c064aa2fd858a8f3bcb035b5e942baace7b50e4de5a73d5c51fc0843cdc163958a62d333078f4c7d883bd7055a602e04c853f9215c9d7f798403c007fcee124cf6099322629c449ad4ef84b7356110798dd87aa4d98ebb47abc6cc8748dd381d588b77db7f4e7550f6ee1ef4360dac6d6c7037a65297d4a0ea7999a5632b90ad48fba0a916846a216941fbd13d62ab36e1066e24990c19592944078435c52d7717b3556595b645cd2359ad151dbb67e92b14168cac12fb2cc5422582a50bf6e99f116751171c9b78744ef719282f1b84bf95b4092514f4c68fb82a1526e0942ca50e186632cd9b0b8b8d91e84f85e35f30f815601798fcae676da6a2d38eab62f22445099694804a36a34142150fb795afb445e78c241f0b645209037a8871cb5487c975975ac997a540b709e3df6bf208d9d8017f9688b152c9ee2b934f65393de8403244b7437108e6d8c973aa723285555d9eb92509b1747977105cbac7fc33e658fd51cd374d21fc2bf229928948292c1698db7934d0f9be44b137514d0a5fbb659bba83861931e03698a61cd20a449d0358a5fce7f288e18bb3eb62b7ba0ae75feeec634fc90fc45ce45239c5e3179309f0c202cfc53d9f42a617f7aaae586e7161a0723ccebb7e8586cd40e1fa12d3ee89b400dba8073b0080ffaab1182e8243afd93318df15bbf3ce179f21804fbb8882e855ef9e0739ce1536d8ebfe9856aefa9874b4e102e705a40ca4c3ab0ab7df63ba525189b518796590035ca780d348de49f0ba8f28456ca6f3e3cff7e761d961ad98b8cf01e855797c88fe2f811e41e787f3e4becb0ef42ca3b9979356020b447294ef295543e0ef512a247e4d356bfe3deacca8ddc5255e6ad047121eaeafe61d71e7f31395cf78890add4f8c688e4eb065479a63ccb3d0c09028bf60c700fe9d19195c26fcbd4130e6feceb52e192a2aa2343c05b43b276f51a7c55dff7233ea512942291900d93315438a96af08e25ea5b9ce656c54e71ed60d1eeb1665ddaa9e42378c930e21d93484b9a4099b7ddd71d983b4c42c6b1f62907ce84b24321422b08b847f1ea97befaa4ec30a794ad7f340210c800cf185ee2c6c72e844cc5671964e1e1ec58953500f149f0f0f25c34d5592de421c2e31535040020237b907e86d753094dd4532e1ab9d821e7583d4a21e1041fa7ad711f29ee3721a2aec6b0c46866a2de71ee850d8122f722898e533848e2bb851ed24cff9ca83badcfad88a171b4be064007aef4d759d93ae9b67b446f3c6fe504f5b4fe851b8312fec86b46ec3cfcb36e0f682e65e117702b888ab8566c9cc716a3a86106d2323c0f7f20fbc1fcd110bed4492a750befbfcbbe16820077dee281bcdf14509b93137a3998b2fdabc2a375b38857bed12bb8a9c67bcae7934d02d6ff89620fa8946c8aa524fde99c12fec0e25bd79788e2c15fc31fa3f27502cb952b9f9482580cf18ecabd92c55113ec4c4470c4dc06d8ca27a10474594eff708209e8f376b6f17915c2966dbeb0e35ac2f02419692c0d232e133b3907059d3a56ff169e7e61915c8b1067e183337b40bc1136241e862eb3ab3f2c6a72b18511c4107ed063d1e2303d0fe6842fb01c204d1bffad7e90bb44a365e62945a7f631811c9c37ffa5ac39c16b4835798686da5baa8e1eb6aa76b42f6b86863c30669486a175d6b3bc5bc47c5eb05b240bd921007fa39506c6605bfbefc9c8c493973bf3f0767817fd8ce126a301c5b8fba79628a9b3a03cad0c491a5f487dc5e89269e5d3bcdc2998a136a012486c5bce2e6c6dc595aeee2ebd5a36dd06919396184aafb2301d1889b668c4d701c7ca01b95f9508f47d4c411cc0397c244ed4e3e3ad7f97d86b6f8834b13b1b2df0625e6b4eae9e439815e65baf2da767d3b1700fc461fad6297fe4e8ed02bfb65b750c2d2801b7308aba9657df3c3ed7d548687f55e85c22343d1db343bc2dbe222fb76fbb3cf490cee7a99ab3a337c626a148fb303b2f8651651588dd4859fd65c95820ee2af85adf4e8fc2c03828ea7427e7c6b0d4a1b0ccd424df6d1450ee436c01351d8b6bffd4ba072756315968845ab7976813d93d0f0f2be1c00faab3ccafa71cd26c5837e87292870cf768c7837e18ddc3c513820c660870b339fc42c5211d33d892ef22b475cea3be20f5e47206efbfdbeac208e26e97c400edfd41f063aaa6b85a0cf86e23fb11274b405f4f796eb10cb97e70783909ad492ad9207ae7b3d204e59d69c886f91bc82a107d0be3ae85797a7cba747b8e2640ec49384f53c785a84cf8de37dd4048dd4b879c58768bd131ad7226506113c446fbf13d769794f1535d58e9c52e23c1bd55e13c647d304e297d968c759a378f1d594897a026e3271aa6b4daabe174d6a35665b35193379f0ee465df7827299c18e1012ac69913a0a5bb5142e99b051763de3e98d5af8b62133e25b32f4f12b787bef7e21dec42de8e4d99a0adc8f365d8cd3e6a5ff3064ca18965ffdc6b383f7ad08186d735a099bb0ee14506388c1a37f7a766d286d748d404457226b952ca6cb3f317b0f4399006b5b8c6eb89f6b8cfa023cec4d2dedde3e31b9a633c0888989b44ab182a5aba30ba78640f477ef1202f6496fafc2a18e283b2e4e8bc60415a1c9a7fd68f15cc1ea0299e3b26f5755ad9f13481a0563a524c6735942f5069dc1d6a070b3c3698e9c503f67a11efe59413e937062668d3439a5dbef197d24ebdc79944b17c549b0648af9b1349cad83c2a0a9e55fd893cffe2aff4626662ebc5014e70baaf7cdbbdfd3f92fcc5eed863fa8afd87f88873f726a0a2eafe41fa81edd5833f5520cf93b0fbf0660e48eb0258d313bafb87dc9b0d0d9349f22fa2d960238f67457ad644bdc60fb5eafd1c88dd2a74db4da0f723a03df08af6c64883f275395020341d9dd3c7fa049ab2bebb4d8af2bb8dc1340d1a80088c4b2c26bfe7314926ee64bf239306c05dc2ec6e6c5e0ed4f6dbe51f5ee09533f558d29ca6fd27092c20dd892c89c83223752006b23e5abecfdc733aaa59c8549e89e5ab0eae1b44189f58cf9cc18de0c2a2f46a9235fbe42c641a890039cf6aad820f1f844edc24e69bc3bd0c22cfad3804d876edf5491e88cf891c347ed5f24464f2df439bb30742e1f9a4a7eabd9346c6a5f93af22e67becc494cadac82cf9cb693acf44560672cb9227eea2575f90b0e28431684ae12ff2e86fded0be3a099f9ddd32a7285531de8963c9a03355f1d9cef88d7ed9b842d0066ccacdb698d42ff9f8a4f000b9764a9aab1f3146f9f95e6636fdfc9ef91c4d060a54ed7f32167e7ac50590dae3a2904d5d2eeaeff2930bd4cad7166fc17edd2c30e6738157eeb0b441491e5dfdc17a7fbb2bdc6426b2cfb26cf2a7e20013f1b3e33a6d6821928443cc7893f7e4a5268a8b94a6ca6097d25be17b214ea4301e9a723194983bbce286f4363a53afd9e94dda9c761481d9d20c7687a2ff85d42436b9d557d5dc6c5e24ea21d5231487df9fc7986100664edbbc51ad4921c5ec9fbb407ab33ef5c3b3bc81f113e68f38d73f0db0261b656fc344d2d23b93446845d69cee1704834d98737848d405f52f5a7bda3dbdfcd3af3881484579d2d2f3ef976cb35c9cbb76252f2e00019363273489b39943d212ccecc647413c56de69e0087532223cf9b28ce3f77fed30bc3ae6a0842b546e0e1a8b6f6ee1ca0ef1b78c3ed829af817099426f94a447f67229cbca3c07b7a8ce547c5eebcf168248e0a0b9fbeb398e5ed2d0dcacb441f95f9e30c108c725507e459d34c1ec01b67065e5e202d685502d6ff015d46c20bbeef1db38c29df7df585b95d79f5687474e71fff162c0ec0c96c94c507f8a0292a8c32168dacd2fff78b5c7dc145e10fee1b25c478172af8f3ea132fdcad75dc22856deb2576a5ff3e8911842c811d1d57ec203c77b82da3658cbfee18d140ac341d38a30f1af298cf60f2a88d0dfbd3e079ae64a07abb4947cc042925fd5c64bb5d4467589f8c495b0097073c081517bc4504dcd7442bad7e7acafc894fcf34f535979364cf5e908a84e0e141ae47e2ae4dc95462b4f345b12b0629502c7bd65579ec66b2d0a951302ba6da1d1176db6aa0c0ea1fa88195dd2248990fa4aba88490b1da4ea405649203f6ff6f734693f40deabdad59ac62e3296cdcbd74061474dd7b63c46bcfe6ea2b0ddb0f7e77fcff3599892c82425b05ae7aa1a2ac1dfddfc67e11921ff4f2c8f6297881dd5e38ccc4076cac8015c59cdd6023ffbd62b887b33ef8d917446a8941d9563acb66a6226fa4d3f2cc21604c080b3f83e73c093d8f2f7067c392671020c7a7eb6fd0d97af0d63032a3116c408b708d4b2f711c1134b88a91aa359608550f0049af2bb97688afc4352a45c4f6d30d4634e70e82515ff1d5f77851ee857e42b486d5e1f3e0406227dded6c5f47eda30d94f44d978322891dc729eb6ae95d29d22c8a5d649193d5d2aaba782fa16ae488f645a7ed90a566e182f97bc62049724f4cb5fc71f6bc7be57f07a7afb9933f6706cc83483cd7dc4182768cd35bc42f1e9b54d5454d3a17e734475ff58fc66d75419d3d122eff05f7b0548188682f1318ec32c5bbea87c8624cc1e548bf18a6b102e7a43e6bafb579e4e84275fe07d8c63ace449a44cace5d9305ff756cbf40e5a6a20334d5b4a74ab0483e31593f2277e90341fa8036496c2bc6d2b7b10b0b354c86d666d65cacc593d1d7349e71b0360d823453011ee16b6280f5c048111b99b185af99e9d901d4eaffd8a96b1ff394b66208ddc1e7e53420fa965bfc4e630d73ad97b9c5c6ea884c619bc24ac3f46234e7d8d35a12b0cad7220d7a0945cdc64fee9d8852bff872c43f359e7aadf8fa3de3551fb716704af68a18f79d03b3c7d90cf21eb4bbdcbb4004f8ba15ff0bbd2d0918ee78e9bde980e4f3cc13558e6fdb40ca71ad2c10f5e5587784bacc6b925f72da12528216895e0ca4b350d078fdf534fe01bc86b45e0c8e2b35799d268a457f8768ed782dfb56abecfd2b9db00cd10e189c6164f82f5ccab423277e3465ec72d76b696cafc1cfa9a7fe47d142fd6672d9c5b77751b40801af07fc53b1c9da0fe6981ea75e066572f7272baef8fc54bfa7cd71cd0fbc5d6cd717e9aa07808496ad2b4b4005a320c9312c73385afd61193581dbae99df6c25f1b9da17093ccfb108b0a26c5ae4963183533ce2f0ade01bf5e818af613416433578522b1b1e5aa7c791570c8c8b26ded266399116f5789a8233fee128e54ca8ce63fd56c1a146c3006316d200e05715993d1d97907ca83d7fd42ef7e7222eebd74f9c86b6cefc82e614a53976272c8801bdcfd882e34d86b39142ac05088a4c47010a71107bc72a380bb3e5122981d1795256beec20a0fe568002d79a4b1577903fe8682f268eeeed0a97861337ffb6861bf378eba1e0957111c7f9fcfeb55a95238005b40e13ce40efe846ddb86d14c9ad2c46cca74baa364ed08da3a3079fae3a36346ac949e2174c661b8801a051423e95dcab6a0f9c965e8744bdd0e629bd3c1a1241e99951ddde184eb8f354209f24c04fcf10fa8f4e43cb55c922c28be041213ddcfad65c86e1ab9b615f91d5fb11e4cdec5b7e25f8e9811c82c2ed457d012e4967b555f228baf4f1648854c624e0525e36e5f4d1961bfbbc3621d79bd6bea72924d8e0146d0965c239a768b417ea4c33237a60fff2760a9dbfb1113a37b01b598f3e06987d99518bd9f1ec96cd7050863898c8664f793ef29114bbeeb9afab8ed09358d1227d7de2aaac0ab2391cb2013028ca5f4d1de6425ec5feb17d95df358572fa27fcd51d14c363a36bc37c7497a0f964a6c004561f68349f828d30d4633e87bdce6b6d92384c9c1c540c8295ea621e9a8006a8d7c163b988853071e06c78f1b9a0246db052e8484a65cbdced3a587e45d9e2b49a5501590cf768d08b6a043971110e9c9dc96abe855abbb7aee2c38bbb77e5c68d61f01f2376b6122450117240532c7c840e3739395dd6c9e80a432423fc5e3a6dce9dcd58eb418e16d7aa507b4d67dd6fe2af4042a5c7398ba4f87c650926084efbfdc9430a4bc2be544880ecdf7361aea06a25e4f592104b0d74312f2729a4db5876b675bc0fa68f6e41e014b7caaf6f49b8ef704b6243df410dce94ad2c51d328fb90b9cf2f5df645015f489a262f57a5aceba40a56d343403b660928cd7a9d165f4a5bc289c0d28f33dac85c9c2a5c79b5ddd22c744a0388a5daf4bab84d7c77685053c912c9a24b5a0664c6253febbcf552c4ff38bbaf2f7e0c9f06e69a91cff9138c2745b99367e00ff6b6a920b1812e17ba44175c033df0e58d1b5c0b7d146f861b62e812ecbe99d638219e0dba4dd88089005977bcc90634c4dfa95f87370d905d32f613358fba2efcface0b9a414ce33b09e271a647b911843933c5d1008fb0717ab59739eb8eb844a4b34bb1a8f635c5895afa285ddc43720e78dc81eee7db822896bd9bd6ae3e7fe2988ba560d58f02592870647b94aad1dbb0d0cb60e28135ceb72e0a6f4b7893a56eae83f9d9a4c549d53d17c6a00f5d6c266d23e7a1d13e22a5fede3a7082dffb34296f8fe9f3bfe525ee1da81efde3aef9b6de8457a10fd4340809e1dafbfb9e2719c327a3c3a4c51d4d5600e8a01ebd5c537a4cd7c4519e963de06de6c83a9b968b01f79e08b5415c5a9d6a92a633d6ae969b80cbb2cf4d6d1ab2c3b94e7c12df27ea89bff4014d92add41a3e961006a194ae3ea4a6b38c2827f6185ae636f6846b1c8401289696fb10c765fa93e58d068bdcd8c9dc95df572f096d65f5de42bae639d41ce7e1ee0f48ba4faf856c0cdd728956d7e4babd6d9d6389ff41d76c5fbd6380f351b05a37022dbce0a6a47ab7168c82c77a2810c80b1882f825ebf86cb7f6d0f54025fddc9b9120802514c797d1d3968631dae95297a857890ff1dee408909223d012925dc08b7d1119fefca7466392a019d4121ea76c8b4c3bd103a820557e4b2283e262af32f1edbffaa253c47d5873bfd0219b8be86c7e64ada2d87ab6b7f428a7d8fb3ae09b05aee71054355eb83ad76c05d836a9f1a65511b1553927ef1b19ab1576d7185af61be6104de1df218918179c6321846085a83bd1217aa63d0b03996ac1fb4018a8ab54fcf635f7d5a8ade95894f0d407e5d4691920f21094c6f632f1661402a0b3351f168f16a13d3a31ad48e89230cffad272926487f36c7a2584c9387623df6227be8c96088db4a21c93b1c88ee756e960f60e614b30bb6ff757c20f3674a7ae7f6ff6a9115a0a6d444513ccc0be5dcd557430e0ee8db3ed5b3e8c405110500b9bf7f6eb7748de4988a1db94bcb16fe33479f64762c53a1e2965363452063d7bc14386ca7b4d46ebcf08489c64ab413ec0f1ddee8719f5fe978d38438ca3059961ecc8480908cfaf139d88db2facb5e7a88a43a67dcb0f97a17f9bd5b09b8369803ccc7ab6d41238e59e43762965814c10c36fa4b6e61bf2e83c0243f20ee8aab62dfa9827aec06f99c5c565c1bc75291292d3113503a202851c26d1a8bde54bb30f0301e555374b71e278925a2afb29b0209c08ecb89601bf612ce811a493abe2bff78e7fd02ee13c5db6b3edce7c87559410b9be3be95465468e33af224d6508a44728cdffde4cb14fb96a0d2ab9c7f597541f9963775c32ac613af9beab89e0ff7a5e35613751061b0511532b10b3947802901505c8e33bae67ce0e28da760af7e80b730811bdf17abfce39d35def51d73a084119449038c2b0f1c86d844123c6e71f28b7038053e279dd11c088dfa11c547a4ce13b19453e88e5b74962101412490cfb68e21d8952db509cd3a814387b67339fd04ddd2163177589146409934f0eceb10db2d90a9e3f6691eb75e84d5e66bc3228baeadcba200f3d11e0cae090ffbb800f5da7032c35ab572de55beea37258bee6f191addf01739a26efaa612991cb2a3c6d1bbb03de0ee1fcf9b7f6c51e452b21c0819a9aad93162eb2dcc189bf355ecd2c3e504713dab24bfe3ed86a4194611029f7f6216cd469fe1f7d35d56b6c8c2045011e238f9cbc0a19b8914d74329e2472f15d0b7d60511814ad2736d6be168aac01868c2a675549c849fe05e05a76f077130b46896735db5490277b76bba43545de6b8ecb53fd20398eb94dd884951fb48d5690ce4bcd0b836615cd9340ff0cdee1122743accfef343811a71c7d14d1369fa49ce47784a6ff8adc26c151edd4969dba513ade6a9b1f009e57c3d6aa845ddee275169ce58e1f04b564ffb6d0eec75f7172e5e8fb814cd702c9fbea8a783bff637db8667d4b6b48a264135bf60acf335936105abacff0351ba9aeac88e9522cf7ed80069822a7db1a5d8221d9492e02ca893e1f15965fb82a80ee2ec491027bbc8906e71cf931fc21e1c0865ee06a79c023929625b4d232c7b3e2e4a4e5dde28fab675391befe583c95dadae71dbaa43e09d8d65ba36d148aa85d1a2a35dc51719ac0311ea72c1237c78a8b1542c59de3b743087245e54d3111c585b5e5e7642f625c8d44c6d9cff50d8d071f6fa573df937d9e7457302d8b293d8fd94ebd3023c55f8b260c3454e93f58f16d0f451189bf41c9f9b91d3c3918adbf98e4ca5aa0eb6314041521ef880ce18f0ce296721a06b329bb5fbb3024e424b46400e03caf0105877465285fcb41a93844fb90b7fc1924883ace6ca8a37c9905068c633761163affae39d0ba55b67fdc6bcf0908ee3a42af286c" ++ }, ++ "transport" : { ++ "secp256k1Address" : "0xe23c5bba38d809fcb2d3384f210e9a6405beb498" ++ }, ++ "ecdsa" : { ++ "addr" : "0x48fcd978ac4d42ff52dd81fcd17e93190f35e5e0", ++ "claim" : "0x2dee91bd2cbfa906aefa3a8ae6e2de773f55dbd28e77bc329d28215183068585601ab9a7f9ff0c48095407474d502a3af3f059a666e5ed1e27468466d69914e801" ++ } ++ }, ++ "1" : { ++ "id" : "0x690a7fd66157e5b777256ea5214f634f61b3a72d", ++ "keys" : { ++ "falcon-512" : "0x09a6d094d9a3a0865864e9a16b477236f1ca26c888fd0c918db331c87a478519c41085cdac7e6cd0d89190a41a3bd6f4d6300995d591f5e22a7b7147caab1f9c7a85a4ba74d47c7b227326ac17535de039a7e604225d3daac7f75b9544654b73f79f5825825ad6e6c45d13e6d385a644633e1c8806d3a0a551c98f032583c95fb13997e52a6b02192d26b5a47fb22ee52999ec92b75c70774a4ae0481a79113ac72346263e53d5dcde708668d317dd00552d5a40ad47e59a501b10a50bdc52c5c2b2c920fa0e3dc9b8eca54b10aa5ab1168c88287dcf80ecd880a8fdec85b6d63a15b9f453845421a5d9b898e6149b60454828eb9dad6442ec62ad27ed72215014f3d17539085ea3f668b0a9183ab96e9db996801c72a0920b02a249911924f181e8dda515d114beb83b075ce7e7a0902a6971e31420ee4921f5cfc123f29dc7775017aefe99a7e326119cb925f6f603ac3bb137313609498d5a2000c426cb332c82500dcfd80d70a5e2d156844a683b313266af6d60216bd9e9998bda53c0028f387ebd21a5fca6c0607d54b1e95724746d15f25f16e45845926a83c7598646a0a0d3a8f8307c1a401b823f1656ca41e5499684150a954318da076af9131fcc93361d9bf0ae035f617e02cb5e1224a982b3591b24013ff80dbb61160d2ba4ce85a4260c8a3a3218e0ec869796b1b04a82079cfc0ac26da03b04a11950b2a3331ecd0026ea9737bd20e6ea3045b56e3c71278d2a8c72c8014b769da9319e19dbe762b1943e5a4be15aa84d0da831eddbb10bd05f35d55b6211d02a61c5d9247e69cab6c112acb568ea51f345a5bf16f84782e04220e217722da71d634e1a68b796376c8a49a965c592b87d06702fe42dac12da108d24ee42a109e8e4cfd3bed6ada5e3de50301696bab0564292864f1b9f47d5a53cc0c5f9cc3d57051065fd57064d08764892ef4c4a92b475184a4cb4ce1f3a0e6da0402414db5a9db34632b9717586e799b06e870b81a330da7be6a45ddfb000fd337a24a29e164449f96be015818c53aaaf09b9a565d7d9d735b9493885e7cb49a5f1985977cd6824fd62f51d2a1e60289dbaeaea148a44dd8876cb58b8ca2f29f6455f354e4e76aa13290f2979b78b22afa0e65c696c21497e94bf0141ac6298aac70b5ea843848a2264fc057abd3593cb17465e06d41731b7153b71f8f0f7a06d362fbd09845f0815794050460b41ad003c9396a86eaab240555ac8c75f85c0ab972c1a0b94b67b1aee2fa3", ++ "slh-dsa-sha2-128s" : "0x2b2fea4a0edd5dcc2f653eb2dd000aecd87deffbce8818aae72d7862b506bac7", ++ "ml-dsa-65" : "0x00" ++ }, ++ "pop" : { ++ "falcon-512" : "0x3968f2999d69a9c28ae792a90a47363e689bd4b349e75c5f837181fc7b16d3d04489bbc32252d750d750417770630c5b65b88cef918ad23e33892a58458e9e63ea591596d3b898f65e1a5be3d36650c3d9834e1ec725426960d337b8f25878525ee3c3798b5afc9add5bec82c8e139c59738aba9ed5f42d11c886472e81cedfdb5b910eb73e884e0d4cc218b87cd9bcc0bc107af586c65b3949460a25892d9607efa341f232e478f3c9fc2d05f324ee6eb7bcddb72af371d47c36856f488872249ffdd322d3de7d12b62b1ec595187b5b363e36cc714b765f0ad5616488300f6e56811e88e359365d5698ab123b917bb32f56566958b154f6fe052b894ccc1fcd99d65d19e8117a8ca4887e01f36f181461a433fb9bbc1790d8b14e34a097b149f0c5c075ecae3501944935f3caa76f0b9370ebe6b90390b4d059f9029ee4af98dad33b9050877d49c3d4f2beaa4b5861a21af95b8c52f9ab4b0eb115357f5b1d25fb66a36b9baaa4d6cc5a4f5fb5462432bd82734d7393cd22c68f52493eb3434c3b88fa255baae5c46c650cae17ebe59827cd6645c6d377b3cdee3aa6a758ad3a96d103bf6ab8ae03b72b53f3aebdda359288c32ff5461a158962924a97a24af29f6c976762e8de9363485ada49c445566e71ac75379aaf7bf190a81c671115e842b5280a05bfb2ef3724bb74487068d5b5ab2d089ebea7ffb4381a7e96233f0915f295d3b71db872393bb990b9c74717bc3d72f6271bc248e54828a1e090f6da56de3643b083e9695db7d0a32bb42355e245e5cc2ed57354d82220b449e10cca1cbf6fbe796d141591d6f71e4eb6770a3c7dfcee509c3c28f2f1988eeca61833b6681e6766790c2a6f043b4f67e145b908ba7f03361cd9d435d054e11edd9667e4f9d12c2d74f2832b619", ++ "slh-dsa-sha2-128s" : "0x39254afc16b1dd8d4fbfff766819460253653dfc6a8e29abed55ffe91325afd578ebfa2dbe74d46b48b381e69d269b5bbe24ca1b85767bd71c744065fa47c646e3603b44261731b50f2d20a7a327e98b84c5ece73697739c8057f99d6ecbc54cf891649fa78b7bcd824972f3b27820ffda3629f481b1193b922cefc907bde3ab1c78b5ac97ff26986f3a553556d0b158e936450b4f41bf006c90a9758e0efb327f67408a7b803ede993522cd9042db4a672c89d4765a0fff8c6e8bf6882a8de432229dee08ae13def90f9fd0a40c99f3d93873a41d74871aaf407b0927a817b476eb93c645254bbc77d131e0bd35a2541248172993b1064d5b26b921396c8c1664178051810961039b15790862415338806329a45a266aece5904312afb1cfbeac1e816fb96256fc6e2b059c25af1966b0bf261bfb72afd8652feaedd6e0e4bf829a75188708ac9c623d4d6699281913bb563b96818f9307b66f7cf4aa9591e30c65a0b0885c22b5d17ff610f40bf2e0a9a32173b2fa7d66c14784402885d84f33fc75afd8f743cd10f5ad6dcce5b33a8f0c0365de2ce1b69aa86df2482a2c2d3746c6f0ee4e6fdbeef5738d809f6b0ef3cc703b0d29e93e198b68d62a5be657e69c33459fe4b163a5ecd72a90f1e53fc00bc8c698af7ae3cc5b07e36cb74088066a54138d6df4ef6e159ce5924b6903346a5fe115272cc951e8713d4b6f96f78d67a542c3bb402e69bdb3c2b06e189186c227927b2aba52b29c14e837b37798321fd000ed3bc0e386ad6e5d3a48494f57109322f0a87f7dd752d862dbf772498154804b09eca84c305595cc1e6654b1b2e94d5b88feda176aa144d3895a249754bb2ea99b2efb4f61b828f265638866a49dd3437c70016347d5aae64c79957ed394a85cfe06b10b98b6e83801728645529537a1102bb04ada4226688594cc28aefb24fbb0d1a60c7b826dadd23f301517e862c67fd88d0f6a5ac08e7f966ae375b468e57f01521b43fc24c761838c174ac106c4e1f435b7ead5e79aa1b303222f6b45c5515d497d8e7b05901bee96945652d304ad9ebae2153321885f19e7ad08c9da73ccc22a66c26c4cdc9360c36e307310714ac44c80887f42a2575305ef649378d76d297dc6faa904377b2037618f23b8be496fbc680645dfb80a76bfc060c6b2aee4ac5537e79b7dc7deeca0ca38041dc877b875cab1a297190269c987dcc46ff34e5bc154e2572695e463542be79d61fd5e96a4be2b07f5beb71b882f99de317116fd0b36131a88ff9707eb25594fec74cf76c2859ba6ba2b968d41479adf8857f4b0f4a26f49f0f04fbae0e2f3c2ab6aefdf01855a7a5a4b8bf516f4551a393a33d3920ca3ec403b4d37c2106d777e3d5dfa768614513885d857ce95b9bc3b992808e7ad71575e5e91b8107c5802043b221c74d73c7bbfa7a191945bbc5ed69e20016b16e2e2987818cfa80695e58950b0c1bbb8c474f861d1447161744c75d99dc8240338c43a5c19a8a9f46d80f6b4b6c1cb57f5a3350bfc35a0522f89e3470ccd71a458968c629c93336af6b5b091f569d1fc9492eb6b976376b8ff19ad9318f5cb1361954a0471419b4207dd9dace8c0545e74dfbb19ce3fdb5d456a1c1bff7383c6fd96dde3a92daf0ff5a315714c74711e3c05e0c59ba525c64ebd17fa20f8e143c5931b3c77da193415e6506c2db27e0e773a6a5b5d47ad95760b8d471d06d5dfe000a2d47e6e4e6abe7219750f1f7892f4e09fe88d13c2e3b53dc904ad58eaed856a4abb0c10830b96bfc1b5764f9e4b34b0072be314608fdea8c5005d40ef99806d4d3edb72e73541fb828d4b2adc38855e09e974293de25da6907f5ea97810eff1be37f88ea879e545bb5a70d2187edec81bd57a95c0314df4ad08a864156579d50826d0cfa511d335ff722e246151a7afce94126232f6bac89b13c142d29e7521479866e35b17c15f16ee89d798ee8bfac5868e505031586b81bfadef4aafc2ecdbde649f63e07eb6026d09910d9d3613a9871b5d1523cf5958124f96b5304d5225b4bbb03aeeef87753d0b6ab51a287df1e9031f56f755d3fe5a20f79b7f0f467fa97eac5bc09a1adc6ec285c8f80ec5c184b8b5eae326300a5bce0b1d757c8e4f27ca2822e73745009291f0d9032051e15b567511908f3ec68840cb6ec6018a9a0e30f2e34759743ef0bc9e12c9b32f29f4b70a998cb8893af2dcf17e0eb4f48e7ba367f68aea5516e7248c8be1d1f896d7e8446fadd9603012dc13126878300f0868bc512221154a5104882621f831e60b49d04fa8a701256b3a413b9db4abc5af10a3f8f4c26cd0b3c2f55a58c9380143d835b759bac7fef824515a18d79b6dbd361541047c79653ab4af5473b7b7e67a6755add78d5c14c0a9edc6c7dd42c3d0359d9f2f6961f8930458a34c4f12478ae45c20969c4c18654d31a7ae73902757b3b8a4eedfd16d6c0d22548d7b8ba77aeb4c1e3f3766b6ea802ee9bd92c5f98d00be80c15e7e3a82eb0d100436c398781607dacbefa98c87b3558f363b3ecb1ff313655838f864c1b2e0f6d6369bae4eb8cef98f564108ab2f763e590a9e9201f4e28ef1971438c30f4376c55cfce9b9910f448e31d06c2e456eb798476d56a890660e45616840377ea0574d1c066ae2fcc46f41cfbb511e5efc4b5c60e00e4846e157bbee5fe3bcd77408e3bf721bf871c05971a70cf7a13c782bb4afbdb1ef800a414260243fd828b67f49007eaf60b3e32f4e2b8186291075a0b1c0a528abb9da7974b3b1e8b20d337161ce234db66ce82a88ae1dc880933343961267cb4932b36aacc5f136cb474bbdb5e4c4be4cd74868775d80317bfba00ca4e58a39d04e63bb797de366c45efe2e356672f567ed1f7b2741df7543d6faa7227601eb7cff367d5a1ff320ca71fa2a1a42866239cc3fa5eba400ee4060266a05b8fe1e729908b95ba6aff8fd76b5e7df547df62cb89f0605c1207c869d7214e4e6972ea6e47b18235855d6f28265a737b4f64f0d215943f13d219292036c1cfc46bc61679f034919e4fea80d882a5121cb3096a50f2112eab265ebf75b607b93e14ceda4e08152221bd368cd1503ce375188d23514dd0936bf980d4282eaa6fe8f38f5eb00c34e3557ae363538a2c15b560b9f9322d1f17446e8f3fd317126986afc2c5e9fbb96f8ca7148f53cd75a4b845a28034c8679baf1f5406564b6e4b8fa8e681b5a9d208f3a1b28e84d6d52d4baa152524908d50d71d9c0d11bb5665c8a6bad669dbf303027bd0d534434f9e76f2c300326e25d00bd8d3bb1debe1c3984961c0ea8dc547e8cb83a8f3b044b673f4a08882d103d6eb143a9645a9a00fab6f1167a2c09015d6ff2dbe4aa4025f604a63eb32330f832162b6dd9364f4ad6afbd86c8d26f56d7d9028dbb3051c85a0c86ec0d7961fd6008f87dbe8347fd5ed1dc4c27285364f63650f161321daa83ad41fbc3412bff800c062a78cc5caea330cd58e63ea9a9d6de2ee069732799f52f49d513c658a44a2122b8427a405d706f740600f855130a0ea720f76b3111dafddf0e2ebbd13f60640379993889089ce508b1343f485457cb8e0c09760d3199b4ea940d584417259e41f2c66853ae4235b6f010cceca3859952b3daaab55da14adff0e421e862f138872c2577637b3e12b00384cd32fb3b9c97b0d59e51f2488e379065d79f5a834b076ab5b35fe4c47f2c4c4f43e622527abb8f682fe9f262d2883fce5c9f16b7566c4e078b67611abf72cb8a0263ba12a6c23b1a04458c759f2bdf6dbcc460bc5df48146468073b61aa5ab4a9c5f6c006f54f1bfdd85373f33af29d68580eba4cb6dd88054c81b3bb7f2be8186e380bee0b32a1b84ef6319798079828080361bcc27473a9634c23652ed6b2b2c8f8d5a6721551c780870f1787726b121263e74c9464a76282dca27249b4532e49455a7485e2cda4ccca823f62d3b2869602197a6f1ecfc9d92ab6e231996e603e81e3dc648aebdfb900a3d929502ff0bbb3dff813660c9d5a417d857c19754ee04e50f1241831517fc2d2a71c5e238a944992cc50b7106aabb5482fc7e0a2e6b5b11bb6845f34ede98a18d5f07759e61603de502b5eaabe59a4d2c69f4b0f8e73a9bc85b8950a54bd91bcd0366dffaa0df736dbbbc35d6accb5ab8b22a870374521f2035c1878718d7d3b025838da75d8bfa3ff36b2a10a3cdef1b150abf3b6be95a5c096a921a3eced20f509dac4ba43f2f515af2b65d3b2ebd0da2d7a58500157a666b387b1814d0a3e84f64d0fc44507b0b6792c0c6bd90ab62e0f75b66d50b6f842cfdbecf1fd043d642c5d5b5fe5cb68af62e6e23cc6f0f9b1cf3cbd0233ce48a996296b6609be1c9e7a027cf76615dd11208f1fde119099352cc17e1c9a22f4b71c3e628d72b620f3cb4bd40e4294ff8dfe19480b5b758b874a737e6092254638a222c83aac52fe0f66670454c313adb0dba2b4e95741d27104bbff159e999e23103c00470a7feee6f4a35f764ec81a8ef520cf1e8623fed3c06b63c022e40e7638db269b8add119fec50456b33224c14486f705e5b3339c6f38aa4ba6dec8b098c27447185ca50cd70772e5389ba703a4a9f8649946671a238e1f005aba0b3a18c8ceda9daf4cede6782d27931c638af3f6083b2bf10ff0a632ebd4dd528da3aa2b7a8bddff2901d902b26d518a058921eb0178ef08e24f7075f77ea0c0d0e72f29847ac7826230c0ddb5e7fc8552ff92c007e9141f51384a12e218da4fbfa9a7a4a1bf266aa975949e120db1b6755ff04adb07c66ba9619b40396072e7cc01dc3dd56f7a2f928a82c8906be416f6d5c41354881f9a6c66a927292f8cc2887aee86e90da32fa3bd9d72bc26dfd334f943305fbe4b645df83fb72c565f61860a480dc0f2f3360368ec3715c2c4a312bd2653051c8f29fc14e0c3d1f515e04b75ec02cac2aad8d411306969d9a8da08c3477eb6201bd54c6ee643d87a89c78a5c8ad48590b7a499cc44ccb812866a4c48ec2da5f1e0aac741464b26988459f3724ea4cf103c27e4a43e5a5fbbf94908878894f8b62995aebc20e632d924c82d9669f64b2093cfe023cdd1542c8f9d19e5e7ad6ed7920ba6834cb0cb91bce48fa94be47c1833c6ada4090509ba38defab7d56dde8168bac8021fb5a2aead00809f1881d53d26fa9cbc824488e16062fd9f68726c837234a82d518e3d10c9931295d20d9affa5fd18c0b2dda299cf1d6fe0c6e6959440af9b397f3441bb9881ba1d2df295d12686ef6b0bfe52fb2bef06620721374328551040d2fa434b161648b058b74df2a7ccacd7609b93421f44a136079c79a3e63bd3b4f79717f3c121ceec2c3918464f5619b1a2e83a7709fdf6d1004b0ee51c73e740b20e329847304a82802e02170db386e360dc6027aa7ba1ee35d7eeddb41ffde093073d92899d568bedee914627c8c48427376e7b5d5ebdab30e58147dac5638090e9c71921431f025f1d4e3ba3c68437555357c651336b326c9c519544363d5f4faa91914195314cc873ef97068d928a6b4e5c6ad70ea7a7b09b3108fd5696aaab800eafe463ee52a3f29e1bbe8a968e84b762484a13714ee260759b4492b749c46ab6603c13ece34e301c13bea57d9de706edc839f55b432b9299d2d6643817cd9d32d0d9ddbdbb23acef51992b62db024365ac2db4c432c531cc1ad18c807cf1ee39dcd842aa9a09b232cfd09bfce33277a8ed09953ab3b5d24e5a8a02fb4a02ceed705185880ecc47cb245665cf640ded4015b4afda053a5d1dff77e390c8105961cb3a954c28ddbb9efd759080dea99e94e69b03b928c8667fa4797dbb3cc6ed093bed107c817780f60729036f13346f05491fb837ef1ffc61be7b61d0b7f8dabfd49ec24cfcee088de38daaae6b4e740ab4faf16eaebf89962331a99f17ca5955b15dd1fa493b91e7cd218aebbfaa7d348b1ceea26951209137448caa93fa466ca32eda497a5b9a4fdbd23a10d9742e74c511a1648d00bca3ca23abcd4f18b7cdeb362e020c73888b76b83e70d26ee358c06933f77d1221a8ff0647200e451e971fe45c23aff60a88baf46f59a0bf94e99ab9337b0336ffacf8e79db92067d2b744134cefac1241dfda288f5c6ab293df7469ae0926c166e999ac99c8871e571eab03f82de73e9de2d8f4deea3724f795480cd47e304f27f2567cd94cbed52e06f1f1cf7af2feaeba8b95927eff950bfc26aa0cc3e46ec7bd5d4aa43374500f8cad4f153cb586620b9a0deeec2cb12ba48bbc8655c7fa70ccf94aa6891b5cc8a3c98b482d906d72e9d425301d0cc6fb4ec9c4a5bcdfdd74fdcef68f05fdb78f2a1c5ae32c28c43ee900738f31ac1fd337ce95966b3f557a727e0c3ada6c6aa61219d92fd5cf68fcd9b444f6b4fb6178b9c74238d2575f442a298127f282b5ad416cf6a365a214048489139918f93ec07f2cd864f5482c418c7336ca4590a7da8a20d33ffb7be19934c80b64f4b982a55b129f4896685534b83251d54e46a2971c0bf49ded9b13a77ade3de9a61f2204a46ed9cd7bc444801381994c8ca5a66abd70936f8d11e2a2fed78fe9fe8889dfcb979c9a3f11f2c2c1aa371d1e98c4fbdaa95d58c6b22410c0d3d3460077dce654a1decfc829f117bc407d06ad9ee6aa06bf818ea2f25312b1cbbb5de527ce9b5c5ddcb0df21e3442ffd149b24af5e59eb4d7e18f68b02b26e57fdf23e7af4fde3e672990295c37186ca67b2abdff6b46e1ff106f041279b61560ea2eae64649c65be22f9070c3239b0cf7929b0778c43dae5391d8d3b8c335ceac672376588a34d3b9c61833578e8d5a9e6e9f72748d860d7af98f7616431d1ae1ca20db3db6ec99d59fa98c25a1cf478e1b4a643c2fc9d3e482d56bedb1b7a1fc9c3e788d9de281c7356b82e3c9e1c9414a0d14cd07fea5364b6a22dcb3b69b6f447343822098548e3ca7e88a83187db145bda17f7c48cb00e6ce36d53e2d1e4c169569ee3fa03620a7131bd5c033062bb82cedd0d0ebc1025937b2d85a3cbcf6ef4458a57525a66244be3a62b582bf2b88549431cdce09f6407e1bee83d3fbe205f585cc7cf9c1eaba047a01f51e13bbe0715a9112c451f1daf6074a1af051d8b98863b6fd03238ebe295995d60e7a26d2f95a2b4b0d617af299133bf357518b84e942bc36a88b4030d91a7067e7a2ed7bbf4e9abda8c6887ecdfebda04dedabb9ea833123507835e0357ca1513b471da73102605ed03297b5e3eb7d3bd01c670f992a7f19962b706e8d0ae0f073638d633b34a1229b6979b8e90f2a536cb6024c644e1f7ef211451dc509e061b294c28be188c96246614a1fbf52db8d9a99f7100c878c1b9da98ee9e9eddf7fcb386061ddf46807c60b24d665f0fe7fde205f91021bfb87c8f4c89b5da254d185bda9cc2f48303b483ecbf934575aa45d0d58cea64662f0fda4d97790bbcfa237984cfb45a9cd611b533dc0ea997d191d14d307c68db318aee8f99544fd48fb86f041fe249a14263e6657a5ee732f7c5c9c97a8924bfdddfd75dc67da65042e711a3cc144f46d10a1a9fdac1b1b321eacd235299a1fab390df24acb739d61bd60c6907b9a3827958198e6e2b5a1c90cb9b44cf8db9b6e45f710d7a39c230ec9cd855af797555fb1d73492e29d17da0b6dac59c2ccde0715565efa1f62898c9b26438c60fc3b9f859bbd33a8e05e1d3d5a762bf19bc7c32cf7d4c6bce26fec6e5c8c537608a1c2aea2e1e5cca5bdbb45a8ed048514ef3d298e7dfb9c5408d941ded6220a44c184dc90c922a3ae31c9248c5f31627389770a59f9431fd0139c5ac0f08f69151a75a5a6a0355b7beab6be9829146ada371aa5791c861dc77598f09448af20deca73cf98a399f35c36f1167ba426c6cf4b8b9b8a22b961bca83e45bade098e20782a9f70bd54fb8eb6eda3acd3a5bbb553438cfe37e1f7fabf15729d6bd562cfe379d586181b71b3d3c4b360852003c4363a8d473198130642972eb3434c3a5ca9b497ec7000e821c3419aae75866496bb1b0a9ac6cf92f799071e06809f1f3f904cd18f32629e2093664755803f62f45942f5a358cb1e925a8694998cb14cfc52733c356cfd739c3976712ca7b007e08841639da14e429c102a8fba3191cd36c1c56eb06bf69afe3f2afc4ebf137c617faacda6baf5cfdcc6462ad02f63e8a5375288d0de5700d0f9f4ca82a65bfdc405d3f96fc663658f0aad91305b86ead3b21bd6561a40db0f2c5b0937ba5e1ecbe91e9c50b1dd6bd83a8145b033a7bb6a4ad4896e0ab160e8a52d39d2756b1c8d8570f7081ba217fd8803954290788882befde24b4971723b0ecbeea14d23c92eb6a0d7022a84aca072729d7ab1a88927a25f19a2086f846a44a2726ea26cf1b69c58243e219c756d06c361e1e161bdff0eca10bd30d23782b3374ed421f50cb66c9ee063ca622fa78c8cede932848f0f8f91bd7a0eaa324377c109808bd66ff463a72389c4b49f2e349be70d07fcb56b28549fca65ad853d70df66b587390febdf6b1881cce6c1ca9e9fdbc9f1ad68ccaff97234325d3c972b57ae5723fd73f975ba640f90e717e9284c111b76367c6797399452d37df6b8b8d22ed5e7dc1481a415fadc06673ce4eb6435d31acb6af68775436629a57db7a0aa192310e8427468e8e310bd3426b7ffab00110324c0c7e04ac6649b6f167fa8b928b3fe12ac162db3f2bc355295650fa2d976c64df69a8017034683bb4bd4baacf1cd8502dff20430d48c907107acfc4e29c584cb497b7a471fbde90aabab25290d853b8ebd2c0d49c2c201eca42a68a15879cf391671946319427b237472cd35431128ea7ab6d545617321592c07b09fff93e71596da30689b3c15368a1c3a57890e0ee5752bb4356290024fd1bd2ebfa19f7f3ca57c36d296ae61ec5581ceb77618dde2821460553ba0dd6dd68026b911f4af1be3986198966f90ab757aca2f5143f1937d09c3a08047b797781d1639db4030f9e59f8c5b71a71787cc84ade5a385ebceb1946177a056179aefb49e1f69ed0aa67901b2d6b2152b6c1fd1db67f358093180fcb8f96483fd35a87fa14825d3849dbf479be493bb2d1c639674bd195b5ea3caf49c2b78eb0e953dbf8fb909910c87efc6f9b6592c020333e00f83bea4bdebef4e107798f9a8e89fa5d063d69f88f31a53548ba2406407251f18c3d1ca6e392fb81a46107191e6d906b487469d0002afdb0f32c39873872a49eee649250d4d5d3a7687fde2952291c8ba78fd9b962060df12d212033303691b05eef0ae0e7f31b7e395576708d211d70281e9501618673afac20a93e82f060135e51b29132a0c9244551814bdf399b746651279ed135d162e366f39d40e3a49e907f72bf7c66fcb4ba75b1f447fbc3ae3f390ab4c10963d755ee188a9b0129416161995adcab12177976208e1c93ef48d3ef55ad22bbd97781dc7035c9f5fe25f47b703b1ed50dba311d24154ab05dd88ccbb5a8cd96d4665829c4dca5d5b22affbfd7e842ffe5e87bf4326f957392229bbc893b1fde9e4b2191a3345490d418e9298179661104f70bf6cf9a0094f9d37be98b82d98497573512d8f6fb4b0b0aa334a9120a5afef20e0379197ac7ec78da3688d2c9b590e40fcf866acbd1d857546522788d1f3ae73f330aad045c5bfd59b8a399ae626fd67d9797b32d6a279d42eec3ec8a2888258728f7c329c4efd0f71b730e57f9bd87204d40ac1ea6032a4b8ee3a338aad58c2f3c9795819af4cb652dedd475e5662d9c0cd23e72a8f4e86f1a63e5683c814a99a6595b779e5d715ac91ba62c1ae4ca1651581506ba80c2ee0d3f97b979758cfe93f373873f4775c882fb3b5815b9274595bf50488b935c82e0fb4ae4d078d30bf0843c89e484bf5a24d5de602649e336fb2b79da6131f96ef1b5f82cbd668f4599fc9a92b4e9ffe3468e39e4c8bd90531952327da74a522e479c66b7b1554c9a72a2e6db58fcd45588c9ff4f48be5ddc994913833b668c275174b9d862dbe8fd01535ff2bcff6ea030842ed3a4d105ba07feb0098e39f61a4cbc06bfa153c598c10c5de57caa413752878c7599e5db8482b6f275db2185c505bc0c9670fa0afe37031eab994120acb935bf9dbe6cee6ba336dce1b44732c4267ee77f5db890041e547bde486335b9a0b85d6640f6534d84b3729b3436ac1c0551d687ddd8da9abc18689e7e932d5d0e787ab5ee5f36eb53789b9ba2b71d7a4f7994e56b056d4a042bd2cac79ad12d87726ef8cb97342e616269e9f87493e95dcebdd91763b134019c0a76e8b12789b026ebd1d9caf1930010aa1a5c348ae2e6273c885ffdf8731b34d87c293e77e9ef14709c2e3b739dec85d5bdb8f5ebc9eb610240576435c8d222ae0c8ebe5844980560bcfd45cacff143a5c208add9011bf9770b7803fa90bbaa10f58d856250b37e481f325c538e473dee7863957121374bf12172321b9c99975078e43a0e1e40138f9c31d6dbe5e06fc881de840e64899c0cf342a806916147de3cc342832a9514eae9550d2cd1166e823f404a05b418e5f9ffa84352cba3007f9d37e5b00049d7c099346257fb53e86b919b45a9c6cd8b67cb3c4e383fcfd5789f2cc087d6b459e2a7dc96d08c826c43410b3df22021855c7d413d9cfe7ca79fa860918a74941e08511595fc9a3bec2e2e0c6dad05781c0a0d6b6609837ca8f78b0368b1217b121cd6ced8fa48dc131709434eed65523269abe95f338bc5e3fce0046ecb24dc1ad8c8fa68b5f9263361e4952ca1aee9229811a5ea85c9c4452235639d1eb8105ff88c048beddc0f7efd3690da8b9bbccbbcfeddcf3e3c9e3ea7b46a5b40098fb85a25842911e42a714c2dd0fab403340ddc1af9484843b33c7f5bed80fbecf68180c9b397ed85c51d39cf08c5c0336b149e6d1747360541e84a93224ae88c1b62384b938ae25ce17d656b9ae52fcd9100a40dd7793ca67357f3fb00621863a490373f0db49b1aebaff7284d450922f1e5243bb7fb5f7230dd7cb8db1e08893696908cad4a45711eadfce8b0b42a9aa937cd011bd5c4a8c3a2ec771b3ee4959eba5e4a17545d1c86acaa4805e4aad", ++ "ml-dsa-65" : "0x00" ++ }, ++ "ecdsa" : { ++ "addr" : "0xa16c987b93f1b3c51fa8a9833c8932eeaa566ce0", ++ "claim" : "0xb0c578f123a8a0c96354a13f98c4c2cb8a67541f5ccecfdd0cb6e61aa77f7768157dfb3ba59aadbc03350577f6f31b4083bec30291a61ee98ecb3db2536f788e01" ++ } ++ }, ++ "2" : { ++ "id" : "0xa5ea2fcff9e3cf29d0c6f5f147b67ff24aec3bd4", ++ "keys" : { ++ "falcon-512" : "0x099202fa37d5e165b88428d963d2a224b8fc82ac0e4b3f6a02376f18218d1aa7d0e910e71586aeeaaddc2a557124d6ab4f9a44b9cad02166413cbeb14b364e13956ea326900eb2900802644167639045d76bbc4e051654cff404dccea94402141ad9fd992cef7a8fa6478b3e6f8912886e9edd1b34c29385b7e964f360e0fb1600787934486f461c95d577d2bc74c4dfeb969b4798565ce0225ad27aac052290a44f844ae233e082c97e4498a31117ac9d02f3605c856e2dde6f611812161f89cb3a54dc936ca1e740a6c659405ed586a9a963b11c89b01746325e39e645c72b0c7e4491b36a17d43ffe38d88c601a5976f5a9636c964a012bfbce5f9b371e7c3b38580d81c6e12b8e8f2aac219f96245d35b4f4afa6c94015b055703b8c4dabaea4ce2577482f5b34fa49e56a912dd58d74580b1f94e1d2056594ea64bcdb696b0baeb33c86b6544761a3ead9ba9888cb1ad51f7027ee52b21e46c5eeaf3f77bc0af7efdc87acbddda7dca00b6acc665002c26447e5b0e0bb5ba261717c68dea7f1576462776954d7249c2fd0886f615ad50d53960ca02d581a4a25517c050ed467c7a820bce6250a9ba2e44fd67fb21bac843bb134c95360dc1c50d54b7280a94440d018181a9d6374bc64d782c84471b47287d8ea748c36cb83cffe053cb89a9e4ae71df497871c2a728ef210903e5b7f39550d0331e15637be7e28b3a2fc05b0a9b0c5a06f9fe81263c3a94403d6c288a561288ebaf788bfe271a578a1a795a85e9d452b61ac204b297090617286922376bf0a8d67dd35fd705b81260b7aad30132b965e39bc3cd64d154c4175951704873992a814814dae5c6bc1e89a83dd91144cd1b88f6ce449900058afdc53bb44bcab63d30cbd6df115a5ee8f5380a127a160e922bebf7b408de82514b2e2550a0931e065565e8dfc389d454823a55b03e5c989b09e3791f656794e8379b7b4b1617aaa9770366d63a657f71ff40c69b1d5da518ef1e2aa42366cfa38e448563f6c2db5e3089bad5520ec26105fc885993630c10db357883f588a5a384cd6de688e1bc3b1200f87ed66ba3d4a4b671b2a500a0436e0955904030d76577aadddb8c1ed21b027f198c072f654c3abb086e7f185980f49d0e109c1a82741809f8afd15ee56a887b392c5b172ba659144a7e99e25ba19792d2a3c0ccb481822839c8c70c65c0943a2994ec9f6085b7ac64ce2b35489a72dd6693d25f2329264e063db26ad4495e3ad00f12df8cf914fd846", ++ "slh-dsa-sha2-128s" : "0x686b5dae4aecd5618b95c3b2a5792888513ba49dd366ac39b7431ef403e04963" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39cf29ab9b80215a9947b975d8c6097e53b39d1483c885ff7527d7fccdd2ca3dafc32bfbc0a19c857fa8be7e52e25064d69c3b7dde6e77eee96ec77011fee440c8bca99a45b432b5468715a0aeff9d61375393b3ca40b9140e1a2bc2a52c3c8a85292f4c9e87d1e0c12fbe4d7236ba7921b8b83bd10ad554179dcebf0791c4b593c8a1bae836883d5094499cf2ba41b00c8c36c77a83466c263a0b01e773f08ec66d46e97caf0f9785943f98e159e353f0d91d5ab526279477a5509129f7a1b8b07ba82a1ccb4acd5be5e40de088f2600e06a8bcf35f54663279f04c74838294048a8f8692904d4f9eaab49635068df74d1f5ed238f6b895acf1364544747bb10ce333a957599594d766ac5d1a3ceecf8a6696cdaa95f824ace18cc551e1f4ec12f345283b366314515849feb5bf81fd203a6c73b5bab7c01b5c1131d442dadcb6bce32d6e13c5a3e77b66eb8f5b2912c0938d89ed9e20a455066d151a973e4509b03f5d66ff7ffb8b362e0c09b969e21173693d9977ba06d48bd3b85657119f9dc3533c91965ed81d1eba72b46cfcff285131f84306fec7b271a02dd22982cb6399a9060d286aa18a3f97666810937f8a5667c94959a4c27299d55e94564dba27ea3d98cb3a9db6197c842eafb237649de3fab72a9d56098b5c1228e70dc062617a8a6b44d46b7899dc1e53a77b700925ed1b438c59458c15e9b91fa2c2164b9661a976720eee2864efc5363d90beea9789a6d3b0628bf4695a853251c7f70ba1ebcea06cb35cb47d72d2340bb9412edc49626d6c78be644c4ab1c539d1469d1cc63f092ccac45f66917d89274af9c84d7f1108b1bd738408e499efa63f1a87c8730400ec19f9a59d241032e9ab78670e85e8da24310b13e89ad521ad4fae3deb9d438dd7eac72b79496c7b65061314ae", ++ "slh-dsa-sha2-128s" : "0xb8f14bb6630512c51d227c12a04ce7b316bfc0d255f5a5d1dec3e1ce5f5cc92927070079430990b4364200dc6d389fde89c78649e21d8fd3a17dd2de7444e77ac3e8c70eda15f2247300fd8e37e1e3c2afcc3e8dd674823106b4297ecedc924ca948a9f80afd7ca1bb85dc0e60e1ccd5d97eb21062b2fabfe94827b4ce5f0e396e5a891fbfc61bb827cd305012515d0a182f163c1a5ee3827aff289ec526cdafd2874c457947e8a6c8332ee7172197cde7388303992be248892e727b559c0d74a2c65d46b6686a48f0b814bbf031d1bde17f55b888e7cbaa7fd6dcf428b13ca43f77d80c3804bd2840e5768c2aa17f6dc773b71f83eb7803fd9e1f1a2e3e158f7e823e9667cebe136d333316fc670442a8c662930a00f72dd2dbda9b19c3dcfdd09c60ba55d9ffb5d5b3384d719d153566bc0b6da89d8dd869fb8c4113258014cd48a67a3591d37f9ba767ad70a554ec98bb59275ce163364915051411db73833a88cab0d3fdb7c491b8580baca2bc44a7bcfc3a51c28ae0a1fc12bb53b2b948c571397a348e664522ea749890d1c7ea7e9561596a3e930bca68377e4d4c0e0301472c8017c1fd5702cd6dd4c3f5881ec4cafb98967a57837c3869720268b61f37836d0c9c5ddac850a835318b17758a6f97df4d4966d516ef100b7e61271c45aeb89242ac7d2b8ee45a08f4081727d54cc08ec0f8af9e16bdf6f6d6797b9f5fcff9686f15efc4e8e34b363d562dba239908a3992b3548566a30cf04c424383b5bea0a5011ac620ee384f6363fca87daa30fa88763146bcfe0a160c071d79dd8de0b11e034fddc032e522b7ee47f318cc6f3f2b6c9b6efa0aaa9b9a9c1243750ea31ac01f087d5f4f5fb97b8296b0953a606c49025f5bedba6773804b15fb3638e72ffffe38ac20486e18eb21059f419b0af9071be12e309a953ac82c0a5a620a7b5c850027b39cdeb5d728522a15c1557e4ebc3f4f09914b3a99e291a814504ff7171c23eb825d2df1bad1ff29144f8a3babcc882258e8a6060272e95c4393fed0ad86698554515e77340ae806746ed859ff9730cd718c767e320ef54fae5e0cb8ba331bdb920229d6047a6db8bad147b75d376c3e72e06fbc6a542f51a312ec831c704099b2eb0f801b68631b464ef484eee077cb7fd9ea951a0307e08dc5fb4ed5a6e62048b010ede39efc5462ccedef2a4c61ffdff63fb3aae19b28ca48593532f051c716835a61f2fbbd5c25883f4a85b48d81658b6d7cc4227f90a81e961c5fd8a388c9efb78da1c9bc50d53a41d2d336232e84e3eb3444389caa3457ef9e3560c25033ed45242d0b4bed69fda4a4f1695830c843e63147b6c2d3f9bc2608b0671e59d827dc1e3876e5fc6075bcdf95223f73dfd11d64399333f7bebdda7f5c2838c072f7baf753a36a1ae8987773fd0ae5acec41d7666c84c1125190f432a4d82ad9b78e22d6536a8135d80a3d1715d17a673033d37104857278a75c2cbcbfe0159343dad8e98e42874e2b001bdb469c9faf79759c4cb3e3f2ccaa16bb29d3e4dc81627441d07469dfb9f545ed83d9c20ce586370be092f3a90b18f30866336c6db9d53e2e0fe1f98c655f1961997e41c25089a518f05270ce06cc115b6c2e9c04f6ba9bf7ce3abfedfada8580ef89f2fea98e8a19c58a0f3ffb89dadb05dbdf05c44b79ad5e1d259d5aa6086cb295341dc40ff800b460a5ac602a687d6feaf66393dd2be22264498509c9d39033aaa22eb248780a3661ecf0a05cb6629ea3d91eb0f68465485e8fa3fad3fc4315a118e4eb2ebc6e9b07284697cacf0257edf67c20b7b0311d3094f4647da567385a508addc9b25a66db1f1544dbced87886946989682b2f2db1363dc635e4cc3c67ad83bd311437d22d8f60a2cb7833c952bab293c9e20ec2b44e1f1f42a797421eecb2e9e9f5e47105b9e7f5d7bd796c360ea39dab45ad701eef0a76b7773c55e7af7909d456c213b0db14f985d0f73652bdf39a6402cee104a168749466e477d8a399469992d65656b607fffbdf73ca1bf4976d3a0c0c64cf5d260d6d3e0198f0b86c451b9ff5840968a2b60a8ec286c81fb55741d7bc9714177c9a77219d3a39dc1d6d7adecb7f8f85af366ed653cd81408b509d0f56b5dccdcd1d982d115754364ca3f14a6f100c54ed8ebfce6b0dc3de4435507acb0c4d974ae3f2453867a70d5ba078a17db34844ea410af4f842dd4a9879a7706b18ddbf94c7b43ba137f7f9b8b3924b4d917f8e0262ad10d083c4dd3b99b70560377ad31784a587cf0ea1f99d6faf0f04a909179f3f93c96aaeae014ea1e74d9d7ccd0eb5ab466a6caf8ed0fae75cba902ae05244e0dde35b8c0bdbb3354ac60875c454ab11f49e47e2d180db319a113a5869bad3ef4580bc7402b0d6bac10a7a4e81403634fd1cd272076074e714b14a6efefc902126df6091330ae387e161789198680b0258c341b6f3ec0b09c7674e9ae8f88699fb7b2f88fdf2461e11ad483ee11fe4e3ddd48ede0ef0a1e54a318ae12473993a8456dbbe8b5ded40232b8d2474a90424281830da7bb36091ebcf591947b04739846d8a600946c2b892e2bf3353b09b08e3a141f33f6ef83d022666d380da43991d3eae4e62dd3f9432678e8be1cd4b9569fa2fa84e95195449716423688aa920e2ba1cd41cd5538907ebdf3ff15df27900ba7ee09f3e9194e1d8cdc0703d6f38b2b887a89b10787986013f688f9a355c6a362f4797576ba022e4f1d1d74e2e31dd98f1b617b99516c944bfa5bb474857fe74a09976cc29c71a7f5b6fa529f3e0c00c33c2f0700064fd507461535a35c0dbc5b69d413fd6ae9af49ccc5d02d7abac88ef02bbd40475595176fa3b68d602469a89afc03359b032fc1f0ae255d623fbf9525bfa36ef98467d5eb2f80cf7c72a04b557e40995471c7adb8701409830b232693bf2fe905ef8b1a32c4b8fe3300bfc5654acfcde685547d5c1b0c213294235b31417da91464619822f3535c93549ab4649a59dc3620e7f4a3327c0e421c5d1a28a2b4c3ba8ab02950631ed54690cee35bc4147aaa8477cae505a1d1757d85251bda5fc91cf65772e1b543bccee1a2cd0c26cd33015533a0e72c815be8634efbb50ceb0ec3c8a3bc6c84638ae371809ab87eec54b934343ee9ed1bebca488d9399a1e347b1647d108652243cf2531a4685c282e0b9e526688a3ae1d10060a78467e6804b705c143d073af664cb72ce657a7d210240011d539cb3144e9411758a211238a872eb4be615d4813b64b8df446d2741db7c9f0af2cc4dc83c0febc41adb5d8413b7ce54ed564e899c0a5a4abcd1cb44c84505915afaaf93751b11bc8e96610216f71cac8d3c9ddb7282f0f864400bdee42c3e5645aea1aa5649485435ffec9e43d43e4341d967c9a89eaaea9cca12e2089f3de222e1a5034baa32372582023b5564909fbb67acfd2a40d5ba40de2d7a31cddac717f5702648c0346e197f99598dc83edda7ad335f9e711a0835c75d4c32e3305e4db9dfafe171181551a8dd5bff89f8a9fb819eca7a171d1be47fbea0e2838a1f1d01f4e68c3d0045da0ed7d3689c17319ef5f5d178e6cf1628402c40d2095c91f7bfe6b837d8f86c5b2585653beb650fc29096f13617ce6d36fd6107ac83c7d7f5a8639e519b161581dd58018ace297bddc3421d358be70179b14bdff66f229a50a329bc30b054a95d0f43e7914a9137055f4dda000357fdb5e2afa3d61b9816c03697168cc022f0418ee5ad7aa71617103fe17e7f47ecf7ef9bf779f157eea74c3caf3821791ab628fe8cba64c12d3226877c48b746d725c46b0ccf5a18f869e6680f1e5ef3c5e7fc2a18915dfd8bc12676ab94ff4401ed22133ac1e1ba0c0352a30156bd80b63eed4a7fe9c948921e1a9843127f1191751312180b75f06e33694853a05a24ee30cae0b02a0be49db16f6f06630ced9b5e57cad548dcff70b1620ffb17e8bf8c247a962d6b2a6fbd4fb3c89e3aa4381e15b92f7245ea700e76ba99678f4b0c998ac90bf3e4b9ba5b52140e15e4b5a38e25462c1b61953cc2068d0b9ebe014db6b8fbdb2fc05751667659f40ba1cafcc2055c364116a058e286f084c2bb73096d46f6736de541b750ad437c27a92ea51baf3478837e99faee73f2a2745918f81547c45f2b7083befc6387a73366c175d2be22314a1fa73f11571395c7fe9df062740c58b56b4982240c63b8a0d5886a3ddbf6ffcbd705d3bf3713a0e1b74497b8c1f34e204ad81b63f27cfa5215d275597599f60d02bbf6cbb229088b56c96d73d09fb3c36fb3f05f4266221984fe8559619da67bb7314ca66405cef4bd3086940c4a7346243776a6fa128cd9b6181d8f584f482c502fce3339f87e4fc5e3593b7a0a64c19fe76c51a29ef776e478ecdd5e093b2aad0ab3cff0baf73f4e09d63e9ccfd4aeaaff147ddf2e9f1e3e6cb3bc9757c57072a1a8076e179e50b0a03dc94de86fbb99f0e92338f26b6ed7c863830f325d3606189b80c8df5a763f422f26436f753168b53bce965c562c2554081cb4eb42d48daf8573206f818ae66d62bafd151e9784d6a9304996b4b82cef081af9b106b42ca4b6b0b2401dc21d8875f9801591234dec266f1f218959af60351178049b487b2784183349e0a7ab361f575fd0237d9f483590a23401f9085b111ac3d740ff4c3eae0b7dca3d149243e3b1fbabdc7431a579652d522bef7023e1c6579d2f6852f1acb9b7f20e3956af8dfbf14617f14981f40b1b2430920be14284dd5f2771f73091adaf9179b8396c6ad2a3579befa1e323177fa2598a3ef80ff5785dc2677f87e9299c6bb16ef2b2080e91f6fcf1b9189e256985e631a05cbfb6427eac995e683f494751f7ae888bb0dfd23aad7fbe942b8100d4daf62b6b8e4d647c818ee7edf0d4d64293edc3b7b6e08a8b9b71a7c38f55ca76593d35770185637fb473da423069de005363ec25235ce816f4df3070ff567f919f47dc4fcf57c168032ef8d7e3fdc5a6a1dace2513fc24f0829e8e4b964d37333febb1eeaa7b81aafe30d16fe64b6ac037ddec2dd9b372c657120df4372504cd14be89d3719c5aa6d545030423fc50e277eaa401e8bb02d70b6614e9768a7e42ba9b35af8f9e3f7dcf175609f7b91a16fdcd65a151c0e85d92dc8a06cddd1ff77d150ccb62c612c90abdad156ced839e837c79b79f456156a28c45f3287cb86a9ca664a13313332a1ed9ef4b3a3df864eda7bd55a6d8705567bd8d1d732f65a324aa6c77f6dd82517d5274343a4e16fc8f41f5a3809e9f2cdec445b88309c9d1de684032a10f8944157a3dc3d4d8d59721f4f9cc0b0e1e7a97b7b066523f7498e0902ac5aa462d9bd096e13c14407bef96b59297391032a4aef8c543cc8b60217ddd5a5d815c4ea1e21625b52e2323b42b4851b0bbc461abad9b71805e8b1b2a16c811be69140d3a6d32d7aa9d5321adb57570fc2e62618cac60a4cce2b011a4c8ddd4dd521b6864c7c4562d8270dbbceec91bf1cd7be926d6b66bf370839bbb22856d1f0c7b2b7119ecea6278793186c50b045d09a1aae7c5bd2ec54df1087cbd1d8094293392605321bd39ffdbbe510f0e8760bd35074c4b0453604ca1f5bee056175ae7943183212ad527e125d2ae113d83c5a4ca1e63e8d89ba07ce8fac8257fe1c603031a1fe2e41bf922d7ffa0a610e0b91eb8c3147262fd228a4ab54fb520b49c91ca268d3954029be8677229af3ed232628e7d3a752e66c2171d1746b7e31d2dc8d1781af454822f36b3ff40f7683fcddc5aec46b13890a6c7c9531f30eeca923f198f4b57112a94e34673c88c70bcf80ee115de27ef5268a753c6f827e71254b5bea2a4f27c8e0e2d0c3f72d051558700196e80abbdf452bd70116c24f635d1850f9466282ae761f1a38a8a0fb5a02a9e1b99df55616f0a7c031fc34f190dfe5cdd4f2442d16ccb49187823fa90f3f87dc0966c4cebbb7472d8184e37522acb165f5d3b508f6a62623def48edddeff361d5ff37fdfddb2b324c4f545bfd5cb98d258edee6ee6170bd41135ddf4c9e358433330a5b590b25fbb276a2284b2df18550270b32b65d9b483fc42e9610537f27715e9f451bccb73e1ce017aaa39b65db4e86c86a50d0379398e57e0c34fa64f73acc0d2b4e953a89ca2f8c01b10135c2af5c234dfaa17ef97941aacb7cce96cd05fb246b76f15275e4d2a8545e52726a48f269d1a558aa12588cc78919a5edf6c0e9e576ed58c92b67d00e4197905d74dbdb3700fbde85d26de20cc652581608ce1d1084b507842a0373fd8830c8d3f68dabe93fb19e3189e486840715f92ae4d916a9ff3424b45ded24780b31fb7f76d506339d9f9a545fe0547c675bde44a3b490bd3b52e3b30842624ab5e8986161be4ef9da785bf537954d3c716da5597a859ef7adb40fd8030611d3ac6581e424ff636aff72f4dcd9f315744a3dae6cd386b2f9945140071a5a49f05e8f979115678eea7d6d884a92e4f14ff94dc102355c3aaa93e02723a92417ff49fe8cdbefee7e6c5e952ad240fa7eab4c7941f6ae8d2a1086e1f2ca73eb8ca5fbe3588ae51bdaf18646ed04bd185a19bdad69394ac15d130297c0fce9d8fce8ea2729dde117facb274f9865ffb4f2c7248102dbd96767483cb7fb764fe667d484a3143db514f08577cad8bcf695b0d953e2a3c8710d8979952929d59c8b8ae62ff678815130e68c85d4714e832733da40b933b7133725a40a12534753eb4877c65fe4c75542f28d6f9e805789995adaaff6fce3929e6027338281c6d0c33aac092fe0eb1797dcd953fc1f815df794249dad7b28407c50371a8c81625f6e7e08ed59a98758a9859c41f7436f937885ad35102b0eea85f3dc4bb9a6260f4e091ed983b1009275d43e4960f9422dddeddd09e9990d545cb67dc3f1061238dffec3ce01376259262b4c32c6173a6f1e239f4502cfb0900bbb7e3b4883ca3c64c8ba91cfd80b2bec6aea25b01124ae11a56ab3e4d448038795ff62e9d5ea5cfdb99c5901a8b8f8731c772690dd964cda343bfd020e920b32910a68b433ddd01d117a833242fd695a54f33fce28b506d931adba499373b0a6182e54323f032f1e7b8bad58dabcffdd1cae831c70e87b2c6fee3494dedaacccfdc93fa23ee1a4273f16adbbbcc21f5d02d8645951b93287732cbca4c61a0d0549345160537501b8c0dfc97128035875e73db7eebec24813d03d11cbcc089929b0f6e2440a26d90cffb6295e8fccf65b4d676abb8ff66709913775e611bc843302a475488c9a9310c0c8885b78d5db5cbb1a919683cfd9bd010cf2f1206ab327122ac87d8e2899cc1ac684e72c91f2d36c7bcc3491b768aac86e92aeb106d22b3e85112a2a871bb8c9d0a0dd15c89d113910f8babf15f27a13b10200ec7078d362773f17286228b0d5a58d6654b0fb4f60c81ee581e507f17a044e6bcad4bb6ddc66bdde7d311810d79ac031086d7b0c334cd3a8a496591aeda23b2c0097cefdb6894b352395dfc79b74a6e4d086656b0cd9c95a48640cc8b3d188189ec0b98c8618b0def4b0175f11369cb2f107e89c4a67a75396cfcbe899334a5d5df5927fef2eb8bd836a27a2834a7ab94813d30fa8431da3178da4ae56caaeeee66cf545537ea260ea6af56d4ba048076ace08ff2a446080a6b688a916a13b43b933e506ad187b1f829a1d54ae261651563874cae19c490004205765b43c3cca4cd8a309fb1bfd7520bcc07794cf7c03d9b1d1ae0cf646534f5a97106925ee96dcb7fc1f74e62c01d382fde19fe027a4b9b7627c08e690abe3ab076f184210acbb4229d483f7471ad551eb614c35e019a8a894b5f92f5371fd6c457f135ae8377c5781a8f3a6dadd2c00697bd8399b6f168dd64b2d2d66d5aebae90fa5f904af9f950f450d8be919ae3f02cb5c0be9687560cfab2d2161db61e978ef46304de248383dc3a99e30573bb66f873ef1e54f523ff8ff79e8c05e7f8143cebd1bdd9d2186ebdbd3b66a0a3dee79475cda2890720ac5bc33f8cd3e817d82bd7c52c34d491e1e9d1d307eec17c0c7679af3626e7b96bbe6ba2550f44de7d1d88b3e4c220b8f185b459f1f882a97248cdfc3d42209ff44806837750b3dd21ac5891254f6c7f6938aef3caca6c55b633770772c2c06734f84612a59aa8cfd4f347267e631658cfc4ff89cea84550bd43699c1d8840655f39e3449ea0d2abba1d81196413302719bc9b39cea85cb7db6ab7f00683842cc480503004c1c819ab80e121d9d21f46f362614a5f2cf80cb2c8d3fda82447cd0155fd7e0ec7589a6df2e6614671071f0f956143c762d51172da46e9f61e588fbf74cb3ceb74bf2ce4ec4ae26a28245f98ae91f09cae77c4660d6dabe7cad33ac506db3000d742f683e08bbd0a7cb9eec72a1a976546ec926b9faba5084e00d66475a514a73f01fbe1e79c0ee0066f4b724e4977f3c1518d28ddc918c573693e9b3fb69b426df0640c5ee42cd5533655f9a82c6843516298d05cd970f34dafa886995545c37b3b939e0dfa3647fb3f330bbd3e69307be3d469a99c24382acdcac76c6cb71decb4b7b11cb5f2e63d112767a7d6467c51f1c0c27900803180337f463e64f507ce245f606f8c1f1df836c7fd02502bd3127424804c69f1d066ec3acd9c4374e857c4607b711f532867cef2c1c8a7d7051a440eb7a8507500d86f11567e2fc812a27e63e5599059af1ee90444497f69add7862b93ea050f100e48df7a578d55b6d6321e70ef7a7625ed89054ab010850912088fdc21551b89397c35ab582aed6c215e00d398a857090e2f7cac21c7b51f34054a45f36157edc603b5d6e76ce20f2dfd2c20158943efd2349560666ca38505cc6af776e0720af2d5f6a7d98f385854700fc0c749dafb597e94d7ac54aedf34840ea778e8873d6f1fd7f53de7c06327d08d34a03b38315efd8eb52683ec1f9abbe2bcf096fa4f379f41e09b8bc67ae4685e68ce456465b38892a238b18358714fee41da0aac8dd729e2c3f17488470648df81040272b2e927e896a4eaf6a11c457938421288ff074da8db60d37c6d022e86952341f2b8d262cba0c5a6efb51925517a8c817a152499ae7ee56d36df86253e6b2d93079c89fc922014b03da3941509e979ff8dede44165ca4cb698924fd12bcb02a35deaad608ff3358d455a49e12e944dbb11ac7e9571476bfa856f3bcf90ca9bac6d57d5c1755104b348d2924ba9b14e9ffb750cafb6edeca6dfb79d73b9839092032035ea700d81f19d035e38bdde754a5098dae1c163f9c473b0681858004ab9d9c2c57282ebd7e57c474b8f7aa091d1048b95e7ef887767f49d2a7f6b410922da142ab8605e735ff6ea9e3f36a29380ec43dd009d98d8c20f4052d81fedfee6cb018b2da59d63b5fc153d5b0948d613415a6b8a2b7338897188582d2930480d897d55bec899723b285dec9abf819ac7e6f39d8c35c484ca13f129fa4b334979bac7715bbf5e52a9926568f359dd3e3e000958b561527bbd52025918ef75228c423da41861396be4f829aa4bb6f94f65e662e6ac91e828d721b741d7333a8e3050f136a463af537ee97af4b42456d65e1e2324f72267c07acb88c91d0cd602ef765f858f69fcd44ddc73dc7c5f8825f3fe04affee769f3ab5486232e35df8fdb75db79721906907ffad83c57a364ab85d93bc03ace8998ede749d88985ae41cef163a3d00f568d43115992362c581745f723a2955ed925cfc7c83c5b5188812fa2dc016dc21844f923b2362afa5ac5f2a6c9355b2eaf724606333f152a01c330ed88f7028e716043330a280c5ee458f2032c8163f5548428ce4c529d487a16ca0e58cbf41dc4dc802cc5ea7fad6a50de0c0f2c2be49c3dd2806911ab1322a30acd4fd8937b8930069fc1a6de86f9ef90f407b2563594adad581b49ad1d19b30ad13efb0ddd8e6f26dc43a36ff8d14d1c99b073f5f1ce8923d3100bb04488b86cd4e89f7b9f5b9cbbb3f86ee03b498ae255e09eeaaba3e4e4d68f1ee4d50f699e460a922e17ea8f0ceef9794e944f128efe835f281a7662f959054aa994afa3982f7a310f46f53d5ffc07884aa91bbdcb3f3779ebdd7f90801e96222f56df39ed9c2bff5d4a11be1da7482835e494b0856ea7c695cc1b53acf3b2e2d1846fff50bf55be65e16548c4fc436f20c50c119ca8eba4cdeda8c7e4d33734a0355586629ca5a7c3591ea4b15428a81b6d91529485004cbbf60e75208579ac354dc705edc7bccb32f23030e733d3f549fbb841329a01f5c5d263ce635a57aa9c69432e5213b155a07c34fe19cee737cb993fdc82ff38eafbeb734f04f58d367e34df15dd6044591983b9b45d4ffd87e2a6b478c7d1e86b4b974991b930370d5eaf5edbb53c3dcda643fb992b5fb0725a8aaf8a9e7c4012311f197179cf1293884e2356fc5b624cd46358d3c7bed1fed6b0305114cd11675aa49c1b9e6569817d34fd60c1105833d78dd00117284cd1722074a60655dfc428072b0d2eb881b93d6c367952a4bd59eb902032cfbf9189bf65f7bff592032c77d61dbf778986b491e297ad0da5b367c8a10c9071b8d509b246393fe04a290b3e2291f04eb750285674ae3e9c7b76a01b679787a4006836dcee956185d3b0ce16c4567fab862d3634b93079305008e2f99ed425489bcf5447699b7a7212fe2196d3999b39191e750fda742c6ffb5509e3806f38edccacbb8bc73c96cd46f0f400c4012f1205813d69a48bbd1f55724c7de917ab56d4188716b96653ebe4fd1b6d5d252f5599f9c53a4683ae60c8c31b86982f32bf73401a328891804daab93a155140fdd41ec87e392c8397c9ecbc48f26acee4e3cc279cfd67d75b5e0b6484274484c18f72c2532b4064cdcc309df796c802c17480428c3b5a5467b38aabce03de2a266c8a22d3b0158beb913d50615a1002fcbaf91edc529b0cd38f35138bd71dcfef1b6b90adb4e68a594de40199724c158db9c85ca78ce3a19378ee90dac98b23e1515324fe18472a4ca93b004295b7abd3c146109da707f5ef37886fe1a8966ff1e96375fd64536eece72ae3433a697492955cb182331ce72e8f1804efee93b1929338f" ++ }, ++ "ecdsa" : { ++ "addr" : "0x5e13d369c8adbd8079272b624343ee1edfa4a560", ++ "claim" : "0x197e55da82eb1daa23a5478ed230c6d0452d3c1920df15e10a8d37a7430a7f2b69eb474bfe0c44a6e4a55db9d5a0e0b74549c044ae22778ce30f47a9fd1eba4100" ++ } ++ } ++ } ++} +diff --git a/consensus/common/src/test/resources/aere/registry-v3/n06-required-scheme.json b/consensus/common/src/test/resources/aere/registry-v3/n06-required-scheme.json +new file mode 100644 +index 0000000000..af77e69fab +--- /dev/null ++++ b/consensus/common/src/test/resources/aere/registry-v3/n06-required-scheme.json +@@ -0,0 +1,60 @@ ++{ ++ "description" : "row 2 carries no slh-dsa key", ++ "chainId" : 28001, ++ "requiredSchemes" : [ "falcon-512", "slh-dsa-sha2-128s" ], ++ "ecdsaRequired" : true, ++ "previous" : null, ++ "expect" : "AERE-PQC-REG3-06", ++ "manifest" : { ++ "formatVersion" : 3, ++ "chainId" : 28001, ++ "bindHeight" : 1000, ++ "count" : 3, ++ "0" : { ++ "id" : "0xaaddb4dde09de5718a906d83be7db3d58e0ae32a", ++ "keys" : { ++ "falcon-512" : "0x09501c96d2f5cf0b28fa00c726e5359c5d36a1fa069971f854b7d914fb2f1295e68b2c6fa91d82f7d287f55ad493c87320bf7ca2a5d5e79d7212e8a540c166b588dc03f73b83be060525b367d9f40f5e77e7798c60b6499767586770722820b3b9e6013cad3eab5fe5de96089a29f34919a2e9ebcb3fa03a3e714593b7a3356d11ffb3441ab40ad94474da662a71aa2419dcd50668cd5d8a9017662cb60998b34ab5b7929c58a94d5e133ebbdadb2b0279543067f76bcc4cb6d7e0a5edb7625467e3ddc92a01206e1b8dce69be31928687d8af4d26633a07e73c2830d5299b878977691cf65700b65b6ea2463e51b6136888c544545e59fe8cf190a7944e215a785b682623c95a79eda28e25e0e1b91b49ac89deaec3b14a3c431d9046a663170111ee541d81b43aa91f29dc147c6fc97739b3a63fad1ca84843d0a65b8d9396f28e9b11f9a41453ab18a2309ae8db03253a09fac8f0cd634c76a5e938a44719660944a95dff056cee43ea99592c3899c2880d7181ee3dd5c04baeb60e1369a69430a66031e3cb10e392622f5246a71761760cf417dcb40ad65f60704fb74ad26f26c3af7513a42f806895e0298c25c049187aa536e0eba21998912e621846c2ca0e323744ba930a29850fdb385c8241382296ba28dd4df05ddb1e61fe525949034b59929a784406de240f8086b4074825f419d5472a28a0b157500be37e9f64897db2b645d3807c48dc143266c99e7cc1638ae278772493a2a4ecf74e526a514bc9119d7129c5a0d115a450ccf4dce05b76d4b6149fdab028006df7ec2209923117abf7578a082128cad42aa66b69eb63acee4456bebeb537ca57bb3d3487f95e4f06c5cb29f292d3b6284e5a162cb83151cd9ae56aebbfda150b7edd5065302ccab70892733a1e096ba0da5f51b42764ad23060eb197d5460425fd9c7a26e7dc3cfd40eac3643539feea72c9ed41569111a7976d2c345ac2183fa2271b424526709fd9aae558a23a5cca29f4e2f31629746a71d904612e95ad9977bbe74fa32e90fac62625838cac49f50e5aed4e8879e2ce2e5651c4f4ba0c96583af9e1612b5ff1a6fac5027c0a308815e592308170b915b4a2de1e8d48e9a5730680ea9db8f3326c430241153b3b218d5347d5c843570cf80ee813871ae10f6b8ce4ab7e4c5197045e85b1cb4977f44c33eb85894b6555b4bd288a50c1b656936841048983c00a01631f10a84522cd613fed0d4beaa4aa4b3e9f30c324108d909e59a80150", ++ "slh-dsa-sha2-128s" : "0x47a0b70170dda85f843607f6c6fcbe6e6acc7c22980c108996a3fe72dc9f61a6" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39c8813cd3b34be58eaab900555a67486034b1923e0b00e435661230cab85f07690a5958a5f5e9c84f033a3dc2039a5296443093fb7fe8d41895fa73be3fb34cefc6cc36750d534e6a3c47307294694729d6cdedb633e8efe8979a9aee486eaa66136e342c578761241192610185feb2d3c196bea0e79222437b6a8e08cb09778d053b29552df96507b1cdaede8e9aa7abc18902f29937f30e7cee6868f349f7ae33738237dcaf86b8e8e01238f3d8ea6fd4090a8161db65dabeb5ded5499e8cc8a5b32607abc291b36a4b34b327d30cdef18c1825232e69a2b09d539ed84dd2a4756efa64f864c563943b3db825824f294c1bbfa2157347b0fb0e7f8a56ec253b39ca9b6cb1ef7d3d7c93a6cb220a7dc50c365905ea5a71575c3aeab25b33523e4fefbaf66137f45c3d96db719a12d2e2d42fbd6cdda58c5a1b958b28c2a8f2cca297871a147dda92a7f008a359027a9288e42ebcd6ea9542f10b66dbbce6e7bb914206122f866d9adc1c89cbf8bbad9bc9517c2ea9018b61d4d2df9abff1dd9f3a0a6faa72a449af9c97e8c4090f3bbd9824298e61599c13c7eb89677c0e845ca2907c728d9296c24e96b6a348dbea7cac62671c9a78a531463614ce321e28ca2f093094ba5f69881e6cd766874622ca769ea556ae757cb7f9546d99f5c90c25e7b8e14f3b7f270861398800b0604ec2a3374659277a23cf6131c63148a41b05b3c06e2a98a268f1b9f0df7969addef17179ca2261d3c229ae3db0c490834564c45f7b8ff6d3bf70784779d75915fb2e2d5bc147bc941b9e249af188f63f39b028547cf080b7674b228e20a600e3b167610f814daf105226f3c1ce5e07834fd33dfe46315546e926fd5be83fd4d47ccd5bb8ae736ac745daabb59c87b9edf9a45c9a1d1617ee84e588f27d12235c59ffd9", ++ "slh-dsa-sha2-128s" : "0x0e8f9bdc22cad3613ed07fba30ed04219b9528f9b657119e2f0886dc71cda4afa7d462fe8bb108feb58d998b370b2f7e162390713d1a17eb7de781a604041cbed13d00effd3b24f2ff87cac74f61e7b7f7aa6a259dc283485179ab4bb966793be018c4bbf4475bf7a69e600a37246908f662813813d4b0f4f83757f4064c5c0713870a0b98b5bb99025dace06100497fda8c73d7385d123afd4953961066e7c8544de3fb620ef5e23174327c2b64089b3fe6df3eb86e83b12634a0c9cc0d7844c894ba6d83afed6becb6f5abcfff397c5cea8064e5e153ea4253abe599dec1614b449329ebb25861b69a9b22228d1a03ba51532ea64ebe7603474a15a2806d3dafa29d57d27c5fa894da673b85b4674ce835fcfbd391d328ef83504101432bbb0c83d7be462b265911aad862118af6f4cea4df0f1dd38969c69428fe438d59d22736fbc7dd5faf6758905b26ec4c99d71e4b8fcc562a694ead91569c9a916df5ad693cb2ad0b7ae4c4f3c5b7322f56612c5449e0339dbd367460c76ab89b6f44942cd33f35eaf33c2ddc0c6af793556d5202fd1fb0f9fa1b7ed45c6ca68d904e476477b71a0bc6ebe248c9b4585da0c7bb186600691269bb4c836667a6d73a455b97127d898b7fae17e1acc6dcc3bac3ecb14da131d5f8adaa64b054e2f569d9bdb164792038e107848882de9bbeff295905c2af68d4c6dcc8cf718c2de872ab6b3d18e00d527166f8ced642281302e2acf4cf4489072a2dc3d55ff8716619cde494be1763dce925438b33ff1b91b35eb511645832720ed92552d4880ae53ff6516cfaeb1d48c923648e502e4038676f7c82e532ea713c6b9348c80ce3c5735f437491d3a8b1765294868c14123af2e9ff61e394216e630c71ff976072d2a1c50cfd8ee1ce27aba5bcf9aaed4a51521bad5e5d5e66abc7a95b215fc8004364aa4df2b8b97b14e3950f521b6327a55fdff9139fb0bd35237b022e3aa128d36c8a60f4621d25d28c59a97418c7dbfc15d900ba626d283632732631ec4a948f66dd9db3bee8c2cf60dfdacbb5ad4c0b2b31f8428868cca035e79c95bcacaba40a9351b2b44cb29753b6b9da0a751bd5af84c9094d5fe91e97501d4f075392290e8516ed5e41b41b00e09793353707fe5c1d942395074637f3ee0a0f105876d6f28a74f9558c5f360e98f047a99af35ccedef8d5cd299365e81e7e91f28a01eb265219e21aa7f7ce56b62f9d2a61560f9fa39f2765f5b50920658100a638aad03482a687905cd27dca02f1deffd1bc49a1be1ea7ff1a505da74fd932937d8f6a8bd75ef456d5f7b71ca5357bc66db6cf14368c4faddf4996363251e6a6113ec64d642c319dd85830d8b4c7ee1437ebfefe01f27709ba0c412c266530f5b6bbb005994774e8935f1d91069f9e7a8cd2bb7ad6527768473affe24709c10294eb588aafca85b379bedf0b142b109e1b186e635b0625c4e59576266acb5f71040c44035fc9480b13932bc657cf332b12da1cd7d5c3977f51d5fa742974cd256e8e3662dc698e0516d615d0a05ea9caf12338d0dcb6151e07f184c9cbd5e59bc40b12ed6372e2d6bd42aa0eb6c3c888f264a8c0d3332631d4919c921cdada6bffbd01ca5445de0779f9723577ebd7e33ab0e5f577843aaa6cb8cb5f0508c33b63913a44d02b76bbb1eabae325581738fbddb5d4fdef8dcb8597bd29c6ecc631839118c44f66ef8dedeca65e58941c30e0423c40bf064b8d19d28dab3787238781d492720236a7ae0695ccc867fbb1cf207ebecc64f84daea66b6745515b9ac9b725061bb9958ed79ad6161318a262528004401633d47a023c645683e36413b8653fa4864fe98c501197c10226b1732337842a1322bb788a00a0de86758139c2d9ea3c5b26bf5d7a4a92cab4cb686c580e3e6cca488136f0da9279073b3dbef9519168ba02588fa29cc60d02273805b425b919a7e2e89c9086609982163e09d5f6eb9c66267ac7be363aadd4617d398d4bdeca37a838d650b0919faf13b78642a058b1bb96b2ed1482cef9bc6e8b2e061e6815936e15a9c754353aaa786ab141e95e5f6c464a41b8bf29e28e764abd638abcfb342b54d08c15ba7e24e6fcb69b844e16cdb5cf4f50db60ff0699f969d8e68511fcc9e16a58e100f80671af6b04ff3edda3a4f05f9183c0c3bb7c1061fee2d3f04e33fe75f1354e6de54f582da914da0138e8565ff45ef52f638cbc33a24bae863fe91e58d7c5da34273438f15e10d4f59db16e505620d97d3fa4862a4097a659925d0e5f4e073103ed29a600b051b83b1f3a21381f4b871c18d262d7e43842c34ed80661438c064aa2fd858a8f3bcb035b5e942baace7b50e4de5a73d5c51fc0843cdc163958a62d333078f4c7d883bd7055a602e04c853f9215c9d7f798403c007fcee124cf6099322629c449ad4ef84b7356110798dd87aa4d98ebb47abc6cc8748dd381d588b77db7f4e7550f6ee1ef4360dac6d6c7037a65297d4a0ea7999a5632b90ad48fba0a916846a216941fbd13d62ab36e1066e24990c19592944078435c52d7717b3556595b645cd2359ad151dbb67e92b14168cac12fb2cc5422582a50bf6e99f116751171c9b78744ef719282f1b84bf95b4092514f4c68fb82a1526e0942ca50e186632cd9b0b8b8d91e84f85e35f30f815601798fcae676da6a2d38eab62f22445099694804a36a34142150fb795afb445e78c241f0b645209037a8871cb5487c975975ac997a540b709e3df6bf208d9d8017f9688b152c9ee2b934f65393de8403244b7437108e6d8c973aa723285555d9eb92509b1747977105cbac7fc33e658fd51cd374d21fc2bf229928948292c1698db7934d0f9be44b137514d0a5fbb659bba83861931e03698a61cd20a449d0358a5fce7f288e18bb3eb62b7ba0ae75feeec634fc90fc45ce45239c5e3179309f0c202cfc53d9f42a617f7aaae586e7161a0723ccebb7e8586cd40e1fa12d3ee89b400dba8073b0080ffaab1182e8243afd93318df15bbf3ce179f21804fbb8882e855ef9e0739ce1536d8ebfe9856aefa9874b4e102e705a40ca4c3ab0ab7df63ba525189b518796590035ca780d348de49f0ba8f28456ca6f3e3cff7e761d961ad98b8cf01e855797c88fe2f811e41e787f3e4becb0ef42ca3b9979356020b447294ef295543e0ef512a247e4d356bfe3deacca8ddc5255e6ad047121eaeafe61d71e7f31395cf78890add4f8c688e4eb065479a63ccb3d0c09028bf60c700fe9d19195c26fcbd4130e6feceb52e192a2aa2343c05b43b276f51a7c55dff7233ea512942291900d93315438a96af08e25ea5b9ce656c54e71ed60d1eeb1665ddaa9e42378c930e21d93484b9a4099b7ddd71d983b4c42c6b1f62907ce84b24321422b08b847f1ea97befaa4ec30a794ad7f340210c800cf185ee2c6c72e844cc5671964e1e1ec58953500f149f0f0f25c34d5592de421c2e31535040020237b907e86d753094dd4532e1ab9d821e7583d4a21e1041fa7ad711f29ee3721a2aec6b0c46866a2de71ee850d8122f722898e533848e2bb851ed24cff9ca83badcfad88a171b4be064007aef4d759d93ae9b67b446f3c6fe504f5b4fe851b8312fec86b46ec3cfcb36e0f682e65e117702b888ab8566c9cc716a3a86106d2323c0f7f20fbc1fcd110bed4492a750befbfcbbe16820077dee281bcdf14509b93137a3998b2fdabc2a375b38857bed12bb8a9c67bcae7934d02d6ff89620fa8946c8aa524fde99c12fec0e25bd79788e2c15fc31fa3f27502cb952b9f9482580cf18ecabd92c55113ec4c4470c4dc06d8ca27a10474594eff708209e8f376b6f17915c2966dbeb0e35ac2f02419692c0d232e133b3907059d3a56ff169e7e61915c8b1067e183337b40bc1136241e862eb3ab3f2c6a72b18511c4107ed063d1e2303d0fe6842fb01c204d1bffad7e90bb44a365e62945a7f631811c9c37ffa5ac39c16b4835798686da5baa8e1eb6aa76b42f6b86863c30669486a175d6b3bc5bc47c5eb05b240bd921007fa39506c6605bfbefc9c8c493973bf3f0767817fd8ce126a301c5b8fba79628a9b3a03cad0c491a5f487dc5e89269e5d3bcdc2998a136a012486c5bce2e6c6dc595aeee2ebd5a36dd06919396184aafb2301d1889b668c4d701c7ca01b95f9508f47d4c411cc0397c244ed4e3e3ad7f97d86b6f8834b13b1b2df0625e6b4eae9e439815e65baf2da767d3b1700fc461fad6297fe4e8ed02bfb65b750c2d2801b7308aba9657df3c3ed7d548687f55e85c22343d1db343bc2dbe222fb76fbb3cf490cee7a99ab3a337c626a148fb303b2f8651651588dd4859fd65c95820ee2af85adf4e8fc2c03828ea7427e7c6b0d4a1b0ccd424df6d1450ee436c01351d8b6bffd4ba072756315968845ab7976813d93d0f0f2be1c00faab3ccafa71cd26c5837e87292870cf768c7837e18ddc3c513820c660870b339fc42c5211d33d892ef22b475cea3be20f5e47206efbfdbeac208e26e97c400edfd41f063aaa6b85a0cf86e23fb11274b405f4f796eb10cb97e70783909ad492ad9207ae7b3d204e59d69c886f91bc82a107d0be3ae85797a7cba747b8e2640ec49384f53c785a84cf8de37dd4048dd4b879c58768bd131ad7226506113c446fbf13d769794f1535d58e9c52e23c1bd55e13c647d304e297d968c759a378f1d594897a026e3271aa6b4daabe174d6a35665b35193379f0ee465df7827299c18e1012ac69913a0a5bb5142e99b051763de3e98d5af8b62133e25b32f4f12b787bef7e21dec42de8e4d99a0adc8f365d8cd3e6a5ff3064ca18965ffdc6b383f7ad08186d735a099bb0ee14506388c1a37f7a766d286d748d404457226b952ca6cb3f317b0f4399006b5b8c6eb89f6b8cfa023cec4d2dedde3e31b9a633c0888989b44ab182a5aba30ba78640f477ef1202f6496fafc2a18e283b2e4e8bc60415a1c9a7fd68f15cc1ea0299e3b26f5755ad9f13481a0563a524c6735942f5069dc1d6a070b3c3698e9c503f67a11efe59413e937062668d3439a5dbef197d24ebdc79944b17c549b0648af9b1349cad83c2a0a9e55fd893cffe2aff4626662ebc5014e70baaf7cdbbdfd3f92fcc5eed863fa8afd87f88873f726a0a2eafe41fa81edd5833f5520cf93b0fbf0660e48eb0258d313bafb87dc9b0d0d9349f22fa2d960238f67457ad644bdc60fb5eafd1c88dd2a74db4da0f723a03df08af6c64883f275395020341d9dd3c7fa049ab2bebb4d8af2bb8dc1340d1a80088c4b2c26bfe7314926ee64bf239306c05dc2ec6e6c5e0ed4f6dbe51f5ee09533f558d29ca6fd27092c20dd892c89c83223752006b23e5abecfdc733aaa59c8549e89e5ab0eae1b44189f58cf9cc18de0c2a2f46a9235fbe42c641a890039cf6aad820f1f844edc24e69bc3bd0c22cfad3804d876edf5491e88cf891c347ed5f24464f2df439bb30742e1f9a4a7eabd9346c6a5f93af22e67becc494cadac82cf9cb693acf44560672cb9227eea2575f90b0e28431684ae12ff2e86fded0be3a099f9ddd32a7285531de8963c9a03355f1d9cef88d7ed9b842d0066ccacdb698d42ff9f8a4f000b9764a9aab1f3146f9f95e6636fdfc9ef91c4d060a54ed7f32167e7ac50590dae3a2904d5d2eeaeff2930bd4cad7166fc17edd2c30e6738157eeb0b441491e5dfdc17a7fbb2bdc6426b2cfb26cf2a7e20013f1b3e33a6d6821928443cc7893f7e4a5268a8b94a6ca6097d25be17b214ea4301e9a723194983bbce286f4363a53afd9e94dda9c761481d9d20c7687a2ff85d42436b9d557d5dc6c5e24ea21d5231487df9fc7986100664edbbc51ad4921c5ec9fbb407ab33ef5c3b3bc81f113e68f38d73f0db0261b656fc344d2d23b93446845d69cee1704834d98737848d405f52f5a7bda3dbdfcd3af3881484579d2d2f3ef976cb35c9cbb76252f2e00019363273489b39943d212ccecc647413c56de69e0087532223cf9b28ce3f77fed30bc3ae6a0842b546e0e1a8b6f6ee1ca0ef1b78c3ed829af817099426f94a447f67229cbca3c07b7a8ce547c5eebcf168248e0a0b9fbeb398e5ed2d0dcacb441f95f9e30c108c725507e459d34c1ec01b67065e5e202d685502d6ff015d46c20bbeef1db38c29df7df585b95d79f5687474e71fff162c0ec0c96c94c507f8a0292a8c32168dacd2fff78b5c7dc145e10fee1b25c478172af8f3ea132fdcad75dc22856deb2576a5ff3e8911842c811d1d57ec203c77b82da3658cbfee18d140ac341d38a30f1af298cf60f2a88d0dfbd3e079ae64a07abb4947cc042925fd5c64bb5d4467589f8c495b0097073c081517bc4504dcd7442bad7e7acafc894fcf34f535979364cf5e908a84e0e141ae47e2ae4dc95462b4f345b12b0629502c7bd65579ec66b2d0a951302ba6da1d1176db6aa0c0ea1fa88195dd2248990fa4aba88490b1da4ea405649203f6ff6f734693f40deabdad59ac62e3296cdcbd74061474dd7b63c46bcfe6ea2b0ddb0f7e77fcff3599892c82425b05ae7aa1a2ac1dfddfc67e11921ff4f2c8f6297881dd5e38ccc4076cac8015c59cdd6023ffbd62b887b33ef8d917446a8941d9563acb66a6226fa4d3f2cc21604c080b3f83e73c093d8f2f7067c392671020c7a7eb6fd0d97af0d63032a3116c408b708d4b2f711c1134b88a91aa359608550f0049af2bb97688afc4352a45c4f6d30d4634e70e82515ff1d5f77851ee857e42b486d5e1f3e0406227dded6c5f47eda30d94f44d978322891dc729eb6ae95d29d22c8a5d649193d5d2aaba782fa16ae488f645a7ed90a566e182f97bc62049724f4cb5fc71f6bc7be57f07a7afb9933f6706cc83483cd7dc4182768cd35bc42f1e9b54d5454d3a17e734475ff58fc66d75419d3d122eff05f7b0548188682f1318ec32c5bbea87c8624cc1e548bf18a6b102e7a43e6bafb579e4e84275fe07d8c63ace449a44cace5d9305ff756cbf40e5a6a20334d5b4a74ab0483e31593f2277e90341fa8036496c2bc6d2b7b10b0b354c86d666d65cacc593d1d7349e71b0360d823453011ee16b6280f5c048111b99b185af99e9d901d4eaffd8a96b1ff394b66208ddc1e7e53420fa965bfc4e630d73ad97b9c5c6ea884c619bc24ac3f46234e7d8d35a12b0cad7220d7a0945cdc64fee9d8852bff872c43f359e7aadf8fa3de3551fb716704af68a18f79d03b3c7d90cf21eb4bbdcbb4004f8ba15ff0bbd2d0918ee78e9bde980e4f3cc13558e6fdb40ca71ad2c10f5e5587784bacc6b925f72da12528216895e0ca4b350d078fdf534fe01bc86b45e0c8e2b35799d268a457f8768ed782dfb56abecfd2b9db00cd10e189c6164f82f5ccab423277e3465ec72d76b696cafc1cfa9a7fe47d142fd6672d9c5b77751b40801af07fc53b1c9da0fe6981ea75e066572f7272baef8fc54bfa7cd71cd0fbc5d6cd717e9aa07808496ad2b4b4005a320c9312c73385afd61193581dbae99df6c25f1b9da17093ccfb108b0a26c5ae4963183533ce2f0ade01bf5e818af613416433578522b1b1e5aa7c791570c8c8b26ded266399116f5789a8233fee128e54ca8ce63fd56c1a146c3006316d200e05715993d1d97907ca83d7fd42ef7e7222eebd74f9c86b6cefc82e614a53976272c8801bdcfd882e34d86b39142ac05088a4c47010a71107bc72a380bb3e5122981d1795256beec20a0fe568002d79a4b1577903fe8682f268eeeed0a97861337ffb6861bf378eba1e0957111c7f9fcfeb55a95238005b40e13ce40efe846ddb86d14c9ad2c46cca74baa364ed08da3a3079fae3a36346ac949e2174c661b8801a051423e95dcab6a0f9c965e8744bdd0e629bd3c1a1241e99951ddde184eb8f354209f24c04fcf10fa8f4e43cb55c922c28be041213ddcfad65c86e1ab9b615f91d5fb11e4cdec5b7e25f8e9811c82c2ed457d012e4967b555f228baf4f1648854c624e0525e36e5f4d1961bfbbc3621d79bd6bea72924d8e0146d0965c239a768b417ea4c33237a60fff2760a9dbfb1113a37b01b598f3e06987d99518bd9f1ec96cd7050863898c8664f793ef29114bbeeb9afab8ed09358d1227d7de2aaac0ab2391cb2013028ca5f4d1de6425ec5feb17d95df358572fa27fcd51d14c363a36bc37c7497a0f964a6c004561f68349f828d30d4633e87bdce6b6d92384c9c1c540c8295ea621e9a8006a8d7c163b988853071e06c78f1b9a0246db052e8484a65cbdced3a587e45d9e2b49a5501590cf768d08b6a043971110e9c9dc96abe855abbb7aee2c38bbb77e5c68d61f01f2376b6122450117240532c7c840e3739395dd6c9e80a432423fc5e3a6dce9dcd58eb418e16d7aa507b4d67dd6fe2af4042a5c7398ba4f87c650926084efbfdc9430a4bc2be544880ecdf7361aea06a25e4f592104b0d74312f2729a4db5876b675bc0fa68f6e41e014b7caaf6f49b8ef704b6243df410dce94ad2c51d328fb90b9cf2f5df645015f489a262f57a5aceba40a56d343403b660928cd7a9d165f4a5bc289c0d28f33dac85c9c2a5c79b5ddd22c744a0388a5daf4bab84d7c77685053c912c9a24b5a0664c6253febbcf552c4ff38bbaf2f7e0c9f06e69a91cff9138c2745b99367e00ff6b6a920b1812e17ba44175c033df0e58d1b5c0b7d146f861b62e812ecbe99d638219e0dba4dd88089005977bcc90634c4dfa95f87370d905d32f613358fba2efcface0b9a414ce33b09e271a647b911843933c5d1008fb0717ab59739eb8eb844a4b34bb1a8f635c5895afa285ddc43720e78dc81eee7db822896bd9bd6ae3e7fe2988ba560d58f02592870647b94aad1dbb0d0cb60e28135ceb72e0a6f4b7893a56eae83f9d9a4c549d53d17c6a00f5d6c266d23e7a1d13e22a5fede3a7082dffb34296f8fe9f3bfe525ee1da81efde3aef9b6de8457a10fd4340809e1dafbfb9e2719c327a3c3a4c51d4d5600e8a01ebd5c537a4cd7c4519e963de06de6c83a9b968b01f79e08b5415c5a9d6a92a633d6ae969b80cbb2cf4d6d1ab2c3b94e7c12df27ea89bff4014d92add41a3e961006a194ae3ea4a6b38c2827f6185ae636f6846b1c8401289696fb10c765fa93e58d068bdcd8c9dc95df572f096d65f5de42bae639d41ce7e1ee0f48ba4faf856c0cdd728956d7e4babd6d9d6389ff41d76c5fbd6380f351b05a37022dbce0a6a47ab7168c82c77a2810c80b1882f825ebf86cb7f6d0f54025fddc9b9120802514c797d1d3968631dae95297a857890ff1dee408909223d012925dc08b7d1119fefca7466392a019d4121ea76c8b4c3bd103a820557e4b2283e262af32f1edbffaa253c47d5873bfd0219b8be86c7e64ada2d87ab6b7f428a7d8fb3ae09b05aee71054355eb83ad76c05d836a9f1a65511b1553927ef1b19ab1576d7185af61be6104de1df218918179c6321846085a83bd1217aa63d0b03996ac1fb4018a8ab54fcf635f7d5a8ade95894f0d407e5d4691920f21094c6f632f1661402a0b3351f168f16a13d3a31ad48e89230cffad272926487f36c7a2584c9387623df6227be8c96088db4a21c93b1c88ee756e960f60e614b30bb6ff757c20f3674a7ae7f6ff6a9115a0a6d444513ccc0be5dcd557430e0ee8db3ed5b3e8c405110500b9bf7f6eb7748de4988a1db94bcb16fe33479f64762c53a1e2965363452063d7bc14386ca7b4d46ebcf08489c64ab413ec0f1ddee8719f5fe978d38438ca3059961ecc8480908cfaf139d88db2facb5e7a88a43a67dcb0f97a17f9bd5b09b8369803ccc7ab6d41238e59e43762965814c10c36fa4b6e61bf2e83c0243f20ee8aab62dfa9827aec06f99c5c565c1bc75291292d3113503a202851c26d1a8bde54bb30f0301e555374b71e278925a2afb29b0209c08ecb89601bf612ce811a493abe2bff78e7fd02ee13c5db6b3edce7c87559410b9be3be95465468e33af224d6508a44728cdffde4cb14fb96a0d2ab9c7f597541f9963775c32ac613af9beab89e0ff7a5e35613751061b0511532b10b3947802901505c8e33bae67ce0e28da760af7e80b730811bdf17abfce39d35def51d73a084119449038c2b0f1c86d844123c6e71f28b7038053e279dd11c088dfa11c547a4ce13b19453e88e5b74962101412490cfb68e21d8952db509cd3a814387b67339fd04ddd2163177589146409934f0eceb10db2d90a9e3f6691eb75e84d5e66bc3228baeadcba200f3d11e0cae090ffbb800f5da7032c35ab572de55beea37258bee6f191addf01739a26efaa612991cb2a3c6d1bbb03de0ee1fcf9b7f6c51e452b21c0819a9aad93162eb2dcc189bf355ecd2c3e504713dab24bfe3ed86a4194611029f7f6216cd469fe1f7d35d56b6c8c2045011e238f9cbc0a19b8914d74329e2472f15d0b7d60511814ad2736d6be168aac01868c2a675549c849fe05e05a76f077130b46896735db5490277b76bba43545de6b8ecb53fd20398eb94dd884951fb48d5690ce4bcd0b836615cd9340ff0cdee1122743accfef343811a71c7d14d1369fa49ce47784a6ff8adc26c151edd4969dba513ade6a9b1f009e57c3d6aa845ddee275169ce58e1f04b564ffb6d0eec75f7172e5e8fb814cd702c9fbea8a783bff637db8667d4b6b48a264135bf60acf335936105abacff0351ba9aeac88e9522cf7ed80069822a7db1a5d8221d9492e02ca893e1f15965fb82a80ee2ec491027bbc8906e71cf931fc21e1c0865ee06a79c023929625b4d232c7b3e2e4a4e5dde28fab675391befe583c95dadae71dbaa43e09d8d65ba36d148aa85d1a2a35dc51719ac0311ea72c1237c78a8b1542c59de3b743087245e54d3111c585b5e5e7642f625c8d44c6d9cff50d8d071f6fa573df937d9e7457302d8b293d8fd94ebd3023c55f8b260c3454e93f58f16d0f451189bf41c9f9b91d3c3918adbf98e4ca5aa0eb6314041521ef880ce18f0ce296721a06b329bb5fbb3024e424b46400e03caf0105877465285fcb41a93844fb90b7fc1924883ace6ca8a37c9905068c633761163affae39d0ba55b67fdc6bcf0908ee3a42af286c" ++ }, ++ "transport" : { ++ "secp256k1Address" : "0xe23c5bba38d809fcb2d3384f210e9a6405beb498" ++ }, ++ "ecdsa" : { ++ "addr" : "0x48fcd978ac4d42ff52dd81fcd17e93190f35e5e0", ++ "claim" : "0x2dee91bd2cbfa906aefa3a8ae6e2de773f55dbd28e77bc329d28215183068585601ab9a7f9ff0c48095407474d502a3af3f059a666e5ed1e27468466d69914e801" ++ } ++ }, ++ "1" : { ++ "id" : "0x690a7fd66157e5b777256ea5214f634f61b3a72d", ++ "keys" : { ++ "falcon-512" : "0x09a6d094d9a3a0865864e9a16b477236f1ca26c888fd0c918db331c87a478519c41085cdac7e6cd0d89190a41a3bd6f4d6300995d591f5e22a7b7147caab1f9c7a85a4ba74d47c7b227326ac17535de039a7e604225d3daac7f75b9544654b73f79f5825825ad6e6c45d13e6d385a644633e1c8806d3a0a551c98f032583c95fb13997e52a6b02192d26b5a47fb22ee52999ec92b75c70774a4ae0481a79113ac72346263e53d5dcde708668d317dd00552d5a40ad47e59a501b10a50bdc52c5c2b2c920fa0e3dc9b8eca54b10aa5ab1168c88287dcf80ecd880a8fdec85b6d63a15b9f453845421a5d9b898e6149b60454828eb9dad6442ec62ad27ed72215014f3d17539085ea3f668b0a9183ab96e9db996801c72a0920b02a249911924f181e8dda515d114beb83b075ce7e7a0902a6971e31420ee4921f5cfc123f29dc7775017aefe99a7e326119cb925f6f603ac3bb137313609498d5a2000c426cb332c82500dcfd80d70a5e2d156844a683b313266af6d60216bd9e9998bda53c0028f387ebd21a5fca6c0607d54b1e95724746d15f25f16e45845926a83c7598646a0a0d3a8f8307c1a401b823f1656ca41e5499684150a954318da076af9131fcc93361d9bf0ae035f617e02cb5e1224a982b3591b24013ff80dbb61160d2ba4ce85a4260c8a3a3218e0ec869796b1b04a82079cfc0ac26da03b04a11950b2a3331ecd0026ea9737bd20e6ea3045b56e3c71278d2a8c72c8014b769da9319e19dbe762b1943e5a4be15aa84d0da831eddbb10bd05f35d55b6211d02a61c5d9247e69cab6c112acb568ea51f345a5bf16f84782e04220e217722da71d634e1a68b796376c8a49a965c592b87d06702fe42dac12da108d24ee42a109e8e4cfd3bed6ada5e3de50301696bab0564292864f1b9f47d5a53cc0c5f9cc3d57051065fd57064d08764892ef4c4a92b475184a4cb4ce1f3a0e6da0402414db5a9db34632b9717586e799b06e870b81a330da7be6a45ddfb000fd337a24a29e164449f96be015818c53aaaf09b9a565d7d9d735b9493885e7cb49a5f1985977cd6824fd62f51d2a1e60289dbaeaea148a44dd8876cb58b8ca2f29f6455f354e4e76aa13290f2979b78b22afa0e65c696c21497e94bf0141ac6298aac70b5ea843848a2264fc057abd3593cb17465e06d41731b7153b71f8f0f7a06d362fbd09845f0815794050460b41ad003c9396a86eaab240555ac8c75f85c0ab972c1a0b94b67b1aee2fa3", ++ "slh-dsa-sha2-128s" : "0x2b2fea4a0edd5dcc2f653eb2dd000aecd87deffbce8818aae72d7862b506bac7" ++ }, ++ "pop" : { ++ "falcon-512" : "0x3968f2999d69a9c28ae792a90a47363e689bd4b349e75c5f837181fc7b16d3d04489bbc32252d750d750417770630c5b65b88cef918ad23e33892a58458e9e63ea591596d3b898f65e1a5be3d36650c3d9834e1ec725426960d337b8f25878525ee3c3798b5afc9add5bec82c8e139c59738aba9ed5f42d11c886472e81cedfdb5b910eb73e884e0d4cc218b87cd9bcc0bc107af586c65b3949460a25892d9607efa341f232e478f3c9fc2d05f324ee6eb7bcddb72af371d47c36856f488872249ffdd322d3de7d12b62b1ec595187b5b363e36cc714b765f0ad5616488300f6e56811e88e359365d5698ab123b917bb32f56566958b154f6fe052b894ccc1fcd99d65d19e8117a8ca4887e01f36f181461a433fb9bbc1790d8b14e34a097b149f0c5c075ecae3501944935f3caa76f0b9370ebe6b90390b4d059f9029ee4af98dad33b9050877d49c3d4f2beaa4b5861a21af95b8c52f9ab4b0eb115357f5b1d25fb66a36b9baaa4d6cc5a4f5fb5462432bd82734d7393cd22c68f52493eb3434c3b88fa255baae5c46c650cae17ebe59827cd6645c6d377b3cdee3aa6a758ad3a96d103bf6ab8ae03b72b53f3aebdda359288c32ff5461a158962924a97a24af29f6c976762e8de9363485ada49c445566e71ac75379aaf7bf190a81c671115e842b5280a05bfb2ef3724bb74487068d5b5ab2d089ebea7ffb4381a7e96233f0915f295d3b71db872393bb990b9c74717bc3d72f6271bc248e54828a1e090f6da56de3643b083e9695db7d0a32bb42355e245e5cc2ed57354d82220b449e10cca1cbf6fbe796d141591d6f71e4eb6770a3c7dfcee509c3c28f2f1988eeca61833b6681e6766790c2a6f043b4f67e145b908ba7f03361cd9d435d054e11edd9667e4f9d12c2d74f2832b619", ++ "slh-dsa-sha2-128s" : "0x39254afc16b1dd8d4fbfff766819460253653dfc6a8e29abed55ffe91325afd578ebfa2dbe74d46b48b381e69d269b5bbe24ca1b85767bd71c744065fa47c646e3603b44261731b50f2d20a7a327e98b84c5ece73697739c8057f99d6ecbc54cf891649fa78b7bcd824972f3b27820ffda3629f481b1193b922cefc907bde3ab1c78b5ac97ff26986f3a553556d0b158e936450b4f41bf006c90a9758e0efb327f67408a7b803ede993522cd9042db4a672c89d4765a0fff8c6e8bf6882a8de432229dee08ae13def90f9fd0a40c99f3d93873a41d74871aaf407b0927a817b476eb93c645254bbc77d131e0bd35a2541248172993b1064d5b26b921396c8c1664178051810961039b15790862415338806329a45a266aece5904312afb1cfbeac1e816fb96256fc6e2b059c25af1966b0bf261bfb72afd8652feaedd6e0e4bf829a75188708ac9c623d4d6699281913bb563b96818f9307b66f7cf4aa9591e30c65a0b0885c22b5d17ff610f40bf2e0a9a32173b2fa7d66c14784402885d84f33fc75afd8f743cd10f5ad6dcce5b33a8f0c0365de2ce1b69aa86df2482a2c2d3746c6f0ee4e6fdbeef5738d809f6b0ef3cc703b0d29e93e198b68d62a5be657e69c33459fe4b163a5ecd72a90f1e53fc00bc8c698af7ae3cc5b07e36cb74088066a54138d6df4ef6e159ce5924b6903346a5fe115272cc951e8713d4b6f96f78d67a542c3bb402e69bdb3c2b06e189186c227927b2aba52b29c14e837b37798321fd000ed3bc0e386ad6e5d3a48494f57109322f0a87f7dd752d862dbf772498154804b09eca84c305595cc1e6654b1b2e94d5b88feda176aa144d3895a249754bb2ea99b2efb4f61b828f265638866a49dd3437c70016347d5aae64c79957ed394a85cfe06b10b98b6e83801728645529537a1102bb04ada4226688594cc28aefb24fbb0d1a60c7b826dadd23f301517e862c67fd88d0f6a5ac08e7f966ae375b468e57f01521b43fc24c761838c174ac106c4e1f435b7ead5e79aa1b303222f6b45c5515d497d8e7b05901bee96945652d304ad9ebae2153321885f19e7ad08c9da73ccc22a66c26c4cdc9360c36e307310714ac44c80887f42a2575305ef649378d76d297dc6faa904377b2037618f23b8be496fbc680645dfb80a76bfc060c6b2aee4ac5537e79b7dc7deeca0ca38041dc877b875cab1a297190269c987dcc46ff34e5bc154e2572695e463542be79d61fd5e96a4be2b07f5beb71b882f99de317116fd0b36131a88ff9707eb25594fec74cf76c2859ba6ba2b968d41479adf8857f4b0f4a26f49f0f04fbae0e2f3c2ab6aefdf01855a7a5a4b8bf516f4551a393a33d3920ca3ec403b4d37c2106d777e3d5dfa768614513885d857ce95b9bc3b992808e7ad71575e5e91b8107c5802043b221c74d73c7bbfa7a191945bbc5ed69e20016b16e2e2987818cfa80695e58950b0c1bbb8c474f861d1447161744c75d99dc8240338c43a5c19a8a9f46d80f6b4b6c1cb57f5a3350bfc35a0522f89e3470ccd71a458968c629c93336af6b5b091f569d1fc9492eb6b976376b8ff19ad9318f5cb1361954a0471419b4207dd9dace8c0545e74dfbb19ce3fdb5d456a1c1bff7383c6fd96dde3a92daf0ff5a315714c74711e3c05e0c59ba525c64ebd17fa20f8e143c5931b3c77da193415e6506c2db27e0e773a6a5b5d47ad95760b8d471d06d5dfe000a2d47e6e4e6abe7219750f1f7892f4e09fe88d13c2e3b53dc904ad58eaed856a4abb0c10830b96bfc1b5764f9e4b34b0072be314608fdea8c5005d40ef99806d4d3edb72e73541fb828d4b2adc38855e09e974293de25da6907f5ea97810eff1be37f88ea879e545bb5a70d2187edec81bd57a95c0314df4ad08a864156579d50826d0cfa511d335ff722e246151a7afce94126232f6bac89b13c142d29e7521479866e35b17c15f16ee89d798ee8bfac5868e505031586b81bfadef4aafc2ecdbde649f63e07eb6026d09910d9d3613a9871b5d1523cf5958124f96b5304d5225b4bbb03aeeef87753d0b6ab51a287df1e9031f56f755d3fe5a20f79b7f0f467fa97eac5bc09a1adc6ec285c8f80ec5c184b8b5eae326300a5bce0b1d757c8e4f27ca2822e73745009291f0d9032051e15b567511908f3ec68840cb6ec6018a9a0e30f2e34759743ef0bc9e12c9b32f29f4b70a998cb8893af2dcf17e0eb4f48e7ba367f68aea5516e7248c8be1d1f896d7e8446fadd9603012dc13126878300f0868bc512221154a5104882621f831e60b49d04fa8a701256b3a413b9db4abc5af10a3f8f4c26cd0b3c2f55a58c9380143d835b759bac7fef824515a18d79b6dbd361541047c79653ab4af5473b7b7e67a6755add78d5c14c0a9edc6c7dd42c3d0359d9f2f6961f8930458a34c4f12478ae45c20969c4c18654d31a7ae73902757b3b8a4eedfd16d6c0d22548d7b8ba77aeb4c1e3f3766b6ea802ee9bd92c5f98d00be80c15e7e3a82eb0d100436c398781607dacbefa98c87b3558f363b3ecb1ff313655838f864c1b2e0f6d6369bae4eb8cef98f564108ab2f763e590a9e9201f4e28ef1971438c30f4376c55cfce9b9910f448e31d06c2e456eb798476d56a890660e45616840377ea0574d1c066ae2fcc46f41cfbb511e5efc4b5c60e00e4846e157bbee5fe3bcd77408e3bf721bf871c05971a70cf7a13c782bb4afbdb1ef800a414260243fd828b67f49007eaf60b3e32f4e2b8186291075a0b1c0a528abb9da7974b3b1e8b20d337161ce234db66ce82a88ae1dc880933343961267cb4932b36aacc5f136cb474bbdb5e4c4be4cd74868775d80317bfba00ca4e58a39d04e63bb797de366c45efe2e356672f567ed1f7b2741df7543d6faa7227601eb7cff367d5a1ff320ca71fa2a1a42866239cc3fa5eba400ee4060266a05b8fe1e729908b95ba6aff8fd76b5e7df547df62cb89f0605c1207c869d7214e4e6972ea6e47b18235855d6f28265a737b4f64f0d215943f13d219292036c1cfc46bc61679f034919e4fea80d882a5121cb3096a50f2112eab265ebf75b607b93e14ceda4e08152221bd368cd1503ce375188d23514dd0936bf980d4282eaa6fe8f38f5eb00c34e3557ae363538a2c15b560b9f9322d1f17446e8f3fd317126986afc2c5e9fbb96f8ca7148f53cd75a4b845a28034c8679baf1f5406564b6e4b8fa8e681b5a9d208f3a1b28e84d6d52d4baa152524908d50d71d9c0d11bb5665c8a6bad669dbf303027bd0d534434f9e76f2c300326e25d00bd8d3bb1debe1c3984961c0ea8dc547e8cb83a8f3b044b673f4a08882d103d6eb143a9645a9a00fab6f1167a2c09015d6ff2dbe4aa4025f604a63eb32330f832162b6dd9364f4ad6afbd86c8d26f56d7d9028dbb3051c85a0c86ec0d7961fd6008f87dbe8347fd5ed1dc4c27285364f63650f161321daa83ad41fbc3412bff800c062a78cc5caea330cd58e63ea9a9d6de2ee069732799f52f49d513c658a44a2122b8427a405d706f740600f855130a0ea720f76b3111dafddf0e2ebbd13f60640379993889089ce508b1343f485457cb8e0c09760d3199b4ea940d584417259e41f2c66853ae4235b6f010cceca3859952b3daaab55da14adff0e421e862f138872c2577637b3e12b00384cd32fb3b9c97b0d59e51f2488e379065d79f5a834b076ab5b35fe4c47f2c4c4f43e622527abb8f682fe9f262d2883fce5c9f16b7566c4e078b67611abf72cb8a0263ba12a6c23b1a04458c759f2bdf6dbcc460bc5df48146468073b61aa5ab4a9c5f6c006f54f1bfdd85373f33af29d68580eba4cb6dd88054c81b3bb7f2be8186e380bee0b32a1b84ef6319798079828080361bcc27473a9634c23652ed6b2b2c8f8d5a6721551c780870f1787726b121263e74c9464a76282dca27249b4532e49455a7485e2cda4ccca823f62d3b2869602197a6f1ecfc9d92ab6e231996e603e81e3dc648aebdfb900a3d929502ff0bbb3dff813660c9d5a417d857c19754ee04e50f1241831517fc2d2a71c5e238a944992cc50b7106aabb5482fc7e0a2e6b5b11bb6845f34ede98a18d5f07759e61603de502b5eaabe59a4d2c69f4b0f8e73a9bc85b8950a54bd91bcd0366dffaa0df736dbbbc35d6accb5ab8b22a870374521f2035c1878718d7d3b025838da75d8bfa3ff36b2a10a3cdef1b150abf3b6be95a5c096a921a3eced20f509dac4ba43f2f515af2b65d3b2ebd0da2d7a58500157a666b387b1814d0a3e84f64d0fc44507b0b6792c0c6bd90ab62e0f75b66d50b6f842cfdbecf1fd043d642c5d5b5fe5cb68af62e6e23cc6f0f9b1cf3cbd0233ce48a996296b6609be1c9e7a027cf76615dd11208f1fde119099352cc17e1c9a22f4b71c3e628d72b620f3cb4bd40e4294ff8dfe19480b5b758b874a737e6092254638a222c83aac52fe0f66670454c313adb0dba2b4e95741d27104bbff159e999e23103c00470a7feee6f4a35f764ec81a8ef520cf1e8623fed3c06b63c022e40e7638db269b8add119fec50456b33224c14486f705e5b3339c6f38aa4ba6dec8b098c27447185ca50cd70772e5389ba703a4a9f8649946671a238e1f005aba0b3a18c8ceda9daf4cede6782d27931c638af3f6083b2bf10ff0a632ebd4dd528da3aa2b7a8bddff2901d902b26d518a058921eb0178ef08e24f7075f77ea0c0d0e72f29847ac7826230c0ddb5e7fc8552ff92c007e9141f51384a12e218da4fbfa9a7a4a1bf266aa975949e120db1b6755ff04adb07c66ba9619b40396072e7cc01dc3dd56f7a2f928a82c8906be416f6d5c41354881f9a6c66a927292f8cc2887aee86e90da32fa3bd9d72bc26dfd334f943305fbe4b645df83fb72c565f61860a480dc0f2f3360368ec3715c2c4a312bd2653051c8f29fc14e0c3d1f515e04b75ec02cac2aad8d411306969d9a8da08c3477eb6201bd54c6ee643d87a89c78a5c8ad48590b7a499cc44ccb812866a4c48ec2da5f1e0aac741464b26988459f3724ea4cf103c27e4a43e5a5fbbf94908878894f8b62995aebc20e632d924c82d9669f64b2093cfe023cdd1542c8f9d19e5e7ad6ed7920ba6834cb0cb91bce48fa94be47c1833c6ada4090509ba38defab7d56dde8168bac8021fb5a2aead00809f1881d53d26fa9cbc824488e16062fd9f68726c837234a82d518e3d10c9931295d20d9affa5fd18c0b2dda299cf1d6fe0c6e6959440af9b397f3441bb9881ba1d2df295d12686ef6b0bfe52fb2bef06620721374328551040d2fa434b161648b058b74df2a7ccacd7609b93421f44a136079c79a3e63bd3b4f79717f3c121ceec2c3918464f5619b1a2e83a7709fdf6d1004b0ee51c73e740b20e329847304a82802e02170db386e360dc6027aa7ba1ee35d7eeddb41ffde093073d92899d568bedee914627c8c48427376e7b5d5ebdab30e58147dac5638090e9c71921431f025f1d4e3ba3c68437555357c651336b326c9c519544363d5f4faa91914195314cc873ef97068d928a6b4e5c6ad70ea7a7b09b3108fd5696aaab800eafe463ee52a3f29e1bbe8a968e84b762484a13714ee260759b4492b749c46ab6603c13ece34e301c13bea57d9de706edc839f55b432b9299d2d6643817cd9d32d0d9ddbdbb23acef51992b62db024365ac2db4c432c531cc1ad18c807cf1ee39dcd842aa9a09b232cfd09bfce33277a8ed09953ab3b5d24e5a8a02fb4a02ceed705185880ecc47cb245665cf640ded4015b4afda053a5d1dff77e390c8105961cb3a954c28ddbb9efd759080dea99e94e69b03b928c8667fa4797dbb3cc6ed093bed107c817780f60729036f13346f05491fb837ef1ffc61be7b61d0b7f8dabfd49ec24cfcee088de38daaae6b4e740ab4faf16eaebf89962331a99f17ca5955b15dd1fa493b91e7cd218aebbfaa7d348b1ceea26951209137448caa93fa466ca32eda497a5b9a4fdbd23a10d9742e74c511a1648d00bca3ca23abcd4f18b7cdeb362e020c73888b76b83e70d26ee358c06933f77d1221a8ff0647200e451e971fe45c23aff60a88baf46f59a0bf94e99ab9337b0336ffacf8e79db92067d2b744134cefac1241dfda288f5c6ab293df7469ae0926c166e999ac99c8871e571eab03f82de73e9de2d8f4deea3724f795480cd47e304f27f2567cd94cbed52e06f1f1cf7af2feaeba8b95927eff950bfc26aa0cc3e46ec7bd5d4aa43374500f8cad4f153cb586620b9a0deeec2cb12ba48bbc8655c7fa70ccf94aa6891b5cc8a3c98b482d906d72e9d425301d0cc6fb4ec9c4a5bcdfdd74fdcef68f05fdb78f2a1c5ae32c28c43ee900738f31ac1fd337ce95966b3f557a727e0c3ada6c6aa61219d92fd5cf68fcd9b444f6b4fb6178b9c74238d2575f442a298127f282b5ad416cf6a365a214048489139918f93ec07f2cd864f5482c418c7336ca4590a7da8a20d33ffb7be19934c80b64f4b982a55b129f4896685534b83251d54e46a2971c0bf49ded9b13a77ade3de9a61f2204a46ed9cd7bc444801381994c8ca5a66abd70936f8d11e2a2fed78fe9fe8889dfcb979c9a3f11f2c2c1aa371d1e98c4fbdaa95d58c6b22410c0d3d3460077dce654a1decfc829f117bc407d06ad9ee6aa06bf818ea2f25312b1cbbb5de527ce9b5c5ddcb0df21e3442ffd149b24af5e59eb4d7e18f68b02b26e57fdf23e7af4fde3e672990295c37186ca67b2abdff6b46e1ff106f041279b61560ea2eae64649c65be22f9070c3239b0cf7929b0778c43dae5391d8d3b8c335ceac672376588a34d3b9c61833578e8d5a9e6e9f72748d860d7af98f7616431d1ae1ca20db3db6ec99d59fa98c25a1cf478e1b4a643c2fc9d3e482d56bedb1b7a1fc9c3e788d9de281c7356b82e3c9e1c9414a0d14cd07fea5364b6a22dcb3b69b6f447343822098548e3ca7e88a83187db145bda17f7c48cb00e6ce36d53e2d1e4c169569ee3fa03620a7131bd5c033062bb82cedd0d0ebc1025937b2d85a3cbcf6ef4458a57525a66244be3a62b582bf2b88549431cdce09f6407e1bee83d3fbe205f585cc7cf9c1eaba047a01f51e13bbe0715a9112c451f1daf6074a1af051d8b98863b6fd03238ebe295995d60e7a26d2f95a2b4b0d617af299133bf357518b84e942bc36a88b4030d91a7067e7a2ed7bbf4e9abda8c6887ecdfebda04dedabb9ea833123507835e0357ca1513b471da73102605ed03297b5e3eb7d3bd01c670f992a7f19962b706e8d0ae0f073638d633b34a1229b6979b8e90f2a536cb6024c644e1f7ef211451dc509e061b294c28be188c96246614a1fbf52db8d9a99f7100c878c1b9da98ee9e9eddf7fcb386061ddf46807c60b24d665f0fe7fde205f91021bfb87c8f4c89b5da254d185bda9cc2f48303b483ecbf934575aa45d0d58cea64662f0fda4d97790bbcfa237984cfb45a9cd611b533dc0ea997d191d14d307c68db318aee8f99544fd48fb86f041fe249a14263e6657a5ee732f7c5c9c97a8924bfdddfd75dc67da65042e711a3cc144f46d10a1a9fdac1b1b321eacd235299a1fab390df24acb739d61bd60c6907b9a3827958198e6e2b5a1c90cb9b44cf8db9b6e45f710d7a39c230ec9cd855af797555fb1d73492e29d17da0b6dac59c2ccde0715565efa1f62898c9b26438c60fc3b9f859bbd33a8e05e1d3d5a762bf19bc7c32cf7d4c6bce26fec6e5c8c537608a1c2aea2e1e5cca5bdbb45a8ed048514ef3d298e7dfb9c5408d941ded6220a44c184dc90c922a3ae31c9248c5f31627389770a59f9431fd0139c5ac0f08f69151a75a5a6a0355b7beab6be9829146ada371aa5791c861dc77598f09448af20deca73cf98a399f35c36f1167ba426c6cf4b8b9b8a22b961bca83e45bade098e20782a9f70bd54fb8eb6eda3acd3a5bbb553438cfe37e1f7fabf15729d6bd562cfe379d586181b71b3d3c4b360852003c4363a8d473198130642972eb3434c3a5ca9b497ec7000e821c3419aae75866496bb1b0a9ac6cf92f799071e06809f1f3f904cd18f32629e2093664755803f62f45942f5a358cb1e925a8694998cb14cfc52733c356cfd739c3976712ca7b007e08841639da14e429c102a8fba3191cd36c1c56eb06bf69afe3f2afc4ebf137c617faacda6baf5cfdcc6462ad02f63e8a5375288d0de5700d0f9f4ca82a65bfdc405d3f96fc663658f0aad91305b86ead3b21bd6561a40db0f2c5b0937ba5e1ecbe91e9c50b1dd6bd83a8145b033a7bb6a4ad4896e0ab160e8a52d39d2756b1c8d8570f7081ba217fd8803954290788882befde24b4971723b0ecbeea14d23c92eb6a0d7022a84aca072729d7ab1a88927a25f19a2086f846a44a2726ea26cf1b69c58243e219c756d06c361e1e161bdff0eca10bd30d23782b3374ed421f50cb66c9ee063ca622fa78c8cede932848f0f8f91bd7a0eaa324377c109808bd66ff463a72389c4b49f2e349be70d07fcb56b28549fca65ad853d70df66b587390febdf6b1881cce6c1ca9e9fdbc9f1ad68ccaff97234325d3c972b57ae5723fd73f975ba640f90e717e9284c111b76367c6797399452d37df6b8b8d22ed5e7dc1481a415fadc06673ce4eb6435d31acb6af68775436629a57db7a0aa192310e8427468e8e310bd3426b7ffab00110324c0c7e04ac6649b6f167fa8b928b3fe12ac162db3f2bc355295650fa2d976c64df69a8017034683bb4bd4baacf1cd8502dff20430d48c907107acfc4e29c584cb497b7a471fbde90aabab25290d853b8ebd2c0d49c2c201eca42a68a15879cf391671946319427b237472cd35431128ea7ab6d545617321592c07b09fff93e71596da30689b3c15368a1c3a57890e0ee5752bb4356290024fd1bd2ebfa19f7f3ca57c36d296ae61ec5581ceb77618dde2821460553ba0dd6dd68026b911f4af1be3986198966f90ab757aca2f5143f1937d09c3a08047b797781d1639db4030f9e59f8c5b71a71787cc84ade5a385ebceb1946177a056179aefb49e1f69ed0aa67901b2d6b2152b6c1fd1db67f358093180fcb8f96483fd35a87fa14825d3849dbf479be493bb2d1c639674bd195b5ea3caf49c2b78eb0e953dbf8fb909910c87efc6f9b6592c020333e00f83bea4bdebef4e107798f9a8e89fa5d063d69f88f31a53548ba2406407251f18c3d1ca6e392fb81a46107191e6d906b487469d0002afdb0f32c39873872a49eee649250d4d5d3a7687fde2952291c8ba78fd9b962060df12d212033303691b05eef0ae0e7f31b7e395576708d211d70281e9501618673afac20a93e82f060135e51b29132a0c9244551814bdf399b746651279ed135d162e366f39d40e3a49e907f72bf7c66fcb4ba75b1f447fbc3ae3f390ab4c10963d755ee188a9b0129416161995adcab12177976208e1c93ef48d3ef55ad22bbd97781dc7035c9f5fe25f47b703b1ed50dba311d24154ab05dd88ccbb5a8cd96d4665829c4dca5d5b22affbfd7e842ffe5e87bf4326f957392229bbc893b1fde9e4b2191a3345490d418e9298179661104f70bf6cf9a0094f9d37be98b82d98497573512d8f6fb4b0b0aa334a9120a5afef20e0379197ac7ec78da3688d2c9b590e40fcf866acbd1d857546522788d1f3ae73f330aad045c5bfd59b8a399ae626fd67d9797b32d6a279d42eec3ec8a2888258728f7c329c4efd0f71b730e57f9bd87204d40ac1ea6032a4b8ee3a338aad58c2f3c9795819af4cb652dedd475e5662d9c0cd23e72a8f4e86f1a63e5683c814a99a6595b779e5d715ac91ba62c1ae4ca1651581506ba80c2ee0d3f97b979758cfe93f373873f4775c882fb3b5815b9274595bf50488b935c82e0fb4ae4d078d30bf0843c89e484bf5a24d5de602649e336fb2b79da6131f96ef1b5f82cbd668f4599fc9a92b4e9ffe3468e39e4c8bd90531952327da74a522e479c66b7b1554c9a72a2e6db58fcd45588c9ff4f48be5ddc994913833b668c275174b9d862dbe8fd01535ff2bcff6ea030842ed3a4d105ba07feb0098e39f61a4cbc06bfa153c598c10c5de57caa413752878c7599e5db8482b6f275db2185c505bc0c9670fa0afe37031eab994120acb935bf9dbe6cee6ba336dce1b44732c4267ee77f5db890041e547bde486335b9a0b85d6640f6534d84b3729b3436ac1c0551d687ddd8da9abc18689e7e932d5d0e787ab5ee5f36eb53789b9ba2b71d7a4f7994e56b056d4a042bd2cac79ad12d87726ef8cb97342e616269e9f87493e95dcebdd91763b134019c0a76e8b12789b026ebd1d9caf1930010aa1a5c348ae2e6273c885ffdf8731b34d87c293e77e9ef14709c2e3b739dec85d5bdb8f5ebc9eb610240576435c8d222ae0c8ebe5844980560bcfd45cacff143a5c208add9011bf9770b7803fa90bbaa10f58d856250b37e481f325c538e473dee7863957121374bf12172321b9c99975078e43a0e1e40138f9c31d6dbe5e06fc881de840e64899c0cf342a806916147de3cc342832a9514eae9550d2cd1166e823f404a05b418e5f9ffa84352cba3007f9d37e5b00049d7c099346257fb53e86b919b45a9c6cd8b67cb3c4e383fcfd5789f2cc087d6b459e2a7dc96d08c826c43410b3df22021855c7d413d9cfe7ca79fa860918a74941e08511595fc9a3bec2e2e0c6dad05781c0a0d6b6609837ca8f78b0368b1217b121cd6ced8fa48dc131709434eed65523269abe95f338bc5e3fce0046ecb24dc1ad8c8fa68b5f9263361e4952ca1aee9229811a5ea85c9c4452235639d1eb8105ff88c048beddc0f7efd3690da8b9bbccbbcfeddcf3e3c9e3ea7b46a5b40098fb85a25842911e42a714c2dd0fab403340ddc1af9484843b33c7f5bed80fbecf68180c9b397ed85c51d39cf08c5c0336b149e6d1747360541e84a93224ae88c1b62384b938ae25ce17d656b9ae52fcd9100a40dd7793ca67357f3fb00621863a490373f0db49b1aebaff7284d450922f1e5243bb7fb5f7230dd7cb8db1e08893696908cad4a45711eadfce8b0b42a9aa937cd011bd5c4a8c3a2ec771b3ee4959eba5e4a17545d1c86acaa4805e4aad" ++ }, ++ "ecdsa" : { ++ "addr" : "0xa16c987b93f1b3c51fa8a9833c8932eeaa566ce0", ++ "claim" : "0xb0c578f123a8a0c96354a13f98c4c2cb8a67541f5ccecfdd0cb6e61aa77f7768157dfb3ba59aadbc03350577f6f31b4083bec30291a61ee98ecb3db2536f788e01" ++ } ++ }, ++ "2" : { ++ "id" : "0xa5ea2fcff9e3cf29d0c6f5f147b67ff24aec3bd4", ++ "keys" : { ++ "falcon-512" : "0x099202fa37d5e165b88428d963d2a224b8fc82ac0e4b3f6a02376f18218d1aa7d0e910e71586aeeaaddc2a557124d6ab4f9a44b9cad02166413cbeb14b364e13956ea326900eb2900802644167639045d76bbc4e051654cff404dccea94402141ad9fd992cef7a8fa6478b3e6f8912886e9edd1b34c29385b7e964f360e0fb1600787934486f461c95d577d2bc74c4dfeb969b4798565ce0225ad27aac052290a44f844ae233e082c97e4498a31117ac9d02f3605c856e2dde6f611812161f89cb3a54dc936ca1e740a6c659405ed586a9a963b11c89b01746325e39e645c72b0c7e4491b36a17d43ffe38d88c601a5976f5a9636c964a012bfbce5f9b371e7c3b38580d81c6e12b8e8f2aac219f96245d35b4f4afa6c94015b055703b8c4dabaea4ce2577482f5b34fa49e56a912dd58d74580b1f94e1d2056594ea64bcdb696b0baeb33c86b6544761a3ead9ba9888cb1ad51f7027ee52b21e46c5eeaf3f77bc0af7efdc87acbddda7dca00b6acc665002c26447e5b0e0bb5ba261717c68dea7f1576462776954d7249c2fd0886f615ad50d53960ca02d581a4a25517c050ed467c7a820bce6250a9ba2e44fd67fb21bac843bb134c95360dc1c50d54b7280a94440d018181a9d6374bc64d782c84471b47287d8ea748c36cb83cffe053cb89a9e4ae71df497871c2a728ef210903e5b7f39550d0331e15637be7e28b3a2fc05b0a9b0c5a06f9fe81263c3a94403d6c288a561288ebaf788bfe271a578a1a795a85e9d452b61ac204b297090617286922376bf0a8d67dd35fd705b81260b7aad30132b965e39bc3cd64d154c4175951704873992a814814dae5c6bc1e89a83dd91144cd1b88f6ce449900058afdc53bb44bcab63d30cbd6df115a5ee8f5380a127a160e922bebf7b408de82514b2e2550a0931e065565e8dfc389d454823a55b03e5c989b09e3791f656794e8379b7b4b1617aaa9770366d63a657f71ff40c69b1d5da518ef1e2aa42366cfa38e448563f6c2db5e3089bad5520ec26105fc885993630c10db357883f588a5a384cd6de688e1bc3b1200f87ed66ba3d4a4b671b2a500a0436e0955904030d76577aadddb8c1ed21b027f198c072f654c3abb086e7f185980f49d0e109c1a82741809f8afd15ee56a887b392c5b172ba659144a7e99e25ba19792d2a3c0ccb481822839c8c70c65c0943a2994ec9f6085b7ac64ce2b35489a72dd6693d25f2329264e063db26ad4495e3ad00f12df8cf914fd846" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39883a85bf19c4c6226ed184055922f5d874d232c6c5b4df688d7bc238a8f67c4e03e4747c85bda6563341e70b135e469907a1d3e727489e05f7ec8a668ebb8583fa6a118448a6668cc5bfea74d54f5b38a2e7f8714acc751678730c0d3fe735e8c5b7f02abf9315f778e0c8cec1bbb6aabb918dcc9c99febba4e3c3e3ccd5069799964ea34437aacfd7a44946125d107ee1e11643dd4df6be35899e64b6bbaef2b1953e5bbe21abc3411a494157f6797070f9122eed64924218259599ae69c2d7941e67729bcca3ca32eb2e0915f3a786ce88b25d30019f134bfa81b6475cfe74d9422ebd3481ae35e4d052ae0d68a77a14d67d9e409bcc6eca46b6c71b9b946ba06e70b64a3b9eca1ea338a7e521246d017e2107aab0d5e1a693ac713edb76280dc3076375a0cdcb586f712500dcf9f0b6b2846714fd2e2511fc7c5f0dea79fe5ba22962cf01b4203deca1fe5b5259c3db98604ca7424db15708ea0d0cebcbe0f828a3a9863931785231fff9788d3b0e6c52220927583539240efebcd9781eebb634b72549d24be2ab6cad7da8366ce61e0665314dbc06a907a63f3d744533659364adb9b5cb6cb59903a66ce97b03e88f43ead94607e88532ee2b96af40bd2b8360bddf18dcd9fe732608541e74ea6a3e14121f468a92649acb9650efec47b3e4d1a7d784a8b0c7323cdfe7f2390ad61f49c67e2093c707b8cba1af39294fb6c86fdff3b645e25df27adb7970e2825e0a4f61bd35f9fbb53b33d7cd7b9a699c7ee11959f11b2972a91e2f92129a3055d846945731c6c705b4fe7ed6372f952b57fa7ef5b214cf6125059f23845655caf4ef1ee351d4baa9eaa5a72de4cb36847e787eda3ed6338bd7cf92025db415df395f22363db33974cd203b583339bee8b99dbabe3fbc8e6ecb76f333278d08" ++ }, ++ "ecdsa" : { ++ "addr" : "0x5e13d369c8adbd8079272b624343ee1edfa4a560", ++ "claim" : "0x4732138455fd4f975bdd2fa3b9b2d5717315b78648f8325cca9d350bc460a20c14ed099ecb4e29c7d37c715e76c3df0fc30462e41b0055c29b4b9285e46c434d00" ++ } ++ } ++ } ++} +diff --git a/consensus/common/src/test/resources/aere/registry-v3/n07-falcon-header.json b/consensus/common/src/test/resources/aere/registry-v3/n07-falcon-header.json +new file mode 100644 +index 0000000000..3bb2585b28 +--- /dev/null ++++ b/consensus/common/src/test/resources/aere/registry-v3/n07-falcon-header.json +@@ -0,0 +1,62 @@ ++{ ++ "description" : "row 0 falcon key with header 0x0a instead of 0x09", ++ "chainId" : 28001, ++ "requiredSchemes" : [ "falcon-512", "slh-dsa-sha2-128s" ], ++ "ecdsaRequired" : true, ++ "previous" : null, ++ "expect" : "AERE-PQC-REG3-07", ++ "manifest" : { ++ "formatVersion" : 3, ++ "chainId" : 28001, ++ "bindHeight" : 1000, ++ "count" : 3, ++ "0" : { ++ "id" : "0xaaddb4dde09de5718a906d83be7db3d58e0ae32a", ++ "keys" : { ++ "falcon-512" : "0x0a501c96d2f5cf0b28fa00c726e5359c5d36a1fa069971f854b7d914fb2f1295e68b2c6fa91d82f7d287f55ad493c87320bf7ca2a5d5e79d7212e8a540c166b588dc03f73b83be060525b367d9f40f5e77e7798c60b6499767586770722820b3b9e6013cad3eab5fe5de96089a29f34919a2e9ebcb3fa03a3e714593b7a3356d11ffb3441ab40ad94474da662a71aa2419dcd50668cd5d8a9017662cb60998b34ab5b7929c58a94d5e133ebbdadb2b0279543067f76bcc4cb6d7e0a5edb7625467e3ddc92a01206e1b8dce69be31928687d8af4d26633a07e73c2830d5299b878977691cf65700b65b6ea2463e51b6136888c544545e59fe8cf190a7944e215a785b682623c95a79eda28e25e0e1b91b49ac89deaec3b14a3c431d9046a663170111ee541d81b43aa91f29dc147c6fc97739b3a63fad1ca84843d0a65b8d9396f28e9b11f9a41453ab18a2309ae8db03253a09fac8f0cd634c76a5e938a44719660944a95dff056cee43ea99592c3899c2880d7181ee3dd5c04baeb60e1369a69430a66031e3cb10e392622f5246a71761760cf417dcb40ad65f60704fb74ad26f26c3af7513a42f806895e0298c25c049187aa536e0eba21998912e621846c2ca0e323744ba930a29850fdb385c8241382296ba28dd4df05ddb1e61fe525949034b59929a784406de240f8086b4074825f419d5472a28a0b157500be37e9f64897db2b645d3807c48dc143266c99e7cc1638ae278772493a2a4ecf74e526a514bc9119d7129c5a0d115a450ccf4dce05b76d4b6149fdab028006df7ec2209923117abf7578a082128cad42aa66b69eb63acee4456bebeb537ca57bb3d3487f95e4f06c5cb29f292d3b6284e5a162cb83151cd9ae56aebbfda150b7edd5065302ccab70892733a1e096ba0da5f51b42764ad23060eb197d5460425fd9c7a26e7dc3cfd40eac3643539feea72c9ed41569111a7976d2c345ac2183fa2271b424526709fd9aae558a23a5cca29f4e2f31629746a71d904612e95ad9977bbe74fa32e90fac62625838cac49f50e5aed4e8879e2ce2e5651c4f4ba0c96583af9e1612b5ff1a6fac5027c0a308815e592308170b915b4a2de1e8d48e9a5730680ea9db8f3326c430241153b3b218d5347d5c843570cf80ee813871ae10f6b8ce4ab7e4c5197045e85b1cb4977f44c33eb85894b6555b4bd288a50c1b656936841048983c00a01631f10a84522cd613fed0d4beaa4aa4b3e9f30c324108d909e59a80150", ++ "slh-dsa-sha2-128s" : "0x47a0b70170dda85f843607f6c6fcbe6e6acc7c22980c108996a3fe72dc9f61a6" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39c8813cd3b34be58eaab900555a67486034b1923e0b00e435661230cab85f07690a5958a5f5e9c84f033a3dc2039a5296443093fb7fe8d41895fa73be3fb34cefc6cc36750d534e6a3c47307294694729d6cdedb633e8efe8979a9aee486eaa66136e342c578761241192610185feb2d3c196bea0e79222437b6a8e08cb09778d053b29552df96507b1cdaede8e9aa7abc18902f29937f30e7cee6868f349f7ae33738237dcaf86b8e8e01238f3d8ea6fd4090a8161db65dabeb5ded5499e8cc8a5b32607abc291b36a4b34b327d30cdef18c1825232e69a2b09d539ed84dd2a4756efa64f864c563943b3db825824f294c1bbfa2157347b0fb0e7f8a56ec253b39ca9b6cb1ef7d3d7c93a6cb220a7dc50c365905ea5a71575c3aeab25b33523e4fefbaf66137f45c3d96db719a12d2e2d42fbd6cdda58c5a1b958b28c2a8f2cca297871a147dda92a7f008a359027a9288e42ebcd6ea9542f10b66dbbce6e7bb914206122f866d9adc1c89cbf8bbad9bc9517c2ea9018b61d4d2df9abff1dd9f3a0a6faa72a449af9c97e8c4090f3bbd9824298e61599c13c7eb89677c0e845ca2907c728d9296c24e96b6a348dbea7cac62671c9a78a531463614ce321e28ca2f093094ba5f69881e6cd766874622ca769ea556ae757cb7f9546d99f5c90c25e7b8e14f3b7f270861398800b0604ec2a3374659277a23cf6131c63148a41b05b3c06e2a98a268f1b9f0df7969addef17179ca2261d3c229ae3db0c490834564c45f7b8ff6d3bf70784779d75915fb2e2d5bc147bc941b9e249af188f63f39b028547cf080b7674b228e20a600e3b167610f814daf105226f3c1ce5e07834fd33dfe46315546e926fd5be83fd4d47ccd5bb8ae736ac745daabb59c87b9edf9a45c9a1d1617ee84e588f27d12235c59ffd9", ++ "slh-dsa-sha2-128s" : "0x0e8f9bdc22cad3613ed07fba30ed04219b9528f9b657119e2f0886dc71cda4afa7d462fe8bb108feb58d998b370b2f7e162390713d1a17eb7de781a604041cbed13d00effd3b24f2ff87cac74f61e7b7f7aa6a259dc283485179ab4bb966793be018c4bbf4475bf7a69e600a37246908f662813813d4b0f4f83757f4064c5c0713870a0b98b5bb99025dace06100497fda8c73d7385d123afd4953961066e7c8544de3fb620ef5e23174327c2b64089b3fe6df3eb86e83b12634a0c9cc0d7844c894ba6d83afed6becb6f5abcfff397c5cea8064e5e153ea4253abe599dec1614b449329ebb25861b69a9b22228d1a03ba51532ea64ebe7603474a15a2806d3dafa29d57d27c5fa894da673b85b4674ce835fcfbd391d328ef83504101432bbb0c83d7be462b265911aad862118af6f4cea4df0f1dd38969c69428fe438d59d22736fbc7dd5faf6758905b26ec4c99d71e4b8fcc562a694ead91569c9a916df5ad693cb2ad0b7ae4c4f3c5b7322f56612c5449e0339dbd367460c76ab89b6f44942cd33f35eaf33c2ddc0c6af793556d5202fd1fb0f9fa1b7ed45c6ca68d904e476477b71a0bc6ebe248c9b4585da0c7bb186600691269bb4c836667a6d73a455b97127d898b7fae17e1acc6dcc3bac3ecb14da131d5f8adaa64b054e2f569d9bdb164792038e107848882de9bbeff295905c2af68d4c6dcc8cf718c2de872ab6b3d18e00d527166f8ced642281302e2acf4cf4489072a2dc3d55ff8716619cde494be1763dce925438b33ff1b91b35eb511645832720ed92552d4880ae53ff6516cfaeb1d48c923648e502e4038676f7c82e532ea713c6b9348c80ce3c5735f437491d3a8b1765294868c14123af2e9ff61e394216e630c71ff976072d2a1c50cfd8ee1ce27aba5bcf9aaed4a51521bad5e5d5e66abc7a95b215fc8004364aa4df2b8b97b14e3950f521b6327a55fdff9139fb0bd35237b022e3aa128d36c8a60f4621d25d28c59a97418c7dbfc15d900ba626d283632732631ec4a948f66dd9db3bee8c2cf60dfdacbb5ad4c0b2b31f8428868cca035e79c95bcacaba40a9351b2b44cb29753b6b9da0a751bd5af84c9094d5fe91e97501d4f075392290e8516ed5e41b41b00e09793353707fe5c1d942395074637f3ee0a0f105876d6f28a74f9558c5f360e98f047a99af35ccedef8d5cd299365e81e7e91f28a01eb265219e21aa7f7ce56b62f9d2a61560f9fa39f2765f5b50920658100a638aad03482a687905cd27dca02f1deffd1bc49a1be1ea7ff1a505da74fd932937d8f6a8bd75ef456d5f7b71ca5357bc66db6cf14368c4faddf4996363251e6a6113ec64d642c319dd85830d8b4c7ee1437ebfefe01f27709ba0c412c266530f5b6bbb005994774e8935f1d91069f9e7a8cd2bb7ad6527768473affe24709c10294eb588aafca85b379bedf0b142b109e1b186e635b0625c4e59576266acb5f71040c44035fc9480b13932bc657cf332b12da1cd7d5c3977f51d5fa742974cd256e8e3662dc698e0516d615d0a05ea9caf12338d0dcb6151e07f184c9cbd5e59bc40b12ed6372e2d6bd42aa0eb6c3c888f264a8c0d3332631d4919c921cdada6bffbd01ca5445de0779f9723577ebd7e33ab0e5f577843aaa6cb8cb5f0508c33b63913a44d02b76bbb1eabae325581738fbddb5d4fdef8dcb8597bd29c6ecc631839118c44f66ef8dedeca65e58941c30e0423c40bf064b8d19d28dab3787238781d492720236a7ae0695ccc867fbb1cf207ebecc64f84daea66b6745515b9ac9b725061bb9958ed79ad6161318a262528004401633d47a023c645683e36413b8653fa4864fe98c501197c10226b1732337842a1322bb788a00a0de86758139c2d9ea3c5b26bf5d7a4a92cab4cb686c580e3e6cca488136f0da9279073b3dbef9519168ba02588fa29cc60d02273805b425b919a7e2e89c9086609982163e09d5f6eb9c66267ac7be363aadd4617d398d4bdeca37a838d650b0919faf13b78642a058b1bb96b2ed1482cef9bc6e8b2e061e6815936e15a9c754353aaa786ab141e95e5f6c464a41b8bf29e28e764abd638abcfb342b54d08c15ba7e24e6fcb69b844e16cdb5cf4f50db60ff0699f969d8e68511fcc9e16a58e100f80671af6b04ff3edda3a4f05f9183c0c3bb7c1061fee2d3f04e33fe75f1354e6de54f582da914da0138e8565ff45ef52f638cbc33a24bae863fe91e58d7c5da34273438f15e10d4f59db16e505620d97d3fa4862a4097a659925d0e5f4e073103ed29a600b051b83b1f3a21381f4b871c18d262d7e43842c34ed80661438c064aa2fd858a8f3bcb035b5e942baace7b50e4de5a73d5c51fc0843cdc163958a62d333078f4c7d883bd7055a602e04c853f9215c9d7f798403c007fcee124cf6099322629c449ad4ef84b7356110798dd87aa4d98ebb47abc6cc8748dd381d588b77db7f4e7550f6ee1ef4360dac6d6c7037a65297d4a0ea7999a5632b90ad48fba0a916846a216941fbd13d62ab36e1066e24990c19592944078435c52d7717b3556595b645cd2359ad151dbb67e92b14168cac12fb2cc5422582a50bf6e99f116751171c9b78744ef719282f1b84bf95b4092514f4c68fb82a1526e0942ca50e186632cd9b0b8b8d91e84f85e35f30f815601798fcae676da6a2d38eab62f22445099694804a36a34142150fb795afb445e78c241f0b645209037a8871cb5487c975975ac997a540b709e3df6bf208d9d8017f9688b152c9ee2b934f65393de8403244b7437108e6d8c973aa723285555d9eb92509b1747977105cbac7fc33e658fd51cd374d21fc2bf229928948292c1698db7934d0f9be44b137514d0a5fbb659bba83861931e03698a61cd20a449d0358a5fce7f288e18bb3eb62b7ba0ae75feeec634fc90fc45ce45239c5e3179309f0c202cfc53d9f42a617f7aaae586e7161a0723ccebb7e8586cd40e1fa12d3ee89b400dba8073b0080ffaab1182e8243afd93318df15bbf3ce179f21804fbb8882e855ef9e0739ce1536d8ebfe9856aefa9874b4e102e705a40ca4c3ab0ab7df63ba525189b518796590035ca780d348de49f0ba8f28456ca6f3e3cff7e761d961ad98b8cf01e855797c88fe2f811e41e787f3e4becb0ef42ca3b9979356020b447294ef295543e0ef512a247e4d356bfe3deacca8ddc5255e6ad047121eaeafe61d71e7f31395cf78890add4f8c688e4eb065479a63ccb3d0c09028bf60c700fe9d19195c26fcbd4130e6feceb52e192a2aa2343c05b43b276f51a7c55dff7233ea512942291900d93315438a96af08e25ea5b9ce656c54e71ed60d1eeb1665ddaa9e42378c930e21d93484b9a4099b7ddd71d983b4c42c6b1f62907ce84b24321422b08b847f1ea97befaa4ec30a794ad7f340210c800cf185ee2c6c72e844cc5671964e1e1ec58953500f149f0f0f25c34d5592de421c2e31535040020237b907e86d753094dd4532e1ab9d821e7583d4a21e1041fa7ad711f29ee3721a2aec6b0c46866a2de71ee850d8122f722898e533848e2bb851ed24cff9ca83badcfad88a171b4be064007aef4d759d93ae9b67b446f3c6fe504f5b4fe851b8312fec86b46ec3cfcb36e0f682e65e117702b888ab8566c9cc716a3a86106d2323c0f7f20fbc1fcd110bed4492a750befbfcbbe16820077dee281bcdf14509b93137a3998b2fdabc2a375b38857bed12bb8a9c67bcae7934d02d6ff89620fa8946c8aa524fde99c12fec0e25bd79788e2c15fc31fa3f27502cb952b9f9482580cf18ecabd92c55113ec4c4470c4dc06d8ca27a10474594eff708209e8f376b6f17915c2966dbeb0e35ac2f02419692c0d232e133b3907059d3a56ff169e7e61915c8b1067e183337b40bc1136241e862eb3ab3f2c6a72b18511c4107ed063d1e2303d0fe6842fb01c204d1bffad7e90bb44a365e62945a7f631811c9c37ffa5ac39c16b4835798686da5baa8e1eb6aa76b42f6b86863c30669486a175d6b3bc5bc47c5eb05b240bd921007fa39506c6605bfbefc9c8c493973bf3f0767817fd8ce126a301c5b8fba79628a9b3a03cad0c491a5f487dc5e89269e5d3bcdc2998a136a012486c5bce2e6c6dc595aeee2ebd5a36dd06919396184aafb2301d1889b668c4d701c7ca01b95f9508f47d4c411cc0397c244ed4e3e3ad7f97d86b6f8834b13b1b2df0625e6b4eae9e439815e65baf2da767d3b1700fc461fad6297fe4e8ed02bfb65b750c2d2801b7308aba9657df3c3ed7d548687f55e85c22343d1db343bc2dbe222fb76fbb3cf490cee7a99ab3a337c626a148fb303b2f8651651588dd4859fd65c95820ee2af85adf4e8fc2c03828ea7427e7c6b0d4a1b0ccd424df6d1450ee436c01351d8b6bffd4ba072756315968845ab7976813d93d0f0f2be1c00faab3ccafa71cd26c5837e87292870cf768c7837e18ddc3c513820c660870b339fc42c5211d33d892ef22b475cea3be20f5e47206efbfdbeac208e26e97c400edfd41f063aaa6b85a0cf86e23fb11274b405f4f796eb10cb97e70783909ad492ad9207ae7b3d204e59d69c886f91bc82a107d0be3ae85797a7cba747b8e2640ec49384f53c785a84cf8de37dd4048dd4b879c58768bd131ad7226506113c446fbf13d769794f1535d58e9c52e23c1bd55e13c647d304e297d968c759a378f1d594897a026e3271aa6b4daabe174d6a35665b35193379f0ee465df7827299c18e1012ac69913a0a5bb5142e99b051763de3e98d5af8b62133e25b32f4f12b787bef7e21dec42de8e4d99a0adc8f365d8cd3e6a5ff3064ca18965ffdc6b383f7ad08186d735a099bb0ee14506388c1a37f7a766d286d748d404457226b952ca6cb3f317b0f4399006b5b8c6eb89f6b8cfa023cec4d2dedde3e31b9a633c0888989b44ab182a5aba30ba78640f477ef1202f6496fafc2a18e283b2e4e8bc60415a1c9a7fd68f15cc1ea0299e3b26f5755ad9f13481a0563a524c6735942f5069dc1d6a070b3c3698e9c503f67a11efe59413e937062668d3439a5dbef197d24ebdc79944b17c549b0648af9b1349cad83c2a0a9e55fd893cffe2aff4626662ebc5014e70baaf7cdbbdfd3f92fcc5eed863fa8afd87f88873f726a0a2eafe41fa81edd5833f5520cf93b0fbf0660e48eb0258d313bafb87dc9b0d0d9349f22fa2d960238f67457ad644bdc60fb5eafd1c88dd2a74db4da0f723a03df08af6c64883f275395020341d9dd3c7fa049ab2bebb4d8af2bb8dc1340d1a80088c4b2c26bfe7314926ee64bf239306c05dc2ec6e6c5e0ed4f6dbe51f5ee09533f558d29ca6fd27092c20dd892c89c83223752006b23e5abecfdc733aaa59c8549e89e5ab0eae1b44189f58cf9cc18de0c2a2f46a9235fbe42c641a890039cf6aad820f1f844edc24e69bc3bd0c22cfad3804d876edf5491e88cf891c347ed5f24464f2df439bb30742e1f9a4a7eabd9346c6a5f93af22e67becc494cadac82cf9cb693acf44560672cb9227eea2575f90b0e28431684ae12ff2e86fded0be3a099f9ddd32a7285531de8963c9a03355f1d9cef88d7ed9b842d0066ccacdb698d42ff9f8a4f000b9764a9aab1f3146f9f95e6636fdfc9ef91c4d060a54ed7f32167e7ac50590dae3a2904d5d2eeaeff2930bd4cad7166fc17edd2c30e6738157eeb0b441491e5dfdc17a7fbb2bdc6426b2cfb26cf2a7e20013f1b3e33a6d6821928443cc7893f7e4a5268a8b94a6ca6097d25be17b214ea4301e9a723194983bbce286f4363a53afd9e94dda9c761481d9d20c7687a2ff85d42436b9d557d5dc6c5e24ea21d5231487df9fc7986100664edbbc51ad4921c5ec9fbb407ab33ef5c3b3bc81f113e68f38d73f0db0261b656fc344d2d23b93446845d69cee1704834d98737848d405f52f5a7bda3dbdfcd3af3881484579d2d2f3ef976cb35c9cbb76252f2e00019363273489b39943d212ccecc647413c56de69e0087532223cf9b28ce3f77fed30bc3ae6a0842b546e0e1a8b6f6ee1ca0ef1b78c3ed829af817099426f94a447f67229cbca3c07b7a8ce547c5eebcf168248e0a0b9fbeb398e5ed2d0dcacb441f95f9e30c108c725507e459d34c1ec01b67065e5e202d685502d6ff015d46c20bbeef1db38c29df7df585b95d79f5687474e71fff162c0ec0c96c94c507f8a0292a8c32168dacd2fff78b5c7dc145e10fee1b25c478172af8f3ea132fdcad75dc22856deb2576a5ff3e8911842c811d1d57ec203c77b82da3658cbfee18d140ac341d38a30f1af298cf60f2a88d0dfbd3e079ae64a07abb4947cc042925fd5c64bb5d4467589f8c495b0097073c081517bc4504dcd7442bad7e7acafc894fcf34f535979364cf5e908a84e0e141ae47e2ae4dc95462b4f345b12b0629502c7bd65579ec66b2d0a951302ba6da1d1176db6aa0c0ea1fa88195dd2248990fa4aba88490b1da4ea405649203f6ff6f734693f40deabdad59ac62e3296cdcbd74061474dd7b63c46bcfe6ea2b0ddb0f7e77fcff3599892c82425b05ae7aa1a2ac1dfddfc67e11921ff4f2c8f6297881dd5e38ccc4076cac8015c59cdd6023ffbd62b887b33ef8d917446a8941d9563acb66a6226fa4d3f2cc21604c080b3f83e73c093d8f2f7067c392671020c7a7eb6fd0d97af0d63032a3116c408b708d4b2f711c1134b88a91aa359608550f0049af2bb97688afc4352a45c4f6d30d4634e70e82515ff1d5f77851ee857e42b486d5e1f3e0406227dded6c5f47eda30d94f44d978322891dc729eb6ae95d29d22c8a5d649193d5d2aaba782fa16ae488f645a7ed90a566e182f97bc62049724f4cb5fc71f6bc7be57f07a7afb9933f6706cc83483cd7dc4182768cd35bc42f1e9b54d5454d3a17e734475ff58fc66d75419d3d122eff05f7b0548188682f1318ec32c5bbea87c8624cc1e548bf18a6b102e7a43e6bafb579e4e84275fe07d8c63ace449a44cace5d9305ff756cbf40e5a6a20334d5b4a74ab0483e31593f2277e90341fa8036496c2bc6d2b7b10b0b354c86d666d65cacc593d1d7349e71b0360d823453011ee16b6280f5c048111b99b185af99e9d901d4eaffd8a96b1ff394b66208ddc1e7e53420fa965bfc4e630d73ad97b9c5c6ea884c619bc24ac3f46234e7d8d35a12b0cad7220d7a0945cdc64fee9d8852bff872c43f359e7aadf8fa3de3551fb716704af68a18f79d03b3c7d90cf21eb4bbdcbb4004f8ba15ff0bbd2d0918ee78e9bde980e4f3cc13558e6fdb40ca71ad2c10f5e5587784bacc6b925f72da12528216895e0ca4b350d078fdf534fe01bc86b45e0c8e2b35799d268a457f8768ed782dfb56abecfd2b9db00cd10e189c6164f82f5ccab423277e3465ec72d76b696cafc1cfa9a7fe47d142fd6672d9c5b77751b40801af07fc53b1c9da0fe6981ea75e066572f7272baef8fc54bfa7cd71cd0fbc5d6cd717e9aa07808496ad2b4b4005a320c9312c73385afd61193581dbae99df6c25f1b9da17093ccfb108b0a26c5ae4963183533ce2f0ade01bf5e818af613416433578522b1b1e5aa7c791570c8c8b26ded266399116f5789a8233fee128e54ca8ce63fd56c1a146c3006316d200e05715993d1d97907ca83d7fd42ef7e7222eebd74f9c86b6cefc82e614a53976272c8801bdcfd882e34d86b39142ac05088a4c47010a71107bc72a380bb3e5122981d1795256beec20a0fe568002d79a4b1577903fe8682f268eeeed0a97861337ffb6861bf378eba1e0957111c7f9fcfeb55a95238005b40e13ce40efe846ddb86d14c9ad2c46cca74baa364ed08da3a3079fae3a36346ac949e2174c661b8801a051423e95dcab6a0f9c965e8744bdd0e629bd3c1a1241e99951ddde184eb8f354209f24c04fcf10fa8f4e43cb55c922c28be041213ddcfad65c86e1ab9b615f91d5fb11e4cdec5b7e25f8e9811c82c2ed457d012e4967b555f228baf4f1648854c624e0525e36e5f4d1961bfbbc3621d79bd6bea72924d8e0146d0965c239a768b417ea4c33237a60fff2760a9dbfb1113a37b01b598f3e06987d99518bd9f1ec96cd7050863898c8664f793ef29114bbeeb9afab8ed09358d1227d7de2aaac0ab2391cb2013028ca5f4d1de6425ec5feb17d95df358572fa27fcd51d14c363a36bc37c7497a0f964a6c004561f68349f828d30d4633e87bdce6b6d92384c9c1c540c8295ea621e9a8006a8d7c163b988853071e06c78f1b9a0246db052e8484a65cbdced3a587e45d9e2b49a5501590cf768d08b6a043971110e9c9dc96abe855abbb7aee2c38bbb77e5c68d61f01f2376b6122450117240532c7c840e3739395dd6c9e80a432423fc5e3a6dce9dcd58eb418e16d7aa507b4d67dd6fe2af4042a5c7398ba4f87c650926084efbfdc9430a4bc2be544880ecdf7361aea06a25e4f592104b0d74312f2729a4db5876b675bc0fa68f6e41e014b7caaf6f49b8ef704b6243df410dce94ad2c51d328fb90b9cf2f5df645015f489a262f57a5aceba40a56d343403b660928cd7a9d165f4a5bc289c0d28f33dac85c9c2a5c79b5ddd22c744a0388a5daf4bab84d7c77685053c912c9a24b5a0664c6253febbcf552c4ff38bbaf2f7e0c9f06e69a91cff9138c2745b99367e00ff6b6a920b1812e17ba44175c033df0e58d1b5c0b7d146f861b62e812ecbe99d638219e0dba4dd88089005977bcc90634c4dfa95f87370d905d32f613358fba2efcface0b9a414ce33b09e271a647b911843933c5d1008fb0717ab59739eb8eb844a4b34bb1a8f635c5895afa285ddc43720e78dc81eee7db822896bd9bd6ae3e7fe2988ba560d58f02592870647b94aad1dbb0d0cb60e28135ceb72e0a6f4b7893a56eae83f9d9a4c549d53d17c6a00f5d6c266d23e7a1d13e22a5fede3a7082dffb34296f8fe9f3bfe525ee1da81efde3aef9b6de8457a10fd4340809e1dafbfb9e2719c327a3c3a4c51d4d5600e8a01ebd5c537a4cd7c4519e963de06de6c83a9b968b01f79e08b5415c5a9d6a92a633d6ae969b80cbb2cf4d6d1ab2c3b94e7c12df27ea89bff4014d92add41a3e961006a194ae3ea4a6b38c2827f6185ae636f6846b1c8401289696fb10c765fa93e58d068bdcd8c9dc95df572f096d65f5de42bae639d41ce7e1ee0f48ba4faf856c0cdd728956d7e4babd6d9d6389ff41d76c5fbd6380f351b05a37022dbce0a6a47ab7168c82c77a2810c80b1882f825ebf86cb7f6d0f54025fddc9b9120802514c797d1d3968631dae95297a857890ff1dee408909223d012925dc08b7d1119fefca7466392a019d4121ea76c8b4c3bd103a820557e4b2283e262af32f1edbffaa253c47d5873bfd0219b8be86c7e64ada2d87ab6b7f428a7d8fb3ae09b05aee71054355eb83ad76c05d836a9f1a65511b1553927ef1b19ab1576d7185af61be6104de1df218918179c6321846085a83bd1217aa63d0b03996ac1fb4018a8ab54fcf635f7d5a8ade95894f0d407e5d4691920f21094c6f632f1661402a0b3351f168f16a13d3a31ad48e89230cffad272926487f36c7a2584c9387623df6227be8c96088db4a21c93b1c88ee756e960f60e614b30bb6ff757c20f3674a7ae7f6ff6a9115a0a6d444513ccc0be5dcd557430e0ee8db3ed5b3e8c405110500b9bf7f6eb7748de4988a1db94bcb16fe33479f64762c53a1e2965363452063d7bc14386ca7b4d46ebcf08489c64ab413ec0f1ddee8719f5fe978d38438ca3059961ecc8480908cfaf139d88db2facb5e7a88a43a67dcb0f97a17f9bd5b09b8369803ccc7ab6d41238e59e43762965814c10c36fa4b6e61bf2e83c0243f20ee8aab62dfa9827aec06f99c5c565c1bc75291292d3113503a202851c26d1a8bde54bb30f0301e555374b71e278925a2afb29b0209c08ecb89601bf612ce811a493abe2bff78e7fd02ee13c5db6b3edce7c87559410b9be3be95465468e33af224d6508a44728cdffde4cb14fb96a0d2ab9c7f597541f9963775c32ac613af9beab89e0ff7a5e35613751061b0511532b10b3947802901505c8e33bae67ce0e28da760af7e80b730811bdf17abfce39d35def51d73a084119449038c2b0f1c86d844123c6e71f28b7038053e279dd11c088dfa11c547a4ce13b19453e88e5b74962101412490cfb68e21d8952db509cd3a814387b67339fd04ddd2163177589146409934f0eceb10db2d90a9e3f6691eb75e84d5e66bc3228baeadcba200f3d11e0cae090ffbb800f5da7032c35ab572de55beea37258bee6f191addf01739a26efaa612991cb2a3c6d1bbb03de0ee1fcf9b7f6c51e452b21c0819a9aad93162eb2dcc189bf355ecd2c3e504713dab24bfe3ed86a4194611029f7f6216cd469fe1f7d35d56b6c8c2045011e238f9cbc0a19b8914d74329e2472f15d0b7d60511814ad2736d6be168aac01868c2a675549c849fe05e05a76f077130b46896735db5490277b76bba43545de6b8ecb53fd20398eb94dd884951fb48d5690ce4bcd0b836615cd9340ff0cdee1122743accfef343811a71c7d14d1369fa49ce47784a6ff8adc26c151edd4969dba513ade6a9b1f009e57c3d6aa845ddee275169ce58e1f04b564ffb6d0eec75f7172e5e8fb814cd702c9fbea8a783bff637db8667d4b6b48a264135bf60acf335936105abacff0351ba9aeac88e9522cf7ed80069822a7db1a5d8221d9492e02ca893e1f15965fb82a80ee2ec491027bbc8906e71cf931fc21e1c0865ee06a79c023929625b4d232c7b3e2e4a4e5dde28fab675391befe583c95dadae71dbaa43e09d8d65ba36d148aa85d1a2a35dc51719ac0311ea72c1237c78a8b1542c59de3b743087245e54d3111c585b5e5e7642f625c8d44c6d9cff50d8d071f6fa573df937d9e7457302d8b293d8fd94ebd3023c55f8b260c3454e93f58f16d0f451189bf41c9f9b91d3c3918adbf98e4ca5aa0eb6314041521ef880ce18f0ce296721a06b329bb5fbb3024e424b46400e03caf0105877465285fcb41a93844fb90b7fc1924883ace6ca8a37c9905068c633761163affae39d0ba55b67fdc6bcf0908ee3a42af286c" ++ }, ++ "transport" : { ++ "secp256k1Address" : "0xe23c5bba38d809fcb2d3384f210e9a6405beb498" ++ }, ++ "ecdsa" : { ++ "addr" : "0x48fcd978ac4d42ff52dd81fcd17e93190f35e5e0", ++ "claim" : "0x2dee91bd2cbfa906aefa3a8ae6e2de773f55dbd28e77bc329d28215183068585601ab9a7f9ff0c48095407474d502a3af3f059a666e5ed1e27468466d69914e801" ++ } ++ }, ++ "1" : { ++ "id" : "0x690a7fd66157e5b777256ea5214f634f61b3a72d", ++ "keys" : { ++ "falcon-512" : "0x09a6d094d9a3a0865864e9a16b477236f1ca26c888fd0c918db331c87a478519c41085cdac7e6cd0d89190a41a3bd6f4d6300995d591f5e22a7b7147caab1f9c7a85a4ba74d47c7b227326ac17535de039a7e604225d3daac7f75b9544654b73f79f5825825ad6e6c45d13e6d385a644633e1c8806d3a0a551c98f032583c95fb13997e52a6b02192d26b5a47fb22ee52999ec92b75c70774a4ae0481a79113ac72346263e53d5dcde708668d317dd00552d5a40ad47e59a501b10a50bdc52c5c2b2c920fa0e3dc9b8eca54b10aa5ab1168c88287dcf80ecd880a8fdec85b6d63a15b9f453845421a5d9b898e6149b60454828eb9dad6442ec62ad27ed72215014f3d17539085ea3f668b0a9183ab96e9db996801c72a0920b02a249911924f181e8dda515d114beb83b075ce7e7a0902a6971e31420ee4921f5cfc123f29dc7775017aefe99a7e326119cb925f6f603ac3bb137313609498d5a2000c426cb332c82500dcfd80d70a5e2d156844a683b313266af6d60216bd9e9998bda53c0028f387ebd21a5fca6c0607d54b1e95724746d15f25f16e45845926a83c7598646a0a0d3a8f8307c1a401b823f1656ca41e5499684150a954318da076af9131fcc93361d9bf0ae035f617e02cb5e1224a982b3591b24013ff80dbb61160d2ba4ce85a4260c8a3a3218e0ec869796b1b04a82079cfc0ac26da03b04a11950b2a3331ecd0026ea9737bd20e6ea3045b56e3c71278d2a8c72c8014b769da9319e19dbe762b1943e5a4be15aa84d0da831eddbb10bd05f35d55b6211d02a61c5d9247e69cab6c112acb568ea51f345a5bf16f84782e04220e217722da71d634e1a68b796376c8a49a965c592b87d06702fe42dac12da108d24ee42a109e8e4cfd3bed6ada5e3de50301696bab0564292864f1b9f47d5a53cc0c5f9cc3d57051065fd57064d08764892ef4c4a92b475184a4cb4ce1f3a0e6da0402414db5a9db34632b9717586e799b06e870b81a330da7be6a45ddfb000fd337a24a29e164449f96be015818c53aaaf09b9a565d7d9d735b9493885e7cb49a5f1985977cd6824fd62f51d2a1e60289dbaeaea148a44dd8876cb58b8ca2f29f6455f354e4e76aa13290f2979b78b22afa0e65c696c21497e94bf0141ac6298aac70b5ea843848a2264fc057abd3593cb17465e06d41731b7153b71f8f0f7a06d362fbd09845f0815794050460b41ad003c9396a86eaab240555ac8c75f85c0ab972c1a0b94b67b1aee2fa3", ++ "slh-dsa-sha2-128s" : "0x2b2fea4a0edd5dcc2f653eb2dd000aecd87deffbce8818aae72d7862b506bac7" ++ }, ++ "pop" : { ++ "falcon-512" : "0x3968f2999d69a9c28ae792a90a47363e689bd4b349e75c5f837181fc7b16d3d04489bbc32252d750d750417770630c5b65b88cef918ad23e33892a58458e9e63ea591596d3b898f65e1a5be3d36650c3d9834e1ec725426960d337b8f25878525ee3c3798b5afc9add5bec82c8e139c59738aba9ed5f42d11c886472e81cedfdb5b910eb73e884e0d4cc218b87cd9bcc0bc107af586c65b3949460a25892d9607efa341f232e478f3c9fc2d05f324ee6eb7bcddb72af371d47c36856f488872249ffdd322d3de7d12b62b1ec595187b5b363e36cc714b765f0ad5616488300f6e56811e88e359365d5698ab123b917bb32f56566958b154f6fe052b894ccc1fcd99d65d19e8117a8ca4887e01f36f181461a433fb9bbc1790d8b14e34a097b149f0c5c075ecae3501944935f3caa76f0b9370ebe6b90390b4d059f9029ee4af98dad33b9050877d49c3d4f2beaa4b5861a21af95b8c52f9ab4b0eb115357f5b1d25fb66a36b9baaa4d6cc5a4f5fb5462432bd82734d7393cd22c68f52493eb3434c3b88fa255baae5c46c650cae17ebe59827cd6645c6d377b3cdee3aa6a758ad3a96d103bf6ab8ae03b72b53f3aebdda359288c32ff5461a158962924a97a24af29f6c976762e8de9363485ada49c445566e71ac75379aaf7bf190a81c671115e842b5280a05bfb2ef3724bb74487068d5b5ab2d089ebea7ffb4381a7e96233f0915f295d3b71db872393bb990b9c74717bc3d72f6271bc248e54828a1e090f6da56de3643b083e9695db7d0a32bb42355e245e5cc2ed57354d82220b449e10cca1cbf6fbe796d141591d6f71e4eb6770a3c7dfcee509c3c28f2f1988eeca61833b6681e6766790c2a6f043b4f67e145b908ba7f03361cd9d435d054e11edd9667e4f9d12c2d74f2832b619", ++ "slh-dsa-sha2-128s" : "0x39254afc16b1dd8d4fbfff766819460253653dfc6a8e29abed55ffe91325afd578ebfa2dbe74d46b48b381e69d269b5bbe24ca1b85767bd71c744065fa47c646e3603b44261731b50f2d20a7a327e98b84c5ece73697739c8057f99d6ecbc54cf891649fa78b7bcd824972f3b27820ffda3629f481b1193b922cefc907bde3ab1c78b5ac97ff26986f3a553556d0b158e936450b4f41bf006c90a9758e0efb327f67408a7b803ede993522cd9042db4a672c89d4765a0fff8c6e8bf6882a8de432229dee08ae13def90f9fd0a40c99f3d93873a41d74871aaf407b0927a817b476eb93c645254bbc77d131e0bd35a2541248172993b1064d5b26b921396c8c1664178051810961039b15790862415338806329a45a266aece5904312afb1cfbeac1e816fb96256fc6e2b059c25af1966b0bf261bfb72afd8652feaedd6e0e4bf829a75188708ac9c623d4d6699281913bb563b96818f9307b66f7cf4aa9591e30c65a0b0885c22b5d17ff610f40bf2e0a9a32173b2fa7d66c14784402885d84f33fc75afd8f743cd10f5ad6dcce5b33a8f0c0365de2ce1b69aa86df2482a2c2d3746c6f0ee4e6fdbeef5738d809f6b0ef3cc703b0d29e93e198b68d62a5be657e69c33459fe4b163a5ecd72a90f1e53fc00bc8c698af7ae3cc5b07e36cb74088066a54138d6df4ef6e159ce5924b6903346a5fe115272cc951e8713d4b6f96f78d67a542c3bb402e69bdb3c2b06e189186c227927b2aba52b29c14e837b37798321fd000ed3bc0e386ad6e5d3a48494f57109322f0a87f7dd752d862dbf772498154804b09eca84c305595cc1e6654b1b2e94d5b88feda176aa144d3895a249754bb2ea99b2efb4f61b828f265638866a49dd3437c70016347d5aae64c79957ed394a85cfe06b10b98b6e83801728645529537a1102bb04ada4226688594cc28aefb24fbb0d1a60c7b826dadd23f301517e862c67fd88d0f6a5ac08e7f966ae375b468e57f01521b43fc24c761838c174ac106c4e1f435b7ead5e79aa1b303222f6b45c5515d497d8e7b05901bee96945652d304ad9ebae2153321885f19e7ad08c9da73ccc22a66c26c4cdc9360c36e307310714ac44c80887f42a2575305ef649378d76d297dc6faa904377b2037618f23b8be496fbc680645dfb80a76bfc060c6b2aee4ac5537e79b7dc7deeca0ca38041dc877b875cab1a297190269c987dcc46ff34e5bc154e2572695e463542be79d61fd5e96a4be2b07f5beb71b882f99de317116fd0b36131a88ff9707eb25594fec74cf76c2859ba6ba2b968d41479adf8857f4b0f4a26f49f0f04fbae0e2f3c2ab6aefdf01855a7a5a4b8bf516f4551a393a33d3920ca3ec403b4d37c2106d777e3d5dfa768614513885d857ce95b9bc3b992808e7ad71575e5e91b8107c5802043b221c74d73c7bbfa7a191945bbc5ed69e20016b16e2e2987818cfa80695e58950b0c1bbb8c474f861d1447161744c75d99dc8240338c43a5c19a8a9f46d80f6b4b6c1cb57f5a3350bfc35a0522f89e3470ccd71a458968c629c93336af6b5b091f569d1fc9492eb6b976376b8ff19ad9318f5cb1361954a0471419b4207dd9dace8c0545e74dfbb19ce3fdb5d456a1c1bff7383c6fd96dde3a92daf0ff5a315714c74711e3c05e0c59ba525c64ebd17fa20f8e143c5931b3c77da193415e6506c2db27e0e773a6a5b5d47ad95760b8d471d06d5dfe000a2d47e6e4e6abe7219750f1f7892f4e09fe88d13c2e3b53dc904ad58eaed856a4abb0c10830b96bfc1b5764f9e4b34b0072be314608fdea8c5005d40ef99806d4d3edb72e73541fb828d4b2adc38855e09e974293de25da6907f5ea97810eff1be37f88ea879e545bb5a70d2187edec81bd57a95c0314df4ad08a864156579d50826d0cfa511d335ff722e246151a7afce94126232f6bac89b13c142d29e7521479866e35b17c15f16ee89d798ee8bfac5868e505031586b81bfadef4aafc2ecdbde649f63e07eb6026d09910d9d3613a9871b5d1523cf5958124f96b5304d5225b4bbb03aeeef87753d0b6ab51a287df1e9031f56f755d3fe5a20f79b7f0f467fa97eac5bc09a1adc6ec285c8f80ec5c184b8b5eae326300a5bce0b1d757c8e4f27ca2822e73745009291f0d9032051e15b567511908f3ec68840cb6ec6018a9a0e30f2e34759743ef0bc9e12c9b32f29f4b70a998cb8893af2dcf17e0eb4f48e7ba367f68aea5516e7248c8be1d1f896d7e8446fadd9603012dc13126878300f0868bc512221154a5104882621f831e60b49d04fa8a701256b3a413b9db4abc5af10a3f8f4c26cd0b3c2f55a58c9380143d835b759bac7fef824515a18d79b6dbd361541047c79653ab4af5473b7b7e67a6755add78d5c14c0a9edc6c7dd42c3d0359d9f2f6961f8930458a34c4f12478ae45c20969c4c18654d31a7ae73902757b3b8a4eedfd16d6c0d22548d7b8ba77aeb4c1e3f3766b6ea802ee9bd92c5f98d00be80c15e7e3a82eb0d100436c398781607dacbefa98c87b3558f363b3ecb1ff313655838f864c1b2e0f6d6369bae4eb8cef98f564108ab2f763e590a9e9201f4e28ef1971438c30f4376c55cfce9b9910f448e31d06c2e456eb798476d56a890660e45616840377ea0574d1c066ae2fcc46f41cfbb511e5efc4b5c60e00e4846e157bbee5fe3bcd77408e3bf721bf871c05971a70cf7a13c782bb4afbdb1ef800a414260243fd828b67f49007eaf60b3e32f4e2b8186291075a0b1c0a528abb9da7974b3b1e8b20d337161ce234db66ce82a88ae1dc880933343961267cb4932b36aacc5f136cb474bbdb5e4c4be4cd74868775d80317bfba00ca4e58a39d04e63bb797de366c45efe2e356672f567ed1f7b2741df7543d6faa7227601eb7cff367d5a1ff320ca71fa2a1a42866239cc3fa5eba400ee4060266a05b8fe1e729908b95ba6aff8fd76b5e7df547df62cb89f0605c1207c869d7214e4e6972ea6e47b18235855d6f28265a737b4f64f0d215943f13d219292036c1cfc46bc61679f034919e4fea80d882a5121cb3096a50f2112eab265ebf75b607b93e14ceda4e08152221bd368cd1503ce375188d23514dd0936bf980d4282eaa6fe8f38f5eb00c34e3557ae363538a2c15b560b9f9322d1f17446e8f3fd317126986afc2c5e9fbb96f8ca7148f53cd75a4b845a28034c8679baf1f5406564b6e4b8fa8e681b5a9d208f3a1b28e84d6d52d4baa152524908d50d71d9c0d11bb5665c8a6bad669dbf303027bd0d534434f9e76f2c300326e25d00bd8d3bb1debe1c3984961c0ea8dc547e8cb83a8f3b044b673f4a08882d103d6eb143a9645a9a00fab6f1167a2c09015d6ff2dbe4aa4025f604a63eb32330f832162b6dd9364f4ad6afbd86c8d26f56d7d9028dbb3051c85a0c86ec0d7961fd6008f87dbe8347fd5ed1dc4c27285364f63650f161321daa83ad41fbc3412bff800c062a78cc5caea330cd58e63ea9a9d6de2ee069732799f52f49d513c658a44a2122b8427a405d706f740600f855130a0ea720f76b3111dafddf0e2ebbd13f60640379993889089ce508b1343f485457cb8e0c09760d3199b4ea940d584417259e41f2c66853ae4235b6f010cceca3859952b3daaab55da14adff0e421e862f138872c2577637b3e12b00384cd32fb3b9c97b0d59e51f2488e379065d79f5a834b076ab5b35fe4c47f2c4c4f43e622527abb8f682fe9f262d2883fce5c9f16b7566c4e078b67611abf72cb8a0263ba12a6c23b1a04458c759f2bdf6dbcc460bc5df48146468073b61aa5ab4a9c5f6c006f54f1bfdd85373f33af29d68580eba4cb6dd88054c81b3bb7f2be8186e380bee0b32a1b84ef6319798079828080361bcc27473a9634c23652ed6b2b2c8f8d5a6721551c780870f1787726b121263e74c9464a76282dca27249b4532e49455a7485e2cda4ccca823f62d3b2869602197a6f1ecfc9d92ab6e231996e603e81e3dc648aebdfb900a3d929502ff0bbb3dff813660c9d5a417d857c19754ee04e50f1241831517fc2d2a71c5e238a944992cc50b7106aabb5482fc7e0a2e6b5b11bb6845f34ede98a18d5f07759e61603de502b5eaabe59a4d2c69f4b0f8e73a9bc85b8950a54bd91bcd0366dffaa0df736dbbbc35d6accb5ab8b22a870374521f2035c1878718d7d3b025838da75d8bfa3ff36b2a10a3cdef1b150abf3b6be95a5c096a921a3eced20f509dac4ba43f2f515af2b65d3b2ebd0da2d7a58500157a666b387b1814d0a3e84f64d0fc44507b0b6792c0c6bd90ab62e0f75b66d50b6f842cfdbecf1fd043d642c5d5b5fe5cb68af62e6e23cc6f0f9b1cf3cbd0233ce48a996296b6609be1c9e7a027cf76615dd11208f1fde119099352cc17e1c9a22f4b71c3e628d72b620f3cb4bd40e4294ff8dfe19480b5b758b874a737e6092254638a222c83aac52fe0f66670454c313adb0dba2b4e95741d27104bbff159e999e23103c00470a7feee6f4a35f764ec81a8ef520cf1e8623fed3c06b63c022e40e7638db269b8add119fec50456b33224c14486f705e5b3339c6f38aa4ba6dec8b098c27447185ca50cd70772e5389ba703a4a9f8649946671a238e1f005aba0b3a18c8ceda9daf4cede6782d27931c638af3f6083b2bf10ff0a632ebd4dd528da3aa2b7a8bddff2901d902b26d518a058921eb0178ef08e24f7075f77ea0c0d0e72f29847ac7826230c0ddb5e7fc8552ff92c007e9141f51384a12e218da4fbfa9a7a4a1bf266aa975949e120db1b6755ff04adb07c66ba9619b40396072e7cc01dc3dd56f7a2f928a82c8906be416f6d5c41354881f9a6c66a927292f8cc2887aee86e90da32fa3bd9d72bc26dfd334f943305fbe4b645df83fb72c565f61860a480dc0f2f3360368ec3715c2c4a312bd2653051c8f29fc14e0c3d1f515e04b75ec02cac2aad8d411306969d9a8da08c3477eb6201bd54c6ee643d87a89c78a5c8ad48590b7a499cc44ccb812866a4c48ec2da5f1e0aac741464b26988459f3724ea4cf103c27e4a43e5a5fbbf94908878894f8b62995aebc20e632d924c82d9669f64b2093cfe023cdd1542c8f9d19e5e7ad6ed7920ba6834cb0cb91bce48fa94be47c1833c6ada4090509ba38defab7d56dde8168bac8021fb5a2aead00809f1881d53d26fa9cbc824488e16062fd9f68726c837234a82d518e3d10c9931295d20d9affa5fd18c0b2dda299cf1d6fe0c6e6959440af9b397f3441bb9881ba1d2df295d12686ef6b0bfe52fb2bef06620721374328551040d2fa434b161648b058b74df2a7ccacd7609b93421f44a136079c79a3e63bd3b4f79717f3c121ceec2c3918464f5619b1a2e83a7709fdf6d1004b0ee51c73e740b20e329847304a82802e02170db386e360dc6027aa7ba1ee35d7eeddb41ffde093073d92899d568bedee914627c8c48427376e7b5d5ebdab30e58147dac5638090e9c71921431f025f1d4e3ba3c68437555357c651336b326c9c519544363d5f4faa91914195314cc873ef97068d928a6b4e5c6ad70ea7a7b09b3108fd5696aaab800eafe463ee52a3f29e1bbe8a968e84b762484a13714ee260759b4492b749c46ab6603c13ece34e301c13bea57d9de706edc839f55b432b9299d2d6643817cd9d32d0d9ddbdbb23acef51992b62db024365ac2db4c432c531cc1ad18c807cf1ee39dcd842aa9a09b232cfd09bfce33277a8ed09953ab3b5d24e5a8a02fb4a02ceed705185880ecc47cb245665cf640ded4015b4afda053a5d1dff77e390c8105961cb3a954c28ddbb9efd759080dea99e94e69b03b928c8667fa4797dbb3cc6ed093bed107c817780f60729036f13346f05491fb837ef1ffc61be7b61d0b7f8dabfd49ec24cfcee088de38daaae6b4e740ab4faf16eaebf89962331a99f17ca5955b15dd1fa493b91e7cd218aebbfaa7d348b1ceea26951209137448caa93fa466ca32eda497a5b9a4fdbd23a10d9742e74c511a1648d00bca3ca23abcd4f18b7cdeb362e020c73888b76b83e70d26ee358c06933f77d1221a8ff0647200e451e971fe45c23aff60a88baf46f59a0bf94e99ab9337b0336ffacf8e79db92067d2b744134cefac1241dfda288f5c6ab293df7469ae0926c166e999ac99c8871e571eab03f82de73e9de2d8f4deea3724f795480cd47e304f27f2567cd94cbed52e06f1f1cf7af2feaeba8b95927eff950bfc26aa0cc3e46ec7bd5d4aa43374500f8cad4f153cb586620b9a0deeec2cb12ba48bbc8655c7fa70ccf94aa6891b5cc8a3c98b482d906d72e9d425301d0cc6fb4ec9c4a5bcdfdd74fdcef68f05fdb78f2a1c5ae32c28c43ee900738f31ac1fd337ce95966b3f557a727e0c3ada6c6aa61219d92fd5cf68fcd9b444f6b4fb6178b9c74238d2575f442a298127f282b5ad416cf6a365a214048489139918f93ec07f2cd864f5482c418c7336ca4590a7da8a20d33ffb7be19934c80b64f4b982a55b129f4896685534b83251d54e46a2971c0bf49ded9b13a77ade3de9a61f2204a46ed9cd7bc444801381994c8ca5a66abd70936f8d11e2a2fed78fe9fe8889dfcb979c9a3f11f2c2c1aa371d1e98c4fbdaa95d58c6b22410c0d3d3460077dce654a1decfc829f117bc407d06ad9ee6aa06bf818ea2f25312b1cbbb5de527ce9b5c5ddcb0df21e3442ffd149b24af5e59eb4d7e18f68b02b26e57fdf23e7af4fde3e672990295c37186ca67b2abdff6b46e1ff106f041279b61560ea2eae64649c65be22f9070c3239b0cf7929b0778c43dae5391d8d3b8c335ceac672376588a34d3b9c61833578e8d5a9e6e9f72748d860d7af98f7616431d1ae1ca20db3db6ec99d59fa98c25a1cf478e1b4a643c2fc9d3e482d56bedb1b7a1fc9c3e788d9de281c7356b82e3c9e1c9414a0d14cd07fea5364b6a22dcb3b69b6f447343822098548e3ca7e88a83187db145bda17f7c48cb00e6ce36d53e2d1e4c169569ee3fa03620a7131bd5c033062bb82cedd0d0ebc1025937b2d85a3cbcf6ef4458a57525a66244be3a62b582bf2b88549431cdce09f6407e1bee83d3fbe205f585cc7cf9c1eaba047a01f51e13bbe0715a9112c451f1daf6074a1af051d8b98863b6fd03238ebe295995d60e7a26d2f95a2b4b0d617af299133bf357518b84e942bc36a88b4030d91a7067e7a2ed7bbf4e9abda8c6887ecdfebda04dedabb9ea833123507835e0357ca1513b471da73102605ed03297b5e3eb7d3bd01c670f992a7f19962b706e8d0ae0f073638d633b34a1229b6979b8e90f2a536cb6024c644e1f7ef211451dc509e061b294c28be188c96246614a1fbf52db8d9a99f7100c878c1b9da98ee9e9eddf7fcb386061ddf46807c60b24d665f0fe7fde205f91021bfb87c8f4c89b5da254d185bda9cc2f48303b483ecbf934575aa45d0d58cea64662f0fda4d97790bbcfa237984cfb45a9cd611b533dc0ea997d191d14d307c68db318aee8f99544fd48fb86f041fe249a14263e6657a5ee732f7c5c9c97a8924bfdddfd75dc67da65042e711a3cc144f46d10a1a9fdac1b1b321eacd235299a1fab390df24acb739d61bd60c6907b9a3827958198e6e2b5a1c90cb9b44cf8db9b6e45f710d7a39c230ec9cd855af797555fb1d73492e29d17da0b6dac59c2ccde0715565efa1f62898c9b26438c60fc3b9f859bbd33a8e05e1d3d5a762bf19bc7c32cf7d4c6bce26fec6e5c8c537608a1c2aea2e1e5cca5bdbb45a8ed048514ef3d298e7dfb9c5408d941ded6220a44c184dc90c922a3ae31c9248c5f31627389770a59f9431fd0139c5ac0f08f69151a75a5a6a0355b7beab6be9829146ada371aa5791c861dc77598f09448af20deca73cf98a399f35c36f1167ba426c6cf4b8b9b8a22b961bca83e45bade098e20782a9f70bd54fb8eb6eda3acd3a5bbb553438cfe37e1f7fabf15729d6bd562cfe379d586181b71b3d3c4b360852003c4363a8d473198130642972eb3434c3a5ca9b497ec7000e821c3419aae75866496bb1b0a9ac6cf92f799071e06809f1f3f904cd18f32629e2093664755803f62f45942f5a358cb1e925a8694998cb14cfc52733c356cfd739c3976712ca7b007e08841639da14e429c102a8fba3191cd36c1c56eb06bf69afe3f2afc4ebf137c617faacda6baf5cfdcc6462ad02f63e8a5375288d0de5700d0f9f4ca82a65bfdc405d3f96fc663658f0aad91305b86ead3b21bd6561a40db0f2c5b0937ba5e1ecbe91e9c50b1dd6bd83a8145b033a7bb6a4ad4896e0ab160e8a52d39d2756b1c8d8570f7081ba217fd8803954290788882befde24b4971723b0ecbeea14d23c92eb6a0d7022a84aca072729d7ab1a88927a25f19a2086f846a44a2726ea26cf1b69c58243e219c756d06c361e1e161bdff0eca10bd30d23782b3374ed421f50cb66c9ee063ca622fa78c8cede932848f0f8f91bd7a0eaa324377c109808bd66ff463a72389c4b49f2e349be70d07fcb56b28549fca65ad853d70df66b587390febdf6b1881cce6c1ca9e9fdbc9f1ad68ccaff97234325d3c972b57ae5723fd73f975ba640f90e717e9284c111b76367c6797399452d37df6b8b8d22ed5e7dc1481a415fadc06673ce4eb6435d31acb6af68775436629a57db7a0aa192310e8427468e8e310bd3426b7ffab00110324c0c7e04ac6649b6f167fa8b928b3fe12ac162db3f2bc355295650fa2d976c64df69a8017034683bb4bd4baacf1cd8502dff20430d48c907107acfc4e29c584cb497b7a471fbde90aabab25290d853b8ebd2c0d49c2c201eca42a68a15879cf391671946319427b237472cd35431128ea7ab6d545617321592c07b09fff93e71596da30689b3c15368a1c3a57890e0ee5752bb4356290024fd1bd2ebfa19f7f3ca57c36d296ae61ec5581ceb77618dde2821460553ba0dd6dd68026b911f4af1be3986198966f90ab757aca2f5143f1937d09c3a08047b797781d1639db4030f9e59f8c5b71a71787cc84ade5a385ebceb1946177a056179aefb49e1f69ed0aa67901b2d6b2152b6c1fd1db67f358093180fcb8f96483fd35a87fa14825d3849dbf479be493bb2d1c639674bd195b5ea3caf49c2b78eb0e953dbf8fb909910c87efc6f9b6592c020333e00f83bea4bdebef4e107798f9a8e89fa5d063d69f88f31a53548ba2406407251f18c3d1ca6e392fb81a46107191e6d906b487469d0002afdb0f32c39873872a49eee649250d4d5d3a7687fde2952291c8ba78fd9b962060df12d212033303691b05eef0ae0e7f31b7e395576708d211d70281e9501618673afac20a93e82f060135e51b29132a0c9244551814bdf399b746651279ed135d162e366f39d40e3a49e907f72bf7c66fcb4ba75b1f447fbc3ae3f390ab4c10963d755ee188a9b0129416161995adcab12177976208e1c93ef48d3ef55ad22bbd97781dc7035c9f5fe25f47b703b1ed50dba311d24154ab05dd88ccbb5a8cd96d4665829c4dca5d5b22affbfd7e842ffe5e87bf4326f957392229bbc893b1fde9e4b2191a3345490d418e9298179661104f70bf6cf9a0094f9d37be98b82d98497573512d8f6fb4b0b0aa334a9120a5afef20e0379197ac7ec78da3688d2c9b590e40fcf866acbd1d857546522788d1f3ae73f330aad045c5bfd59b8a399ae626fd67d9797b32d6a279d42eec3ec8a2888258728f7c329c4efd0f71b730e57f9bd87204d40ac1ea6032a4b8ee3a338aad58c2f3c9795819af4cb652dedd475e5662d9c0cd23e72a8f4e86f1a63e5683c814a99a6595b779e5d715ac91ba62c1ae4ca1651581506ba80c2ee0d3f97b979758cfe93f373873f4775c882fb3b5815b9274595bf50488b935c82e0fb4ae4d078d30bf0843c89e484bf5a24d5de602649e336fb2b79da6131f96ef1b5f82cbd668f4599fc9a92b4e9ffe3468e39e4c8bd90531952327da74a522e479c66b7b1554c9a72a2e6db58fcd45588c9ff4f48be5ddc994913833b668c275174b9d862dbe8fd01535ff2bcff6ea030842ed3a4d105ba07feb0098e39f61a4cbc06bfa153c598c10c5de57caa413752878c7599e5db8482b6f275db2185c505bc0c9670fa0afe37031eab994120acb935bf9dbe6cee6ba336dce1b44732c4267ee77f5db890041e547bde486335b9a0b85d6640f6534d84b3729b3436ac1c0551d687ddd8da9abc18689e7e932d5d0e787ab5ee5f36eb53789b9ba2b71d7a4f7994e56b056d4a042bd2cac79ad12d87726ef8cb97342e616269e9f87493e95dcebdd91763b134019c0a76e8b12789b026ebd1d9caf1930010aa1a5c348ae2e6273c885ffdf8731b34d87c293e77e9ef14709c2e3b739dec85d5bdb8f5ebc9eb610240576435c8d222ae0c8ebe5844980560bcfd45cacff143a5c208add9011bf9770b7803fa90bbaa10f58d856250b37e481f325c538e473dee7863957121374bf12172321b9c99975078e43a0e1e40138f9c31d6dbe5e06fc881de840e64899c0cf342a806916147de3cc342832a9514eae9550d2cd1166e823f404a05b418e5f9ffa84352cba3007f9d37e5b00049d7c099346257fb53e86b919b45a9c6cd8b67cb3c4e383fcfd5789f2cc087d6b459e2a7dc96d08c826c43410b3df22021855c7d413d9cfe7ca79fa860918a74941e08511595fc9a3bec2e2e0c6dad05781c0a0d6b6609837ca8f78b0368b1217b121cd6ced8fa48dc131709434eed65523269abe95f338bc5e3fce0046ecb24dc1ad8c8fa68b5f9263361e4952ca1aee9229811a5ea85c9c4452235639d1eb8105ff88c048beddc0f7efd3690da8b9bbccbbcfeddcf3e3c9e3ea7b46a5b40098fb85a25842911e42a714c2dd0fab403340ddc1af9484843b33c7f5bed80fbecf68180c9b397ed85c51d39cf08c5c0336b149e6d1747360541e84a93224ae88c1b62384b938ae25ce17d656b9ae52fcd9100a40dd7793ca67357f3fb00621863a490373f0db49b1aebaff7284d450922f1e5243bb7fb5f7230dd7cb8db1e08893696908cad4a45711eadfce8b0b42a9aa937cd011bd5c4a8c3a2ec771b3ee4959eba5e4a17545d1c86acaa4805e4aad" ++ }, ++ "ecdsa" : { ++ "addr" : "0xa16c987b93f1b3c51fa8a9833c8932eeaa566ce0", ++ "claim" : "0xb0c578f123a8a0c96354a13f98c4c2cb8a67541f5ccecfdd0cb6e61aa77f7768157dfb3ba59aadbc03350577f6f31b4083bec30291a61ee98ecb3db2536f788e01" ++ } ++ }, ++ "2" : { ++ "id" : "0xa5ea2fcff9e3cf29d0c6f5f147b67ff24aec3bd4", ++ "keys" : { ++ "falcon-512" : "0x099202fa37d5e165b88428d963d2a224b8fc82ac0e4b3f6a02376f18218d1aa7d0e910e71586aeeaaddc2a557124d6ab4f9a44b9cad02166413cbeb14b364e13956ea326900eb2900802644167639045d76bbc4e051654cff404dccea94402141ad9fd992cef7a8fa6478b3e6f8912886e9edd1b34c29385b7e964f360e0fb1600787934486f461c95d577d2bc74c4dfeb969b4798565ce0225ad27aac052290a44f844ae233e082c97e4498a31117ac9d02f3605c856e2dde6f611812161f89cb3a54dc936ca1e740a6c659405ed586a9a963b11c89b01746325e39e645c72b0c7e4491b36a17d43ffe38d88c601a5976f5a9636c964a012bfbce5f9b371e7c3b38580d81c6e12b8e8f2aac219f96245d35b4f4afa6c94015b055703b8c4dabaea4ce2577482f5b34fa49e56a912dd58d74580b1f94e1d2056594ea64bcdb696b0baeb33c86b6544761a3ead9ba9888cb1ad51f7027ee52b21e46c5eeaf3f77bc0af7efdc87acbddda7dca00b6acc665002c26447e5b0e0bb5ba261717c68dea7f1576462776954d7249c2fd0886f615ad50d53960ca02d581a4a25517c050ed467c7a820bce6250a9ba2e44fd67fb21bac843bb134c95360dc1c50d54b7280a94440d018181a9d6374bc64d782c84471b47287d8ea748c36cb83cffe053cb89a9e4ae71df497871c2a728ef210903e5b7f39550d0331e15637be7e28b3a2fc05b0a9b0c5a06f9fe81263c3a94403d6c288a561288ebaf788bfe271a578a1a795a85e9d452b61ac204b297090617286922376bf0a8d67dd35fd705b81260b7aad30132b965e39bc3cd64d154c4175951704873992a814814dae5c6bc1e89a83dd91144cd1b88f6ce449900058afdc53bb44bcab63d30cbd6df115a5ee8f5380a127a160e922bebf7b408de82514b2e2550a0931e065565e8dfc389d454823a55b03e5c989b09e3791f656794e8379b7b4b1617aaa9770366d63a657f71ff40c69b1d5da518ef1e2aa42366cfa38e448563f6c2db5e3089bad5520ec26105fc885993630c10db357883f588a5a384cd6de688e1bc3b1200f87ed66ba3d4a4b671b2a500a0436e0955904030d76577aadddb8c1ed21b027f198c072f654c3abb086e7f185980f49d0e109c1a82741809f8afd15ee56a887b392c5b172ba659144a7e99e25ba19792d2a3c0ccb481822839c8c70c65c0943a2994ec9f6085b7ac64ce2b35489a72dd6693d25f2329264e063db26ad4495e3ad00f12df8cf914fd846", ++ "slh-dsa-sha2-128s" : "0x686b5dae4aecd5618b95c3b2a5792888513ba49dd366ac39b7431ef403e04963" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39cf29ab9b80215a9947b975d8c6097e53b39d1483c885ff7527d7fccdd2ca3dafc32bfbc0a19c857fa8be7e52e25064d69c3b7dde6e77eee96ec77011fee440c8bca99a45b432b5468715a0aeff9d61375393b3ca40b9140e1a2bc2a52c3c8a85292f4c9e87d1e0c12fbe4d7236ba7921b8b83bd10ad554179dcebf0791c4b593c8a1bae836883d5094499cf2ba41b00c8c36c77a83466c263a0b01e773f08ec66d46e97caf0f9785943f98e159e353f0d91d5ab526279477a5509129f7a1b8b07ba82a1ccb4acd5be5e40de088f2600e06a8bcf35f54663279f04c74838294048a8f8692904d4f9eaab49635068df74d1f5ed238f6b895acf1364544747bb10ce333a957599594d766ac5d1a3ceecf8a6696cdaa95f824ace18cc551e1f4ec12f345283b366314515849feb5bf81fd203a6c73b5bab7c01b5c1131d442dadcb6bce32d6e13c5a3e77b66eb8f5b2912c0938d89ed9e20a455066d151a973e4509b03f5d66ff7ffb8b362e0c09b969e21173693d9977ba06d48bd3b85657119f9dc3533c91965ed81d1eba72b46cfcff285131f84306fec7b271a02dd22982cb6399a9060d286aa18a3f97666810937f8a5667c94959a4c27299d55e94564dba27ea3d98cb3a9db6197c842eafb237649de3fab72a9d56098b5c1228e70dc062617a8a6b44d46b7899dc1e53a77b700925ed1b438c59458c15e9b91fa2c2164b9661a976720eee2864efc5363d90beea9789a6d3b0628bf4695a853251c7f70ba1ebcea06cb35cb47d72d2340bb9412edc49626d6c78be644c4ab1c539d1469d1cc63f092ccac45f66917d89274af9c84d7f1108b1bd738408e499efa63f1a87c8730400ec19f9a59d241032e9ab78670e85e8da24310b13e89ad521ad4fae3deb9d438dd7eac72b79496c7b65061314ae", ++ "slh-dsa-sha2-128s" : "0xb8f14bb6630512c51d227c12a04ce7b316bfc0d255f5a5d1dec3e1ce5f5cc92927070079430990b4364200dc6d389fde89c78649e21d8fd3a17dd2de7444e77ac3e8c70eda15f2247300fd8e37e1e3c2afcc3e8dd674823106b4297ecedc924ca948a9f80afd7ca1bb85dc0e60e1ccd5d97eb21062b2fabfe94827b4ce5f0e396e5a891fbfc61bb827cd305012515d0a182f163c1a5ee3827aff289ec526cdafd2874c457947e8a6c8332ee7172197cde7388303992be248892e727b559c0d74a2c65d46b6686a48f0b814bbf031d1bde17f55b888e7cbaa7fd6dcf428b13ca43f77d80c3804bd2840e5768c2aa17f6dc773b71f83eb7803fd9e1f1a2e3e158f7e823e9667cebe136d333316fc670442a8c662930a00f72dd2dbda9b19c3dcfdd09c60ba55d9ffb5d5b3384d719d153566bc0b6da89d8dd869fb8c4113258014cd48a67a3591d37f9ba767ad70a554ec98bb59275ce163364915051411db73833a88cab0d3fdb7c491b8580baca2bc44a7bcfc3a51c28ae0a1fc12bb53b2b948c571397a348e664522ea749890d1c7ea7e9561596a3e930bca68377e4d4c0e0301472c8017c1fd5702cd6dd4c3f5881ec4cafb98967a57837c3869720268b61f37836d0c9c5ddac850a835318b17758a6f97df4d4966d516ef100b7e61271c45aeb89242ac7d2b8ee45a08f4081727d54cc08ec0f8af9e16bdf6f6d6797b9f5fcff9686f15efc4e8e34b363d562dba239908a3992b3548566a30cf04c424383b5bea0a5011ac620ee384f6363fca87daa30fa88763146bcfe0a160c071d79dd8de0b11e034fddc032e522b7ee47f318cc6f3f2b6c9b6efa0aaa9b9a9c1243750ea31ac01f087d5f4f5fb97b8296b0953a606c49025f5bedba6773804b15fb3638e72ffffe38ac20486e18eb21059f419b0af9071be12e309a953ac82c0a5a620a7b5c850027b39cdeb5d728522a15c1557e4ebc3f4f09914b3a99e291a814504ff7171c23eb825d2df1bad1ff29144f8a3babcc882258e8a6060272e95c4393fed0ad86698554515e77340ae806746ed859ff9730cd718c767e320ef54fae5e0cb8ba331bdb920229d6047a6db8bad147b75d376c3e72e06fbc6a542f51a312ec831c704099b2eb0f801b68631b464ef484eee077cb7fd9ea951a0307e08dc5fb4ed5a6e62048b010ede39efc5462ccedef2a4c61ffdff63fb3aae19b28ca48593532f051c716835a61f2fbbd5c25883f4a85b48d81658b6d7cc4227f90a81e961c5fd8a388c9efb78da1c9bc50d53a41d2d336232e84e3eb3444389caa3457ef9e3560c25033ed45242d0b4bed69fda4a4f1695830c843e63147b6c2d3f9bc2608b0671e59d827dc1e3876e5fc6075bcdf95223f73dfd11d64399333f7bebdda7f5c2838c072f7baf753a36a1ae8987773fd0ae5acec41d7666c84c1125190f432a4d82ad9b78e22d6536a8135d80a3d1715d17a673033d37104857278a75c2cbcbfe0159343dad8e98e42874e2b001bdb469c9faf79759c4cb3e3f2ccaa16bb29d3e4dc81627441d07469dfb9f545ed83d9c20ce586370be092f3a90b18f30866336c6db9d53e2e0fe1f98c655f1961997e41c25089a518f05270ce06cc115b6c2e9c04f6ba9bf7ce3abfedfada8580ef89f2fea98e8a19c58a0f3ffb89dadb05dbdf05c44b79ad5e1d259d5aa6086cb295341dc40ff800b460a5ac602a687d6feaf66393dd2be22264498509c9d39033aaa22eb248780a3661ecf0a05cb6629ea3d91eb0f68465485e8fa3fad3fc4315a118e4eb2ebc6e9b07284697cacf0257edf67c20b7b0311d3094f4647da567385a508addc9b25a66db1f1544dbced87886946989682b2f2db1363dc635e4cc3c67ad83bd311437d22d8f60a2cb7833c952bab293c9e20ec2b44e1f1f42a797421eecb2e9e9f5e47105b9e7f5d7bd796c360ea39dab45ad701eef0a76b7773c55e7af7909d456c213b0db14f985d0f73652bdf39a6402cee104a168749466e477d8a399469992d65656b607fffbdf73ca1bf4976d3a0c0c64cf5d260d6d3e0198f0b86c451b9ff5840968a2b60a8ec286c81fb55741d7bc9714177c9a77219d3a39dc1d6d7adecb7f8f85af366ed653cd81408b509d0f56b5dccdcd1d982d115754364ca3f14a6f100c54ed8ebfce6b0dc3de4435507acb0c4d974ae3f2453867a70d5ba078a17db34844ea410af4f842dd4a9879a7706b18ddbf94c7b43ba137f7f9b8b3924b4d917f8e0262ad10d083c4dd3b99b70560377ad31784a587cf0ea1f99d6faf0f04a909179f3f93c96aaeae014ea1e74d9d7ccd0eb5ab466a6caf8ed0fae75cba902ae05244e0dde35b8c0bdbb3354ac60875c454ab11f49e47e2d180db319a113a5869bad3ef4580bc7402b0d6bac10a7a4e81403634fd1cd272076074e714b14a6efefc902126df6091330ae387e161789198680b0258c341b6f3ec0b09c7674e9ae8f88699fb7b2f88fdf2461e11ad483ee11fe4e3ddd48ede0ef0a1e54a318ae12473993a8456dbbe8b5ded40232b8d2474a90424281830da7bb36091ebcf591947b04739846d8a600946c2b892e2bf3353b09b08e3a141f33f6ef83d022666d380da43991d3eae4e62dd3f9432678e8be1cd4b9569fa2fa84e95195449716423688aa920e2ba1cd41cd5538907ebdf3ff15df27900ba7ee09f3e9194e1d8cdc0703d6f38b2b887a89b10787986013f688f9a355c6a362f4797576ba022e4f1d1d74e2e31dd98f1b617b99516c944bfa5bb474857fe74a09976cc29c71a7f5b6fa529f3e0c00c33c2f0700064fd507461535a35c0dbc5b69d413fd6ae9af49ccc5d02d7abac88ef02bbd40475595176fa3b68d602469a89afc03359b032fc1f0ae255d623fbf9525bfa36ef98467d5eb2f80cf7c72a04b557e40995471c7adb8701409830b232693bf2fe905ef8b1a32c4b8fe3300bfc5654acfcde685547d5c1b0c213294235b31417da91464619822f3535c93549ab4649a59dc3620e7f4a3327c0e421c5d1a28a2b4c3ba8ab02950631ed54690cee35bc4147aaa8477cae505a1d1757d85251bda5fc91cf65772e1b543bccee1a2cd0c26cd33015533a0e72c815be8634efbb50ceb0ec3c8a3bc6c84638ae371809ab87eec54b934343ee9ed1bebca488d9399a1e347b1647d108652243cf2531a4685c282e0b9e526688a3ae1d10060a78467e6804b705c143d073af664cb72ce657a7d210240011d539cb3144e9411758a211238a872eb4be615d4813b64b8df446d2741db7c9f0af2cc4dc83c0febc41adb5d8413b7ce54ed564e899c0a5a4abcd1cb44c84505915afaaf93751b11bc8e96610216f71cac8d3c9ddb7282f0f864400bdee42c3e5645aea1aa5649485435ffec9e43d43e4341d967c9a89eaaea9cca12e2089f3de222e1a5034baa32372582023b5564909fbb67acfd2a40d5ba40de2d7a31cddac717f5702648c0346e197f99598dc83edda7ad335f9e711a0835c75d4c32e3305e4db9dfafe171181551a8dd5bff89f8a9fb819eca7a171d1be47fbea0e2838a1f1d01f4e68c3d0045da0ed7d3689c17319ef5f5d178e6cf1628402c40d2095c91f7bfe6b837d8f86c5b2585653beb650fc29096f13617ce6d36fd6107ac83c7d7f5a8639e519b161581dd58018ace297bddc3421d358be70179b14bdff66f229a50a329bc30b054a95d0f43e7914a9137055f4dda000357fdb5e2afa3d61b9816c03697168cc022f0418ee5ad7aa71617103fe17e7f47ecf7ef9bf779f157eea74c3caf3821791ab628fe8cba64c12d3226877c48b746d725c46b0ccf5a18f869e6680f1e5ef3c5e7fc2a18915dfd8bc12676ab94ff4401ed22133ac1e1ba0c0352a30156bd80b63eed4a7fe9c948921e1a9843127f1191751312180b75f06e33694853a05a24ee30cae0b02a0be49db16f6f06630ced9b5e57cad548dcff70b1620ffb17e8bf8c247a962d6b2a6fbd4fb3c89e3aa4381e15b92f7245ea700e76ba99678f4b0c998ac90bf3e4b9ba5b52140e15e4b5a38e25462c1b61953cc2068d0b9ebe014db6b8fbdb2fc05751667659f40ba1cafcc2055c364116a058e286f084c2bb73096d46f6736de541b750ad437c27a92ea51baf3478837e99faee73f2a2745918f81547c45f2b7083befc6387a73366c175d2be22314a1fa73f11571395c7fe9df062740c58b56b4982240c63b8a0d5886a3ddbf6ffcbd705d3bf3713a0e1b74497b8c1f34e204ad81b63f27cfa5215d275597599f60d02bbf6cbb229088b56c96d73d09fb3c36fb3f05f4266221984fe8559619da67bb7314ca66405cef4bd3086940c4a7346243776a6fa128cd9b6181d8f584f482c502fce3339f87e4fc5e3593b7a0a64c19fe76c51a29ef776e478ecdd5e093b2aad0ab3cff0baf73f4e09d63e9ccfd4aeaaff147ddf2e9f1e3e6cb3bc9757c57072a1a8076e179e50b0a03dc94de86fbb99f0e92338f26b6ed7c863830f325d3606189b80c8df5a763f422f26436f753168b53bce965c562c2554081cb4eb42d48daf8573206f818ae66d62bafd151e9784d6a9304996b4b82cef081af9b106b42ca4b6b0b2401dc21d8875f9801591234dec266f1f218959af60351178049b487b2784183349e0a7ab361f575fd0237d9f483590a23401f9085b111ac3d740ff4c3eae0b7dca3d149243e3b1fbabdc7431a579652d522bef7023e1c6579d2f6852f1acb9b7f20e3956af8dfbf14617f14981f40b1b2430920be14284dd5f2771f73091adaf9179b8396c6ad2a3579befa1e323177fa2598a3ef80ff5785dc2677f87e9299c6bb16ef2b2080e91f6fcf1b9189e256985e631a05cbfb6427eac995e683f494751f7ae888bb0dfd23aad7fbe942b8100d4daf62b6b8e4d647c818ee7edf0d4d64293edc3b7b6e08a8b9b71a7c38f55ca76593d35770185637fb473da423069de005363ec25235ce816f4df3070ff567f919f47dc4fcf57c168032ef8d7e3fdc5a6a1dace2513fc24f0829e8e4b964d37333febb1eeaa7b81aafe30d16fe64b6ac037ddec2dd9b372c657120df4372504cd14be89d3719c5aa6d545030423fc50e277eaa401e8bb02d70b6614e9768a7e42ba9b35af8f9e3f7dcf175609f7b91a16fdcd65a151c0e85d92dc8a06cddd1ff77d150ccb62c612c90abdad156ced839e837c79b79f456156a28c45f3287cb86a9ca664a13313332a1ed9ef4b3a3df864eda7bd55a6d8705567bd8d1d732f65a324aa6c77f6dd82517d5274343a4e16fc8f41f5a3809e9f2cdec445b88309c9d1de684032a10f8944157a3dc3d4d8d59721f4f9cc0b0e1e7a97b7b066523f7498e0902ac5aa462d9bd096e13c14407bef96b59297391032a4aef8c543cc8b60217ddd5a5d815c4ea1e21625b52e2323b42b4851b0bbc461abad9b71805e8b1b2a16c811be69140d3a6d32d7aa9d5321adb57570fc2e62618cac60a4cce2b011a4c8ddd4dd521b6864c7c4562d8270dbbceec91bf1cd7be926d6b66bf370839bbb22856d1f0c7b2b7119ecea6278793186c50b045d09a1aae7c5bd2ec54df1087cbd1d8094293392605321bd39ffdbbe510f0e8760bd35074c4b0453604ca1f5bee056175ae7943183212ad527e125d2ae113d83c5a4ca1e63e8d89ba07ce8fac8257fe1c603031a1fe2e41bf922d7ffa0a610e0b91eb8c3147262fd228a4ab54fb520b49c91ca268d3954029be8677229af3ed232628e7d3a752e66c2171d1746b7e31d2dc8d1781af454822f36b3ff40f7683fcddc5aec46b13890a6c7c9531f30eeca923f198f4b57112a94e34673c88c70bcf80ee115de27ef5268a753c6f827e71254b5bea2a4f27c8e0e2d0c3f72d051558700196e80abbdf452bd70116c24f635d1850f9466282ae761f1a38a8a0fb5a02a9e1b99df55616f0a7c031fc34f190dfe5cdd4f2442d16ccb49187823fa90f3f87dc0966c4cebbb7472d8184e37522acb165f5d3b508f6a62623def48edddeff361d5ff37fdfddb2b324c4f545bfd5cb98d258edee6ee6170bd41135ddf4c9e358433330a5b590b25fbb276a2284b2df18550270b32b65d9b483fc42e9610537f27715e9f451bccb73e1ce017aaa39b65db4e86c86a50d0379398e57e0c34fa64f73acc0d2b4e953a89ca2f8c01b10135c2af5c234dfaa17ef97941aacb7cce96cd05fb246b76f15275e4d2a8545e52726a48f269d1a558aa12588cc78919a5edf6c0e9e576ed58c92b67d00e4197905d74dbdb3700fbde85d26de20cc652581608ce1d1084b507842a0373fd8830c8d3f68dabe93fb19e3189e486840715f92ae4d916a9ff3424b45ded24780b31fb7f76d506339d9f9a545fe0547c675bde44a3b490bd3b52e3b30842624ab5e8986161be4ef9da785bf537954d3c716da5597a859ef7adb40fd8030611d3ac6581e424ff636aff72f4dcd9f315744a3dae6cd386b2f9945140071a5a49f05e8f979115678eea7d6d884a92e4f14ff94dc102355c3aaa93e02723a92417ff49fe8cdbefee7e6c5e952ad240fa7eab4c7941f6ae8d2a1086e1f2ca73eb8ca5fbe3588ae51bdaf18646ed04bd185a19bdad69394ac15d130297c0fce9d8fce8ea2729dde117facb274f9865ffb4f2c7248102dbd96767483cb7fb764fe667d484a3143db514f08577cad8bcf695b0d953e2a3c8710d8979952929d59c8b8ae62ff678815130e68c85d4714e832733da40b933b7133725a40a12534753eb4877c65fe4c75542f28d6f9e805789995adaaff6fce3929e6027338281c6d0c33aac092fe0eb1797dcd953fc1f815df794249dad7b28407c50371a8c81625f6e7e08ed59a98758a9859c41f7436f937885ad35102b0eea85f3dc4bb9a6260f4e091ed983b1009275d43e4960f9422dddeddd09e9990d545cb67dc3f1061238dffec3ce01376259262b4c32c6173a6f1e239f4502cfb0900bbb7e3b4883ca3c64c8ba91cfd80b2bec6aea25b01124ae11a56ab3e4d448038795ff62e9d5ea5cfdb99c5901a8b8f8731c772690dd964cda343bfd020e920b32910a68b433ddd01d117a833242fd695a54f33fce28b506d931adba499373b0a6182e54323f032f1e7b8bad58dabcffdd1cae831c70e87b2c6fee3494dedaacccfdc93fa23ee1a4273f16adbbbcc21f5d02d8645951b93287732cbca4c61a0d0549345160537501b8c0dfc97128035875e73db7eebec24813d03d11cbcc089929b0f6e2440a26d90cffb6295e8fccf65b4d676abb8ff66709913775e611bc843302a475488c9a9310c0c8885b78d5db5cbb1a919683cfd9bd010cf2f1206ab327122ac87d8e2899cc1ac684e72c91f2d36c7bcc3491b768aac86e92aeb106d22b3e85112a2a871bb8c9d0a0dd15c89d113910f8babf15f27a13b10200ec7078d362773f17286228b0d5a58d6654b0fb4f60c81ee581e507f17a044e6bcad4bb6ddc66bdde7d311810d79ac031086d7b0c334cd3a8a496591aeda23b2c0097cefdb6894b352395dfc79b74a6e4d086656b0cd9c95a48640cc8b3d188189ec0b98c8618b0def4b0175f11369cb2f107e89c4a67a75396cfcbe899334a5d5df5927fef2eb8bd836a27a2834a7ab94813d30fa8431da3178da4ae56caaeeee66cf545537ea260ea6af56d4ba048076ace08ff2a446080a6b688a916a13b43b933e506ad187b1f829a1d54ae261651563874cae19c490004205765b43c3cca4cd8a309fb1bfd7520bcc07794cf7c03d9b1d1ae0cf646534f5a97106925ee96dcb7fc1f74e62c01d382fde19fe027a4b9b7627c08e690abe3ab076f184210acbb4229d483f7471ad551eb614c35e019a8a894b5f92f5371fd6c457f135ae8377c5781a8f3a6dadd2c00697bd8399b6f168dd64b2d2d66d5aebae90fa5f904af9f950f450d8be919ae3f02cb5c0be9687560cfab2d2161db61e978ef46304de248383dc3a99e30573bb66f873ef1e54f523ff8ff79e8c05e7f8143cebd1bdd9d2186ebdbd3b66a0a3dee79475cda2890720ac5bc33f8cd3e817d82bd7c52c34d491e1e9d1d307eec17c0c7679af3626e7b96bbe6ba2550f44de7d1d88b3e4c220b8f185b459f1f882a97248cdfc3d42209ff44806837750b3dd21ac5891254f6c7f6938aef3caca6c55b633770772c2c06734f84612a59aa8cfd4f347267e631658cfc4ff89cea84550bd43699c1d8840655f39e3449ea0d2abba1d81196413302719bc9b39cea85cb7db6ab7f00683842cc480503004c1c819ab80e121d9d21f46f362614a5f2cf80cb2c8d3fda82447cd0155fd7e0ec7589a6df2e6614671071f0f956143c762d51172da46e9f61e588fbf74cb3ceb74bf2ce4ec4ae26a28245f98ae91f09cae77c4660d6dabe7cad33ac506db3000d742f683e08bbd0a7cb9eec72a1a976546ec926b9faba5084e00d66475a514a73f01fbe1e79c0ee0066f4b724e4977f3c1518d28ddc918c573693e9b3fb69b426df0640c5ee42cd5533655f9a82c6843516298d05cd970f34dafa886995545c37b3b939e0dfa3647fb3f330bbd3e69307be3d469a99c24382acdcac76c6cb71decb4b7b11cb5f2e63d112767a7d6467c51f1c0c27900803180337f463e64f507ce245f606f8c1f1df836c7fd02502bd3127424804c69f1d066ec3acd9c4374e857c4607b711f532867cef2c1c8a7d7051a440eb7a8507500d86f11567e2fc812a27e63e5599059af1ee90444497f69add7862b93ea050f100e48df7a578d55b6d6321e70ef7a7625ed89054ab010850912088fdc21551b89397c35ab582aed6c215e00d398a857090e2f7cac21c7b51f34054a45f36157edc603b5d6e76ce20f2dfd2c20158943efd2349560666ca38505cc6af776e0720af2d5f6a7d98f385854700fc0c749dafb597e94d7ac54aedf34840ea778e8873d6f1fd7f53de7c06327d08d34a03b38315efd8eb52683ec1f9abbe2bcf096fa4f379f41e09b8bc67ae4685e68ce456465b38892a238b18358714fee41da0aac8dd729e2c3f17488470648df81040272b2e927e896a4eaf6a11c457938421288ff074da8db60d37c6d022e86952341f2b8d262cba0c5a6efb51925517a8c817a152499ae7ee56d36df86253e6b2d93079c89fc922014b03da3941509e979ff8dede44165ca4cb698924fd12bcb02a35deaad608ff3358d455a49e12e944dbb11ac7e9571476bfa856f3bcf90ca9bac6d57d5c1755104b348d2924ba9b14e9ffb750cafb6edeca6dfb79d73b9839092032035ea700d81f19d035e38bdde754a5098dae1c163f9c473b0681858004ab9d9c2c57282ebd7e57c474b8f7aa091d1048b95e7ef887767f49d2a7f6b410922da142ab8605e735ff6ea9e3f36a29380ec43dd009d98d8c20f4052d81fedfee6cb018b2da59d63b5fc153d5b0948d613415a6b8a2b7338897188582d2930480d897d55bec899723b285dec9abf819ac7e6f39d8c35c484ca13f129fa4b334979bac7715bbf5e52a9926568f359dd3e3e000958b561527bbd52025918ef75228c423da41861396be4f829aa4bb6f94f65e662e6ac91e828d721b741d7333a8e3050f136a463af537ee97af4b42456d65e1e2324f72267c07acb88c91d0cd602ef765f858f69fcd44ddc73dc7c5f8825f3fe04affee769f3ab5486232e35df8fdb75db79721906907ffad83c57a364ab85d93bc03ace8998ede749d88985ae41cef163a3d00f568d43115992362c581745f723a2955ed925cfc7c83c5b5188812fa2dc016dc21844f923b2362afa5ac5f2a6c9355b2eaf724606333f152a01c330ed88f7028e716043330a280c5ee458f2032c8163f5548428ce4c529d487a16ca0e58cbf41dc4dc802cc5ea7fad6a50de0c0f2c2be49c3dd2806911ab1322a30acd4fd8937b8930069fc1a6de86f9ef90f407b2563594adad581b49ad1d19b30ad13efb0ddd8e6f26dc43a36ff8d14d1c99b073f5f1ce8923d3100bb04488b86cd4e89f7b9f5b9cbbb3f86ee03b498ae255e09eeaaba3e4e4d68f1ee4d50f699e460a922e17ea8f0ceef9794e944f128efe835f281a7662f959054aa994afa3982f7a310f46f53d5ffc07884aa91bbdcb3f3779ebdd7f90801e96222f56df39ed9c2bff5d4a11be1da7482835e494b0856ea7c695cc1b53acf3b2e2d1846fff50bf55be65e16548c4fc436f20c50c119ca8eba4cdeda8c7e4d33734a0355586629ca5a7c3591ea4b15428a81b6d91529485004cbbf60e75208579ac354dc705edc7bccb32f23030e733d3f549fbb841329a01f5c5d263ce635a57aa9c69432e5213b155a07c34fe19cee737cb993fdc82ff38eafbeb734f04f58d367e34df15dd6044591983b9b45d4ffd87e2a6b478c7d1e86b4b974991b930370d5eaf5edbb53c3dcda643fb992b5fb0725a8aaf8a9e7c4012311f197179cf1293884e2356fc5b624cd46358d3c7bed1fed6b0305114cd11675aa49c1b9e6569817d34fd60c1105833d78dd00117284cd1722074a60655dfc428072b0d2eb881b93d6c367952a4bd59eb902032cfbf9189bf65f7bff592032c77d61dbf778986b491e297ad0da5b367c8a10c9071b8d509b246393fe04a290b3e2291f04eb750285674ae3e9c7b76a01b679787a4006836dcee956185d3b0ce16c4567fab862d3634b93079305008e2f99ed425489bcf5447699b7a7212fe2196d3999b39191e750fda742c6ffb5509e3806f38edccacbb8bc73c96cd46f0f400c4012f1205813d69a48bbd1f55724c7de917ab56d4188716b96653ebe4fd1b6d5d252f5599f9c53a4683ae60c8c31b86982f32bf73401a328891804daab93a155140fdd41ec87e392c8397c9ecbc48f26acee4e3cc279cfd67d75b5e0b6484274484c18f72c2532b4064cdcc309df796c802c17480428c3b5a5467b38aabce03de2a266c8a22d3b0158beb913d50615a1002fcbaf91edc529b0cd38f35138bd71dcfef1b6b90adb4e68a594de40199724c158db9c85ca78ce3a19378ee90dac98b23e1515324fe18472a4ca93b004295b7abd3c146109da707f5ef37886fe1a8966ff1e96375fd64536eece72ae3433a697492955cb182331ce72e8f1804efee93b1929338f" ++ }, ++ "ecdsa" : { ++ "addr" : "0x5e13d369c8adbd8079272b624343ee1edfa4a560", ++ "claim" : "0x197e55da82eb1daa23a5478ed230c6d0452d3c1920df15e10a8d37a7430a7f2b69eb474bfe0c44a6e4a55db9d5a0e0b74549c044ae22778ce30f47a9fd1eba4100" ++ } ++ } ++ } ++} +diff --git a/consensus/common/src/test/resources/aere/registry-v3/n08-pop.json b/consensus/common/src/test/resources/aere/registry-v3/n08-pop.json +new file mode 100644 +index 0000000000..128c8d19e8 +--- /dev/null ++++ b/consensus/common/src/test/resources/aere/registry-v3/n08-pop.json +@@ -0,0 +1,62 @@ ++{ ++ "description" : "row 1 carries row 0's falcon possession proof", ++ "chainId" : 28001, ++ "requiredSchemes" : [ "falcon-512", "slh-dsa-sha2-128s" ], ++ "ecdsaRequired" : true, ++ "previous" : null, ++ "expect" : "AERE-PQC-REG3-08", ++ "manifest" : { ++ "formatVersion" : 3, ++ "chainId" : 28001, ++ "bindHeight" : 1000, ++ "count" : 3, ++ "0" : { ++ "id" : "0xaaddb4dde09de5718a906d83be7db3d58e0ae32a", ++ "keys" : { ++ "falcon-512" : "0x09501c96d2f5cf0b28fa00c726e5359c5d36a1fa069971f854b7d914fb2f1295e68b2c6fa91d82f7d287f55ad493c87320bf7ca2a5d5e79d7212e8a540c166b588dc03f73b83be060525b367d9f40f5e77e7798c60b6499767586770722820b3b9e6013cad3eab5fe5de96089a29f34919a2e9ebcb3fa03a3e714593b7a3356d11ffb3441ab40ad94474da662a71aa2419dcd50668cd5d8a9017662cb60998b34ab5b7929c58a94d5e133ebbdadb2b0279543067f76bcc4cb6d7e0a5edb7625467e3ddc92a01206e1b8dce69be31928687d8af4d26633a07e73c2830d5299b878977691cf65700b65b6ea2463e51b6136888c544545e59fe8cf190a7944e215a785b682623c95a79eda28e25e0e1b91b49ac89deaec3b14a3c431d9046a663170111ee541d81b43aa91f29dc147c6fc97739b3a63fad1ca84843d0a65b8d9396f28e9b11f9a41453ab18a2309ae8db03253a09fac8f0cd634c76a5e938a44719660944a95dff056cee43ea99592c3899c2880d7181ee3dd5c04baeb60e1369a69430a66031e3cb10e392622f5246a71761760cf417dcb40ad65f60704fb74ad26f26c3af7513a42f806895e0298c25c049187aa536e0eba21998912e621846c2ca0e323744ba930a29850fdb385c8241382296ba28dd4df05ddb1e61fe525949034b59929a784406de240f8086b4074825f419d5472a28a0b157500be37e9f64897db2b645d3807c48dc143266c99e7cc1638ae278772493a2a4ecf74e526a514bc9119d7129c5a0d115a450ccf4dce05b76d4b6149fdab028006df7ec2209923117abf7578a082128cad42aa66b69eb63acee4456bebeb537ca57bb3d3487f95e4f06c5cb29f292d3b6284e5a162cb83151cd9ae56aebbfda150b7edd5065302ccab70892733a1e096ba0da5f51b42764ad23060eb197d5460425fd9c7a26e7dc3cfd40eac3643539feea72c9ed41569111a7976d2c345ac2183fa2271b424526709fd9aae558a23a5cca29f4e2f31629746a71d904612e95ad9977bbe74fa32e90fac62625838cac49f50e5aed4e8879e2ce2e5651c4f4ba0c96583af9e1612b5ff1a6fac5027c0a308815e592308170b915b4a2de1e8d48e9a5730680ea9db8f3326c430241153b3b218d5347d5c843570cf80ee813871ae10f6b8ce4ab7e4c5197045e85b1cb4977f44c33eb85894b6555b4bd288a50c1b656936841048983c00a01631f10a84522cd613fed0d4beaa4aa4b3e9f30c324108d909e59a80150", ++ "slh-dsa-sha2-128s" : "0x47a0b70170dda85f843607f6c6fcbe6e6acc7c22980c108996a3fe72dc9f61a6" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39c8813cd3b34be58eaab900555a67486034b1923e0b00e435661230cab85f07690a5958a5f5e9c84f033a3dc2039a5296443093fb7fe8d41895fa73be3fb34cefc6cc36750d534e6a3c47307294694729d6cdedb633e8efe8979a9aee486eaa66136e342c578761241192610185feb2d3c196bea0e79222437b6a8e08cb09778d053b29552df96507b1cdaede8e9aa7abc18902f29937f30e7cee6868f349f7ae33738237dcaf86b8e8e01238f3d8ea6fd4090a8161db65dabeb5ded5499e8cc8a5b32607abc291b36a4b34b327d30cdef18c1825232e69a2b09d539ed84dd2a4756efa64f864c563943b3db825824f294c1bbfa2157347b0fb0e7f8a56ec253b39ca9b6cb1ef7d3d7c93a6cb220a7dc50c365905ea5a71575c3aeab25b33523e4fefbaf66137f45c3d96db719a12d2e2d42fbd6cdda58c5a1b958b28c2a8f2cca297871a147dda92a7f008a359027a9288e42ebcd6ea9542f10b66dbbce6e7bb914206122f866d9adc1c89cbf8bbad9bc9517c2ea9018b61d4d2df9abff1dd9f3a0a6faa72a449af9c97e8c4090f3bbd9824298e61599c13c7eb89677c0e845ca2907c728d9296c24e96b6a348dbea7cac62671c9a78a531463614ce321e28ca2f093094ba5f69881e6cd766874622ca769ea556ae757cb7f9546d99f5c90c25e7b8e14f3b7f270861398800b0604ec2a3374659277a23cf6131c63148a41b05b3c06e2a98a268f1b9f0df7969addef17179ca2261d3c229ae3db0c490834564c45f7b8ff6d3bf70784779d75915fb2e2d5bc147bc941b9e249af188f63f39b028547cf080b7674b228e20a600e3b167610f814daf105226f3c1ce5e07834fd33dfe46315546e926fd5be83fd4d47ccd5bb8ae736ac745daabb59c87b9edf9a45c9a1d1617ee84e588f27d12235c59ffd9", ++ "slh-dsa-sha2-128s" : "0x0e8f9bdc22cad3613ed07fba30ed04219b9528f9b657119e2f0886dc71cda4afa7d462fe8bb108feb58d998b370b2f7e162390713d1a17eb7de781a604041cbed13d00effd3b24f2ff87cac74f61e7b7f7aa6a259dc283485179ab4bb966793be018c4bbf4475bf7a69e600a37246908f662813813d4b0f4f83757f4064c5c0713870a0b98b5bb99025dace06100497fda8c73d7385d123afd4953961066e7c8544de3fb620ef5e23174327c2b64089b3fe6df3eb86e83b12634a0c9cc0d7844c894ba6d83afed6becb6f5abcfff397c5cea8064e5e153ea4253abe599dec1614b449329ebb25861b69a9b22228d1a03ba51532ea64ebe7603474a15a2806d3dafa29d57d27c5fa894da673b85b4674ce835fcfbd391d328ef83504101432bbb0c83d7be462b265911aad862118af6f4cea4df0f1dd38969c69428fe438d59d22736fbc7dd5faf6758905b26ec4c99d71e4b8fcc562a694ead91569c9a916df5ad693cb2ad0b7ae4c4f3c5b7322f56612c5449e0339dbd367460c76ab89b6f44942cd33f35eaf33c2ddc0c6af793556d5202fd1fb0f9fa1b7ed45c6ca68d904e476477b71a0bc6ebe248c9b4585da0c7bb186600691269bb4c836667a6d73a455b97127d898b7fae17e1acc6dcc3bac3ecb14da131d5f8adaa64b054e2f569d9bdb164792038e107848882de9bbeff295905c2af68d4c6dcc8cf718c2de872ab6b3d18e00d527166f8ced642281302e2acf4cf4489072a2dc3d55ff8716619cde494be1763dce925438b33ff1b91b35eb511645832720ed92552d4880ae53ff6516cfaeb1d48c923648e502e4038676f7c82e532ea713c6b9348c80ce3c5735f437491d3a8b1765294868c14123af2e9ff61e394216e630c71ff976072d2a1c50cfd8ee1ce27aba5bcf9aaed4a51521bad5e5d5e66abc7a95b215fc8004364aa4df2b8b97b14e3950f521b6327a55fdff9139fb0bd35237b022e3aa128d36c8a60f4621d25d28c59a97418c7dbfc15d900ba626d283632732631ec4a948f66dd9db3bee8c2cf60dfdacbb5ad4c0b2b31f8428868cca035e79c95bcacaba40a9351b2b44cb29753b6b9da0a751bd5af84c9094d5fe91e97501d4f075392290e8516ed5e41b41b00e09793353707fe5c1d942395074637f3ee0a0f105876d6f28a74f9558c5f360e98f047a99af35ccedef8d5cd299365e81e7e91f28a01eb265219e21aa7f7ce56b62f9d2a61560f9fa39f2765f5b50920658100a638aad03482a687905cd27dca02f1deffd1bc49a1be1ea7ff1a505da74fd932937d8f6a8bd75ef456d5f7b71ca5357bc66db6cf14368c4faddf4996363251e6a6113ec64d642c319dd85830d8b4c7ee1437ebfefe01f27709ba0c412c266530f5b6bbb005994774e8935f1d91069f9e7a8cd2bb7ad6527768473affe24709c10294eb588aafca85b379bedf0b142b109e1b186e635b0625c4e59576266acb5f71040c44035fc9480b13932bc657cf332b12da1cd7d5c3977f51d5fa742974cd256e8e3662dc698e0516d615d0a05ea9caf12338d0dcb6151e07f184c9cbd5e59bc40b12ed6372e2d6bd42aa0eb6c3c888f264a8c0d3332631d4919c921cdada6bffbd01ca5445de0779f9723577ebd7e33ab0e5f577843aaa6cb8cb5f0508c33b63913a44d02b76bbb1eabae325581738fbddb5d4fdef8dcb8597bd29c6ecc631839118c44f66ef8dedeca65e58941c30e0423c40bf064b8d19d28dab3787238781d492720236a7ae0695ccc867fbb1cf207ebecc64f84daea66b6745515b9ac9b725061bb9958ed79ad6161318a262528004401633d47a023c645683e36413b8653fa4864fe98c501197c10226b1732337842a1322bb788a00a0de86758139c2d9ea3c5b26bf5d7a4a92cab4cb686c580e3e6cca488136f0da9279073b3dbef9519168ba02588fa29cc60d02273805b425b919a7e2e89c9086609982163e09d5f6eb9c66267ac7be363aadd4617d398d4bdeca37a838d650b0919faf13b78642a058b1bb96b2ed1482cef9bc6e8b2e061e6815936e15a9c754353aaa786ab141e95e5f6c464a41b8bf29e28e764abd638abcfb342b54d08c15ba7e24e6fcb69b844e16cdb5cf4f50db60ff0699f969d8e68511fcc9e16a58e100f80671af6b04ff3edda3a4f05f9183c0c3bb7c1061fee2d3f04e33fe75f1354e6de54f582da914da0138e8565ff45ef52f638cbc33a24bae863fe91e58d7c5da34273438f15e10d4f59db16e505620d97d3fa4862a4097a659925d0e5f4e073103ed29a600b051b83b1f3a21381f4b871c18d262d7e43842c34ed80661438c064aa2fd858a8f3bcb035b5e942baace7b50e4de5a73d5c51fc0843cdc163958a62d333078f4c7d883bd7055a602e04c853f9215c9d7f798403c007fcee124cf6099322629c449ad4ef84b7356110798dd87aa4d98ebb47abc6cc8748dd381d588b77db7f4e7550f6ee1ef4360dac6d6c7037a65297d4a0ea7999a5632b90ad48fba0a916846a216941fbd13d62ab36e1066e24990c19592944078435c52d7717b3556595b645cd2359ad151dbb67e92b14168cac12fb2cc5422582a50bf6e99f116751171c9b78744ef719282f1b84bf95b4092514f4c68fb82a1526e0942ca50e186632cd9b0b8b8d91e84f85e35f30f815601798fcae676da6a2d38eab62f22445099694804a36a34142150fb795afb445e78c241f0b645209037a8871cb5487c975975ac997a540b709e3df6bf208d9d8017f9688b152c9ee2b934f65393de8403244b7437108e6d8c973aa723285555d9eb92509b1747977105cbac7fc33e658fd51cd374d21fc2bf229928948292c1698db7934d0f9be44b137514d0a5fbb659bba83861931e03698a61cd20a449d0358a5fce7f288e18bb3eb62b7ba0ae75feeec634fc90fc45ce45239c5e3179309f0c202cfc53d9f42a617f7aaae586e7161a0723ccebb7e8586cd40e1fa12d3ee89b400dba8073b0080ffaab1182e8243afd93318df15bbf3ce179f21804fbb8882e855ef9e0739ce1536d8ebfe9856aefa9874b4e102e705a40ca4c3ab0ab7df63ba525189b518796590035ca780d348de49f0ba8f28456ca6f3e3cff7e761d961ad98b8cf01e855797c88fe2f811e41e787f3e4becb0ef42ca3b9979356020b447294ef295543e0ef512a247e4d356bfe3deacca8ddc5255e6ad047121eaeafe61d71e7f31395cf78890add4f8c688e4eb065479a63ccb3d0c09028bf60c700fe9d19195c26fcbd4130e6feceb52e192a2aa2343c05b43b276f51a7c55dff7233ea512942291900d93315438a96af08e25ea5b9ce656c54e71ed60d1eeb1665ddaa9e42378c930e21d93484b9a4099b7ddd71d983b4c42c6b1f62907ce84b24321422b08b847f1ea97befaa4ec30a794ad7f340210c800cf185ee2c6c72e844cc5671964e1e1ec58953500f149f0f0f25c34d5592de421c2e31535040020237b907e86d753094dd4532e1ab9d821e7583d4a21e1041fa7ad711f29ee3721a2aec6b0c46866a2de71ee850d8122f722898e533848e2bb851ed24cff9ca83badcfad88a171b4be064007aef4d759d93ae9b67b446f3c6fe504f5b4fe851b8312fec86b46ec3cfcb36e0f682e65e117702b888ab8566c9cc716a3a86106d2323c0f7f20fbc1fcd110bed4492a750befbfcbbe16820077dee281bcdf14509b93137a3998b2fdabc2a375b38857bed12bb8a9c67bcae7934d02d6ff89620fa8946c8aa524fde99c12fec0e25bd79788e2c15fc31fa3f27502cb952b9f9482580cf18ecabd92c55113ec4c4470c4dc06d8ca27a10474594eff708209e8f376b6f17915c2966dbeb0e35ac2f02419692c0d232e133b3907059d3a56ff169e7e61915c8b1067e183337b40bc1136241e862eb3ab3f2c6a72b18511c4107ed063d1e2303d0fe6842fb01c204d1bffad7e90bb44a365e62945a7f631811c9c37ffa5ac39c16b4835798686da5baa8e1eb6aa76b42f6b86863c30669486a175d6b3bc5bc47c5eb05b240bd921007fa39506c6605bfbefc9c8c493973bf3f0767817fd8ce126a301c5b8fba79628a9b3a03cad0c491a5f487dc5e89269e5d3bcdc2998a136a012486c5bce2e6c6dc595aeee2ebd5a36dd06919396184aafb2301d1889b668c4d701c7ca01b95f9508f47d4c411cc0397c244ed4e3e3ad7f97d86b6f8834b13b1b2df0625e6b4eae9e439815e65baf2da767d3b1700fc461fad6297fe4e8ed02bfb65b750c2d2801b7308aba9657df3c3ed7d548687f55e85c22343d1db343bc2dbe222fb76fbb3cf490cee7a99ab3a337c626a148fb303b2f8651651588dd4859fd65c95820ee2af85adf4e8fc2c03828ea7427e7c6b0d4a1b0ccd424df6d1450ee436c01351d8b6bffd4ba072756315968845ab7976813d93d0f0f2be1c00faab3ccafa71cd26c5837e87292870cf768c7837e18ddc3c513820c660870b339fc42c5211d33d892ef22b475cea3be20f5e47206efbfdbeac208e26e97c400edfd41f063aaa6b85a0cf86e23fb11274b405f4f796eb10cb97e70783909ad492ad9207ae7b3d204e59d69c886f91bc82a107d0be3ae85797a7cba747b8e2640ec49384f53c785a84cf8de37dd4048dd4b879c58768bd131ad7226506113c446fbf13d769794f1535d58e9c52e23c1bd55e13c647d304e297d968c759a378f1d594897a026e3271aa6b4daabe174d6a35665b35193379f0ee465df7827299c18e1012ac69913a0a5bb5142e99b051763de3e98d5af8b62133e25b32f4f12b787bef7e21dec42de8e4d99a0adc8f365d8cd3e6a5ff3064ca18965ffdc6b383f7ad08186d735a099bb0ee14506388c1a37f7a766d286d748d404457226b952ca6cb3f317b0f4399006b5b8c6eb89f6b8cfa023cec4d2dedde3e31b9a633c0888989b44ab182a5aba30ba78640f477ef1202f6496fafc2a18e283b2e4e8bc60415a1c9a7fd68f15cc1ea0299e3b26f5755ad9f13481a0563a524c6735942f5069dc1d6a070b3c3698e9c503f67a11efe59413e937062668d3439a5dbef197d24ebdc79944b17c549b0648af9b1349cad83c2a0a9e55fd893cffe2aff4626662ebc5014e70baaf7cdbbdfd3f92fcc5eed863fa8afd87f88873f726a0a2eafe41fa81edd5833f5520cf93b0fbf0660e48eb0258d313bafb87dc9b0d0d9349f22fa2d960238f67457ad644bdc60fb5eafd1c88dd2a74db4da0f723a03df08af6c64883f275395020341d9dd3c7fa049ab2bebb4d8af2bb8dc1340d1a80088c4b2c26bfe7314926ee64bf239306c05dc2ec6e6c5e0ed4f6dbe51f5ee09533f558d29ca6fd27092c20dd892c89c83223752006b23e5abecfdc733aaa59c8549e89e5ab0eae1b44189f58cf9cc18de0c2a2f46a9235fbe42c641a890039cf6aad820f1f844edc24e69bc3bd0c22cfad3804d876edf5491e88cf891c347ed5f24464f2df439bb30742e1f9a4a7eabd9346c6a5f93af22e67becc494cadac82cf9cb693acf44560672cb9227eea2575f90b0e28431684ae12ff2e86fded0be3a099f9ddd32a7285531de8963c9a03355f1d9cef88d7ed9b842d0066ccacdb698d42ff9f8a4f000b9764a9aab1f3146f9f95e6636fdfc9ef91c4d060a54ed7f32167e7ac50590dae3a2904d5d2eeaeff2930bd4cad7166fc17edd2c30e6738157eeb0b441491e5dfdc17a7fbb2bdc6426b2cfb26cf2a7e20013f1b3e33a6d6821928443cc7893f7e4a5268a8b94a6ca6097d25be17b214ea4301e9a723194983bbce286f4363a53afd9e94dda9c761481d9d20c7687a2ff85d42436b9d557d5dc6c5e24ea21d5231487df9fc7986100664edbbc51ad4921c5ec9fbb407ab33ef5c3b3bc81f113e68f38d73f0db0261b656fc344d2d23b93446845d69cee1704834d98737848d405f52f5a7bda3dbdfcd3af3881484579d2d2f3ef976cb35c9cbb76252f2e00019363273489b39943d212ccecc647413c56de69e0087532223cf9b28ce3f77fed30bc3ae6a0842b546e0e1a8b6f6ee1ca0ef1b78c3ed829af817099426f94a447f67229cbca3c07b7a8ce547c5eebcf168248e0a0b9fbeb398e5ed2d0dcacb441f95f9e30c108c725507e459d34c1ec01b67065e5e202d685502d6ff015d46c20bbeef1db38c29df7df585b95d79f5687474e71fff162c0ec0c96c94c507f8a0292a8c32168dacd2fff78b5c7dc145e10fee1b25c478172af8f3ea132fdcad75dc22856deb2576a5ff3e8911842c811d1d57ec203c77b82da3658cbfee18d140ac341d38a30f1af298cf60f2a88d0dfbd3e079ae64a07abb4947cc042925fd5c64bb5d4467589f8c495b0097073c081517bc4504dcd7442bad7e7acafc894fcf34f535979364cf5e908a84e0e141ae47e2ae4dc95462b4f345b12b0629502c7bd65579ec66b2d0a951302ba6da1d1176db6aa0c0ea1fa88195dd2248990fa4aba88490b1da4ea405649203f6ff6f734693f40deabdad59ac62e3296cdcbd74061474dd7b63c46bcfe6ea2b0ddb0f7e77fcff3599892c82425b05ae7aa1a2ac1dfddfc67e11921ff4f2c8f6297881dd5e38ccc4076cac8015c59cdd6023ffbd62b887b33ef8d917446a8941d9563acb66a6226fa4d3f2cc21604c080b3f83e73c093d8f2f7067c392671020c7a7eb6fd0d97af0d63032a3116c408b708d4b2f711c1134b88a91aa359608550f0049af2bb97688afc4352a45c4f6d30d4634e70e82515ff1d5f77851ee857e42b486d5e1f3e0406227dded6c5f47eda30d94f44d978322891dc729eb6ae95d29d22c8a5d649193d5d2aaba782fa16ae488f645a7ed90a566e182f97bc62049724f4cb5fc71f6bc7be57f07a7afb9933f6706cc83483cd7dc4182768cd35bc42f1e9b54d5454d3a17e734475ff58fc66d75419d3d122eff05f7b0548188682f1318ec32c5bbea87c8624cc1e548bf18a6b102e7a43e6bafb579e4e84275fe07d8c63ace449a44cace5d9305ff756cbf40e5a6a20334d5b4a74ab0483e31593f2277e90341fa8036496c2bc6d2b7b10b0b354c86d666d65cacc593d1d7349e71b0360d823453011ee16b6280f5c048111b99b185af99e9d901d4eaffd8a96b1ff394b66208ddc1e7e53420fa965bfc4e630d73ad97b9c5c6ea884c619bc24ac3f46234e7d8d35a12b0cad7220d7a0945cdc64fee9d8852bff872c43f359e7aadf8fa3de3551fb716704af68a18f79d03b3c7d90cf21eb4bbdcbb4004f8ba15ff0bbd2d0918ee78e9bde980e4f3cc13558e6fdb40ca71ad2c10f5e5587784bacc6b925f72da12528216895e0ca4b350d078fdf534fe01bc86b45e0c8e2b35799d268a457f8768ed782dfb56abecfd2b9db00cd10e189c6164f82f5ccab423277e3465ec72d76b696cafc1cfa9a7fe47d142fd6672d9c5b77751b40801af07fc53b1c9da0fe6981ea75e066572f7272baef8fc54bfa7cd71cd0fbc5d6cd717e9aa07808496ad2b4b4005a320c9312c73385afd61193581dbae99df6c25f1b9da17093ccfb108b0a26c5ae4963183533ce2f0ade01bf5e818af613416433578522b1b1e5aa7c791570c8c8b26ded266399116f5789a8233fee128e54ca8ce63fd56c1a146c3006316d200e05715993d1d97907ca83d7fd42ef7e7222eebd74f9c86b6cefc82e614a53976272c8801bdcfd882e34d86b39142ac05088a4c47010a71107bc72a380bb3e5122981d1795256beec20a0fe568002d79a4b1577903fe8682f268eeeed0a97861337ffb6861bf378eba1e0957111c7f9fcfeb55a95238005b40e13ce40efe846ddb86d14c9ad2c46cca74baa364ed08da3a3079fae3a36346ac949e2174c661b8801a051423e95dcab6a0f9c965e8744bdd0e629bd3c1a1241e99951ddde184eb8f354209f24c04fcf10fa8f4e43cb55c922c28be041213ddcfad65c86e1ab9b615f91d5fb11e4cdec5b7e25f8e9811c82c2ed457d012e4967b555f228baf4f1648854c624e0525e36e5f4d1961bfbbc3621d79bd6bea72924d8e0146d0965c239a768b417ea4c33237a60fff2760a9dbfb1113a37b01b598f3e06987d99518bd9f1ec96cd7050863898c8664f793ef29114bbeeb9afab8ed09358d1227d7de2aaac0ab2391cb2013028ca5f4d1de6425ec5feb17d95df358572fa27fcd51d14c363a36bc37c7497a0f964a6c004561f68349f828d30d4633e87bdce6b6d92384c9c1c540c8295ea621e9a8006a8d7c163b988853071e06c78f1b9a0246db052e8484a65cbdced3a587e45d9e2b49a5501590cf768d08b6a043971110e9c9dc96abe855abbb7aee2c38bbb77e5c68d61f01f2376b6122450117240532c7c840e3739395dd6c9e80a432423fc5e3a6dce9dcd58eb418e16d7aa507b4d67dd6fe2af4042a5c7398ba4f87c650926084efbfdc9430a4bc2be544880ecdf7361aea06a25e4f592104b0d74312f2729a4db5876b675bc0fa68f6e41e014b7caaf6f49b8ef704b6243df410dce94ad2c51d328fb90b9cf2f5df645015f489a262f57a5aceba40a56d343403b660928cd7a9d165f4a5bc289c0d28f33dac85c9c2a5c79b5ddd22c744a0388a5daf4bab84d7c77685053c912c9a24b5a0664c6253febbcf552c4ff38bbaf2f7e0c9f06e69a91cff9138c2745b99367e00ff6b6a920b1812e17ba44175c033df0e58d1b5c0b7d146f861b62e812ecbe99d638219e0dba4dd88089005977bcc90634c4dfa95f87370d905d32f613358fba2efcface0b9a414ce33b09e271a647b911843933c5d1008fb0717ab59739eb8eb844a4b34bb1a8f635c5895afa285ddc43720e78dc81eee7db822896bd9bd6ae3e7fe2988ba560d58f02592870647b94aad1dbb0d0cb60e28135ceb72e0a6f4b7893a56eae83f9d9a4c549d53d17c6a00f5d6c266d23e7a1d13e22a5fede3a7082dffb34296f8fe9f3bfe525ee1da81efde3aef9b6de8457a10fd4340809e1dafbfb9e2719c327a3c3a4c51d4d5600e8a01ebd5c537a4cd7c4519e963de06de6c83a9b968b01f79e08b5415c5a9d6a92a633d6ae969b80cbb2cf4d6d1ab2c3b94e7c12df27ea89bff4014d92add41a3e961006a194ae3ea4a6b38c2827f6185ae636f6846b1c8401289696fb10c765fa93e58d068bdcd8c9dc95df572f096d65f5de42bae639d41ce7e1ee0f48ba4faf856c0cdd728956d7e4babd6d9d6389ff41d76c5fbd6380f351b05a37022dbce0a6a47ab7168c82c77a2810c80b1882f825ebf86cb7f6d0f54025fddc9b9120802514c797d1d3968631dae95297a857890ff1dee408909223d012925dc08b7d1119fefca7466392a019d4121ea76c8b4c3bd103a820557e4b2283e262af32f1edbffaa253c47d5873bfd0219b8be86c7e64ada2d87ab6b7f428a7d8fb3ae09b05aee71054355eb83ad76c05d836a9f1a65511b1553927ef1b19ab1576d7185af61be6104de1df218918179c6321846085a83bd1217aa63d0b03996ac1fb4018a8ab54fcf635f7d5a8ade95894f0d407e5d4691920f21094c6f632f1661402a0b3351f168f16a13d3a31ad48e89230cffad272926487f36c7a2584c9387623df6227be8c96088db4a21c93b1c88ee756e960f60e614b30bb6ff757c20f3674a7ae7f6ff6a9115a0a6d444513ccc0be5dcd557430e0ee8db3ed5b3e8c405110500b9bf7f6eb7748de4988a1db94bcb16fe33479f64762c53a1e2965363452063d7bc14386ca7b4d46ebcf08489c64ab413ec0f1ddee8719f5fe978d38438ca3059961ecc8480908cfaf139d88db2facb5e7a88a43a67dcb0f97a17f9bd5b09b8369803ccc7ab6d41238e59e43762965814c10c36fa4b6e61bf2e83c0243f20ee8aab62dfa9827aec06f99c5c565c1bc75291292d3113503a202851c26d1a8bde54bb30f0301e555374b71e278925a2afb29b0209c08ecb89601bf612ce811a493abe2bff78e7fd02ee13c5db6b3edce7c87559410b9be3be95465468e33af224d6508a44728cdffde4cb14fb96a0d2ab9c7f597541f9963775c32ac613af9beab89e0ff7a5e35613751061b0511532b10b3947802901505c8e33bae67ce0e28da760af7e80b730811bdf17abfce39d35def51d73a084119449038c2b0f1c86d844123c6e71f28b7038053e279dd11c088dfa11c547a4ce13b19453e88e5b74962101412490cfb68e21d8952db509cd3a814387b67339fd04ddd2163177589146409934f0eceb10db2d90a9e3f6691eb75e84d5e66bc3228baeadcba200f3d11e0cae090ffbb800f5da7032c35ab572de55beea37258bee6f191addf01739a26efaa612991cb2a3c6d1bbb03de0ee1fcf9b7f6c51e452b21c0819a9aad93162eb2dcc189bf355ecd2c3e504713dab24bfe3ed86a4194611029f7f6216cd469fe1f7d35d56b6c8c2045011e238f9cbc0a19b8914d74329e2472f15d0b7d60511814ad2736d6be168aac01868c2a675549c849fe05e05a76f077130b46896735db5490277b76bba43545de6b8ecb53fd20398eb94dd884951fb48d5690ce4bcd0b836615cd9340ff0cdee1122743accfef343811a71c7d14d1369fa49ce47784a6ff8adc26c151edd4969dba513ade6a9b1f009e57c3d6aa845ddee275169ce58e1f04b564ffb6d0eec75f7172e5e8fb814cd702c9fbea8a783bff637db8667d4b6b48a264135bf60acf335936105abacff0351ba9aeac88e9522cf7ed80069822a7db1a5d8221d9492e02ca893e1f15965fb82a80ee2ec491027bbc8906e71cf931fc21e1c0865ee06a79c023929625b4d232c7b3e2e4a4e5dde28fab675391befe583c95dadae71dbaa43e09d8d65ba36d148aa85d1a2a35dc51719ac0311ea72c1237c78a8b1542c59de3b743087245e54d3111c585b5e5e7642f625c8d44c6d9cff50d8d071f6fa573df937d9e7457302d8b293d8fd94ebd3023c55f8b260c3454e93f58f16d0f451189bf41c9f9b91d3c3918adbf98e4ca5aa0eb6314041521ef880ce18f0ce296721a06b329bb5fbb3024e424b46400e03caf0105877465285fcb41a93844fb90b7fc1924883ace6ca8a37c9905068c633761163affae39d0ba55b67fdc6bcf0908ee3a42af286c" ++ }, ++ "transport" : { ++ "secp256k1Address" : "0xe23c5bba38d809fcb2d3384f210e9a6405beb498" ++ }, ++ "ecdsa" : { ++ "addr" : "0x48fcd978ac4d42ff52dd81fcd17e93190f35e5e0", ++ "claim" : "0x2dee91bd2cbfa906aefa3a8ae6e2de773f55dbd28e77bc329d28215183068585601ab9a7f9ff0c48095407474d502a3af3f059a666e5ed1e27468466d69914e801" ++ } ++ }, ++ "1" : { ++ "id" : "0x690a7fd66157e5b777256ea5214f634f61b3a72d", ++ "keys" : { ++ "falcon-512" : "0x09a6d094d9a3a0865864e9a16b477236f1ca26c888fd0c918db331c87a478519c41085cdac7e6cd0d89190a41a3bd6f4d6300995d591f5e22a7b7147caab1f9c7a85a4ba74d47c7b227326ac17535de039a7e604225d3daac7f75b9544654b73f79f5825825ad6e6c45d13e6d385a644633e1c8806d3a0a551c98f032583c95fb13997e52a6b02192d26b5a47fb22ee52999ec92b75c70774a4ae0481a79113ac72346263e53d5dcde708668d317dd00552d5a40ad47e59a501b10a50bdc52c5c2b2c920fa0e3dc9b8eca54b10aa5ab1168c88287dcf80ecd880a8fdec85b6d63a15b9f453845421a5d9b898e6149b60454828eb9dad6442ec62ad27ed72215014f3d17539085ea3f668b0a9183ab96e9db996801c72a0920b02a249911924f181e8dda515d114beb83b075ce7e7a0902a6971e31420ee4921f5cfc123f29dc7775017aefe99a7e326119cb925f6f603ac3bb137313609498d5a2000c426cb332c82500dcfd80d70a5e2d156844a683b313266af6d60216bd9e9998bda53c0028f387ebd21a5fca6c0607d54b1e95724746d15f25f16e45845926a83c7598646a0a0d3a8f8307c1a401b823f1656ca41e5499684150a954318da076af9131fcc93361d9bf0ae035f617e02cb5e1224a982b3591b24013ff80dbb61160d2ba4ce85a4260c8a3a3218e0ec869796b1b04a82079cfc0ac26da03b04a11950b2a3331ecd0026ea9737bd20e6ea3045b56e3c71278d2a8c72c8014b769da9319e19dbe762b1943e5a4be15aa84d0da831eddbb10bd05f35d55b6211d02a61c5d9247e69cab6c112acb568ea51f345a5bf16f84782e04220e217722da71d634e1a68b796376c8a49a965c592b87d06702fe42dac12da108d24ee42a109e8e4cfd3bed6ada5e3de50301696bab0564292864f1b9f47d5a53cc0c5f9cc3d57051065fd57064d08764892ef4c4a92b475184a4cb4ce1f3a0e6da0402414db5a9db34632b9717586e799b06e870b81a330da7be6a45ddfb000fd337a24a29e164449f96be015818c53aaaf09b9a565d7d9d735b9493885e7cb49a5f1985977cd6824fd62f51d2a1e60289dbaeaea148a44dd8876cb58b8ca2f29f6455f354e4e76aa13290f2979b78b22afa0e65c696c21497e94bf0141ac6298aac70b5ea843848a2264fc057abd3593cb17465e06d41731b7153b71f8f0f7a06d362fbd09845f0815794050460b41ad003c9396a86eaab240555ac8c75f85c0ab972c1a0b94b67b1aee2fa3", ++ "slh-dsa-sha2-128s" : "0x2b2fea4a0edd5dcc2f653eb2dd000aecd87deffbce8818aae72d7862b506bac7" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39c8813cd3b34be58eaab900555a67486034b1923e0b00e435661230cab85f07690a5958a5f5e9c84f033a3dc2039a5296443093fb7fe8d41895fa73be3fb34cefc6cc36750d534e6a3c47307294694729d6cdedb633e8efe8979a9aee486eaa66136e342c578761241192610185feb2d3c196bea0e79222437b6a8e08cb09778d053b29552df96507b1cdaede8e9aa7abc18902f29937f30e7cee6868f349f7ae33738237dcaf86b8e8e01238f3d8ea6fd4090a8161db65dabeb5ded5499e8cc8a5b32607abc291b36a4b34b327d30cdef18c1825232e69a2b09d539ed84dd2a4756efa64f864c563943b3db825824f294c1bbfa2157347b0fb0e7f8a56ec253b39ca9b6cb1ef7d3d7c93a6cb220a7dc50c365905ea5a71575c3aeab25b33523e4fefbaf66137f45c3d96db719a12d2e2d42fbd6cdda58c5a1b958b28c2a8f2cca297871a147dda92a7f008a359027a9288e42ebcd6ea9542f10b66dbbce6e7bb914206122f866d9adc1c89cbf8bbad9bc9517c2ea9018b61d4d2df9abff1dd9f3a0a6faa72a449af9c97e8c4090f3bbd9824298e61599c13c7eb89677c0e845ca2907c728d9296c24e96b6a348dbea7cac62671c9a78a531463614ce321e28ca2f093094ba5f69881e6cd766874622ca769ea556ae757cb7f9546d99f5c90c25e7b8e14f3b7f270861398800b0604ec2a3374659277a23cf6131c63148a41b05b3c06e2a98a268f1b9f0df7969addef17179ca2261d3c229ae3db0c490834564c45f7b8ff6d3bf70784779d75915fb2e2d5bc147bc941b9e249af188f63f39b028547cf080b7674b228e20a600e3b167610f814daf105226f3c1ce5e07834fd33dfe46315546e926fd5be83fd4d47ccd5bb8ae736ac745daabb59c87b9edf9a45c9a1d1617ee84e588f27d12235c59ffd9", ++ "slh-dsa-sha2-128s" : "0x39254afc16b1dd8d4fbfff766819460253653dfc6a8e29abed55ffe91325afd578ebfa2dbe74d46b48b381e69d269b5bbe24ca1b85767bd71c744065fa47c646e3603b44261731b50f2d20a7a327e98b84c5ece73697739c8057f99d6ecbc54cf891649fa78b7bcd824972f3b27820ffda3629f481b1193b922cefc907bde3ab1c78b5ac97ff26986f3a553556d0b158e936450b4f41bf006c90a9758e0efb327f67408a7b803ede993522cd9042db4a672c89d4765a0fff8c6e8bf6882a8de432229dee08ae13def90f9fd0a40c99f3d93873a41d74871aaf407b0927a817b476eb93c645254bbc77d131e0bd35a2541248172993b1064d5b26b921396c8c1664178051810961039b15790862415338806329a45a266aece5904312afb1cfbeac1e816fb96256fc6e2b059c25af1966b0bf261bfb72afd8652feaedd6e0e4bf829a75188708ac9c623d4d6699281913bb563b96818f9307b66f7cf4aa9591e30c65a0b0885c22b5d17ff610f40bf2e0a9a32173b2fa7d66c14784402885d84f33fc75afd8f743cd10f5ad6dcce5b33a8f0c0365de2ce1b69aa86df2482a2c2d3746c6f0ee4e6fdbeef5738d809f6b0ef3cc703b0d29e93e198b68d62a5be657e69c33459fe4b163a5ecd72a90f1e53fc00bc8c698af7ae3cc5b07e36cb74088066a54138d6df4ef6e159ce5924b6903346a5fe115272cc951e8713d4b6f96f78d67a542c3bb402e69bdb3c2b06e189186c227927b2aba52b29c14e837b37798321fd000ed3bc0e386ad6e5d3a48494f57109322f0a87f7dd752d862dbf772498154804b09eca84c305595cc1e6654b1b2e94d5b88feda176aa144d3895a249754bb2ea99b2efb4f61b828f265638866a49dd3437c70016347d5aae64c79957ed394a85cfe06b10b98b6e83801728645529537a1102bb04ada4226688594cc28aefb24fbb0d1a60c7b826dadd23f301517e862c67fd88d0f6a5ac08e7f966ae375b468e57f01521b43fc24c761838c174ac106c4e1f435b7ead5e79aa1b303222f6b45c5515d497d8e7b05901bee96945652d304ad9ebae2153321885f19e7ad08c9da73ccc22a66c26c4cdc9360c36e307310714ac44c80887f42a2575305ef649378d76d297dc6faa904377b2037618f23b8be496fbc680645dfb80a76bfc060c6b2aee4ac5537e79b7dc7deeca0ca38041dc877b875cab1a297190269c987dcc46ff34e5bc154e2572695e463542be79d61fd5e96a4be2b07f5beb71b882f99de317116fd0b36131a88ff9707eb25594fec74cf76c2859ba6ba2b968d41479adf8857f4b0f4a26f49f0f04fbae0e2f3c2ab6aefdf01855a7a5a4b8bf516f4551a393a33d3920ca3ec403b4d37c2106d777e3d5dfa768614513885d857ce95b9bc3b992808e7ad71575e5e91b8107c5802043b221c74d73c7bbfa7a191945bbc5ed69e20016b16e2e2987818cfa80695e58950b0c1bbb8c474f861d1447161744c75d99dc8240338c43a5c19a8a9f46d80f6b4b6c1cb57f5a3350bfc35a0522f89e3470ccd71a458968c629c93336af6b5b091f569d1fc9492eb6b976376b8ff19ad9318f5cb1361954a0471419b4207dd9dace8c0545e74dfbb19ce3fdb5d456a1c1bff7383c6fd96dde3a92daf0ff5a315714c74711e3c05e0c59ba525c64ebd17fa20f8e143c5931b3c77da193415e6506c2db27e0e773a6a5b5d47ad95760b8d471d06d5dfe000a2d47e6e4e6abe7219750f1f7892f4e09fe88d13c2e3b53dc904ad58eaed856a4abb0c10830b96bfc1b5764f9e4b34b0072be314608fdea8c5005d40ef99806d4d3edb72e73541fb828d4b2adc38855e09e974293de25da6907f5ea97810eff1be37f88ea879e545bb5a70d2187edec81bd57a95c0314df4ad08a864156579d50826d0cfa511d335ff722e246151a7afce94126232f6bac89b13c142d29e7521479866e35b17c15f16ee89d798ee8bfac5868e505031586b81bfadef4aafc2ecdbde649f63e07eb6026d09910d9d3613a9871b5d1523cf5958124f96b5304d5225b4bbb03aeeef87753d0b6ab51a287df1e9031f56f755d3fe5a20f79b7f0f467fa97eac5bc09a1adc6ec285c8f80ec5c184b8b5eae326300a5bce0b1d757c8e4f27ca2822e73745009291f0d9032051e15b567511908f3ec68840cb6ec6018a9a0e30f2e34759743ef0bc9e12c9b32f29f4b70a998cb8893af2dcf17e0eb4f48e7ba367f68aea5516e7248c8be1d1f896d7e8446fadd9603012dc13126878300f0868bc512221154a5104882621f831e60b49d04fa8a701256b3a413b9db4abc5af10a3f8f4c26cd0b3c2f55a58c9380143d835b759bac7fef824515a18d79b6dbd361541047c79653ab4af5473b7b7e67a6755add78d5c14c0a9edc6c7dd42c3d0359d9f2f6961f8930458a34c4f12478ae45c20969c4c18654d31a7ae73902757b3b8a4eedfd16d6c0d22548d7b8ba77aeb4c1e3f3766b6ea802ee9bd92c5f98d00be80c15e7e3a82eb0d100436c398781607dacbefa98c87b3558f363b3ecb1ff313655838f864c1b2e0f6d6369bae4eb8cef98f564108ab2f763e590a9e9201f4e28ef1971438c30f4376c55cfce9b9910f448e31d06c2e456eb798476d56a890660e45616840377ea0574d1c066ae2fcc46f41cfbb511e5efc4b5c60e00e4846e157bbee5fe3bcd77408e3bf721bf871c05971a70cf7a13c782bb4afbdb1ef800a414260243fd828b67f49007eaf60b3e32f4e2b8186291075a0b1c0a528abb9da7974b3b1e8b20d337161ce234db66ce82a88ae1dc880933343961267cb4932b36aacc5f136cb474bbdb5e4c4be4cd74868775d80317bfba00ca4e58a39d04e63bb797de366c45efe2e356672f567ed1f7b2741df7543d6faa7227601eb7cff367d5a1ff320ca71fa2a1a42866239cc3fa5eba400ee4060266a05b8fe1e729908b95ba6aff8fd76b5e7df547df62cb89f0605c1207c869d7214e4e6972ea6e47b18235855d6f28265a737b4f64f0d215943f13d219292036c1cfc46bc61679f034919e4fea80d882a5121cb3096a50f2112eab265ebf75b607b93e14ceda4e08152221bd368cd1503ce375188d23514dd0936bf980d4282eaa6fe8f38f5eb00c34e3557ae363538a2c15b560b9f9322d1f17446e8f3fd317126986afc2c5e9fbb96f8ca7148f53cd75a4b845a28034c8679baf1f5406564b6e4b8fa8e681b5a9d208f3a1b28e84d6d52d4baa152524908d50d71d9c0d11bb5665c8a6bad669dbf303027bd0d534434f9e76f2c300326e25d00bd8d3bb1debe1c3984961c0ea8dc547e8cb83a8f3b044b673f4a08882d103d6eb143a9645a9a00fab6f1167a2c09015d6ff2dbe4aa4025f604a63eb32330f832162b6dd9364f4ad6afbd86c8d26f56d7d9028dbb3051c85a0c86ec0d7961fd6008f87dbe8347fd5ed1dc4c27285364f63650f161321daa83ad41fbc3412bff800c062a78cc5caea330cd58e63ea9a9d6de2ee069732799f52f49d513c658a44a2122b8427a405d706f740600f855130a0ea720f76b3111dafddf0e2ebbd13f60640379993889089ce508b1343f485457cb8e0c09760d3199b4ea940d584417259e41f2c66853ae4235b6f010cceca3859952b3daaab55da14adff0e421e862f138872c2577637b3e12b00384cd32fb3b9c97b0d59e51f2488e379065d79f5a834b076ab5b35fe4c47f2c4c4f43e622527abb8f682fe9f262d2883fce5c9f16b7566c4e078b67611abf72cb8a0263ba12a6c23b1a04458c759f2bdf6dbcc460bc5df48146468073b61aa5ab4a9c5f6c006f54f1bfdd85373f33af29d68580eba4cb6dd88054c81b3bb7f2be8186e380bee0b32a1b84ef6319798079828080361bcc27473a9634c23652ed6b2b2c8f8d5a6721551c780870f1787726b121263e74c9464a76282dca27249b4532e49455a7485e2cda4ccca823f62d3b2869602197a6f1ecfc9d92ab6e231996e603e81e3dc648aebdfb900a3d929502ff0bbb3dff813660c9d5a417d857c19754ee04e50f1241831517fc2d2a71c5e238a944992cc50b7106aabb5482fc7e0a2e6b5b11bb6845f34ede98a18d5f07759e61603de502b5eaabe59a4d2c69f4b0f8e73a9bc85b8950a54bd91bcd0366dffaa0df736dbbbc35d6accb5ab8b22a870374521f2035c1878718d7d3b025838da75d8bfa3ff36b2a10a3cdef1b150abf3b6be95a5c096a921a3eced20f509dac4ba43f2f515af2b65d3b2ebd0da2d7a58500157a666b387b1814d0a3e84f64d0fc44507b0b6792c0c6bd90ab62e0f75b66d50b6f842cfdbecf1fd043d642c5d5b5fe5cb68af62e6e23cc6f0f9b1cf3cbd0233ce48a996296b6609be1c9e7a027cf76615dd11208f1fde119099352cc17e1c9a22f4b71c3e628d72b620f3cb4bd40e4294ff8dfe19480b5b758b874a737e6092254638a222c83aac52fe0f66670454c313adb0dba2b4e95741d27104bbff159e999e23103c00470a7feee6f4a35f764ec81a8ef520cf1e8623fed3c06b63c022e40e7638db269b8add119fec50456b33224c14486f705e5b3339c6f38aa4ba6dec8b098c27447185ca50cd70772e5389ba703a4a9f8649946671a238e1f005aba0b3a18c8ceda9daf4cede6782d27931c638af3f6083b2bf10ff0a632ebd4dd528da3aa2b7a8bddff2901d902b26d518a058921eb0178ef08e24f7075f77ea0c0d0e72f29847ac7826230c0ddb5e7fc8552ff92c007e9141f51384a12e218da4fbfa9a7a4a1bf266aa975949e120db1b6755ff04adb07c66ba9619b40396072e7cc01dc3dd56f7a2f928a82c8906be416f6d5c41354881f9a6c66a927292f8cc2887aee86e90da32fa3bd9d72bc26dfd334f943305fbe4b645df83fb72c565f61860a480dc0f2f3360368ec3715c2c4a312bd2653051c8f29fc14e0c3d1f515e04b75ec02cac2aad8d411306969d9a8da08c3477eb6201bd54c6ee643d87a89c78a5c8ad48590b7a499cc44ccb812866a4c48ec2da5f1e0aac741464b26988459f3724ea4cf103c27e4a43e5a5fbbf94908878894f8b62995aebc20e632d924c82d9669f64b2093cfe023cdd1542c8f9d19e5e7ad6ed7920ba6834cb0cb91bce48fa94be47c1833c6ada4090509ba38defab7d56dde8168bac8021fb5a2aead00809f1881d53d26fa9cbc824488e16062fd9f68726c837234a82d518e3d10c9931295d20d9affa5fd18c0b2dda299cf1d6fe0c6e6959440af9b397f3441bb9881ba1d2df295d12686ef6b0bfe52fb2bef06620721374328551040d2fa434b161648b058b74df2a7ccacd7609b93421f44a136079c79a3e63bd3b4f79717f3c121ceec2c3918464f5619b1a2e83a7709fdf6d1004b0ee51c73e740b20e329847304a82802e02170db386e360dc6027aa7ba1ee35d7eeddb41ffde093073d92899d568bedee914627c8c48427376e7b5d5ebdab30e58147dac5638090e9c71921431f025f1d4e3ba3c68437555357c651336b326c9c519544363d5f4faa91914195314cc873ef97068d928a6b4e5c6ad70ea7a7b09b3108fd5696aaab800eafe463ee52a3f29e1bbe8a968e84b762484a13714ee260759b4492b749c46ab6603c13ece34e301c13bea57d9de706edc839f55b432b9299d2d6643817cd9d32d0d9ddbdbb23acef51992b62db024365ac2db4c432c531cc1ad18c807cf1ee39dcd842aa9a09b232cfd09bfce33277a8ed09953ab3b5d24e5a8a02fb4a02ceed705185880ecc47cb245665cf640ded4015b4afda053a5d1dff77e390c8105961cb3a954c28ddbb9efd759080dea99e94e69b03b928c8667fa4797dbb3cc6ed093bed107c817780f60729036f13346f05491fb837ef1ffc61be7b61d0b7f8dabfd49ec24cfcee088de38daaae6b4e740ab4faf16eaebf89962331a99f17ca5955b15dd1fa493b91e7cd218aebbfaa7d348b1ceea26951209137448caa93fa466ca32eda497a5b9a4fdbd23a10d9742e74c511a1648d00bca3ca23abcd4f18b7cdeb362e020c73888b76b83e70d26ee358c06933f77d1221a8ff0647200e451e971fe45c23aff60a88baf46f59a0bf94e99ab9337b0336ffacf8e79db92067d2b744134cefac1241dfda288f5c6ab293df7469ae0926c166e999ac99c8871e571eab03f82de73e9de2d8f4deea3724f795480cd47e304f27f2567cd94cbed52e06f1f1cf7af2feaeba8b95927eff950bfc26aa0cc3e46ec7bd5d4aa43374500f8cad4f153cb586620b9a0deeec2cb12ba48bbc8655c7fa70ccf94aa6891b5cc8a3c98b482d906d72e9d425301d0cc6fb4ec9c4a5bcdfdd74fdcef68f05fdb78f2a1c5ae32c28c43ee900738f31ac1fd337ce95966b3f557a727e0c3ada6c6aa61219d92fd5cf68fcd9b444f6b4fb6178b9c74238d2575f442a298127f282b5ad416cf6a365a214048489139918f93ec07f2cd864f5482c418c7336ca4590a7da8a20d33ffb7be19934c80b64f4b982a55b129f4896685534b83251d54e46a2971c0bf49ded9b13a77ade3de9a61f2204a46ed9cd7bc444801381994c8ca5a66abd70936f8d11e2a2fed78fe9fe8889dfcb979c9a3f11f2c2c1aa371d1e98c4fbdaa95d58c6b22410c0d3d3460077dce654a1decfc829f117bc407d06ad9ee6aa06bf818ea2f25312b1cbbb5de527ce9b5c5ddcb0df21e3442ffd149b24af5e59eb4d7e18f68b02b26e57fdf23e7af4fde3e672990295c37186ca67b2abdff6b46e1ff106f041279b61560ea2eae64649c65be22f9070c3239b0cf7929b0778c43dae5391d8d3b8c335ceac672376588a34d3b9c61833578e8d5a9e6e9f72748d860d7af98f7616431d1ae1ca20db3db6ec99d59fa98c25a1cf478e1b4a643c2fc9d3e482d56bedb1b7a1fc9c3e788d9de281c7356b82e3c9e1c9414a0d14cd07fea5364b6a22dcb3b69b6f447343822098548e3ca7e88a83187db145bda17f7c48cb00e6ce36d53e2d1e4c169569ee3fa03620a7131bd5c033062bb82cedd0d0ebc1025937b2d85a3cbcf6ef4458a57525a66244be3a62b582bf2b88549431cdce09f6407e1bee83d3fbe205f585cc7cf9c1eaba047a01f51e13bbe0715a9112c451f1daf6074a1af051d8b98863b6fd03238ebe295995d60e7a26d2f95a2b4b0d617af299133bf357518b84e942bc36a88b4030d91a7067e7a2ed7bbf4e9abda8c6887ecdfebda04dedabb9ea833123507835e0357ca1513b471da73102605ed03297b5e3eb7d3bd01c670f992a7f19962b706e8d0ae0f073638d633b34a1229b6979b8e90f2a536cb6024c644e1f7ef211451dc509e061b294c28be188c96246614a1fbf52db8d9a99f7100c878c1b9da98ee9e9eddf7fcb386061ddf46807c60b24d665f0fe7fde205f91021bfb87c8f4c89b5da254d185bda9cc2f48303b483ecbf934575aa45d0d58cea64662f0fda4d97790bbcfa237984cfb45a9cd611b533dc0ea997d191d14d307c68db318aee8f99544fd48fb86f041fe249a14263e6657a5ee732f7c5c9c97a8924bfdddfd75dc67da65042e711a3cc144f46d10a1a9fdac1b1b321eacd235299a1fab390df24acb739d61bd60c6907b9a3827958198e6e2b5a1c90cb9b44cf8db9b6e45f710d7a39c230ec9cd855af797555fb1d73492e29d17da0b6dac59c2ccde0715565efa1f62898c9b26438c60fc3b9f859bbd33a8e05e1d3d5a762bf19bc7c32cf7d4c6bce26fec6e5c8c537608a1c2aea2e1e5cca5bdbb45a8ed048514ef3d298e7dfb9c5408d941ded6220a44c184dc90c922a3ae31c9248c5f31627389770a59f9431fd0139c5ac0f08f69151a75a5a6a0355b7beab6be9829146ada371aa5791c861dc77598f09448af20deca73cf98a399f35c36f1167ba426c6cf4b8b9b8a22b961bca83e45bade098e20782a9f70bd54fb8eb6eda3acd3a5bbb553438cfe37e1f7fabf15729d6bd562cfe379d586181b71b3d3c4b360852003c4363a8d473198130642972eb3434c3a5ca9b497ec7000e821c3419aae75866496bb1b0a9ac6cf92f799071e06809f1f3f904cd18f32629e2093664755803f62f45942f5a358cb1e925a8694998cb14cfc52733c356cfd739c3976712ca7b007e08841639da14e429c102a8fba3191cd36c1c56eb06bf69afe3f2afc4ebf137c617faacda6baf5cfdcc6462ad02f63e8a5375288d0de5700d0f9f4ca82a65bfdc405d3f96fc663658f0aad91305b86ead3b21bd6561a40db0f2c5b0937ba5e1ecbe91e9c50b1dd6bd83a8145b033a7bb6a4ad4896e0ab160e8a52d39d2756b1c8d8570f7081ba217fd8803954290788882befde24b4971723b0ecbeea14d23c92eb6a0d7022a84aca072729d7ab1a88927a25f19a2086f846a44a2726ea26cf1b69c58243e219c756d06c361e1e161bdff0eca10bd30d23782b3374ed421f50cb66c9ee063ca622fa78c8cede932848f0f8f91bd7a0eaa324377c109808bd66ff463a72389c4b49f2e349be70d07fcb56b28549fca65ad853d70df66b587390febdf6b1881cce6c1ca9e9fdbc9f1ad68ccaff97234325d3c972b57ae5723fd73f975ba640f90e717e9284c111b76367c6797399452d37df6b8b8d22ed5e7dc1481a415fadc06673ce4eb6435d31acb6af68775436629a57db7a0aa192310e8427468e8e310bd3426b7ffab00110324c0c7e04ac6649b6f167fa8b928b3fe12ac162db3f2bc355295650fa2d976c64df69a8017034683bb4bd4baacf1cd8502dff20430d48c907107acfc4e29c584cb497b7a471fbde90aabab25290d853b8ebd2c0d49c2c201eca42a68a15879cf391671946319427b237472cd35431128ea7ab6d545617321592c07b09fff93e71596da30689b3c15368a1c3a57890e0ee5752bb4356290024fd1bd2ebfa19f7f3ca57c36d296ae61ec5581ceb77618dde2821460553ba0dd6dd68026b911f4af1be3986198966f90ab757aca2f5143f1937d09c3a08047b797781d1639db4030f9e59f8c5b71a71787cc84ade5a385ebceb1946177a056179aefb49e1f69ed0aa67901b2d6b2152b6c1fd1db67f358093180fcb8f96483fd35a87fa14825d3849dbf479be493bb2d1c639674bd195b5ea3caf49c2b78eb0e953dbf8fb909910c87efc6f9b6592c020333e00f83bea4bdebef4e107798f9a8e89fa5d063d69f88f31a53548ba2406407251f18c3d1ca6e392fb81a46107191e6d906b487469d0002afdb0f32c39873872a49eee649250d4d5d3a7687fde2952291c8ba78fd9b962060df12d212033303691b05eef0ae0e7f31b7e395576708d211d70281e9501618673afac20a93e82f060135e51b29132a0c9244551814bdf399b746651279ed135d162e366f39d40e3a49e907f72bf7c66fcb4ba75b1f447fbc3ae3f390ab4c10963d755ee188a9b0129416161995adcab12177976208e1c93ef48d3ef55ad22bbd97781dc7035c9f5fe25f47b703b1ed50dba311d24154ab05dd88ccbb5a8cd96d4665829c4dca5d5b22affbfd7e842ffe5e87bf4326f957392229bbc893b1fde9e4b2191a3345490d418e9298179661104f70bf6cf9a0094f9d37be98b82d98497573512d8f6fb4b0b0aa334a9120a5afef20e0379197ac7ec78da3688d2c9b590e40fcf866acbd1d857546522788d1f3ae73f330aad045c5bfd59b8a399ae626fd67d9797b32d6a279d42eec3ec8a2888258728f7c329c4efd0f71b730e57f9bd87204d40ac1ea6032a4b8ee3a338aad58c2f3c9795819af4cb652dedd475e5662d9c0cd23e72a8f4e86f1a63e5683c814a99a6595b779e5d715ac91ba62c1ae4ca1651581506ba80c2ee0d3f97b979758cfe93f373873f4775c882fb3b5815b9274595bf50488b935c82e0fb4ae4d078d30bf0843c89e484bf5a24d5de602649e336fb2b79da6131f96ef1b5f82cbd668f4599fc9a92b4e9ffe3468e39e4c8bd90531952327da74a522e479c66b7b1554c9a72a2e6db58fcd45588c9ff4f48be5ddc994913833b668c275174b9d862dbe8fd01535ff2bcff6ea030842ed3a4d105ba07feb0098e39f61a4cbc06bfa153c598c10c5de57caa413752878c7599e5db8482b6f275db2185c505bc0c9670fa0afe37031eab994120acb935bf9dbe6cee6ba336dce1b44732c4267ee77f5db890041e547bde486335b9a0b85d6640f6534d84b3729b3436ac1c0551d687ddd8da9abc18689e7e932d5d0e787ab5ee5f36eb53789b9ba2b71d7a4f7994e56b056d4a042bd2cac79ad12d87726ef8cb97342e616269e9f87493e95dcebdd91763b134019c0a76e8b12789b026ebd1d9caf1930010aa1a5c348ae2e6273c885ffdf8731b34d87c293e77e9ef14709c2e3b739dec85d5bdb8f5ebc9eb610240576435c8d222ae0c8ebe5844980560bcfd45cacff143a5c208add9011bf9770b7803fa90bbaa10f58d856250b37e481f325c538e473dee7863957121374bf12172321b9c99975078e43a0e1e40138f9c31d6dbe5e06fc881de840e64899c0cf342a806916147de3cc342832a9514eae9550d2cd1166e823f404a05b418e5f9ffa84352cba3007f9d37e5b00049d7c099346257fb53e86b919b45a9c6cd8b67cb3c4e383fcfd5789f2cc087d6b459e2a7dc96d08c826c43410b3df22021855c7d413d9cfe7ca79fa860918a74941e08511595fc9a3bec2e2e0c6dad05781c0a0d6b6609837ca8f78b0368b1217b121cd6ced8fa48dc131709434eed65523269abe95f338bc5e3fce0046ecb24dc1ad8c8fa68b5f9263361e4952ca1aee9229811a5ea85c9c4452235639d1eb8105ff88c048beddc0f7efd3690da8b9bbccbbcfeddcf3e3c9e3ea7b46a5b40098fb85a25842911e42a714c2dd0fab403340ddc1af9484843b33c7f5bed80fbecf68180c9b397ed85c51d39cf08c5c0336b149e6d1747360541e84a93224ae88c1b62384b938ae25ce17d656b9ae52fcd9100a40dd7793ca67357f3fb00621863a490373f0db49b1aebaff7284d450922f1e5243bb7fb5f7230dd7cb8db1e08893696908cad4a45711eadfce8b0b42a9aa937cd011bd5c4a8c3a2ec771b3ee4959eba5e4a17545d1c86acaa4805e4aad" ++ }, ++ "ecdsa" : { ++ "addr" : "0xa16c987b93f1b3c51fa8a9833c8932eeaa566ce0", ++ "claim" : "0xb0c578f123a8a0c96354a13f98c4c2cb8a67541f5ccecfdd0cb6e61aa77f7768157dfb3ba59aadbc03350577f6f31b4083bec30291a61ee98ecb3db2536f788e01" ++ } ++ }, ++ "2" : { ++ "id" : "0xa5ea2fcff9e3cf29d0c6f5f147b67ff24aec3bd4", ++ "keys" : { ++ "falcon-512" : "0x099202fa37d5e165b88428d963d2a224b8fc82ac0e4b3f6a02376f18218d1aa7d0e910e71586aeeaaddc2a557124d6ab4f9a44b9cad02166413cbeb14b364e13956ea326900eb2900802644167639045d76bbc4e051654cff404dccea94402141ad9fd992cef7a8fa6478b3e6f8912886e9edd1b34c29385b7e964f360e0fb1600787934486f461c95d577d2bc74c4dfeb969b4798565ce0225ad27aac052290a44f844ae233e082c97e4498a31117ac9d02f3605c856e2dde6f611812161f89cb3a54dc936ca1e740a6c659405ed586a9a963b11c89b01746325e39e645c72b0c7e4491b36a17d43ffe38d88c601a5976f5a9636c964a012bfbce5f9b371e7c3b38580d81c6e12b8e8f2aac219f96245d35b4f4afa6c94015b055703b8c4dabaea4ce2577482f5b34fa49e56a912dd58d74580b1f94e1d2056594ea64bcdb696b0baeb33c86b6544761a3ead9ba9888cb1ad51f7027ee52b21e46c5eeaf3f77bc0af7efdc87acbddda7dca00b6acc665002c26447e5b0e0bb5ba261717c68dea7f1576462776954d7249c2fd0886f615ad50d53960ca02d581a4a25517c050ed467c7a820bce6250a9ba2e44fd67fb21bac843bb134c95360dc1c50d54b7280a94440d018181a9d6374bc64d782c84471b47287d8ea748c36cb83cffe053cb89a9e4ae71df497871c2a728ef210903e5b7f39550d0331e15637be7e28b3a2fc05b0a9b0c5a06f9fe81263c3a94403d6c288a561288ebaf788bfe271a578a1a795a85e9d452b61ac204b297090617286922376bf0a8d67dd35fd705b81260b7aad30132b965e39bc3cd64d154c4175951704873992a814814dae5c6bc1e89a83dd91144cd1b88f6ce449900058afdc53bb44bcab63d30cbd6df115a5ee8f5380a127a160e922bebf7b408de82514b2e2550a0931e065565e8dfc389d454823a55b03e5c989b09e3791f656794e8379b7b4b1617aaa9770366d63a657f71ff40c69b1d5da518ef1e2aa42366cfa38e448563f6c2db5e3089bad5520ec26105fc885993630c10db357883f588a5a384cd6de688e1bc3b1200f87ed66ba3d4a4b671b2a500a0436e0955904030d76577aadddb8c1ed21b027f198c072f654c3abb086e7f185980f49d0e109c1a82741809f8afd15ee56a887b392c5b172ba659144a7e99e25ba19792d2a3c0ccb481822839c8c70c65c0943a2994ec9f6085b7ac64ce2b35489a72dd6693d25f2329264e063db26ad4495e3ad00f12df8cf914fd846", ++ "slh-dsa-sha2-128s" : "0x686b5dae4aecd5618b95c3b2a5792888513ba49dd366ac39b7431ef403e04963" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39cf29ab9b80215a9947b975d8c6097e53b39d1483c885ff7527d7fccdd2ca3dafc32bfbc0a19c857fa8be7e52e25064d69c3b7dde6e77eee96ec77011fee440c8bca99a45b432b5468715a0aeff9d61375393b3ca40b9140e1a2bc2a52c3c8a85292f4c9e87d1e0c12fbe4d7236ba7921b8b83bd10ad554179dcebf0791c4b593c8a1bae836883d5094499cf2ba41b00c8c36c77a83466c263a0b01e773f08ec66d46e97caf0f9785943f98e159e353f0d91d5ab526279477a5509129f7a1b8b07ba82a1ccb4acd5be5e40de088f2600e06a8bcf35f54663279f04c74838294048a8f8692904d4f9eaab49635068df74d1f5ed238f6b895acf1364544747bb10ce333a957599594d766ac5d1a3ceecf8a6696cdaa95f824ace18cc551e1f4ec12f345283b366314515849feb5bf81fd203a6c73b5bab7c01b5c1131d442dadcb6bce32d6e13c5a3e77b66eb8f5b2912c0938d89ed9e20a455066d151a973e4509b03f5d66ff7ffb8b362e0c09b969e21173693d9977ba06d48bd3b85657119f9dc3533c91965ed81d1eba72b46cfcff285131f84306fec7b271a02dd22982cb6399a9060d286aa18a3f97666810937f8a5667c94959a4c27299d55e94564dba27ea3d98cb3a9db6197c842eafb237649de3fab72a9d56098b5c1228e70dc062617a8a6b44d46b7899dc1e53a77b700925ed1b438c59458c15e9b91fa2c2164b9661a976720eee2864efc5363d90beea9789a6d3b0628bf4695a853251c7f70ba1ebcea06cb35cb47d72d2340bb9412edc49626d6c78be644c4ab1c539d1469d1cc63f092ccac45f66917d89274af9c84d7f1108b1bd738408e499efa63f1a87c8730400ec19f9a59d241032e9ab78670e85e8da24310b13e89ad521ad4fae3deb9d438dd7eac72b79496c7b65061314ae", ++ "slh-dsa-sha2-128s" : "0xb8f14bb6630512c51d227c12a04ce7b316bfc0d255f5a5d1dec3e1ce5f5cc92927070079430990b4364200dc6d389fde89c78649e21d8fd3a17dd2de7444e77ac3e8c70eda15f2247300fd8e37e1e3c2afcc3e8dd674823106b4297ecedc924ca948a9f80afd7ca1bb85dc0e60e1ccd5d97eb21062b2fabfe94827b4ce5f0e396e5a891fbfc61bb827cd305012515d0a182f163c1a5ee3827aff289ec526cdafd2874c457947e8a6c8332ee7172197cde7388303992be248892e727b559c0d74a2c65d46b6686a48f0b814bbf031d1bde17f55b888e7cbaa7fd6dcf428b13ca43f77d80c3804bd2840e5768c2aa17f6dc773b71f83eb7803fd9e1f1a2e3e158f7e823e9667cebe136d333316fc670442a8c662930a00f72dd2dbda9b19c3dcfdd09c60ba55d9ffb5d5b3384d719d153566bc0b6da89d8dd869fb8c4113258014cd48a67a3591d37f9ba767ad70a554ec98bb59275ce163364915051411db73833a88cab0d3fdb7c491b8580baca2bc44a7bcfc3a51c28ae0a1fc12bb53b2b948c571397a348e664522ea749890d1c7ea7e9561596a3e930bca68377e4d4c0e0301472c8017c1fd5702cd6dd4c3f5881ec4cafb98967a57837c3869720268b61f37836d0c9c5ddac850a835318b17758a6f97df4d4966d516ef100b7e61271c45aeb89242ac7d2b8ee45a08f4081727d54cc08ec0f8af9e16bdf6f6d6797b9f5fcff9686f15efc4e8e34b363d562dba239908a3992b3548566a30cf04c424383b5bea0a5011ac620ee384f6363fca87daa30fa88763146bcfe0a160c071d79dd8de0b11e034fddc032e522b7ee47f318cc6f3f2b6c9b6efa0aaa9b9a9c1243750ea31ac01f087d5f4f5fb97b8296b0953a606c49025f5bedba6773804b15fb3638e72ffffe38ac20486e18eb21059f419b0af9071be12e309a953ac82c0a5a620a7b5c850027b39cdeb5d728522a15c1557e4ebc3f4f09914b3a99e291a814504ff7171c23eb825d2df1bad1ff29144f8a3babcc882258e8a6060272e95c4393fed0ad86698554515e77340ae806746ed859ff9730cd718c767e320ef54fae5e0cb8ba331bdb920229d6047a6db8bad147b75d376c3e72e06fbc6a542f51a312ec831c704099b2eb0f801b68631b464ef484eee077cb7fd9ea951a0307e08dc5fb4ed5a6e62048b010ede39efc5462ccedef2a4c61ffdff63fb3aae19b28ca48593532f051c716835a61f2fbbd5c25883f4a85b48d81658b6d7cc4227f90a81e961c5fd8a388c9efb78da1c9bc50d53a41d2d336232e84e3eb3444389caa3457ef9e3560c25033ed45242d0b4bed69fda4a4f1695830c843e63147b6c2d3f9bc2608b0671e59d827dc1e3876e5fc6075bcdf95223f73dfd11d64399333f7bebdda7f5c2838c072f7baf753a36a1ae8987773fd0ae5acec41d7666c84c1125190f432a4d82ad9b78e22d6536a8135d80a3d1715d17a673033d37104857278a75c2cbcbfe0159343dad8e98e42874e2b001bdb469c9faf79759c4cb3e3f2ccaa16bb29d3e4dc81627441d07469dfb9f545ed83d9c20ce586370be092f3a90b18f30866336c6db9d53e2e0fe1f98c655f1961997e41c25089a518f05270ce06cc115b6c2e9c04f6ba9bf7ce3abfedfada8580ef89f2fea98e8a19c58a0f3ffb89dadb05dbdf05c44b79ad5e1d259d5aa6086cb295341dc40ff800b460a5ac602a687d6feaf66393dd2be22264498509c9d39033aaa22eb248780a3661ecf0a05cb6629ea3d91eb0f68465485e8fa3fad3fc4315a118e4eb2ebc6e9b07284697cacf0257edf67c20b7b0311d3094f4647da567385a508addc9b25a66db1f1544dbced87886946989682b2f2db1363dc635e4cc3c67ad83bd311437d22d8f60a2cb7833c952bab293c9e20ec2b44e1f1f42a797421eecb2e9e9f5e47105b9e7f5d7bd796c360ea39dab45ad701eef0a76b7773c55e7af7909d456c213b0db14f985d0f73652bdf39a6402cee104a168749466e477d8a399469992d65656b607fffbdf73ca1bf4976d3a0c0c64cf5d260d6d3e0198f0b86c451b9ff5840968a2b60a8ec286c81fb55741d7bc9714177c9a77219d3a39dc1d6d7adecb7f8f85af366ed653cd81408b509d0f56b5dccdcd1d982d115754364ca3f14a6f100c54ed8ebfce6b0dc3de4435507acb0c4d974ae3f2453867a70d5ba078a17db34844ea410af4f842dd4a9879a7706b18ddbf94c7b43ba137f7f9b8b3924b4d917f8e0262ad10d083c4dd3b99b70560377ad31784a587cf0ea1f99d6faf0f04a909179f3f93c96aaeae014ea1e74d9d7ccd0eb5ab466a6caf8ed0fae75cba902ae05244e0dde35b8c0bdbb3354ac60875c454ab11f49e47e2d180db319a113a5869bad3ef4580bc7402b0d6bac10a7a4e81403634fd1cd272076074e714b14a6efefc902126df6091330ae387e161789198680b0258c341b6f3ec0b09c7674e9ae8f88699fb7b2f88fdf2461e11ad483ee11fe4e3ddd48ede0ef0a1e54a318ae12473993a8456dbbe8b5ded40232b8d2474a90424281830da7bb36091ebcf591947b04739846d8a600946c2b892e2bf3353b09b08e3a141f33f6ef83d022666d380da43991d3eae4e62dd3f9432678e8be1cd4b9569fa2fa84e95195449716423688aa920e2ba1cd41cd5538907ebdf3ff15df27900ba7ee09f3e9194e1d8cdc0703d6f38b2b887a89b10787986013f688f9a355c6a362f4797576ba022e4f1d1d74e2e31dd98f1b617b99516c944bfa5bb474857fe74a09976cc29c71a7f5b6fa529f3e0c00c33c2f0700064fd507461535a35c0dbc5b69d413fd6ae9af49ccc5d02d7abac88ef02bbd40475595176fa3b68d602469a89afc03359b032fc1f0ae255d623fbf9525bfa36ef98467d5eb2f80cf7c72a04b557e40995471c7adb8701409830b232693bf2fe905ef8b1a32c4b8fe3300bfc5654acfcde685547d5c1b0c213294235b31417da91464619822f3535c93549ab4649a59dc3620e7f4a3327c0e421c5d1a28a2b4c3ba8ab02950631ed54690cee35bc4147aaa8477cae505a1d1757d85251bda5fc91cf65772e1b543bccee1a2cd0c26cd33015533a0e72c815be8634efbb50ceb0ec3c8a3bc6c84638ae371809ab87eec54b934343ee9ed1bebca488d9399a1e347b1647d108652243cf2531a4685c282e0b9e526688a3ae1d10060a78467e6804b705c143d073af664cb72ce657a7d210240011d539cb3144e9411758a211238a872eb4be615d4813b64b8df446d2741db7c9f0af2cc4dc83c0febc41adb5d8413b7ce54ed564e899c0a5a4abcd1cb44c84505915afaaf93751b11bc8e96610216f71cac8d3c9ddb7282f0f864400bdee42c3e5645aea1aa5649485435ffec9e43d43e4341d967c9a89eaaea9cca12e2089f3de222e1a5034baa32372582023b5564909fbb67acfd2a40d5ba40de2d7a31cddac717f5702648c0346e197f99598dc83edda7ad335f9e711a0835c75d4c32e3305e4db9dfafe171181551a8dd5bff89f8a9fb819eca7a171d1be47fbea0e2838a1f1d01f4e68c3d0045da0ed7d3689c17319ef5f5d178e6cf1628402c40d2095c91f7bfe6b837d8f86c5b2585653beb650fc29096f13617ce6d36fd6107ac83c7d7f5a8639e519b161581dd58018ace297bddc3421d358be70179b14bdff66f229a50a329bc30b054a95d0f43e7914a9137055f4dda000357fdb5e2afa3d61b9816c03697168cc022f0418ee5ad7aa71617103fe17e7f47ecf7ef9bf779f157eea74c3caf3821791ab628fe8cba64c12d3226877c48b746d725c46b0ccf5a18f869e6680f1e5ef3c5e7fc2a18915dfd8bc12676ab94ff4401ed22133ac1e1ba0c0352a30156bd80b63eed4a7fe9c948921e1a9843127f1191751312180b75f06e33694853a05a24ee30cae0b02a0be49db16f6f06630ced9b5e57cad548dcff70b1620ffb17e8bf8c247a962d6b2a6fbd4fb3c89e3aa4381e15b92f7245ea700e76ba99678f4b0c998ac90bf3e4b9ba5b52140e15e4b5a38e25462c1b61953cc2068d0b9ebe014db6b8fbdb2fc05751667659f40ba1cafcc2055c364116a058e286f084c2bb73096d46f6736de541b750ad437c27a92ea51baf3478837e99faee73f2a2745918f81547c45f2b7083befc6387a73366c175d2be22314a1fa73f11571395c7fe9df062740c58b56b4982240c63b8a0d5886a3ddbf6ffcbd705d3bf3713a0e1b74497b8c1f34e204ad81b63f27cfa5215d275597599f60d02bbf6cbb229088b56c96d73d09fb3c36fb3f05f4266221984fe8559619da67bb7314ca66405cef4bd3086940c4a7346243776a6fa128cd9b6181d8f584f482c502fce3339f87e4fc5e3593b7a0a64c19fe76c51a29ef776e478ecdd5e093b2aad0ab3cff0baf73f4e09d63e9ccfd4aeaaff147ddf2e9f1e3e6cb3bc9757c57072a1a8076e179e50b0a03dc94de86fbb99f0e92338f26b6ed7c863830f325d3606189b80c8df5a763f422f26436f753168b53bce965c562c2554081cb4eb42d48daf8573206f818ae66d62bafd151e9784d6a9304996b4b82cef081af9b106b42ca4b6b0b2401dc21d8875f9801591234dec266f1f218959af60351178049b487b2784183349e0a7ab361f575fd0237d9f483590a23401f9085b111ac3d740ff4c3eae0b7dca3d149243e3b1fbabdc7431a579652d522bef7023e1c6579d2f6852f1acb9b7f20e3956af8dfbf14617f14981f40b1b2430920be14284dd5f2771f73091adaf9179b8396c6ad2a3579befa1e323177fa2598a3ef80ff5785dc2677f87e9299c6bb16ef2b2080e91f6fcf1b9189e256985e631a05cbfb6427eac995e683f494751f7ae888bb0dfd23aad7fbe942b8100d4daf62b6b8e4d647c818ee7edf0d4d64293edc3b7b6e08a8b9b71a7c38f55ca76593d35770185637fb473da423069de005363ec25235ce816f4df3070ff567f919f47dc4fcf57c168032ef8d7e3fdc5a6a1dace2513fc24f0829e8e4b964d37333febb1eeaa7b81aafe30d16fe64b6ac037ddec2dd9b372c657120df4372504cd14be89d3719c5aa6d545030423fc50e277eaa401e8bb02d70b6614e9768a7e42ba9b35af8f9e3f7dcf175609f7b91a16fdcd65a151c0e85d92dc8a06cddd1ff77d150ccb62c612c90abdad156ced839e837c79b79f456156a28c45f3287cb86a9ca664a13313332a1ed9ef4b3a3df864eda7bd55a6d8705567bd8d1d732f65a324aa6c77f6dd82517d5274343a4e16fc8f41f5a3809e9f2cdec445b88309c9d1de684032a10f8944157a3dc3d4d8d59721f4f9cc0b0e1e7a97b7b066523f7498e0902ac5aa462d9bd096e13c14407bef96b59297391032a4aef8c543cc8b60217ddd5a5d815c4ea1e21625b52e2323b42b4851b0bbc461abad9b71805e8b1b2a16c811be69140d3a6d32d7aa9d5321adb57570fc2e62618cac60a4cce2b011a4c8ddd4dd521b6864c7c4562d8270dbbceec91bf1cd7be926d6b66bf370839bbb22856d1f0c7b2b7119ecea6278793186c50b045d09a1aae7c5bd2ec54df1087cbd1d8094293392605321bd39ffdbbe510f0e8760bd35074c4b0453604ca1f5bee056175ae7943183212ad527e125d2ae113d83c5a4ca1e63e8d89ba07ce8fac8257fe1c603031a1fe2e41bf922d7ffa0a610e0b91eb8c3147262fd228a4ab54fb520b49c91ca268d3954029be8677229af3ed232628e7d3a752e66c2171d1746b7e31d2dc8d1781af454822f36b3ff40f7683fcddc5aec46b13890a6c7c9531f30eeca923f198f4b57112a94e34673c88c70bcf80ee115de27ef5268a753c6f827e71254b5bea2a4f27c8e0e2d0c3f72d051558700196e80abbdf452bd70116c24f635d1850f9466282ae761f1a38a8a0fb5a02a9e1b99df55616f0a7c031fc34f190dfe5cdd4f2442d16ccb49187823fa90f3f87dc0966c4cebbb7472d8184e37522acb165f5d3b508f6a62623def48edddeff361d5ff37fdfddb2b324c4f545bfd5cb98d258edee6ee6170bd41135ddf4c9e358433330a5b590b25fbb276a2284b2df18550270b32b65d9b483fc42e9610537f27715e9f451bccb73e1ce017aaa39b65db4e86c86a50d0379398e57e0c34fa64f73acc0d2b4e953a89ca2f8c01b10135c2af5c234dfaa17ef97941aacb7cce96cd05fb246b76f15275e4d2a8545e52726a48f269d1a558aa12588cc78919a5edf6c0e9e576ed58c92b67d00e4197905d74dbdb3700fbde85d26de20cc652581608ce1d1084b507842a0373fd8830c8d3f68dabe93fb19e3189e486840715f92ae4d916a9ff3424b45ded24780b31fb7f76d506339d9f9a545fe0547c675bde44a3b490bd3b52e3b30842624ab5e8986161be4ef9da785bf537954d3c716da5597a859ef7adb40fd8030611d3ac6581e424ff636aff72f4dcd9f315744a3dae6cd386b2f9945140071a5a49f05e8f979115678eea7d6d884a92e4f14ff94dc102355c3aaa93e02723a92417ff49fe8cdbefee7e6c5e952ad240fa7eab4c7941f6ae8d2a1086e1f2ca73eb8ca5fbe3588ae51bdaf18646ed04bd185a19bdad69394ac15d130297c0fce9d8fce8ea2729dde117facb274f9865ffb4f2c7248102dbd96767483cb7fb764fe667d484a3143db514f08577cad8bcf695b0d953e2a3c8710d8979952929d59c8b8ae62ff678815130e68c85d4714e832733da40b933b7133725a40a12534753eb4877c65fe4c75542f28d6f9e805789995adaaff6fce3929e6027338281c6d0c33aac092fe0eb1797dcd953fc1f815df794249dad7b28407c50371a8c81625f6e7e08ed59a98758a9859c41f7436f937885ad35102b0eea85f3dc4bb9a6260f4e091ed983b1009275d43e4960f9422dddeddd09e9990d545cb67dc3f1061238dffec3ce01376259262b4c32c6173a6f1e239f4502cfb0900bbb7e3b4883ca3c64c8ba91cfd80b2bec6aea25b01124ae11a56ab3e4d448038795ff62e9d5ea5cfdb99c5901a8b8f8731c772690dd964cda343bfd020e920b32910a68b433ddd01d117a833242fd695a54f33fce28b506d931adba499373b0a6182e54323f032f1e7b8bad58dabcffdd1cae831c70e87b2c6fee3494dedaacccfdc93fa23ee1a4273f16adbbbcc21f5d02d8645951b93287732cbca4c61a0d0549345160537501b8c0dfc97128035875e73db7eebec24813d03d11cbcc089929b0f6e2440a26d90cffb6295e8fccf65b4d676abb8ff66709913775e611bc843302a475488c9a9310c0c8885b78d5db5cbb1a919683cfd9bd010cf2f1206ab327122ac87d8e2899cc1ac684e72c91f2d36c7bcc3491b768aac86e92aeb106d22b3e85112a2a871bb8c9d0a0dd15c89d113910f8babf15f27a13b10200ec7078d362773f17286228b0d5a58d6654b0fb4f60c81ee581e507f17a044e6bcad4bb6ddc66bdde7d311810d79ac031086d7b0c334cd3a8a496591aeda23b2c0097cefdb6894b352395dfc79b74a6e4d086656b0cd9c95a48640cc8b3d188189ec0b98c8618b0def4b0175f11369cb2f107e89c4a67a75396cfcbe899334a5d5df5927fef2eb8bd836a27a2834a7ab94813d30fa8431da3178da4ae56caaeeee66cf545537ea260ea6af56d4ba048076ace08ff2a446080a6b688a916a13b43b933e506ad187b1f829a1d54ae261651563874cae19c490004205765b43c3cca4cd8a309fb1bfd7520bcc07794cf7c03d9b1d1ae0cf646534f5a97106925ee96dcb7fc1f74e62c01d382fde19fe027a4b9b7627c08e690abe3ab076f184210acbb4229d483f7471ad551eb614c35e019a8a894b5f92f5371fd6c457f135ae8377c5781a8f3a6dadd2c00697bd8399b6f168dd64b2d2d66d5aebae90fa5f904af9f950f450d8be919ae3f02cb5c0be9687560cfab2d2161db61e978ef46304de248383dc3a99e30573bb66f873ef1e54f523ff8ff79e8c05e7f8143cebd1bdd9d2186ebdbd3b66a0a3dee79475cda2890720ac5bc33f8cd3e817d82bd7c52c34d491e1e9d1d307eec17c0c7679af3626e7b96bbe6ba2550f44de7d1d88b3e4c220b8f185b459f1f882a97248cdfc3d42209ff44806837750b3dd21ac5891254f6c7f6938aef3caca6c55b633770772c2c06734f84612a59aa8cfd4f347267e631658cfc4ff89cea84550bd43699c1d8840655f39e3449ea0d2abba1d81196413302719bc9b39cea85cb7db6ab7f00683842cc480503004c1c819ab80e121d9d21f46f362614a5f2cf80cb2c8d3fda82447cd0155fd7e0ec7589a6df2e6614671071f0f956143c762d51172da46e9f61e588fbf74cb3ceb74bf2ce4ec4ae26a28245f98ae91f09cae77c4660d6dabe7cad33ac506db3000d742f683e08bbd0a7cb9eec72a1a976546ec926b9faba5084e00d66475a514a73f01fbe1e79c0ee0066f4b724e4977f3c1518d28ddc918c573693e9b3fb69b426df0640c5ee42cd5533655f9a82c6843516298d05cd970f34dafa886995545c37b3b939e0dfa3647fb3f330bbd3e69307be3d469a99c24382acdcac76c6cb71decb4b7b11cb5f2e63d112767a7d6467c51f1c0c27900803180337f463e64f507ce245f606f8c1f1df836c7fd02502bd3127424804c69f1d066ec3acd9c4374e857c4607b711f532867cef2c1c8a7d7051a440eb7a8507500d86f11567e2fc812a27e63e5599059af1ee90444497f69add7862b93ea050f100e48df7a578d55b6d6321e70ef7a7625ed89054ab010850912088fdc21551b89397c35ab582aed6c215e00d398a857090e2f7cac21c7b51f34054a45f36157edc603b5d6e76ce20f2dfd2c20158943efd2349560666ca38505cc6af776e0720af2d5f6a7d98f385854700fc0c749dafb597e94d7ac54aedf34840ea778e8873d6f1fd7f53de7c06327d08d34a03b38315efd8eb52683ec1f9abbe2bcf096fa4f379f41e09b8bc67ae4685e68ce456465b38892a238b18358714fee41da0aac8dd729e2c3f17488470648df81040272b2e927e896a4eaf6a11c457938421288ff074da8db60d37c6d022e86952341f2b8d262cba0c5a6efb51925517a8c817a152499ae7ee56d36df86253e6b2d93079c89fc922014b03da3941509e979ff8dede44165ca4cb698924fd12bcb02a35deaad608ff3358d455a49e12e944dbb11ac7e9571476bfa856f3bcf90ca9bac6d57d5c1755104b348d2924ba9b14e9ffb750cafb6edeca6dfb79d73b9839092032035ea700d81f19d035e38bdde754a5098dae1c163f9c473b0681858004ab9d9c2c57282ebd7e57c474b8f7aa091d1048b95e7ef887767f49d2a7f6b410922da142ab8605e735ff6ea9e3f36a29380ec43dd009d98d8c20f4052d81fedfee6cb018b2da59d63b5fc153d5b0948d613415a6b8a2b7338897188582d2930480d897d55bec899723b285dec9abf819ac7e6f39d8c35c484ca13f129fa4b334979bac7715bbf5e52a9926568f359dd3e3e000958b561527bbd52025918ef75228c423da41861396be4f829aa4bb6f94f65e662e6ac91e828d721b741d7333a8e3050f136a463af537ee97af4b42456d65e1e2324f72267c07acb88c91d0cd602ef765f858f69fcd44ddc73dc7c5f8825f3fe04affee769f3ab5486232e35df8fdb75db79721906907ffad83c57a364ab85d93bc03ace8998ede749d88985ae41cef163a3d00f568d43115992362c581745f723a2955ed925cfc7c83c5b5188812fa2dc016dc21844f923b2362afa5ac5f2a6c9355b2eaf724606333f152a01c330ed88f7028e716043330a280c5ee458f2032c8163f5548428ce4c529d487a16ca0e58cbf41dc4dc802cc5ea7fad6a50de0c0f2c2be49c3dd2806911ab1322a30acd4fd8937b8930069fc1a6de86f9ef90f407b2563594adad581b49ad1d19b30ad13efb0ddd8e6f26dc43a36ff8d14d1c99b073f5f1ce8923d3100bb04488b86cd4e89f7b9f5b9cbbb3f86ee03b498ae255e09eeaaba3e4e4d68f1ee4d50f699e460a922e17ea8f0ceef9794e944f128efe835f281a7662f959054aa994afa3982f7a310f46f53d5ffc07884aa91bbdcb3f3779ebdd7f90801e96222f56df39ed9c2bff5d4a11be1da7482835e494b0856ea7c695cc1b53acf3b2e2d1846fff50bf55be65e16548c4fc436f20c50c119ca8eba4cdeda8c7e4d33734a0355586629ca5a7c3591ea4b15428a81b6d91529485004cbbf60e75208579ac354dc705edc7bccb32f23030e733d3f549fbb841329a01f5c5d263ce635a57aa9c69432e5213b155a07c34fe19cee737cb993fdc82ff38eafbeb734f04f58d367e34df15dd6044591983b9b45d4ffd87e2a6b478c7d1e86b4b974991b930370d5eaf5edbb53c3dcda643fb992b5fb0725a8aaf8a9e7c4012311f197179cf1293884e2356fc5b624cd46358d3c7bed1fed6b0305114cd11675aa49c1b9e6569817d34fd60c1105833d78dd00117284cd1722074a60655dfc428072b0d2eb881b93d6c367952a4bd59eb902032cfbf9189bf65f7bff592032c77d61dbf778986b491e297ad0da5b367c8a10c9071b8d509b246393fe04a290b3e2291f04eb750285674ae3e9c7b76a01b679787a4006836dcee956185d3b0ce16c4567fab862d3634b93079305008e2f99ed425489bcf5447699b7a7212fe2196d3999b39191e750fda742c6ffb5509e3806f38edccacbb8bc73c96cd46f0f400c4012f1205813d69a48bbd1f55724c7de917ab56d4188716b96653ebe4fd1b6d5d252f5599f9c53a4683ae60c8c31b86982f32bf73401a328891804daab93a155140fdd41ec87e392c8397c9ecbc48f26acee4e3cc279cfd67d75b5e0b6484274484c18f72c2532b4064cdcc309df796c802c17480428c3b5a5467b38aabce03de2a266c8a22d3b0158beb913d50615a1002fcbaf91edc529b0cd38f35138bd71dcfef1b6b90adb4e68a594de40199724c158db9c85ca78ce3a19378ee90dac98b23e1515324fe18472a4ca93b004295b7abd3c146109da707f5ef37886fe1a8966ff1e96375fd64536eece72ae3433a697492955cb182331ce72e8f1804efee93b1929338f" ++ }, ++ "ecdsa" : { ++ "addr" : "0x5e13d369c8adbd8079272b624343ee1edfa4a560", ++ "claim" : "0x197e55da82eb1daa23a5478ed230c6d0452d3c1920df15e10a8d37a7430a7f2b69eb474bfe0c44a6e4a55db9d5a0e0b74549c044ae22778ce30f47a9fd1eba4100" ++ } ++ } ++ } ++} +diff --git a/consensus/common/src/test/resources/aere/registry-v3/n09-id-derivation.json b/consensus/common/src/test/resources/aere/registry-v3/n09-id-derivation.json +new file mode 100644 +index 0000000000..b1c2c8ddf6 +--- /dev/null ++++ b/consensus/common/src/test/resources/aere/registry-v3/n09-id-derivation.json +@@ -0,0 +1,62 @@ ++{ ++ "description" : "row 1 id is not keccak(0x50||0x20||falcon)[12:]", ++ "chainId" : 28001, ++ "requiredSchemes" : [ "falcon-512", "slh-dsa-sha2-128s" ], ++ "ecdsaRequired" : true, ++ "previous" : null, ++ "expect" : "AERE-PQC-REG3-09", ++ "manifest" : { ++ "formatVersion" : 3, ++ "chainId" : 28001, ++ "bindHeight" : 1000, ++ "count" : 3, ++ "0" : { ++ "id" : "0xaaddb4dde09de5718a906d83be7db3d58e0ae32a", ++ "keys" : { ++ "falcon-512" : "0x09501c96d2f5cf0b28fa00c726e5359c5d36a1fa069971f854b7d914fb2f1295e68b2c6fa91d82f7d287f55ad493c87320bf7ca2a5d5e79d7212e8a540c166b588dc03f73b83be060525b367d9f40f5e77e7798c60b6499767586770722820b3b9e6013cad3eab5fe5de96089a29f34919a2e9ebcb3fa03a3e714593b7a3356d11ffb3441ab40ad94474da662a71aa2419dcd50668cd5d8a9017662cb60998b34ab5b7929c58a94d5e133ebbdadb2b0279543067f76bcc4cb6d7e0a5edb7625467e3ddc92a01206e1b8dce69be31928687d8af4d26633a07e73c2830d5299b878977691cf65700b65b6ea2463e51b6136888c544545e59fe8cf190a7944e215a785b682623c95a79eda28e25e0e1b91b49ac89deaec3b14a3c431d9046a663170111ee541d81b43aa91f29dc147c6fc97739b3a63fad1ca84843d0a65b8d9396f28e9b11f9a41453ab18a2309ae8db03253a09fac8f0cd634c76a5e938a44719660944a95dff056cee43ea99592c3899c2880d7181ee3dd5c04baeb60e1369a69430a66031e3cb10e392622f5246a71761760cf417dcb40ad65f60704fb74ad26f26c3af7513a42f806895e0298c25c049187aa536e0eba21998912e621846c2ca0e323744ba930a29850fdb385c8241382296ba28dd4df05ddb1e61fe525949034b59929a784406de240f8086b4074825f419d5472a28a0b157500be37e9f64897db2b645d3807c48dc143266c99e7cc1638ae278772493a2a4ecf74e526a514bc9119d7129c5a0d115a450ccf4dce05b76d4b6149fdab028006df7ec2209923117abf7578a082128cad42aa66b69eb63acee4456bebeb537ca57bb3d3487f95e4f06c5cb29f292d3b6284e5a162cb83151cd9ae56aebbfda150b7edd5065302ccab70892733a1e096ba0da5f51b42764ad23060eb197d5460425fd9c7a26e7dc3cfd40eac3643539feea72c9ed41569111a7976d2c345ac2183fa2271b424526709fd9aae558a23a5cca29f4e2f31629746a71d904612e95ad9977bbe74fa32e90fac62625838cac49f50e5aed4e8879e2ce2e5651c4f4ba0c96583af9e1612b5ff1a6fac5027c0a308815e592308170b915b4a2de1e8d48e9a5730680ea9db8f3326c430241153b3b218d5347d5c843570cf80ee813871ae10f6b8ce4ab7e4c5197045e85b1cb4977f44c33eb85894b6555b4bd288a50c1b656936841048983c00a01631f10a84522cd613fed0d4beaa4aa4b3e9f30c324108d909e59a80150", ++ "slh-dsa-sha2-128s" : "0x47a0b70170dda85f843607f6c6fcbe6e6acc7c22980c108996a3fe72dc9f61a6" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39c8813cd3b34be58eaab900555a67486034b1923e0b00e435661230cab85f07690a5958a5f5e9c84f033a3dc2039a5296443093fb7fe8d41895fa73be3fb34cefc6cc36750d534e6a3c47307294694729d6cdedb633e8efe8979a9aee486eaa66136e342c578761241192610185feb2d3c196bea0e79222437b6a8e08cb09778d053b29552df96507b1cdaede8e9aa7abc18902f29937f30e7cee6868f349f7ae33738237dcaf86b8e8e01238f3d8ea6fd4090a8161db65dabeb5ded5499e8cc8a5b32607abc291b36a4b34b327d30cdef18c1825232e69a2b09d539ed84dd2a4756efa64f864c563943b3db825824f294c1bbfa2157347b0fb0e7f8a56ec253b39ca9b6cb1ef7d3d7c93a6cb220a7dc50c365905ea5a71575c3aeab25b33523e4fefbaf66137f45c3d96db719a12d2e2d42fbd6cdda58c5a1b958b28c2a8f2cca297871a147dda92a7f008a359027a9288e42ebcd6ea9542f10b66dbbce6e7bb914206122f866d9adc1c89cbf8bbad9bc9517c2ea9018b61d4d2df9abff1dd9f3a0a6faa72a449af9c97e8c4090f3bbd9824298e61599c13c7eb89677c0e845ca2907c728d9296c24e96b6a348dbea7cac62671c9a78a531463614ce321e28ca2f093094ba5f69881e6cd766874622ca769ea556ae757cb7f9546d99f5c90c25e7b8e14f3b7f270861398800b0604ec2a3374659277a23cf6131c63148a41b05b3c06e2a98a268f1b9f0df7969addef17179ca2261d3c229ae3db0c490834564c45f7b8ff6d3bf70784779d75915fb2e2d5bc147bc941b9e249af188f63f39b028547cf080b7674b228e20a600e3b167610f814daf105226f3c1ce5e07834fd33dfe46315546e926fd5be83fd4d47ccd5bb8ae736ac745daabb59c87b9edf9a45c9a1d1617ee84e588f27d12235c59ffd9", ++ "slh-dsa-sha2-128s" : "0x0e8f9bdc22cad3613ed07fba30ed04219b9528f9b657119e2f0886dc71cda4afa7d462fe8bb108feb58d998b370b2f7e162390713d1a17eb7de781a604041cbed13d00effd3b24f2ff87cac74f61e7b7f7aa6a259dc283485179ab4bb966793be018c4bbf4475bf7a69e600a37246908f662813813d4b0f4f83757f4064c5c0713870a0b98b5bb99025dace06100497fda8c73d7385d123afd4953961066e7c8544de3fb620ef5e23174327c2b64089b3fe6df3eb86e83b12634a0c9cc0d7844c894ba6d83afed6becb6f5abcfff397c5cea8064e5e153ea4253abe599dec1614b449329ebb25861b69a9b22228d1a03ba51532ea64ebe7603474a15a2806d3dafa29d57d27c5fa894da673b85b4674ce835fcfbd391d328ef83504101432bbb0c83d7be462b265911aad862118af6f4cea4df0f1dd38969c69428fe438d59d22736fbc7dd5faf6758905b26ec4c99d71e4b8fcc562a694ead91569c9a916df5ad693cb2ad0b7ae4c4f3c5b7322f56612c5449e0339dbd367460c76ab89b6f44942cd33f35eaf33c2ddc0c6af793556d5202fd1fb0f9fa1b7ed45c6ca68d904e476477b71a0bc6ebe248c9b4585da0c7bb186600691269bb4c836667a6d73a455b97127d898b7fae17e1acc6dcc3bac3ecb14da131d5f8adaa64b054e2f569d9bdb164792038e107848882de9bbeff295905c2af68d4c6dcc8cf718c2de872ab6b3d18e00d527166f8ced642281302e2acf4cf4489072a2dc3d55ff8716619cde494be1763dce925438b33ff1b91b35eb511645832720ed92552d4880ae53ff6516cfaeb1d48c923648e502e4038676f7c82e532ea713c6b9348c80ce3c5735f437491d3a8b1765294868c14123af2e9ff61e394216e630c71ff976072d2a1c50cfd8ee1ce27aba5bcf9aaed4a51521bad5e5d5e66abc7a95b215fc8004364aa4df2b8b97b14e3950f521b6327a55fdff9139fb0bd35237b022e3aa128d36c8a60f4621d25d28c59a97418c7dbfc15d900ba626d283632732631ec4a948f66dd9db3bee8c2cf60dfdacbb5ad4c0b2b31f8428868cca035e79c95bcacaba40a9351b2b44cb29753b6b9da0a751bd5af84c9094d5fe91e97501d4f075392290e8516ed5e41b41b00e09793353707fe5c1d942395074637f3ee0a0f105876d6f28a74f9558c5f360e98f047a99af35ccedef8d5cd299365e81e7e91f28a01eb265219e21aa7f7ce56b62f9d2a61560f9fa39f2765f5b50920658100a638aad03482a687905cd27dca02f1deffd1bc49a1be1ea7ff1a505da74fd932937d8f6a8bd75ef456d5f7b71ca5357bc66db6cf14368c4faddf4996363251e6a6113ec64d642c319dd85830d8b4c7ee1437ebfefe01f27709ba0c412c266530f5b6bbb005994774e8935f1d91069f9e7a8cd2bb7ad6527768473affe24709c10294eb588aafca85b379bedf0b142b109e1b186e635b0625c4e59576266acb5f71040c44035fc9480b13932bc657cf332b12da1cd7d5c3977f51d5fa742974cd256e8e3662dc698e0516d615d0a05ea9caf12338d0dcb6151e07f184c9cbd5e59bc40b12ed6372e2d6bd42aa0eb6c3c888f264a8c0d3332631d4919c921cdada6bffbd01ca5445de0779f9723577ebd7e33ab0e5f577843aaa6cb8cb5f0508c33b63913a44d02b76bbb1eabae325581738fbddb5d4fdef8dcb8597bd29c6ecc631839118c44f66ef8dedeca65e58941c30e0423c40bf064b8d19d28dab3787238781d492720236a7ae0695ccc867fbb1cf207ebecc64f84daea66b6745515b9ac9b725061bb9958ed79ad6161318a262528004401633d47a023c645683e36413b8653fa4864fe98c501197c10226b1732337842a1322bb788a00a0de86758139c2d9ea3c5b26bf5d7a4a92cab4cb686c580e3e6cca488136f0da9279073b3dbef9519168ba02588fa29cc60d02273805b425b919a7e2e89c9086609982163e09d5f6eb9c66267ac7be363aadd4617d398d4bdeca37a838d650b0919faf13b78642a058b1bb96b2ed1482cef9bc6e8b2e061e6815936e15a9c754353aaa786ab141e95e5f6c464a41b8bf29e28e764abd638abcfb342b54d08c15ba7e24e6fcb69b844e16cdb5cf4f50db60ff0699f969d8e68511fcc9e16a58e100f80671af6b04ff3edda3a4f05f9183c0c3bb7c1061fee2d3f04e33fe75f1354e6de54f582da914da0138e8565ff45ef52f638cbc33a24bae863fe91e58d7c5da34273438f15e10d4f59db16e505620d97d3fa4862a4097a659925d0e5f4e073103ed29a600b051b83b1f3a21381f4b871c18d262d7e43842c34ed80661438c064aa2fd858a8f3bcb035b5e942baace7b50e4de5a73d5c51fc0843cdc163958a62d333078f4c7d883bd7055a602e04c853f9215c9d7f798403c007fcee124cf6099322629c449ad4ef84b7356110798dd87aa4d98ebb47abc6cc8748dd381d588b77db7f4e7550f6ee1ef4360dac6d6c7037a65297d4a0ea7999a5632b90ad48fba0a916846a216941fbd13d62ab36e1066e24990c19592944078435c52d7717b3556595b645cd2359ad151dbb67e92b14168cac12fb2cc5422582a50bf6e99f116751171c9b78744ef719282f1b84bf95b4092514f4c68fb82a1526e0942ca50e186632cd9b0b8b8d91e84f85e35f30f815601798fcae676da6a2d38eab62f22445099694804a36a34142150fb795afb445e78c241f0b645209037a8871cb5487c975975ac997a540b709e3df6bf208d9d8017f9688b152c9ee2b934f65393de8403244b7437108e6d8c973aa723285555d9eb92509b1747977105cbac7fc33e658fd51cd374d21fc2bf229928948292c1698db7934d0f9be44b137514d0a5fbb659bba83861931e03698a61cd20a449d0358a5fce7f288e18bb3eb62b7ba0ae75feeec634fc90fc45ce45239c5e3179309f0c202cfc53d9f42a617f7aaae586e7161a0723ccebb7e8586cd40e1fa12d3ee89b400dba8073b0080ffaab1182e8243afd93318df15bbf3ce179f21804fbb8882e855ef9e0739ce1536d8ebfe9856aefa9874b4e102e705a40ca4c3ab0ab7df63ba525189b518796590035ca780d348de49f0ba8f28456ca6f3e3cff7e761d961ad98b8cf01e855797c88fe2f811e41e787f3e4becb0ef42ca3b9979356020b447294ef295543e0ef512a247e4d356bfe3deacca8ddc5255e6ad047121eaeafe61d71e7f31395cf78890add4f8c688e4eb065479a63ccb3d0c09028bf60c700fe9d19195c26fcbd4130e6feceb52e192a2aa2343c05b43b276f51a7c55dff7233ea512942291900d93315438a96af08e25ea5b9ce656c54e71ed60d1eeb1665ddaa9e42378c930e21d93484b9a4099b7ddd71d983b4c42c6b1f62907ce84b24321422b08b847f1ea97befaa4ec30a794ad7f340210c800cf185ee2c6c72e844cc5671964e1e1ec58953500f149f0f0f25c34d5592de421c2e31535040020237b907e86d753094dd4532e1ab9d821e7583d4a21e1041fa7ad711f29ee3721a2aec6b0c46866a2de71ee850d8122f722898e533848e2bb851ed24cff9ca83badcfad88a171b4be064007aef4d759d93ae9b67b446f3c6fe504f5b4fe851b8312fec86b46ec3cfcb36e0f682e65e117702b888ab8566c9cc716a3a86106d2323c0f7f20fbc1fcd110bed4492a750befbfcbbe16820077dee281bcdf14509b93137a3998b2fdabc2a375b38857bed12bb8a9c67bcae7934d02d6ff89620fa8946c8aa524fde99c12fec0e25bd79788e2c15fc31fa3f27502cb952b9f9482580cf18ecabd92c55113ec4c4470c4dc06d8ca27a10474594eff708209e8f376b6f17915c2966dbeb0e35ac2f02419692c0d232e133b3907059d3a56ff169e7e61915c8b1067e183337b40bc1136241e862eb3ab3f2c6a72b18511c4107ed063d1e2303d0fe6842fb01c204d1bffad7e90bb44a365e62945a7f631811c9c37ffa5ac39c16b4835798686da5baa8e1eb6aa76b42f6b86863c30669486a175d6b3bc5bc47c5eb05b240bd921007fa39506c6605bfbefc9c8c493973bf3f0767817fd8ce126a301c5b8fba79628a9b3a03cad0c491a5f487dc5e89269e5d3bcdc2998a136a012486c5bce2e6c6dc595aeee2ebd5a36dd06919396184aafb2301d1889b668c4d701c7ca01b95f9508f47d4c411cc0397c244ed4e3e3ad7f97d86b6f8834b13b1b2df0625e6b4eae9e439815e65baf2da767d3b1700fc461fad6297fe4e8ed02bfb65b750c2d2801b7308aba9657df3c3ed7d548687f55e85c22343d1db343bc2dbe222fb76fbb3cf490cee7a99ab3a337c626a148fb303b2f8651651588dd4859fd65c95820ee2af85adf4e8fc2c03828ea7427e7c6b0d4a1b0ccd424df6d1450ee436c01351d8b6bffd4ba072756315968845ab7976813d93d0f0f2be1c00faab3ccafa71cd26c5837e87292870cf768c7837e18ddc3c513820c660870b339fc42c5211d33d892ef22b475cea3be20f5e47206efbfdbeac208e26e97c400edfd41f063aaa6b85a0cf86e23fb11274b405f4f796eb10cb97e70783909ad492ad9207ae7b3d204e59d69c886f91bc82a107d0be3ae85797a7cba747b8e2640ec49384f53c785a84cf8de37dd4048dd4b879c58768bd131ad7226506113c446fbf13d769794f1535d58e9c52e23c1bd55e13c647d304e297d968c759a378f1d594897a026e3271aa6b4daabe174d6a35665b35193379f0ee465df7827299c18e1012ac69913a0a5bb5142e99b051763de3e98d5af8b62133e25b32f4f12b787bef7e21dec42de8e4d99a0adc8f365d8cd3e6a5ff3064ca18965ffdc6b383f7ad08186d735a099bb0ee14506388c1a37f7a766d286d748d404457226b952ca6cb3f317b0f4399006b5b8c6eb89f6b8cfa023cec4d2dedde3e31b9a633c0888989b44ab182a5aba30ba78640f477ef1202f6496fafc2a18e283b2e4e8bc60415a1c9a7fd68f15cc1ea0299e3b26f5755ad9f13481a0563a524c6735942f5069dc1d6a070b3c3698e9c503f67a11efe59413e937062668d3439a5dbef197d24ebdc79944b17c549b0648af9b1349cad83c2a0a9e55fd893cffe2aff4626662ebc5014e70baaf7cdbbdfd3f92fcc5eed863fa8afd87f88873f726a0a2eafe41fa81edd5833f5520cf93b0fbf0660e48eb0258d313bafb87dc9b0d0d9349f22fa2d960238f67457ad644bdc60fb5eafd1c88dd2a74db4da0f723a03df08af6c64883f275395020341d9dd3c7fa049ab2bebb4d8af2bb8dc1340d1a80088c4b2c26bfe7314926ee64bf239306c05dc2ec6e6c5e0ed4f6dbe51f5ee09533f558d29ca6fd27092c20dd892c89c83223752006b23e5abecfdc733aaa59c8549e89e5ab0eae1b44189f58cf9cc18de0c2a2f46a9235fbe42c641a890039cf6aad820f1f844edc24e69bc3bd0c22cfad3804d876edf5491e88cf891c347ed5f24464f2df439bb30742e1f9a4a7eabd9346c6a5f93af22e67becc494cadac82cf9cb693acf44560672cb9227eea2575f90b0e28431684ae12ff2e86fded0be3a099f9ddd32a7285531de8963c9a03355f1d9cef88d7ed9b842d0066ccacdb698d42ff9f8a4f000b9764a9aab1f3146f9f95e6636fdfc9ef91c4d060a54ed7f32167e7ac50590dae3a2904d5d2eeaeff2930bd4cad7166fc17edd2c30e6738157eeb0b441491e5dfdc17a7fbb2bdc6426b2cfb26cf2a7e20013f1b3e33a6d6821928443cc7893f7e4a5268a8b94a6ca6097d25be17b214ea4301e9a723194983bbce286f4363a53afd9e94dda9c761481d9d20c7687a2ff85d42436b9d557d5dc6c5e24ea21d5231487df9fc7986100664edbbc51ad4921c5ec9fbb407ab33ef5c3b3bc81f113e68f38d73f0db0261b656fc344d2d23b93446845d69cee1704834d98737848d405f52f5a7bda3dbdfcd3af3881484579d2d2f3ef976cb35c9cbb76252f2e00019363273489b39943d212ccecc647413c56de69e0087532223cf9b28ce3f77fed30bc3ae6a0842b546e0e1a8b6f6ee1ca0ef1b78c3ed829af817099426f94a447f67229cbca3c07b7a8ce547c5eebcf168248e0a0b9fbeb398e5ed2d0dcacb441f95f9e30c108c725507e459d34c1ec01b67065e5e202d685502d6ff015d46c20bbeef1db38c29df7df585b95d79f5687474e71fff162c0ec0c96c94c507f8a0292a8c32168dacd2fff78b5c7dc145e10fee1b25c478172af8f3ea132fdcad75dc22856deb2576a5ff3e8911842c811d1d57ec203c77b82da3658cbfee18d140ac341d38a30f1af298cf60f2a88d0dfbd3e079ae64a07abb4947cc042925fd5c64bb5d4467589f8c495b0097073c081517bc4504dcd7442bad7e7acafc894fcf34f535979364cf5e908a84e0e141ae47e2ae4dc95462b4f345b12b0629502c7bd65579ec66b2d0a951302ba6da1d1176db6aa0c0ea1fa88195dd2248990fa4aba88490b1da4ea405649203f6ff6f734693f40deabdad59ac62e3296cdcbd74061474dd7b63c46bcfe6ea2b0ddb0f7e77fcff3599892c82425b05ae7aa1a2ac1dfddfc67e11921ff4f2c8f6297881dd5e38ccc4076cac8015c59cdd6023ffbd62b887b33ef8d917446a8941d9563acb66a6226fa4d3f2cc21604c080b3f83e73c093d8f2f7067c392671020c7a7eb6fd0d97af0d63032a3116c408b708d4b2f711c1134b88a91aa359608550f0049af2bb97688afc4352a45c4f6d30d4634e70e82515ff1d5f77851ee857e42b486d5e1f3e0406227dded6c5f47eda30d94f44d978322891dc729eb6ae95d29d22c8a5d649193d5d2aaba782fa16ae488f645a7ed90a566e182f97bc62049724f4cb5fc71f6bc7be57f07a7afb9933f6706cc83483cd7dc4182768cd35bc42f1e9b54d5454d3a17e734475ff58fc66d75419d3d122eff05f7b0548188682f1318ec32c5bbea87c8624cc1e548bf18a6b102e7a43e6bafb579e4e84275fe07d8c63ace449a44cace5d9305ff756cbf40e5a6a20334d5b4a74ab0483e31593f2277e90341fa8036496c2bc6d2b7b10b0b354c86d666d65cacc593d1d7349e71b0360d823453011ee16b6280f5c048111b99b185af99e9d901d4eaffd8a96b1ff394b66208ddc1e7e53420fa965bfc4e630d73ad97b9c5c6ea884c619bc24ac3f46234e7d8d35a12b0cad7220d7a0945cdc64fee9d8852bff872c43f359e7aadf8fa3de3551fb716704af68a18f79d03b3c7d90cf21eb4bbdcbb4004f8ba15ff0bbd2d0918ee78e9bde980e4f3cc13558e6fdb40ca71ad2c10f5e5587784bacc6b925f72da12528216895e0ca4b350d078fdf534fe01bc86b45e0c8e2b35799d268a457f8768ed782dfb56abecfd2b9db00cd10e189c6164f82f5ccab423277e3465ec72d76b696cafc1cfa9a7fe47d142fd6672d9c5b77751b40801af07fc53b1c9da0fe6981ea75e066572f7272baef8fc54bfa7cd71cd0fbc5d6cd717e9aa07808496ad2b4b4005a320c9312c73385afd61193581dbae99df6c25f1b9da17093ccfb108b0a26c5ae4963183533ce2f0ade01bf5e818af613416433578522b1b1e5aa7c791570c8c8b26ded266399116f5789a8233fee128e54ca8ce63fd56c1a146c3006316d200e05715993d1d97907ca83d7fd42ef7e7222eebd74f9c86b6cefc82e614a53976272c8801bdcfd882e34d86b39142ac05088a4c47010a71107bc72a380bb3e5122981d1795256beec20a0fe568002d79a4b1577903fe8682f268eeeed0a97861337ffb6861bf378eba1e0957111c7f9fcfeb55a95238005b40e13ce40efe846ddb86d14c9ad2c46cca74baa364ed08da3a3079fae3a36346ac949e2174c661b8801a051423e95dcab6a0f9c965e8744bdd0e629bd3c1a1241e99951ddde184eb8f354209f24c04fcf10fa8f4e43cb55c922c28be041213ddcfad65c86e1ab9b615f91d5fb11e4cdec5b7e25f8e9811c82c2ed457d012e4967b555f228baf4f1648854c624e0525e36e5f4d1961bfbbc3621d79bd6bea72924d8e0146d0965c239a768b417ea4c33237a60fff2760a9dbfb1113a37b01b598f3e06987d99518bd9f1ec96cd7050863898c8664f793ef29114bbeeb9afab8ed09358d1227d7de2aaac0ab2391cb2013028ca5f4d1de6425ec5feb17d95df358572fa27fcd51d14c363a36bc37c7497a0f964a6c004561f68349f828d30d4633e87bdce6b6d92384c9c1c540c8295ea621e9a8006a8d7c163b988853071e06c78f1b9a0246db052e8484a65cbdced3a587e45d9e2b49a5501590cf768d08b6a043971110e9c9dc96abe855abbb7aee2c38bbb77e5c68d61f01f2376b6122450117240532c7c840e3739395dd6c9e80a432423fc5e3a6dce9dcd58eb418e16d7aa507b4d67dd6fe2af4042a5c7398ba4f87c650926084efbfdc9430a4bc2be544880ecdf7361aea06a25e4f592104b0d74312f2729a4db5876b675bc0fa68f6e41e014b7caaf6f49b8ef704b6243df410dce94ad2c51d328fb90b9cf2f5df645015f489a262f57a5aceba40a56d343403b660928cd7a9d165f4a5bc289c0d28f33dac85c9c2a5c79b5ddd22c744a0388a5daf4bab84d7c77685053c912c9a24b5a0664c6253febbcf552c4ff38bbaf2f7e0c9f06e69a91cff9138c2745b99367e00ff6b6a920b1812e17ba44175c033df0e58d1b5c0b7d146f861b62e812ecbe99d638219e0dba4dd88089005977bcc90634c4dfa95f87370d905d32f613358fba2efcface0b9a414ce33b09e271a647b911843933c5d1008fb0717ab59739eb8eb844a4b34bb1a8f635c5895afa285ddc43720e78dc81eee7db822896bd9bd6ae3e7fe2988ba560d58f02592870647b94aad1dbb0d0cb60e28135ceb72e0a6f4b7893a56eae83f9d9a4c549d53d17c6a00f5d6c266d23e7a1d13e22a5fede3a7082dffb34296f8fe9f3bfe525ee1da81efde3aef9b6de8457a10fd4340809e1dafbfb9e2719c327a3c3a4c51d4d5600e8a01ebd5c537a4cd7c4519e963de06de6c83a9b968b01f79e08b5415c5a9d6a92a633d6ae969b80cbb2cf4d6d1ab2c3b94e7c12df27ea89bff4014d92add41a3e961006a194ae3ea4a6b38c2827f6185ae636f6846b1c8401289696fb10c765fa93e58d068bdcd8c9dc95df572f096d65f5de42bae639d41ce7e1ee0f48ba4faf856c0cdd728956d7e4babd6d9d6389ff41d76c5fbd6380f351b05a37022dbce0a6a47ab7168c82c77a2810c80b1882f825ebf86cb7f6d0f54025fddc9b9120802514c797d1d3968631dae95297a857890ff1dee408909223d012925dc08b7d1119fefca7466392a019d4121ea76c8b4c3bd103a820557e4b2283e262af32f1edbffaa253c47d5873bfd0219b8be86c7e64ada2d87ab6b7f428a7d8fb3ae09b05aee71054355eb83ad76c05d836a9f1a65511b1553927ef1b19ab1576d7185af61be6104de1df218918179c6321846085a83bd1217aa63d0b03996ac1fb4018a8ab54fcf635f7d5a8ade95894f0d407e5d4691920f21094c6f632f1661402a0b3351f168f16a13d3a31ad48e89230cffad272926487f36c7a2584c9387623df6227be8c96088db4a21c93b1c88ee756e960f60e614b30bb6ff757c20f3674a7ae7f6ff6a9115a0a6d444513ccc0be5dcd557430e0ee8db3ed5b3e8c405110500b9bf7f6eb7748de4988a1db94bcb16fe33479f64762c53a1e2965363452063d7bc14386ca7b4d46ebcf08489c64ab413ec0f1ddee8719f5fe978d38438ca3059961ecc8480908cfaf139d88db2facb5e7a88a43a67dcb0f97a17f9bd5b09b8369803ccc7ab6d41238e59e43762965814c10c36fa4b6e61bf2e83c0243f20ee8aab62dfa9827aec06f99c5c565c1bc75291292d3113503a202851c26d1a8bde54bb30f0301e555374b71e278925a2afb29b0209c08ecb89601bf612ce811a493abe2bff78e7fd02ee13c5db6b3edce7c87559410b9be3be95465468e33af224d6508a44728cdffde4cb14fb96a0d2ab9c7f597541f9963775c32ac613af9beab89e0ff7a5e35613751061b0511532b10b3947802901505c8e33bae67ce0e28da760af7e80b730811bdf17abfce39d35def51d73a084119449038c2b0f1c86d844123c6e71f28b7038053e279dd11c088dfa11c547a4ce13b19453e88e5b74962101412490cfb68e21d8952db509cd3a814387b67339fd04ddd2163177589146409934f0eceb10db2d90a9e3f6691eb75e84d5e66bc3228baeadcba200f3d11e0cae090ffbb800f5da7032c35ab572de55beea37258bee6f191addf01739a26efaa612991cb2a3c6d1bbb03de0ee1fcf9b7f6c51e452b21c0819a9aad93162eb2dcc189bf355ecd2c3e504713dab24bfe3ed86a4194611029f7f6216cd469fe1f7d35d56b6c8c2045011e238f9cbc0a19b8914d74329e2472f15d0b7d60511814ad2736d6be168aac01868c2a675549c849fe05e05a76f077130b46896735db5490277b76bba43545de6b8ecb53fd20398eb94dd884951fb48d5690ce4bcd0b836615cd9340ff0cdee1122743accfef343811a71c7d14d1369fa49ce47784a6ff8adc26c151edd4969dba513ade6a9b1f009e57c3d6aa845ddee275169ce58e1f04b564ffb6d0eec75f7172e5e8fb814cd702c9fbea8a783bff637db8667d4b6b48a264135bf60acf335936105abacff0351ba9aeac88e9522cf7ed80069822a7db1a5d8221d9492e02ca893e1f15965fb82a80ee2ec491027bbc8906e71cf931fc21e1c0865ee06a79c023929625b4d232c7b3e2e4a4e5dde28fab675391befe583c95dadae71dbaa43e09d8d65ba36d148aa85d1a2a35dc51719ac0311ea72c1237c78a8b1542c59de3b743087245e54d3111c585b5e5e7642f625c8d44c6d9cff50d8d071f6fa573df937d9e7457302d8b293d8fd94ebd3023c55f8b260c3454e93f58f16d0f451189bf41c9f9b91d3c3918adbf98e4ca5aa0eb6314041521ef880ce18f0ce296721a06b329bb5fbb3024e424b46400e03caf0105877465285fcb41a93844fb90b7fc1924883ace6ca8a37c9905068c633761163affae39d0ba55b67fdc6bcf0908ee3a42af286c" ++ }, ++ "transport" : { ++ "secp256k1Address" : "0xe23c5bba38d809fcb2d3384f210e9a6405beb498" ++ }, ++ "ecdsa" : { ++ "addr" : "0x48fcd978ac4d42ff52dd81fcd17e93190f35e5e0", ++ "claim" : "0x2dee91bd2cbfa906aefa3a8ae6e2de773f55dbd28e77bc329d28215183068585601ab9a7f9ff0c48095407474d502a3af3f059a666e5ed1e27468466d69914e801" ++ } ++ }, ++ "1" : { ++ "id" : "0x86f21da7cc9a47f4030f45bc704fad2154b45bb9", ++ "keys" : { ++ "falcon-512" : "0x09a6d094d9a3a0865864e9a16b477236f1ca26c888fd0c918db331c87a478519c41085cdac7e6cd0d89190a41a3bd6f4d6300995d591f5e22a7b7147caab1f9c7a85a4ba74d47c7b227326ac17535de039a7e604225d3daac7f75b9544654b73f79f5825825ad6e6c45d13e6d385a644633e1c8806d3a0a551c98f032583c95fb13997e52a6b02192d26b5a47fb22ee52999ec92b75c70774a4ae0481a79113ac72346263e53d5dcde708668d317dd00552d5a40ad47e59a501b10a50bdc52c5c2b2c920fa0e3dc9b8eca54b10aa5ab1168c88287dcf80ecd880a8fdec85b6d63a15b9f453845421a5d9b898e6149b60454828eb9dad6442ec62ad27ed72215014f3d17539085ea3f668b0a9183ab96e9db996801c72a0920b02a249911924f181e8dda515d114beb83b075ce7e7a0902a6971e31420ee4921f5cfc123f29dc7775017aefe99a7e326119cb925f6f603ac3bb137313609498d5a2000c426cb332c82500dcfd80d70a5e2d156844a683b313266af6d60216bd9e9998bda53c0028f387ebd21a5fca6c0607d54b1e95724746d15f25f16e45845926a83c7598646a0a0d3a8f8307c1a401b823f1656ca41e5499684150a954318da076af9131fcc93361d9bf0ae035f617e02cb5e1224a982b3591b24013ff80dbb61160d2ba4ce85a4260c8a3a3218e0ec869796b1b04a82079cfc0ac26da03b04a11950b2a3331ecd0026ea9737bd20e6ea3045b56e3c71278d2a8c72c8014b769da9319e19dbe762b1943e5a4be15aa84d0da831eddbb10bd05f35d55b6211d02a61c5d9247e69cab6c112acb568ea51f345a5bf16f84782e04220e217722da71d634e1a68b796376c8a49a965c592b87d06702fe42dac12da108d24ee42a109e8e4cfd3bed6ada5e3de50301696bab0564292864f1b9f47d5a53cc0c5f9cc3d57051065fd57064d08764892ef4c4a92b475184a4cb4ce1f3a0e6da0402414db5a9db34632b9717586e799b06e870b81a330da7be6a45ddfb000fd337a24a29e164449f96be015818c53aaaf09b9a565d7d9d735b9493885e7cb49a5f1985977cd6824fd62f51d2a1e60289dbaeaea148a44dd8876cb58b8ca2f29f6455f354e4e76aa13290f2979b78b22afa0e65c696c21497e94bf0141ac6298aac70b5ea843848a2264fc057abd3593cb17465e06d41731b7153b71f8f0f7a06d362fbd09845f0815794050460b41ad003c9396a86eaab240555ac8c75f85c0ab972c1a0b94b67b1aee2fa3", ++ "slh-dsa-sha2-128s" : "0x2b2fea4a0edd5dcc2f653eb2dd000aecd87deffbce8818aae72d7862b506bac7" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39f3424cc32c4c2bdb8e81d8e158b4b51a163f5c389e440e053666da13d90b2c55ce9034afb919a85ce9dbfea3f4ad217f67759764f5f6f59e6b8bee9bef8cd431f341653d4678ccacc60919ac21672f44c5bc161f6f9d9bd056f41be829666814d847c3f931db1b78a3c8ee17929542e9ccfbf40f5e78c1a29804d337a672adbc0ea63e0367acc6b2e702b295bc31c6a52547afce023b4177750fd5f929dc99076dc0ca2e9258c5c2bca3c3893ca9a00d963e3aecc3dbd9bdad2120a95a670068daa7504392cda930266cc41ac29a1d8805c0d0cfc75606f4f9b5587d6d1b97b626ec5bb7e8dd2f48f2706f64e76ea08845f45055a6a0b5eb5f7eadd19ac36ae12a12cf2ef58e2c8f43359845b51fdfc523ccebfad1b4ada4d14f4de5da0313cd309872608b44b190cdcd45f09f4ad5940d85d8083e3319c19bfe227d6d8df56152aaf11cbbed2330afc689f3a4dcaeb4a57f0537edd510cde7704d343dc54dc65db05316b95ca44aeeaf06ef5ca2abce8fed3095b35cff2b6afbf5e47e672671aa73ec92b9d37301d8488bb2ac71b28dd64eed637a56acf24c6f9d34bfe58d9645e18b0cc939a748f04a396746f3158601d95fbbfd7c8904932a0eef057843d44f6a01ec297b9dbd5712ca4ff83022270279ad1164a623876a75983c3ef7a7de6449dcaf697bd023d728ddab54fee05b5d4d8f3755a74a3507ba96c2e3617f78645a33a8a4c5f0869c9e212c09394e5c03d3bf631bcbe4394d4da8dddd7369df38b9ec83cedec3f03475914390361cb5522e9d1df381be267af77bb7e1b8ea9ac4679dd4c360153f96688c35a8d4fe12db57b2fd895c5327b98a1024898f50708501c58a4551c55db5d86db3ecc4ad28dde6ee8d0eaa0b7350a7dd4c4b2cb3252b5b3499a5b44b9a333c80", ++ "slh-dsa-sha2-128s" : "0xc7c85a7c49c8c259c3166dce0f1f2155457e792c84764ce212d277586195859b6144ea3b90735555fd7e96eda0a2b052e80e4f20968de14d33ab27bbd1d1b83ded17b9f69ca31ecb4a32e6449ced6433ffcb6b8bb933c59c09fca37a16fdad554067ae6315da891ae10e8e706f711a3a938c6c1a06d6d81e0fc5351e0b2f534821ff1161201697558e561743ee8c356b0ebd165573a162457de3acc60a2f3c299e59b04f0a28b944afe344ab8981486b4f84327980cc2634b990ac26fbfe2a2def151f21c9031797d2a683faa342035e35cbd6e63621ba78291d6cbc5d490eaec4b683c831a2a3b9e3b7f56f6700ce9e8f536177b9deec6dbaaea4709454cf791c7175149190fd61ee615e59b896272f7f03008a4ba435d3690806c9798827a5c02f4e9d6cce8de388465a98794b4180e7c4224fda72659aab19aacbce0e0c5cd0a4b86169b15939418adabffd03c9d269cbd16a1ae4350eada6edaebd686c70a8e50059529c19e1b7c4a3e9a1d8dc336c12a948b48525fc58e8aa831b775c9049ef47c9665468f67af5c6a877f7831b9367015059ee1f39f42494f6718cf5fb7f53e6c85e59a7a1c14c6b63bae82bd446d39681e556d7f4ca876b3a1115eb1c901f243b6dfd47f5ea7e956978aac47e6cc0e4aba4d26de8ad159274974f70765ab04b88837322f22f3f8ccb9fc8616fbe6dec1fea6aabd395a9c0efd22d43f57f920daf9b1e7d3cc7822c7d696be96ade2979caba15bef0da98531e0cb92924910c5ff57f918431d15cb8b84c3e862c940675f0992d447aee93188848e61215b8d70e787c0f2166c367592f305d5f625ce2f824927b9c626a365227095e1beffe2da3f00c651e821f9182e736f3e01fb05aa994705f19355c87ae7bf02e1905680960408899e7a05098c9fe82100dddd51602e6b1e341dccfc4c29190a798192972d7101ab6c86141f88ee3ff59481331072e4b0a0085000a7d93f3f46e3308a00a8bdce9dc9952a0cfabb98b564580d5ba1fb14f02592b17d5be74aba69b30871f8949764e01019c760f1ea2a979104243cef01e64f7f26ade55770c1226db30e6b7f0ca5e9d4bec189a2b88e20518b579c94b51c0e45749c7aa64feebba7acefdbe4e2c305736a6118f237b5f84fdb2adc315d3b6c33ccc5d56b4b25cac9953dd6d1f4ca03d97ae0f624565251b3b97e5073e988aadd4b1803bccea1a0f07423d00f805645c5b5c7227939d55ac9d9aaf1813877ef1ef420703d63521ca5e2561da45532a131790ae3130b96bcfb5419c8ed886823173c80ff92e7a3efaf6e80682b67f63108395c35d896423bd4d9195f3c186da8de257ff0927bcd1c33a95effe0dd33776af45bbc4be1611cb5868005e6927f0bd9fdd39682b9f3ffd062b5e4e5bbc9354e8e2d9b4db2afb198ec0c5450c43d5eb09c38c7896efe0e129c286445977e3be9496868ed3df248f9c77a3c0b455f37ab3972b28936526e611c7c8052e0ce28be6167b838684fa2a41682a4a15bda1084c8668dfa606287980af5457646682f04aa62a0d836d8417faf52ec1c4434aed5519491bb07d27042a056b782b7bd7d4ba8f4afd9e54f63188b49edaabe72fb7acbf767f83416d3ba90efa9995fcb1d7c89a01d1ca9e2b9d9bf77f809fc5fcb5ff916991e94040f242d2e1d35f3822c46c720d8a4b283409e55dc1ceff3d7dd3e64329e75b295ea492ca819332f0c21a07097b2d14200b2055bc923af6b4d6c6fd1d2b4337966c2fd781308b8beca6fb6f14a81fe689ac6b568f7f86b60b7a811a34b7dfa6d61a1e4caa2b7bbf2c19e0c41165309e38e3b55f3b09bf22d98fd5f91bd3f68b1c08fa83d003e962863b56cb24544db5d25989284c154221419b7de8bf02486b57c00fc51a1cd462275539c9850cc5e170351a9d63a27971d1830e4229d18dad2cab73dafd73950c8d41aa046bc355ef892da8aef82dcc85667453da46868e23f647dcff6299f349972ed8bfed7690c26b8277f8975664e2fd30bba65b90723e52315ee80bceeb6234f42497bb1936ae03dc7de1b1d62b0fba152fc742dee4ada7981698936ba45ed7619c6a1c90a9d7d2de176a54e2fed25ce0e4f204cd6f3a8d94ff34eeebe9af8a97d7e6baea00ab7006ce259e523cdeb32404ed38073b04e23e70e335f0c6ecfae71d80136d8d4b4ed3f213ad71514b0d4e79f4564b894eab00d5f401287d4d2be7763131847a7051d1c3f399ee1def1375f0b32475725343a37c279c4caf06978a53594110dd581f7820361ea9110458414682963092c241b10db7c89b364a71f4c576d9808f47f2eeacd124d081543ab4b9433dbafe8e90a8077c2024e47b1109bda4a61ded707e89cd60cff05e4aa7394cb4bd01f4abc8d7253682814bc3ffe3c3599a80ca2cfd80a0026e2c9341f9bbcb3de905f33a45bb4341ae88b462434516d640802b73272d25aaeb5bd03d6e72109a23369fbe99b2bce745ede6b0dd7b91705e9139ef77ac2bc0ae58518214383a0286b98219392178f79517ea14b986a05182ce744956107207ea9c5c2d793f83522ee9937bb2cf2e2839a06a6fc813ae065acd91dbc6aebdda4d144519e29293fe6c03def2e4fc6c8dd82eab21bb4e752576c6c3e9e10f9561383ab8fb056dddc870ba7e43067a8083b703ac3b7bdd9895c369c7d543dcc2b3d57e5bd1e25fea5581397eea7b5fc87dd73ae2279a13122f1cfffe93875a075fd71e5d2e600d310a898c79b901c21a2f887d76b9c863129f8550bc909e401eac2eadb17ced4f2e42585620a95a80c375dae577fe2271901b225c29da22145be6bc1d15159733d29504f21d4b61493902e5d3ad7e9868841e3d9097063caffd1aab5f6e8dfd95250a42878169e0371a3b9f9efde9e5215e02ffcc8609ed56c01c2d8a2b55a3283e9ce93b9b10930fd6080f40ccf098674cf2291fa1a58a00ee97ed553578a4129f906c1279fcac25ae1c149c7e7a2f0d445a31113584b481dfa6a915f3189dfaf10745a1f76d554830eeb8834ded30dde668809de0d570451f84ad457719c77b50fd6f8d60c03999e0b99cdeff0443527c5613bc89b066c97fdc2cd4a96c1fc84ca558f706fc0567b05d1b691a819870127c8fea456602610272c7d023df1476bfcc60cbc0d44f6e6d2e93c8c14d1bf1c71f1dd2bb3253b6f62a4ba9c84eb1a7d15a09a899a4d563b778511a67af7c2d5d90ebc2bf8a46d1ce14d05281591a8c5c866559535bf6467b1b7caf6d847ba520526083b1d56561650e3be0aaf44251190f0f0d0624a789754dedb7088c4b66dd7c144d873ae8c510e1673fd52c12d0c0253b38e395de07fa36d6ae61d23fc3035ca708ef3f3913061477856a22647b022dedf89896c117c1b85338783f72334951e8451aba87a4111cd7a6f04bcf8ecfb113d2e27e4eb50bb0232003673c7600c5a4242cef139fc14e0b532bc80a64c51b0e8767f6432236c0582abca2b2f1d443f2048684a1f8af6fe360a8dc0ed0760660bfeb4852fc807df06a58482de1affd3d517496020fab2f2b37fd445f5cddec391440d0b890c4453e42b5eeb87f9a5de41b64c5d38356884a8766d6ecdf800bb1636143e0985d01368081127681c06add07c2ce4f6e0633f35e23d49ffcf08f770312649710839b9e17118afe60aaeb1442ceae9f496669e8bd1e84885e39bc1ba934134bed0bef28902b69e851600945b7a96808b5039181e990154a17825570e2b273490c52e1817977a9f3b21700b10f74a80cb15e795377dc0b252ac9889480c7888cfdafc28b247c719fe579ea08cd93fec1d7debfdffe80ac4505ffa1a717468849c6f6bea9d6b835c37a17c768c9db73315a50a09e832bdb2c1de657e75e6dc6f5a7225d676dfa4119dff5c1d3d6a82ff1d345d1e90d43bf4f8afc0103da3c1984261b1922503d86379753e9e5d63ca9c6bf75ceba231276eac4823a1a87790fc242aba218c2fcfec4ccdbe1de393008ef6f44101c41aeebe372663c5687c280a2252adf1f9970587c03cf8130dd906a4551c24fb8957e12e511d38cf0a14e2cddba0887be829eac0755797bc18ce4e7f2150701bdaa3ebc97e201289bb7a0d103cc7adf54652dbf1fb2c3569e80c74c8a3748105fc272cb4c89dbd99c41cef171abb0209cbb1be8f9faac8452ee32d009abacc60b8b75d0acead3ead7385aec2a879983460b3f3cc59400eeaf9c60a41775bf759aceaf899a13f715845e7cec0227369073c94511a184e0c3db3e246981a1d24c7e62befa4df3cd0a0850c6a4e099bb3daa120e053a899e176bc092acfb1780cbe90a995b25b3b1fed31623d7e68378f676a07ee701fa19334fa83fce3fea5f1b3d3c3f5887e74fe6e48153670ae27ad84fa7ed88cc22f6b1ef393bb4cee3fa63c195a6ffe20d6c3f82ec03b81373c6b352c5bd3c66636f57c823c4aedb29d8024414c258c723f3b8e6657d8d08b812cca6af68fdb92bbab15733d1dd31fc58a2016a5c4fa03fb0653f910d6dd1a87cb28533b3508fa5db1e3612d1e2b319daf372e0b775a6a0328859a2d4e6d89ce5b3263c68009c3cedab1a79e61a66ced75495834b87c444268c86c309f61f41a2484394891a46a7e16fcd5622581b83569f281ccf599d5f045671e666a6036bf2b65cc793f3794fd829052303a64b0363177672228c359dac45163058c5d2742d2dd86771794777548754ee49f3d4651f292ea30ec7cf3e8c5b74db15923991015d2f18de70f79a73169c6a4fc5819e9fdca7b3d7a4720d0d1de141c91d6e946c25556cf4d272b9c2ca25ef7d4f028ac2cc1bdc4fa1d579f87ce31d514c2ae5b3072c483d274d984eda9f6450a4f4bc47b05fa75d9f6a3152027315aeca879d2f6a27a342cc9a2a2109fa73fbea16aea9c25294c9276d84fed450cfed38f34a3daf82d11c22e9554140f32cc16e3fe737fb403c3b9e44f6f3ad417e6c3cceb76e104f184382955a5e87860c455458df5d8f8aa44af9571dc47fb337c83db67a6eed4a9a41b912a6d99ef15ef9672ebd91bb62037e46cf91f68fade2eeeb5fcfdf4b86f6d816df1489bad34bbdf99ddcf7f18d1062e05d8f14cf41f7aaabe22768a123703a96d561e01a693df984a7c719d603a32d8f45de4441e04e208ccb15adc9813ded7e9197a9adc6da6f16147da196aeaf9404a8e6c8395a2705da81c9f3e75aa9b0798e35250299c250e4e4540b4e3ffa1191292eb44160779bfdf10feaaabd081fe975486c458e5abf97aa45e26cce18fc749aa200460a54cc2293647aadaabe70fb01c7b3670700a419025949ef9f7677594b85d0837977640156acf48678afa477a242145a1c8fcea198d1b6a0f296568dff2b8dbb8b79d5151c68f9b7a9b8c5f9ba9275dad04de3dd7563c71ee0d62e3c068745ffa79b42085862c30eafeb806408786e491ed2dc80afe93879d50117063aa16024ff79aa6cb15d19d5affe5b0c5d19d53c48e1185f50e1c49c34d872895ada2bc63e71be3f578384171a4faefc33062e1c5b8afbebef3931f33864e6a6f180e2fbf24cf70bf1f9114ab6c3e360a9766243ae7e24a5a1e9ea130745a4f17007c16ed3d0b2a3aad226a0312c968c0ee2aef7203af3cb5f8388e1c723b8d3f1118672daf87d1e8652c8b2aa59fbdd56cc98200f3eac2ab2d95961e1cbc3b7a7d1f89786d73be0823aa7df818482def88c7cc1041d53f11cd4c6223c7988aed51002f20eacd2e9655fce66a5daa5349500c9d083680a4f282c337bbcd957d47e2f7451c41018d156720f135ddc641c8569dc8a9cf77528e1c9a74bd2796cdadd67b42901ac0951377e5b2210d2f48b2d4322fe200d4834713b17ea5e38bd6f518b401c53a6d0d60d3691dc895843a7419c6960301e49c6b263f9b31c797ba2294a3a7b3968a13bf0bdb085b357244ffaa8c20da84be65b9d1a3ad287662d8b99a14899fcc21f423f739440bb0bfd51e3ac3196a69a3b145eaaa0e5d1a205e6168a5bfa92181e7e7bc8b6fcafb1edc5837f619736bbb8d74976b07161a0206dbc0a28baf0dfd259485c3a02bb5c0e5191514fdd8bf09d1006940bdde987454af348b9b9e5ac70a981f9f560c5e213073c6fefb674d482b037657d79cc284f33fa37f7e3e854da6f4f2acceb8b946e7af85770d8cf797c88d8c710ba552139749a256b5d34d4d2d7dfde90c4db2ea791b6a02b9882a18da502ebb22f2ca33de1bbab158cff5604586915f018d852338ecf4fc6037cb9a54f237cefcec458fee8e35693d7d369bfd6c8b6a328af535d7e174173fb9c0205b56cfb97330b19a9ef51dcdd5bdc1d7f4d3525334ac963c9af3253354bfef26e5e1a76244bb8bec800eeecec7698eb024591c84aa1c0fa83b1936773998e37c241171511bf9f4a419be8e65c3f619d25e04384de8f7977ab98feb8ca915f724fab36ff48e36cde7df3a27528584e6f89de3ecc28f19290113781d41d1d18f6970a1ff5b24490daccf30012accf94de3620c2e90b3bc107fc13196e002b4c7beeb0ef0349af18aeac3a40ddd7c6c83d0729f7ab8109d18f2d999fa0a6e34268c96515046c9d2cb7732ad95282837f826ad3c2ac8e3ea1e4dd7391fcc76baf9c3ee7402448d5921f9654cd000466c302827a274c041a58eae83b0c89f1b05b0e72710b4cfbe78c20c35f87096d54cd53dd16057a48bcdaa0c3d29d4bfd8c1d275563862ad46fdfb9482c16b42a084b4e566539e31a3d71265e2aad2875f526b6422e69d4770bb594006069814a12c7a91f4ce4eb96bf607f8034c1dcddfe63e7c3d24c35f4aea46e1d9fbeacd471a21837efe0d72f9463f95eae3720316b3c1fe4de540b1b50b3a462e5bf9a2a948fcd93a5cc343c22d535d46a28aa78eaa5a9899acac5165e0ffe5ca431f535e1445dcf55cc9836323a324d7e9d9131564753f1a1717fabc4f37631b99a48b409e7d55b09793c145431cc0d22267cef81cee5bb984ebc771cdcd7fa87514734854ef98997f9e8e4fdc6799f399e8c5e2300f70998166217e8a5e3e981f726d373a317821c82509f4fc043d967edc5cf236b156f7ce452abfaf08702e2020f747f23d0cea8abfad05a6745bd6c96f93f073cf10bd23f15fd35c60c65972efa01e2d506e32276813523045fe404567905e25f4d185069402d43efe34d52d3027bd03ac9be5e0e253dc0bede7f6a3cb758b1d0e272078ea6d74d255f69ac64a92e8a10ab63b56aeffc12d77e8f482fa2befff52b78e2f2d2b2d7647eecac8daf8adbbcbae213141723c0b82506568c8ace99a6d1881dad8cfcc1ba5d802f739dcab913d563fc27e3980ec2f73ab67516ad50fcaf25fd273fcc860742cfd6df7c382af54a49b88a93919a1764d0d5784bf14d9f4e70556d2681d66f3a20d4374aeae1e3a8f39b430ee096e6da798714cc7aad2635b387f9ec61808d45f14fe5d386bd34836e40cdf7ff34200e4564043274076ad36e31acf26d3f44b3456ac7d57339dce14323c00bf8974c73f7b509c62b3abb8aa331d0a673995aad271194e5a9fb0f142226a6d4effb0e7f6563541c7a3bcc95267c255fa118c24b2b054e5bcfdb95fa8ab86bfe9d3317d405ab3cd37b79b2256f9c4b94807a0e141007a001936b510a5372bd5bca125e924bbfad8e3336f10253196ac8b4a7e7fdd6cc3e483cd862e0c6c6d594aed8462ac51b83de7dd5a4e840423be98df6b1a114accb3fd74dbf904ed900e0fd216704e6ed754c0d720a220f32c3422c341cf5eae6589645c65be7704db6c7a43c558506129155637c41f2007e1c2c41e3c132131364e863b9824861c81306f6d20fca430c1029d57c00826b66aa7eac954bfe189733220c00af05fed6093cee3e907b9cd2c2af7ddb3aaa818b6b168a16ce4bfcea932749f061c222fe6eb611e7efc04e9eac547ab14e6dfaad3f7c06ef3aedee6022434566e1921206a45b5dd0650dc91ce611203ccf8dd681ad9eb6907a7a19e52c61b4b2808e64e4ed89933d3dde4d7231730d8b840ab49b3f66977f2d1002a753b42db089e56b2823359becd78b1034a25d99198fc3902acf7393ceb0003327f6c18bd034c18cb6e63a1dfcf34ac2fe2d10af83c7330bf1d9398e0ddd692a7825f9c5a4de0805039d8b4176d16c7ce11a067595b86f019efa07d13ec489981b3f486f692ad112ad80779e0e8b341817e4631fb24f7696800a8e9c42eba1a40bccc8cf48d6d8a2d4f059d2a63bacb2f338232c90e5eb52fd4f8b303ca88b7aadc04174d76f6441d603cf44d3edc643c1d38c998b58902c01cdf97ddc86f029ace8adf0404c3dd922d64eba76248b894513952c9590421083b10f9b98a1ea57992b547b41360caeee4deee0fddf0d86ad6d6259000b22c92826444b9537f62b93234133b82800ca517a91dbc6e16473e798fdbfe780495225ee2930a59dc942a8e35da7c3ad410bf053619463d247349cc2037e8fa579c2f93bf857253d4da9e2f4023ca2b14ba9f0aad93d1a7609bda79d9877ac81493b68a571276873976563d1251b0c22c684ae9223dbcecedc3d94de456121428a82912364433951c8eeafbc4574f5a00b81428194cda9707e3744ff79699809037b460dc604d2153e06170764cd5be276c535a6b8942feab4dcebf49f41d533e58b59e1de21f0e528c6f868fd3a220b36e24cbdf1af8a89608da5de874ea3b57d14424712edd570325844a1624a1853ee4ad74aff09ab375d4ae7b8e431c1d5d63d3e7ee51c4d22e73652eea838329fb4bebe3ad92ce7152bc3a7660432483502ff6e392ca0d4772292a988aa002946e4e3a061c9a121ffa27e8032d60f58cdf4e79dace6bd36c10a09b4a298d3b8a76bc414bbf56e88b171a1774e04cfcd6a866ed8cb1ac4a263b66458f530de14171e9cbf85105b892bf7b450938483082d8989aa3582a3909bca5c03639d6045d072087ec38b0bc7b9fa024be7144383d669e2e35915d0fdc01d581346bb0e5d8b47760738f772e08df0bee8b5c8b575c2b4b0b3de1d1f5fd260b54c0959d2fc5c7241444ffe0bdea0fe520d60a7e54b51686f40cf6773e3e4287bb88fc5f0f869632764196c5ffe3b5a3c66cb15d44d945b992a4bb84f617bc6ac90ad040765a59ec312bd0b95ab823a5874c4ba4f9865c883a9cc493d7b4e5e09992dcb998be63007eb1d675cd294da94a8a1504e6668b45dbfd3aef4fb08e9c737f7bc1434afd489f490313ac9c719dbfce1e88d8ab5c99ee542c9ae97ce13023bd041875503cd7c9e6d8784f64bdbdef2da7d682617fef77416ffef3eda866c38c8e91570398ee3168b7f834d2c960f54aaf2f80f6021b7eaf8182303b4ed9bd4eaf5049750e29203a45b7518878e3e0a9d2674b53881a722a246317c4fb472231af1dfa2a945574c60c507db33f6edc54a19219e5d5f60dc2c6fd81726b6735542afaa228988f5bb4a22ecac6279212eb4790f551451b1bc68a43a7f29a08766946bafa5b678782e027ed4d2255f4c93d753fddfea84b1e41f5c444dae8dfd3664a8d708a20ef2b549aeebb4423b80ba61ef617ce10ab702d4799f3c40fd37490f5677ee8784f6dc1dba9e731ec6e4768db926748f962be373e4ceca3f399148ef249b28699e9f4f584d4b66ce4e64ff6f50938a80a2cff992321577b2fa29455cbcbf97bf4effc227c79b023a0b836da9be9425b68d258c800b44e3acd4c8de445f1fadb1f5c7f005c44e6466199f2d67ddd0c660dbe014d8562fe6892dec8d2ca3d16413845c424a015fb3d3f47abb236db04c429fc988c2c220bffe2e442fe50c7be1114dec77b7a7d172346aa9982c93a33d321668027fe11f9dfb5deba429920966f92619d443f722066ace9e3304f9b8340b069e8de27363bd12202836ad9ef1dd99d94918e92a75dbeedd4b7a6c307e6a9c0489788976f330806a7fad424076d2b3c79e3319a2001871a204abda1210af00d3380c863063d576377a562bcaf0978929b3e0c805aa4fdc51365f5ca95ef1a0cef3229c642b6b9501b5765159ef34efbaeedbdfa7a3a9f075b411c8ebc0b82de72515ad02b39a30c23aa68be4530137ba8bff7e341c788092887cc9c1def3a9ef754ff324501c5cd3cbfdd635dca123bcac7093a767e25caab6cee7bf10fefce0a2084e2e040f8aa489698282c906bbde1869e7d605dd5d9bf8691863d007a6c97adcc727179b5ac7c4c23ffb9b3b70e6108cf95c51f2d37e8f65360b40216bbd05467d7edeb9f63a9fc45daeef5f2fbed0a0a7b0dd8b84d8a3d07041b576e20cdd3780fddbc1a3ef9cc8ab5f5c50227e8dd2303a9dd1d24b7b7d96de315100a7762c48f5aab88ee853eab14d6444be1605b91c5a4c50c3a4d6e921a7a51acf631194d60c5a73249a899880f57874d3986468c64e894c73c13df92047a48bc5720cc6be4fb06738679a82a4b6e5d41cdc5dbc3661073281076d73c0b86177b6a0a61160e92dd68efc9900ca45e59c9139a62c08a603aa7cf431caa68ab3acf69efd51619684ec79d07727cef9ecb8e1a093dc2d7e110234f413ff77cae5260135de14d5609c86339dc58e0f1b26043650dea0bd6c7f1501a3e1f224c940eefba7bc42ab4e8ff8c35e6889d141826eabd2d3d6b86e8ac54d462c26a2b04543a63448939a632978940b1c025892d844b0734499e55079fab745a152dc2afc87c7dd175c12c113c0596d7889458101326e1666e63e79b2c0bcd0b5fee7285bdda22d6afe424fc344773ceb5339d046ae2b0dab8116286bd8475af7f22c02099b839c48b8b138dea653f3c57bc0ad6684bcd75163eeb9796ccf3f4fd9414b3cd778b8640a4d4d459350e6908708466cca5bacad3f3c06cb6be8528e27d0a9652019cc1cb947a1e486cb612e320e4d309d60aa6eb6e6521cf8ba9ea67333c8803b9c6561d87e1cbb377b2a0d97bf6469957c3e4d06e64b2420050ecd1856a86a99fc3a34cf106d5963d65207a2d35e2bee30edf947994407ec912d8d80bf8397a9660ac69ea906e6cd4d0a82cd099bcdea5c22cb94ccd2b1173cbc59ea0fbc8719a60314ecd535326f0dc45253d370c5a1e7dce7a2d1457dbf59eba5e4a17545d1c86acaa4805e4aad" ++ }, ++ "ecdsa" : { ++ "addr" : "0xa16c987b93f1b3c51fa8a9833c8932eeaa566ce0", ++ "claim" : "0xf4c9b39d82d4240ebea3a6fc6d3eb294fcef05bcfd4a817656372bb43494b58c39911c689115a8c27dcd3cc6628c885779213612cfba7e4e57b7f5dff61d117001" ++ } ++ }, ++ "2" : { ++ "id" : "0xa5ea2fcff9e3cf29d0c6f5f147b67ff24aec3bd4", ++ "keys" : { ++ "falcon-512" : "0x099202fa37d5e165b88428d963d2a224b8fc82ac0e4b3f6a02376f18218d1aa7d0e910e71586aeeaaddc2a557124d6ab4f9a44b9cad02166413cbeb14b364e13956ea326900eb2900802644167639045d76bbc4e051654cff404dccea94402141ad9fd992cef7a8fa6478b3e6f8912886e9edd1b34c29385b7e964f360e0fb1600787934486f461c95d577d2bc74c4dfeb969b4798565ce0225ad27aac052290a44f844ae233e082c97e4498a31117ac9d02f3605c856e2dde6f611812161f89cb3a54dc936ca1e740a6c659405ed586a9a963b11c89b01746325e39e645c72b0c7e4491b36a17d43ffe38d88c601a5976f5a9636c964a012bfbce5f9b371e7c3b38580d81c6e12b8e8f2aac219f96245d35b4f4afa6c94015b055703b8c4dabaea4ce2577482f5b34fa49e56a912dd58d74580b1f94e1d2056594ea64bcdb696b0baeb33c86b6544761a3ead9ba9888cb1ad51f7027ee52b21e46c5eeaf3f77bc0af7efdc87acbddda7dca00b6acc665002c26447e5b0e0bb5ba261717c68dea7f1576462776954d7249c2fd0886f615ad50d53960ca02d581a4a25517c050ed467c7a820bce6250a9ba2e44fd67fb21bac843bb134c95360dc1c50d54b7280a94440d018181a9d6374bc64d782c84471b47287d8ea748c36cb83cffe053cb89a9e4ae71df497871c2a728ef210903e5b7f39550d0331e15637be7e28b3a2fc05b0a9b0c5a06f9fe81263c3a94403d6c288a561288ebaf788bfe271a578a1a795a85e9d452b61ac204b297090617286922376bf0a8d67dd35fd705b81260b7aad30132b965e39bc3cd64d154c4175951704873992a814814dae5c6bc1e89a83dd91144cd1b88f6ce449900058afdc53bb44bcab63d30cbd6df115a5ee8f5380a127a160e922bebf7b408de82514b2e2550a0931e065565e8dfc389d454823a55b03e5c989b09e3791f656794e8379b7b4b1617aaa9770366d63a657f71ff40c69b1d5da518ef1e2aa42366cfa38e448563f6c2db5e3089bad5520ec26105fc885993630c10db357883f588a5a384cd6de688e1bc3b1200f87ed66ba3d4a4b671b2a500a0436e0955904030d76577aadddb8c1ed21b027f198c072f654c3abb086e7f185980f49d0e109c1a82741809f8afd15ee56a887b392c5b172ba659144a7e99e25ba19792d2a3c0ccb481822839c8c70c65c0943a2994ec9f6085b7ac64ce2b35489a72dd6693d25f2329264e063db26ad4495e3ad00f12df8cf914fd846", ++ "slh-dsa-sha2-128s" : "0x686b5dae4aecd5618b95c3b2a5792888513ba49dd366ac39b7431ef403e04963" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39cf29ab9b80215a9947b975d8c6097e53b39d1483c885ff7527d7fccdd2ca3dafc32bfbc0a19c857fa8be7e52e25064d69c3b7dde6e77eee96ec77011fee440c8bca99a45b432b5468715a0aeff9d61375393b3ca40b9140e1a2bc2a52c3c8a85292f4c9e87d1e0c12fbe4d7236ba7921b8b83bd10ad554179dcebf0791c4b593c8a1bae836883d5094499cf2ba41b00c8c36c77a83466c263a0b01e773f08ec66d46e97caf0f9785943f98e159e353f0d91d5ab526279477a5509129f7a1b8b07ba82a1ccb4acd5be5e40de088f2600e06a8bcf35f54663279f04c74838294048a8f8692904d4f9eaab49635068df74d1f5ed238f6b895acf1364544747bb10ce333a957599594d766ac5d1a3ceecf8a6696cdaa95f824ace18cc551e1f4ec12f345283b366314515849feb5bf81fd203a6c73b5bab7c01b5c1131d442dadcb6bce32d6e13c5a3e77b66eb8f5b2912c0938d89ed9e20a455066d151a973e4509b03f5d66ff7ffb8b362e0c09b969e21173693d9977ba06d48bd3b85657119f9dc3533c91965ed81d1eba72b46cfcff285131f84306fec7b271a02dd22982cb6399a9060d286aa18a3f97666810937f8a5667c94959a4c27299d55e94564dba27ea3d98cb3a9db6197c842eafb237649de3fab72a9d56098b5c1228e70dc062617a8a6b44d46b7899dc1e53a77b700925ed1b438c59458c15e9b91fa2c2164b9661a976720eee2864efc5363d90beea9789a6d3b0628bf4695a853251c7f70ba1ebcea06cb35cb47d72d2340bb9412edc49626d6c78be644c4ab1c539d1469d1cc63f092ccac45f66917d89274af9c84d7f1108b1bd738408e499efa63f1a87c8730400ec19f9a59d241032e9ab78670e85e8da24310b13e89ad521ad4fae3deb9d438dd7eac72b79496c7b65061314ae", ++ "slh-dsa-sha2-128s" : "0xb8f14bb6630512c51d227c12a04ce7b316bfc0d255f5a5d1dec3e1ce5f5cc92927070079430990b4364200dc6d389fde89c78649e21d8fd3a17dd2de7444e77ac3e8c70eda15f2247300fd8e37e1e3c2afcc3e8dd674823106b4297ecedc924ca948a9f80afd7ca1bb85dc0e60e1ccd5d97eb21062b2fabfe94827b4ce5f0e396e5a891fbfc61bb827cd305012515d0a182f163c1a5ee3827aff289ec526cdafd2874c457947e8a6c8332ee7172197cde7388303992be248892e727b559c0d74a2c65d46b6686a48f0b814bbf031d1bde17f55b888e7cbaa7fd6dcf428b13ca43f77d80c3804bd2840e5768c2aa17f6dc773b71f83eb7803fd9e1f1a2e3e158f7e823e9667cebe136d333316fc670442a8c662930a00f72dd2dbda9b19c3dcfdd09c60ba55d9ffb5d5b3384d719d153566bc0b6da89d8dd869fb8c4113258014cd48a67a3591d37f9ba767ad70a554ec98bb59275ce163364915051411db73833a88cab0d3fdb7c491b8580baca2bc44a7bcfc3a51c28ae0a1fc12bb53b2b948c571397a348e664522ea749890d1c7ea7e9561596a3e930bca68377e4d4c0e0301472c8017c1fd5702cd6dd4c3f5881ec4cafb98967a57837c3869720268b61f37836d0c9c5ddac850a835318b17758a6f97df4d4966d516ef100b7e61271c45aeb89242ac7d2b8ee45a08f4081727d54cc08ec0f8af9e16bdf6f6d6797b9f5fcff9686f15efc4e8e34b363d562dba239908a3992b3548566a30cf04c424383b5bea0a5011ac620ee384f6363fca87daa30fa88763146bcfe0a160c071d79dd8de0b11e034fddc032e522b7ee47f318cc6f3f2b6c9b6efa0aaa9b9a9c1243750ea31ac01f087d5f4f5fb97b8296b0953a606c49025f5bedba6773804b15fb3638e72ffffe38ac20486e18eb21059f419b0af9071be12e309a953ac82c0a5a620a7b5c850027b39cdeb5d728522a15c1557e4ebc3f4f09914b3a99e291a814504ff7171c23eb825d2df1bad1ff29144f8a3babcc882258e8a6060272e95c4393fed0ad86698554515e77340ae806746ed859ff9730cd718c767e320ef54fae5e0cb8ba331bdb920229d6047a6db8bad147b75d376c3e72e06fbc6a542f51a312ec831c704099b2eb0f801b68631b464ef484eee077cb7fd9ea951a0307e08dc5fb4ed5a6e62048b010ede39efc5462ccedef2a4c61ffdff63fb3aae19b28ca48593532f051c716835a61f2fbbd5c25883f4a85b48d81658b6d7cc4227f90a81e961c5fd8a388c9efb78da1c9bc50d53a41d2d336232e84e3eb3444389caa3457ef9e3560c25033ed45242d0b4bed69fda4a4f1695830c843e63147b6c2d3f9bc2608b0671e59d827dc1e3876e5fc6075bcdf95223f73dfd11d64399333f7bebdda7f5c2838c072f7baf753a36a1ae8987773fd0ae5acec41d7666c84c1125190f432a4d82ad9b78e22d6536a8135d80a3d1715d17a673033d37104857278a75c2cbcbfe0159343dad8e98e42874e2b001bdb469c9faf79759c4cb3e3f2ccaa16bb29d3e4dc81627441d07469dfb9f545ed83d9c20ce586370be092f3a90b18f30866336c6db9d53e2e0fe1f98c655f1961997e41c25089a518f05270ce06cc115b6c2e9c04f6ba9bf7ce3abfedfada8580ef89f2fea98e8a19c58a0f3ffb89dadb05dbdf05c44b79ad5e1d259d5aa6086cb295341dc40ff800b460a5ac602a687d6feaf66393dd2be22264498509c9d39033aaa22eb248780a3661ecf0a05cb6629ea3d91eb0f68465485e8fa3fad3fc4315a118e4eb2ebc6e9b07284697cacf0257edf67c20b7b0311d3094f4647da567385a508addc9b25a66db1f1544dbced87886946989682b2f2db1363dc635e4cc3c67ad83bd311437d22d8f60a2cb7833c952bab293c9e20ec2b44e1f1f42a797421eecb2e9e9f5e47105b9e7f5d7bd796c360ea39dab45ad701eef0a76b7773c55e7af7909d456c213b0db14f985d0f73652bdf39a6402cee104a168749466e477d8a399469992d65656b607fffbdf73ca1bf4976d3a0c0c64cf5d260d6d3e0198f0b86c451b9ff5840968a2b60a8ec286c81fb55741d7bc9714177c9a77219d3a39dc1d6d7adecb7f8f85af366ed653cd81408b509d0f56b5dccdcd1d982d115754364ca3f14a6f100c54ed8ebfce6b0dc3de4435507acb0c4d974ae3f2453867a70d5ba078a17db34844ea410af4f842dd4a9879a7706b18ddbf94c7b43ba137f7f9b8b3924b4d917f8e0262ad10d083c4dd3b99b70560377ad31784a587cf0ea1f99d6faf0f04a909179f3f93c96aaeae014ea1e74d9d7ccd0eb5ab466a6caf8ed0fae75cba902ae05244e0dde35b8c0bdbb3354ac60875c454ab11f49e47e2d180db319a113a5869bad3ef4580bc7402b0d6bac10a7a4e81403634fd1cd272076074e714b14a6efefc902126df6091330ae387e161789198680b0258c341b6f3ec0b09c7674e9ae8f88699fb7b2f88fdf2461e11ad483ee11fe4e3ddd48ede0ef0a1e54a318ae12473993a8456dbbe8b5ded40232b8d2474a90424281830da7bb36091ebcf591947b04739846d8a600946c2b892e2bf3353b09b08e3a141f33f6ef83d022666d380da43991d3eae4e62dd3f9432678e8be1cd4b9569fa2fa84e95195449716423688aa920e2ba1cd41cd5538907ebdf3ff15df27900ba7ee09f3e9194e1d8cdc0703d6f38b2b887a89b10787986013f688f9a355c6a362f4797576ba022e4f1d1d74e2e31dd98f1b617b99516c944bfa5bb474857fe74a09976cc29c71a7f5b6fa529f3e0c00c33c2f0700064fd507461535a35c0dbc5b69d413fd6ae9af49ccc5d02d7abac88ef02bbd40475595176fa3b68d602469a89afc03359b032fc1f0ae255d623fbf9525bfa36ef98467d5eb2f80cf7c72a04b557e40995471c7adb8701409830b232693bf2fe905ef8b1a32c4b8fe3300bfc5654acfcde685547d5c1b0c213294235b31417da91464619822f3535c93549ab4649a59dc3620e7f4a3327c0e421c5d1a28a2b4c3ba8ab02950631ed54690cee35bc4147aaa8477cae505a1d1757d85251bda5fc91cf65772e1b543bccee1a2cd0c26cd33015533a0e72c815be8634efbb50ceb0ec3c8a3bc6c84638ae371809ab87eec54b934343ee9ed1bebca488d9399a1e347b1647d108652243cf2531a4685c282e0b9e526688a3ae1d10060a78467e6804b705c143d073af664cb72ce657a7d210240011d539cb3144e9411758a211238a872eb4be615d4813b64b8df446d2741db7c9f0af2cc4dc83c0febc41adb5d8413b7ce54ed564e899c0a5a4abcd1cb44c84505915afaaf93751b11bc8e96610216f71cac8d3c9ddb7282f0f864400bdee42c3e5645aea1aa5649485435ffec9e43d43e4341d967c9a89eaaea9cca12e2089f3de222e1a5034baa32372582023b5564909fbb67acfd2a40d5ba40de2d7a31cddac717f5702648c0346e197f99598dc83edda7ad335f9e711a0835c75d4c32e3305e4db9dfafe171181551a8dd5bff89f8a9fb819eca7a171d1be47fbea0e2838a1f1d01f4e68c3d0045da0ed7d3689c17319ef5f5d178e6cf1628402c40d2095c91f7bfe6b837d8f86c5b2585653beb650fc29096f13617ce6d36fd6107ac83c7d7f5a8639e519b161581dd58018ace297bddc3421d358be70179b14bdff66f229a50a329bc30b054a95d0f43e7914a9137055f4dda000357fdb5e2afa3d61b9816c03697168cc022f0418ee5ad7aa71617103fe17e7f47ecf7ef9bf779f157eea74c3caf3821791ab628fe8cba64c12d3226877c48b746d725c46b0ccf5a18f869e6680f1e5ef3c5e7fc2a18915dfd8bc12676ab94ff4401ed22133ac1e1ba0c0352a30156bd80b63eed4a7fe9c948921e1a9843127f1191751312180b75f06e33694853a05a24ee30cae0b02a0be49db16f6f06630ced9b5e57cad548dcff70b1620ffb17e8bf8c247a962d6b2a6fbd4fb3c89e3aa4381e15b92f7245ea700e76ba99678f4b0c998ac90bf3e4b9ba5b52140e15e4b5a38e25462c1b61953cc2068d0b9ebe014db6b8fbdb2fc05751667659f40ba1cafcc2055c364116a058e286f084c2bb73096d46f6736de541b750ad437c27a92ea51baf3478837e99faee73f2a2745918f81547c45f2b7083befc6387a73366c175d2be22314a1fa73f11571395c7fe9df062740c58b56b4982240c63b8a0d5886a3ddbf6ffcbd705d3bf3713a0e1b74497b8c1f34e204ad81b63f27cfa5215d275597599f60d02bbf6cbb229088b56c96d73d09fb3c36fb3f05f4266221984fe8559619da67bb7314ca66405cef4bd3086940c4a7346243776a6fa128cd9b6181d8f584f482c502fce3339f87e4fc5e3593b7a0a64c19fe76c51a29ef776e478ecdd5e093b2aad0ab3cff0baf73f4e09d63e9ccfd4aeaaff147ddf2e9f1e3e6cb3bc9757c57072a1a8076e179e50b0a03dc94de86fbb99f0e92338f26b6ed7c863830f325d3606189b80c8df5a763f422f26436f753168b53bce965c562c2554081cb4eb42d48daf8573206f818ae66d62bafd151e9784d6a9304996b4b82cef081af9b106b42ca4b6b0b2401dc21d8875f9801591234dec266f1f218959af60351178049b487b2784183349e0a7ab361f575fd0237d9f483590a23401f9085b111ac3d740ff4c3eae0b7dca3d149243e3b1fbabdc7431a579652d522bef7023e1c6579d2f6852f1acb9b7f20e3956af8dfbf14617f14981f40b1b2430920be14284dd5f2771f73091adaf9179b8396c6ad2a3579befa1e323177fa2598a3ef80ff5785dc2677f87e9299c6bb16ef2b2080e91f6fcf1b9189e256985e631a05cbfb6427eac995e683f494751f7ae888bb0dfd23aad7fbe942b8100d4daf62b6b8e4d647c818ee7edf0d4d64293edc3b7b6e08a8b9b71a7c38f55ca76593d35770185637fb473da423069de005363ec25235ce816f4df3070ff567f919f47dc4fcf57c168032ef8d7e3fdc5a6a1dace2513fc24f0829e8e4b964d37333febb1eeaa7b81aafe30d16fe64b6ac037ddec2dd9b372c657120df4372504cd14be89d3719c5aa6d545030423fc50e277eaa401e8bb02d70b6614e9768a7e42ba9b35af8f9e3f7dcf175609f7b91a16fdcd65a151c0e85d92dc8a06cddd1ff77d150ccb62c612c90abdad156ced839e837c79b79f456156a28c45f3287cb86a9ca664a13313332a1ed9ef4b3a3df864eda7bd55a6d8705567bd8d1d732f65a324aa6c77f6dd82517d5274343a4e16fc8f41f5a3809e9f2cdec445b88309c9d1de684032a10f8944157a3dc3d4d8d59721f4f9cc0b0e1e7a97b7b066523f7498e0902ac5aa462d9bd096e13c14407bef96b59297391032a4aef8c543cc8b60217ddd5a5d815c4ea1e21625b52e2323b42b4851b0bbc461abad9b71805e8b1b2a16c811be69140d3a6d32d7aa9d5321adb57570fc2e62618cac60a4cce2b011a4c8ddd4dd521b6864c7c4562d8270dbbceec91bf1cd7be926d6b66bf370839bbb22856d1f0c7b2b7119ecea6278793186c50b045d09a1aae7c5bd2ec54df1087cbd1d8094293392605321bd39ffdbbe510f0e8760bd35074c4b0453604ca1f5bee056175ae7943183212ad527e125d2ae113d83c5a4ca1e63e8d89ba07ce8fac8257fe1c603031a1fe2e41bf922d7ffa0a610e0b91eb8c3147262fd228a4ab54fb520b49c91ca268d3954029be8677229af3ed232628e7d3a752e66c2171d1746b7e31d2dc8d1781af454822f36b3ff40f7683fcddc5aec46b13890a6c7c9531f30eeca923f198f4b57112a94e34673c88c70bcf80ee115de27ef5268a753c6f827e71254b5bea2a4f27c8e0e2d0c3f72d051558700196e80abbdf452bd70116c24f635d1850f9466282ae761f1a38a8a0fb5a02a9e1b99df55616f0a7c031fc34f190dfe5cdd4f2442d16ccb49187823fa90f3f87dc0966c4cebbb7472d8184e37522acb165f5d3b508f6a62623def48edddeff361d5ff37fdfddb2b324c4f545bfd5cb98d258edee6ee6170bd41135ddf4c9e358433330a5b590b25fbb276a2284b2df18550270b32b65d9b483fc42e9610537f27715e9f451bccb73e1ce017aaa39b65db4e86c86a50d0379398e57e0c34fa64f73acc0d2b4e953a89ca2f8c01b10135c2af5c234dfaa17ef97941aacb7cce96cd05fb246b76f15275e4d2a8545e52726a48f269d1a558aa12588cc78919a5edf6c0e9e576ed58c92b67d00e4197905d74dbdb3700fbde85d26de20cc652581608ce1d1084b507842a0373fd8830c8d3f68dabe93fb19e3189e486840715f92ae4d916a9ff3424b45ded24780b31fb7f76d506339d9f9a545fe0547c675bde44a3b490bd3b52e3b30842624ab5e8986161be4ef9da785bf537954d3c716da5597a859ef7adb40fd8030611d3ac6581e424ff636aff72f4dcd9f315744a3dae6cd386b2f9945140071a5a49f05e8f979115678eea7d6d884a92e4f14ff94dc102355c3aaa93e02723a92417ff49fe8cdbefee7e6c5e952ad240fa7eab4c7941f6ae8d2a1086e1f2ca73eb8ca5fbe3588ae51bdaf18646ed04bd185a19bdad69394ac15d130297c0fce9d8fce8ea2729dde117facb274f9865ffb4f2c7248102dbd96767483cb7fb764fe667d484a3143db514f08577cad8bcf695b0d953e2a3c8710d8979952929d59c8b8ae62ff678815130e68c85d4714e832733da40b933b7133725a40a12534753eb4877c65fe4c75542f28d6f9e805789995adaaff6fce3929e6027338281c6d0c33aac092fe0eb1797dcd953fc1f815df794249dad7b28407c50371a8c81625f6e7e08ed59a98758a9859c41f7436f937885ad35102b0eea85f3dc4bb9a6260f4e091ed983b1009275d43e4960f9422dddeddd09e9990d545cb67dc3f1061238dffec3ce01376259262b4c32c6173a6f1e239f4502cfb0900bbb7e3b4883ca3c64c8ba91cfd80b2bec6aea25b01124ae11a56ab3e4d448038795ff62e9d5ea5cfdb99c5901a8b8f8731c772690dd964cda343bfd020e920b32910a68b433ddd01d117a833242fd695a54f33fce28b506d931adba499373b0a6182e54323f032f1e7b8bad58dabcffdd1cae831c70e87b2c6fee3494dedaacccfdc93fa23ee1a4273f16adbbbcc21f5d02d8645951b93287732cbca4c61a0d0549345160537501b8c0dfc97128035875e73db7eebec24813d03d11cbcc089929b0f6e2440a26d90cffb6295e8fccf65b4d676abb8ff66709913775e611bc843302a475488c9a9310c0c8885b78d5db5cbb1a919683cfd9bd010cf2f1206ab327122ac87d8e2899cc1ac684e72c91f2d36c7bcc3491b768aac86e92aeb106d22b3e85112a2a871bb8c9d0a0dd15c89d113910f8babf15f27a13b10200ec7078d362773f17286228b0d5a58d6654b0fb4f60c81ee581e507f17a044e6bcad4bb6ddc66bdde7d311810d79ac031086d7b0c334cd3a8a496591aeda23b2c0097cefdb6894b352395dfc79b74a6e4d086656b0cd9c95a48640cc8b3d188189ec0b98c8618b0def4b0175f11369cb2f107e89c4a67a75396cfcbe899334a5d5df5927fef2eb8bd836a27a2834a7ab94813d30fa8431da3178da4ae56caaeeee66cf545537ea260ea6af56d4ba048076ace08ff2a446080a6b688a916a13b43b933e506ad187b1f829a1d54ae261651563874cae19c490004205765b43c3cca4cd8a309fb1bfd7520bcc07794cf7c03d9b1d1ae0cf646534f5a97106925ee96dcb7fc1f74e62c01d382fde19fe027a4b9b7627c08e690abe3ab076f184210acbb4229d483f7471ad551eb614c35e019a8a894b5f92f5371fd6c457f135ae8377c5781a8f3a6dadd2c00697bd8399b6f168dd64b2d2d66d5aebae90fa5f904af9f950f450d8be919ae3f02cb5c0be9687560cfab2d2161db61e978ef46304de248383dc3a99e30573bb66f873ef1e54f523ff8ff79e8c05e7f8143cebd1bdd9d2186ebdbd3b66a0a3dee79475cda2890720ac5bc33f8cd3e817d82bd7c52c34d491e1e9d1d307eec17c0c7679af3626e7b96bbe6ba2550f44de7d1d88b3e4c220b8f185b459f1f882a97248cdfc3d42209ff44806837750b3dd21ac5891254f6c7f6938aef3caca6c55b633770772c2c06734f84612a59aa8cfd4f347267e631658cfc4ff89cea84550bd43699c1d8840655f39e3449ea0d2abba1d81196413302719bc9b39cea85cb7db6ab7f00683842cc480503004c1c819ab80e121d9d21f46f362614a5f2cf80cb2c8d3fda82447cd0155fd7e0ec7589a6df2e6614671071f0f956143c762d51172da46e9f61e588fbf74cb3ceb74bf2ce4ec4ae26a28245f98ae91f09cae77c4660d6dabe7cad33ac506db3000d742f683e08bbd0a7cb9eec72a1a976546ec926b9faba5084e00d66475a514a73f01fbe1e79c0ee0066f4b724e4977f3c1518d28ddc918c573693e9b3fb69b426df0640c5ee42cd5533655f9a82c6843516298d05cd970f34dafa886995545c37b3b939e0dfa3647fb3f330bbd3e69307be3d469a99c24382acdcac76c6cb71decb4b7b11cb5f2e63d112767a7d6467c51f1c0c27900803180337f463e64f507ce245f606f8c1f1df836c7fd02502bd3127424804c69f1d066ec3acd9c4374e857c4607b711f532867cef2c1c8a7d7051a440eb7a8507500d86f11567e2fc812a27e63e5599059af1ee90444497f69add7862b93ea050f100e48df7a578d55b6d6321e70ef7a7625ed89054ab010850912088fdc21551b89397c35ab582aed6c215e00d398a857090e2f7cac21c7b51f34054a45f36157edc603b5d6e76ce20f2dfd2c20158943efd2349560666ca38505cc6af776e0720af2d5f6a7d98f385854700fc0c749dafb597e94d7ac54aedf34840ea778e8873d6f1fd7f53de7c06327d08d34a03b38315efd8eb52683ec1f9abbe2bcf096fa4f379f41e09b8bc67ae4685e68ce456465b38892a238b18358714fee41da0aac8dd729e2c3f17488470648df81040272b2e927e896a4eaf6a11c457938421288ff074da8db60d37c6d022e86952341f2b8d262cba0c5a6efb51925517a8c817a152499ae7ee56d36df86253e6b2d93079c89fc922014b03da3941509e979ff8dede44165ca4cb698924fd12bcb02a35deaad608ff3358d455a49e12e944dbb11ac7e9571476bfa856f3bcf90ca9bac6d57d5c1755104b348d2924ba9b14e9ffb750cafb6edeca6dfb79d73b9839092032035ea700d81f19d035e38bdde754a5098dae1c163f9c473b0681858004ab9d9c2c57282ebd7e57c474b8f7aa091d1048b95e7ef887767f49d2a7f6b410922da142ab8605e735ff6ea9e3f36a29380ec43dd009d98d8c20f4052d81fedfee6cb018b2da59d63b5fc153d5b0948d613415a6b8a2b7338897188582d2930480d897d55bec899723b285dec9abf819ac7e6f39d8c35c484ca13f129fa4b334979bac7715bbf5e52a9926568f359dd3e3e000958b561527bbd52025918ef75228c423da41861396be4f829aa4bb6f94f65e662e6ac91e828d721b741d7333a8e3050f136a463af537ee97af4b42456d65e1e2324f72267c07acb88c91d0cd602ef765f858f69fcd44ddc73dc7c5f8825f3fe04affee769f3ab5486232e35df8fdb75db79721906907ffad83c57a364ab85d93bc03ace8998ede749d88985ae41cef163a3d00f568d43115992362c581745f723a2955ed925cfc7c83c5b5188812fa2dc016dc21844f923b2362afa5ac5f2a6c9355b2eaf724606333f152a01c330ed88f7028e716043330a280c5ee458f2032c8163f5548428ce4c529d487a16ca0e58cbf41dc4dc802cc5ea7fad6a50de0c0f2c2be49c3dd2806911ab1322a30acd4fd8937b8930069fc1a6de86f9ef90f407b2563594adad581b49ad1d19b30ad13efb0ddd8e6f26dc43a36ff8d14d1c99b073f5f1ce8923d3100bb04488b86cd4e89f7b9f5b9cbbb3f86ee03b498ae255e09eeaaba3e4e4d68f1ee4d50f699e460a922e17ea8f0ceef9794e944f128efe835f281a7662f959054aa994afa3982f7a310f46f53d5ffc07884aa91bbdcb3f3779ebdd7f90801e96222f56df39ed9c2bff5d4a11be1da7482835e494b0856ea7c695cc1b53acf3b2e2d1846fff50bf55be65e16548c4fc436f20c50c119ca8eba4cdeda8c7e4d33734a0355586629ca5a7c3591ea4b15428a81b6d91529485004cbbf60e75208579ac354dc705edc7bccb32f23030e733d3f549fbb841329a01f5c5d263ce635a57aa9c69432e5213b155a07c34fe19cee737cb993fdc82ff38eafbeb734f04f58d367e34df15dd6044591983b9b45d4ffd87e2a6b478c7d1e86b4b974991b930370d5eaf5edbb53c3dcda643fb992b5fb0725a8aaf8a9e7c4012311f197179cf1293884e2356fc5b624cd46358d3c7bed1fed6b0305114cd11675aa49c1b9e6569817d34fd60c1105833d78dd00117284cd1722074a60655dfc428072b0d2eb881b93d6c367952a4bd59eb902032cfbf9189bf65f7bff592032c77d61dbf778986b491e297ad0da5b367c8a10c9071b8d509b246393fe04a290b3e2291f04eb750285674ae3e9c7b76a01b679787a4006836dcee956185d3b0ce16c4567fab862d3634b93079305008e2f99ed425489bcf5447699b7a7212fe2196d3999b39191e750fda742c6ffb5509e3806f38edccacbb8bc73c96cd46f0f400c4012f1205813d69a48bbd1f55724c7de917ab56d4188716b96653ebe4fd1b6d5d252f5599f9c53a4683ae60c8c31b86982f32bf73401a328891804daab93a155140fdd41ec87e392c8397c9ecbc48f26acee4e3cc279cfd67d75b5e0b6484274484c18f72c2532b4064cdcc309df796c802c17480428c3b5a5467b38aabce03de2a266c8a22d3b0158beb913d50615a1002fcbaf91edc529b0cd38f35138bd71dcfef1b6b90adb4e68a594de40199724c158db9c85ca78ce3a19378ee90dac98b23e1515324fe18472a4ca93b004295b7abd3c146109da707f5ef37886fe1a8966ff1e96375fd64536eece72ae3433a697492955cb182331ce72e8f1804efee93b1929338f" ++ }, ++ "ecdsa" : { ++ "addr" : "0x5e13d369c8adbd8079272b624343ee1edfa4a560", ++ "claim" : "0x197e55da82eb1daa23a5478ed230c6d0452d3c1920df15e10a8d37a7430a7f2b69eb474bfe0c44a6e4a55db9d5a0e0b74549c044ae22778ce30f47a9fd1eba4100" ++ } ++ } ++ } ++} +diff --git a/consensus/common/src/test/resources/aere/registry-v3/n10-duplicate-id.json b/consensus/common/src/test/resources/aere/registry-v3/n10-duplicate-id.json +new file mode 100644 +index 0000000000..91961390e5 +--- /dev/null ++++ b/consensus/common/src/test/resources/aere/registry-v3/n10-duplicate-id.json +@@ -0,0 +1,62 @@ ++{ ++ "description" : "row 2 carries row 1's id", ++ "chainId" : 28001, ++ "requiredSchemes" : [ "falcon-512", "slh-dsa-sha2-128s" ], ++ "ecdsaRequired" : true, ++ "previous" : null, ++ "expect" : "AERE-PQC-REG3-10", ++ "manifest" : { ++ "formatVersion" : 3, ++ "chainId" : 28001, ++ "bindHeight" : 1000, ++ "count" : 3, ++ "0" : { ++ "id" : "0xaaddb4dde09de5718a906d83be7db3d58e0ae32a", ++ "keys" : { ++ "falcon-512" : "0x09501c96d2f5cf0b28fa00c726e5359c5d36a1fa069971f854b7d914fb2f1295e68b2c6fa91d82f7d287f55ad493c87320bf7ca2a5d5e79d7212e8a540c166b588dc03f73b83be060525b367d9f40f5e77e7798c60b6499767586770722820b3b9e6013cad3eab5fe5de96089a29f34919a2e9ebcb3fa03a3e714593b7a3356d11ffb3441ab40ad94474da662a71aa2419dcd50668cd5d8a9017662cb60998b34ab5b7929c58a94d5e133ebbdadb2b0279543067f76bcc4cb6d7e0a5edb7625467e3ddc92a01206e1b8dce69be31928687d8af4d26633a07e73c2830d5299b878977691cf65700b65b6ea2463e51b6136888c544545e59fe8cf190a7944e215a785b682623c95a79eda28e25e0e1b91b49ac89deaec3b14a3c431d9046a663170111ee541d81b43aa91f29dc147c6fc97739b3a63fad1ca84843d0a65b8d9396f28e9b11f9a41453ab18a2309ae8db03253a09fac8f0cd634c76a5e938a44719660944a95dff056cee43ea99592c3899c2880d7181ee3dd5c04baeb60e1369a69430a66031e3cb10e392622f5246a71761760cf417dcb40ad65f60704fb74ad26f26c3af7513a42f806895e0298c25c049187aa536e0eba21998912e621846c2ca0e323744ba930a29850fdb385c8241382296ba28dd4df05ddb1e61fe525949034b59929a784406de240f8086b4074825f419d5472a28a0b157500be37e9f64897db2b645d3807c48dc143266c99e7cc1638ae278772493a2a4ecf74e526a514bc9119d7129c5a0d115a450ccf4dce05b76d4b6149fdab028006df7ec2209923117abf7578a082128cad42aa66b69eb63acee4456bebeb537ca57bb3d3487f95e4f06c5cb29f292d3b6284e5a162cb83151cd9ae56aebbfda150b7edd5065302ccab70892733a1e096ba0da5f51b42764ad23060eb197d5460425fd9c7a26e7dc3cfd40eac3643539feea72c9ed41569111a7976d2c345ac2183fa2271b424526709fd9aae558a23a5cca29f4e2f31629746a71d904612e95ad9977bbe74fa32e90fac62625838cac49f50e5aed4e8879e2ce2e5651c4f4ba0c96583af9e1612b5ff1a6fac5027c0a308815e592308170b915b4a2de1e8d48e9a5730680ea9db8f3326c430241153b3b218d5347d5c843570cf80ee813871ae10f6b8ce4ab7e4c5197045e85b1cb4977f44c33eb85894b6555b4bd288a50c1b656936841048983c00a01631f10a84522cd613fed0d4beaa4aa4b3e9f30c324108d909e59a80150", ++ "slh-dsa-sha2-128s" : "0x47a0b70170dda85f843607f6c6fcbe6e6acc7c22980c108996a3fe72dc9f61a6" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39c8813cd3b34be58eaab900555a67486034b1923e0b00e435661230cab85f07690a5958a5f5e9c84f033a3dc2039a5296443093fb7fe8d41895fa73be3fb34cefc6cc36750d534e6a3c47307294694729d6cdedb633e8efe8979a9aee486eaa66136e342c578761241192610185feb2d3c196bea0e79222437b6a8e08cb09778d053b29552df96507b1cdaede8e9aa7abc18902f29937f30e7cee6868f349f7ae33738237dcaf86b8e8e01238f3d8ea6fd4090a8161db65dabeb5ded5499e8cc8a5b32607abc291b36a4b34b327d30cdef18c1825232e69a2b09d539ed84dd2a4756efa64f864c563943b3db825824f294c1bbfa2157347b0fb0e7f8a56ec253b39ca9b6cb1ef7d3d7c93a6cb220a7dc50c365905ea5a71575c3aeab25b33523e4fefbaf66137f45c3d96db719a12d2e2d42fbd6cdda58c5a1b958b28c2a8f2cca297871a147dda92a7f008a359027a9288e42ebcd6ea9542f10b66dbbce6e7bb914206122f866d9adc1c89cbf8bbad9bc9517c2ea9018b61d4d2df9abff1dd9f3a0a6faa72a449af9c97e8c4090f3bbd9824298e61599c13c7eb89677c0e845ca2907c728d9296c24e96b6a348dbea7cac62671c9a78a531463614ce321e28ca2f093094ba5f69881e6cd766874622ca769ea556ae757cb7f9546d99f5c90c25e7b8e14f3b7f270861398800b0604ec2a3374659277a23cf6131c63148a41b05b3c06e2a98a268f1b9f0df7969addef17179ca2261d3c229ae3db0c490834564c45f7b8ff6d3bf70784779d75915fb2e2d5bc147bc941b9e249af188f63f39b028547cf080b7674b228e20a600e3b167610f814daf105226f3c1ce5e07834fd33dfe46315546e926fd5be83fd4d47ccd5bb8ae736ac745daabb59c87b9edf9a45c9a1d1617ee84e588f27d12235c59ffd9", ++ "slh-dsa-sha2-128s" : "0x0e8f9bdc22cad3613ed07fba30ed04219b9528f9b657119e2f0886dc71cda4afa7d462fe8bb108feb58d998b370b2f7e162390713d1a17eb7de781a604041cbed13d00effd3b24f2ff87cac74f61e7b7f7aa6a259dc283485179ab4bb966793be018c4bbf4475bf7a69e600a37246908f662813813d4b0f4f83757f4064c5c0713870a0b98b5bb99025dace06100497fda8c73d7385d123afd4953961066e7c8544de3fb620ef5e23174327c2b64089b3fe6df3eb86e83b12634a0c9cc0d7844c894ba6d83afed6becb6f5abcfff397c5cea8064e5e153ea4253abe599dec1614b449329ebb25861b69a9b22228d1a03ba51532ea64ebe7603474a15a2806d3dafa29d57d27c5fa894da673b85b4674ce835fcfbd391d328ef83504101432bbb0c83d7be462b265911aad862118af6f4cea4df0f1dd38969c69428fe438d59d22736fbc7dd5faf6758905b26ec4c99d71e4b8fcc562a694ead91569c9a916df5ad693cb2ad0b7ae4c4f3c5b7322f56612c5449e0339dbd367460c76ab89b6f44942cd33f35eaf33c2ddc0c6af793556d5202fd1fb0f9fa1b7ed45c6ca68d904e476477b71a0bc6ebe248c9b4585da0c7bb186600691269bb4c836667a6d73a455b97127d898b7fae17e1acc6dcc3bac3ecb14da131d5f8adaa64b054e2f569d9bdb164792038e107848882de9bbeff295905c2af68d4c6dcc8cf718c2de872ab6b3d18e00d527166f8ced642281302e2acf4cf4489072a2dc3d55ff8716619cde494be1763dce925438b33ff1b91b35eb511645832720ed92552d4880ae53ff6516cfaeb1d48c923648e502e4038676f7c82e532ea713c6b9348c80ce3c5735f437491d3a8b1765294868c14123af2e9ff61e394216e630c71ff976072d2a1c50cfd8ee1ce27aba5bcf9aaed4a51521bad5e5d5e66abc7a95b215fc8004364aa4df2b8b97b14e3950f521b6327a55fdff9139fb0bd35237b022e3aa128d36c8a60f4621d25d28c59a97418c7dbfc15d900ba626d283632732631ec4a948f66dd9db3bee8c2cf60dfdacbb5ad4c0b2b31f8428868cca035e79c95bcacaba40a9351b2b44cb29753b6b9da0a751bd5af84c9094d5fe91e97501d4f075392290e8516ed5e41b41b00e09793353707fe5c1d942395074637f3ee0a0f105876d6f28a74f9558c5f360e98f047a99af35ccedef8d5cd299365e81e7e91f28a01eb265219e21aa7f7ce56b62f9d2a61560f9fa39f2765f5b50920658100a638aad03482a687905cd27dca02f1deffd1bc49a1be1ea7ff1a505da74fd932937d8f6a8bd75ef456d5f7b71ca5357bc66db6cf14368c4faddf4996363251e6a6113ec64d642c319dd85830d8b4c7ee1437ebfefe01f27709ba0c412c266530f5b6bbb005994774e8935f1d91069f9e7a8cd2bb7ad6527768473affe24709c10294eb588aafca85b379bedf0b142b109e1b186e635b0625c4e59576266acb5f71040c44035fc9480b13932bc657cf332b12da1cd7d5c3977f51d5fa742974cd256e8e3662dc698e0516d615d0a05ea9caf12338d0dcb6151e07f184c9cbd5e59bc40b12ed6372e2d6bd42aa0eb6c3c888f264a8c0d3332631d4919c921cdada6bffbd01ca5445de0779f9723577ebd7e33ab0e5f577843aaa6cb8cb5f0508c33b63913a44d02b76bbb1eabae325581738fbddb5d4fdef8dcb8597bd29c6ecc631839118c44f66ef8dedeca65e58941c30e0423c40bf064b8d19d28dab3787238781d492720236a7ae0695ccc867fbb1cf207ebecc64f84daea66b6745515b9ac9b725061bb9958ed79ad6161318a262528004401633d47a023c645683e36413b8653fa4864fe98c501197c10226b1732337842a1322bb788a00a0de86758139c2d9ea3c5b26bf5d7a4a92cab4cb686c580e3e6cca488136f0da9279073b3dbef9519168ba02588fa29cc60d02273805b425b919a7e2e89c9086609982163e09d5f6eb9c66267ac7be363aadd4617d398d4bdeca37a838d650b0919faf13b78642a058b1bb96b2ed1482cef9bc6e8b2e061e6815936e15a9c754353aaa786ab141e95e5f6c464a41b8bf29e28e764abd638abcfb342b54d08c15ba7e24e6fcb69b844e16cdb5cf4f50db60ff0699f969d8e68511fcc9e16a58e100f80671af6b04ff3edda3a4f05f9183c0c3bb7c1061fee2d3f04e33fe75f1354e6de54f582da914da0138e8565ff45ef52f638cbc33a24bae863fe91e58d7c5da34273438f15e10d4f59db16e505620d97d3fa4862a4097a659925d0e5f4e073103ed29a600b051b83b1f3a21381f4b871c18d262d7e43842c34ed80661438c064aa2fd858a8f3bcb035b5e942baace7b50e4de5a73d5c51fc0843cdc163958a62d333078f4c7d883bd7055a602e04c853f9215c9d7f798403c007fcee124cf6099322629c449ad4ef84b7356110798dd87aa4d98ebb47abc6cc8748dd381d588b77db7f4e7550f6ee1ef4360dac6d6c7037a65297d4a0ea7999a5632b90ad48fba0a916846a216941fbd13d62ab36e1066e24990c19592944078435c52d7717b3556595b645cd2359ad151dbb67e92b14168cac12fb2cc5422582a50bf6e99f116751171c9b78744ef719282f1b84bf95b4092514f4c68fb82a1526e0942ca50e186632cd9b0b8b8d91e84f85e35f30f815601798fcae676da6a2d38eab62f22445099694804a36a34142150fb795afb445e78c241f0b645209037a8871cb5487c975975ac997a540b709e3df6bf208d9d8017f9688b152c9ee2b934f65393de8403244b7437108e6d8c973aa723285555d9eb92509b1747977105cbac7fc33e658fd51cd374d21fc2bf229928948292c1698db7934d0f9be44b137514d0a5fbb659bba83861931e03698a61cd20a449d0358a5fce7f288e18bb3eb62b7ba0ae75feeec634fc90fc45ce45239c5e3179309f0c202cfc53d9f42a617f7aaae586e7161a0723ccebb7e8586cd40e1fa12d3ee89b400dba8073b0080ffaab1182e8243afd93318df15bbf3ce179f21804fbb8882e855ef9e0739ce1536d8ebfe9856aefa9874b4e102e705a40ca4c3ab0ab7df63ba525189b518796590035ca780d348de49f0ba8f28456ca6f3e3cff7e761d961ad98b8cf01e855797c88fe2f811e41e787f3e4becb0ef42ca3b9979356020b447294ef295543e0ef512a247e4d356bfe3deacca8ddc5255e6ad047121eaeafe61d71e7f31395cf78890add4f8c688e4eb065479a63ccb3d0c09028bf60c700fe9d19195c26fcbd4130e6feceb52e192a2aa2343c05b43b276f51a7c55dff7233ea512942291900d93315438a96af08e25ea5b9ce656c54e71ed60d1eeb1665ddaa9e42378c930e21d93484b9a4099b7ddd71d983b4c42c6b1f62907ce84b24321422b08b847f1ea97befaa4ec30a794ad7f340210c800cf185ee2c6c72e844cc5671964e1e1ec58953500f149f0f0f25c34d5592de421c2e31535040020237b907e86d753094dd4532e1ab9d821e7583d4a21e1041fa7ad711f29ee3721a2aec6b0c46866a2de71ee850d8122f722898e533848e2bb851ed24cff9ca83badcfad88a171b4be064007aef4d759d93ae9b67b446f3c6fe504f5b4fe851b8312fec86b46ec3cfcb36e0f682e65e117702b888ab8566c9cc716a3a86106d2323c0f7f20fbc1fcd110bed4492a750befbfcbbe16820077dee281bcdf14509b93137a3998b2fdabc2a375b38857bed12bb8a9c67bcae7934d02d6ff89620fa8946c8aa524fde99c12fec0e25bd79788e2c15fc31fa3f27502cb952b9f9482580cf18ecabd92c55113ec4c4470c4dc06d8ca27a10474594eff708209e8f376b6f17915c2966dbeb0e35ac2f02419692c0d232e133b3907059d3a56ff169e7e61915c8b1067e183337b40bc1136241e862eb3ab3f2c6a72b18511c4107ed063d1e2303d0fe6842fb01c204d1bffad7e90bb44a365e62945a7f631811c9c37ffa5ac39c16b4835798686da5baa8e1eb6aa76b42f6b86863c30669486a175d6b3bc5bc47c5eb05b240bd921007fa39506c6605bfbefc9c8c493973bf3f0767817fd8ce126a301c5b8fba79628a9b3a03cad0c491a5f487dc5e89269e5d3bcdc2998a136a012486c5bce2e6c6dc595aeee2ebd5a36dd06919396184aafb2301d1889b668c4d701c7ca01b95f9508f47d4c411cc0397c244ed4e3e3ad7f97d86b6f8834b13b1b2df0625e6b4eae9e439815e65baf2da767d3b1700fc461fad6297fe4e8ed02bfb65b750c2d2801b7308aba9657df3c3ed7d548687f55e85c22343d1db343bc2dbe222fb76fbb3cf490cee7a99ab3a337c626a148fb303b2f8651651588dd4859fd65c95820ee2af85adf4e8fc2c03828ea7427e7c6b0d4a1b0ccd424df6d1450ee436c01351d8b6bffd4ba072756315968845ab7976813d93d0f0f2be1c00faab3ccafa71cd26c5837e87292870cf768c7837e18ddc3c513820c660870b339fc42c5211d33d892ef22b475cea3be20f5e47206efbfdbeac208e26e97c400edfd41f063aaa6b85a0cf86e23fb11274b405f4f796eb10cb97e70783909ad492ad9207ae7b3d204e59d69c886f91bc82a107d0be3ae85797a7cba747b8e2640ec49384f53c785a84cf8de37dd4048dd4b879c58768bd131ad7226506113c446fbf13d769794f1535d58e9c52e23c1bd55e13c647d304e297d968c759a378f1d594897a026e3271aa6b4daabe174d6a35665b35193379f0ee465df7827299c18e1012ac69913a0a5bb5142e99b051763de3e98d5af8b62133e25b32f4f12b787bef7e21dec42de8e4d99a0adc8f365d8cd3e6a5ff3064ca18965ffdc6b383f7ad08186d735a099bb0ee14506388c1a37f7a766d286d748d404457226b952ca6cb3f317b0f4399006b5b8c6eb89f6b8cfa023cec4d2dedde3e31b9a633c0888989b44ab182a5aba30ba78640f477ef1202f6496fafc2a18e283b2e4e8bc60415a1c9a7fd68f15cc1ea0299e3b26f5755ad9f13481a0563a524c6735942f5069dc1d6a070b3c3698e9c503f67a11efe59413e937062668d3439a5dbef197d24ebdc79944b17c549b0648af9b1349cad83c2a0a9e55fd893cffe2aff4626662ebc5014e70baaf7cdbbdfd3f92fcc5eed863fa8afd87f88873f726a0a2eafe41fa81edd5833f5520cf93b0fbf0660e48eb0258d313bafb87dc9b0d0d9349f22fa2d960238f67457ad644bdc60fb5eafd1c88dd2a74db4da0f723a03df08af6c64883f275395020341d9dd3c7fa049ab2bebb4d8af2bb8dc1340d1a80088c4b2c26bfe7314926ee64bf239306c05dc2ec6e6c5e0ed4f6dbe51f5ee09533f558d29ca6fd27092c20dd892c89c83223752006b23e5abecfdc733aaa59c8549e89e5ab0eae1b44189f58cf9cc18de0c2a2f46a9235fbe42c641a890039cf6aad820f1f844edc24e69bc3bd0c22cfad3804d876edf5491e88cf891c347ed5f24464f2df439bb30742e1f9a4a7eabd9346c6a5f93af22e67becc494cadac82cf9cb693acf44560672cb9227eea2575f90b0e28431684ae12ff2e86fded0be3a099f9ddd32a7285531de8963c9a03355f1d9cef88d7ed9b842d0066ccacdb698d42ff9f8a4f000b9764a9aab1f3146f9f95e6636fdfc9ef91c4d060a54ed7f32167e7ac50590dae3a2904d5d2eeaeff2930bd4cad7166fc17edd2c30e6738157eeb0b441491e5dfdc17a7fbb2bdc6426b2cfb26cf2a7e20013f1b3e33a6d6821928443cc7893f7e4a5268a8b94a6ca6097d25be17b214ea4301e9a723194983bbce286f4363a53afd9e94dda9c761481d9d20c7687a2ff85d42436b9d557d5dc6c5e24ea21d5231487df9fc7986100664edbbc51ad4921c5ec9fbb407ab33ef5c3b3bc81f113e68f38d73f0db0261b656fc344d2d23b93446845d69cee1704834d98737848d405f52f5a7bda3dbdfcd3af3881484579d2d2f3ef976cb35c9cbb76252f2e00019363273489b39943d212ccecc647413c56de69e0087532223cf9b28ce3f77fed30bc3ae6a0842b546e0e1a8b6f6ee1ca0ef1b78c3ed829af817099426f94a447f67229cbca3c07b7a8ce547c5eebcf168248e0a0b9fbeb398e5ed2d0dcacb441f95f9e30c108c725507e459d34c1ec01b67065e5e202d685502d6ff015d46c20bbeef1db38c29df7df585b95d79f5687474e71fff162c0ec0c96c94c507f8a0292a8c32168dacd2fff78b5c7dc145e10fee1b25c478172af8f3ea132fdcad75dc22856deb2576a5ff3e8911842c811d1d57ec203c77b82da3658cbfee18d140ac341d38a30f1af298cf60f2a88d0dfbd3e079ae64a07abb4947cc042925fd5c64bb5d4467589f8c495b0097073c081517bc4504dcd7442bad7e7acafc894fcf34f535979364cf5e908a84e0e141ae47e2ae4dc95462b4f345b12b0629502c7bd65579ec66b2d0a951302ba6da1d1176db6aa0c0ea1fa88195dd2248990fa4aba88490b1da4ea405649203f6ff6f734693f40deabdad59ac62e3296cdcbd74061474dd7b63c46bcfe6ea2b0ddb0f7e77fcff3599892c82425b05ae7aa1a2ac1dfddfc67e11921ff4f2c8f6297881dd5e38ccc4076cac8015c59cdd6023ffbd62b887b33ef8d917446a8941d9563acb66a6226fa4d3f2cc21604c080b3f83e73c093d8f2f7067c392671020c7a7eb6fd0d97af0d63032a3116c408b708d4b2f711c1134b88a91aa359608550f0049af2bb97688afc4352a45c4f6d30d4634e70e82515ff1d5f77851ee857e42b486d5e1f3e0406227dded6c5f47eda30d94f44d978322891dc729eb6ae95d29d22c8a5d649193d5d2aaba782fa16ae488f645a7ed90a566e182f97bc62049724f4cb5fc71f6bc7be57f07a7afb9933f6706cc83483cd7dc4182768cd35bc42f1e9b54d5454d3a17e734475ff58fc66d75419d3d122eff05f7b0548188682f1318ec32c5bbea87c8624cc1e548bf18a6b102e7a43e6bafb579e4e84275fe07d8c63ace449a44cace5d9305ff756cbf40e5a6a20334d5b4a74ab0483e31593f2277e90341fa8036496c2bc6d2b7b10b0b354c86d666d65cacc593d1d7349e71b0360d823453011ee16b6280f5c048111b99b185af99e9d901d4eaffd8a96b1ff394b66208ddc1e7e53420fa965bfc4e630d73ad97b9c5c6ea884c619bc24ac3f46234e7d8d35a12b0cad7220d7a0945cdc64fee9d8852bff872c43f359e7aadf8fa3de3551fb716704af68a18f79d03b3c7d90cf21eb4bbdcbb4004f8ba15ff0bbd2d0918ee78e9bde980e4f3cc13558e6fdb40ca71ad2c10f5e5587784bacc6b925f72da12528216895e0ca4b350d078fdf534fe01bc86b45e0c8e2b35799d268a457f8768ed782dfb56abecfd2b9db00cd10e189c6164f82f5ccab423277e3465ec72d76b696cafc1cfa9a7fe47d142fd6672d9c5b77751b40801af07fc53b1c9da0fe6981ea75e066572f7272baef8fc54bfa7cd71cd0fbc5d6cd717e9aa07808496ad2b4b4005a320c9312c73385afd61193581dbae99df6c25f1b9da17093ccfb108b0a26c5ae4963183533ce2f0ade01bf5e818af613416433578522b1b1e5aa7c791570c8c8b26ded266399116f5789a8233fee128e54ca8ce63fd56c1a146c3006316d200e05715993d1d97907ca83d7fd42ef7e7222eebd74f9c86b6cefc82e614a53976272c8801bdcfd882e34d86b39142ac05088a4c47010a71107bc72a380bb3e5122981d1795256beec20a0fe568002d79a4b1577903fe8682f268eeeed0a97861337ffb6861bf378eba1e0957111c7f9fcfeb55a95238005b40e13ce40efe846ddb86d14c9ad2c46cca74baa364ed08da3a3079fae3a36346ac949e2174c661b8801a051423e95dcab6a0f9c965e8744bdd0e629bd3c1a1241e99951ddde184eb8f354209f24c04fcf10fa8f4e43cb55c922c28be041213ddcfad65c86e1ab9b615f91d5fb11e4cdec5b7e25f8e9811c82c2ed457d012e4967b555f228baf4f1648854c624e0525e36e5f4d1961bfbbc3621d79bd6bea72924d8e0146d0965c239a768b417ea4c33237a60fff2760a9dbfb1113a37b01b598f3e06987d99518bd9f1ec96cd7050863898c8664f793ef29114bbeeb9afab8ed09358d1227d7de2aaac0ab2391cb2013028ca5f4d1de6425ec5feb17d95df358572fa27fcd51d14c363a36bc37c7497a0f964a6c004561f68349f828d30d4633e87bdce6b6d92384c9c1c540c8295ea621e9a8006a8d7c163b988853071e06c78f1b9a0246db052e8484a65cbdced3a587e45d9e2b49a5501590cf768d08b6a043971110e9c9dc96abe855abbb7aee2c38bbb77e5c68d61f01f2376b6122450117240532c7c840e3739395dd6c9e80a432423fc5e3a6dce9dcd58eb418e16d7aa507b4d67dd6fe2af4042a5c7398ba4f87c650926084efbfdc9430a4bc2be544880ecdf7361aea06a25e4f592104b0d74312f2729a4db5876b675bc0fa68f6e41e014b7caaf6f49b8ef704b6243df410dce94ad2c51d328fb90b9cf2f5df645015f489a262f57a5aceba40a56d343403b660928cd7a9d165f4a5bc289c0d28f33dac85c9c2a5c79b5ddd22c744a0388a5daf4bab84d7c77685053c912c9a24b5a0664c6253febbcf552c4ff38bbaf2f7e0c9f06e69a91cff9138c2745b99367e00ff6b6a920b1812e17ba44175c033df0e58d1b5c0b7d146f861b62e812ecbe99d638219e0dba4dd88089005977bcc90634c4dfa95f87370d905d32f613358fba2efcface0b9a414ce33b09e271a647b911843933c5d1008fb0717ab59739eb8eb844a4b34bb1a8f635c5895afa285ddc43720e78dc81eee7db822896bd9bd6ae3e7fe2988ba560d58f02592870647b94aad1dbb0d0cb60e28135ceb72e0a6f4b7893a56eae83f9d9a4c549d53d17c6a00f5d6c266d23e7a1d13e22a5fede3a7082dffb34296f8fe9f3bfe525ee1da81efde3aef9b6de8457a10fd4340809e1dafbfb9e2719c327a3c3a4c51d4d5600e8a01ebd5c537a4cd7c4519e963de06de6c83a9b968b01f79e08b5415c5a9d6a92a633d6ae969b80cbb2cf4d6d1ab2c3b94e7c12df27ea89bff4014d92add41a3e961006a194ae3ea4a6b38c2827f6185ae636f6846b1c8401289696fb10c765fa93e58d068bdcd8c9dc95df572f096d65f5de42bae639d41ce7e1ee0f48ba4faf856c0cdd728956d7e4babd6d9d6389ff41d76c5fbd6380f351b05a37022dbce0a6a47ab7168c82c77a2810c80b1882f825ebf86cb7f6d0f54025fddc9b9120802514c797d1d3968631dae95297a857890ff1dee408909223d012925dc08b7d1119fefca7466392a019d4121ea76c8b4c3bd103a820557e4b2283e262af32f1edbffaa253c47d5873bfd0219b8be86c7e64ada2d87ab6b7f428a7d8fb3ae09b05aee71054355eb83ad76c05d836a9f1a65511b1553927ef1b19ab1576d7185af61be6104de1df218918179c6321846085a83bd1217aa63d0b03996ac1fb4018a8ab54fcf635f7d5a8ade95894f0d407e5d4691920f21094c6f632f1661402a0b3351f168f16a13d3a31ad48e89230cffad272926487f36c7a2584c9387623df6227be8c96088db4a21c93b1c88ee756e960f60e614b30bb6ff757c20f3674a7ae7f6ff6a9115a0a6d444513ccc0be5dcd557430e0ee8db3ed5b3e8c405110500b9bf7f6eb7748de4988a1db94bcb16fe33479f64762c53a1e2965363452063d7bc14386ca7b4d46ebcf08489c64ab413ec0f1ddee8719f5fe978d38438ca3059961ecc8480908cfaf139d88db2facb5e7a88a43a67dcb0f97a17f9bd5b09b8369803ccc7ab6d41238e59e43762965814c10c36fa4b6e61bf2e83c0243f20ee8aab62dfa9827aec06f99c5c565c1bc75291292d3113503a202851c26d1a8bde54bb30f0301e555374b71e278925a2afb29b0209c08ecb89601bf612ce811a493abe2bff78e7fd02ee13c5db6b3edce7c87559410b9be3be95465468e33af224d6508a44728cdffde4cb14fb96a0d2ab9c7f597541f9963775c32ac613af9beab89e0ff7a5e35613751061b0511532b10b3947802901505c8e33bae67ce0e28da760af7e80b730811bdf17abfce39d35def51d73a084119449038c2b0f1c86d844123c6e71f28b7038053e279dd11c088dfa11c547a4ce13b19453e88e5b74962101412490cfb68e21d8952db509cd3a814387b67339fd04ddd2163177589146409934f0eceb10db2d90a9e3f6691eb75e84d5e66bc3228baeadcba200f3d11e0cae090ffbb800f5da7032c35ab572de55beea37258bee6f191addf01739a26efaa612991cb2a3c6d1bbb03de0ee1fcf9b7f6c51e452b21c0819a9aad93162eb2dcc189bf355ecd2c3e504713dab24bfe3ed86a4194611029f7f6216cd469fe1f7d35d56b6c8c2045011e238f9cbc0a19b8914d74329e2472f15d0b7d60511814ad2736d6be168aac01868c2a675549c849fe05e05a76f077130b46896735db5490277b76bba43545de6b8ecb53fd20398eb94dd884951fb48d5690ce4bcd0b836615cd9340ff0cdee1122743accfef343811a71c7d14d1369fa49ce47784a6ff8adc26c151edd4969dba513ade6a9b1f009e57c3d6aa845ddee275169ce58e1f04b564ffb6d0eec75f7172e5e8fb814cd702c9fbea8a783bff637db8667d4b6b48a264135bf60acf335936105abacff0351ba9aeac88e9522cf7ed80069822a7db1a5d8221d9492e02ca893e1f15965fb82a80ee2ec491027bbc8906e71cf931fc21e1c0865ee06a79c023929625b4d232c7b3e2e4a4e5dde28fab675391befe583c95dadae71dbaa43e09d8d65ba36d148aa85d1a2a35dc51719ac0311ea72c1237c78a8b1542c59de3b743087245e54d3111c585b5e5e7642f625c8d44c6d9cff50d8d071f6fa573df937d9e7457302d8b293d8fd94ebd3023c55f8b260c3454e93f58f16d0f451189bf41c9f9b91d3c3918adbf98e4ca5aa0eb6314041521ef880ce18f0ce296721a06b329bb5fbb3024e424b46400e03caf0105877465285fcb41a93844fb90b7fc1924883ace6ca8a37c9905068c633761163affae39d0ba55b67fdc6bcf0908ee3a42af286c" ++ }, ++ "transport" : { ++ "secp256k1Address" : "0xe23c5bba38d809fcb2d3384f210e9a6405beb498" ++ }, ++ "ecdsa" : { ++ "addr" : "0x48fcd978ac4d42ff52dd81fcd17e93190f35e5e0", ++ "claim" : "0x2dee91bd2cbfa906aefa3a8ae6e2de773f55dbd28e77bc329d28215183068585601ab9a7f9ff0c48095407474d502a3af3f059a666e5ed1e27468466d69914e801" ++ } ++ }, ++ "1" : { ++ "id" : "0x690a7fd66157e5b777256ea5214f634f61b3a72d", ++ "keys" : { ++ "falcon-512" : "0x09a6d094d9a3a0865864e9a16b477236f1ca26c888fd0c918db331c87a478519c41085cdac7e6cd0d89190a41a3bd6f4d6300995d591f5e22a7b7147caab1f9c7a85a4ba74d47c7b227326ac17535de039a7e604225d3daac7f75b9544654b73f79f5825825ad6e6c45d13e6d385a644633e1c8806d3a0a551c98f032583c95fb13997e52a6b02192d26b5a47fb22ee52999ec92b75c70774a4ae0481a79113ac72346263e53d5dcde708668d317dd00552d5a40ad47e59a501b10a50bdc52c5c2b2c920fa0e3dc9b8eca54b10aa5ab1168c88287dcf80ecd880a8fdec85b6d63a15b9f453845421a5d9b898e6149b60454828eb9dad6442ec62ad27ed72215014f3d17539085ea3f668b0a9183ab96e9db996801c72a0920b02a249911924f181e8dda515d114beb83b075ce7e7a0902a6971e31420ee4921f5cfc123f29dc7775017aefe99a7e326119cb925f6f603ac3bb137313609498d5a2000c426cb332c82500dcfd80d70a5e2d156844a683b313266af6d60216bd9e9998bda53c0028f387ebd21a5fca6c0607d54b1e95724746d15f25f16e45845926a83c7598646a0a0d3a8f8307c1a401b823f1656ca41e5499684150a954318da076af9131fcc93361d9bf0ae035f617e02cb5e1224a982b3591b24013ff80dbb61160d2ba4ce85a4260c8a3a3218e0ec869796b1b04a82079cfc0ac26da03b04a11950b2a3331ecd0026ea9737bd20e6ea3045b56e3c71278d2a8c72c8014b769da9319e19dbe762b1943e5a4be15aa84d0da831eddbb10bd05f35d55b6211d02a61c5d9247e69cab6c112acb568ea51f345a5bf16f84782e04220e217722da71d634e1a68b796376c8a49a965c592b87d06702fe42dac12da108d24ee42a109e8e4cfd3bed6ada5e3de50301696bab0564292864f1b9f47d5a53cc0c5f9cc3d57051065fd57064d08764892ef4c4a92b475184a4cb4ce1f3a0e6da0402414db5a9db34632b9717586e799b06e870b81a330da7be6a45ddfb000fd337a24a29e164449f96be015818c53aaaf09b9a565d7d9d735b9493885e7cb49a5f1985977cd6824fd62f51d2a1e60289dbaeaea148a44dd8876cb58b8ca2f29f6455f354e4e76aa13290f2979b78b22afa0e65c696c21497e94bf0141ac6298aac70b5ea843848a2264fc057abd3593cb17465e06d41731b7153b71f8f0f7a06d362fbd09845f0815794050460b41ad003c9396a86eaab240555ac8c75f85c0ab972c1a0b94b67b1aee2fa3", ++ "slh-dsa-sha2-128s" : "0x2b2fea4a0edd5dcc2f653eb2dd000aecd87deffbce8818aae72d7862b506bac7" ++ }, ++ "pop" : { ++ "falcon-512" : "0x3968f2999d69a9c28ae792a90a47363e689bd4b349e75c5f837181fc7b16d3d04489bbc32252d750d750417770630c5b65b88cef918ad23e33892a58458e9e63ea591596d3b898f65e1a5be3d36650c3d9834e1ec725426960d337b8f25878525ee3c3798b5afc9add5bec82c8e139c59738aba9ed5f42d11c886472e81cedfdb5b910eb73e884e0d4cc218b87cd9bcc0bc107af586c65b3949460a25892d9607efa341f232e478f3c9fc2d05f324ee6eb7bcddb72af371d47c36856f488872249ffdd322d3de7d12b62b1ec595187b5b363e36cc714b765f0ad5616488300f6e56811e88e359365d5698ab123b917bb32f56566958b154f6fe052b894ccc1fcd99d65d19e8117a8ca4887e01f36f181461a433fb9bbc1790d8b14e34a097b149f0c5c075ecae3501944935f3caa76f0b9370ebe6b90390b4d059f9029ee4af98dad33b9050877d49c3d4f2beaa4b5861a21af95b8c52f9ab4b0eb115357f5b1d25fb66a36b9baaa4d6cc5a4f5fb5462432bd82734d7393cd22c68f52493eb3434c3b88fa255baae5c46c650cae17ebe59827cd6645c6d377b3cdee3aa6a758ad3a96d103bf6ab8ae03b72b53f3aebdda359288c32ff5461a158962924a97a24af29f6c976762e8de9363485ada49c445566e71ac75379aaf7bf190a81c671115e842b5280a05bfb2ef3724bb74487068d5b5ab2d089ebea7ffb4381a7e96233f0915f295d3b71db872393bb990b9c74717bc3d72f6271bc248e54828a1e090f6da56de3643b083e9695db7d0a32bb42355e245e5cc2ed57354d82220b449e10cca1cbf6fbe796d141591d6f71e4eb6770a3c7dfcee509c3c28f2f1988eeca61833b6681e6766790c2a6f043b4f67e145b908ba7f03361cd9d435d054e11edd9667e4f9d12c2d74f2832b619", ++ "slh-dsa-sha2-128s" : "0x39254afc16b1dd8d4fbfff766819460253653dfc6a8e29abed55ffe91325afd578ebfa2dbe74d46b48b381e69d269b5bbe24ca1b85767bd71c744065fa47c646e3603b44261731b50f2d20a7a327e98b84c5ece73697739c8057f99d6ecbc54cf891649fa78b7bcd824972f3b27820ffda3629f481b1193b922cefc907bde3ab1c78b5ac97ff26986f3a553556d0b158e936450b4f41bf006c90a9758e0efb327f67408a7b803ede993522cd9042db4a672c89d4765a0fff8c6e8bf6882a8de432229dee08ae13def90f9fd0a40c99f3d93873a41d74871aaf407b0927a817b476eb93c645254bbc77d131e0bd35a2541248172993b1064d5b26b921396c8c1664178051810961039b15790862415338806329a45a266aece5904312afb1cfbeac1e816fb96256fc6e2b059c25af1966b0bf261bfb72afd8652feaedd6e0e4bf829a75188708ac9c623d4d6699281913bb563b96818f9307b66f7cf4aa9591e30c65a0b0885c22b5d17ff610f40bf2e0a9a32173b2fa7d66c14784402885d84f33fc75afd8f743cd10f5ad6dcce5b33a8f0c0365de2ce1b69aa86df2482a2c2d3746c6f0ee4e6fdbeef5738d809f6b0ef3cc703b0d29e93e198b68d62a5be657e69c33459fe4b163a5ecd72a90f1e53fc00bc8c698af7ae3cc5b07e36cb74088066a54138d6df4ef6e159ce5924b6903346a5fe115272cc951e8713d4b6f96f78d67a542c3bb402e69bdb3c2b06e189186c227927b2aba52b29c14e837b37798321fd000ed3bc0e386ad6e5d3a48494f57109322f0a87f7dd752d862dbf772498154804b09eca84c305595cc1e6654b1b2e94d5b88feda176aa144d3895a249754bb2ea99b2efb4f61b828f265638866a49dd3437c70016347d5aae64c79957ed394a85cfe06b10b98b6e83801728645529537a1102bb04ada4226688594cc28aefb24fbb0d1a60c7b826dadd23f301517e862c67fd88d0f6a5ac08e7f966ae375b468e57f01521b43fc24c761838c174ac106c4e1f435b7ead5e79aa1b303222f6b45c5515d497d8e7b05901bee96945652d304ad9ebae2153321885f19e7ad08c9da73ccc22a66c26c4cdc9360c36e307310714ac44c80887f42a2575305ef649378d76d297dc6faa904377b2037618f23b8be496fbc680645dfb80a76bfc060c6b2aee4ac5537e79b7dc7deeca0ca38041dc877b875cab1a297190269c987dcc46ff34e5bc154e2572695e463542be79d61fd5e96a4be2b07f5beb71b882f99de317116fd0b36131a88ff9707eb25594fec74cf76c2859ba6ba2b968d41479adf8857f4b0f4a26f49f0f04fbae0e2f3c2ab6aefdf01855a7a5a4b8bf516f4551a393a33d3920ca3ec403b4d37c2106d777e3d5dfa768614513885d857ce95b9bc3b992808e7ad71575e5e91b8107c5802043b221c74d73c7bbfa7a191945bbc5ed69e20016b16e2e2987818cfa80695e58950b0c1bbb8c474f861d1447161744c75d99dc8240338c43a5c19a8a9f46d80f6b4b6c1cb57f5a3350bfc35a0522f89e3470ccd71a458968c629c93336af6b5b091f569d1fc9492eb6b976376b8ff19ad9318f5cb1361954a0471419b4207dd9dace8c0545e74dfbb19ce3fdb5d456a1c1bff7383c6fd96dde3a92daf0ff5a315714c74711e3c05e0c59ba525c64ebd17fa20f8e143c5931b3c77da193415e6506c2db27e0e773a6a5b5d47ad95760b8d471d06d5dfe000a2d47e6e4e6abe7219750f1f7892f4e09fe88d13c2e3b53dc904ad58eaed856a4abb0c10830b96bfc1b5764f9e4b34b0072be314608fdea8c5005d40ef99806d4d3edb72e73541fb828d4b2adc38855e09e974293de25da6907f5ea97810eff1be37f88ea879e545bb5a70d2187edec81bd57a95c0314df4ad08a864156579d50826d0cfa511d335ff722e246151a7afce94126232f6bac89b13c142d29e7521479866e35b17c15f16ee89d798ee8bfac5868e505031586b81bfadef4aafc2ecdbde649f63e07eb6026d09910d9d3613a9871b5d1523cf5958124f96b5304d5225b4bbb03aeeef87753d0b6ab51a287df1e9031f56f755d3fe5a20f79b7f0f467fa97eac5bc09a1adc6ec285c8f80ec5c184b8b5eae326300a5bce0b1d757c8e4f27ca2822e73745009291f0d9032051e15b567511908f3ec68840cb6ec6018a9a0e30f2e34759743ef0bc9e12c9b32f29f4b70a998cb8893af2dcf17e0eb4f48e7ba367f68aea5516e7248c8be1d1f896d7e8446fadd9603012dc13126878300f0868bc512221154a5104882621f831e60b49d04fa8a701256b3a413b9db4abc5af10a3f8f4c26cd0b3c2f55a58c9380143d835b759bac7fef824515a18d79b6dbd361541047c79653ab4af5473b7b7e67a6755add78d5c14c0a9edc6c7dd42c3d0359d9f2f6961f8930458a34c4f12478ae45c20969c4c18654d31a7ae73902757b3b8a4eedfd16d6c0d22548d7b8ba77aeb4c1e3f3766b6ea802ee9bd92c5f98d00be80c15e7e3a82eb0d100436c398781607dacbefa98c87b3558f363b3ecb1ff313655838f864c1b2e0f6d6369bae4eb8cef98f564108ab2f763e590a9e9201f4e28ef1971438c30f4376c55cfce9b9910f448e31d06c2e456eb798476d56a890660e45616840377ea0574d1c066ae2fcc46f41cfbb511e5efc4b5c60e00e4846e157bbee5fe3bcd77408e3bf721bf871c05971a70cf7a13c782bb4afbdb1ef800a414260243fd828b67f49007eaf60b3e32f4e2b8186291075a0b1c0a528abb9da7974b3b1e8b20d337161ce234db66ce82a88ae1dc880933343961267cb4932b36aacc5f136cb474bbdb5e4c4be4cd74868775d80317bfba00ca4e58a39d04e63bb797de366c45efe2e356672f567ed1f7b2741df7543d6faa7227601eb7cff367d5a1ff320ca71fa2a1a42866239cc3fa5eba400ee4060266a05b8fe1e729908b95ba6aff8fd76b5e7df547df62cb89f0605c1207c869d7214e4e6972ea6e47b18235855d6f28265a737b4f64f0d215943f13d219292036c1cfc46bc61679f034919e4fea80d882a5121cb3096a50f2112eab265ebf75b607b93e14ceda4e08152221bd368cd1503ce375188d23514dd0936bf980d4282eaa6fe8f38f5eb00c34e3557ae363538a2c15b560b9f9322d1f17446e8f3fd317126986afc2c5e9fbb96f8ca7148f53cd75a4b845a28034c8679baf1f5406564b6e4b8fa8e681b5a9d208f3a1b28e84d6d52d4baa152524908d50d71d9c0d11bb5665c8a6bad669dbf303027bd0d534434f9e76f2c300326e25d00bd8d3bb1debe1c3984961c0ea8dc547e8cb83a8f3b044b673f4a08882d103d6eb143a9645a9a00fab6f1167a2c09015d6ff2dbe4aa4025f604a63eb32330f832162b6dd9364f4ad6afbd86c8d26f56d7d9028dbb3051c85a0c86ec0d7961fd6008f87dbe8347fd5ed1dc4c27285364f63650f161321daa83ad41fbc3412bff800c062a78cc5caea330cd58e63ea9a9d6de2ee069732799f52f49d513c658a44a2122b8427a405d706f740600f855130a0ea720f76b3111dafddf0e2ebbd13f60640379993889089ce508b1343f485457cb8e0c09760d3199b4ea940d584417259e41f2c66853ae4235b6f010cceca3859952b3daaab55da14adff0e421e862f138872c2577637b3e12b00384cd32fb3b9c97b0d59e51f2488e379065d79f5a834b076ab5b35fe4c47f2c4c4f43e622527abb8f682fe9f262d2883fce5c9f16b7566c4e078b67611abf72cb8a0263ba12a6c23b1a04458c759f2bdf6dbcc460bc5df48146468073b61aa5ab4a9c5f6c006f54f1bfdd85373f33af29d68580eba4cb6dd88054c81b3bb7f2be8186e380bee0b32a1b84ef6319798079828080361bcc27473a9634c23652ed6b2b2c8f8d5a6721551c780870f1787726b121263e74c9464a76282dca27249b4532e49455a7485e2cda4ccca823f62d3b2869602197a6f1ecfc9d92ab6e231996e603e81e3dc648aebdfb900a3d929502ff0bbb3dff813660c9d5a417d857c19754ee04e50f1241831517fc2d2a71c5e238a944992cc50b7106aabb5482fc7e0a2e6b5b11bb6845f34ede98a18d5f07759e61603de502b5eaabe59a4d2c69f4b0f8e73a9bc85b8950a54bd91bcd0366dffaa0df736dbbbc35d6accb5ab8b22a870374521f2035c1878718d7d3b025838da75d8bfa3ff36b2a10a3cdef1b150abf3b6be95a5c096a921a3eced20f509dac4ba43f2f515af2b65d3b2ebd0da2d7a58500157a666b387b1814d0a3e84f64d0fc44507b0b6792c0c6bd90ab62e0f75b66d50b6f842cfdbecf1fd043d642c5d5b5fe5cb68af62e6e23cc6f0f9b1cf3cbd0233ce48a996296b6609be1c9e7a027cf76615dd11208f1fde119099352cc17e1c9a22f4b71c3e628d72b620f3cb4bd40e4294ff8dfe19480b5b758b874a737e6092254638a222c83aac52fe0f66670454c313adb0dba2b4e95741d27104bbff159e999e23103c00470a7feee6f4a35f764ec81a8ef520cf1e8623fed3c06b63c022e40e7638db269b8add119fec50456b33224c14486f705e5b3339c6f38aa4ba6dec8b098c27447185ca50cd70772e5389ba703a4a9f8649946671a238e1f005aba0b3a18c8ceda9daf4cede6782d27931c638af3f6083b2bf10ff0a632ebd4dd528da3aa2b7a8bddff2901d902b26d518a058921eb0178ef08e24f7075f77ea0c0d0e72f29847ac7826230c0ddb5e7fc8552ff92c007e9141f51384a12e218da4fbfa9a7a4a1bf266aa975949e120db1b6755ff04adb07c66ba9619b40396072e7cc01dc3dd56f7a2f928a82c8906be416f6d5c41354881f9a6c66a927292f8cc2887aee86e90da32fa3bd9d72bc26dfd334f943305fbe4b645df83fb72c565f61860a480dc0f2f3360368ec3715c2c4a312bd2653051c8f29fc14e0c3d1f515e04b75ec02cac2aad8d411306969d9a8da08c3477eb6201bd54c6ee643d87a89c78a5c8ad48590b7a499cc44ccb812866a4c48ec2da5f1e0aac741464b26988459f3724ea4cf103c27e4a43e5a5fbbf94908878894f8b62995aebc20e632d924c82d9669f64b2093cfe023cdd1542c8f9d19e5e7ad6ed7920ba6834cb0cb91bce48fa94be47c1833c6ada4090509ba38defab7d56dde8168bac8021fb5a2aead00809f1881d53d26fa9cbc824488e16062fd9f68726c837234a82d518e3d10c9931295d20d9affa5fd18c0b2dda299cf1d6fe0c6e6959440af9b397f3441bb9881ba1d2df295d12686ef6b0bfe52fb2bef06620721374328551040d2fa434b161648b058b74df2a7ccacd7609b93421f44a136079c79a3e63bd3b4f79717f3c121ceec2c3918464f5619b1a2e83a7709fdf6d1004b0ee51c73e740b20e329847304a82802e02170db386e360dc6027aa7ba1ee35d7eeddb41ffde093073d92899d568bedee914627c8c48427376e7b5d5ebdab30e58147dac5638090e9c71921431f025f1d4e3ba3c68437555357c651336b326c9c519544363d5f4faa91914195314cc873ef97068d928a6b4e5c6ad70ea7a7b09b3108fd5696aaab800eafe463ee52a3f29e1bbe8a968e84b762484a13714ee260759b4492b749c46ab6603c13ece34e301c13bea57d9de706edc839f55b432b9299d2d6643817cd9d32d0d9ddbdbb23acef51992b62db024365ac2db4c432c531cc1ad18c807cf1ee39dcd842aa9a09b232cfd09bfce33277a8ed09953ab3b5d24e5a8a02fb4a02ceed705185880ecc47cb245665cf640ded4015b4afda053a5d1dff77e390c8105961cb3a954c28ddbb9efd759080dea99e94e69b03b928c8667fa4797dbb3cc6ed093bed107c817780f60729036f13346f05491fb837ef1ffc61be7b61d0b7f8dabfd49ec24cfcee088de38daaae6b4e740ab4faf16eaebf89962331a99f17ca5955b15dd1fa493b91e7cd218aebbfaa7d348b1ceea26951209137448caa93fa466ca32eda497a5b9a4fdbd23a10d9742e74c511a1648d00bca3ca23abcd4f18b7cdeb362e020c73888b76b83e70d26ee358c06933f77d1221a8ff0647200e451e971fe45c23aff60a88baf46f59a0bf94e99ab9337b0336ffacf8e79db92067d2b744134cefac1241dfda288f5c6ab293df7469ae0926c166e999ac99c8871e571eab03f82de73e9de2d8f4deea3724f795480cd47e304f27f2567cd94cbed52e06f1f1cf7af2feaeba8b95927eff950bfc26aa0cc3e46ec7bd5d4aa43374500f8cad4f153cb586620b9a0deeec2cb12ba48bbc8655c7fa70ccf94aa6891b5cc8a3c98b482d906d72e9d425301d0cc6fb4ec9c4a5bcdfdd74fdcef68f05fdb78f2a1c5ae32c28c43ee900738f31ac1fd337ce95966b3f557a727e0c3ada6c6aa61219d92fd5cf68fcd9b444f6b4fb6178b9c74238d2575f442a298127f282b5ad416cf6a365a214048489139918f93ec07f2cd864f5482c418c7336ca4590a7da8a20d33ffb7be19934c80b64f4b982a55b129f4896685534b83251d54e46a2971c0bf49ded9b13a77ade3de9a61f2204a46ed9cd7bc444801381994c8ca5a66abd70936f8d11e2a2fed78fe9fe8889dfcb979c9a3f11f2c2c1aa371d1e98c4fbdaa95d58c6b22410c0d3d3460077dce654a1decfc829f117bc407d06ad9ee6aa06bf818ea2f25312b1cbbb5de527ce9b5c5ddcb0df21e3442ffd149b24af5e59eb4d7e18f68b02b26e57fdf23e7af4fde3e672990295c37186ca67b2abdff6b46e1ff106f041279b61560ea2eae64649c65be22f9070c3239b0cf7929b0778c43dae5391d8d3b8c335ceac672376588a34d3b9c61833578e8d5a9e6e9f72748d860d7af98f7616431d1ae1ca20db3db6ec99d59fa98c25a1cf478e1b4a643c2fc9d3e482d56bedb1b7a1fc9c3e788d9de281c7356b82e3c9e1c9414a0d14cd07fea5364b6a22dcb3b69b6f447343822098548e3ca7e88a83187db145bda17f7c48cb00e6ce36d53e2d1e4c169569ee3fa03620a7131bd5c033062bb82cedd0d0ebc1025937b2d85a3cbcf6ef4458a57525a66244be3a62b582bf2b88549431cdce09f6407e1bee83d3fbe205f585cc7cf9c1eaba047a01f51e13bbe0715a9112c451f1daf6074a1af051d8b98863b6fd03238ebe295995d60e7a26d2f95a2b4b0d617af299133bf357518b84e942bc36a88b4030d91a7067e7a2ed7bbf4e9abda8c6887ecdfebda04dedabb9ea833123507835e0357ca1513b471da73102605ed03297b5e3eb7d3bd01c670f992a7f19962b706e8d0ae0f073638d633b34a1229b6979b8e90f2a536cb6024c644e1f7ef211451dc509e061b294c28be188c96246614a1fbf52db8d9a99f7100c878c1b9da98ee9e9eddf7fcb386061ddf46807c60b24d665f0fe7fde205f91021bfb87c8f4c89b5da254d185bda9cc2f48303b483ecbf934575aa45d0d58cea64662f0fda4d97790bbcfa237984cfb45a9cd611b533dc0ea997d191d14d307c68db318aee8f99544fd48fb86f041fe249a14263e6657a5ee732f7c5c9c97a8924bfdddfd75dc67da65042e711a3cc144f46d10a1a9fdac1b1b321eacd235299a1fab390df24acb739d61bd60c6907b9a3827958198e6e2b5a1c90cb9b44cf8db9b6e45f710d7a39c230ec9cd855af797555fb1d73492e29d17da0b6dac59c2ccde0715565efa1f62898c9b26438c60fc3b9f859bbd33a8e05e1d3d5a762bf19bc7c32cf7d4c6bce26fec6e5c8c537608a1c2aea2e1e5cca5bdbb45a8ed048514ef3d298e7dfb9c5408d941ded6220a44c184dc90c922a3ae31c9248c5f31627389770a59f9431fd0139c5ac0f08f69151a75a5a6a0355b7beab6be9829146ada371aa5791c861dc77598f09448af20deca73cf98a399f35c36f1167ba426c6cf4b8b9b8a22b961bca83e45bade098e20782a9f70bd54fb8eb6eda3acd3a5bbb553438cfe37e1f7fabf15729d6bd562cfe379d586181b71b3d3c4b360852003c4363a8d473198130642972eb3434c3a5ca9b497ec7000e821c3419aae75866496bb1b0a9ac6cf92f799071e06809f1f3f904cd18f32629e2093664755803f62f45942f5a358cb1e925a8694998cb14cfc52733c356cfd739c3976712ca7b007e08841639da14e429c102a8fba3191cd36c1c56eb06bf69afe3f2afc4ebf137c617faacda6baf5cfdcc6462ad02f63e8a5375288d0de5700d0f9f4ca82a65bfdc405d3f96fc663658f0aad91305b86ead3b21bd6561a40db0f2c5b0937ba5e1ecbe91e9c50b1dd6bd83a8145b033a7bb6a4ad4896e0ab160e8a52d39d2756b1c8d8570f7081ba217fd8803954290788882befde24b4971723b0ecbeea14d23c92eb6a0d7022a84aca072729d7ab1a88927a25f19a2086f846a44a2726ea26cf1b69c58243e219c756d06c361e1e161bdff0eca10bd30d23782b3374ed421f50cb66c9ee063ca622fa78c8cede932848f0f8f91bd7a0eaa324377c109808bd66ff463a72389c4b49f2e349be70d07fcb56b28549fca65ad853d70df66b587390febdf6b1881cce6c1ca9e9fdbc9f1ad68ccaff97234325d3c972b57ae5723fd73f975ba640f90e717e9284c111b76367c6797399452d37df6b8b8d22ed5e7dc1481a415fadc06673ce4eb6435d31acb6af68775436629a57db7a0aa192310e8427468e8e310bd3426b7ffab00110324c0c7e04ac6649b6f167fa8b928b3fe12ac162db3f2bc355295650fa2d976c64df69a8017034683bb4bd4baacf1cd8502dff20430d48c907107acfc4e29c584cb497b7a471fbde90aabab25290d853b8ebd2c0d49c2c201eca42a68a15879cf391671946319427b237472cd35431128ea7ab6d545617321592c07b09fff93e71596da30689b3c15368a1c3a57890e0ee5752bb4356290024fd1bd2ebfa19f7f3ca57c36d296ae61ec5581ceb77618dde2821460553ba0dd6dd68026b911f4af1be3986198966f90ab757aca2f5143f1937d09c3a08047b797781d1639db4030f9e59f8c5b71a71787cc84ade5a385ebceb1946177a056179aefb49e1f69ed0aa67901b2d6b2152b6c1fd1db67f358093180fcb8f96483fd35a87fa14825d3849dbf479be493bb2d1c639674bd195b5ea3caf49c2b78eb0e953dbf8fb909910c87efc6f9b6592c020333e00f83bea4bdebef4e107798f9a8e89fa5d063d69f88f31a53548ba2406407251f18c3d1ca6e392fb81a46107191e6d906b487469d0002afdb0f32c39873872a49eee649250d4d5d3a7687fde2952291c8ba78fd9b962060df12d212033303691b05eef0ae0e7f31b7e395576708d211d70281e9501618673afac20a93e82f060135e51b29132a0c9244551814bdf399b746651279ed135d162e366f39d40e3a49e907f72bf7c66fcb4ba75b1f447fbc3ae3f390ab4c10963d755ee188a9b0129416161995adcab12177976208e1c93ef48d3ef55ad22bbd97781dc7035c9f5fe25f47b703b1ed50dba311d24154ab05dd88ccbb5a8cd96d4665829c4dca5d5b22affbfd7e842ffe5e87bf4326f957392229bbc893b1fde9e4b2191a3345490d418e9298179661104f70bf6cf9a0094f9d37be98b82d98497573512d8f6fb4b0b0aa334a9120a5afef20e0379197ac7ec78da3688d2c9b590e40fcf866acbd1d857546522788d1f3ae73f330aad045c5bfd59b8a399ae626fd67d9797b32d6a279d42eec3ec8a2888258728f7c329c4efd0f71b730e57f9bd87204d40ac1ea6032a4b8ee3a338aad58c2f3c9795819af4cb652dedd475e5662d9c0cd23e72a8f4e86f1a63e5683c814a99a6595b779e5d715ac91ba62c1ae4ca1651581506ba80c2ee0d3f97b979758cfe93f373873f4775c882fb3b5815b9274595bf50488b935c82e0fb4ae4d078d30bf0843c89e484bf5a24d5de602649e336fb2b79da6131f96ef1b5f82cbd668f4599fc9a92b4e9ffe3468e39e4c8bd90531952327da74a522e479c66b7b1554c9a72a2e6db58fcd45588c9ff4f48be5ddc994913833b668c275174b9d862dbe8fd01535ff2bcff6ea030842ed3a4d105ba07feb0098e39f61a4cbc06bfa153c598c10c5de57caa413752878c7599e5db8482b6f275db2185c505bc0c9670fa0afe37031eab994120acb935bf9dbe6cee6ba336dce1b44732c4267ee77f5db890041e547bde486335b9a0b85d6640f6534d84b3729b3436ac1c0551d687ddd8da9abc18689e7e932d5d0e787ab5ee5f36eb53789b9ba2b71d7a4f7994e56b056d4a042bd2cac79ad12d87726ef8cb97342e616269e9f87493e95dcebdd91763b134019c0a76e8b12789b026ebd1d9caf1930010aa1a5c348ae2e6273c885ffdf8731b34d87c293e77e9ef14709c2e3b739dec85d5bdb8f5ebc9eb610240576435c8d222ae0c8ebe5844980560bcfd45cacff143a5c208add9011bf9770b7803fa90bbaa10f58d856250b37e481f325c538e473dee7863957121374bf12172321b9c99975078e43a0e1e40138f9c31d6dbe5e06fc881de840e64899c0cf342a806916147de3cc342832a9514eae9550d2cd1166e823f404a05b418e5f9ffa84352cba3007f9d37e5b00049d7c099346257fb53e86b919b45a9c6cd8b67cb3c4e383fcfd5789f2cc087d6b459e2a7dc96d08c826c43410b3df22021855c7d413d9cfe7ca79fa860918a74941e08511595fc9a3bec2e2e0c6dad05781c0a0d6b6609837ca8f78b0368b1217b121cd6ced8fa48dc131709434eed65523269abe95f338bc5e3fce0046ecb24dc1ad8c8fa68b5f9263361e4952ca1aee9229811a5ea85c9c4452235639d1eb8105ff88c048beddc0f7efd3690da8b9bbccbbcfeddcf3e3c9e3ea7b46a5b40098fb85a25842911e42a714c2dd0fab403340ddc1af9484843b33c7f5bed80fbecf68180c9b397ed85c51d39cf08c5c0336b149e6d1747360541e84a93224ae88c1b62384b938ae25ce17d656b9ae52fcd9100a40dd7793ca67357f3fb00621863a490373f0db49b1aebaff7284d450922f1e5243bb7fb5f7230dd7cb8db1e08893696908cad4a45711eadfce8b0b42a9aa937cd011bd5c4a8c3a2ec771b3ee4959eba5e4a17545d1c86acaa4805e4aad" ++ }, ++ "ecdsa" : { ++ "addr" : "0xa16c987b93f1b3c51fa8a9833c8932eeaa566ce0", ++ "claim" : "0xb0c578f123a8a0c96354a13f98c4c2cb8a67541f5ccecfdd0cb6e61aa77f7768157dfb3ba59aadbc03350577f6f31b4083bec30291a61ee98ecb3db2536f788e01" ++ } ++ }, ++ "2" : { ++ "id" : "0x690a7fd66157e5b777256ea5214f634f61b3a72d", ++ "keys" : { ++ "falcon-512" : "0x099202fa37d5e165b88428d963d2a224b8fc82ac0e4b3f6a02376f18218d1aa7d0e910e71586aeeaaddc2a557124d6ab4f9a44b9cad02166413cbeb14b364e13956ea326900eb2900802644167639045d76bbc4e051654cff404dccea94402141ad9fd992cef7a8fa6478b3e6f8912886e9edd1b34c29385b7e964f360e0fb1600787934486f461c95d577d2bc74c4dfeb969b4798565ce0225ad27aac052290a44f844ae233e082c97e4498a31117ac9d02f3605c856e2dde6f611812161f89cb3a54dc936ca1e740a6c659405ed586a9a963b11c89b01746325e39e645c72b0c7e4491b36a17d43ffe38d88c601a5976f5a9636c964a012bfbce5f9b371e7c3b38580d81c6e12b8e8f2aac219f96245d35b4f4afa6c94015b055703b8c4dabaea4ce2577482f5b34fa49e56a912dd58d74580b1f94e1d2056594ea64bcdb696b0baeb33c86b6544761a3ead9ba9888cb1ad51f7027ee52b21e46c5eeaf3f77bc0af7efdc87acbddda7dca00b6acc665002c26447e5b0e0bb5ba261717c68dea7f1576462776954d7249c2fd0886f615ad50d53960ca02d581a4a25517c050ed467c7a820bce6250a9ba2e44fd67fb21bac843bb134c95360dc1c50d54b7280a94440d018181a9d6374bc64d782c84471b47287d8ea748c36cb83cffe053cb89a9e4ae71df497871c2a728ef210903e5b7f39550d0331e15637be7e28b3a2fc05b0a9b0c5a06f9fe81263c3a94403d6c288a561288ebaf788bfe271a578a1a795a85e9d452b61ac204b297090617286922376bf0a8d67dd35fd705b81260b7aad30132b965e39bc3cd64d154c4175951704873992a814814dae5c6bc1e89a83dd91144cd1b88f6ce449900058afdc53bb44bcab63d30cbd6df115a5ee8f5380a127a160e922bebf7b408de82514b2e2550a0931e065565e8dfc389d454823a55b03e5c989b09e3791f656794e8379b7b4b1617aaa9770366d63a657f71ff40c69b1d5da518ef1e2aa42366cfa38e448563f6c2db5e3089bad5520ec26105fc885993630c10db357883f588a5a384cd6de688e1bc3b1200f87ed66ba3d4a4b671b2a500a0436e0955904030d76577aadddb8c1ed21b027f198c072f654c3abb086e7f185980f49d0e109c1a82741809f8afd15ee56a887b392c5b172ba659144a7e99e25ba19792d2a3c0ccb481822839c8c70c65c0943a2994ec9f6085b7ac64ce2b35489a72dd6693d25f2329264e063db26ad4495e3ad00f12df8cf914fd846", ++ "slh-dsa-sha2-128s" : "0x686b5dae4aecd5618b95c3b2a5792888513ba49dd366ac39b7431ef403e04963" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39cf9c9de83a646dc7f78f23792e596dd3ada0989a9b24524300fe109992fd619014ed6842cc68ec0ccb505132b51c98f72a718aaba11c1ee761c787e3cc4d96bcb4cd4dbf865773b2c71f75d0ae3384b1cfc259c9d36b50765c9ca23adfc5e91c8208d833193279876f96f4610d8d462a6595a82daaa451f396c996bc5366bce0cd446300f238f1f30c639b4d1162de28c58e8a7214cc52d394f8302678b1fde127beb8733c340db994b12ba951bb637635fda6fb3ea8c62b78f4591fc328721dfcd2397e2699afcb37472d396ff48799ceb9faf3bd4af4616eb75c9fdfd888658f04bd1343eb767c740ecc541f1b95469a6c7499684dbaa3c0ce74afa5f316f56d0628cef994f474e6712c51ed108cb00845f9c5e4e1f4d1ef151babab5877a8cbbbbb8ebc8a0c3966bca7ebb3f59255f7b0765f31d0c1fdce9e617e5eadeb94ca65aab2b8789dfe757cccc7b3bcb5010a64b33dd3d7462e7467951f84305e1ca379076439bc897b77944e1b83d1cfee4a3438aed40ac744a1c0bfb39230a8312e7dcfcd40c0aef08ad6b7096fdc288abfaf5e97a308396e919cda9471843187025be38ce75241e9bb9e68cb3f0123ea83d2650a771b7f95b8eee9abba4910a1a5d0ab5c7d0b33105fa6a7306ff62642bac6a35b5f4611739ede89d9728d3acb3c278f37e0a3783c4c7db9a3b73ce468ed62d8794476f6d1ece9c9817d93d491e135b534ce4a84ea3d53040f77883ab055d9ce645ad2c455355a755ad0a1a5d24fb4fd348d1188d909211248b75a65b8cd44cde264f18c3a437ec8358d14b4b5d18a14096b41d16b0c296b37539981cc655bde421de16e7935c3d1966f153608f2b85ae8ba599558f48f366d0a537562017a411bdb83cce350120174480e1fdf1d3dcca8562c21cb932d5c58b1b3dfc0", ++ "slh-dsa-sha2-128s" : "0xc9de54d901b6fa6bd74f85ba38a2858f64f2826854beff593d80632adc63afecc9e035ba1eca4fe543400ba56b8d83986910002cf9bf630b2bfd3c67a47210d9bcb1276c5888813a81a016f54c8bc2bcba88f7ae12c7506053273e289837cf9f3299de2d9b9ca7a73d6314a297a6dbde9cb7f38b9c0b67cc824bb4ed03c62087188c6b0116d62be4a49b2087a8150b882512565a1c45ef316c27adbfced543002ac88a304a9cecbfd1acfb9d1a46037cbd4cff2832deb574aa2295109fbb79e8e95f53ec31524e9de3e29117403453b82638acc1bc54f781ad9de9e8fc50b398cc11f4ba59ee8c8d7395961f3f75e4867fdc9abf4e3b53b799befa69ac1473a2b178f709906240ff4c0bd4b65c3ac488106c4eb880e1af47dc92d20cd2aebddb78c8151b8a685db9743295bedbad090cc443de04d58894d1dfe1d7d8e08e8d1df1b4847ea7be835993804c0c60754e42486b8566e1b3b3e47bfa262e752197fc95e611f4015b1b94369608982d5ca8cb9faaaf6ac001e48f02cf5f18118e999de2ffd557cc7ca02aaea2a96f6b0fc5229bb497f6842b7a007a8c3572c77e1b5a87a9585bc34b41678832381e051bab823d8a37f1e1dc09fba0c8815c1c9d3fc360c6d70fb19a7675e7b97e9e5046a7bf7e23e463e0ff38eaf10e9dc466145413df96010e96b058499c27686c4d4918743229d3214c3636b351ca421d9fc4505d139e0f60c7226f01d59cc7e0db46fa80dd1267dadc064bbe960f91a8d06007db6f32f33fab0626020a979fdfc9cd72f317108dc29ce26e8e8681ba1a75131a045ee58fef714671d03dc99f53903835e5020497087aa41f2c3076f2077a442d9a9d4b18bf8c1eb0229637fe03f13519127ef8b5013cb8a38d8ecec5c87357737bf857aad26c69d8d6e20cd5883d7df0cd674a63f7d98720f80ab8f0ddf99b6cc8bb279578cdb4ffaf3c5536ebf29ed45f932cea5100404789368965a47350ea672eb34e59744279fd94a233d72c98c731ef729c0ab7e3b9dce92ba9ab5cdccbb9f194e7a05652aa4fc239406ba6692cee5b1dba9674626d376bdd72e89f52019026333a46b7b437088f9c5c372f2efc8f4417e07678e87bb1970e9eba6d5518bd186e03b5d9ca2643d1214708e180169580ab2a59469fc170826c13e329d2d8bacf3b892405a2db21664557ff6161f2ca2439b0d10e1bfbbae0fdd01e567a78b6e016fb19575a5e26d5568ee3657bd49172c23bcda3e0fc94c458d622fe314e1cbaa8b20cc63cc7da1409a624c581ee0d665f199f24b52c3ea31abb954d86c7aacd79d1709cd90105352ec18f435e9066e722f116a912aa92b9f6a91dd1e092a08d5e9d3cbaf77555005815850182f595bed56f645f4da24f7f654e5393d765e2723632f5e05b48bf2bcb82a88ebe21c2078a72b3ea97fcf01f80b017c7b05dd788f0504b157802e9ea7061b8a81b5df14e72428fa13a19b7dfa3ba8fadc6ddd19821a380fb2bb41f5ba61bc6782c4fce6d683f82b56a55048e418bce0356003ce8be9e827e3367ba56bf17f7a3531d07635d7dd2c2ac0515fdb99b371f9e7b93bf28af94f9fa752936f8c302fe9c5a0753c25617184450ba98634b7b3040307fe7af9d30e138803f2d50f9a4db048ef049f488473e598e6707db264048f931775947e481e9c2b012fe5aa05889acbec05e98783d39b65e39373b0dc59a24f6517ee4a17989e053659896b914c3f7af77633fda0f2a06eafc72eca0f7c5d5b8163cf65cd91761584267b6fd666689d7f6a141b52aa58fc31f64fb5c04c65453ba6262dcbb1d8afcf8432b21beb1d5e10753710c9bfbee37eb3dc0a566d83a2fd5d94906bf9d811e51dc3583f3379ddab34347586eed0c64195bf97450a22bd0740954251cdd3a9c63375215652343b2f2a5bf05b022b1ee722b9c9e3d60cb54ec7d3ca81639ff611fe2c2a754e75cc1f445f66a0098d642cb36e1b199863050b334b751bddc152da95e1b32aa49da80fe90841bf9dd02be330dc0bd033f864d227d5db104374d1c551d57de3da82bad013be5e779b42028c1173c52f7cc31a310853a7ce782ba1f3444107a728fe7263580757d2b86f2adb8a648e2ed1902ec15ce0644abe6a1c8f9211d2a97d22899f7da63b4f5b960a30bafb814a928e814f996dc8d63327c79ed8cc57e4e9332ae200a0249d78ef4333ce97c524ed07d357a2142e8fd3d29884acbaede1aca34891414d066d15b254a087998acffd99698f51b5860961fabfbede5ea33d73182140f38de7ccac5911ff7c5e72d6a83268330aa62487ae26ad1a0f9e9b63036c44489742c9b52cf99a6aeb32927a96e4b80468807efefe2399883c8438d76cb727077662b3116883c784f6c479b2d3c2a77ba19301654426ca1c6a6bcd4ed2df1ae383e89dcf16c06c26fee5c15df697c963610720e76c92ed7644814f087ad4c9384a486060fb8918c14a5f3af270e649c4fb6671712ab85534066070757fea8856297af0b4686291ea6592d3c13624cb81e1f870823ad232fec874cdaa0b63c49ec7e8d25ad1c2d6cb2b1d227ac689091b852383818419bd24c3635625e0523b335b87e0e56a08b1e7486983b1b5e473e5a019493dc07a4e0c73ced0b8dd56bd6f7124216b0c8fb1e74d3dd9be21833723242e3578446bd949717e1360144785320ce79acd274a5074ab695c45d9eb49b889b841ea1605b300a1adda0f18770291cf3780a38b50073c393bfa9e721ffba89dd0a3e84c795799f2d2ba2f70041a13e34dd1de43e550f7ba92496eabce75c91e023450aa37dca806ca9a30cd899fb332d0cf3b479e21bc47572a51b5acf7e181667237c25bd4239c2479a59b47c9c32046889b35394433c30cb96c78226b53ea89a8f07754320ad2237129b4a60164dbe0c21ae7cf53b1dd26231ffed917139a6f8783b3eebbb542b938d7969f007458655d2224cc761f61d41ba0a2ee356847c886ead864802027d58c82ff58cc56395bb1e3c623deaf76e6dc322e9109f91b1ebf35e196da1400cfeaeab77b1c6ef8f8330b4969628b1ebd23f1f8f39e557925367d6102ad8f34e908f782a4e6ddc9e14f540f4ade4d630296e412237e77baf745ec093547de84d0604afd7841c5ffea36be213f3bd08d5ebcee65d1108e3d4907ab0aa491f01e155d1e9419ed5549c17ad24032b79091f4bee3392b2ac3aef0f6090b9234e8edc2883f7b872fe74a422a8bdb790b375abe105b07041a05d96a37f3131c5b907b49fd80bca05159d0922a0b8a1518ca549777b7b8f11ef677fe7fe0995cc83690a4370bde93ddca9a6243acec7d5974d2b47f6712fa3dfde07523ad59a6c945d354b9105a363cb4b3f2d380ef5c66f7b67ae50b4d9a524c4694ab33bd2e93fdd0e423b81e955a0aa52bcb0471f2ff7aa8969c44092839ffab230977cb29b81f44d7c56ea5e2841709898da2b0b6a58e40052480ed40beb2c360f1ff3cc10cecbab23777085ae9c2f416fe8f7474a183d9e01e1eb706220b058688ecc650d9e5c69364eb6a755a9bcca5d9177cc48ea5ee39840ec5489252c5713b730234b59a9bcfebd86b7e9212593ea6a7dff5d99e5f26c486567d2f272c1d97c1e69e5847fa0deaab1c8781f48431ef9767c955ce4fbf2829d562be985951d3257511798b74bdb2f5284087c0195ce3b85f6125b16a0001e8c0b10481ee63be97c15f50b0a97b418bd743afd499a6f1107c2d4af18aa7539c33ac19b6794058825d08666e7ad937d4e10b94fbb012749ddbb3819e98c4a9a9cab016103aa0550a17f7eee535207447f228b5dbcfcbf3752de79bc92a3e9ef2b269dfeba7b1265dd29a3e7096eec1b284426f83c9fdfe630d9da9093bcbcf45180d7ce97fafcf1fb53ff559f53d445e96294c91ec0cbdf8c0d34df645bb1a737356fa8138f03748fefbbae40d25eb39a938870f0ab65e46fceed858e78b2d297da91ee56a7046c3bdfd65116a6afc28c0ed4e26b73ef75ea1383698f9a6de23def22d6e38adbdcc7dbb65f7d4aa92edfa61c5e29806898f3de6d756354d5e5d2dae0e6839eacc7eb8684b7b67ddd2ae084235740bcd8c645ae324065e482ed8fb9e857fca3beb4a82f34b89ac6be1029e034a64787a04eab41d001e5a4916a9b7d994250c1e5f32eab646dac9ca463c2d8b9f0b755dd50b5a077db8f4875000461c677f44289eaee145d52cb591cb139f761c64246ed90a306f7667f7587dadcb5c6274e47eb9acfb12f893dd3852763f30f801daf184a506cb5fa070138643db566bcd962f22d1d32c383a8204675040b887cebe61933526e673115ccfe4e636170569787c119c53a6fd2b0924283958a1450ab2113a69cdd8f99e83a1fd0cb96595cfed5ad3dad843d8538cab3c977314a3f230e358625c63801765196979eae49341d02cca3b8aa5185d73faea75623804edb27722211413d6059ff78fe12c448678ac636dae9ad2565317f5eb83575483f17b5e86f2f32be1306821ceeab3eab2ab7908db00785d506ca5c64a7add4c738ff8f6051873c05351f6eec9fd303d1986fa1a0149b524c9cfd5e834806c66b3f0ca81124e9a6970b83a64af256bd9c574a5eefb4bb66ff9b967b7ebe5d10a106f8d9135b12ee040a99ff20d61f9fb62eb0ddf676a15d29a179ee1c7f83cdc26fd0645d49dfae18422321b0070260dc5e66f8ca76dbe4ce4943a15963c2e565dbaaa1adf4477a7163c8bba558ed1a372e47f84164ee2d3110ad80dd3e608131fa11e920e701c29863980205865344827b61d63c342daad9bb52d1aab4c53b732c0cb1359ad7f1b0a60c3cefa7ddc0f420a5c59f124d1c6c4bdb8ce2cb3e591cdc16166c497782c9c4261aece4f2cf638741c34e913e08f701622c112e9942a11900a7e6373a50cdd3dcd283a4f994f4e8ac7e7ab6fcf414d87d8664bd4b1fc8051596fe09572488f0485a6e63904a46213a82caf4a57f03af2f29cd50c72b2f203daaaa641e03f45ea92182faea719acc5219e6868ba59fda61d32b644600aa18c2677813813f1fbc6b4d5526b516b8cd3b798fb5aee5cdce41dd421ecdd6f3a13c9f8ec69ca0779faefe0afaeb37e6e0cd9127fb3a3600b5db3d2737b44d7c3fac76a1549a7d55df1b4bef3fdf64fe9a094edd84706bc20b630c7680961f500679da9f279a9e20b71c1a200ef06b7ed79177f48e830fd58e3300916c946f61b1845233224cf65d49806d73d4b30297826ec2174f63d8625b4023c9d0c13a924172bb0ea55299b9156c2c517a5e91f089df07747377f490f7b2d1cbbadee76a8e97ba1af0cae68ffb9f140f05c1115fc8928457d0f9ccf186d8c6d07ec6c6a7c7d95460fa24c80e073fc50199cb9ac66d1bd2fa5378dd37160da7657815d81338b718bb88d3881e6ac34eec9794d345e401022d9aa62f76052b79cce25a13cdaf1c8dde90b6b28bb4eefd06de47b606f22eac990484f6be859b3a79db4b70b8837c8b46f48b14a795e073c908a1ecb60558a2eed052095611d5f601806992faf4893f0e9e155a4a396df455610842b1eb3a773d1401288b76bf8b3a0bb1767b858e7cf33a6f59950af0a7eef6ad03525611eaca985889a575cc96038233553bb3421ad82f0dc9050afd08d39701fdb708c71147f4f5e9f4e85966f98666d63d81481e63a27e105d8b81d852734cb2c46250b5d90f008a6af80dbaa0e12494525710a9ba32c245de59d79417fffd9d4475aa5f6580a5c3095021e391fecb3395d1b4d37d4aa0ebbbafb03646a220486e7dcd1ea471979592e992aa45fd4b361aa7fbb263c9e49235baf23daef532be753f9bb231cbf3ca3d31d5b55f0ef3bb9ae616ebf3e760b1d04b5e066552d12bf60dd970809e38b8617826138dacbf1375ef828fa6e01eee2eb1dc6a5979e5f9a8e795af0102cbedb7c51c9c550a8128f3d780c6dbfb1740a556e3fbfcc2a8f0c510bde87f6ed03540fe7cadd5bd256af56065f764ee22c0980561afc392dfb6b0c7d520b4d4aa0666567ddab5d5aa0cb039cbe65343ec1e776bb8e0e69999886eb19ead813f69ca515a758474a31494e1e611c0cad2d91abb68c69914232ecaac0cad8fb0af8b4c18e460bba6139198bab41b405afbaafbfd95e4ccbe69ad6fc4b05b68423d4e49f7d313d9fe593dd472cba497a07a86b77d057c9ef26d101dee907588b6b443e0bd65918cc1db642b082848b7757245ac19466c6dcaff1235baf1ace182235394ea01c516f776cc1c80a6c4a1305b31aa52fc7179e97dad1c0d79f81dd7905ebf305b296393aecfc67f6f9d28a7dce5f74d53b0a9acce05320f53c7788437ce863ba196f3881a0bb19edb4355e772a5539d9b23b2a631ee31d55c5a28d3410dbe7e340dd0b6b6c171be399f5a6930f1dbef0e850204b2faa99516cf19899c93d1ef1e2fafc20c5f74642ce6b1035db9597507f43f754fbf32f3e598115b451377bddec28fc19f8410e48413fa9b6d227f323bb2a71fb7e984bb8cdcabbed3151b2cf19e8997fee8fa20f80e5eb5edc71cfa38b0093f957cebaa569be1a1d29b4ac9c4cb5d8e4a2cf36909ba9a1ac5cbdf41c2595a86d9b33524eb25b1f93e0d4a787f68923917e2c9942f776d3163cf791618eae20df41e3af5f9704d2d586b6f6e4347f032ac981726c95ba72c60a38570885e97198d3f9a3cf8637032de5f35f851a0a3c775452f3265a8b0f567a9925dfc0854b2ade20e0b28f7b878bec3c4c170df454dcdc641f32638ea7766d6d1bce6ab4a99ec169d69673f79449bba8a00e6842bc25be10ebbdffc0d74a0f5bcc8e7ffdd743f3232db2eb10e75417bf8ecc672f5e1b158171993540e2b1f7505c81a4978463d45af571e013b4619181028d63b51f73a9e325ebc79398c865b876202185a3860ab98fbe00cd4e385cb4ea5b262f43b2d6524ba0c8cdc24b7fd9a377a8e798281a4e2eff177a871f0aa41159066c89fdcd0bbb89eb42635f6e360148b25e590422a623e0f6a042629effadf969bbe82398bce9fa1297e26976aa39ed5f3c157985656bdad1149054c1a01f385cb6f3cabc2c534730d9174e53ef9157059ff5156b2a01ac71f01ce8869b0e192c3897935dd59356c95751e4119205558db2f040694a57a9a67aa7dbfe9f62d4cd1aa43ede69222884bb88cd74d91c09eee6f6fb96e1ac0b31f7dc29b58a6487c996a2dc1f6af396ab1c60e8c287cbb03a273889661a0f80aaf7d67e2d2ce5e29e64e2ec60c605803bf28e394d4a611af48d5ae920589d3958285f4287c0f56209de0e46a99bc2b184fecc292a0da8351790f8c029ca2eaec8f195efe1a4b2534b98674116e1fce19e625785b857393a92543e4f276024d9c4053f12985ebb40f2d6d7ab22b128f34e4a7e8f26ec138bf62d75aefbb5d1efa4d36578ef3c7d2af3f9990bc8c0a368ad184d6ba36be7a8dba125491e610ed0aa5ef19809afeec4ddaeaea2853a927081f92e58797d581e8e6f6fe73da8d50c13d37b5241000a92e3224c75f228007f3acb2c38ee8d633e1a587379f497e7b93fec2cbc7286827ad0c98ed961ad526407d97c5ffb17d108d345cb6b0d45abf90fca99610c7ff291dd9347bdb94e56555a9610afc3ad27042113ccd9f1561d9fb8441685fd9be44fbb0f2323ed1adf7285c8e65667aa4f8ebf6bd8599f13efa5a3ab2a9ca97e6963cec0c10023674d623f8d25507a47b24f9a0c491087f84613cdae0a1ce438d832a3464d96d1e75fe473359369a1f46871fe097f46a0047a290ff3a4f8200dc7c1e5ced78e3fad8b7470a1f8768d631450ca9ac8b379b65a141143a9e10daf38a246e21b290895a4d903c2e47f039c1d6070128860d3b531c8e46ab617ae34ecb3429169c72e3f134e26ce56e7d4e1669535f25f521b1a5e3a179e9d8a16688b101e91021aa80f9988026c3e92ada1f2411f2965b00616df0fb9fad76c7dd40f36e0778b6ae3046bf61298da63f6039df8aaad0e86e830e83bd85462590f77c7f9f5ad87ca72da678c36d175d23e7df017681549e103628dd0fb47d507a1e0df822006b6278f5c2787c18427919be5a0abf49a98faf159b07eca7dd08be113b053b811b8da734538205d792e7b21904ef90162da6484cabda74302a1aab4db7bbd23bff51810702b2642b3d964f50f234a657608c2464121d4a33000eca4b30ac9357e81310817e1a2de8485487c2a7342259aa3b4260001180df6b0290a8739c0a9d296c3db5cbae8b8e1f3138a4f1fe3e67eceaae13f88da7e86f471740adecefb267089392b2e798614edfa66fdfbe45236cf6189d2b5538df56e635144054cf4f4d9347cc02ab214305be94f1632c02d0110ee5292d6e5755b9a837ead7ad1db8dc71ae91bfad768e7f34ef53bf6b90b7713a3d1f0d4cc0b6df3db1936ab7306d6020eafeed31d7627476d94bd6765a1110969852bdc630c490ddc03879ea1416dce21a2f364f2551fe2383d121e54c568f8bd480ab2fcbe9df0b8790daec4e146f6daf939f5860c8f3c77ef7c4530381de716adc36a7ac284d8dd7ba86241b910e838869c59f5c72431181fb37f8dbdb1d5aee402697823bdd6992449f437bded25af21eecee30bceb02f807cf77afbee810f95a6be473aef683ab1a2ab7ecea32834a44009fa8ae3efa66d5553dd8fb97900468020fddd2d519d66da1f453ac1a6e8c29c34ce9aaf8bbd5a2c59f8e7dfd057a258bf5eda4aa364396145d7e21a63138a01fce8fd7eb259deea64ee92181bbe01de69e7ae060f312b2230bb948aae99cc814692abb6488ed25cc28e8c62f3ad5081b0ac4acc7992e233c9008a1687fc843fe9c0352016ddedd624b060eb62957094f423332fc72c6162628b27f83300c188e53aa078d827aab56b885cfed3ef50ae5543f884bb2d860a051e6d369e3e6b2d30b7abbd9e9564bb123955f1d31e13181e963f346f558fcae1f26fb81c90be77464d63064656ee9edc0d08cee1c2797557f90dd46c8e0dc852f4a11119025b346e1c35e735dd739f4ce869c7583c0819ee748371799d3292c5eebfeef3542a08abf79db73945878520594fd1e79f1d57a22cf288025c9990c0801190ff54be4df7ad92c86e886ef08d81645ef92e93f666216f9c3a95358227f505f3c586f5fcc5e417d8847b91079c5fbd2b3289ccad9c08f4be5b9e04577d9b768da2d7b192d4217f14a8fe31869921f8cf899c744d1857f7e66fbf09aad0206261db64e8285d86cf5050a591c6ed0cacb138637423b7bf44a735300c8d31d4ff434b10a6ea142595ac0a3e1cc51d87728a56ba78943407909866638164ccb2c2fb241d5b7943e76dba3f29192ad5d3aba4027448ea99708b81a06a15feb3909325c38841f0bd904c51ad383b55eedc282b7350435f75f2e3aa691fa8e24f0318c4055137de195ba0432772ac70a2cd0cd0819b55170c610862cee136143f8e467bb14c9a548c0f46166b75bd0541749b3fc486ed02f774556edd410f0600bbc784ce32f1732d58607867ee583e584b70df8b276e98a72a09873668124fe3b09c403fa6b3d30087a64d551da4d373a9fa4256f0f2dafd254c14696a0c4dc1f2de33c67ec3051cb606c5dd37c9ed8d03299d7198d6d1b8232d2ea7e0cbb8b8a3acf144d110a04420286f8b538569be5672f3c6b93d8343f1f9927d72cc64733450d188b8e82b9b30187f68751bd3579e4d035965f4d337a600a5304669e27207ba5f80e5ba68932749174018fcaac4b5e39cbb79dd0cea07f2a3da996ed69b5d728992c67025c69f7a3ac5f419cfd267ab72cc91596215ccab718b4db8706bfcede4aad669c91b42537991cc508282c9d4a8c2c15003bdb810716a02f3f08215dbb3204178e10179373b822107de5e3637ad23463efdc6b18c6a5ec7363794c971cbe338b9db08f69af2912b9d45be8396a7f726d78e6e85f7b4341c3b35403ab399a7181c4b33a9975a1c4d07ce6c5a8f8b9f614d4638db39eb05eed248b63b45440af6d790fed26d77183581bd7129e7e03d61108d81f590385f2c413835a11b57729f6fff470b56e78f54a2d73a2d104f4994299543d8783482c2aa218a31bfe3cb2e68aa6cdbf2dfc9b75f7c55e3005979196c4aada77490aad5c52c2493ba4b08cff6b17c0614c4673f902809512770539c7ade6ba2cd43cdf9c668310bed149f467c0d44ebbb76a23a8fb28fe7fc2e1000ea5e8c5e61dff237be9f0c2ee0fab29114dc07b229a93a2ff02bc7077eeecf087f3716fcd69e64ed9b5d9b78b8b159384d51bc43d64415da2a4f29410459603a4cf6a6735bbdca3650fd15aff192a785a3ccab7f3a4df74a02d724d36d4e98e243256e6361c50f4b9839e0e73bab1ab3cfe3f8e2a1a94a7734644c2e0077c9c12614db21f024ecbb048c15cde54859e93e73ba07df2b11eef7d7ad9485d9a8dc674645510547b6f0d586f7beb8c2b1991b4e9794730fcd31cfff08743f41c82f1bfd11f01f10af1c2a8b7d4e5a586016f5b523abdd11d1bc77d9b678920fbd73c406db701c27020f910fb63dc59ed44ef7de5676346989152da54b0073228e439c32d1ac85e667ce2392278ea1d528bb9828287ed1ac64c91413a2d849fcb56e5f08a070487730e25bf566529a1f7e4ceb037e10fbae016713069bd81e874950f6ba5c1b2f4eb26d04aed24a1e64ee0eef339f13c5c55cc229da57c86f676103c10d20e5da578cde3f2bc71acf2ab1afab32df621cdc451eca58cd86c9f55c8fe41d056a581a446bfac3acde068e930583e0fd43c51f8a36677d23436e48c5306795d745aa3c1679893b9223bebfdde35beed183de0b663d9099eed1edb3b7b1ca9eadd7d5b73421ffdc59ee0a3dac1688546fb42e78db833cdd1706d8bcc91f3eb0c66ae5834361cf78f8122b95e48e5b8149b46ca8e0338205965182150ff69e0f7f129b725779e9c7cd83782da6e6a7f97d596480369866899684068e051fb98e5ce562b05992e27a1358d3ac495300f21f474e7ad94f8c0958c8c7ae4801e39ffbac70c4ec3fdfbdc13ceb919aba3822b1c0311b115c861290fc333c32aa74f38f7ee4c1fbc3f1ddff350c7393a48dcceb1e9ca" ++ }, ++ "ecdsa" : { ++ "addr" : "0x5e13d369c8adbd8079272b624343ee1edfa4a560", ++ "claim" : "0xdc947bf1571de4970daa8a731a94015700b880a4b5f0bb1a06f50a8fdf3282452d45e3f3052db6e09410480b99bafb7d0f887de669c896b4547efc64ef20446d01" ++ } ++ } ++ } ++} +diff --git a/consensus/common/src/test/resources/aere/registry-v3/n11-duplicate-key.json b/consensus/common/src/test/resources/aere/registry-v3/n11-duplicate-key.json +new file mode 100644 +index 0000000000..d1e7730e74 +--- /dev/null ++++ b/consensus/common/src/test/resources/aere/registry-v3/n11-duplicate-key.json +@@ -0,0 +1,62 @@ ++{ ++ "description" : "row 2 carries row 1's slh-dsa key", ++ "chainId" : 28001, ++ "requiredSchemes" : [ "falcon-512", "slh-dsa-sha2-128s" ], ++ "ecdsaRequired" : true, ++ "previous" : null, ++ "expect" : "AERE-PQC-REG3-11", ++ "manifest" : { ++ "formatVersion" : 3, ++ "chainId" : 28001, ++ "bindHeight" : 1000, ++ "count" : 3, ++ "0" : { ++ "id" : "0xaaddb4dde09de5718a906d83be7db3d58e0ae32a", ++ "keys" : { ++ "falcon-512" : "0x09501c96d2f5cf0b28fa00c726e5359c5d36a1fa069971f854b7d914fb2f1295e68b2c6fa91d82f7d287f55ad493c87320bf7ca2a5d5e79d7212e8a540c166b588dc03f73b83be060525b367d9f40f5e77e7798c60b6499767586770722820b3b9e6013cad3eab5fe5de96089a29f34919a2e9ebcb3fa03a3e714593b7a3356d11ffb3441ab40ad94474da662a71aa2419dcd50668cd5d8a9017662cb60998b34ab5b7929c58a94d5e133ebbdadb2b0279543067f76bcc4cb6d7e0a5edb7625467e3ddc92a01206e1b8dce69be31928687d8af4d26633a07e73c2830d5299b878977691cf65700b65b6ea2463e51b6136888c544545e59fe8cf190a7944e215a785b682623c95a79eda28e25e0e1b91b49ac89deaec3b14a3c431d9046a663170111ee541d81b43aa91f29dc147c6fc97739b3a63fad1ca84843d0a65b8d9396f28e9b11f9a41453ab18a2309ae8db03253a09fac8f0cd634c76a5e938a44719660944a95dff056cee43ea99592c3899c2880d7181ee3dd5c04baeb60e1369a69430a66031e3cb10e392622f5246a71761760cf417dcb40ad65f60704fb74ad26f26c3af7513a42f806895e0298c25c049187aa536e0eba21998912e621846c2ca0e323744ba930a29850fdb385c8241382296ba28dd4df05ddb1e61fe525949034b59929a784406de240f8086b4074825f419d5472a28a0b157500be37e9f64897db2b645d3807c48dc143266c99e7cc1638ae278772493a2a4ecf74e526a514bc9119d7129c5a0d115a450ccf4dce05b76d4b6149fdab028006df7ec2209923117abf7578a082128cad42aa66b69eb63acee4456bebeb537ca57bb3d3487f95e4f06c5cb29f292d3b6284e5a162cb83151cd9ae56aebbfda150b7edd5065302ccab70892733a1e096ba0da5f51b42764ad23060eb197d5460425fd9c7a26e7dc3cfd40eac3643539feea72c9ed41569111a7976d2c345ac2183fa2271b424526709fd9aae558a23a5cca29f4e2f31629746a71d904612e95ad9977bbe74fa32e90fac62625838cac49f50e5aed4e8879e2ce2e5651c4f4ba0c96583af9e1612b5ff1a6fac5027c0a308815e592308170b915b4a2de1e8d48e9a5730680ea9db8f3326c430241153b3b218d5347d5c843570cf80ee813871ae10f6b8ce4ab7e4c5197045e85b1cb4977f44c33eb85894b6555b4bd288a50c1b656936841048983c00a01631f10a84522cd613fed0d4beaa4aa4b3e9f30c324108d909e59a80150", ++ "slh-dsa-sha2-128s" : "0x47a0b70170dda85f843607f6c6fcbe6e6acc7c22980c108996a3fe72dc9f61a6" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39c8813cd3b34be58eaab900555a67486034b1923e0b00e435661230cab85f07690a5958a5f5e9c84f033a3dc2039a5296443093fb7fe8d41895fa73be3fb34cefc6cc36750d534e6a3c47307294694729d6cdedb633e8efe8979a9aee486eaa66136e342c578761241192610185feb2d3c196bea0e79222437b6a8e08cb09778d053b29552df96507b1cdaede8e9aa7abc18902f29937f30e7cee6868f349f7ae33738237dcaf86b8e8e01238f3d8ea6fd4090a8161db65dabeb5ded5499e8cc8a5b32607abc291b36a4b34b327d30cdef18c1825232e69a2b09d539ed84dd2a4756efa64f864c563943b3db825824f294c1bbfa2157347b0fb0e7f8a56ec253b39ca9b6cb1ef7d3d7c93a6cb220a7dc50c365905ea5a71575c3aeab25b33523e4fefbaf66137f45c3d96db719a12d2e2d42fbd6cdda58c5a1b958b28c2a8f2cca297871a147dda92a7f008a359027a9288e42ebcd6ea9542f10b66dbbce6e7bb914206122f866d9adc1c89cbf8bbad9bc9517c2ea9018b61d4d2df9abff1dd9f3a0a6faa72a449af9c97e8c4090f3bbd9824298e61599c13c7eb89677c0e845ca2907c728d9296c24e96b6a348dbea7cac62671c9a78a531463614ce321e28ca2f093094ba5f69881e6cd766874622ca769ea556ae757cb7f9546d99f5c90c25e7b8e14f3b7f270861398800b0604ec2a3374659277a23cf6131c63148a41b05b3c06e2a98a268f1b9f0df7969addef17179ca2261d3c229ae3db0c490834564c45f7b8ff6d3bf70784779d75915fb2e2d5bc147bc941b9e249af188f63f39b028547cf080b7674b228e20a600e3b167610f814daf105226f3c1ce5e07834fd33dfe46315546e926fd5be83fd4d47ccd5bb8ae736ac745daabb59c87b9edf9a45c9a1d1617ee84e588f27d12235c59ffd9", ++ "slh-dsa-sha2-128s" : "0x0e8f9bdc22cad3613ed07fba30ed04219b9528f9b657119e2f0886dc71cda4afa7d462fe8bb108feb58d998b370b2f7e162390713d1a17eb7de781a604041cbed13d00effd3b24f2ff87cac74f61e7b7f7aa6a259dc283485179ab4bb966793be018c4bbf4475bf7a69e600a37246908f662813813d4b0f4f83757f4064c5c0713870a0b98b5bb99025dace06100497fda8c73d7385d123afd4953961066e7c8544de3fb620ef5e23174327c2b64089b3fe6df3eb86e83b12634a0c9cc0d7844c894ba6d83afed6becb6f5abcfff397c5cea8064e5e153ea4253abe599dec1614b449329ebb25861b69a9b22228d1a03ba51532ea64ebe7603474a15a2806d3dafa29d57d27c5fa894da673b85b4674ce835fcfbd391d328ef83504101432bbb0c83d7be462b265911aad862118af6f4cea4df0f1dd38969c69428fe438d59d22736fbc7dd5faf6758905b26ec4c99d71e4b8fcc562a694ead91569c9a916df5ad693cb2ad0b7ae4c4f3c5b7322f56612c5449e0339dbd367460c76ab89b6f44942cd33f35eaf33c2ddc0c6af793556d5202fd1fb0f9fa1b7ed45c6ca68d904e476477b71a0bc6ebe248c9b4585da0c7bb186600691269bb4c836667a6d73a455b97127d898b7fae17e1acc6dcc3bac3ecb14da131d5f8adaa64b054e2f569d9bdb164792038e107848882de9bbeff295905c2af68d4c6dcc8cf718c2de872ab6b3d18e00d527166f8ced642281302e2acf4cf4489072a2dc3d55ff8716619cde494be1763dce925438b33ff1b91b35eb511645832720ed92552d4880ae53ff6516cfaeb1d48c923648e502e4038676f7c82e532ea713c6b9348c80ce3c5735f437491d3a8b1765294868c14123af2e9ff61e394216e630c71ff976072d2a1c50cfd8ee1ce27aba5bcf9aaed4a51521bad5e5d5e66abc7a95b215fc8004364aa4df2b8b97b14e3950f521b6327a55fdff9139fb0bd35237b022e3aa128d36c8a60f4621d25d28c59a97418c7dbfc15d900ba626d283632732631ec4a948f66dd9db3bee8c2cf60dfdacbb5ad4c0b2b31f8428868cca035e79c95bcacaba40a9351b2b44cb29753b6b9da0a751bd5af84c9094d5fe91e97501d4f075392290e8516ed5e41b41b00e09793353707fe5c1d942395074637f3ee0a0f105876d6f28a74f9558c5f360e98f047a99af35ccedef8d5cd299365e81e7e91f28a01eb265219e21aa7f7ce56b62f9d2a61560f9fa39f2765f5b50920658100a638aad03482a687905cd27dca02f1deffd1bc49a1be1ea7ff1a505da74fd932937d8f6a8bd75ef456d5f7b71ca5357bc66db6cf14368c4faddf4996363251e6a6113ec64d642c319dd85830d8b4c7ee1437ebfefe01f27709ba0c412c266530f5b6bbb005994774e8935f1d91069f9e7a8cd2bb7ad6527768473affe24709c10294eb588aafca85b379bedf0b142b109e1b186e635b0625c4e59576266acb5f71040c44035fc9480b13932bc657cf332b12da1cd7d5c3977f51d5fa742974cd256e8e3662dc698e0516d615d0a05ea9caf12338d0dcb6151e07f184c9cbd5e59bc40b12ed6372e2d6bd42aa0eb6c3c888f264a8c0d3332631d4919c921cdada6bffbd01ca5445de0779f9723577ebd7e33ab0e5f577843aaa6cb8cb5f0508c33b63913a44d02b76bbb1eabae325581738fbddb5d4fdef8dcb8597bd29c6ecc631839118c44f66ef8dedeca65e58941c30e0423c40bf064b8d19d28dab3787238781d492720236a7ae0695ccc867fbb1cf207ebecc64f84daea66b6745515b9ac9b725061bb9958ed79ad6161318a262528004401633d47a023c645683e36413b8653fa4864fe98c501197c10226b1732337842a1322bb788a00a0de86758139c2d9ea3c5b26bf5d7a4a92cab4cb686c580e3e6cca488136f0da9279073b3dbef9519168ba02588fa29cc60d02273805b425b919a7e2e89c9086609982163e09d5f6eb9c66267ac7be363aadd4617d398d4bdeca37a838d650b0919faf13b78642a058b1bb96b2ed1482cef9bc6e8b2e061e6815936e15a9c754353aaa786ab141e95e5f6c464a41b8bf29e28e764abd638abcfb342b54d08c15ba7e24e6fcb69b844e16cdb5cf4f50db60ff0699f969d8e68511fcc9e16a58e100f80671af6b04ff3edda3a4f05f9183c0c3bb7c1061fee2d3f04e33fe75f1354e6de54f582da914da0138e8565ff45ef52f638cbc33a24bae863fe91e58d7c5da34273438f15e10d4f59db16e505620d97d3fa4862a4097a659925d0e5f4e073103ed29a600b051b83b1f3a21381f4b871c18d262d7e43842c34ed80661438c064aa2fd858a8f3bcb035b5e942baace7b50e4de5a73d5c51fc0843cdc163958a62d333078f4c7d883bd7055a602e04c853f9215c9d7f798403c007fcee124cf6099322629c449ad4ef84b7356110798dd87aa4d98ebb47abc6cc8748dd381d588b77db7f4e7550f6ee1ef4360dac6d6c7037a65297d4a0ea7999a5632b90ad48fba0a916846a216941fbd13d62ab36e1066e24990c19592944078435c52d7717b3556595b645cd2359ad151dbb67e92b14168cac12fb2cc5422582a50bf6e99f116751171c9b78744ef719282f1b84bf95b4092514f4c68fb82a1526e0942ca50e186632cd9b0b8b8d91e84f85e35f30f815601798fcae676da6a2d38eab62f22445099694804a36a34142150fb795afb445e78c241f0b645209037a8871cb5487c975975ac997a540b709e3df6bf208d9d8017f9688b152c9ee2b934f65393de8403244b7437108e6d8c973aa723285555d9eb92509b1747977105cbac7fc33e658fd51cd374d21fc2bf229928948292c1698db7934d0f9be44b137514d0a5fbb659bba83861931e03698a61cd20a449d0358a5fce7f288e18bb3eb62b7ba0ae75feeec634fc90fc45ce45239c5e3179309f0c202cfc53d9f42a617f7aaae586e7161a0723ccebb7e8586cd40e1fa12d3ee89b400dba8073b0080ffaab1182e8243afd93318df15bbf3ce179f21804fbb8882e855ef9e0739ce1536d8ebfe9856aefa9874b4e102e705a40ca4c3ab0ab7df63ba525189b518796590035ca780d348de49f0ba8f28456ca6f3e3cff7e761d961ad98b8cf01e855797c88fe2f811e41e787f3e4becb0ef42ca3b9979356020b447294ef295543e0ef512a247e4d356bfe3deacca8ddc5255e6ad047121eaeafe61d71e7f31395cf78890add4f8c688e4eb065479a63ccb3d0c09028bf60c700fe9d19195c26fcbd4130e6feceb52e192a2aa2343c05b43b276f51a7c55dff7233ea512942291900d93315438a96af08e25ea5b9ce656c54e71ed60d1eeb1665ddaa9e42378c930e21d93484b9a4099b7ddd71d983b4c42c6b1f62907ce84b24321422b08b847f1ea97befaa4ec30a794ad7f340210c800cf185ee2c6c72e844cc5671964e1e1ec58953500f149f0f0f25c34d5592de421c2e31535040020237b907e86d753094dd4532e1ab9d821e7583d4a21e1041fa7ad711f29ee3721a2aec6b0c46866a2de71ee850d8122f722898e533848e2bb851ed24cff9ca83badcfad88a171b4be064007aef4d759d93ae9b67b446f3c6fe504f5b4fe851b8312fec86b46ec3cfcb36e0f682e65e117702b888ab8566c9cc716a3a86106d2323c0f7f20fbc1fcd110bed4492a750befbfcbbe16820077dee281bcdf14509b93137a3998b2fdabc2a375b38857bed12bb8a9c67bcae7934d02d6ff89620fa8946c8aa524fde99c12fec0e25bd79788e2c15fc31fa3f27502cb952b9f9482580cf18ecabd92c55113ec4c4470c4dc06d8ca27a10474594eff708209e8f376b6f17915c2966dbeb0e35ac2f02419692c0d232e133b3907059d3a56ff169e7e61915c8b1067e183337b40bc1136241e862eb3ab3f2c6a72b18511c4107ed063d1e2303d0fe6842fb01c204d1bffad7e90bb44a365e62945a7f631811c9c37ffa5ac39c16b4835798686da5baa8e1eb6aa76b42f6b86863c30669486a175d6b3bc5bc47c5eb05b240bd921007fa39506c6605bfbefc9c8c493973bf3f0767817fd8ce126a301c5b8fba79628a9b3a03cad0c491a5f487dc5e89269e5d3bcdc2998a136a012486c5bce2e6c6dc595aeee2ebd5a36dd06919396184aafb2301d1889b668c4d701c7ca01b95f9508f47d4c411cc0397c244ed4e3e3ad7f97d86b6f8834b13b1b2df0625e6b4eae9e439815e65baf2da767d3b1700fc461fad6297fe4e8ed02bfb65b750c2d2801b7308aba9657df3c3ed7d548687f55e85c22343d1db343bc2dbe222fb76fbb3cf490cee7a99ab3a337c626a148fb303b2f8651651588dd4859fd65c95820ee2af85adf4e8fc2c03828ea7427e7c6b0d4a1b0ccd424df6d1450ee436c01351d8b6bffd4ba072756315968845ab7976813d93d0f0f2be1c00faab3ccafa71cd26c5837e87292870cf768c7837e18ddc3c513820c660870b339fc42c5211d33d892ef22b475cea3be20f5e47206efbfdbeac208e26e97c400edfd41f063aaa6b85a0cf86e23fb11274b405f4f796eb10cb97e70783909ad492ad9207ae7b3d204e59d69c886f91bc82a107d0be3ae85797a7cba747b8e2640ec49384f53c785a84cf8de37dd4048dd4b879c58768bd131ad7226506113c446fbf13d769794f1535d58e9c52e23c1bd55e13c647d304e297d968c759a378f1d594897a026e3271aa6b4daabe174d6a35665b35193379f0ee465df7827299c18e1012ac69913a0a5bb5142e99b051763de3e98d5af8b62133e25b32f4f12b787bef7e21dec42de8e4d99a0adc8f365d8cd3e6a5ff3064ca18965ffdc6b383f7ad08186d735a099bb0ee14506388c1a37f7a766d286d748d404457226b952ca6cb3f317b0f4399006b5b8c6eb89f6b8cfa023cec4d2dedde3e31b9a633c0888989b44ab182a5aba30ba78640f477ef1202f6496fafc2a18e283b2e4e8bc60415a1c9a7fd68f15cc1ea0299e3b26f5755ad9f13481a0563a524c6735942f5069dc1d6a070b3c3698e9c503f67a11efe59413e937062668d3439a5dbef197d24ebdc79944b17c549b0648af9b1349cad83c2a0a9e55fd893cffe2aff4626662ebc5014e70baaf7cdbbdfd3f92fcc5eed863fa8afd87f88873f726a0a2eafe41fa81edd5833f5520cf93b0fbf0660e48eb0258d313bafb87dc9b0d0d9349f22fa2d960238f67457ad644bdc60fb5eafd1c88dd2a74db4da0f723a03df08af6c64883f275395020341d9dd3c7fa049ab2bebb4d8af2bb8dc1340d1a80088c4b2c26bfe7314926ee64bf239306c05dc2ec6e6c5e0ed4f6dbe51f5ee09533f558d29ca6fd27092c20dd892c89c83223752006b23e5abecfdc733aaa59c8549e89e5ab0eae1b44189f58cf9cc18de0c2a2f46a9235fbe42c641a890039cf6aad820f1f844edc24e69bc3bd0c22cfad3804d876edf5491e88cf891c347ed5f24464f2df439bb30742e1f9a4a7eabd9346c6a5f93af22e67becc494cadac82cf9cb693acf44560672cb9227eea2575f90b0e28431684ae12ff2e86fded0be3a099f9ddd32a7285531de8963c9a03355f1d9cef88d7ed9b842d0066ccacdb698d42ff9f8a4f000b9764a9aab1f3146f9f95e6636fdfc9ef91c4d060a54ed7f32167e7ac50590dae3a2904d5d2eeaeff2930bd4cad7166fc17edd2c30e6738157eeb0b441491e5dfdc17a7fbb2bdc6426b2cfb26cf2a7e20013f1b3e33a6d6821928443cc7893f7e4a5268a8b94a6ca6097d25be17b214ea4301e9a723194983bbce286f4363a53afd9e94dda9c761481d9d20c7687a2ff85d42436b9d557d5dc6c5e24ea21d5231487df9fc7986100664edbbc51ad4921c5ec9fbb407ab33ef5c3b3bc81f113e68f38d73f0db0261b656fc344d2d23b93446845d69cee1704834d98737848d405f52f5a7bda3dbdfcd3af3881484579d2d2f3ef976cb35c9cbb76252f2e00019363273489b39943d212ccecc647413c56de69e0087532223cf9b28ce3f77fed30bc3ae6a0842b546e0e1a8b6f6ee1ca0ef1b78c3ed829af817099426f94a447f67229cbca3c07b7a8ce547c5eebcf168248e0a0b9fbeb398e5ed2d0dcacb441f95f9e30c108c725507e459d34c1ec01b67065e5e202d685502d6ff015d46c20bbeef1db38c29df7df585b95d79f5687474e71fff162c0ec0c96c94c507f8a0292a8c32168dacd2fff78b5c7dc145e10fee1b25c478172af8f3ea132fdcad75dc22856deb2576a5ff3e8911842c811d1d57ec203c77b82da3658cbfee18d140ac341d38a30f1af298cf60f2a88d0dfbd3e079ae64a07abb4947cc042925fd5c64bb5d4467589f8c495b0097073c081517bc4504dcd7442bad7e7acafc894fcf34f535979364cf5e908a84e0e141ae47e2ae4dc95462b4f345b12b0629502c7bd65579ec66b2d0a951302ba6da1d1176db6aa0c0ea1fa88195dd2248990fa4aba88490b1da4ea405649203f6ff6f734693f40deabdad59ac62e3296cdcbd74061474dd7b63c46bcfe6ea2b0ddb0f7e77fcff3599892c82425b05ae7aa1a2ac1dfddfc67e11921ff4f2c8f6297881dd5e38ccc4076cac8015c59cdd6023ffbd62b887b33ef8d917446a8941d9563acb66a6226fa4d3f2cc21604c080b3f83e73c093d8f2f7067c392671020c7a7eb6fd0d97af0d63032a3116c408b708d4b2f711c1134b88a91aa359608550f0049af2bb97688afc4352a45c4f6d30d4634e70e82515ff1d5f77851ee857e42b486d5e1f3e0406227dded6c5f47eda30d94f44d978322891dc729eb6ae95d29d22c8a5d649193d5d2aaba782fa16ae488f645a7ed90a566e182f97bc62049724f4cb5fc71f6bc7be57f07a7afb9933f6706cc83483cd7dc4182768cd35bc42f1e9b54d5454d3a17e734475ff58fc66d75419d3d122eff05f7b0548188682f1318ec32c5bbea87c8624cc1e548bf18a6b102e7a43e6bafb579e4e84275fe07d8c63ace449a44cace5d9305ff756cbf40e5a6a20334d5b4a74ab0483e31593f2277e90341fa8036496c2bc6d2b7b10b0b354c86d666d65cacc593d1d7349e71b0360d823453011ee16b6280f5c048111b99b185af99e9d901d4eaffd8a96b1ff394b66208ddc1e7e53420fa965bfc4e630d73ad97b9c5c6ea884c619bc24ac3f46234e7d8d35a12b0cad7220d7a0945cdc64fee9d8852bff872c43f359e7aadf8fa3de3551fb716704af68a18f79d03b3c7d90cf21eb4bbdcbb4004f8ba15ff0bbd2d0918ee78e9bde980e4f3cc13558e6fdb40ca71ad2c10f5e5587784bacc6b925f72da12528216895e0ca4b350d078fdf534fe01bc86b45e0c8e2b35799d268a457f8768ed782dfb56abecfd2b9db00cd10e189c6164f82f5ccab423277e3465ec72d76b696cafc1cfa9a7fe47d142fd6672d9c5b77751b40801af07fc53b1c9da0fe6981ea75e066572f7272baef8fc54bfa7cd71cd0fbc5d6cd717e9aa07808496ad2b4b4005a320c9312c73385afd61193581dbae99df6c25f1b9da17093ccfb108b0a26c5ae4963183533ce2f0ade01bf5e818af613416433578522b1b1e5aa7c791570c8c8b26ded266399116f5789a8233fee128e54ca8ce63fd56c1a146c3006316d200e05715993d1d97907ca83d7fd42ef7e7222eebd74f9c86b6cefc82e614a53976272c8801bdcfd882e34d86b39142ac05088a4c47010a71107bc72a380bb3e5122981d1795256beec20a0fe568002d79a4b1577903fe8682f268eeeed0a97861337ffb6861bf378eba1e0957111c7f9fcfeb55a95238005b40e13ce40efe846ddb86d14c9ad2c46cca74baa364ed08da3a3079fae3a36346ac949e2174c661b8801a051423e95dcab6a0f9c965e8744bdd0e629bd3c1a1241e99951ddde184eb8f354209f24c04fcf10fa8f4e43cb55c922c28be041213ddcfad65c86e1ab9b615f91d5fb11e4cdec5b7e25f8e9811c82c2ed457d012e4967b555f228baf4f1648854c624e0525e36e5f4d1961bfbbc3621d79bd6bea72924d8e0146d0965c239a768b417ea4c33237a60fff2760a9dbfb1113a37b01b598f3e06987d99518bd9f1ec96cd7050863898c8664f793ef29114bbeeb9afab8ed09358d1227d7de2aaac0ab2391cb2013028ca5f4d1de6425ec5feb17d95df358572fa27fcd51d14c363a36bc37c7497a0f964a6c004561f68349f828d30d4633e87bdce6b6d92384c9c1c540c8295ea621e9a8006a8d7c163b988853071e06c78f1b9a0246db052e8484a65cbdced3a587e45d9e2b49a5501590cf768d08b6a043971110e9c9dc96abe855abbb7aee2c38bbb77e5c68d61f01f2376b6122450117240532c7c840e3739395dd6c9e80a432423fc5e3a6dce9dcd58eb418e16d7aa507b4d67dd6fe2af4042a5c7398ba4f87c650926084efbfdc9430a4bc2be544880ecdf7361aea06a25e4f592104b0d74312f2729a4db5876b675bc0fa68f6e41e014b7caaf6f49b8ef704b6243df410dce94ad2c51d328fb90b9cf2f5df645015f489a262f57a5aceba40a56d343403b660928cd7a9d165f4a5bc289c0d28f33dac85c9c2a5c79b5ddd22c744a0388a5daf4bab84d7c77685053c912c9a24b5a0664c6253febbcf552c4ff38bbaf2f7e0c9f06e69a91cff9138c2745b99367e00ff6b6a920b1812e17ba44175c033df0e58d1b5c0b7d146f861b62e812ecbe99d638219e0dba4dd88089005977bcc90634c4dfa95f87370d905d32f613358fba2efcface0b9a414ce33b09e271a647b911843933c5d1008fb0717ab59739eb8eb844a4b34bb1a8f635c5895afa285ddc43720e78dc81eee7db822896bd9bd6ae3e7fe2988ba560d58f02592870647b94aad1dbb0d0cb60e28135ceb72e0a6f4b7893a56eae83f9d9a4c549d53d17c6a00f5d6c266d23e7a1d13e22a5fede3a7082dffb34296f8fe9f3bfe525ee1da81efde3aef9b6de8457a10fd4340809e1dafbfb9e2719c327a3c3a4c51d4d5600e8a01ebd5c537a4cd7c4519e963de06de6c83a9b968b01f79e08b5415c5a9d6a92a633d6ae969b80cbb2cf4d6d1ab2c3b94e7c12df27ea89bff4014d92add41a3e961006a194ae3ea4a6b38c2827f6185ae636f6846b1c8401289696fb10c765fa93e58d068bdcd8c9dc95df572f096d65f5de42bae639d41ce7e1ee0f48ba4faf856c0cdd728956d7e4babd6d9d6389ff41d76c5fbd6380f351b05a37022dbce0a6a47ab7168c82c77a2810c80b1882f825ebf86cb7f6d0f54025fddc9b9120802514c797d1d3968631dae95297a857890ff1dee408909223d012925dc08b7d1119fefca7466392a019d4121ea76c8b4c3bd103a820557e4b2283e262af32f1edbffaa253c47d5873bfd0219b8be86c7e64ada2d87ab6b7f428a7d8fb3ae09b05aee71054355eb83ad76c05d836a9f1a65511b1553927ef1b19ab1576d7185af61be6104de1df218918179c6321846085a83bd1217aa63d0b03996ac1fb4018a8ab54fcf635f7d5a8ade95894f0d407e5d4691920f21094c6f632f1661402a0b3351f168f16a13d3a31ad48e89230cffad272926487f36c7a2584c9387623df6227be8c96088db4a21c93b1c88ee756e960f60e614b30bb6ff757c20f3674a7ae7f6ff6a9115a0a6d444513ccc0be5dcd557430e0ee8db3ed5b3e8c405110500b9bf7f6eb7748de4988a1db94bcb16fe33479f64762c53a1e2965363452063d7bc14386ca7b4d46ebcf08489c64ab413ec0f1ddee8719f5fe978d38438ca3059961ecc8480908cfaf139d88db2facb5e7a88a43a67dcb0f97a17f9bd5b09b8369803ccc7ab6d41238e59e43762965814c10c36fa4b6e61bf2e83c0243f20ee8aab62dfa9827aec06f99c5c565c1bc75291292d3113503a202851c26d1a8bde54bb30f0301e555374b71e278925a2afb29b0209c08ecb89601bf612ce811a493abe2bff78e7fd02ee13c5db6b3edce7c87559410b9be3be95465468e33af224d6508a44728cdffde4cb14fb96a0d2ab9c7f597541f9963775c32ac613af9beab89e0ff7a5e35613751061b0511532b10b3947802901505c8e33bae67ce0e28da760af7e80b730811bdf17abfce39d35def51d73a084119449038c2b0f1c86d844123c6e71f28b7038053e279dd11c088dfa11c547a4ce13b19453e88e5b74962101412490cfb68e21d8952db509cd3a814387b67339fd04ddd2163177589146409934f0eceb10db2d90a9e3f6691eb75e84d5e66bc3228baeadcba200f3d11e0cae090ffbb800f5da7032c35ab572de55beea37258bee6f191addf01739a26efaa612991cb2a3c6d1bbb03de0ee1fcf9b7f6c51e452b21c0819a9aad93162eb2dcc189bf355ecd2c3e504713dab24bfe3ed86a4194611029f7f6216cd469fe1f7d35d56b6c8c2045011e238f9cbc0a19b8914d74329e2472f15d0b7d60511814ad2736d6be168aac01868c2a675549c849fe05e05a76f077130b46896735db5490277b76bba43545de6b8ecb53fd20398eb94dd884951fb48d5690ce4bcd0b836615cd9340ff0cdee1122743accfef343811a71c7d14d1369fa49ce47784a6ff8adc26c151edd4969dba513ade6a9b1f009e57c3d6aa845ddee275169ce58e1f04b564ffb6d0eec75f7172e5e8fb814cd702c9fbea8a783bff637db8667d4b6b48a264135bf60acf335936105abacff0351ba9aeac88e9522cf7ed80069822a7db1a5d8221d9492e02ca893e1f15965fb82a80ee2ec491027bbc8906e71cf931fc21e1c0865ee06a79c023929625b4d232c7b3e2e4a4e5dde28fab675391befe583c95dadae71dbaa43e09d8d65ba36d148aa85d1a2a35dc51719ac0311ea72c1237c78a8b1542c59de3b743087245e54d3111c585b5e5e7642f625c8d44c6d9cff50d8d071f6fa573df937d9e7457302d8b293d8fd94ebd3023c55f8b260c3454e93f58f16d0f451189bf41c9f9b91d3c3918adbf98e4ca5aa0eb6314041521ef880ce18f0ce296721a06b329bb5fbb3024e424b46400e03caf0105877465285fcb41a93844fb90b7fc1924883ace6ca8a37c9905068c633761163affae39d0ba55b67fdc6bcf0908ee3a42af286c" ++ }, ++ "transport" : { ++ "secp256k1Address" : "0xe23c5bba38d809fcb2d3384f210e9a6405beb498" ++ }, ++ "ecdsa" : { ++ "addr" : "0x48fcd978ac4d42ff52dd81fcd17e93190f35e5e0", ++ "claim" : "0x2dee91bd2cbfa906aefa3a8ae6e2de773f55dbd28e77bc329d28215183068585601ab9a7f9ff0c48095407474d502a3af3f059a666e5ed1e27468466d69914e801" ++ } ++ }, ++ "1" : { ++ "id" : "0x690a7fd66157e5b777256ea5214f634f61b3a72d", ++ "keys" : { ++ "falcon-512" : "0x09a6d094d9a3a0865864e9a16b477236f1ca26c888fd0c918db331c87a478519c41085cdac7e6cd0d89190a41a3bd6f4d6300995d591f5e22a7b7147caab1f9c7a85a4ba74d47c7b227326ac17535de039a7e604225d3daac7f75b9544654b73f79f5825825ad6e6c45d13e6d385a644633e1c8806d3a0a551c98f032583c95fb13997e52a6b02192d26b5a47fb22ee52999ec92b75c70774a4ae0481a79113ac72346263e53d5dcde708668d317dd00552d5a40ad47e59a501b10a50bdc52c5c2b2c920fa0e3dc9b8eca54b10aa5ab1168c88287dcf80ecd880a8fdec85b6d63a15b9f453845421a5d9b898e6149b60454828eb9dad6442ec62ad27ed72215014f3d17539085ea3f668b0a9183ab96e9db996801c72a0920b02a249911924f181e8dda515d114beb83b075ce7e7a0902a6971e31420ee4921f5cfc123f29dc7775017aefe99a7e326119cb925f6f603ac3bb137313609498d5a2000c426cb332c82500dcfd80d70a5e2d156844a683b313266af6d60216bd9e9998bda53c0028f387ebd21a5fca6c0607d54b1e95724746d15f25f16e45845926a83c7598646a0a0d3a8f8307c1a401b823f1656ca41e5499684150a954318da076af9131fcc93361d9bf0ae035f617e02cb5e1224a982b3591b24013ff80dbb61160d2ba4ce85a4260c8a3a3218e0ec869796b1b04a82079cfc0ac26da03b04a11950b2a3331ecd0026ea9737bd20e6ea3045b56e3c71278d2a8c72c8014b769da9319e19dbe762b1943e5a4be15aa84d0da831eddbb10bd05f35d55b6211d02a61c5d9247e69cab6c112acb568ea51f345a5bf16f84782e04220e217722da71d634e1a68b796376c8a49a965c592b87d06702fe42dac12da108d24ee42a109e8e4cfd3bed6ada5e3de50301696bab0564292864f1b9f47d5a53cc0c5f9cc3d57051065fd57064d08764892ef4c4a92b475184a4cb4ce1f3a0e6da0402414db5a9db34632b9717586e799b06e870b81a330da7be6a45ddfb000fd337a24a29e164449f96be015818c53aaaf09b9a565d7d9d735b9493885e7cb49a5f1985977cd6824fd62f51d2a1e60289dbaeaea148a44dd8876cb58b8ca2f29f6455f354e4e76aa13290f2979b78b22afa0e65c696c21497e94bf0141ac6298aac70b5ea843848a2264fc057abd3593cb17465e06d41731b7153b71f8f0f7a06d362fbd09845f0815794050460b41ad003c9396a86eaab240555ac8c75f85c0ab972c1a0b94b67b1aee2fa3", ++ "slh-dsa-sha2-128s" : "0x2b2fea4a0edd5dcc2f653eb2dd000aecd87deffbce8818aae72d7862b506bac7" ++ }, ++ "pop" : { ++ "falcon-512" : "0x3968f2999d69a9c28ae792a90a47363e689bd4b349e75c5f837181fc7b16d3d04489bbc32252d750d750417770630c5b65b88cef918ad23e33892a58458e9e63ea591596d3b898f65e1a5be3d36650c3d9834e1ec725426960d337b8f25878525ee3c3798b5afc9add5bec82c8e139c59738aba9ed5f42d11c886472e81cedfdb5b910eb73e884e0d4cc218b87cd9bcc0bc107af586c65b3949460a25892d9607efa341f232e478f3c9fc2d05f324ee6eb7bcddb72af371d47c36856f488872249ffdd322d3de7d12b62b1ec595187b5b363e36cc714b765f0ad5616488300f6e56811e88e359365d5698ab123b917bb32f56566958b154f6fe052b894ccc1fcd99d65d19e8117a8ca4887e01f36f181461a433fb9bbc1790d8b14e34a097b149f0c5c075ecae3501944935f3caa76f0b9370ebe6b90390b4d059f9029ee4af98dad33b9050877d49c3d4f2beaa4b5861a21af95b8c52f9ab4b0eb115357f5b1d25fb66a36b9baaa4d6cc5a4f5fb5462432bd82734d7393cd22c68f52493eb3434c3b88fa255baae5c46c650cae17ebe59827cd6645c6d377b3cdee3aa6a758ad3a96d103bf6ab8ae03b72b53f3aebdda359288c32ff5461a158962924a97a24af29f6c976762e8de9363485ada49c445566e71ac75379aaf7bf190a81c671115e842b5280a05bfb2ef3724bb74487068d5b5ab2d089ebea7ffb4381a7e96233f0915f295d3b71db872393bb990b9c74717bc3d72f6271bc248e54828a1e090f6da56de3643b083e9695db7d0a32bb42355e245e5cc2ed57354d82220b449e10cca1cbf6fbe796d141591d6f71e4eb6770a3c7dfcee509c3c28f2f1988eeca61833b6681e6766790c2a6f043b4f67e145b908ba7f03361cd9d435d054e11edd9667e4f9d12c2d74f2832b619", ++ "slh-dsa-sha2-128s" : "0x39254afc16b1dd8d4fbfff766819460253653dfc6a8e29abed55ffe91325afd578ebfa2dbe74d46b48b381e69d269b5bbe24ca1b85767bd71c744065fa47c646e3603b44261731b50f2d20a7a327e98b84c5ece73697739c8057f99d6ecbc54cf891649fa78b7bcd824972f3b27820ffda3629f481b1193b922cefc907bde3ab1c78b5ac97ff26986f3a553556d0b158e936450b4f41bf006c90a9758e0efb327f67408a7b803ede993522cd9042db4a672c89d4765a0fff8c6e8bf6882a8de432229dee08ae13def90f9fd0a40c99f3d93873a41d74871aaf407b0927a817b476eb93c645254bbc77d131e0bd35a2541248172993b1064d5b26b921396c8c1664178051810961039b15790862415338806329a45a266aece5904312afb1cfbeac1e816fb96256fc6e2b059c25af1966b0bf261bfb72afd8652feaedd6e0e4bf829a75188708ac9c623d4d6699281913bb563b96818f9307b66f7cf4aa9591e30c65a0b0885c22b5d17ff610f40bf2e0a9a32173b2fa7d66c14784402885d84f33fc75afd8f743cd10f5ad6dcce5b33a8f0c0365de2ce1b69aa86df2482a2c2d3746c6f0ee4e6fdbeef5738d809f6b0ef3cc703b0d29e93e198b68d62a5be657e69c33459fe4b163a5ecd72a90f1e53fc00bc8c698af7ae3cc5b07e36cb74088066a54138d6df4ef6e159ce5924b6903346a5fe115272cc951e8713d4b6f96f78d67a542c3bb402e69bdb3c2b06e189186c227927b2aba52b29c14e837b37798321fd000ed3bc0e386ad6e5d3a48494f57109322f0a87f7dd752d862dbf772498154804b09eca84c305595cc1e6654b1b2e94d5b88feda176aa144d3895a249754bb2ea99b2efb4f61b828f265638866a49dd3437c70016347d5aae64c79957ed394a85cfe06b10b98b6e83801728645529537a1102bb04ada4226688594cc28aefb24fbb0d1a60c7b826dadd23f301517e862c67fd88d0f6a5ac08e7f966ae375b468e57f01521b43fc24c761838c174ac106c4e1f435b7ead5e79aa1b303222f6b45c5515d497d8e7b05901bee96945652d304ad9ebae2153321885f19e7ad08c9da73ccc22a66c26c4cdc9360c36e307310714ac44c80887f42a2575305ef649378d76d297dc6faa904377b2037618f23b8be496fbc680645dfb80a76bfc060c6b2aee4ac5537e79b7dc7deeca0ca38041dc877b875cab1a297190269c987dcc46ff34e5bc154e2572695e463542be79d61fd5e96a4be2b07f5beb71b882f99de317116fd0b36131a88ff9707eb25594fec74cf76c2859ba6ba2b968d41479adf8857f4b0f4a26f49f0f04fbae0e2f3c2ab6aefdf01855a7a5a4b8bf516f4551a393a33d3920ca3ec403b4d37c2106d777e3d5dfa768614513885d857ce95b9bc3b992808e7ad71575e5e91b8107c5802043b221c74d73c7bbfa7a191945bbc5ed69e20016b16e2e2987818cfa80695e58950b0c1bbb8c474f861d1447161744c75d99dc8240338c43a5c19a8a9f46d80f6b4b6c1cb57f5a3350bfc35a0522f89e3470ccd71a458968c629c93336af6b5b091f569d1fc9492eb6b976376b8ff19ad9318f5cb1361954a0471419b4207dd9dace8c0545e74dfbb19ce3fdb5d456a1c1bff7383c6fd96dde3a92daf0ff5a315714c74711e3c05e0c59ba525c64ebd17fa20f8e143c5931b3c77da193415e6506c2db27e0e773a6a5b5d47ad95760b8d471d06d5dfe000a2d47e6e4e6abe7219750f1f7892f4e09fe88d13c2e3b53dc904ad58eaed856a4abb0c10830b96bfc1b5764f9e4b34b0072be314608fdea8c5005d40ef99806d4d3edb72e73541fb828d4b2adc38855e09e974293de25da6907f5ea97810eff1be37f88ea879e545bb5a70d2187edec81bd57a95c0314df4ad08a864156579d50826d0cfa511d335ff722e246151a7afce94126232f6bac89b13c142d29e7521479866e35b17c15f16ee89d798ee8bfac5868e505031586b81bfadef4aafc2ecdbde649f63e07eb6026d09910d9d3613a9871b5d1523cf5958124f96b5304d5225b4bbb03aeeef87753d0b6ab51a287df1e9031f56f755d3fe5a20f79b7f0f467fa97eac5bc09a1adc6ec285c8f80ec5c184b8b5eae326300a5bce0b1d757c8e4f27ca2822e73745009291f0d9032051e15b567511908f3ec68840cb6ec6018a9a0e30f2e34759743ef0bc9e12c9b32f29f4b70a998cb8893af2dcf17e0eb4f48e7ba367f68aea5516e7248c8be1d1f896d7e8446fadd9603012dc13126878300f0868bc512221154a5104882621f831e60b49d04fa8a701256b3a413b9db4abc5af10a3f8f4c26cd0b3c2f55a58c9380143d835b759bac7fef824515a18d79b6dbd361541047c79653ab4af5473b7b7e67a6755add78d5c14c0a9edc6c7dd42c3d0359d9f2f6961f8930458a34c4f12478ae45c20969c4c18654d31a7ae73902757b3b8a4eedfd16d6c0d22548d7b8ba77aeb4c1e3f3766b6ea802ee9bd92c5f98d00be80c15e7e3a82eb0d100436c398781607dacbefa98c87b3558f363b3ecb1ff313655838f864c1b2e0f6d6369bae4eb8cef98f564108ab2f763e590a9e9201f4e28ef1971438c30f4376c55cfce9b9910f448e31d06c2e456eb798476d56a890660e45616840377ea0574d1c066ae2fcc46f41cfbb511e5efc4b5c60e00e4846e157bbee5fe3bcd77408e3bf721bf871c05971a70cf7a13c782bb4afbdb1ef800a414260243fd828b67f49007eaf60b3e32f4e2b8186291075a0b1c0a528abb9da7974b3b1e8b20d337161ce234db66ce82a88ae1dc880933343961267cb4932b36aacc5f136cb474bbdb5e4c4be4cd74868775d80317bfba00ca4e58a39d04e63bb797de366c45efe2e356672f567ed1f7b2741df7543d6faa7227601eb7cff367d5a1ff320ca71fa2a1a42866239cc3fa5eba400ee4060266a05b8fe1e729908b95ba6aff8fd76b5e7df547df62cb89f0605c1207c869d7214e4e6972ea6e47b18235855d6f28265a737b4f64f0d215943f13d219292036c1cfc46bc61679f034919e4fea80d882a5121cb3096a50f2112eab265ebf75b607b93e14ceda4e08152221bd368cd1503ce375188d23514dd0936bf980d4282eaa6fe8f38f5eb00c34e3557ae363538a2c15b560b9f9322d1f17446e8f3fd317126986afc2c5e9fbb96f8ca7148f53cd75a4b845a28034c8679baf1f5406564b6e4b8fa8e681b5a9d208f3a1b28e84d6d52d4baa152524908d50d71d9c0d11bb5665c8a6bad669dbf303027bd0d534434f9e76f2c300326e25d00bd8d3bb1debe1c3984961c0ea8dc547e8cb83a8f3b044b673f4a08882d103d6eb143a9645a9a00fab6f1167a2c09015d6ff2dbe4aa4025f604a63eb32330f832162b6dd9364f4ad6afbd86c8d26f56d7d9028dbb3051c85a0c86ec0d7961fd6008f87dbe8347fd5ed1dc4c27285364f63650f161321daa83ad41fbc3412bff800c062a78cc5caea330cd58e63ea9a9d6de2ee069732799f52f49d513c658a44a2122b8427a405d706f740600f855130a0ea720f76b3111dafddf0e2ebbd13f60640379993889089ce508b1343f485457cb8e0c09760d3199b4ea940d584417259e41f2c66853ae4235b6f010cceca3859952b3daaab55da14adff0e421e862f138872c2577637b3e12b00384cd32fb3b9c97b0d59e51f2488e379065d79f5a834b076ab5b35fe4c47f2c4c4f43e622527abb8f682fe9f262d2883fce5c9f16b7566c4e078b67611abf72cb8a0263ba12a6c23b1a04458c759f2bdf6dbcc460bc5df48146468073b61aa5ab4a9c5f6c006f54f1bfdd85373f33af29d68580eba4cb6dd88054c81b3bb7f2be8186e380bee0b32a1b84ef6319798079828080361bcc27473a9634c23652ed6b2b2c8f8d5a6721551c780870f1787726b121263e74c9464a76282dca27249b4532e49455a7485e2cda4ccca823f62d3b2869602197a6f1ecfc9d92ab6e231996e603e81e3dc648aebdfb900a3d929502ff0bbb3dff813660c9d5a417d857c19754ee04e50f1241831517fc2d2a71c5e238a944992cc50b7106aabb5482fc7e0a2e6b5b11bb6845f34ede98a18d5f07759e61603de502b5eaabe59a4d2c69f4b0f8e73a9bc85b8950a54bd91bcd0366dffaa0df736dbbbc35d6accb5ab8b22a870374521f2035c1878718d7d3b025838da75d8bfa3ff36b2a10a3cdef1b150abf3b6be95a5c096a921a3eced20f509dac4ba43f2f515af2b65d3b2ebd0da2d7a58500157a666b387b1814d0a3e84f64d0fc44507b0b6792c0c6bd90ab62e0f75b66d50b6f842cfdbecf1fd043d642c5d5b5fe5cb68af62e6e23cc6f0f9b1cf3cbd0233ce48a996296b6609be1c9e7a027cf76615dd11208f1fde119099352cc17e1c9a22f4b71c3e628d72b620f3cb4bd40e4294ff8dfe19480b5b758b874a737e6092254638a222c83aac52fe0f66670454c313adb0dba2b4e95741d27104bbff159e999e23103c00470a7feee6f4a35f764ec81a8ef520cf1e8623fed3c06b63c022e40e7638db269b8add119fec50456b33224c14486f705e5b3339c6f38aa4ba6dec8b098c27447185ca50cd70772e5389ba703a4a9f8649946671a238e1f005aba0b3a18c8ceda9daf4cede6782d27931c638af3f6083b2bf10ff0a632ebd4dd528da3aa2b7a8bddff2901d902b26d518a058921eb0178ef08e24f7075f77ea0c0d0e72f29847ac7826230c0ddb5e7fc8552ff92c007e9141f51384a12e218da4fbfa9a7a4a1bf266aa975949e120db1b6755ff04adb07c66ba9619b40396072e7cc01dc3dd56f7a2f928a82c8906be416f6d5c41354881f9a6c66a927292f8cc2887aee86e90da32fa3bd9d72bc26dfd334f943305fbe4b645df83fb72c565f61860a480dc0f2f3360368ec3715c2c4a312bd2653051c8f29fc14e0c3d1f515e04b75ec02cac2aad8d411306969d9a8da08c3477eb6201bd54c6ee643d87a89c78a5c8ad48590b7a499cc44ccb812866a4c48ec2da5f1e0aac741464b26988459f3724ea4cf103c27e4a43e5a5fbbf94908878894f8b62995aebc20e632d924c82d9669f64b2093cfe023cdd1542c8f9d19e5e7ad6ed7920ba6834cb0cb91bce48fa94be47c1833c6ada4090509ba38defab7d56dde8168bac8021fb5a2aead00809f1881d53d26fa9cbc824488e16062fd9f68726c837234a82d518e3d10c9931295d20d9affa5fd18c0b2dda299cf1d6fe0c6e6959440af9b397f3441bb9881ba1d2df295d12686ef6b0bfe52fb2bef06620721374328551040d2fa434b161648b058b74df2a7ccacd7609b93421f44a136079c79a3e63bd3b4f79717f3c121ceec2c3918464f5619b1a2e83a7709fdf6d1004b0ee51c73e740b20e329847304a82802e02170db386e360dc6027aa7ba1ee35d7eeddb41ffde093073d92899d568bedee914627c8c48427376e7b5d5ebdab30e58147dac5638090e9c71921431f025f1d4e3ba3c68437555357c651336b326c9c519544363d5f4faa91914195314cc873ef97068d928a6b4e5c6ad70ea7a7b09b3108fd5696aaab800eafe463ee52a3f29e1bbe8a968e84b762484a13714ee260759b4492b749c46ab6603c13ece34e301c13bea57d9de706edc839f55b432b9299d2d6643817cd9d32d0d9ddbdbb23acef51992b62db024365ac2db4c432c531cc1ad18c807cf1ee39dcd842aa9a09b232cfd09bfce33277a8ed09953ab3b5d24e5a8a02fb4a02ceed705185880ecc47cb245665cf640ded4015b4afda053a5d1dff77e390c8105961cb3a954c28ddbb9efd759080dea99e94e69b03b928c8667fa4797dbb3cc6ed093bed107c817780f60729036f13346f05491fb837ef1ffc61be7b61d0b7f8dabfd49ec24cfcee088de38daaae6b4e740ab4faf16eaebf89962331a99f17ca5955b15dd1fa493b91e7cd218aebbfaa7d348b1ceea26951209137448caa93fa466ca32eda497a5b9a4fdbd23a10d9742e74c511a1648d00bca3ca23abcd4f18b7cdeb362e020c73888b76b83e70d26ee358c06933f77d1221a8ff0647200e451e971fe45c23aff60a88baf46f59a0bf94e99ab9337b0336ffacf8e79db92067d2b744134cefac1241dfda288f5c6ab293df7469ae0926c166e999ac99c8871e571eab03f82de73e9de2d8f4deea3724f795480cd47e304f27f2567cd94cbed52e06f1f1cf7af2feaeba8b95927eff950bfc26aa0cc3e46ec7bd5d4aa43374500f8cad4f153cb586620b9a0deeec2cb12ba48bbc8655c7fa70ccf94aa6891b5cc8a3c98b482d906d72e9d425301d0cc6fb4ec9c4a5bcdfdd74fdcef68f05fdb78f2a1c5ae32c28c43ee900738f31ac1fd337ce95966b3f557a727e0c3ada6c6aa61219d92fd5cf68fcd9b444f6b4fb6178b9c74238d2575f442a298127f282b5ad416cf6a365a214048489139918f93ec07f2cd864f5482c418c7336ca4590a7da8a20d33ffb7be19934c80b64f4b982a55b129f4896685534b83251d54e46a2971c0bf49ded9b13a77ade3de9a61f2204a46ed9cd7bc444801381994c8ca5a66abd70936f8d11e2a2fed78fe9fe8889dfcb979c9a3f11f2c2c1aa371d1e98c4fbdaa95d58c6b22410c0d3d3460077dce654a1decfc829f117bc407d06ad9ee6aa06bf818ea2f25312b1cbbb5de527ce9b5c5ddcb0df21e3442ffd149b24af5e59eb4d7e18f68b02b26e57fdf23e7af4fde3e672990295c37186ca67b2abdff6b46e1ff106f041279b61560ea2eae64649c65be22f9070c3239b0cf7929b0778c43dae5391d8d3b8c335ceac672376588a34d3b9c61833578e8d5a9e6e9f72748d860d7af98f7616431d1ae1ca20db3db6ec99d59fa98c25a1cf478e1b4a643c2fc9d3e482d56bedb1b7a1fc9c3e788d9de281c7356b82e3c9e1c9414a0d14cd07fea5364b6a22dcb3b69b6f447343822098548e3ca7e88a83187db145bda17f7c48cb00e6ce36d53e2d1e4c169569ee3fa03620a7131bd5c033062bb82cedd0d0ebc1025937b2d85a3cbcf6ef4458a57525a66244be3a62b582bf2b88549431cdce09f6407e1bee83d3fbe205f585cc7cf9c1eaba047a01f51e13bbe0715a9112c451f1daf6074a1af051d8b98863b6fd03238ebe295995d60e7a26d2f95a2b4b0d617af299133bf357518b84e942bc36a88b4030d91a7067e7a2ed7bbf4e9abda8c6887ecdfebda04dedabb9ea833123507835e0357ca1513b471da73102605ed03297b5e3eb7d3bd01c670f992a7f19962b706e8d0ae0f073638d633b34a1229b6979b8e90f2a536cb6024c644e1f7ef211451dc509e061b294c28be188c96246614a1fbf52db8d9a99f7100c878c1b9da98ee9e9eddf7fcb386061ddf46807c60b24d665f0fe7fde205f91021bfb87c8f4c89b5da254d185bda9cc2f48303b483ecbf934575aa45d0d58cea64662f0fda4d97790bbcfa237984cfb45a9cd611b533dc0ea997d191d14d307c68db318aee8f99544fd48fb86f041fe249a14263e6657a5ee732f7c5c9c97a8924bfdddfd75dc67da65042e711a3cc144f46d10a1a9fdac1b1b321eacd235299a1fab390df24acb739d61bd60c6907b9a3827958198e6e2b5a1c90cb9b44cf8db9b6e45f710d7a39c230ec9cd855af797555fb1d73492e29d17da0b6dac59c2ccde0715565efa1f62898c9b26438c60fc3b9f859bbd33a8e05e1d3d5a762bf19bc7c32cf7d4c6bce26fec6e5c8c537608a1c2aea2e1e5cca5bdbb45a8ed048514ef3d298e7dfb9c5408d941ded6220a44c184dc90c922a3ae31c9248c5f31627389770a59f9431fd0139c5ac0f08f69151a75a5a6a0355b7beab6be9829146ada371aa5791c861dc77598f09448af20deca73cf98a399f35c36f1167ba426c6cf4b8b9b8a22b961bca83e45bade098e20782a9f70bd54fb8eb6eda3acd3a5bbb553438cfe37e1f7fabf15729d6bd562cfe379d586181b71b3d3c4b360852003c4363a8d473198130642972eb3434c3a5ca9b497ec7000e821c3419aae75866496bb1b0a9ac6cf92f799071e06809f1f3f904cd18f32629e2093664755803f62f45942f5a358cb1e925a8694998cb14cfc52733c356cfd739c3976712ca7b007e08841639da14e429c102a8fba3191cd36c1c56eb06bf69afe3f2afc4ebf137c617faacda6baf5cfdcc6462ad02f63e8a5375288d0de5700d0f9f4ca82a65bfdc405d3f96fc663658f0aad91305b86ead3b21bd6561a40db0f2c5b0937ba5e1ecbe91e9c50b1dd6bd83a8145b033a7bb6a4ad4896e0ab160e8a52d39d2756b1c8d8570f7081ba217fd8803954290788882befde24b4971723b0ecbeea14d23c92eb6a0d7022a84aca072729d7ab1a88927a25f19a2086f846a44a2726ea26cf1b69c58243e219c756d06c361e1e161bdff0eca10bd30d23782b3374ed421f50cb66c9ee063ca622fa78c8cede932848f0f8f91bd7a0eaa324377c109808bd66ff463a72389c4b49f2e349be70d07fcb56b28549fca65ad853d70df66b587390febdf6b1881cce6c1ca9e9fdbc9f1ad68ccaff97234325d3c972b57ae5723fd73f975ba640f90e717e9284c111b76367c6797399452d37df6b8b8d22ed5e7dc1481a415fadc06673ce4eb6435d31acb6af68775436629a57db7a0aa192310e8427468e8e310bd3426b7ffab00110324c0c7e04ac6649b6f167fa8b928b3fe12ac162db3f2bc355295650fa2d976c64df69a8017034683bb4bd4baacf1cd8502dff20430d48c907107acfc4e29c584cb497b7a471fbde90aabab25290d853b8ebd2c0d49c2c201eca42a68a15879cf391671946319427b237472cd35431128ea7ab6d545617321592c07b09fff93e71596da30689b3c15368a1c3a57890e0ee5752bb4356290024fd1bd2ebfa19f7f3ca57c36d296ae61ec5581ceb77618dde2821460553ba0dd6dd68026b911f4af1be3986198966f90ab757aca2f5143f1937d09c3a08047b797781d1639db4030f9e59f8c5b71a71787cc84ade5a385ebceb1946177a056179aefb49e1f69ed0aa67901b2d6b2152b6c1fd1db67f358093180fcb8f96483fd35a87fa14825d3849dbf479be493bb2d1c639674bd195b5ea3caf49c2b78eb0e953dbf8fb909910c87efc6f9b6592c020333e00f83bea4bdebef4e107798f9a8e89fa5d063d69f88f31a53548ba2406407251f18c3d1ca6e392fb81a46107191e6d906b487469d0002afdb0f32c39873872a49eee649250d4d5d3a7687fde2952291c8ba78fd9b962060df12d212033303691b05eef0ae0e7f31b7e395576708d211d70281e9501618673afac20a93e82f060135e51b29132a0c9244551814bdf399b746651279ed135d162e366f39d40e3a49e907f72bf7c66fcb4ba75b1f447fbc3ae3f390ab4c10963d755ee188a9b0129416161995adcab12177976208e1c93ef48d3ef55ad22bbd97781dc7035c9f5fe25f47b703b1ed50dba311d24154ab05dd88ccbb5a8cd96d4665829c4dca5d5b22affbfd7e842ffe5e87bf4326f957392229bbc893b1fde9e4b2191a3345490d418e9298179661104f70bf6cf9a0094f9d37be98b82d98497573512d8f6fb4b0b0aa334a9120a5afef20e0379197ac7ec78da3688d2c9b590e40fcf866acbd1d857546522788d1f3ae73f330aad045c5bfd59b8a399ae626fd67d9797b32d6a279d42eec3ec8a2888258728f7c329c4efd0f71b730e57f9bd87204d40ac1ea6032a4b8ee3a338aad58c2f3c9795819af4cb652dedd475e5662d9c0cd23e72a8f4e86f1a63e5683c814a99a6595b779e5d715ac91ba62c1ae4ca1651581506ba80c2ee0d3f97b979758cfe93f373873f4775c882fb3b5815b9274595bf50488b935c82e0fb4ae4d078d30bf0843c89e484bf5a24d5de602649e336fb2b79da6131f96ef1b5f82cbd668f4599fc9a92b4e9ffe3468e39e4c8bd90531952327da74a522e479c66b7b1554c9a72a2e6db58fcd45588c9ff4f48be5ddc994913833b668c275174b9d862dbe8fd01535ff2bcff6ea030842ed3a4d105ba07feb0098e39f61a4cbc06bfa153c598c10c5de57caa413752878c7599e5db8482b6f275db2185c505bc0c9670fa0afe37031eab994120acb935bf9dbe6cee6ba336dce1b44732c4267ee77f5db890041e547bde486335b9a0b85d6640f6534d84b3729b3436ac1c0551d687ddd8da9abc18689e7e932d5d0e787ab5ee5f36eb53789b9ba2b71d7a4f7994e56b056d4a042bd2cac79ad12d87726ef8cb97342e616269e9f87493e95dcebdd91763b134019c0a76e8b12789b026ebd1d9caf1930010aa1a5c348ae2e6273c885ffdf8731b34d87c293e77e9ef14709c2e3b739dec85d5bdb8f5ebc9eb610240576435c8d222ae0c8ebe5844980560bcfd45cacff143a5c208add9011bf9770b7803fa90bbaa10f58d856250b37e481f325c538e473dee7863957121374bf12172321b9c99975078e43a0e1e40138f9c31d6dbe5e06fc881de840e64899c0cf342a806916147de3cc342832a9514eae9550d2cd1166e823f404a05b418e5f9ffa84352cba3007f9d37e5b00049d7c099346257fb53e86b919b45a9c6cd8b67cb3c4e383fcfd5789f2cc087d6b459e2a7dc96d08c826c43410b3df22021855c7d413d9cfe7ca79fa860918a74941e08511595fc9a3bec2e2e0c6dad05781c0a0d6b6609837ca8f78b0368b1217b121cd6ced8fa48dc131709434eed65523269abe95f338bc5e3fce0046ecb24dc1ad8c8fa68b5f9263361e4952ca1aee9229811a5ea85c9c4452235639d1eb8105ff88c048beddc0f7efd3690da8b9bbccbbcfeddcf3e3c9e3ea7b46a5b40098fb85a25842911e42a714c2dd0fab403340ddc1af9484843b33c7f5bed80fbecf68180c9b397ed85c51d39cf08c5c0336b149e6d1747360541e84a93224ae88c1b62384b938ae25ce17d656b9ae52fcd9100a40dd7793ca67357f3fb00621863a490373f0db49b1aebaff7284d450922f1e5243bb7fb5f7230dd7cb8db1e08893696908cad4a45711eadfce8b0b42a9aa937cd011bd5c4a8c3a2ec771b3ee4959eba5e4a17545d1c86acaa4805e4aad" ++ }, ++ "ecdsa" : { ++ "addr" : "0xa16c987b93f1b3c51fa8a9833c8932eeaa566ce0", ++ "claim" : "0xb0c578f123a8a0c96354a13f98c4c2cb8a67541f5ccecfdd0cb6e61aa77f7768157dfb3ba59aadbc03350577f6f31b4083bec30291a61ee98ecb3db2536f788e01" ++ } ++ }, ++ "2" : { ++ "id" : "0xa5ea2fcff9e3cf29d0c6f5f147b67ff24aec3bd4", ++ "keys" : { ++ "falcon-512" : "0x099202fa37d5e165b88428d963d2a224b8fc82ac0e4b3f6a02376f18218d1aa7d0e910e71586aeeaaddc2a557124d6ab4f9a44b9cad02166413cbeb14b364e13956ea326900eb2900802644167639045d76bbc4e051654cff404dccea94402141ad9fd992cef7a8fa6478b3e6f8912886e9edd1b34c29385b7e964f360e0fb1600787934486f461c95d577d2bc74c4dfeb969b4798565ce0225ad27aac052290a44f844ae233e082c97e4498a31117ac9d02f3605c856e2dde6f611812161f89cb3a54dc936ca1e740a6c659405ed586a9a963b11c89b01746325e39e645c72b0c7e4491b36a17d43ffe38d88c601a5976f5a9636c964a012bfbce5f9b371e7c3b38580d81c6e12b8e8f2aac219f96245d35b4f4afa6c94015b055703b8c4dabaea4ce2577482f5b34fa49e56a912dd58d74580b1f94e1d2056594ea64bcdb696b0baeb33c86b6544761a3ead9ba9888cb1ad51f7027ee52b21e46c5eeaf3f77bc0af7efdc87acbddda7dca00b6acc665002c26447e5b0e0bb5ba261717c68dea7f1576462776954d7249c2fd0886f615ad50d53960ca02d581a4a25517c050ed467c7a820bce6250a9ba2e44fd67fb21bac843bb134c95360dc1c50d54b7280a94440d018181a9d6374bc64d782c84471b47287d8ea748c36cb83cffe053cb89a9e4ae71df497871c2a728ef210903e5b7f39550d0331e15637be7e28b3a2fc05b0a9b0c5a06f9fe81263c3a94403d6c288a561288ebaf788bfe271a578a1a795a85e9d452b61ac204b297090617286922376bf0a8d67dd35fd705b81260b7aad30132b965e39bc3cd64d154c4175951704873992a814814dae5c6bc1e89a83dd91144cd1b88f6ce449900058afdc53bb44bcab63d30cbd6df115a5ee8f5380a127a160e922bebf7b408de82514b2e2550a0931e065565e8dfc389d454823a55b03e5c989b09e3791f656794e8379b7b4b1617aaa9770366d63a657f71ff40c69b1d5da518ef1e2aa42366cfa38e448563f6c2db5e3089bad5520ec26105fc885993630c10db357883f588a5a384cd6de688e1bc3b1200f87ed66ba3d4a4b671b2a500a0436e0955904030d76577aadddb8c1ed21b027f198c072f654c3abb086e7f185980f49d0e109c1a82741809f8afd15ee56a887b392c5b172ba659144a7e99e25ba19792d2a3c0ccb481822839c8c70c65c0943a2994ec9f6085b7ac64ce2b35489a72dd6693d25f2329264e063db26ad4495e3ad00f12df8cf914fd846", ++ "slh-dsa-sha2-128s" : "0x2b2fea4a0edd5dcc2f653eb2dd000aecd87deffbce8818aae72d7862b506bac7" ++ }, ++ "pop" : { ++ "falcon-512" : "0x3974a283855c2660f08a7de343c0ebb15dbe2963c3dd6e5167a9214aaf91483e511ba80e41ed58933631744da49a2aa9406f729496c3858c21128715719736ef2ef8a6f766308f834b9a8bdf37a9acce248e95d78e5acfbc0c40e8af2c52a0f018e3a9dbe0f7198c809efc71d5ddca55115c7076687a2fa34e3ed98c2d53697344d5892c3704416d11775492e393d93f8ceebbc8bf00ea6f8fb413e4481299a74232e53bb08efc4634e812a67b11f3c66f394c2c82857791aa912bb7960160921dc630444beb693164b57834519e33682542cd8b47f22a5562a0bcbe046512c38fd4909becd1c896d6d5cb96c3dfa413c32e98945cfb85f8a246899f6ca2a619530383d665583c5cae30bf4734da866f323c96a6725116ded3b79c527b9ecbc166753829b966fd75c454935fab98e7cbcccb2385011099d6762c320493e2d57aa50d85a9358b5a34ea74258ddca98c22c3255beba5306f3668c3a1bfda3a7da93ea9c27ec42b502647f0de2097cde4b34c9daeb5c5534ca0f0cf12f0d1dd4d8605d15bcd02d58c6e6e51a5436fbad2d6597ae2dbe7e090c8c3928ba75384bd09997e3f512e03ab81d4b24a4ea71b0ad1d5f5f16f72950046618c0198df20ded31541aec2bc0c8a1b38936a595eb7e30b8322942d24c6b138cfa9939647c65bfe7642ce716aa7db44689ab54b2badc8184641a0753f36cd32ed95f8467345df6e99274c5ab0f9725378035b2592346733283310f168b0e14e423baa6c917d2cefdb2075a48d0584785e03b2e8213bfb314acb11fe66b297c16e86abf390244e2b2885bafb7641ba86e20649f4bf4612f936319034554df58d71f0e7296dfc6f74c0bc0f5ac9869705173429b149fe47bdb29c27194262d94f62e49b6bb3e0f5d054760dd3d4e31f685d8e766be0ab0c", ++ "slh-dsa-sha2-128s" : "0x81709f7b1144f9f5dff017c8404c3a0d6915874e412f3a49100aa094998baf781b3813554da2507c6dac69721c353bde08d7916e70cbcb85c8aebac92c41a420bb72e3239d878ef704089319f11ed02fcc081216bd69c01d5c9f1b2df5c8124941a08e0b5bb0e001eb357a9c1eedf78ab65e1a0d3c37bde0b04ad42f051f13eb690960cb1f0918f3e2c6bb8d0268d5b152426bec82cc9df9c0859effcbcc4bdc9861b188d5f58a39f756dad13384b1d715df24d5ae8d6d867a14093417621892954b0b003623ec7effc1740d1022d752626472742b914ab7bf77131a5372d452901bdc13e7478525067812025da47f43ed6fea5e28a627b5dabed2dab313bb0ef2575c9c1cb4678e3465533086f11976c7210ae58968ec5c72646fa52cd54f61fc0d0f22ee45e69e21e25ef06feba51083454ff55a8fdc25f9b77a8348a9e0b7e7d9652914bab0446d10e3d449b656d27bc2d2349d559fb5c7e893216ad6b05cc5d3107125072f9495c0b72d03c0137ba0bb402dfdff6a5f3a94096885b9b2aa63c012cccc2f10496d9d5de2a044c730600c2f1bef829cdd8128f26bb0995ce91a54e3ab3cc24b03b482e4cd342aeff77defa4e1390149b04659e5d46fef266474aa89a81db88bbc7867f80424efac9a3145df2b44b8a70b10c748a9858e77189fa85dbb0cda5c1a4db3c1a585ce3da4241d404e4926a4ff5776357e32d806b632270cbef14615aed54ffe8ded20de50301364b46bad87c0b00f6f895a8d41671ca473ff978ca5c23851df6af08167916c5eb0f85eed0daca0c8cce14a307974924a44c458f7993a2d6fcef3e1935c943bd2b96038a525cb801d25a337526107a5e8406e1ba5d5907593af3d702d63bc7a4e966652cf6816da5c2dd3ace68f5cc554794affd42d4c64d022b54c9ce32802142f98c742e1ec7cd18c8079a215ea6106ddc76a79705db9f574a45be1a0f5d1bfa91274f1d560180b346c58ed068c2147b172af30c3b85f3aca5a4370a5b94142364d21bfe28de8012e252f75b69aedb4e41053e11f055805991cf93a60defc865fc3a1318418982feb7f7bc24eb22eec05a0023e56a72705ba4623c3c9187ee71502c86897d82d1e6c962ba97646db58756bd1cd934814d26ddd7ac0d13ae74c0654c1a55bef9eb7474f18ea1e18776f1eeae615085cbf7c7cc807708062a47320ae195cb20e7952f2d357a9c134adff063a276c6fb08d7e9a435ae0071a76256f2e6f043f1ef26a57f8f7d92de7e81c3c46c26015ad3aec2b8d789e9eb6e3800e3cb4000b2ce19ad80193db8916bcc3c22c78060f61dbce94f05da69df9cd7fdc56b746de15c3eec4ff7b194207cb6e467ecb518db510031abb9e36683d4e6d16d9f03386c017855425361f027498e82c0432b315a643ea873bd9c82a60a699547cc65247bd573760f3d63191cd813d2dc4eac926fe93ad981239bb9b5f1decab35d805e85ac312f17e2d925de220e3e34a98a92948e2c5f7c8bd7967bdf26d602ce474ddd799941ae8729b14dcab428d80222960f710de03792a21f8598a798a2f4154fce79e7b405be5f2c5f50c096eadb91c09ad8b97173f1be97125955d8b86ced4c525877f6a4727b9137bf351cac869eaa68264d3f348f6abbe7399d42c8d9f892d8ee47750ee02e7904b0611d46d5cdbee450765839a99304493d8979088b2e16f663c16196201059ee02328d1716311dd921be932440dadcc3b00d1aa4f57bebae2c3769429db44709e91ee8bd244adac252a0a56b29846b24fc0a6d81c14d766f4f3a40e07f2e76be8b408cc4d380a44d9ae009248c033ca792cbdb3b7aa7a5c8b01ccf950456787a3ac0dc915747cb81ff17bb986bf30841f9c7f515cd506a0fb87a9dd8558ff6b028be9d7b87fd449519d1cf1e8dfd7a93594645b635c469bc1a64a6429d59a3f46d495390730f4614db293757b71e8a8c6339678190a1817f3fc4a770b7f60aac2f36757bfe4fc7e6305ae6d2c3fabbf239807079bee138c209b8e7919c6d28c89d2c95e229ffd15d0faa70c0ac77210327e0c49d6d3819fc0d6bfe25f4369685c12c9662d45b464c5e5c241a26127de1ef6afdebe372e9ecdd3d1a94066eef2bf33e1cb870986e0d27970c4decb8b5718bb0711fdea5ae35445c54f67b42c8317426ba4a2a2f3fe5bdf67f92b4acf8d729a68c1362fe91ce613e490793910653814efa47a7db6177338e832eb363bfc4c7942e3c8d06cb5984080cf8f0acaf8551f18ab36621fa6d4ef6973f5a927690e1e5b3eb538f3a6118280cad37ca9ea7cfa7e5a24b5ee01fc98b07bb02741f7f20e135c2e20253e41c8265c115894ae33d0f18f294822ce5a4b2d1895bde7ec205c548c52f3a33520277ddac099cc9fd654174ac3a9380a3cf246c74dc3e847a4f4c178a79024804ac1be3405dd5e1b4f1e5097d7dc8e49c5f6646d56b4e6b70fbb7a6bfa2a42b389ab0a67750f2fff0e1caf18c7d46e05a245c3a45357dd97699eb40559916fe67953f702cbb6603303f37d6305cc6405b7f39c05ad63d162a91f032e245b3cc6b40f483cf5a5bef09f31eacb3effbfd0fba965ac8896e16d3c17646fa7bb722517eb7fbdb7849683d8e082901209cdcc51a9fdd19442267acf93752935f4e981973f7c9137a0dde8f241cd44f4188eaff6bd1c770f89370d457e3aaa1017545ee9913c8e821f998e562b7ea72aafa9d3983352c42e3224ff6a1134149e6c0972f3f5b9e798524ab5d7c956067d10d9197035d02823e800aeeccd830ea228734d503036f0eb3427517ef5270328773c8c19fb10bffd8b78dff1c62812ba24bc9bafbccbb1563754f803196797612e983c0e529d4731cd1b8c4f325b9110241a49d2a142b07b03af9c8c0f21e6c7560d0ed0d7b7fb76959dd1a02ce9af31a452947404d355d19093e4061524e6aebbcf8012ee88680a5ab4337a3e204517cfcf02e5f0b7dd17d56daf171ce910d1da62a8baff52b3c432270eb31ea000948c77087f9a16d2eb5ab0a60113891900ebf3a4fd50f5fe6492b03b301454312cb33100e8f7171cab291fb5c2abc7289ab390616364b35ed7cd8fcf9336053c3e6dfdd4bac5ed2a3f951bd24b599e97d417fd8d3d75c473a3fd39d60cfc60cc1643dc3c9fee812802992ecba7fef5b83a8f835c3605aaac5dc6b1a30b8ab2d3f7cf0021ff17de965e98945e65d6ff8608081b9cae901f8db3f5f4795e1943b500e2d5c751e3c3dcf6e133e3f03108f89b507346daa4e793b1644a63df3cf165b842ce72b6b82c4d2b34cd049d74f464d602de8e1a17a1126aa881bdd1e46494aaf18ca7d2771214f24810a2491a1bd5340a66e422b5caa0d99af2536f7b0d61e050c448fbf95cbfdcde26c011b4b5cbe0ed14706ab310e8494c6b7de256a1084a8efc7e7c46425c48fc11669e3c59ab4275a17b97385fd6abe772eab55ba80485b23c07c994e997e7792420d164d2f56ca81d23af5e330ceeb9a98326b102fd7c4928c1aebc07d85232f73283df607215c5399232397c27da072c00a4d9b889a5335425c8402c174c4a82e46bb47e44582c887efb8018858decec4827a1a8e0e51acf554dc925a759ed729eb218a770be9ebd40152ae05e8bcab0306280bf2e441c30c3e85cbff7c4dd80569081bc11b1bf4e901ce1771c5f9562a2b5f3e78f04a831ebe744d1f14471701ed243ea474b03448e4b894c1528298c9090102d69518c58c49bd37e9d09b272a0506917c0d010c1d552924a89b5e5085ea08050088e3bcc6683d277c112ad254a93bf6d593e161a0f2dba3acebf175d34e179e3d4affa9a67c7abe77fe741f86d3614f69d78d5424f06c5aa592604e5e17b325811734494e9e08bc3182384b21c8f9b89ab416125f29b7c5492e04007e7d257efe01006b9e0d9d2a5ad7037286c3fa95ca29f26cc8067aed4a6b09885af4700bea93c8f3971d617b04dafb53f2cf349a38c7ff5ac491f0a3de1c62b24234867985a190a07ddb16ae34c67a28bf24f3e62d5aaa70b96866e5eb545098ce5b4b2ee3ecac0ea8a364c8a1eaf2f9c15c4a2f3f8126339123693555c7bc64e506a98b4b9f0d77308e33f71c6a3dcfc2bcf7d331d889db6210788427878c93fea18fc3ee7e9c5c416fa3125630096529e90175f8246f906372825ff87c433af9fa60ddbbe54a44238278c3b2439b6b572dfbfced008765d1dbc05f9e5abdb01d98d14e748628c3ce197162cb2a293b9d7cf7b5775ab52a43a31d25fecac96f0daa371958f226c963abea16f280292e45375c6a4caf980cd84abca8f280c31e6355561b06b90b98efcb7ae86ffb1b4c2fb829c7bfc02d63b146a07af6b2c70dd3fea0d7e3b2189492051f825dd318dd586b88b0f69bb4adadcfcddb616ac24b2a6ebbff7dc4042b6b02872c8c16374b96bd5f2adcdfc75e94c743eb0bc4abcd1cdb028d840c8c89b69b5b917057e4f6b90055e6f903d8f023cea016dc706ee89f2f654324cbafb03b0b4f7016b0fec4319a19596e226bb1d6cafe41cd0ae4f1ad9b54163814ed2cbf1a6008964c1a6d8115734d960c0b978ef26fe911dcd1ab83db34d1f8a5e5288bdea20dad9f5e4364986ef95ddaa1bf75a37fe30ce3075c93652e746f49d0981b5d631fdc15baf0069d57bdfc28a27413d04884aa306f2c9db7fe288b6056d9b9c132a95a13401f17d924bb7b7ad44dfc6b371a77b0a23ce40045472812690ae34b0ee6bf7056200971dde6a133acbdd586dfb91df14d181093110b22d3e13c06adb9e5eddc6838a14ed6683beab5910fece340572b3109c9d09b4dab95f2aaa5c286cbcd9a413ff5b0765bb0c912dbc717dd13c7fe46b05dc0417ee6fc81b011074783b61f7feecfce6f8f4cc87bbd988430bc3ee68c9d06d843c1d51ad1f37a40c73d448786eecafaac7fd84e028d746f6b0689ee61e93f0d436eee6466f1bfa0ab0288a080a817eb31c59106217efd5ba43620401db5042e4b0ea0ce39f9450decf2d4d69937ac08b0ac9f538f3795d24da9c12f8e781961d1183edad10fea48279972760486a470a640966e091c7ad8c1bf435fe15978613e188b4bc5e0ed8afa0961909928d35cbebc8284110956964880a664196a355102b21e4930f4cbc74aaba3000838a3e84182a486f8f94a223369adbdd3060a424e0eaf79e97a5158289f513176c8d583143d612c7bb951c040bf71a4f9797463385bb9a8934885fcd3b5cd28a8296fbd16e9eefb600d5e9f0f1e61a35f202eed5042da1cc4631b9546cbd27b0b31a8a764bc4950f3bc2b725983e29d43344ddc394b7d531f1a3f8c299ba9b9672abe9dce3244aee6eaca69ba7357a046dbedfe0ca3ac137cc4c68c9582921a801df2c10f4a62c5ee6837d93e90c346eb9424e027177b6af5d676734295adcdf9ff1fe239b7d8ec5defba43a365927fa6d055375d23132e2e945f33cb0edd3c0e519c039b489a4bb5eb4b619c6d80cf40fb87598acc9164b748824c409573b2d80880dd8ed6f67f715178c52a6c4d27f6f8b7b183c25740c6a81d22c1d88a9b13d44feee20cdf900f39ad1086c53a2e853d9c8c9e987d5b151459f921782710002c602fc94c7639cda910268ebe823d752a2954289933f99bb6f2d5eb22b615392ac4a6e5921beb51a0af757cea3ea56d913faa1ab71a0601a0664d3beb4e6a7b0716ba6bf5e720662376d3a71516833840359a73a1a868d9da700d47651efc3490b0340226d8cc6afd5ff6fd1f684120ca9c444bf19fd7f55a159e06bdd202855e2824311994eca4a206478fc7e1e29fec619506e43ba77feb8c159f067b55a47a2d0fce452f0f61b2a746fdb7ad963e0c74fc06243b650496f3ea72ca06f36813befad7c20008d2fcb3eb4db2799a70e6cfd30d499b16154d86a1f1714e8f02827e367be7c06464eb8fb0f75293ff2aa2a8a04577043b60b2a41492de40a235b69bc6006e45fc651301fc300acfce3494c18710fab004601cec07a08d86b466c6e0c9f156a647a9787dc26c483cb589d2f1622b31caa07f32a2a878d9806ba3dee087949d8ccb3506a3110fe717de36cc41c74046deb937f878086c04279e16135a4f6a8c824af7883b3e22958d9aafd26f0ac57e2421e2722799d5638a2f42311a1f93869b972f6bb5f23e7b0fcfc8d15b4b5b29eed5fefd8a8e33d8bafa4765e08a1f00ce21487a5d4801b221db87e9635d63035209bb6e3d5c1835184689dfcb34f3864ab8f409777f3d335501c48da98d6d6bac1b683645c9e6ca9a0ee0e7dc57572b0051b23a5a51b113c64e89fe256dfd6143d9ff487030e6d48d8b0288ceee6a1c66b9a04dcb94a8e02f46954271d55d75ed61f22ce4583cf1899c0b00d8ec509d20eb1bf3663f44ad40f2d2f462a45c81322e3b5786a6a5318c9f1ba9606ee75f119ef398822765f548f268f17a831dbd5f20aa018e0e90ac6dbe4c353b03c8814e3823b4fddc513ce201d987ee7691f682ddce6fe19ec530ee5a48cf4a14de58bea44ef9dc2d6dcd9e78068ccc55789b8cda917d2321441280a86feb3a99d965cf894930607e61e3aff981c86c635718dba067f2ee9967d2200e453ca6fb7399e31e6edb5c71828c1e9afbbb4d2527d4308ad3926bf9dd9bf21d0a09e604b5382168d420f7038bdca5183b3130121260c20f71a79ab839ba47cb00451811a3e4575700e0a9a33c9a5007ec15e29548e6753c4674c48a7c940e2452aad50b2de471d7df174597c2be8790fa532919752b4e25aa3cf7ac5d24ce3c7dc29bb9593e0a6ba3d15ae7eb25b962ad7070aa0b0ee6f5752d2ba75a6667809d336b10fcc64b076a1dfea563dc16a15bf81956222387ebb529f59671928b0363e48df63cb753ba4acfc7d47c1ca52717d7f39e165b8028e6b4534ff532d50ea6c4e53e2edcc3f030168c9f643237286d4f4d79e6d0c574826d04432267b3e83b6d14550a5c3486d6c4f9664901bb7ba5c8eeeb71f9ad7564551d4fc2cb2a9887b4b67ca8bb47bbfb267a0fef98e0065689f3cf846ea8079fc7a4946c4775d47db01fb42242461b90d8ca064de876cceb1c81acfb3b0ae1df7884f22ac23e294d1db4a34f51cc78266c2fec31e4e302776ae004c186f935c6b4ea0848fb535a53a192f4d7cae2519cda8e329257864569aa89d95104cae0605e671601b513d3fde5287059e51e133b57fe822cbb3ec8cb211104ca8eabbdca781c331d6c6cbfde5d1e07a7e4480b9bc899ff81172bed01a17764cb4903b4b1dca91bf9766f5a017cc2cfb80b568169bfff2a0faec60c68bcb23466011d98e153423aca4084870817381a156803b032d0cecdda83df8cf3b1ffdce232cebebcfcfa3334066d4967726e10d1f422303c97d8ce863d3706846b8c3d611131817ad117edd929f228924644daa9127383c5b5dc7c86415f7a71ce3defe42c585954711d85e505d7da236e3f89e2732a5f1138a3228225572252a57d2a264f708f59ce667817426ed200e12138900520280887e4ceb1e5b35c4491b42c82dccbad0e892773e99f7e33344bc03885b55e812089c70e3cf2d224ce08b767a38c30c5dc0b83a8272a94d499d7796e9d5baf2511f5ff74a5c4af5943c0c450ecff4ffb7b466196894b2da7833df08979ffc7a8414960da90d02a64e266fcd1570b5666608ae345e9009abc0a3765eecc1bb4340525b53f145b99efcfc148f6134f61e99d7968c06241b5f8628f793f58b26085ee9df53403ebdd4f93278be4f108c3e13b5d34998fc375bcef2e31bf99d7b3fa653c472c11deba26ece9e6c2f9376847bf167a7d98518dd90f586bc77db402efb7e7a8eabbfa1facb0401793db5de20b4f4b2c4579017b2ed826d1f09a297819d735918a23de4eb7383a21bb90f18fd996e2f04bc7f207d175cffe2c332f2fa0e7e80e4383fc8f584d725126f382025da0fede837f5fe4dc647ded43c7530c1777c2c5ca2091123673b49fcc248ddb72bde28d557f919d0ffe93354ee68d854e9c5823620161e616190fa0d3a32f1d106c576d8a38dd64df3fb03e3d0fef034fe09b438d1fe8800bf5094f184e29d736e94d0bfb410cae39500e253b6c973ebd24c2950270d85f2aa71408440e487618d53fa0a1521de9e3e24cf7bab8b43e4a464bfe1fdbb0bfbd443d3ff45dbcaf761ffea019f1d835e945a7e06ed09e945fe3278fc3d3154d418c0cbc82612d3dcfb029aa807087324c6b46b60ae25d061878df415153064f83e3ef6da2b2149785e41805e5be0b96f61d315c5defe936a649d5bee68cf92f831e651e0f588dc4d86c48f36d5ccae935d40e8b0cfe6acb65ab535715bfa87a3763c4bdca155f7e1e1ce65dea089d7866a4b212e488223918c60049263a776c3a934af1edd04859edd1d393df0adb67c455a56575b44eafddebf6feb70910c720cd771cd1c09866f493731e8cef9484180b0ef67dfc579e21cd55641bda6981b1d5d3e2b664327044fb3de9c9b05fee297328e54eabfbe9917f3cd5ed9855f9c93ecaab0ea8a9497e7e1bf35322cafef0ca95a117b62261aae081191d67ad7a915f0fed459e4d27e944d8ebec31fd6d2062956f5c833b2a4ccb30814dd91b5a8efe9c152e1f5e68f41ff48e925ed9a0a78b33b43373a64d9c87ab2ad01b3807f38e72d8adc21808d831a888def2895e6e7acf1527483ed2dfe065172fade7750604a7ee62200c486d9144369a2fe72bfaaea3d7e3981e124819aed1c36f0dc9ce6f5b36bd4c5018493dc91d1e078bcb6dd0c96e46f83739ccc7cb7c9f2dc88edbd988df1ef4fe58d640667922e9a49d83da004db34488d09aab0cba8e2ac141648ec4cbfe90853aa3b94f7055522f3ff8c83a25e671456c977e0183d6e9d56da437dc8d60efe9f6f8bbc094b0f79c754612574ee8901eedfcc90d2981ff578a48856ebc35150acbf0538df7cc5f5a5d620ca47bcdae52cdef2952d8486bf23d903c400374ef6bd1dd9f4c1760d3824104c1f37cb7811cebcd6d18b58d9ae580d781dfd3f47b6b1f43fa8d98d7315fdc844cd40a6a3d9c3e55b4e655ddbcbbfada63ce0c7c2f174021ca80df9d692ee2ec6c68df4b20ccaa4305a95ee90b42dfe8cebf6a504a6ed504525a1d63053809f6e38b334013acdc899e842f02f703963ef760997199784fe9e426d31524af130e15e350d16355cb69985cb6989017a4872c10b252a940916414ea9bc84105560801ac77c7f400132b5a192365c1da6025ed7668f889aedf4ac2a664afe2620ac881dc072fd5edeb87b0f2ffc1c0fcb27ae9a62835292f0b51611de58f2b3260675a11998de1e3bf626b7d0b033c8f148779c54d9524e420268e949fa1884d56eaf0bafa33ac12829fc3d556082f5644a8f3a53c4e6181fa9831a404832180f06152ce01ed24682bcffe60026956883b050a4c43d33cdf8dc56318bd76021318c2427bd19eb600badc4038c5bf760d461543b36de718e4e91a0850ad2f8ea82c265842f614e99d70b385fec917dbdee81b227cd0adc0a5f4db5c4d268271fb739154420bcbb2ba33303d9f939da5d3f2803f5dbd2e02becc683b1c5f825b2a2c7332e4bd3fb9b41d4b07532c2de5772cec38f5e2ddf6f9926f2cd2c63f752d06a407723ff1ad4c3e0d11565a414de52c7e8c46bd913f9e2c0a53c2f731ce5851b1a14ed968a3fbbb9e8a55b93aecdf2868dc81d6c77a8fc9ddfd3ff43799034e7eee170b2fa9b0e7ab5076c35e5f3db3da00100d0712d05a8789af1eccaf37443408634659bb67f51a93057b14118021197c77ccb096f09a5102dbd64af86fc10a6a4699c8fa0aaab6a7f2ca63e95d7d950128056d3cfd76d6ad7404190430ef77803b4cc477d2d2ea5403cfc306ce3ec547d79f1c5f41547981629360f40158bc7c27215804ebd4f42bd8defb920da7d60b15c5a3641aa4f56dc54a14da0fcf7c1c5f238272fd75d70ceed15847a33564845685944035d55488c95d9113b148d434714eb4dcea337daf0b1dad4ad5926c5cac406bece6826b4f335b1b02d0538a32276a1df31b5c378f83f248a4398ac18a06a136375711a8935443471f44758dfa462c24ce9169182eff1698475a064c697b56510cf2dfc77023596304fbedfa865a2127f54a3fce0c2a8400bdf3e106b49edd53dc2f4414fd3af6d62ead68af57a88216546731edc26c0717b804df554ba3ec5d7cc39bb68613d99c6ac4e50df2720e151b37bb1f01843af17540ede0cfcfcc744871e2869f776c78ceb04398a7c9222d76cf7469852c825f53ada2e39c521df4240ca70129ef2d123f3f6efa138808386237d1b3b5a4dafd4429d143fe92205329f2062331f775867311970038cbde439ce6fc5425dd713cc4ea1bb5d0e36e97b75c031b138a3170a89d7107e795a0e052f56d3731fca334977d11e6e0aaba784f4366740649d28e01b9a47d26aff23cd6eee2b3a0e57a9cb8a8a9fbbb81a608a6444f9941f77757e52727166ee1bdef8c621a6d27e776f62b24eda9d1e1aae160280f011fdcbc45f995681b56b500a967de5a765c8f6f80336421e96e90cd251344e9d84f83cbf09176e29dcd15365f8892130bda24975b70df3717504a007a8d64bac7b2644931375a56df1e76fb3554c87cf6a674baf1293462a8140981fc7ccba0cd3cfe3c002ba9d443da991464dc27c85e6c599ed8f3eae56ca1a8aca810eec0472318fa7734535036292b870229e44fa3c6bcd79e2d72930b8da76f54b627dfe2b572db5946e49e482a128e6ab5b4cacf1a8480f4b2a89d889d22110bd44c3823e4359d9b21edb5dfcd65c968b17d2a56729f7bc9591fb5423a51d3173b1cab3de487564619eb4975af7d1882374c8c1f3652c433cae0001796b37098d62f9f5c8660d855d106388c38a7175fd503bb092e1dd3fbe9da79c977588f62dcab26b414620c25b6b50a649988fb6f177c66df6f6bec3e9e2c491e00be0641974a86fa730929869cac672a45c497cf7fdfb23fd2d4b9bff2551d98587af13867fb17fdb1e77d95b286539260631bc800bd27f3cf3f6904d81d4cb8a19a924af0dc45253d370c5a1e7dce7a2d1457dbf59eba5e4a17545d1c86acaa4805e4aad" ++ }, ++ "ecdsa" : { ++ "addr" : "0x5e13d369c8adbd8079272b624343ee1edfa4a560", ++ "claim" : "0x85bb15dd7f350a7178cc3b8ea7601c890a82b052c1aef38b249e5455de31d592531031bce1f03b71782bfc6293d7a146f84b834ce5da977efd1c1eae03c0312701" ++ } ++ } ++ } ++} +diff --git a/consensus/common/src/test/resources/aere/registry-v3/n12-rotation-one-key.json b/consensus/common/src/test/resources/aere/registry-v3/n12-rotation-one-key.json +new file mode 100644 +index 0000000000..898f5b344c +--- /dev/null ++++ b/consensus/common/src/test/resources/aere/registry-v3/n12-rotation-one-key.json +@@ -0,0 +1,50 @@ ++{ ++ "description" : "index 1 rotates with the old falcon key only (slh missing)", ++ "chainId" : 28001, ++ "requiredSchemes" : [ "falcon-512", "slh-dsa-sha2-128s" ], ++ "ecdsaRequired" : false, ++ "previous" : "ok-epoch-a", ++ "expect" : "AERE-PQC-REG3-12", ++ "manifest" : { ++ "formatVersion" : 3, ++ "chainId" : 28001, ++ "bindHeight" : 2000, ++ "count" : 3, ++ "0" : { ++ "id" : "0xa5ea2fcff9e3cf29d0c6f5f147b67ff24aec3bd4", ++ "keys" : { ++ "falcon-512" : "0x099202fa37d5e165b88428d963d2a224b8fc82ac0e4b3f6a02376f18218d1aa7d0e910e71586aeeaaddc2a557124d6ab4f9a44b9cad02166413cbeb14b364e13956ea326900eb2900802644167639045d76bbc4e051654cff404dccea94402141ad9fd992cef7a8fa6478b3e6f8912886e9edd1b34c29385b7e964f360e0fb1600787934486f461c95d577d2bc74c4dfeb969b4798565ce0225ad27aac052290a44f844ae233e082c97e4498a31117ac9d02f3605c856e2dde6f611812161f89cb3a54dc936ca1e740a6c659405ed586a9a963b11c89b01746325e39e645c72b0c7e4491b36a17d43ffe38d88c601a5976f5a9636c964a012bfbce5f9b371e7c3b38580d81c6e12b8e8f2aac219f96245d35b4f4afa6c94015b055703b8c4dabaea4ce2577482f5b34fa49e56a912dd58d74580b1f94e1d2056594ea64bcdb696b0baeb33c86b6544761a3ead9ba9888cb1ad51f7027ee52b21e46c5eeaf3f77bc0af7efdc87acbddda7dca00b6acc665002c26447e5b0e0bb5ba261717c68dea7f1576462776954d7249c2fd0886f615ad50d53960ca02d581a4a25517c050ed467c7a820bce6250a9ba2e44fd67fb21bac843bb134c95360dc1c50d54b7280a94440d018181a9d6374bc64d782c84471b47287d8ea748c36cb83cffe053cb89a9e4ae71df497871c2a728ef210903e5b7f39550d0331e15637be7e28b3a2fc05b0a9b0c5a06f9fe81263c3a94403d6c288a561288ebaf788bfe271a578a1a795a85e9d452b61ac204b297090617286922376bf0a8d67dd35fd705b81260b7aad30132b965e39bc3cd64d154c4175951704873992a814814dae5c6bc1e89a83dd91144cd1b88f6ce449900058afdc53bb44bcab63d30cbd6df115a5ee8f5380a127a160e922bebf7b408de82514b2e2550a0931e065565e8dfc389d454823a55b03e5c989b09e3791f656794e8379b7b4b1617aaa9770366d63a657f71ff40c69b1d5da518ef1e2aa42366cfa38e448563f6c2db5e3089bad5520ec26105fc885993630c10db357883f588a5a384cd6de688e1bc3b1200f87ed66ba3d4a4b671b2a500a0436e0955904030d76577aadddb8c1ed21b027f198c072f654c3abb086e7f185980f49d0e109c1a82741809f8afd15ee56a887b392c5b172ba659144a7e99e25ba19792d2a3c0ccb481822839c8c70c65c0943a2994ec9f6085b7ac64ce2b35489a72dd6693d25f2329264e063db26ad4495e3ad00f12df8cf914fd846", ++ "slh-dsa-sha2-128s" : "0x686b5dae4aecd5618b95c3b2a5792888513ba49dd366ac39b7431ef403e04963" ++ }, ++ "pop" : { ++ "falcon-512" : "0x391de378d9ee4e1d810e6ce145b1819f1b73dab7f6dc2468fa65d1ddc8e2a7e6fd8f185f8945700a938cc0c5afd87bda48c1b8167c3e6607ac864bb2b194a368c33cf8ab6a5eebb9a704d4160b068184264c2e59c4f82b9b4eaa9197c3ba5289c429e0f4c548769279daade1286d354212b1ba2ea4818c974c17770dbb59b65b3b9f891c826721f51a7ce14f94e2ef4cab868cf852ed9bfb17cd33ebdc4d688d6ba12c74aed2c8104d117574642af25e9bc91ba3fdabfdf1ed13c6e59fa1a0a4388925d2254195c666a6c235174a73125790bbdbed463617757fcc17cfd32da7c7f89e755f051aaee186665d9de393a82508d15f88db0271495c959bda6651a81a04dfc2103364f95f5464effde48f3b7ea80af9c1bbee99c9d39b0627984f09ccc6a4c888d121ca34e56760b1c3178e48607325676c484f4d666681f0d2454f7fdc59cca37136c5c06e746987e6a116728f8b0ae1ae9a32efdfcc956fefa55577ac670bc3d66016391bbb833d97f91d3a78696370a6f05efbd77cd50d4697c3df5699277eb1cafc1883776d9ecc72a763e5b65dbdd184efb9696cf58360e73f2d4db5e8bc6ad65bbbe7a8a994f5073fb4b12ad9b5196c450e27a53d8ca231f670966a238a6223b47d90990b1f6796f93eae971d4939d99dfea29d4ba2e3feffb97c0b27d6b6d2ee10751e75c658b44ee71abe9230f74a0d7f232329b165f5b2a3e584dfedaafa9ab477c0c516b6553c58797421f8d1e9236f992b61963c108752b1c43278a9b910926b396292fba67211e9a16b88aa9bab7b6b6db29f30ab5b7ef1568d46a010e8a27144a5e958022be5cf6bf4305f14e10781323acca3bb1d6b567d3fe5f652661dfc54d71ed9e3969289c29bff0c8972899993505cde2fca11c821d9280abfd5c20d4fb53380", ++ "slh-dsa-sha2-128s" : "0xee44a0de25b75a42e32080200c89b82e2f89551d44da272720c816fb144aa42ca29cc7a0045d97c82676d36286a9f1bf4d5b9e44b6855d90f25e03e3370cccc7665f3c7fdeb6f9565b76745a7652f70b7cb18989582559b81160fa32c7db7915f14c657ca37224955d174cc69de41774e4ac576f362306f3383733b322f8b333d9d0dee44d80e36a86491bfb7441a3c66809bc600399ac9788b4d7796604d4ec423c40dc1a6fb2b02db9a0d35072cb5aa617ef769006c504052596186ac0d504561c815617067f669b29757aed1de7a03c9c0410fb8b040dac268aa95232533eef1f69cc0100b33c9726d55af73b5d608b501b0470c4e9340b68251fc645bca481dc2d375de626580faa7b7faba8f8a596f795481cac23240854839a1100cd92a6410291ccd40cfdf1f70981c568b32904a0ad649de41b32299dd5a8bf50c35e5dbbd474c258946881b49e335e01c72ab6654741e657bcc5109fbda7297999cb4b272302739ee07cff0d1c9ef454a5dc5403cb7c170337336f94d56f6ccf563af44bcc8382de301720076a7ac1edc1ad95dba129760d7e9cd4df609bb8f7b389e7ab1e85e1b54fa5e3f2163afd7e24c5e5eb61a9e8e79dccefaed30f5fae83bdbd8a1673b36ce894891720b476652a26401e7890af9199bfc74fd0aeb6622fed8e488b8151a6c51a11bd808702f945ae9f9a016bdd94f45279d4765bb376df7fed5506b52b74c867c087c3386f74b130cacd7bcb4e832b697b50c796fa8fe4881c3f994820799417885af464f4f1a85989e5e3b54c3bd878a7ab054bd08c1ad850c96f3c0105380323908fdc94771609b10e489a8445f751f75a9b617cb1aec4460be2b53920e52f7d85096065fecbc6f19daae458f657dfc894758f3d9a6519fb4276e16b38aaeebcefba89a7686546901c57a29b95266d7ab87155a854ba9b269ac94a279e9c4bb38e6a4928cf6fdc3984b4363cc44e0e3cd7a7edf08388b9ecd5a04c55ac26b98f98cda79cd3f402caba28360899cca559be68d7a825022f9010e65f9a6564fcd0ec1cc4c0f4029086c90288fa83656cf2ca2cf30d5c423342cd15b9197905e9ab30a9d147aa2599abae71070e40058f0787ae39f39d6e5c1a8184b2cb3b1e6e45c40c61d46af8490cc9af6422a439f16adfe93a3cbe88f63df5eb8fcde9ea111ca96ea7be416d030500f2c7cf967dcaa4d3ed76a613b2bcc034ed3aa84f35556e7a65a8798825b576236798318034204f041dc59a9f9c407d34c2ca2d77470700ed6442cea5282ee99ceb71c6bf074423dc0785a39b89b062f89231af868812777536d0b144212d5b4b6fc7b87ea04fcd6f94438704f985b746a13dd519c57260f87150db4dc483b664944b9e805197df797be099940fed468b1e214ae99a68e99c6b5cf3d30fdbb1b3cc009ea58958eb4c4a7b7bad6b34fcea2a87eeafda01dca5223458affe54422ca70ef541ca8437171943d5bcdb70eca8de02b93098653160cae52f4d72fe5a6a7ad51c6465388f0362e6e72a3c96b9cad2248e8d9a2cdf89747444c7e51e2f89eb19daac76da37180e4133e0dcab15fc72c7bb90c1024d03eb2e630fc6d2537a101961b388e32ca5019a626b5a23914b06e7822905a5e3c21369b69fa63fc9f43cf7ecb6749c668c7a940b82f88c71802ce6e3c68b5c10c9249ba356bb3bb0539b581a8bd6ca141e5dc2b5932251746c1fc1c3da475581f3e3717f5d905f5ff3c83f1523f57cb750dabae0404beb55aba1105b995268906131835718cd43240bae9aecb30c794a8b186436cf752179b1de65b2a87917147612e3c95288a3e816238b3fccccae1da8041b4f784ddcb3d37ef3f019ef997bd8a4e172d397106a5adebb166c5f565016bb1c5f7f1a0cbb5bb22cd642fa4390ea640c04a968fb5a49ef929df1cafbb69c124ea58b31bf066be388d7b6d4c52409581da785d6447fd72b54949e4c1ad08fa64b520f2b8df83bbfa417952b87fbf802652a65df0d388ea32dfcab3227f645b6b28b66087819b4339ad171a48760e2bf90f1a01184389e23e7df583eab7c2dce385bb7a4d60ae5573966f916bb84aaec6cafe710f839b103532f9a7a556bfa116a05480386ddefa2858ac7ebdb58664a0e633a53e1685d71d5aad11f5eeb3d9ae30ab120fb88f96f383bb86917b72e02768f071ffca7e3fc2ac79846a36f6bd72c58aff03f9e87fdbeb65c8ce5976255227778cfa40ce0eee943b66a382e172abc814ebbcb0bf49efa75f87ef8621d227224b7be51b73a928c23a8937570e1a046bf1fd4c6993a9c14e552915953776265f78882ac8302f70900f9d612d2e7b7dad88cdedcdce7e615baf89ef249d6d535f92a2ec90a7435785f4d0c7a75812b875ec22e638f4af1705cc362ecf52c67900c888d068dc6f72a161013c30dcaa49cbf25c56e8937aa4897451061dcc7579ca99a25348e76ff121983444553419e820a3d1a41744f4227dca054c454a6497e0762155e2a06d17acb44ea55f54e4d6d2e1631a63d9494cf69c38ba66deb9d95c0ee01950dff8e6a5d1c46fececc7027997b8ec626f8405ae99ac20600898fd7fc422e6cd3f774b4009f371ce38e1f089ec93ec0a48d6bfb90ee79c3bcff321eeea33a44022ab910458984b75c5089cec0d8beec20c4c39311b991154fac7c0461b7d667488dc9f0f5497cf66166782e2dfb69a71031fd0251918e4c1243aa4dfb9fc2b6123b4f02f436c0f8737a6663af2b99fbd22c6af539ca9389bfb4e55da2c9ad42521ca6978f71991f53fc8cb227e228a62f3e22d7c3eca8ecee260e55084ad3ace0d6379d5eaf82bf6d3b69c4e74fade4210114d95b41a4c004858119a9a9b178d5a0cc97386bfed0dc6edbac5281c2842951a0c4d7da10207523973c676b8e6887a087c1c2f156970cc6db9cbd3c8ec1c9c1bec41fcbfdb4e8929b67e6c1939bb990ee2cfec3197b4ce824d25a7b4c765945e85ff2b096037adc4dd763b87850fb39aa98f1d395c9353ae3b5b53842a7056c011fb690e856401fc6f67b1c0a5414fc229284e74c230ced260d4fafc5fad153a5154d35c3bf9c559239ce18ca9810a1254a0a6c2960a53d838431447739261dc3b055a0b115914af263ac9fce2b512884620451156c40cd84b7bb2d449aad243a8aea3859412476ddbb5eb73028bfc6b2a942839e363262f94795aa45f6579680997d6acd7a8c8daeace08362fcd420f2f8a96801c002361b942493cc5ae79884eddee989af9832d55319ec033956660c5f11b9fbff9f1410a18c0e9a38e9261bdd13bc392a18a3df97aa33e7f59c125f88d78c86058f3c7e9a9d3b37bdb1e05d90375de0090b418de3ca761560f079a6ddf328e72cd89dcb63c9dd0357ec736782696241e2095aa6107a8bf7bbcde26d5d14533f28ddad7fe1b3f0c181c0e6d55204f6ce79cfc557cfb2d54cd2f33adf17a837243b51705bca7ad8cc452e5340732e678274f9eb532bfea122cfd2959b2499ad25a18db7dc387e976f8b5510821cfff778be799b80505cf38ab1ba6b01561ff81ef17f7735a1ed6a319a7f571daf92afb7490fc17064ccb6a8453ae6e66a2afdcded0c7359461278c49d342df84c43a0607b7327853db675e4c9ca95c52ae013461ca0763d157ac992e219a6683a547c32374631b53138676f50ae0d30588fb25de808e1d9efd5fb9485192428477c2f64fcaa862761c7f5505cc650910224400e2a2db13fbea0b0cc358d163c6d4a8e6296e4c9554078a55f23e60de9bea12ac199cd19b97babe61b2a3b853860b4441ae8dcd85d59695393816c64bfc074e945452080e15bcf6776cbb6b251c13be63932702468679b2bd7e1693a1d910e1b62be91e177a8dec8e4d7642e88e513e3a871ca502854ab0fb7fb8a099d0e0dfd73064012051af337abc78bbbc6fa2dc7169ebfde2d40167048d78f12cb5e7c130a2137a0b26922553f43aefdcdcec55bdbee0fa752a4787ea9d1c75d1bcd9d28135515a0ecfa9735901a0eb89f915d036e21263f90606f65e62f6e5c8237db14d570612611b3ceb4d026ac13f473e5706cd7975c95d49734253757f9c1e6aca9261cd2b95722098c5f7c74daa6c926ea4867ab54e4605a15bbf7ab94348d9b45c31a1fbdc7f420cccce25abb4249cf413008a01e53296318414dfac822cdc0bfc4298273f65cda3fcd61236e255dedd879fbf20b8c4843e27ef413c7a1ce2c714c88358091abccd7fed337a7d4f725ffbf7856ea4694113d605b1ff7b2bdbaf60f7abf7d43eebb1e82f4b6b7f3f8fc23ae27b09f78a7a3b324c7790431c800293e08fed2fa49aafe8f5670d4e6bff4cf6e7924993d6e18ad87699da99a2f2ca9f3c7b44b3b61dcfa5f041f7a6df94131b8e5c04069678541c87872daeb2943902afa6ff4798e45a75659568a02471afde44f8e116fff4eb7c16053a7aa370bcddbf5229c231ef8f2e642c1a88f90e0a309d24a3ab28d3adc176665e522cf5bda0285baca5bf2a0fb4c0fefff3b8ea1522c9ef29342ea57eb4f16d69bcf948d66247ed2f2cc4e567476f736d170c98398ac7c0d158f294ff33ec8d2794ec1929c57ee6d7f46da8e40337a2b380717227ed82eb13a14d129069e98cdd65bc34472fe1a52dfa7e466e559705c53d73d97239e38bbd600aaab107ced36fe7d8ef2387a05d8548a48a684fdf02b984022aeb28e8c5eccd1941ae19d2cb12a31de296b4fd1409266c43118848962e9e59a41054a52bf2f20b09eb4e77cca72df70cdc4d712d5c0313ddf9ec8df2d901145341b3ccfcbed77288ce3e4afc677ad8681c746eca02e7f7538d0108b68a922a21d6a8c2cfd67d8849ff5779de1c00588133309d4158d1738e508a1a2ba3351a46fd3f86339d66b1244bc2788de3fc60144d03c08b0ef08914088f9ce947d2b230ffb9ce176a4bd45b0c8b100e17ec7829eb1ce10b1a514b5e33d4f40792f0a300a4c3ba7a912db8e19cb72ee02ae8ddafc2caf116df905640d0cb65cd0c61d38e0a9741d3dc2b7677e8ec051d329183c954ff9c0c2d8771182d5550a742ba8147ec6571bde519c2f57f10aeb1c8900f8324f017f3b1dad92fb0d19a76de75c0c7cb67d079c8bc0bd7355fa25752d5d00ab00f9ab332aa23aaf8b5cfa4d2723b2020c9e494208c61a76e18c9a583172d6ddf544a327c931e8b908830e46f184998fc0d34ebe767e4f5d06f99804759c7e2b76a8baa302d6950f90194b0cc694a0d351374cd028ba6b0414377a850ca2f209d13cb7daf43d14f606a0e549ce14189023fc7b45e2b095a3f45930a72296eced3e2da24bf237959c0b966bb88a3a9818932b1cd41e8ee002df515ec94901902b2e67545dae53e08810b99dade7b579b847a6570211687a62a56dcb324bb442c4fc22f9d85e54b3f939937daba84c86fcc36c83ca87de70fc7f4afed335e8f9aae027e854e3a022a053c3b22be3617240f1355be9af3f4c8e9481005cbef07bf1380ddc012412c31b221275b56c3ad52cb2f7a9b340526e6128416025d4fe497f2d502070653d36f924420c0844b5560a8728e4a3be8b1ce67a1541c00e97aef9c808bd77af5aa280690d98f5ec218bf5c9d135d85069405b82c221d834b8285402f481b7d51ecdca91c4c2b27c12f486d382e0c14ec23c2bdf33ea8ff693af551fbe55e46bd84f335a68646bd092f914da4954c57201d7e812f4974a553f043ace9c6ce2c609cb4d90dc1ceacd5d610cf4723024538cfedc1bb22c9663ac541f89f97b37d2e1b4d8073ada1596e684b94e74c2c2f0087251f1eaa6789ece436b2940d3285f297cb7482aa9b8c47118a0b1d2031fc311689828b64855bc17306529e4b0a3326438b42698dd4e2e0c2f624aa510a2363583cbac47fbf9974925d81af9534d0ccb41e2b445eb19569d703cd8ace661139fa344a5e097290c233114370831d4710676f7e93889ed533454928333655b06ac5ae67f301f2b7944d769892ed76374a1f3861c8624b2a302df1a2f1a60d41e61379ab3681d8eee152c251e1b7b0806aab2f287338b752918cb989d864e9acaa92944f5194f8eba19a18a025157d2c3988163baf8b7ca9060edc2227ade8e05348d86d18f9eb633e4f06ee346e4c2912ed1c763a75fd1baf32cffd0c856ff9b44f1470136c0a8ae0b88175a7e7f993d8469cc8ac3f643aa7db36992cc97011be0a42ff1df8aa7cd82e260e05fdd67304644335b386c7825858a438c51b63f877af005f7d95202b54a2130a1f652ff7addfb798daf4415572376fdd910cd099066e8d2fe251a907e41bb950e960fe5116f4a4fc6037273250569b41ac07002ecf3b4b63f8b853f9693badd2e8bff695266095f4b2f38ee4d60428a45e7586d9d47c01c12c5e18d1ca9afedca6f03384567ddc730fb8fed27516eb7c54135cc7447af831f0c37727997ab2b01fdbc5e12c112aa987e95cf5aaaf44be14bf4882f49cd84894d555655d17aff21f077b2cca1ff0922afbcbf4781145cfb87df585e6af1955db04843a763fa735d33b3df836585c5894e5125d500673d5e4d0bdf6708d8d28c80298a9bb47c7430ae8ec52285a4c14371b3f8ac1e21306b34bcb0c1e3aa7a8dc8955cd9cac32a0f69d0fa0aab30abcbeb2c21d655ccdbae1c2040faedfc7a5ef29cd5d9227908335ebd257ae8c410b1916b9a5bf0e72902c2bcf701a18c1fe13695a8435b0d0129f3db883f428acea8b7f274a629865f1849d4c263a1536421875ffacf058f0128f0d012fd60f2b3fa6b71fbb96f3e1e33faa09b1d20b0919018e91a6bd9595e9c16d4fa6665c4d0adbd77a59cbbbd587029a4f306c887277a7a27748a6f289edfa16c7e4042fc81355b85a994cc6784f5fde054f188b9775836594abd82c1309a66db4388ad49f60794d8c8e1fe279f8965312a1e23c2956427bd6e289e55ec728f66c36526d40aed7c44e5352fa3e2b5d27bdc1f7b3bfc4f095d002bc8e7b2df2032daea9bd3e0bed2733e7ba13c6d8b45c492becabbef0e8c62c257480faaf6aefede888ce1546046f04ce7e06936cbda44c5f33c71c07b53fb3ac7a72c3770838471aace69f7ea454d2980fb5462173aaade7964b888606741270f92bc18950284d013b692bad63ec3726d8f6596788a032eee6eba08eecc836202b06ca43fcdb062e65f8ec91f7400963bbb8094de4b4e1042e040e81130a3ff037e1b7e947b0c3e8b7ab5b539f8570ec2cf08971a1bf0d4f3e8311b5c625b7d032fe2e0603ac1a4824432b4c7bb5afa190afa30c36f168d196fc89015aff8229fd4b299206e8183897229e95ba06324edc1a9ac81aad786d5c9d38c87c48fc6159934a8532489f06e1aa314a057d91c0f7218861ec241dfccce63d60bfa624652795229fff21cf5ca61ce05ea0ad6a1763173675377d1f2427564e397683428fbcc4b97495735d075f84b289b73389a1fece959f9d9b4932f4d33a0907202c650ccf65327d24cc24922d0d675fb59621e2bcd2eb31ed1ec5fddc96593d4f936ad42731a50f164e404b93920283bf9fa43f8be5878d18e07cb8813914508532625f71d02a615bf47018e3b3efed72d17e0c974d33df18ae70e3a4a743ac3c955d1c366bc94d789c90a8b3771969210c7f0c4b9b12f9fedca5d2b71b6c04e7024a0a5e3d0d3c7d30cf568a659cc17309b223399b39ee5efd0cdec3a34b0735df8d7e0bafa40a8aefd742b3e0157fc89d113af5fcb0cd136a9cfb82acce406054aeda30b83ade59cb6771c366c86b5d9b016a74f220a967b83254db3e24d3e1f5d5e23b21354420dfca6bd8454575c6b0e528744f44ff8e1b9679b084d083b9ebeff09df273a476332dfa172cb98c79ecbf3ae4a722c25be71a3b206d848f56b02fd04bd32ff959e6931bf6cba042f9fde027d832632cc40d4320166f9644296d2dcc845491ed780cb609c0432408d08dddc70fa2d52884df47a55a8a3e706a24ac6ceb375a894636e1ac121040561ef486ffeebed3c5336d123dc05a5cf221b9e895f6d3ffb24b3674039d50fec114d3648d6dcf4fbc0b503658672d675c4ac64dac4db4615d011e82bcabd9573fe9e2af224103f99c4e6e5acd2196f1eb2260fb4aa61c298f99c20c4ac1c9e70a9a9e28db441c3adf2f2b3a00ca3f1398b5a112126fc3f0e2d11d40db36d0aa47d59cf8ece36df8daa854509e546295bebf92465f32a7edae6af4218b49781034329c22ce9e87258216b4a901b823a227e46f2938df336d3fe03fdbff4efc7b8ff8142b4bb60592abe508675d04081e5eee99468971fd49989eddf4648d3948266b08133b8c22ce3523757821a05f254cf5691848b1532655e85fece5eb186e87fea61936fa63aa047b5cb77c08aeeb2991c26619139b951ba4c2ed487703a6123c9c16d7b6cd3a17ad108fbb7c79fc3706f654be77a6cd8a5213d3976b1a4527144e788b712f37cbfd5f4ea5aa5fcc0f91b98d74ddcacb83fb33e039e1b88811a2138743ffc0dc5eae46c688f48c0be92a7094f92c2d4bae0c1dd95d40ffa113f27b8fd1808178be0c3bf77b677df2a17c9443fb6023c9e43c48614fd7d09a904e7a064125f8b7671fbb7529169138feed4bf3e6c215947efbf44fdb5eb1e3a5700fc8bcd1cf2a393ed438e68b607a1061e6cbd46a0b4f30fb4a492e786c5cc6d4f80542d64d0d271308ba072deaf7b1ff1c5200a2bb24c68aa2a5cd07052ee5760e0ede484e0a9c482cc74ab564654787e1698bef1386fe446106af25cf2fd950a78f4b521d547c83b6e4b6ef652444af342e90bb5761ea0dbf6b8c315996ed3d3a1a9d1e5f2b75ab18d0bcc87ee639299a248406d9deefecbb6883fe81ad12f20d80fc9b3c8962cd84e5da215b96bd457d5146aeb36d08185b2ee021fef7fdd43d0555c0fd16e7b66d1f534ae0b87f6299fc3b8e70236f39c91601564a5c2b3abce248ecd5450096e65df8b69de8b5cd963127f207f0df538f990bf29ff0c2930ab8b378b86d2619b150ab4dde82469e40e9e6e503182882b03442f92cf7449fc2c4b2f7ab91cf5ec57b8b0ebc18b27ad9125da57b6c139edbe7495defc73d68e71019b2b808a1ecb89fde58ed9dfce8b17e072170983e3dc3551149108582b95b2e4bd9552faff0bc7fd13dc0130f62a967761928dd62c9cae970ee447842a15baac31a280b443390bfefb7d4115e8d1c6458e1920485985635b75bf84b6af5226dd9b36c94bcd1a5f3ed99fc3e5adc6f3c4a592d2eaecce02d0e5ae97e6c4c7e101d4138e526fe3f090123c6df8596505b4d28c1be9e0c3f83dd4ac07946617eb553f7688f6724c8d8d34281a8c094740170280cec80b61b07eadb2c63427690ce73233f18593537e07266a71523688e6fdd36943d015c1bde058ebf5fcd12ea00e6b41565d062722941ca346b5949078421cf1f32fd38ce1be52fd65f2e9862bc5c57b45f33581eb72d387f0c212d68f85baf7e42058e41966429b0189da4eb4e58c1104e59d34eb0678a1385c38289210ac86f77cf8bef670b9ed04414875a29c27b79bc97e7febc40c39cc8e201ca56b25cd8c96f1a37ff688fd5d55cf5232d216283169b51cb41c631ca323056f2e8f74d5178a83b3bf43cfbbbb40f2680f338a89b294d4b611b0f275cc60e99bfcf270cb761c1c2a6773503a3c0e03b2a858d0cb5f81b032012bb0e15add080cecf19bedadc4d0c7e9d81fa75b97e7ca5e1c9eec88bcd10afc0d8e48f83aee498633bb260d731e0f900a9b0ae3f0d6e57346b8d3d8019bf079b4f909b6dce5718052416de8b61e9ef317ecf2faec5a64c0ce4bd5aa72b79360ff9b58d4a5f3e0648000d90a947933b0fe71d81ebaa96cd4c54c5d42b941e73423efb1f6626767f0e6dde52cd8796b0db31cedaad75b4ff72b83e0e9ece164c4f4dac170cca65e42db8b7ead0fa6e2f0b2d9576c79d1d73aa4b7ce4b954958dea381a65d4287bb1e02b7b88b33b2f1872d92ec6bf79fbb726aa436434fc7f2e79f0ff8bf243e19c08f680a5012c3c3d0501abb46026c420e485166fff457412a075086266b854aeaf5ac3a300ff5501bfd7ae96ebe56a5df5b7abb5fe2d9bf7ffc0005b6aae9dca8380a66c8c14e884f9f3338346ef1daad62042d09cd774b43016b0339aa208c5d6c2f7373797202ffe680edce71d684030e5841edd57cacb0cd596c63515a1b992de113fd2c8330840915d3409f608c8d43601f09dddeda6c504352e4d8ed932d8b5076a557fa2d87914ccbb0fed61c1f4d9950be0900b2212a82abcc4d9f4466d1f5469939c1e35dcd2d124623e2e1aa2dbe90ce09b958edc4e60d7e7502ed16a8a1d08dfcef84eed8a93d6940441ad41e493ec09abce869a8de0a778fd8df55cd1d9d7f053a72314e786088abdf968a3b1d1427e52427c2313182f51b5556466960017468a35ed2594280ad8493a5d3503ee4c479fd4c8db0141fb6b77331b46fb228f94e213ad372c09ebfc8bbcc79eb074162b4694b7bfb8444a4938a80747d2c15879e28e3cf44a8ac2ef8c5d9f93e9cb42f81cf88035dab96b6c078bceb4fb9cf293dc964b0cc9b722a84f3423bd4fbc57ad1f68a8166e86da595fb3b7a4dd87190dc65756e0f7750b68e3f605def2821619fb4fada9cfd1c41343dd4f5424a1911ca709ca745962a484d981db73a23a85c046a3eb73cb48b085d3286738e689437cd4976cbd3e2c5a4a4e385b3aadd09b08859bcf5506164db33d414caee679c65069543f1db8b242dc424af5a45bcb5ef9b939ce94e4dfe56ca25702d7912c38dc44d94670d90109ab685ccd59988bb7e932ffebc882b7dab274065578c041591d481501797b4039da17684a7242622f4390544b05023d3902949d348a44d9ff421d04a55395cb4248c7cb0f13b697f1423be1342d31fa9b85aab70c16bc62eae5660256d2472dc908768ccb7ff02cc84ffc6059752499711338e41d37f8751d84eec47a51c7daaa273e19c523d3d97ee5f71571def6f7268f24afaae71eafc84986eb8a0bdd50fa553c815939a4b56380b22b650fbb989b525d2862c5d420c83509b5c76b1a9a2105b45c2182331ce72e8f1804efee93b1929338f" ++ } ++ }, ++ "1" : { ++ "id" : "0x690a7fd66157e5b777256ea5214f634f61b3a72d", ++ "keys" : { ++ "falcon-512" : "0x09a89834aba90aa88f605981578667395d730a408f3d112231997200c28865ec37a4a1f044c8817949cfc8a4fd9028832fc406f1bb919789f2099629c2c8d6bd128de4f51c02a73c49dbf17883ef90a9dbc0350aa67e024a893e555b4f989780a45320af4858421346445f66aa86e4954c0bce0debc896f21bc960e4fbd4eebed93e943a40387210ecda652c36b6da73570500adae1a2a03284dc47f1e370570a07007d8c5a64089e81e2c4d45eb6ca01530884070d46f4605ffe139457d5155c8e9ce8f201715ce7b9d18755304ddb6871551498985ab400cdc4349c6b5ed10b76b425e70376e39a6167622eb5d4b7cbd932aeeaca53b3e28ea06c44780b01684e66eed712559543cea677f1d9807e2ad0312c42e43d399302a0c4c506da7cba37000c3ecd10b58922889e5c8d31a9882ab8ae4b69d3d3d3abc6450881e9b79d9e2ac51085f61ddcfde73e57c1784a6a766ee2bc434d4973a9667c1c8e00eba0c544a36c593a764f519de83251ec48fb45a63e00ad4aaf01d1a295eda0eb95b27fc364c33e3482f4e5256cd622242840d0630194316033219c3051258f548a23c08d205a7b15199ba8d6507565d06a1f20db367183d56d9dcfd2e12c36bed83d239ddbda9efe8507451542942033282bce486f002a215c2ef599a6619247888a81782b005acb3d550988c1f22c6b186038bbfe1c583d165588e00c7f0f7e462a778e6a8126be71ee0dae7b5cfc6145aa6e65c8c136d34f7b45252652995898150cbf177f47ca8d16b583ce5b0e809567c08b99c06095c879b4d945b13c8a62429966347946b606dd78803a3c8113a431761dc868ba2e2541c66b39f30ee21b0ee3fba5eee922d56f49ea60c25a1094381908a69b351e325357d9b4b9e2d040d8be7795891ad46a334a057b0aebdb2e5a9cd760b02c774f60df240e05ed3708840b1663cb435adf9929c138b9fd15461d86328d5895d8778ada79d9b567386a6302b67b4b99a37f4362dea36fa2fa1f1ee2f4f8293b131c57595468aa5ba62a03dfadc9784c8190559887603c4b50b7487e795285705f07f90d8a9ca50e4abf0905d7487f04549132cb3a62ac2e490d6d5bfde20568290b693681218426fa0458eb356b198b41bc60505afdf7219ce5959124e4d1a56ba63345f91ab39afd970997895689c8397c023b1c8b774f92f0e5940c764abe3bd609a0d50a98dfe291e1677e6232896ccdea3d047f35c558daa130ff53cc66aa03ca5687a2006cb7c8c3f", ++ "slh-dsa-sha2-128s" : "0x3345627b00d77c13ce3ebdd12964c45d0bec4dcaea60b64fbf6cbe7b897b8136" ++ }, ++ "pop" : { ++ "falcon-512" : "0x398665ef3725ef330b6f53d5f76d657e97169314a4005b2a0d60feba61548a5feeb57b8c985312bebf8466f329bb42c76e604d7555168cd6f373a22b3827f043a3224851071f9ecb55386243392eba25baf906f8c035eeac71c9c523b5968d7df4cc7dfa52e4919bce0f474a9cb04fbc698260e4d37114ecf919434117cc9a0e7befce3559125d60c2a0e93a9dcef72ee54c47d0dd657b45dbfff4b586cf5b9e4c33ec8dc53632040766a2df13ccbbe6a649df9649bab629a6a5a3cd33b53fe7e20ae515aad9db894e75ffc44f786ea2b054c75e560a31e46c29308451fad294989d91c0883125430fc439d648d49e9457b546884e2a471dcd7df66ac42565c017fcee3190a09cdcadba95e836bd292f83f9b2c4ea08fdf6ba44d856a6c375bde9083bbf2b6d89e32a19427a4613a38351f448dbad1da609a551259582d8c843a0c89d5b3b9f85b24fc469896e8b9683abee444ef7288c98561f4657f236e9142de5e7a98960ef4d35576fcae78e9e6ef5dd28a19435c79b9f37b71dd85c070ead1d4c7695b763bbe8d689c566e22a224902a24418548b227be8736d8cb98c2cc20a3042759e43935409ece39c96f7eb90516b73efe4732597e7c088e9185eacd08f094b4311c2c8f4cb770b7a7b5fd526ac44111b72a50a0b7fa36c2c9bab7d4ec39286bf509bcb08ea221fab495fd050b2a83b1bdc308405088144f649162aaef2d71f94db507628ad673152c29b05fb1aa3d1a68a867b6472347a54845549f7cbec83328f8c71f1d862195edd15164d7652078d8d4f5c0d2419948d13d204d3d4f998f336621b7479c526ccb629abf3b0e3a0eee6ab363ee7936117e4ad8445a124ec2215298f2b38ac95c5d3402f3c9c1f0d34b4e0d7dc9c95dde6f18c1b59676615cec25c340522153a75767c560e6f7d80", ++ "slh-dsa-sha2-128s" : "0x6e16547734391aae71d29745c3ac8cdfbc98f07ad9a8470650f0a0085883ff970643e21b67d6ffe83653a99f2198f821cc080dd7f0cd1a612ab5c6f18d9903ecce34a5cdf069ac66483448219c06b131b377900b999f9aecf637713feedd8c7d4beb03ee11bb297bf4a97959ac5c85c0c83b48147fa9a3be7543ce1050394e83ed745f9ec0c555328d3786da46acac3074c0611667ce5bb4613436dac210c2e9cb186e9540d7d43ceed7f278363811083368d50f6d258a46a32c8df5d62c42c4f6f34c627076169428e646774dd6dfe6924e2240e720fd4d53dee8f880c782862de1ff96fc5204a17625ca008781cb120f74caa37a36dd20136567c05e8e7723a2e21569f065d4fc631811ed0b2d9bb67d2c82b755d14cdeaccb797f207427d572419360af1c443fa68064a653b1e21a2b83fbd93e38c7cfa5046eda9b86c68f3855c61cee9f799ba02e611a1b7df6a15fdc4b4b09e51b3b5e1101d0dc90a213cfa0522e93808fc4ab3d8cef74d279b98069988f6b8c6b4c8d3d62fe2a5a62f1a7fb0fbac7fb36529dd85416a330f35a7e4e161757a83282ad50ddf92c6096cc1fe071952dae4540e0c9d0507d4b61ad34751ce17fdf2e99c3e54cb523d3ffe2cbe8a5c58b84bdde119175e9599df6b2666a7721e246305457cdb5ff5ab4ec9d04bca439d59989253bbfd9a91cb10a9fac3134d85ef28f1e4d4f884aa195216a4811be7617c0d6004c7833088851fb7758aa5aac838ddc5e3a51d122fbb03b0b5d0a3593b2b97eb69c2266eb236bcf3134414536ff36895bb081e9fdd2e5a9f9ba71310af0fa126eddac07ca67020ddd4caafc9b102afd4d0bcae2a957bd65d0a15762b98f4dc7b548cfb463ae10ec3da3b5a4e9976b8f05405904aff74d3d536f9a321b41e0c1d5e4fdbbf61b42d868602e112b53552b8199a6618723e5638273822fe0afc5e6fe068d117bd5af3a1c1e8bb4ea9ae639674b51a523d19f950629a76e9a52c673dd153915863d0ad166d357f8d23b85010aa0b8263de0f253a0ec29b0973af15e4419d965164b5fc6a0e782716d86bfeedfabf4d9705e7093373819a814a45b245cdd13a667b31f1724b5cbffe3b5ed3087118715a0ee68af333bf26f1ac1ff13eaad6a5edd5e760e89518e24a982af4f44386c6d92db7a2229bc9c4df23274cb0f10d348f2373a79f55ee05e3dcb256df464c5f3e54ab790f1fdc585cbacd93c775e50bd02f451b69972728bdce813b46742ebe9e45d45c8bc23d4b298b5956e03b48c0a11c602ccdebace8f92e2521cb346f291717cc1881b0fe3a2e23d4ac694b7f1cd296b32b7f2f139877a129079a524d7e3c4f9c36b5836346a6944c49967796d8564ac8d2ed5e804a14c655ef235fcac5a8cf0372f7df952af0de7e4319089b54ea3f718b539a9bca631ea0bcc9259c64626d252245d541d90179364072b081d70da0a7e561ba2902e8ce864a398dccf55a4f583df7b6f6ad6738813eef6815f8f67936b7b842ed7dcc48808156d236d70a9ecba41994bc0296c3a236f2772c747db6ad62723c4457bf8a2e526f306d8012e04adcff0015a88167d199029ecbd333a6ea35f5b9dc2eaf11a14fd09b35bb2842a4e610da4afef15f332d5d1e82c7b0b452b7564eb45193af060595975d496ee59151e3c0f1545ef2694eeb1a2e38d4e008c0943c8e7f181a258c35e5068df39376aad6ef356e0010303d9a0dbcab91dc708b8e9482f50aa18f88f45864d539dc0818148149aa259eeb270a474b0a117de91b6834672a5cb4b5fb7c2ea0ea7e3bc9884163887986aff1cd89c49a6ca417dff067da528dd33dcd1f7db96ed50820bd72dc41984ed5c767478b79d8f61cb7b417893a3a4451129525a915b1e999086e6db74ef627534015206953ed3a5e2bbc5c629b00f3f3b22a37519426c20b2a10c60087ea32fe606d81c6457a02bdcadd8d56360dbd278ced2d4cb9af64af4ec77989475882f3c1c0b9f9e0b6528b9834e34024dbbd64dc19fab35f3bfda66c086f4c0ff06a29e9fe881340d1c0719ef568e3f8f683282b963005e93620c01de327adc0af4ea7f968fa987cb8f38350ebbb3b91192ebb009f9fa85657e06cca6f71edd3d0dbcfafcc11b908cfc38a08ba288910fcb14f97746ac20ff6e6c43eb099d09a717ac03f5e0600f0bb611d6972626999f5661e048476aa999c83e3f476e77e7ae09c6fb7c343a196e1846ef061be75fd8b662932fdd2c7d8784c6e498d4d828c910eca00ac199957fb44d572d4bd2c599fa6c7c2a166d96aaf4959c561d1e9dacf502f76b050c836194fe1897d54a017944a973f49b2ea59b66c24d18f13048e093e83af249854da9fd6b4974b4db3e8e65684b3b6a0a11d942ad5bb667460dd98ab54319cc2ab704a7a57c1583b8289477f5557d2da684aecf66eec3a54da742e2d24a6935ffc4f439d4a8abc21921087df93da2bbdc3a0f61729b397faf12bfe59c85a6af75c9f4ce4af19239840b57c3a4ead6096f2910da23bdfd02ee4f3676897f475d625d0e9a9cc930116bb2327232dacbd0ff32cfaa40aed89024b9ccfacdb76bae77a87b569582442ad2230c8fb3e0dca3937dea5685c46aff9ae6e16438e0e9ea8ba299936a42d68967926edeb3ef955d95c5a0b74a13edd280bdcb462dfc2d82e7ec89377edf6760450e1ebc61f035fff661173de5fc80dc66b8e3d38c67f4ef8c25c2c5626dd2875e10d870f12b3f36f749eaa0c82e94b2f30686cda1da606e0c815a35fe6fd671915483e1b2b48fab000ae560dca0119be7a0a3dfb347ef95c7fcd9a78e76911cb5bd438a7e96562e437e32eb399782a9498ac992716bd9f3d7d4e35a1f1821f9008f547d171ce2b69b007b5e377a3244092396acf958932616bc5cb95059762f48468a94f9f897736b11bec2ce0af9ebaed9add43bf5c262106a96083ad967b7fcb127012b1b37970a6be14cd9088f6ea927a66a76c35e1320452848bf7496fadbc613b2e122e55634f0491397ee5d211d780971998244f303802d7630837d05f3dcc588d8ca32e02f16d2297aa577576ea5c1b90d6d330a18444dba772d7aa94d0bf2000d598a069d03e7873f114cab9174af2f28e257ef2c0e44925da7ccb593d6183fdd37a1abfd7107ce02c655e7966286b72d65394f312d72505803bd53621a08100a041210cb912d5aef260b84e39faa7b5d8a539b6392b32ce6287e1a619804677b3f69ac46fbec010e726f3eb3458433e68e6417ee375dc70c2b2ee16b2cd9b228d6a46f92ba66a8c5b08cbd284dd759478c9f690c5e1e16d6332b5a0b9aeee43ac8ce3eb0c3eb6940b61a65bf7c3348d8dd15302b8b7bf6b6257e074d0af3eda088f7c22e6778c8cfef1f15d9f86c76a4b05c9afa228bc4f116ee8adb959b4ed9afb2307f2252b10baa436795028629d05277ea2722ffc14d9a5fd56e6cd6f0ba218675df025e50586e46429f1c6028e305d22b5479dd045d98a93fa30de08bec1576ea692bfe6b657b4be65578fa2dfcc197212643ec9a1a8de5971c07023abd8767c528025281f9854145e3d9c47e01bd37dc3a35b76639e4716465b862b705ebaf674a64313641de333828d75c16d4f6ebc4193fc2c92e5a3373fc79dcdd8505a8ea7ef8be6ffcecbb2e80017b6fe401e49193ab31e67a56e8163cce767abc393608e7485f41983ce27b9b1de1a0281f237d685d401641f860f8f11d10805fbf0c7125deaf583458787c6f2850b0cc8c62053e069df241192c6af9018158c27e30574a9025af5af73bd956bc008efe84b31fd9a49c110b803947fc939faeb773cd3c33d1b6a96fca0c079f2eeb4e3ff768bbe1cbada9ad22c2d97928389e5f7145a346931e4138d66319f0154cdf3b28cc9bc04139f92e421efb522d0639f02935e228d6eacf3ccf0356b32c163dff6b597d51b64a13c8c93f60f150f445271489db644665ed1208c025b35dcebe82e73034561704c602d1b24e04c08e4ca8fab21c5136b6d4b7af05cf8ed62961b4bc1c2883154116a0ca8933e36042eb98d851be695d8c4de2c2530372c606c93bab254d6b00e59fdaaec98c56415da26ea8449061e12bd22743a1a0e0e1e117a4a9448d75b3a9dfe6f213460ca639632d404af60c764d91405391137ab9ec4e8519d11e3dcae18dfad0404ce14ea4dd36dc3ee24b7a15709410818ed0a42091a01ed9b7f39f7c87d60d2b3dcbba880001a519fb7de152ec06c73d35c08b3e375b9186752931b6108a4b84189fe07a7165e18357a94962dc2761f4eff0df829427646d2210b55915be710e2a1bb413df2055e7aa0b0b9a4067d35881f22c08e61b587a59ef82ed4df267afbcd4c62f22435167f2d7a4a939eaf28a6f1903c8c046b2d7719b7134834cd56964ba860e60ebb6fbf4605a11b52aac2d595cf3b6533fe2452b65dfa0fff71aff39124a88e3e02977d6063a8370f98e3cb8c80f35260a8541b9584b1d2bcb315b394d7641ca56539b4ca8bd9e4fbc594b0a3bf1ed678be2f9a18d31d610b55ee175514738717d47e4821150a799ebce655d0c75228c2160aa1936dd42f9923de2ac97d0dc3ea062d41d5beffdd1d69672b73490d6a5e14a655228bc39ffc8f1e862fd39dc950dfe648e0ff87807e543d02c40411ddfc6c1f8eed733750557c9f68d830c83af737c9d8c3ff0d23987a8e09e6293d707940eef4cc838365775046af35dd26acfbb4264a9ab84818a71c5a13d8e615c5675656671e5fc2e91b682e91eca76ebfeb1c09334e962496f583affefc56dc144873c79d4df77da394845fa29ff348007c8ee7f23f2944c121ee3177879e6938eb043a0abb75991b3e789571e3eff009cf089acee93612e97be85e1cd83da9ff5006c14151afa67fddbd9262667f98df52dfded25f28b36fa32ec662cd5a6b0f844030dbe1c87e9e2d435fca1a81045b8de5b8ccc411a839064bfd133731f55ee2ed2ee727d9382d130ced8a48942ea295bcf75fc74e24204b808956bfc171392f18554764aa80e75a539941d90a4afbce1f981f0c35bcfc78330ecf3d416d0683c7682cbca066a10c43273a0f85495cb4916ec0eee9952431a11717cadc95c7626436953fdd5fbfbf9ffe329159d1bd79499807796d75c458c3e3914d1f73f656e9fa273244615710c3eee84553a7ca0250e97a0b8895695bf86408d2f3cb2fbffffd62c8583af5b25b7e2a38e266c9623429f8d80ab8fdda6774df598f966b86ac228639af66cd0e3ee7ad7714b4ecb42876c31eb2608fab0c6ee26e97fca305aceeee80bbe22cb5e9819322aedff05cdb78b1fb3060ef18ce0385ae0fe6803b414aaf0b340eef94a7517e5cc3df4bd273f92120b8ce73281cab96821ddaab08b41b97708dbc7d0edc49cb362759905ce8d42743f83a0d75878596c4c5ca878b7aae6fee6ca7b20f2ee60ea773499a781b958f4353ceb078e5c04b0fef3e0112dd0e3a7ef19e4c63a202fdcb8ea56d15b2fb0deee4198a19c9aa59c1ef2b3de73f291445c248779eb5fc76953137adce5dff20f2198cc9e729be4adf385e0f25f67f68c04b4cc26987c133b987f477d89977621b8313d6d18a5ff6a76c73ed608f5e4adb860e2e8a6cdf237d4871a98f0c448668bb42f29ccad560fc1e571f8abb3c75665a65a212fe9d2c1c48eae9b92bd0a8b7b3d2fef99ffaf7942f5834533a592423d2cd66aa793e85bc8351876946a1e49e13ee374609932ec1af8d4d3f52e00f783368aa2bba882cc91c5fc6eeb657f3682dca8e9d63f319df3bd1cf52c511f600a6c815e4ad59426d9e1f32831dc5d8b0673c7c58e8bc1601d241bcb76c1306ddd5aea847dc903f376bc4d8e73a55f0a5ad331f57bee70533b29e6b8493d9f11ce4f27f9605f693c05487bd43882ebe8a1090a95abcfc186d74a3708ce3351ce7226183a21c08497dcf52727b7de08ad6a970b2c9f314bc7b33995ffc77a9a36ab46c7a05f61315d18b3f2217703be5753b4ee1670eba3af00e90a94664039aac93e89dcaa59d4566bf286f33c740feb763d0a385855f4410052c52abcfc972298ce03ddcb2e65dca251afbbb75c516ba77001dcaad8470f61e3391c1c68b1b7dfac9e50d53d2ad12876ba96419b39d7f94fd88b58ac1c123790bca733b12dadec6922384c6f3b7284334bed918acc06ecac7674428d56496e9d2e8f0175b3c7e384218380b6d59dc93541ac0a7419eb0ced7ca8c12a487fef9ea50280b7f7067a8855e784362e85703f6b848ddcd4bd31293baecda021fcaa7198b27d37900ac192d71de4e5124089bc1c8234fc455fe71171fc44494395b323fe3575ac720af5cff428326cca56ceb0c47e20e1432018a769f467405f5a8b71e15e0bd32f027640212d893678ec6fa16e5c00bf5c0eaf2de0333126ebba6b2306211cbc731a6baa8fc5a64a30141a8bde237c217161e384af3355b4a253d35766a55cc69be97abead95dc2ccdb4d243f64aa6d74330cbb2fc9fffa79fb6b6baf99e5ba9abd7966efc1586e72bd25f6563fbe125abec67f24e3510bcaa34c49499811ad2425c25593ff362c90c5c4fb3c4c45a4c63c46cae8cb1759ff2d82ac2726b60b4f094b6344191f3828c78d369956b7a28f650f63260c2dcdfa66d1df4731866efa6a335281d1cf2ce3635eb4294c8b2e1d4b7ced7b4b58a10d693e9f5a269b9d3451198735697af3a7b4b630b835e3b56e252f71f9aa6dcdfddfae13668bbbe3538d5aca766dbab6655c4aa906e0106640d21c30f1a241f4f5dedd526e8f579848f1b64808afb54bd2737a18d9a0e4a078705847b59a1ca4b2b554d03304daedca50726cd23326a6507393b2dff27921b5d7d322cb9901e0efce9bfd95039bb3bf6a99282f9dfb1e90289e986a657b3aa212cec6e611423eb3e4523f4723302b1b4ea5db2cc3fe3a7f0f3add38eaf228a6f0c02b9237e4078b438c01a0856d64053427af9f84eb04f022fd12986287b48cde73554b014f75a04d01f7d3fc6285347be643ce214b72c911e6c5360909ec590ffec8b4395fe271e97af852edd3801ccf04d3ed6684c66c67278cf331ac7c9b748e2dff377cafc7fc6732352245aabc9f5f25cc29d8f7f211a88a7aac750e488ad0304b7907bb063e29fccb16dd7ca0b78fc3962046a83f9c7138d49df3b765df47829e5f56e5155dba194d5128648b92e4f5c11bdc9232725faea4b87d6d940b9bd7cead9462736c7ef605336c40c9a053a000ac390b6340dc85a6905d35dc83c2d13786d233952ca8777b5981b761376f4ce2c5bec0587c2b28aecf39371b8899d227dd58c054aea7257dcfd838c32d6053362842a0baee7f967b6a4f5e1cac240896a8ec8fabbc4a551a55e674dc8cede1b9cee3874ff9fd3b91db433a12e78904aa3ec84d57a0169f1719297b467c46b278f671f74b8bb3c2c0cc2a093cf93439c1267e3be38b12e9b5881c27ab47bb01397c6470b80174ede3df34ee51ac116bad6fba58f8b8e2c7e0d1dde184460a5bce9e1d853d11ac017001fccfd5b767afb69691844e8327d39660c06b8916e918f5587f5abcd0f0bc45328ac01b1ace66405ed6c7a5080f5795f2ba0c0d9e5d05f462d89aaa230f240fa47c5c0de0b2099e93ae8c0f94a45f0513ce2797cddccb5216bad88333f6fec5805e0b9474a18ff562e78dfe325c1a6bb3648b41595690cab5ca9805eaa8e13526d036f4233f8181aa8efc76e14031d343bd5d9023fd6cd6b32947e173807883b6a964d398d3fdf9f34a44bc5fe41c5d72ffe5fedaa13fa1da68e19656ed70771529cfe822fc694be1445c79a041eff9753cf47a48ebe9f2c9f1546117b97a1c2bd6e375b957fe38cfcbb29f8eb726f18bc6131b1e27316064980e35d95fd913583b9735c6bfb03ec86e935024e60679a61d972b4aa296189fbc268552acb6cd890c68e50e325719d2f2c99b8105bc92fb582eafc1d618b4e88070e6d8df4924a1780f63ee216c0e937073725353b0c97acae72ebe521fb05fa78a4d6ecb7ba2b860190b6a5c340c83249919c26466c9cf4a9b774fc823141f65196df32edddad59fb05ba24738d81734004c42a7f92f5234b7f4fc0d605b032b08eda4cdfa3b03a3b805ecf5e4ad667a8cf399efb3c1d6822d9d5bb5eece6e08a515cd75c4485537eed6cbd55efb0a3d393d2cdcf44846f0c27cf6a664c70dbd54fd56b20bcc482de2eba84163375b1bccd43da63467557828b791dfb0a976628206e26e9eb10f1e9b9fc34571cc1a38f54909a1ee0b097e0f22f3ca58b56c631708e9baa52d7eb551bd327a6e0014fe98f04d7b0544fadc06c16a5652ea16b6c92a014bdeb2c070843152847293a0a925cf3c22bc9ac23464919ba6340cf233990690c94601876bc30bd5283f97cfdee757caee7b7b41fc265fb2ca9751e3b523e8498d665151d1c67624a084571f6c29973e624703d2e87f1ae5a5e0dbeeb96f46698223e063d10d85fd13fa0deb3891359844ad5e8100036d9b70b3b7831ae78c927a5e2c2ec62992cc424894ccd6f064e9ac307e6a2dd092deed179cf60b4bdc6c56c32a538d477d7917f7203f898659104ad5aab3e520a9f21d9c01b581cc968a68a77648cd95f66b5a1eb1b9d60b0a73c2eb05873f279c4ce43409853df2c8db254fd5b63af900c764ad4a0aeb4641e1a4e4089967e83603cef0317d06d1b990354c11b17c83c2a78cb9152615b9eed33e20f61a83179748ed4044a65edf285b155d41c735a883a481fa07c4941865b86d3cbd54c345d7933e32daa90a1291211191e0a3a5015f0f60d2ff07782606c164485aa469bc97f74dbf1345ea631bacb972be00547074759fab2b98a78cc43b7e4fee587e40e23d9f8ecaf03337d47d27bce633ccd97c0b18509afe35d54b1761a4ecbff6c44dba5402f3111eb671183b5e6bdcd69398056b980c35628f03214e0cb4ee5364e51de27843ad6c24b1e972889d54ed2a31d74000c32fc90b3c96dc3761c9649305c5f5e75f5b5ab7eaee213dbdda1039d4f3f450c77e6434752b74a55c42c98719836fd91fceb27be449d65c89a823218e882b987277622ce62fd0b46130760f10be6b49ec57e25cf6584a99433cedb1ecb1ce25cbf5e2b6eb716c12064f2cc45f4989c4c1b6c1ebd390c44195a16da16340d3a8588754ae676a990df1eaf04336b3252a5177ca3b3b2afd8e7555e92be6f6d7e64bea52c8d25adce3c580b5731574729107afe0e1025e6da2f2b05d6cc223778ac7de1202566098d43d0e4db6df8d242b57353cbadc0711030c6612cb92a9f9685c88856a0739e61d08c8fc5864fb9d8f41b27b43152ec15b3307e2c6f20e00254984e6284763acc977d9e16ffd4ca8be3ba7a289e3c5863371c132b8300f59d50f9efd344d1cf51c5ac64f29210740be2dfb720397941e2ba939e31c9ed563a674628b6ec3c8983be01e41eca61f869b920bf08db3255cc04a1f459653a4a3c204e6ec5496af1984f5e47caf56993bce1124bbfdb5d7081895a96170241307f000ed22ba92d5f5d920ab39d3ad1e288abb76ec3acbda6a7779be4c65e99bc7d7d5aa57d08ca1774e0fb146cd3a894beac12715bf322febeb256518addf26df507db3c79cb2883e6bb1e4716e185026cd760c76038d52a2e0695d76b3bf9da7df9f4dea5323f7dddc8ea1a0031851928e354e703651f7a21df505a4e7f9f7a8a398582aaa9f504510c0bc6f9af8942601bb3a6df3faf2e97c9df28268e1dd466857d413fa0bab4ff017f12554dd317455d6c716f9449c5273ffc959f147d7e0da0c2eab432b83f96f7d2de7b1ebc41eaf2128f8eb8f9c09c7b3fb4e95bb3424b216232406b81abd4c0afe11835a8425304376b08a4442c6eb0e88a51bc67a49b143bb35416c9ce613538483c091bf181d322efe10b2204aa0f0e01507a7cb809cb54b5cca5f44c20da32b2b7ec52098e53de672795b68a44ba667bccac558210307ac27bc5c203a2e6a264e7cf3028cb4ed41e29bc46985c1440187155b8bd737fbf9480749d62481d805463d75ec17c7ba83c60cc7020fe4b110ab1a248f6fbfda3e5b8a688a280f87a53ea7154311951c2001a7894eee171a64cba9b19a21e09540dc5ba85b1b2880efc39c8886dee72e64f045d00d99a90ffc81fc957ee65b7bb93e113717e7e7a275814404198f9e9d33f45335908f1ae917e0322b3d12c3d298ee814d22f8a57304faa93c18a14fdf53f05499239b66498512a6856ea194705521857a1724bc2925ba34f0e2707c84ee234c3436b4d3ab46cab863a28a011236e564ddbab3d49baf77be49ff2f5f2ca75252971a421aa2d4975aeacedba6cd3629efef8b2322b516c60ecca2541112b59d73b88177cd3be06163a463306cac2c0c1b11f84ab9b2fb6ab776bf0dc0fcb381975e4c1a0198b41bf6c1587bf6ca7272d8c722a581bce4494be5431cc5e3038ec33d843b9049b018fffa03cb3ff58e5da6bd6d49ffa6f776a5c4fee3cb258c4bf92e5e4079e38437f321e0c29d608cf5f69129e705e66a7036d67d43fd4a2919271fe07052fd30c049b793d2af0dec2431ea687077cb7a7a5badc21fcb0c2ac10bb37247207596d33d1c2232fc2a225acb9f30be7fe6da19514def9b595929c1c0c4b146099bcd980356b601ed0701299ca1a5547d62badd0475bc76fe51d0565b95b52a801f14e1f1ca62526cf8931f0706e3a478d20ce7eb1b1088454beac15277a72c90dd95f6146f961e41caccb2cddb2cd0680760731bb6db221944eab186425b0c2caedd840be5a2575d8dfd5810c4db5403d4491304130bbc564cb578d814d952706570e56641e8ce6232a2d4b18941c35301cd5c29211237c274dfb1aae379e25efdf827ff6e41cade1d57ed229a6ba76bf98de6592e5ae3ffcd481b53071e452a0b25f12919003474bf4ad2f36138d3d7c23c89b5b41a25c3622bf1dab6762cfa86a5bdeb6f2baa9cb3ea7dfdf9bdc700f4062ce8fdf477a17088bb2bf654e2eb9ab943472dadd73e3b63a4fdcf90fffa98983130e16d512b54aa0d4acbb1604d00fb2adc4a88e87d466237ee7b0fb33e5f384656a8759143db4c377e2cd264259" ++ }, ++ "rotation" : { ++ "falcon-512" : "0x39aa8af7d097a0c1c179367796790d2e6f01dc80a2936d8f1db4a57f4cf4e17e29e341b1a07806c8dee46b3fdfa567968dbfb21e510f4d269afdfbcf6df5dd60a9be3d28abfe2633d4db26f751cc26188b4ed2cac9b3a7b02b7db9574797b3fbed1a94786c57f50dd59ab32e213769521ec5926519e22a5084f7508f197eddabb3ba3a85a192187649eb4ace6b4decc0a3ae576aa6bba0c9052e2e8eb044b3874f8a66faadd717a0833791dc67f6670ee2e916f46b7dddfdcd1f0e138ab8a93dcb4b69626b5eaabbb08f61d0af2765d7e0d8e5500d460a76d2ec9dd4590b340f3f4e559393a13d88aa12501c5313ae58d1a5f52621b2940243de4ff00b4cc32d42921c5ca12246e2f0ed14b4623dfaaff4a2eea3477e3d0e2bbfe0a42f96fc468184388c8b70da9769c49113371c252748a02a789b00e41e2ae202e3c873bae8fbdf1cc9a706e58bcdbfd764272f3585185a4c8f1ea541394d55808a9db4670ab55fb32cab28e52d0b2e793398cfdccc3fdfc72059d36dd73e66c886e68b6d7a78d13f07a79283e088440d789dcf13db64a24b30bfdddf225d6c3324afa0dec9decf4d15906363383a910d446d996ad2b1b6d8de68ca7e07d5df59b8c679d089a2a81f723f3ad06fab71daa1ec8c45712c3342cda4ac84ffc58e35ccfc9cbf498f899c542d6525c8d6bce984dd25379edd7b4488a19c8717cfa1bde4a90cf7573fc06fe39eecc96a73f1d2be1c98c2e3cc590a48b56eb76b5cc6a5d9f7649aa69b9913b48e46e654c625ace3f116aa65b6e8c333af67755e5552a8d11c733e5e921085716977e65fbd1aa4aa4d0f0552815f5c63708d12acec91deff083c594af671bf90320a5f1078540631a1aa681b8ea44322cf7aa0c99ec7816f6e261f3821b58599faea28cded6bd3c600da40" ++ } ++ }, ++ "2" : { ++ "id" : "0x41f547a71d1404f147606491f3b96e49f67d4658", ++ "keys" : { ++ "falcon-512" : "0x09b3f618864123704b78a9552a0b068f395444870c2cbd5d741a0c565554bc2785a691ff502d6ed0e14c925eaa24c075d20949d12f369848e178d50b085e87c9b251f68b61ec506435bf5b53a49d299409f54e906daed0c1a25a63563090f6660380321e786311b492bd7ff684a2650bec34d5bdf071c49f5a050415b2c3579b2994fbaa9a97b7f24a30e7e8bba68145196e0424471de31775aeca732dad506b16ad4f61a325136a6664f439e60687e764a009db3218f706785b98b154a625c168fa2ac541b8dce39682172b95e19424b98ba985622b2a23d8db2d46a7230bcb667372a924aa4d1a9e9cc1a8dc1ae11fe88081d74d857bf63e9814a08c9ce059a4b1ccab23a2fba765086b15bcba135d0937a064b90663ec69ab521746600610bec0a6b3c705277f90d588a00e908dd075059de6c52fe05fd8fa8ba1b3c2cf151cc810225db79aae0328b8ea1e92fc67b7bde405a1442128023128a5f7089722b954f15597ebba3aa3b55ae947be1e659be52af04c3205492387b51e72746a904ff13ae41964281ebd81783528269ccd6d2a7845d790fe4cda8ee58d93de3a3ca28bc4e6e18e812c313452a4468049a86ae39d5fe156fa2a43d29161bc911d515f4cb6b625f4679e37d5b55064a16c3e48a7f3ae10a09d9ab7f0ea4dfa2fba9da412af1978720fc47185c7ae16474833c8d278dca65b822c5526bd4da67c0700166cba95e3d23691e6e1e86ea4e560cddd59af18a689c4dc2b6dc0e114f2a84754498a8e299ac17a12fd199d1fd8d5c31b0a40ef4b2fc9627d16ec11241fddb4fee6c652d0119f7d60e852decd3489cdfb75c10a18f562154e542614427ee7cb0e96b99d74eb9585223760bac37de51697d86403ac877f823451d8c60e84188a8fa6804c3a8298f223169c4c61fe443434a76d6a51ccc1d06df3b962fdba9e27d7723a8390f4672d66dc2f756263ab928d9d14f6d550acb286647ed6dfb091c462cf4756194ebac9c94bdf7ae4ac7b5093ab9cb94455dad8ab15b134d31947df478a1aca5e28e98020dfdb6d4ab750911bb2690104b9606e78c8659c2f511bfa3254d32e65aab180ebb74f9848700a8cba3a1a546b77678a17716f232e57b204157761161670bf654f182a14bbbb1c16b14b652127241167e898e097b6270b062f0607a50bb040868768a24312a8da316dbc547237ace3a160b7835c805061f8f2723386929835251945908058905f625cd9a91eea83c0f693523128c68613038e", ++ "slh-dsa-sha2-128s" : "0x9fc24e59b10d63d59b6c448f79d029745c4f27a31903ad2a6f6fdd09b3abebb1" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39916580739423a110970dbfa8b6f06ebfe827b6503b1629f4008d64024e63c71af7a932f3f29cbf08eae4cca92f36f670de2f3a0a461999f431bd5da16b868d2230d6403158010384f0f98d2b95936e0a132f5b86f5d11e32ecf3cf206ab9d26c1cb7fc93ea3468109a59163b15391795b76ce450813b28d28510767270c1c474632bd6eab70174350d329d0039ef8fa6739b2f665fff021cf669156e3797da72e5913d08c94a48a16d12b5ad7e521b730bef92d7cc277a92b3e4c9f9cfff7cb3896f93dbd495637c2a47835f2afde4222c8dd36d4d6d9cb419b5b5563bcc1a61b640e70bf2c4bed6599c5ec50643fa302c227ae56adc3d4b044926f4bc4b26d58d0d0778e2b8ec5e18b5cb9ecb6d7a26808962082bea23a932afefd0d483a9952f98ea11b629b0ad74c367e09cc016b817b624547ed8fdf360a8a06acf7b5f0d3c92448d9f7e9453a4e29222611490a7188dcd0a8568b67d333228454cd9cb99fdc9d6d945a64d8d96348120295b8f2ea9e95f92d9dddfa2a91b6ea2c44de7b605db8e3e1019dbe5cb464e0b211713cdcc32ef3631caccb48b6b0c968492a5f1288e99ada3a4d8287b5c9f46236b4b3fcfa55135f1ee4b13e3d6765866a316d8cb3ce80d67a518ee974976172f91eff1cf973631ade2a2b81134c39d0f3c72bf4fe546a7bc7d3f1142aaae3f5b4e8f3932d9b516ff1cfd827e7395d576d96cff52f00e76abe5ba3f1f0887fb064ee11096e52d441d1b4dc7a69462acb7296c489f498c456b2336f2f112391bd7e545629697bd096ab373a34147643199222b8f1b05a95bba5877aeed29c43bddecbc814a6f2bb38d1dde30c352e06f19bf52717236488848599eaa1ef17873681e91064430aa2f4a23445fac0a8c8231c8cd7c27f928ca0ebf7ab08feb53", ++ "slh-dsa-sha2-128s" : "0xe922917f6a5d9d49338e445586f4b3bfcdd92b89a013edba38e598aad56f8d10875fa62dddbce6c66865eb7d14067931d640a3b7c5dc448bf7cb6309943c2f0930c78c03fad2cdfa1c21689c6f621bfb1cba1968dd28e66ceb6cd5cd4f10b8797a53a8ad54e93febced4dc1c48fc4bf768b85a811866f86f004fdc340628ccf44b295fb5310898614b6a0341a2456b94930d086ee75f67bb935e62c739fb87407975f78f372ec11c0bf8bce5144abbb2678711850174134e6e5acc3b87f14022d158a57dcc7916a8e75341488af6b1d9c0af90bf2ea86440fd1b8001d7fdb8ecb8cf392498e41f8be5c7aaa81841aba7422c45fcc0caadd52d36d1d56cd02d027b6ed9d122ab3d53597507079bd9fb476105b12e3406c1873a8bf6a5b9479b5cab9c370b79425b1bc7616e2f1f66a398c2e38f7a9ff1077918fb3f7e65f025d4feb8b13397460a753b1999b3d351c5b77ece3751686c02db0ea4ff23727527cdaf038ff060a09689a13fb7dc902cb82844b11f8092625272d8888090e60cb1040b6cc5b0ceb6854a7fa769a77523e7a718a1a9cf56b94be12fe8fc4d319b335757c6b4807e17e9ffdbb486d9910404e675648d069c55e96894c7b2ab17d91aff88f44ad609142ea3747117596c98831338c616cea7439b1754390604188018818a5fd2cac7522b2df5e42c14e77b7383744234da5fe1a02a60e18a178751eb9c0212cd847317d64dabe4407c4a4d2ccb6965eb33699c37c733d42e66f92b01cf8b0ba2c8d737711439de358756ab4ba374e7359f8ec5838f531c984e2903026acbce89ff2935855ba5e5f3d85c82bfc3975ba3d4a9721ffaab1182035bb7526f062466895c5900f854fb52f5913591828cef55cd07d70c5805327cccb9822860f32a8e8f78806e39d36ea7be59186da6ab5f1739b6716323b9379446ce6e50345cfc9b769162ba96929e2cf0693b77a558e5386945fe5c6410a2594805695a4cb602fb25993a0359753f4ecea67d0a1045a80054664a5f589dd823d11b1e440813b3bf141f119c38f9595c1eec85ce74fd0cd69ab783ff7adf32746d3c4db1153df20ca1ff94acfcf3c8ece27b9a7819f7751028435730771a0d7eee4d5a05627e9577de7a1c0d16400a81c6d93fe48990d8d4eb942233b6e81f2606c228423d52fa012ba6de7c24ef446f32ba1e1bee5ab78e79f40ddc3f8279277735564901682f03ffbae6176aa8c2dc6871cdea56cb875f25c88d955ad2e5f560fa25acb5d2130327aff86a324aaa721874c4276667404738fffa534f26e4e0dd67a9d0e5d447c2868af3f5b93dad621f528509fa6c3d2b9a391275396d3db6487ef219bf42088433b79d34ce793f024380319f1a0017c0cf821d998871fd35d2da47b774f6c6664e54090d74d087fa43ca622417314ac0a7f2d23da0e9be5242191b9096ab0e200bcee276a787ecb770a60f975c2935f24600869822ce96462d97f34c23eaa50b443a504670923b260e1698eb12a76a094b9a8b9bc2fb07c38b03b495a70e4976d05477ee88b58e2d66729a91f0fc003e56236c5285869a6eba073b36efdac3999ca0b91408282f83b179629bebabd5355381c4435bb173598ce3496dd8616eba46505a64d29a166b51b1033cafccc0c6cce63afe4f2dff7a2cc62a909853b14b40c418d3a180a922b02243637700c87bd0268e3ba09730a2e2e20065a7310d8cb86ae6b2174454ee4c01fc86c0441cbc51f1801a021da1f1fa4ba6cc0e8e35a11a0e55a4aec60d5c98330ea1822991083deb2a80efaf382d29cd0b04fc2b3289e024814281aad94ffde1a837da103a0022b23f223e63b852ce8bb89d50271b29b5dd805edf1f4339bed98ad4e4fa42cd726f3f70c7c434035cd9180a02ac954a1173c2694f0cd59942291c34a8071803a69552d71b8191c4299add494d05e838803e5e9de4e5a2d7b0f8b4a221ce677b5b365e57284f4b74c973c72a565422b2233a5b3770cf28645a18ce1bf7cd0e726566c382d801e655829a7c5e2aa149217075014492b80533bad2c8013c382aae26cf4dc39a6eace929903894f85c8e97e4be1df2bbd53fc780c46ed384e01fb40c515e88bcbeb2005df6c152f0d169a90ce3a43c2c3469a85a456991996f6e9ffab555233598f767b38307fab61336a8d57c1f6753749d46e1b3032532a5ef11082cb30e12bb6b292d0f37806e6208d4bbb7c7cba1b3b410ec1d29dd35af7d38ba79059999992088f06b587bd9570ad0a1e2352a6133a50a3a45da27fcf63cb7c6fa98e6d3d3d7987447fc596edd9a157d72d0bb60441935481c54f9c163b985c708ea1dc510f35f9aa8768e73843ba5e8621912f43383365f534f3ceef986e90664123079f7355e5a5193b0ca1bce0443e01adc00f18f8f07a9038cfbc672494715221c0b8c5dadf7a66875ad67300e5fd662ae7b4281f2df29aa0f5b7f9f70fd3180d7875aaf784eb3da36f9fd8abfcbf2f156392cd196ab952669a531bf941b48b7d2850cb8a66addeeb1447d89daac2079094bd4163d9e0d8ed52e9a93e31a7d4f5d2afc4b7d2c0b988d41c3e247237363dc05dd16d49d159005b42ab9def7290a51beb7811e9f4fb9961a7af09fd4f291f797f8eeb05bf76884ca340af07f62f587dfcbadb344c1b350960686aeecf772f59d3f5c9f6c01240667d1fa5c3d84dae1f0dc9562543e4636d81a3f0407bc29127bf4b4527d0f6d7815a941fb53e6527d5940739bd369786e710f6b0f69b05b2e0c49bfa51411319b9f7b172fc11d901e41ec54887a0fe5748b1d2403d23ed5494b96639126c1d3fde11d85c8c717fe8b01319a9668b109e2d34a6ef5911aeb31c88b71c32a6723b0ad2a28b2d8c75087a546550b0971dde64d3cd69434914d5544a8828c6e7775cc802fd71e467e0327d692cba302f681fdf0c7425ee580c413d1a3904974e55e7ddb19de793541a7a4310e50990744b4655e72b4eb5a3a8c5fcc09a545198c6475dd26a43338753855ae4dbd845d3122b16063b9d4f1170b0fb1eddbe15bf6a0f935565ea46bbbd6c00491a9ea8288822dbfe8788aec3eb3e5e42140fe3cdf16328587b736242c2aa85828dc84352bea3c6d985ac48437bd72f12adc7fc08d03371992547b91a3061c9f9bc6c32a8555df262c14dba813ae8e2f9c732bf7360b1e94498f5a1248ca4a0c020e381d8c25f4924f91bf0c649207b1314bc0088d2f15f662a2594962596ea66c036677c451e77f051cf9c5f6b83ada58109f68b415af541dff5d6cba732a938ef4d425243a3571f475af0a456a7ea5afc7c78fa195780b270ee1f4d69fca7c93087e103595af8757afa5dd23ed17bd723c1edf8701a1b4bcb2102ab2aaef2df7cf485370d310651f6e897cd2d687375d29c7f101aed941cbbbc12ac7ad60c3147e41fffafb766e548f0e96bc911f38a6d1864277c170fae28e4b06fee1d1925923432bbe28e41f8cc19271f68196bf4724278f8492a6d5c0826e03d8dc1232c0efe5c7598b71be7d6c468ccb1077d7c8bd4630bfa4a108d58d5498e40584f6ab690e27ec8152c1c39bb70ccf7c5f2c33e48af63d536d9e7ba90db931783a9cccc05c22dbfd90f84f75d139aa22b1246a15534f1521ecb9031ff0686c39b728fcf6e0323cda56b641561a88c6f78cb1d880d102d26b20213d03af41c91ba6924a0ae17a92fdb375492fa0b514ce2fe88fb95d72e5b1b11bff99d1b0ea0832a0d3472b5880b3ddef0bc0891833adec1f7797f86fc549b22df2a0a59390a900e588cdd2405e5afea987db98554585c85fa2428cababff59c17713cfb100084192cee9f4ee3855163ce76fc59ebd4b23766b0ca7c2d59754ca42ebe3c997cc4cdcfc2ef455d3afd488474b4da2a6ba278c196616f995c4398710c291efccbe36bb724bff2d097095f440f79917229a6fce31dbd89e58696c4571dce1e535adf5e1b0942fb5d59a13f7fb4eb17647e83e587acc50d920db2951bb48e1495256e10a62a8d43d3cb7719c54c24f546ce4937e2ba7b1911f5684068c365398e41f7153cb1e2b9ac014bb7395a36efff14ee94373dd128d725dd6ae6af408a5da12ee540fd8d2264b24cc7fffdb2859ce5227ec3c3d5e0bae49b5f495a39e5d6b3baf7c967b21a55e3528fb0bda0e9f2a3cdc37904005a76b07d044ce439a345f5ab69a3db8c711d478288df2d4776d53ccfbf49a06d0d0332814d34053c98ee3464bbf46309b763114ddf1073100c34466cbf3414b4bc7b8ee73c44d76c46435c0354a71fba7d8ba8b0248f867cee79a4beacb5dee9c45577e5b423582fd261b6164de192e98aaabb47179a6fff8827221a70c77df46d01357bf27392d4dfe3b8e24abe9854d3109b533edab16f495eaae07562dfb4428cefbffd748f144329f7653931a9f65a3b024bf19d2fe04764d53730df662469a19c4bd966dc925b1ac52d9094ff7dd7268697468135000a8766d8292f9079f9bb5601193df637f8192812a9a97f604015ec15c89fee9f700509cd745da588a86c7c756bc84745c593bcb7c7d9d34bea98d505a57b31a90833e3d1e154c3b686d5d8a20375111bfc6964bdf2f815e160754b56c59fec8fa533cca9e21d4f688ed94cdab427f9e179fd308856ab7f7206d13d65cace5f8d65c8b95270559a7d33c76c81794ec38d75e2b3f9ebd1351e07da0540e3981d447558d6c21ce6b0c32bf61a3f554cae9edac7a92e2e25965037830c57f30a021953d91c8349b94181ca8c3bec9f33327caa08e437e542d4cd9742ea16801aae94e19442030e8c95bd4f23d88ae9a1f1cfe4a80b046f2e54885c54572a215f17bf8359db4edc830c48941153bdff79a6777a67a9ca0ee3c5d2e4497871f4797974c1d932fa3417b909ca5b29dfb315bf1590829f1cfad84b9e068213b8a6e9171c1c41757e262d371b7073d1b90fde5bdbafab76426f486581bf52fb2a53df2fdd0a6d5065afa6148606a3dd311b155dc0dcaf9f741a50d105053225f1c223ad0fd8af47d27db808cd32f733fcc8e2655523fd36a906c6e6a1d6eba56311424458b446bc1b77b866af76be210b9a417e87903a1ba2e431c176a82cc5a71a4ddf29350efa6dd8d1707d3884b31b9b52bc876b6599f40b077c43d815d2e02ba043505abe7ecd7dcf73818ceb77a09ea4e582616f4af11133a80429edc9a434f3cd2b41192edad842b433ee7936fa5c7680023f0727f4337c53912fdf6fc7e6d5c0dda2e0a8722d5b0565ddd8f9349815bf38e8615b5c7ae35622d7feb7907e6423c8aa7bdf57355c0353da377977e180b88ecb1faaeee2d7142f342263e636eb99c78af9cd0ef0314d9b57fe1176bf8b13c221b5a05c1f876194ac26c35b0ddd91a2130276ac402314367d99c2e300a33073c06dc18cdf5361908d58a9553268c6d0ba19ef6f6d0bfbf2b1e2f5d284c74695189d8a3236e927d9598a4be253d0492f98015851be3693b0c1b3c4a73a95ea57c20699240887d501db5d3525e787dd1a583c2a831a9b59886c873b8ea5dcec376ff37fdabfa21b74b3968008dfd9784fec35696779217b4f5507ea15852f751af31243dbf857d66cdbfb2e290b52f67312fe5d93bdba25b1b7dfb0f3488974a7ff0e437cea09d0baaba7bbd2506fcd182cf0dabe7c262a823fa1dcfe00bfaf7cb5f54283763a45134dfabe9927fecacd648ef767fdce12d570693ca6aa10c74c41761f64f31139f3aabbabefe6c7bd79a6a3334cb465f4203604c0288c49db25bd25c6c4c113e09fbd65c0f271f4a373294831c33f7b2ef392e4a4b91a3973d38473b9f3a485cdb04b7f75a833e2c0461c6f27e6d8f518d3a4366ea3bf37f43e4408f00c4c72ca8d0a9fdbf1ac7fc9fed47e8a3f3f33ebcbac25fc2e70bd39a85519181383597ccc3503e597a734c98e98a15be8bf4b37330f585ea138e5a2e4104ec1cb6f5a23df7ad83751c32432033f072e8ee3cdeaae4e7de98f9e58633bcdceab69ff60004cfdf51b54e9a33232e1df86ca9708811a69b8759e5b2daf57eaa8f1f74ae6aedfd9106c105a6cd715b66f561c0a0500a501a9f3d50a0b5540ec96d24fa5f6157f5465d413b204a224e2b752a49322a90aa340e4422e60a449cab5b6106135ad34ae309ada87ce9a99cab959f6c2502b2da99d8ef296884f4255fa88f38908e4294f799afbf3d664900c5230ebbec54328167495caa99942c13e834da5c488f2dcbbe4d2448eea2657a2f82a91a53d09b2b5445de8c8c8ede11f028e067620f2ad83be80d19f3b9a9f3b81bc8a405c233b2b17ce8ee5e0ef05847aeb36f219817d735faf6092d13569cbf069696bcbc50cb50cbef921f8fe76775f1034e73bf04431b696eae4943efd78ef6c19436c76ab389825e57b23f4529fb848233833afa418d85a92fc865e634357071bc415da56078f44bfe306d3b00574c04b2e94d6b801d5e3bc03686d1bb27dc2753112b2c22a43610a4dbe1e78c9f4f6f2b4ca3ccbddc2ce0e78fa34cac5935bf0867bf14f40648c805876e61fa841292ef2d2d53ecc00319a6df0bb6347dc865e39d9da574ad93f9cc910a9eb920986d5e6b331cb29b45ff32ddbc9e09b71eef73c8673307d6684a34ce85ff3a4208741b205d31011555b17b7c5effc210ad9309468a007d76983011b88c818eaeb3d3815a02d76f735433192f1bc99a6c7dbb57e107caf9e986248ebcb2e9c28279ea1e19a8f8027bd6f8728c9aed0b974322254e686526cd9ee0c6720de4eac01cd83e5705570c249856ebd7ec76cddd98cc096fb93db8ed86a5aa0736c36d978c09b915f7b9290cc255ea1a4b355888fb96e506cba34683c6a890c77d92fb01bba6b69f91efb3e4313111dafc3a189db063195bb650e0cf353dd975fb5c286f86b8f7d982ca5f74a78fa0fa3d693980be09298bd41c4ef38874ddb95e928494b9e345525b00e4760a1d6a4d54675e39b1d955e20a58f3ee65ffd1e249eb3558ba348a2be114f396c422c57314ce6df0ae9406dc6bd0bf5f1db49f012a03834b3314dec7839860867033643aa7dab3fe17ee025812ad2c05484abd0bdeb67043be2a57533d294aa03f24ec8afae512537343eaa16b07eabbbd2cf6755261ee473dc457ec36775102e1c8150248e4e51dcaa6abb7753920bd5247ccf6dcfed9dde98c9f37938d1c824fce116f39f0d67ab9c1fbc79e034e8bee6f79715433d485edc70e5c098ef7bcf2972171da06cd2f19cde8f824e0f2bbcd816f7eb87b7bdad659a900f36df708d3446d8e412b92142d8414f3a0508d106473e809a0831953e2064c655519a8f22fd0c517df7ac44d72a0e7b6fb697b188133fdea4d16e51c6da3109f7cec1a43fdf47957a35f4651454ae04da9e9d5a1668f46cbc58422c38fdf204f4e9c0df3b1f0ed2e14d0e008bed642353ede25a5c25684e7d593eee9d14b3a5a81429b30895ff5d1f7f4a124d2fc9bc1eda61e8e4bd73b57ef1a168cdfb1ce1d70955567a3d949bab203c379e3676932f96c04ddd0271a6afa0bd55988134de26bf5d6c725c09e04aaa03d393a82805a366e0d98e4b65bf45e05ce45f4dbdc1f8ec052102df08f5852630b706dcde9a3efebca3852e85cbd7fb6e6e00b4bb397004db1602b7f8c0dd365eb2d946d00eacf0ecedae83d26555a1bef8be88eee9de9f9811074151f0cc747f36d45ea7290d53c18fa8ce73f77f54226e5b1719a9bc911c9d7565693836edeaa6cdb7b2e2f9cc8c86b7c207cc14c261793df6c4c623355db04d5eac01c011677d26b764e9048bff8d76e2b6bdf792c57e044eea4307f5a3a62900df3f57ae88577644e2121134d61bbf3100fedf83371438b7854d06340ffc00383a0a4789a6a85062aaad3761dbb3c77e61c5926b0488f711a77735dce429b6e028373dd341fa2db5394867242331168665b4d7fc4ef96b12a571b8b25d44fb0de64b9820734e5647821a038428d67dbe95885526c3f2b8064e8baa5144b7fabbbf5a133c4b8d7a2f950a4fb69f9cdb37ac28cf0421894f0b771f80db988e25fb4ba9991664c93116bab82ba808693d583a2b697fd2b5eb673f954255da410df58231eb7c89b8257c5a68ca0306d088638b2faecbe3cacbbf77725e1685aa81d965f1ef663f1e474eceecbd52943c2e4e0456b52aa0c7758cd2fe67f3132176113a16dc9bd11d6dc03ee643fe8bd6677f2ec0ea754ab499e00ced482d78147ecb2f91d3154e03b57dfad4e4cdab98e134a609a7512a5a0e7c3c4adc9db444238e0fc3c3586b389d8d090ca46222a9533672eabe4fabcf61beaeb59c507f2941ced1ee4cd2afefee5aebeb354ec33cb85c9695426126f016929b471b9cc07dd6ff787fc2d682cc1e80657bd656acfb865dc91d6b032785cdd7a1d66d4d5463e142b6f028e8fb5bd6c621109e7022818b39197f85fd6ad4785efe48c4509e9a537f10d4fc9d23f275fb9e684c2f827868c9ff3baca8faa59903c829bbe1992541d15d538e64329e886ade0c5517cbab3b15fdb4e82506e27f449e268b488de32fd036fcf80f6c97505a5f33e4d3a004772a8970a3fe54049513cbc57131ffca1c82918a81bcb879b8f48d4300b11cd90069912ec9e59d10b6bebbc24ba1061c62a8762156df586a4aa758f13cab5ab59a3b1ef7d038c68920eb0a3c8a673c27b6fb80e5e8741b3b7fedff0c068a83e72373da07c8d73abbd9fa0084bdc92866917b546dbf7a6304f04b18d9bcebe2b4bcf5ac7ec526abb4a52a19094c8c231668d063c5558bdef0436ac418f42c5f41f2df996d19d48f8bec412de05a6a3b079e5b6ac1be0773814acc3d20166874ef64a6cf27f7fc72e0232031ddef1a6a4ac9897a86605550dd635c995626fe985aaabdd937bafe3e2a4082f0fc875ba7ea963a8e5987ad400423967bba1c0e369263ddf16fefc88901be069fc617ba6dca90608cd4a9d86476f8cbb41fc8197a9ee6fb331aae55959d107bef29b4f6f064651964999fb8dc904b8193dc7582fd47b0b0fb912f1c0c3838dd489c374ba5ea614cc80d4d196291c4a54989ae628dff5beb61612353ea0cdfd75962ab057bac887ce7f5df01861c769b88c7e1682f0ec6f7cea63598c3e6f41093d845db95377654fc56702a4110810917521ffada7432b7b16a64699e6a955a4273fe9220976f8b1ae9ea79678a3a74344a44c32454e7bbbae9a1fc440811693f66d63663c84bf847e0a2e8299fb0a6413194231a666a2efe5ae1c41db1cf12dbd8d58408cbeb1a9507b5b09ebf416f712b0040f8300dc5188e673c5ab1f13156718031f25cd5156beb8e77e95b48f42d1361da25a94cf1bb4a2a5c41f8da5c3f6a30c00e7d0323f7bc14583fe20815f468928fb69a480673b6c775b2d1af6a176abe5f6c679aae41ee1d5c89439a798823b65ef718515ceed5a7ec87eff54479a9afb48d0fcdb9a240e946719598512220d2afb20840e3680689cbbbf096e7d7505d1d854faacf024935a672278c5dfad333373015b11571b2a7329a0d2fa792d838ba3fcbe5303f84cc6d0454b89cf740bb0f83b79c98b38fa17dca42c5d57d8e86cbe16d46c4c0caad1f55ac4a399d9755067b642299b6b023e47ef74343b9d856545a51907f86034397dc1cdeb0856ea9fa753ba82c5f7e44e4423684f1b03ec59e5cdd96c03dbb1421e89bb0d1dd570309d92519e2b90fc83ece91ec6b13134cad1272f0fb1092a21e0066cc0a783e566167b52856fa6ef12aca963dde340e94f04980279f67a1eaec339d0656c09a3fe91a2b1885f1c09e831471ebe78f2af2efa1fe5821034ae172082de7cf5fd8599f7c575311d35248f2b0e6342cf7ac4bbcd19942a74ae9a9ea3ef5641f70ad1746406ad9bc24a1a3ed17dfda75ad54fb920ee9c92b792b76d42cec2c22fd1bb0f7acfa398d82b5f016f2943dfb44ca1d96b2a54ceb7595837379d62feac76dfa610a82ec947047176aa74fa8d58aef3d34e79768ba7b213a8c44c6e9739f05eb197148b2d2f3c5a1dbf0d4ddc4ae2bf0eeb93d2d4d0990c2c21ae34300a3139ccb5cf216b4031f5be4fc61b137a952fd516e45236dc791b692910a09a600fce9c14ce9e429ef1ae3ae737ebe9921d10522a4507d0794fde66f639189cca95923c51f97cfde4d57c718b6e0ee709227fef69a95a229ab54a4ba9d858115ac04dd0a594ee8fba7d29a23d8df53c131dbd6f7f47c6ec482cb2da38e98a8bb51a2878950877408f0892199ae4e94c4c8eeb614eeac1435b2947ba67c30ff52ff4c958eefd318814a17f53c8ae691d3fd91ea8196bd82d4af9fa216e32636d6535d5c68f579d3066654f2cc067873fea5d56f9676800892f210363fc790086a778fb721854a0abf9a2403ac6de964c2eee9011a44cc0d66ced8bb0634cb986a12b0d5d875db0f26f008555f7ff57f42a441250dc5d13dc5342ef36c288127d46b4a2cd85e5189877003589579aa787c46843e47666be2ca6e8aa84e065ec77f0f77e5cee75785e2358a5e1fd7d540ba1d36052964d7a5de9d1598cb71b238c6a6f2a4b6c72d8c5b0a4c2f17342747dcfb2bf7bc52256fa21741e1f8e7c2b749005ef240296ff9935f75e943c2e725e9f54636c3466450a49eadcc6f330558f2146426fe6786f4ac6fed1943d616474f7665e8ecc2612479eac464c8313066de5fb652beb42ee17c0d9eac4496b5a732c3df31d90e24ffa8eacb12b72dc1d393d0880959e0ce9db8141ae1490bb12af9bb2d12da5809a348714024d7beb73dbdeb4d7adcb68c59ada159fd1855ddfaa33e0b985d7bc3f509e64ee52b5057656295dc669939c45d89a07f03c0062e20e309a0388725c993f74cfbb8db38b85f13bae8b27a4da755398f228d79eba2ad5101d80c75eebee608dae268dac0c3a1c63e311fd82cddb78f06fd576314ffbee8ed598818894fffa54b56e7a7be5c20ac553d106609f4bc757acfe7b116f695fa4ac3ac93bd0de4bf87aa6aca5535e467298aa934c11143bbf39c464db663b97ad416b6501daa12fa8d9aaa31334851f36f654356467cf4f42fcf0c4cb239c2acf7c7938c0760a6a8f953e75471881c59293285241f7b73e4b3dd5" ++ } ++ } ++ } ++} +diff --git a/consensus/common/src/test/resources/aere/registry-v3/n12b-rotation-wrong-key.json b/consensus/common/src/test/resources/aere/registry-v3/n12b-rotation-wrong-key.json +new file mode 100644 +index 0000000000..531040d2c4 +--- /dev/null ++++ b/consensus/common/src/test/resources/aere/registry-v3/n12b-rotation-wrong-key.json +@@ -0,0 +1,51 @@ ++{ ++ "description" : "index 1 rotation's falcon signature is by another validator's key", ++ "chainId" : 28001, ++ "requiredSchemes" : [ "falcon-512", "slh-dsa-sha2-128s" ], ++ "ecdsaRequired" : false, ++ "previous" : "ok-epoch-a", ++ "expect" : "AERE-PQC-REG3-12", ++ "manifest" : { ++ "formatVersion" : 3, ++ "chainId" : 28001, ++ "bindHeight" : 2000, ++ "count" : 3, ++ "0" : { ++ "id" : "0xa5ea2fcff9e3cf29d0c6f5f147b67ff24aec3bd4", ++ "keys" : { ++ "falcon-512" : "0x099202fa37d5e165b88428d963d2a224b8fc82ac0e4b3f6a02376f18218d1aa7d0e910e71586aeeaaddc2a557124d6ab4f9a44b9cad02166413cbeb14b364e13956ea326900eb2900802644167639045d76bbc4e051654cff404dccea94402141ad9fd992cef7a8fa6478b3e6f8912886e9edd1b34c29385b7e964f360e0fb1600787934486f461c95d577d2bc74c4dfeb969b4798565ce0225ad27aac052290a44f844ae233e082c97e4498a31117ac9d02f3605c856e2dde6f611812161f89cb3a54dc936ca1e740a6c659405ed586a9a963b11c89b01746325e39e645c72b0c7e4491b36a17d43ffe38d88c601a5976f5a9636c964a012bfbce5f9b371e7c3b38580d81c6e12b8e8f2aac219f96245d35b4f4afa6c94015b055703b8c4dabaea4ce2577482f5b34fa49e56a912dd58d74580b1f94e1d2056594ea64bcdb696b0baeb33c86b6544761a3ead9ba9888cb1ad51f7027ee52b21e46c5eeaf3f77bc0af7efdc87acbddda7dca00b6acc665002c26447e5b0e0bb5ba261717c68dea7f1576462776954d7249c2fd0886f615ad50d53960ca02d581a4a25517c050ed467c7a820bce6250a9ba2e44fd67fb21bac843bb134c95360dc1c50d54b7280a94440d018181a9d6374bc64d782c84471b47287d8ea748c36cb83cffe053cb89a9e4ae71df497871c2a728ef210903e5b7f39550d0331e15637be7e28b3a2fc05b0a9b0c5a06f9fe81263c3a94403d6c288a561288ebaf788bfe271a578a1a795a85e9d452b61ac204b297090617286922376bf0a8d67dd35fd705b81260b7aad30132b965e39bc3cd64d154c4175951704873992a814814dae5c6bc1e89a83dd91144cd1b88f6ce449900058afdc53bb44bcab63d30cbd6df115a5ee8f5380a127a160e922bebf7b408de82514b2e2550a0931e065565e8dfc389d454823a55b03e5c989b09e3791f656794e8379b7b4b1617aaa9770366d63a657f71ff40c69b1d5da518ef1e2aa42366cfa38e448563f6c2db5e3089bad5520ec26105fc885993630c10db357883f588a5a384cd6de688e1bc3b1200f87ed66ba3d4a4b671b2a500a0436e0955904030d76577aadddb8c1ed21b027f198c072f654c3abb086e7f185980f49d0e109c1a82741809f8afd15ee56a887b392c5b172ba659144a7e99e25ba19792d2a3c0ccb481822839c8c70c65c0943a2994ec9f6085b7ac64ce2b35489a72dd6693d25f2329264e063db26ad4495e3ad00f12df8cf914fd846", ++ "slh-dsa-sha2-128s" : "0x686b5dae4aecd5618b95c3b2a5792888513ba49dd366ac39b7431ef403e04963" ++ }, ++ "pop" : { ++ "falcon-512" : "0x391de378d9ee4e1d810e6ce145b1819f1b73dab7f6dc2468fa65d1ddc8e2a7e6fd8f185f8945700a938cc0c5afd87bda48c1b8167c3e6607ac864bb2b194a368c33cf8ab6a5eebb9a704d4160b068184264c2e59c4f82b9b4eaa9197c3ba5289c429e0f4c548769279daade1286d354212b1ba2ea4818c974c17770dbb59b65b3b9f891c826721f51a7ce14f94e2ef4cab868cf852ed9bfb17cd33ebdc4d688d6ba12c74aed2c8104d117574642af25e9bc91ba3fdabfdf1ed13c6e59fa1a0a4388925d2254195c666a6c235174a73125790bbdbed463617757fcc17cfd32da7c7f89e755f051aaee186665d9de393a82508d15f88db0271495c959bda6651a81a04dfc2103364f95f5464effde48f3b7ea80af9c1bbee99c9d39b0627984f09ccc6a4c888d121ca34e56760b1c3178e48607325676c484f4d666681f0d2454f7fdc59cca37136c5c06e746987e6a116728f8b0ae1ae9a32efdfcc956fefa55577ac670bc3d66016391bbb833d97f91d3a78696370a6f05efbd77cd50d4697c3df5699277eb1cafc1883776d9ecc72a763e5b65dbdd184efb9696cf58360e73f2d4db5e8bc6ad65bbbe7a8a994f5073fb4b12ad9b5196c450e27a53d8ca231f670966a238a6223b47d90990b1f6796f93eae971d4939d99dfea29d4ba2e3feffb97c0b27d6b6d2ee10751e75c658b44ee71abe9230f74a0d7f232329b165f5b2a3e584dfedaafa9ab477c0c516b6553c58797421f8d1e9236f992b61963c108752b1c43278a9b910926b396292fba67211e9a16b88aa9bab7b6b6db29f30ab5b7ef1568d46a010e8a27144a5e958022be5cf6bf4305f14e10781323acca3bb1d6b567d3fe5f652661dfc54d71ed9e3969289c29bff0c8972899993505cde2fca11c821d9280abfd5c20d4fb53380", ++ "slh-dsa-sha2-128s" : "0xee44a0de25b75a42e32080200c89b82e2f89551d44da272720c816fb144aa42ca29cc7a0045d97c82676d36286a9f1bf4d5b9e44b6855d90f25e03e3370cccc7665f3c7fdeb6f9565b76745a7652f70b7cb18989582559b81160fa32c7db7915f14c657ca37224955d174cc69de41774e4ac576f362306f3383733b322f8b333d9d0dee44d80e36a86491bfb7441a3c66809bc600399ac9788b4d7796604d4ec423c40dc1a6fb2b02db9a0d35072cb5aa617ef769006c504052596186ac0d504561c815617067f669b29757aed1de7a03c9c0410fb8b040dac268aa95232533eef1f69cc0100b33c9726d55af73b5d608b501b0470c4e9340b68251fc645bca481dc2d375de626580faa7b7faba8f8a596f795481cac23240854839a1100cd92a6410291ccd40cfdf1f70981c568b32904a0ad649de41b32299dd5a8bf50c35e5dbbd474c258946881b49e335e01c72ab6654741e657bcc5109fbda7297999cb4b272302739ee07cff0d1c9ef454a5dc5403cb7c170337336f94d56f6ccf563af44bcc8382de301720076a7ac1edc1ad95dba129760d7e9cd4df609bb8f7b389e7ab1e85e1b54fa5e3f2163afd7e24c5e5eb61a9e8e79dccefaed30f5fae83bdbd8a1673b36ce894891720b476652a26401e7890af9199bfc74fd0aeb6622fed8e488b8151a6c51a11bd808702f945ae9f9a016bdd94f45279d4765bb376df7fed5506b52b74c867c087c3386f74b130cacd7bcb4e832b697b50c796fa8fe4881c3f994820799417885af464f4f1a85989e5e3b54c3bd878a7ab054bd08c1ad850c96f3c0105380323908fdc94771609b10e489a8445f751f75a9b617cb1aec4460be2b53920e52f7d85096065fecbc6f19daae458f657dfc894758f3d9a6519fb4276e16b38aaeebcefba89a7686546901c57a29b95266d7ab87155a854ba9b269ac94a279e9c4bb38e6a4928cf6fdc3984b4363cc44e0e3cd7a7edf08388b9ecd5a04c55ac26b98f98cda79cd3f402caba28360899cca559be68d7a825022f9010e65f9a6564fcd0ec1cc4c0f4029086c90288fa83656cf2ca2cf30d5c423342cd15b9197905e9ab30a9d147aa2599abae71070e40058f0787ae39f39d6e5c1a8184b2cb3b1e6e45c40c61d46af8490cc9af6422a439f16adfe93a3cbe88f63df5eb8fcde9ea111ca96ea7be416d030500f2c7cf967dcaa4d3ed76a613b2bcc034ed3aa84f35556e7a65a8798825b576236798318034204f041dc59a9f9c407d34c2ca2d77470700ed6442cea5282ee99ceb71c6bf074423dc0785a39b89b062f89231af868812777536d0b144212d5b4b6fc7b87ea04fcd6f94438704f985b746a13dd519c57260f87150db4dc483b664944b9e805197df797be099940fed468b1e214ae99a68e99c6b5cf3d30fdbb1b3cc009ea58958eb4c4a7b7bad6b34fcea2a87eeafda01dca5223458affe54422ca70ef541ca8437171943d5bcdb70eca8de02b93098653160cae52f4d72fe5a6a7ad51c6465388f0362e6e72a3c96b9cad2248e8d9a2cdf89747444c7e51e2f89eb19daac76da37180e4133e0dcab15fc72c7bb90c1024d03eb2e630fc6d2537a101961b388e32ca5019a626b5a23914b06e7822905a5e3c21369b69fa63fc9f43cf7ecb6749c668c7a940b82f88c71802ce6e3c68b5c10c9249ba356bb3bb0539b581a8bd6ca141e5dc2b5932251746c1fc1c3da475581f3e3717f5d905f5ff3c83f1523f57cb750dabae0404beb55aba1105b995268906131835718cd43240bae9aecb30c794a8b186436cf752179b1de65b2a87917147612e3c95288a3e816238b3fccccae1da8041b4f784ddcb3d37ef3f019ef997bd8a4e172d397106a5adebb166c5f565016bb1c5f7f1a0cbb5bb22cd642fa4390ea640c04a968fb5a49ef929df1cafbb69c124ea58b31bf066be388d7b6d4c52409581da785d6447fd72b54949e4c1ad08fa64b520f2b8df83bbfa417952b87fbf802652a65df0d388ea32dfcab3227f645b6b28b66087819b4339ad171a48760e2bf90f1a01184389e23e7df583eab7c2dce385bb7a4d60ae5573966f916bb84aaec6cafe710f839b103532f9a7a556bfa116a05480386ddefa2858ac7ebdb58664a0e633a53e1685d71d5aad11f5eeb3d9ae30ab120fb88f96f383bb86917b72e02768f071ffca7e3fc2ac79846a36f6bd72c58aff03f9e87fdbeb65c8ce5976255227778cfa40ce0eee943b66a382e172abc814ebbcb0bf49efa75f87ef8621d227224b7be51b73a928c23a8937570e1a046bf1fd4c6993a9c14e552915953776265f78882ac8302f70900f9d612d2e7b7dad88cdedcdce7e615baf89ef249d6d535f92a2ec90a7435785f4d0c7a75812b875ec22e638f4af1705cc362ecf52c67900c888d068dc6f72a161013c30dcaa49cbf25c56e8937aa4897451061dcc7579ca99a25348e76ff121983444553419e820a3d1a41744f4227dca054c454a6497e0762155e2a06d17acb44ea55f54e4d6d2e1631a63d9494cf69c38ba66deb9d95c0ee01950dff8e6a5d1c46fececc7027997b8ec626f8405ae99ac20600898fd7fc422e6cd3f774b4009f371ce38e1f089ec93ec0a48d6bfb90ee79c3bcff321eeea33a44022ab910458984b75c5089cec0d8beec20c4c39311b991154fac7c0461b7d667488dc9f0f5497cf66166782e2dfb69a71031fd0251918e4c1243aa4dfb9fc2b6123b4f02f436c0f8737a6663af2b99fbd22c6af539ca9389bfb4e55da2c9ad42521ca6978f71991f53fc8cb227e228a62f3e22d7c3eca8ecee260e55084ad3ace0d6379d5eaf82bf6d3b69c4e74fade4210114d95b41a4c004858119a9a9b178d5a0cc97386bfed0dc6edbac5281c2842951a0c4d7da10207523973c676b8e6887a087c1c2f156970cc6db9cbd3c8ec1c9c1bec41fcbfdb4e8929b67e6c1939bb990ee2cfec3197b4ce824d25a7b4c765945e85ff2b096037adc4dd763b87850fb39aa98f1d395c9353ae3b5b53842a7056c011fb690e856401fc6f67b1c0a5414fc229284e74c230ced260d4fafc5fad153a5154d35c3bf9c559239ce18ca9810a1254a0a6c2960a53d838431447739261dc3b055a0b115914af263ac9fce2b512884620451156c40cd84b7bb2d449aad243a8aea3859412476ddbb5eb73028bfc6b2a942839e363262f94795aa45f6579680997d6acd7a8c8daeace08362fcd420f2f8a96801c002361b942493cc5ae79884eddee989af9832d55319ec033956660c5f11b9fbff9f1410a18c0e9a38e9261bdd13bc392a18a3df97aa33e7f59c125f88d78c86058f3c7e9a9d3b37bdb1e05d90375de0090b418de3ca761560f079a6ddf328e72cd89dcb63c9dd0357ec736782696241e2095aa6107a8bf7bbcde26d5d14533f28ddad7fe1b3f0c181c0e6d55204f6ce79cfc557cfb2d54cd2f33adf17a837243b51705bca7ad8cc452e5340732e678274f9eb532bfea122cfd2959b2499ad25a18db7dc387e976f8b5510821cfff778be799b80505cf38ab1ba6b01561ff81ef17f7735a1ed6a319a7f571daf92afb7490fc17064ccb6a8453ae6e66a2afdcded0c7359461278c49d342df84c43a0607b7327853db675e4c9ca95c52ae013461ca0763d157ac992e219a6683a547c32374631b53138676f50ae0d30588fb25de808e1d9efd5fb9485192428477c2f64fcaa862761c7f5505cc650910224400e2a2db13fbea0b0cc358d163c6d4a8e6296e4c9554078a55f23e60de9bea12ac199cd19b97babe61b2a3b853860b4441ae8dcd85d59695393816c64bfc074e945452080e15bcf6776cbb6b251c13be63932702468679b2bd7e1693a1d910e1b62be91e177a8dec8e4d7642e88e513e3a871ca502854ab0fb7fb8a099d0e0dfd73064012051af337abc78bbbc6fa2dc7169ebfde2d40167048d78f12cb5e7c130a2137a0b26922553f43aefdcdcec55bdbee0fa752a4787ea9d1c75d1bcd9d28135515a0ecfa9735901a0eb89f915d036e21263f90606f65e62f6e5c8237db14d570612611b3ceb4d026ac13f473e5706cd7975c95d49734253757f9c1e6aca9261cd2b95722098c5f7c74daa6c926ea4867ab54e4605a15bbf7ab94348d9b45c31a1fbdc7f420cccce25abb4249cf413008a01e53296318414dfac822cdc0bfc4298273f65cda3fcd61236e255dedd879fbf20b8c4843e27ef413c7a1ce2c714c88358091abccd7fed337a7d4f725ffbf7856ea4694113d605b1ff7b2bdbaf60f7abf7d43eebb1e82f4b6b7f3f8fc23ae27b09f78a7a3b324c7790431c800293e08fed2fa49aafe8f5670d4e6bff4cf6e7924993d6e18ad87699da99a2f2ca9f3c7b44b3b61dcfa5f041f7a6df94131b8e5c04069678541c87872daeb2943902afa6ff4798e45a75659568a02471afde44f8e116fff4eb7c16053a7aa370bcddbf5229c231ef8f2e642c1a88f90e0a309d24a3ab28d3adc176665e522cf5bda0285baca5bf2a0fb4c0fefff3b8ea1522c9ef29342ea57eb4f16d69bcf948d66247ed2f2cc4e567476f736d170c98398ac7c0d158f294ff33ec8d2794ec1929c57ee6d7f46da8e40337a2b380717227ed82eb13a14d129069e98cdd65bc34472fe1a52dfa7e466e559705c53d73d97239e38bbd600aaab107ced36fe7d8ef2387a05d8548a48a684fdf02b984022aeb28e8c5eccd1941ae19d2cb12a31de296b4fd1409266c43118848962e9e59a41054a52bf2f20b09eb4e77cca72df70cdc4d712d5c0313ddf9ec8df2d901145341b3ccfcbed77288ce3e4afc677ad8681c746eca02e7f7538d0108b68a922a21d6a8c2cfd67d8849ff5779de1c00588133309d4158d1738e508a1a2ba3351a46fd3f86339d66b1244bc2788de3fc60144d03c08b0ef08914088f9ce947d2b230ffb9ce176a4bd45b0c8b100e17ec7829eb1ce10b1a514b5e33d4f40792f0a300a4c3ba7a912db8e19cb72ee02ae8ddafc2caf116df905640d0cb65cd0c61d38e0a9741d3dc2b7677e8ec051d329183c954ff9c0c2d8771182d5550a742ba8147ec6571bde519c2f57f10aeb1c8900f8324f017f3b1dad92fb0d19a76de75c0c7cb67d079c8bc0bd7355fa25752d5d00ab00f9ab332aa23aaf8b5cfa4d2723b2020c9e494208c61a76e18c9a583172d6ddf544a327c931e8b908830e46f184998fc0d34ebe767e4f5d06f99804759c7e2b76a8baa302d6950f90194b0cc694a0d351374cd028ba6b0414377a850ca2f209d13cb7daf43d14f606a0e549ce14189023fc7b45e2b095a3f45930a72296eced3e2da24bf237959c0b966bb88a3a9818932b1cd41e8ee002df515ec94901902b2e67545dae53e08810b99dade7b579b847a6570211687a62a56dcb324bb442c4fc22f9d85e54b3f939937daba84c86fcc36c83ca87de70fc7f4afed335e8f9aae027e854e3a022a053c3b22be3617240f1355be9af3f4c8e9481005cbef07bf1380ddc012412c31b221275b56c3ad52cb2f7a9b340526e6128416025d4fe497f2d502070653d36f924420c0844b5560a8728e4a3be8b1ce67a1541c00e97aef9c808bd77af5aa280690d98f5ec218bf5c9d135d85069405b82c221d834b8285402f481b7d51ecdca91c4c2b27c12f486d382e0c14ec23c2bdf33ea8ff693af551fbe55e46bd84f335a68646bd092f914da4954c57201d7e812f4974a553f043ace9c6ce2c609cb4d90dc1ceacd5d610cf4723024538cfedc1bb22c9663ac541f89f97b37d2e1b4d8073ada1596e684b94e74c2c2f0087251f1eaa6789ece436b2940d3285f297cb7482aa9b8c47118a0b1d2031fc311689828b64855bc17306529e4b0a3326438b42698dd4e2e0c2f624aa510a2363583cbac47fbf9974925d81af9534d0ccb41e2b445eb19569d703cd8ace661139fa344a5e097290c233114370831d4710676f7e93889ed533454928333655b06ac5ae67f301f2b7944d769892ed76374a1f3861c8624b2a302df1a2f1a60d41e61379ab3681d8eee152c251e1b7b0806aab2f287338b752918cb989d864e9acaa92944f5194f8eba19a18a025157d2c3988163baf8b7ca9060edc2227ade8e05348d86d18f9eb633e4f06ee346e4c2912ed1c763a75fd1baf32cffd0c856ff9b44f1470136c0a8ae0b88175a7e7f993d8469cc8ac3f643aa7db36992cc97011be0a42ff1df8aa7cd82e260e05fdd67304644335b386c7825858a438c51b63f877af005f7d95202b54a2130a1f652ff7addfb798daf4415572376fdd910cd099066e8d2fe251a907e41bb950e960fe5116f4a4fc6037273250569b41ac07002ecf3b4b63f8b853f9693badd2e8bff695266095f4b2f38ee4d60428a45e7586d9d47c01c12c5e18d1ca9afedca6f03384567ddc730fb8fed27516eb7c54135cc7447af831f0c37727997ab2b01fdbc5e12c112aa987e95cf5aaaf44be14bf4882f49cd84894d555655d17aff21f077b2cca1ff0922afbcbf4781145cfb87df585e6af1955db04843a763fa735d33b3df836585c5894e5125d500673d5e4d0bdf6708d8d28c80298a9bb47c7430ae8ec52285a4c14371b3f8ac1e21306b34bcb0c1e3aa7a8dc8955cd9cac32a0f69d0fa0aab30abcbeb2c21d655ccdbae1c2040faedfc7a5ef29cd5d9227908335ebd257ae8c410b1916b9a5bf0e72902c2bcf701a18c1fe13695a8435b0d0129f3db883f428acea8b7f274a629865f1849d4c263a1536421875ffacf058f0128f0d012fd60f2b3fa6b71fbb96f3e1e33faa09b1d20b0919018e91a6bd9595e9c16d4fa6665c4d0adbd77a59cbbbd587029a4f306c887277a7a27748a6f289edfa16c7e4042fc81355b85a994cc6784f5fde054f188b9775836594abd82c1309a66db4388ad49f60794d8c8e1fe279f8965312a1e23c2956427bd6e289e55ec728f66c36526d40aed7c44e5352fa3e2b5d27bdc1f7b3bfc4f095d002bc8e7b2df2032daea9bd3e0bed2733e7ba13c6d8b45c492becabbef0e8c62c257480faaf6aefede888ce1546046f04ce7e06936cbda44c5f33c71c07b53fb3ac7a72c3770838471aace69f7ea454d2980fb5462173aaade7964b888606741270f92bc18950284d013b692bad63ec3726d8f6596788a032eee6eba08eecc836202b06ca43fcdb062e65f8ec91f7400963bbb8094de4b4e1042e040e81130a3ff037e1b7e947b0c3e8b7ab5b539f8570ec2cf08971a1bf0d4f3e8311b5c625b7d032fe2e0603ac1a4824432b4c7bb5afa190afa30c36f168d196fc89015aff8229fd4b299206e8183897229e95ba06324edc1a9ac81aad786d5c9d38c87c48fc6159934a8532489f06e1aa314a057d91c0f7218861ec241dfccce63d60bfa624652795229fff21cf5ca61ce05ea0ad6a1763173675377d1f2427564e397683428fbcc4b97495735d075f84b289b73389a1fece959f9d9b4932f4d33a0907202c650ccf65327d24cc24922d0d675fb59621e2bcd2eb31ed1ec5fddc96593d4f936ad42731a50f164e404b93920283bf9fa43f8be5878d18e07cb8813914508532625f71d02a615bf47018e3b3efed72d17e0c974d33df18ae70e3a4a743ac3c955d1c366bc94d789c90a8b3771969210c7f0c4b9b12f9fedca5d2b71b6c04e7024a0a5e3d0d3c7d30cf568a659cc17309b223399b39ee5efd0cdec3a34b0735df8d7e0bafa40a8aefd742b3e0157fc89d113af5fcb0cd136a9cfb82acce406054aeda30b83ade59cb6771c366c86b5d9b016a74f220a967b83254db3e24d3e1f5d5e23b21354420dfca6bd8454575c6b0e528744f44ff8e1b9679b084d083b9ebeff09df273a476332dfa172cb98c79ecbf3ae4a722c25be71a3b206d848f56b02fd04bd32ff959e6931bf6cba042f9fde027d832632cc40d4320166f9644296d2dcc845491ed780cb609c0432408d08dddc70fa2d52884df47a55a8a3e706a24ac6ceb375a894636e1ac121040561ef486ffeebed3c5336d123dc05a5cf221b9e895f6d3ffb24b3674039d50fec114d3648d6dcf4fbc0b503658672d675c4ac64dac4db4615d011e82bcabd9573fe9e2af224103f99c4e6e5acd2196f1eb2260fb4aa61c298f99c20c4ac1c9e70a9a9e28db441c3adf2f2b3a00ca3f1398b5a112126fc3f0e2d11d40db36d0aa47d59cf8ece36df8daa854509e546295bebf92465f32a7edae6af4218b49781034329c22ce9e87258216b4a901b823a227e46f2938df336d3fe03fdbff4efc7b8ff8142b4bb60592abe508675d04081e5eee99468971fd49989eddf4648d3948266b08133b8c22ce3523757821a05f254cf5691848b1532655e85fece5eb186e87fea61936fa63aa047b5cb77c08aeeb2991c26619139b951ba4c2ed487703a6123c9c16d7b6cd3a17ad108fbb7c79fc3706f654be77a6cd8a5213d3976b1a4527144e788b712f37cbfd5f4ea5aa5fcc0f91b98d74ddcacb83fb33e039e1b88811a2138743ffc0dc5eae46c688f48c0be92a7094f92c2d4bae0c1dd95d40ffa113f27b8fd1808178be0c3bf77b677df2a17c9443fb6023c9e43c48614fd7d09a904e7a064125f8b7671fbb7529169138feed4bf3e6c215947efbf44fdb5eb1e3a5700fc8bcd1cf2a393ed438e68b607a1061e6cbd46a0b4f30fb4a492e786c5cc6d4f80542d64d0d271308ba072deaf7b1ff1c5200a2bb24c68aa2a5cd07052ee5760e0ede484e0a9c482cc74ab564654787e1698bef1386fe446106af25cf2fd950a78f4b521d547c83b6e4b6ef652444af342e90bb5761ea0dbf6b8c315996ed3d3a1a9d1e5f2b75ab18d0bcc87ee639299a248406d9deefecbb6883fe81ad12f20d80fc9b3c8962cd84e5da215b96bd457d5146aeb36d08185b2ee021fef7fdd43d0555c0fd16e7b66d1f534ae0b87f6299fc3b8e70236f39c91601564a5c2b3abce248ecd5450096e65df8b69de8b5cd963127f207f0df538f990bf29ff0c2930ab8b378b86d2619b150ab4dde82469e40e9e6e503182882b03442f92cf7449fc2c4b2f7ab91cf5ec57b8b0ebc18b27ad9125da57b6c139edbe7495defc73d68e71019b2b808a1ecb89fde58ed9dfce8b17e072170983e3dc3551149108582b95b2e4bd9552faff0bc7fd13dc0130f62a967761928dd62c9cae970ee447842a15baac31a280b443390bfefb7d4115e8d1c6458e1920485985635b75bf84b6af5226dd9b36c94bcd1a5f3ed99fc3e5adc6f3c4a592d2eaecce02d0e5ae97e6c4c7e101d4138e526fe3f090123c6df8596505b4d28c1be9e0c3f83dd4ac07946617eb553f7688f6724c8d8d34281a8c094740170280cec80b61b07eadb2c63427690ce73233f18593537e07266a71523688e6fdd36943d015c1bde058ebf5fcd12ea00e6b41565d062722941ca346b5949078421cf1f32fd38ce1be52fd65f2e9862bc5c57b45f33581eb72d387f0c212d68f85baf7e42058e41966429b0189da4eb4e58c1104e59d34eb0678a1385c38289210ac86f77cf8bef670b9ed04414875a29c27b79bc97e7febc40c39cc8e201ca56b25cd8c96f1a37ff688fd5d55cf5232d216283169b51cb41c631ca323056f2e8f74d5178a83b3bf43cfbbbb40f2680f338a89b294d4b611b0f275cc60e99bfcf270cb761c1c2a6773503a3c0e03b2a858d0cb5f81b032012bb0e15add080cecf19bedadc4d0c7e9d81fa75b97e7ca5e1c9eec88bcd10afc0d8e48f83aee498633bb260d731e0f900a9b0ae3f0d6e57346b8d3d8019bf079b4f909b6dce5718052416de8b61e9ef317ecf2faec5a64c0ce4bd5aa72b79360ff9b58d4a5f3e0648000d90a947933b0fe71d81ebaa96cd4c54c5d42b941e73423efb1f6626767f0e6dde52cd8796b0db31cedaad75b4ff72b83e0e9ece164c4f4dac170cca65e42db8b7ead0fa6e2f0b2d9576c79d1d73aa4b7ce4b954958dea381a65d4287bb1e02b7b88b33b2f1872d92ec6bf79fbb726aa436434fc7f2e79f0ff8bf243e19c08f680a5012c3c3d0501abb46026c420e485166fff457412a075086266b854aeaf5ac3a300ff5501bfd7ae96ebe56a5df5b7abb5fe2d9bf7ffc0005b6aae9dca8380a66c8c14e884f9f3338346ef1daad62042d09cd774b43016b0339aa208c5d6c2f7373797202ffe680edce71d684030e5841edd57cacb0cd596c63515a1b992de113fd2c8330840915d3409f608c8d43601f09dddeda6c504352e4d8ed932d8b5076a557fa2d87914ccbb0fed61c1f4d9950be0900b2212a82abcc4d9f4466d1f5469939c1e35dcd2d124623e2e1aa2dbe90ce09b958edc4e60d7e7502ed16a8a1d08dfcef84eed8a93d6940441ad41e493ec09abce869a8de0a778fd8df55cd1d9d7f053a72314e786088abdf968a3b1d1427e52427c2313182f51b5556466960017468a35ed2594280ad8493a5d3503ee4c479fd4c8db0141fb6b77331b46fb228f94e213ad372c09ebfc8bbcc79eb074162b4694b7bfb8444a4938a80747d2c15879e28e3cf44a8ac2ef8c5d9f93e9cb42f81cf88035dab96b6c078bceb4fb9cf293dc964b0cc9b722a84f3423bd4fbc57ad1f68a8166e86da595fb3b7a4dd87190dc65756e0f7750b68e3f605def2821619fb4fada9cfd1c41343dd4f5424a1911ca709ca745962a484d981db73a23a85c046a3eb73cb48b085d3286738e689437cd4976cbd3e2c5a4a4e385b3aadd09b08859bcf5506164db33d414caee679c65069543f1db8b242dc424af5a45bcb5ef9b939ce94e4dfe56ca25702d7912c38dc44d94670d90109ab685ccd59988bb7e932ffebc882b7dab274065578c041591d481501797b4039da17684a7242622f4390544b05023d3902949d348a44d9ff421d04a55395cb4248c7cb0f13b697f1423be1342d31fa9b85aab70c16bc62eae5660256d2472dc908768ccb7ff02cc84ffc6059752499711338e41d37f8751d84eec47a51c7daaa273e19c523d3d97ee5f71571def6f7268f24afaae71eafc84986eb8a0bdd50fa553c815939a4b56380b22b650fbb989b525d2862c5d420c83509b5c76b1a9a2105b45c2182331ce72e8f1804efee93b1929338f" ++ } ++ }, ++ "1" : { ++ "id" : "0x690a7fd66157e5b777256ea5214f634f61b3a72d", ++ "keys" : { ++ "falcon-512" : "0x09a89834aba90aa88f605981578667395d730a408f3d112231997200c28865ec37a4a1f044c8817949cfc8a4fd9028832fc406f1bb919789f2099629c2c8d6bd128de4f51c02a73c49dbf17883ef90a9dbc0350aa67e024a893e555b4f989780a45320af4858421346445f66aa86e4954c0bce0debc896f21bc960e4fbd4eebed93e943a40387210ecda652c36b6da73570500adae1a2a03284dc47f1e370570a07007d8c5a64089e81e2c4d45eb6ca01530884070d46f4605ffe139457d5155c8e9ce8f201715ce7b9d18755304ddb6871551498985ab400cdc4349c6b5ed10b76b425e70376e39a6167622eb5d4b7cbd932aeeaca53b3e28ea06c44780b01684e66eed712559543cea677f1d9807e2ad0312c42e43d399302a0c4c506da7cba37000c3ecd10b58922889e5c8d31a9882ab8ae4b69d3d3d3abc6450881e9b79d9e2ac51085f61ddcfde73e57c1784a6a766ee2bc434d4973a9667c1c8e00eba0c544a36c593a764f519de83251ec48fb45a63e00ad4aaf01d1a295eda0eb95b27fc364c33e3482f4e5256cd622242840d0630194316033219c3051258f548a23c08d205a7b15199ba8d6507565d06a1f20db367183d56d9dcfd2e12c36bed83d239ddbda9efe8507451542942033282bce486f002a215c2ef599a6619247888a81782b005acb3d550988c1f22c6b186038bbfe1c583d165588e00c7f0f7e462a778e6a8126be71ee0dae7b5cfc6145aa6e65c8c136d34f7b45252652995898150cbf177f47ca8d16b583ce5b0e809567c08b99c06095c879b4d945b13c8a62429966347946b606dd78803a3c8113a431761dc868ba2e2541c66b39f30ee21b0ee3fba5eee922d56f49ea60c25a1094381908a69b351e325357d9b4b9e2d040d8be7795891ad46a334a057b0aebdb2e5a9cd760b02c774f60df240e05ed3708840b1663cb435adf9929c138b9fd15461d86328d5895d8778ada79d9b567386a6302b67b4b99a37f4362dea36fa2fa1f1ee2f4f8293b131c57595468aa5ba62a03dfadc9784c8190559887603c4b50b7487e795285705f07f90d8a9ca50e4abf0905d7487f04549132cb3a62ac2e490d6d5bfde20568290b693681218426fa0458eb356b198b41bc60505afdf7219ce5959124e4d1a56ba63345f91ab39afd970997895689c8397c023b1c8b774f92f0e5940c764abe3bd609a0d50a98dfe291e1677e6232896ccdea3d047f35c558daa130ff53cc66aa03ca5687a2006cb7c8c3f", ++ "slh-dsa-sha2-128s" : "0x3345627b00d77c13ce3ebdd12964c45d0bec4dcaea60b64fbf6cbe7b897b8136" ++ }, ++ "pop" : { ++ "falcon-512" : "0x3906b14ccdbed5db7be47d08798522129164ea6ddb3dbb9b03435bc210adcf65b7be2eee34a0cff0abae6e8bf68b57594952e3a11d308d4a3b2182afc92b4d835f3f14b6009266ca17121aea6fb139793642168f298e631fa26d8be5e945fd77b159e4589311d7a98b2e964f1a158586f37f47cd3567ff0ab62df6c29ad5ded1a3715b8d96c342d0a51db423bb09171f45b2a90a7abef2056a5972af54ad8c4a1f9033c85a2eb17bf392c7867a4bd2b5035944b7a5dca5273e8d3a7a9cfc64c698047b2edec90dbc6f43d471550ecb03ff4e63529d7dae0e72efd9fe4c2fc5d7fd30d77b4679a1eeaa9b035331756f788ffc9489f38c77ef47338d6bbdd84bdc371534d5e60ff5ee2a49f329865e04610f9de2f5f420f51a3e0c84f7a92ff53fd99837278e17f4a66991f2f3a2199776331543d6b7c262c4287c45276c47ab38fa9e2de9a32185731f4ee6b1b6c7f71f7eab59a5a7fb54b92488431ee74a7d10841755548064b8496f12c669bd96499f7a20323973fe61b2ec8be9ae47618d927381a6f6fe57f89a13094c76305cadee5e737b58c41d837724edad2b5fa4250b066acf7e45cfb589d7e2c79d9f2a7cf928dd1a57930f8abdc1d64cc7ce84aa1082b1f1e46cf52a3366c1c3fc158fcb27f3f81cb94ccb6ef6ade8ca8a87f258e77f3308b123a8b11749b1919bed8cb77891e55eb79b41bf1c8a936ab2298a956cffd24ccbad08e8b63508dd1596374ee283c53ab056ff3ba7956ddfcc6f68c5f0b1b1248fe76aa3a346b64ce6e015cc3e2dfd5de75d0870419c8a4c172d964ebb587ddda7a5828f4fd13308bb6315e83d28c86959ed21ad635a07a22095238cb9c9a690d26ddf67e4592342bef6929482d529b037ed542d4cb4374b819b611bf69d3dd52e2a3635053244077d0220", ++ "slh-dsa-sha2-128s" : "0x6e16547734391aae71d29745c3ac8cdfbc98f07ad9a8470650f0a0085883ff970643e21b67d6ffe83653a99f2198f821cc080dd7f0cd1a612ab5c6f18d9903ecce34a5cdf069ac66483448219c06b131b377900b999f9aecf637713feedd8c7d4beb03ee11bb297bf4a97959ac5c85c0c83b48147fa9a3be7543ce1050394e83ed745f9ec0c555328d3786da46acac3074c0611667ce5bb4613436dac210c2e9cb186e9540d7d43ceed7f278363811083368d50f6d258a46a32c8df5d62c42c4f6f34c627076169428e646774dd6dfe6924e2240e720fd4d53dee8f880c782862de1ff96fc5204a17625ca008781cb120f74caa37a36dd20136567c05e8e7723a2e21569f065d4fc631811ed0b2d9bb67d2c82b755d14cdeaccb797f207427d572419360af1c443fa68064a653b1e21a2b83fbd93e38c7cfa5046eda9b86c68f3855c61cee9f799ba02e611a1b7df6a15fdc4b4b09e51b3b5e1101d0dc90a213cfa0522e93808fc4ab3d8cef74d279b98069988f6b8c6b4c8d3d62fe2a5a62f1a7fb0fbac7fb36529dd85416a330f35a7e4e161757a83282ad50ddf92c6096cc1fe071952dae4540e0c9d0507d4b61ad34751ce17fdf2e99c3e54cb523d3ffe2cbe8a5c58b84bdde119175e9599df6b2666a7721e246305457cdb5ff5ab4ec9d04bca439d59989253bbfd9a91cb10a9fac3134d85ef28f1e4d4f884aa195216a4811be7617c0d6004c7833088851fb7758aa5aac838ddc5e3a51d122fbb03b0b5d0a3593b2b97eb69c2266eb236bcf3134414536ff36895bb081e9fdd2e5a9f9ba71310af0fa126eddac07ca67020ddd4caafc9b102afd4d0bcae2a957bd65d0a15762b98f4dc7b548cfb463ae10ec3da3b5a4e9976b8f05405904aff74d3d536f9a321b41e0c1d5e4fdbbf61b42d868602e112b53552b8199a6618723e5638273822fe0afc5e6fe068d117bd5af3a1c1e8bb4ea9ae639674b51a523d19f950629a76e9a52c673dd153915863d0ad166d357f8d23b85010aa0b8263de0f253a0ec29b0973af15e4419d965164b5fc6a0e782716d86bfeedfabf4d9705e7093373819a814a45b245cdd13a667b31f1724b5cbffe3b5ed3087118715a0ee68af333bf26f1ac1ff13eaad6a5edd5e760e89518e24a982af4f44386c6d92db7a2229bc9c4df23274cb0f10d348f2373a79f55ee05e3dcb256df464c5f3e54ab790f1fdc585cbacd93c775e50bd02f451b69972728bdce813b46742ebe9e45d45c8bc23d4b298b5956e03b48c0a11c602ccdebace8f92e2521cb346f291717cc1881b0fe3a2e23d4ac694b7f1cd296b32b7f2f139877a129079a524d7e3c4f9c36b5836346a6944c49967796d8564ac8d2ed5e804a14c655ef235fcac5a8cf0372f7df952af0de7e4319089b54ea3f718b539a9bca631ea0bcc9259c64626d252245d541d90179364072b081d70da0a7e561ba2902e8ce864a398dccf55a4f583df7b6f6ad6738813eef6815f8f67936b7b842ed7dcc48808156d236d70a9ecba41994bc0296c3a236f2772c747db6ad62723c4457bf8a2e526f306d8012e04adcff0015a88167d199029ecbd333a6ea35f5b9dc2eaf11a14fd09b35bb2842a4e610da4afef15f332d5d1e82c7b0b452b7564eb45193af060595975d496ee59151e3c0f1545ef2694eeb1a2e38d4e008c0943c8e7f181a258c35e5068df39376aad6ef356e0010303d9a0dbcab91dc708b8e9482f50aa18f88f45864d539dc0818148149aa259eeb270a474b0a117de91b6834672a5cb4b5fb7c2ea0ea7e3bc9884163887986aff1cd89c49a6ca417dff067da528dd33dcd1f7db96ed50820bd72dc41984ed5c767478b79d8f61cb7b417893a3a4451129525a915b1e999086e6db74ef627534015206953ed3a5e2bbc5c629b00f3f3b22a37519426c20b2a10c60087ea32fe606d81c6457a02bdcadd8d56360dbd278ced2d4cb9af64af4ec77989475882f3c1c0b9f9e0b6528b9834e34024dbbd64dc19fab35f3bfda66c086f4c0ff06a29e9fe881340d1c0719ef568e3f8f683282b963005e93620c01de327adc0af4ea7f968fa987cb8f38350ebbb3b91192ebb009f9fa85657e06cca6f71edd3d0dbcfafcc11b908cfc38a08ba288910fcb14f97746ac20ff6e6c43eb099d09a717ac03f5e0600f0bb611d6972626999f5661e048476aa999c83e3f476e77e7ae09c6fb7c343a196e1846ef061be75fd8b662932fdd2c7d8784c6e498d4d828c910eca00ac199957fb44d572d4bd2c599fa6c7c2a166d96aaf4959c561d1e9dacf502f76b050c836194fe1897d54a017944a973f49b2ea59b66c24d18f13048e093e83af249854da9fd6b4974b4db3e8e65684b3b6a0a11d942ad5bb667460dd98ab54319cc2ab704a7a57c1583b8289477f5557d2da684aecf66eec3a54da742e2d24a6935ffc4f439d4a8abc21921087df93da2bbdc3a0f61729b397faf12bfe59c85a6af75c9f4ce4af19239840b57c3a4ead6096f2910da23bdfd02ee4f3676897f475d625d0e9a9cc930116bb2327232dacbd0ff32cfaa40aed89024b9ccfacdb76bae77a87b569582442ad2230c8fb3e0dca3937dea5685c46aff9ae6e16438e0e9ea8ba299936a42d68967926edeb3ef955d95c5a0b74a13edd280bdcb462dfc2d82e7ec89377edf6760450e1ebc61f035fff661173de5fc80dc66b8e3d38c67f4ef8c25c2c5626dd2875e10d870f12b3f36f749eaa0c82e94b2f30686cda1da606e0c815a35fe6fd671915483e1b2b48fab000ae560dca0119be7a0a3dfb347ef95c7fcd9a78e76911cb5bd438a7e96562e437e32eb399782a9498ac992716bd9f3d7d4e35a1f1821f9008f547d171ce2b69b007b5e377a3244092396acf958932616bc5cb95059762f48468a94f9f897736b11bec2ce0af9ebaed9add43bf5c262106a96083ad967b7fcb127012b1b37970a6be14cd9088f6ea927a66a76c35e1320452848bf7496fadbc613b2e122e55634f0491397ee5d211d780971998244f303802d7630837d05f3dcc588d8ca32e02f16d2297aa577576ea5c1b90d6d330a18444dba772d7aa94d0bf2000d598a069d03e7873f114cab9174af2f28e257ef2c0e44925da7ccb593d6183fdd37a1abfd7107ce02c655e7966286b72d65394f312d72505803bd53621a08100a041210cb912d5aef260b84e39faa7b5d8a539b6392b32ce6287e1a619804677b3f69ac46fbec010e726f3eb3458433e68e6417ee375dc70c2b2ee16b2cd9b228d6a46f92ba66a8c5b08cbd284dd759478c9f690c5e1e16d6332b5a0b9aeee43ac8ce3eb0c3eb6940b61a65bf7c3348d8dd15302b8b7bf6b6257e074d0af3eda088f7c22e6778c8cfef1f15d9f86c76a4b05c9afa228bc4f116ee8adb959b4ed9afb2307f2252b10baa436795028629d05277ea2722ffc14d9a5fd56e6cd6f0ba218675df025e50586e46429f1c6028e305d22b5479dd045d98a93fa30de08bec1576ea692bfe6b657b4be65578fa2dfcc197212643ec9a1a8de5971c07023abd8767c528025281f9854145e3d9c47e01bd37dc3a35b76639e4716465b862b705ebaf674a64313641de333828d75c16d4f6ebc4193fc2c92e5a3373fc79dcdd8505a8ea7ef8be6ffcecbb2e80017b6fe401e49193ab31e67a56e8163cce767abc393608e7485f41983ce27b9b1de1a0281f237d685d401641f860f8f11d10805fbf0c7125deaf583458787c6f2850b0cc8c62053e069df241192c6af9018158c27e30574a9025af5af73bd956bc008efe84b31fd9a49c110b803947fc939faeb773cd3c33d1b6a96fca0c079f2eeb4e3ff768bbe1cbada9ad22c2d97928389e5f7145a346931e4138d66319f0154cdf3b28cc9bc04139f92e421efb522d0639f02935e228d6eacf3ccf0356b32c163dff6b597d51b64a13c8c93f60f150f445271489db644665ed1208c025b35dcebe82e73034561704c602d1b24e04c08e4ca8fab21c5136b6d4b7af05cf8ed62961b4bc1c2883154116a0ca8933e36042eb98d851be695d8c4de2c2530372c606c93bab254d6b00e59fdaaec98c56415da26ea8449061e12bd22743a1a0e0e1e117a4a9448d75b3a9dfe6f213460ca639632d404af60c764d91405391137ab9ec4e8519d11e3dcae18dfad0404ce14ea4dd36dc3ee24b7a15709410818ed0a42091a01ed9b7f39f7c87d60d2b3dcbba880001a519fb7de152ec06c73d35c08b3e375b9186752931b6108a4b84189fe07a7165e18357a94962dc2761f4eff0df829427646d2210b55915be710e2a1bb413df2055e7aa0b0b9a4067d35881f22c08e61b587a59ef82ed4df267afbcd4c62f22435167f2d7a4a939eaf28a6f1903c8c046b2d7719b7134834cd56964ba860e60ebb6fbf4605a11b52aac2d595cf3b6533fe2452b65dfa0fff71aff39124a88e3e02977d6063a8370f98e3cb8c80f35260a8541b9584b1d2bcb315b394d7641ca56539b4ca8bd9e4fbc594b0a3bf1ed678be2f9a18d31d610b55ee175514738717d47e4821150a799ebce655d0c75228c2160aa1936dd42f9923de2ac97d0dc3ea062d41d5beffdd1d69672b73490d6a5e14a655228bc39ffc8f1e862fd39dc950dfe648e0ff87807e543d02c40411ddfc6c1f8eed733750557c9f68d830c83af737c9d8c3ff0d23987a8e09e6293d707940eef4cc838365775046af35dd26acfbb4264a9ab84818a71c5a13d8e615c5675656671e5fc2e91b682e91eca76ebfeb1c09334e962496f583affefc56dc144873c79d4df77da394845fa29ff348007c8ee7f23f2944c121ee3177879e6938eb043a0abb75991b3e789571e3eff009cf089acee93612e97be85e1cd83da9ff5006c14151afa67fddbd9262667f98df52dfded25f28b36fa32ec662cd5a6b0f844030dbe1c87e9e2d435fca1a81045b8de5b8ccc411a839064bfd133731f55ee2ed2ee727d9382d130ced8a48942ea295bcf75fc74e24204b808956bfc171392f18554764aa80e75a539941d90a4afbce1f981f0c35bcfc78330ecf3d416d0683c7682cbca066a10c43273a0f85495cb4916ec0eee9952431a11717cadc95c7626436953fdd5fbfbf9ffe329159d1bd79499807796d75c458c3e3914d1f73f656e9fa273244615710c3eee84553a7ca0250e97a0b8895695bf86408d2f3cb2fbffffd62c8583af5b25b7e2a38e266c9623429f8d80ab8fdda6774df598f966b86ac228639af66cd0e3ee7ad7714b4ecb42876c31eb2608fab0c6ee26e97fca305aceeee80bbe22cb5e9819322aedff05cdb78b1fb3060ef18ce0385ae0fe6803b414aaf0b340eef94a7517e5cc3df4bd273f92120b8ce73281cab96821ddaab08b41b97708dbc7d0edc49cb362759905ce8d42743f83a0d75878596c4c5ca878b7aae6fee6ca7b20f2ee60ea773499a781b958f4353ceb078e5c04b0fef3e0112dd0e3a7ef19e4c63a202fdcb8ea56d15b2fb0deee4198a19c9aa59c1ef2b3de73f291445c248779eb5fc76953137adce5dff20f2198cc9e729be4adf385e0f25f67f68c04b4cc26987c133b987f477d89977621b8313d6d18a5ff6a76c73ed608f5e4adb860e2e8a6cdf237d4871a98f0c448668bb42f29ccad560fc1e571f8abb3c75665a65a212fe9d2c1c48eae9b92bd0a8b7b3d2fef99ffaf7942f5834533a592423d2cd66aa793e85bc8351876946a1e49e13ee374609932ec1af8d4d3f52e00f783368aa2bba882cc91c5fc6eeb657f3682dca8e9d63f319df3bd1cf52c511f600a6c815e4ad59426d9e1f32831dc5d8b0673c7c58e8bc1601d241bcb76c1306ddd5aea847dc903f376bc4d8e73a55f0a5ad331f57bee70533b29e6b8493d9f11ce4f27f9605f693c05487bd43882ebe8a1090a95abcfc186d74a3708ce3351ce7226183a21c08497dcf52727b7de08ad6a970b2c9f314bc7b33995ffc77a9a36ab46c7a05f61315d18b3f2217703be5753b4ee1670eba3af00e90a94664039aac93e89dcaa59d4566bf286f33c740feb763d0a385855f4410052c52abcfc972298ce03ddcb2e65dca251afbbb75c516ba77001dcaad8470f61e3391c1c68b1b7dfac9e50d53d2ad12876ba96419b39d7f94fd88b58ac1c123790bca733b12dadec6922384c6f3b7284334bed918acc06ecac7674428d56496e9d2e8f0175b3c7e384218380b6d59dc93541ac0a7419eb0ced7ca8c12a487fef9ea50280b7f7067a8855e784362e85703f6b848ddcd4bd31293baecda021fcaa7198b27d37900ac192d71de4e5124089bc1c8234fc455fe71171fc44494395b323fe3575ac720af5cff428326cca56ceb0c47e20e1432018a769f467405f5a8b71e15e0bd32f027640212d893678ec6fa16e5c00bf5c0eaf2de0333126ebba6b2306211cbc731a6baa8fc5a64a30141a8bde237c217161e384af3355b4a253d35766a55cc69be97abead95dc2ccdb4d243f64aa6d74330cbb2fc9fffa79fb6b6baf99e5ba9abd7966efc1586e72bd25f6563fbe125abec67f24e3510bcaa34c49499811ad2425c25593ff362c90c5c4fb3c4c45a4c63c46cae8cb1759ff2d82ac2726b60b4f094b6344191f3828c78d369956b7a28f650f63260c2dcdfa66d1df4731866efa6a335281d1cf2ce3635eb4294c8b2e1d4b7ced7b4b58a10d693e9f5a269b9d3451198735697af3a7b4b630b835e3b56e252f71f9aa6dcdfddfae13668bbbe3538d5aca766dbab6655c4aa906e0106640d21c30f1a241f4f5dedd526e8f579848f1b64808afb54bd2737a18d9a0e4a078705847b59a1ca4b2b554d03304daedca50726cd23326a6507393b2dff27921b5d7d322cb9901e0efce9bfd95039bb3bf6a99282f9dfb1e90289e986a657b3aa212cec6e611423eb3e4523f4723302b1b4ea5db2cc3fe3a7f0f3add38eaf228a6f0c02b9237e4078b438c01a0856d64053427af9f84eb04f022fd12986287b48cde73554b014f75a04d01f7d3fc6285347be643ce214b72c911e6c5360909ec590ffec8b4395fe271e97af852edd3801ccf04d3ed6684c66c67278cf331ac7c9b748e2dff377cafc7fc6732352245aabc9f5f25cc29d8f7f211a88a7aac750e488ad0304b7907bb063e29fccb16dd7ca0b78fc3962046a83f9c7138d49df3b765df47829e5f56e5155dba194d5128648b92e4f5c11bdc9232725faea4b87d6d940b9bd7cead9462736c7ef605336c40c9a053a000ac390b6340dc85a6905d35dc83c2d13786d233952ca8777b5981b761376f4ce2c5bec0587c2b28aecf39371b8899d227dd58c054aea7257dcfd838c32d6053362842a0baee7f967b6a4f5e1cac240896a8ec8fabbc4a551a55e674dc8cede1b9cee3874ff9fd3b91db433a12e78904aa3ec84d57a0169f1719297b467c46b278f671f74b8bb3c2c0cc2a093cf93439c1267e3be38b12e9b5881c27ab47bb01397c6470b80174ede3df34ee51ac116bad6fba58f8b8e2c7e0d1dde184460a5bce9e1d853d11ac017001fccfd5b767afb69691844e8327d39660c06b8916e918f5587f5abcd0f0bc45328ac01b1ace66405ed6c7a5080f5795f2ba0c0d9e5d05f462d89aaa230f240fa47c5c0de0b2099e93ae8c0f94a45f0513ce2797cddccb5216bad88333f6fec5805e0b9474a18ff562e78dfe325c1a6bb3648b41595690cab5ca9805eaa8e13526d036f4233f8181aa8efc76e14031d343bd5d9023fd6cd6b32947e173807883b6a964d398d3fdf9f34a44bc5fe41c5d72ffe5fedaa13fa1da68e19656ed70771529cfe822fc694be1445c79a041eff9753cf47a48ebe9f2c9f1546117b97a1c2bd6e375b957fe38cfcbb29f8eb726f18bc6131b1e27316064980e35d95fd913583b9735c6bfb03ec86e935024e60679a61d972b4aa296189fbc268552acb6cd890c68e50e325719d2f2c99b8105bc92fb582eafc1d618b4e88070e6d8df4924a1780f63ee216c0e937073725353b0c97acae72ebe521fb05fa78a4d6ecb7ba2b860190b6a5c340c83249919c26466c9cf4a9b774fc823141f65196df32edddad59fb05ba24738d81734004c42a7f92f5234b7f4fc0d605b032b08eda4cdfa3b03a3b805ecf5e4ad667a8cf399efb3c1d6822d9d5bb5eece6e08a515cd75c4485537eed6cbd55efb0a3d393d2cdcf44846f0c27cf6a664c70dbd54fd56b20bcc482de2eba84163375b1bccd43da63467557828b791dfb0a976628206e26e9eb10f1e9b9fc34571cc1a38f54909a1ee0b097e0f22f3ca58b56c631708e9baa52d7eb551bd327a6e0014fe98f04d7b0544fadc06c16a5652ea16b6c92a014bdeb2c070843152847293a0a925cf3c22bc9ac23464919ba6340cf233990690c94601876bc30bd5283f97cfdee757caee7b7b41fc265fb2ca9751e3b523e8498d665151d1c67624a084571f6c29973e624703d2e87f1ae5a5e0dbeeb96f46698223e063d10d85fd13fa0deb3891359844ad5e8100036d9b70b3b7831ae78c927a5e2c2ec62992cc424894ccd6f064e9ac307e6a2dd092deed179cf60b4bdc6c56c32a538d477d7917f7203f898659104ad5aab3e520a9f21d9c01b581cc968a68a77648cd95f66b5a1eb1b9d60b0a73c2eb05873f279c4ce43409853df2c8db254fd5b63af900c764ad4a0aeb4641e1a4e4089967e83603cef0317d06d1b990354c11b17c83c2a78cb9152615b9eed33e20f61a83179748ed4044a65edf285b155d41c735a883a481fa07c4941865b86d3cbd54c345d7933e32daa90a1291211191e0a3a5015f0f60d2ff07782606c164485aa469bc97f74dbf1345ea631bacb972be00547074759fab2b98a78cc43b7e4fee587e40e23d9f8ecaf03337d47d27bce633ccd97c0b18509afe35d54b1761a4ecbff6c44dba5402f3111eb671183b5e6bdcd69398056b980c35628f03214e0cb4ee5364e51de27843ad6c24b1e972889d54ed2a31d74000c32fc90b3c96dc3761c9649305c5f5e75f5b5ab7eaee213dbdda1039d4f3f450c77e6434752b74a55c42c98719836fd91fceb27be449d65c89a823218e882b987277622ce62fd0b46130760f10be6b49ec57e25cf6584a99433cedb1ecb1ce25cbf5e2b6eb716c12064f2cc45f4989c4c1b6c1ebd390c44195a16da16340d3a8588754ae676a990df1eaf04336b3252a5177ca3b3b2afd8e7555e92be6f6d7e64bea52c8d25adce3c580b5731574729107afe0e1025e6da2f2b05d6cc223778ac7de1202566098d43d0e4db6df8d242b57353cbadc0711030c6612cb92a9f9685c88856a0739e61d08c8fc5864fb9d8f41b27b43152ec15b3307e2c6f20e00254984e6284763acc977d9e16ffd4ca8be3ba7a289e3c5863371c132b8300f59d50f9efd344d1cf51c5ac64f29210740be2dfb720397941e2ba939e31c9ed563a674628b6ec3c8983be01e41eca61f869b920bf08db3255cc04a1f459653a4a3c204e6ec5496af1984f5e47caf56993bce1124bbfdb5d7081895a96170241307f000ed22ba92d5f5d920ab39d3ad1e288abb76ec3acbda6a7779be4c65e99bc7d7d5aa57d08ca1774e0fb146cd3a894beac12715bf322febeb256518addf26df507db3c79cb2883e6bb1e4716e185026cd760c76038d52a2e0695d76b3bf9da7df9f4dea5323f7dddc8ea1a0031851928e354e703651f7a21df505a4e7f9f7a8a398582aaa9f504510c0bc6f9af8942601bb3a6df3faf2e97c9df28268e1dd466857d413fa0bab4ff017f12554dd317455d6c716f9449c5273ffc959f147d7e0da0c2eab432b83f96f7d2de7b1ebc41eaf2128f8eb8f9c09c7b3fb4e95bb3424b216232406b81abd4c0afe11835a8425304376b08a4442c6eb0e88a51bc67a49b143bb35416c9ce613538483c091bf181d322efe10b2204aa0f0e01507a7cb809cb54b5cca5f44c20da32b2b7ec52098e53de672795b68a44ba667bccac558210307ac27bc5c203a2e6a264e7cf3028cb4ed41e29bc46985c1440187155b8bd737fbf9480749d62481d805463d75ec17c7ba83c60cc7020fe4b110ab1a248f6fbfda3e5b8a688a280f87a53ea7154311951c2001a7894eee171a64cba9b19a21e09540dc5ba85b1b2880efc39c8886dee72e64f045d00d99a90ffc81fc957ee65b7bb93e113717e7e7a275814404198f9e9d33f45335908f1ae917e0322b3d12c3d298ee814d22f8a57304faa93c18a14fdf53f05499239b66498512a6856ea194705521857a1724bc2925ba34f0e2707c84ee234c3436b4d3ab46cab863a28a011236e564ddbab3d49baf77be49ff2f5f2ca75252971a421aa2d4975aeacedba6cd3629efef8b2322b516c60ecca2541112b59d73b88177cd3be06163a463306cac2c0c1b11f84ab9b2fb6ab776bf0dc0fcb381975e4c1a0198b41bf6c1587bf6ca7272d8c722a581bce4494be5431cc5e3038ec33d843b9049b018fffa03cb3ff58e5da6bd6d49ffa6f776a5c4fee3cb258c4bf92e5e4079e38437f321e0c29d608cf5f69129e705e66a7036d67d43fd4a2919271fe07052fd30c049b793d2af0dec2431ea687077cb7a7a5badc21fcb0c2ac10bb37247207596d33d1c2232fc2a225acb9f30be7fe6da19514def9b595929c1c0c4b146099bcd980356b601ed0701299ca1a5547d62badd0475bc76fe51d0565b95b52a801f14e1f1ca62526cf8931f0706e3a478d20ce7eb1b1088454beac15277a72c90dd95f6146f961e41caccb2cddb2cd0680760731bb6db221944eab186425b0c2caedd840be5a2575d8dfd5810c4db5403d4491304130bbc564cb578d814d952706570e56641e8ce6232a2d4b18941c35301cd5c29211237c274dfb1aae379e25efdf827ff6e41cade1d57ed229a6ba76bf98de6592e5ae3ffcd481b53071e452a0b25f12919003474bf4ad2f36138d3d7c23c89b5b41a25c3622bf1dab6762cfa86a5bdeb6f2baa9cb3ea7dfdf9bdc700f4062ce8fdf477a17088bb2bf654e2eb9ab943472dadd73e3b63a4fdcf90fffa98983130e16d512b54aa0d4acbb1604d00fb2adc4a88e87d466237ee7b0fb33e5f384656a8759143db4c377e2cd264259" ++ }, ++ "rotation" : { ++ "falcon-512" : "0x398c95150c8779a927aff8c6d9e3ec76e88a29b75d92eebc295296c2ee884f0a2379fa05bf5070639631133c9f52157b6972ecea3a9fad349a3417b92bc1b9eeb32505801a35cbbcb6546db5f67672940b1ea9fb8ab5fe58a3c9242b677355db84d2c9e452c4ccbd3dc4d95b2329b5631a429f4aa10a772f15bdba2bfc92a1b0d6eb02b4c70b45ab224b2c69d6f1ed771489a2c9e29356e63e3feca0c4a8d9bfe5f7c709385eb1225d93197e054b263e911c8132077a4564f1182a4691de144401f66b162fce3b844d67710d41ecc92398f3169df8fae4c76dd370355ccbfcbda290e1fa8c29685a7e077f58c9b675faadc3b9cdcd7df1ae9d6b209c4128f3492260f9230416739832c91a429ee2a1b1133699b1a427299d54e0917bd2047ad0061ba9c982d614350ecb0b6ae8b914f911a1b603344f954bd775f2f2311bb851ac8044f4eedf2a44dc4b1a26adb0d8ba9c7c344b4157873e72ba1a2d84e7d07dd99d05127bdb6f5d011e4bfab388ceddab572553f8363bf0d157b17a939bc96979239da528150b79a0c214de36805f170c54e9fbc52ee43770c2ea4d3dfe89b7e1cbe3bd0b3f7627db43e3fdfae3ecd1486590e609441166e24f2c814bb2487ae8e74a2d882e0daa657246ea5f706f60384edf767ec6465855328f3cc1b51e8669225a1cfdc21b9a52b6a661cbaa47e78c94bd0921c9474772e0c2abc9b68b9b3f848edbd2bcf9a531559a532adf16668220a55530d0c74ef93e52f3b2536595aea5362bc6fa14b0140487749722d3afb4bd26db204c62f115e01178626ad2426b7c058d0d419957461d3b9973b12fdf21e66d5cfbbed2c4c8e484ada7bc43cc023c2c99942314919a5f3a868c36ec3b9d8e6278f037966c8a39d32aaf0ec131b9350bfdeb8cba218387389b61d0", ++ "slh-dsa-sha2-128s" : "0x9ad59fc071d803b9023fd65b499d1f93f09fcbf693eaab05f864ad85c31d2b072baf524898af2096e711c65dd070168833d9f1565d4636f5a9c2e65d3ed87740da30981e2939749d5f4da0c91ca6520101a99d56b9215d3e2edd1e91df5ae968c04dfcc508aa70d16035ea7a7a7369c5f5e1b7edff39db94ea13ad4267802f87c11cee817f3f566d62e2bb68d43fe8ad9f740529b23aa944b73e38cc2b1d76337c9d7c020189e0982ee60d1936898f36251de7a94a89b8bf89ff45bf6c54dbf8651947cb181eddb6a2c1cdc481e552422225639534ad12345462c7d282324ec00e012515d2c2a382edef86fa87399de982cda3f59fb1cef212c09301d6eb10b6f5491d9442dbd70b362944a961ed2b0f588cbeafca796078f986a46dfc99636a31154f10c4721198c22f2ce35ab7911bb1f86fe08f4d4977fd0ba9e33efbfd8429fd2e2dece6ce1d1f798f7b3c501ca903bd248f977bbef2567c562d9f4bfe3ad522a1494a0439f10237e2758286b58a245cad505c662433a427b6c14883abe8be61aed798c4564c6c24dc072ef9d6b9ccf3d7aee26cc4e8bac1fb639f9af1ac5ecdfc6a412cca0a1fb5759230171d45886c0585d3634295bde2a2055df5c8949c2a52aade0785696c7c6fbda2db9217e71caa834c55f51646102e64d0f14ee16a18ab03d2b0c8540ad05a3b80bab5755c23a654dc60758e8130952bb1b1306e2e92ea15c9feb58bef481ed6e9d7335503577d27bf22274c7a079badb6117c85a06587016d1bbecf53aba658649554b67b2cd8dd4b94b519477f11db77753ba1408a62215fad93cda89498d14b387ded2a142bf5c6e85f2a658ee295a57861f9a408529fc5e83006a551a0f30c0996d8a34b6932aeb7e9c102ddc9e0559af6003a361ef9a9214450adaba2d2a04e11f27ee7e1a495c87da925f50d5afccd6eae686c100e817663aaf5b6a9bef72c928dc34de62408bcd72f791d398ffe61a2c6dc865bc28c324a2e060f2c7e2f8e9c6b913d6bdca590e81448e2d7317a661cb83393648814a2ed1d54ca14d1930d1d8d20a169f8a614393fc949063917ed099d2f6a7673df30ee8aa8cd5614069e4c612f4734b06130ca1351263249621db9f612dda4b853d9f9224ba624d8f716fe5e9eaecade48463d6e6da0f639f895c1e5f8e9337bb0e98a6347022315f729edd1e252ec9663030acd0fca1b7524391c3113792d3dd60e81b5b55fb58072db55dffe1dcfe8d531b647b5c64182cdf7794773d2ba27b7bb34433337e14e1c114daff27121a0feff0558254262f4073d9d692e662ca7773655ccfc80bf3b80fac6b507aac4c2a40345bd3e7598e2ab6eee8da230374b46ee6e40ada0e750d9c345e153f0a66cdf30cce8e2b9eabb46132db6ae6f45f87d0fa6ad092abc21594656688824da4536b5be57c3c0d7cab3bf21a268bdf0e1f7cdbf1e774d374bcdf9787f08631437e7d711d218db3c64a43fb5943bd114ac5a673082e8a687702cfe0d5ca620c994e0ee1fa76248972060f45ce79f25c070c1d147b9301c05a6cdfd385e0f5ba2ae78ddf2303dbe5cbaa2188597bf13e7ebab864d447cf06112dc1b38d1e9abfe82fc750585eb51b79f95176b82322e13a57cc6948a28728e98f7061b2a05967a26d19f81adc54ea613376495ea2cfc0c23b6f107c3506b33b367223dc88d5cc34342efecf9a7d66e9426c7e744f20cd89e26dc88561eceb65a16ceb6e330c82c9bd4b4d30cb5db50ad4ae0b2fd751ddb794dd434717574d4d485b29e9c767f8aa5c0277884f1de828e5e213bc05e75467f7b57dd36afb3d5ae2b48683d0b5dac05e6f104adf3afcc8d334c90718340a4c9ae880499e0534dc8ba48f605a38564275fc52574e0faa554a52c23f84853623c54db93acdc1c32a952593e5cd75e17e2619c48afd27c3cd8a3be62956babc6e2795565a48e21475a4679aeb9bdd13f5b304448a16e307b28791329173847d7ce6c0990b4a1b1a8278ad6671cb5f83af5bd6ecec387a434917f2a902fd36f7c79d898478a40076ee87f6ce03c6ce5b0bca864fe58a4a61ad8727ff11b16c8a28f7208b2ad4f2c30e79fea01df53584c40e8f3ddb66c3e4b25b7781c8eb144b55865bf2d70c8b8f1dd7778075ee906bca43b1d5092ccb811754c612df33566cab5c7e2b1e04670ebe50b2a4fdf80aa1ecabcc4366a21da389c0cc6ba252b587c714e98ee9e832c56bafbb9c0365d5a05c026db5ee72281ea64ef43c7da8c289ef3bdc82a78b7c1b352095e086d9b246e96d3b54677eb7af15121b4b4b59a00d5e247c9b22c98226565b19d393b5a412cfbb8515fc77f4e137fe2bd93c0ec3bc61f8c180ce57f45b9d1825df36148b2572a10ab550cf22bcac64d8605be4a0d18683a65a6720a9d765007709157f218d3b751f3cbb2e8733e3c05ab6938d568573bf65ccfdd682dde65c25bb288786ecbccd4d7dfa998267a4b4e6f9629b75909ac731c5a6530feb97f38e25961672ac6a8b2b3c39feed6bda2872ec2d96bc4bd708b6bf05ec6e38ea2e29053584ae53dc12668cbe21a851d225e773c8e9efe0c30a183d158771eb255df45ae91ed5d37daea1b3708f22ca2522aca6ea0c6269a16fedcd3a1dc9dfa8d4333c7dcf95e0c8a983d113423c5a4ba55428fa016bb15e1a42004e7d88df137a77914f322b456f9b2c9f537e75ed7bd6e25d4f6c51a2af8d45915f245892bad2694a56f4cadfff818e211c3853165d51d6cd91f129d85b14b067b9eaebbd3d3a3f849d0d45f51a690c4dcc9b4766f18ea30ddc541ad8fd97f7e4214640106b542db8fe31519d1c86d1e7a694aec2dd4a3cc97357e24c8f04f815a4bfe7c016d18149694d00a930a4f2ff889902a58d59cc7af6893ca538e1141a1f602bd6692e347dec834bd12dffb019490166a2aedd25daae3cdef372d8bd3ad02ae3ce4d96f22913a89534b6eb428b0ed3794f477ca5bcad0d1bd8c55e50444295041f45ba07f1f745a085aac47cdee14f7a4f0517a2644ca3c66dc05caeda11a3dc500d94326984078bcd9369c77b51cf3e7fb52f186b44f23b48ed6b12a24232d3909383c49f377f29d5650d6545802af24181c580e4b10f4f879146c6849973e36e00faf7cea302b0f86465fe0cbd5fa93e6f46e3660e9ddfd1ff0691d94d20005701a378a34c150fe5a1b33f6b484745c753b8b95d1e6424ebe566fccf7df7c3318482872f352f66fccbc3f8847796ff923fc59a129de107e251bf8bf00c09e7419ccd18ac92c26e20952c68c22706794a66b934021c031d98c8fc80447155455c6c7078da4ad9df937a61b09fffacda649e71be02590c8ac4cefb9a486cfc25678fb8bdac17a5badbb7f76a740cceaeb03e30ce058b5fdf707b60be946893ba67ab9d38da4640c928b071c36fca0b9c2176f7cbdcb8a595b04b1aa41f5339f64928e89ffbb3137e6ad9d14d31e2647b0ef1d92ce35d4cbf18e1d586433f310e5fbcac2a6737fa06d2469e3860d994816f54c19b9b3ee2b86b477537d8f9e285a4fd168ffc304ab2cb39e0e46ce105f01354c307cc670e152931fa4f24b0b10a4faf2d862d982e3ac625be859e4ae03a697dd52fa57ea20f72da895bfb16ddf8e666f3a8d2733775a5f9313ced51c7698110e26be215e9557f7824918b9d15fd690915e06299778e80bb29f82a75505a04d71ed5d84a1e9bff12ad98cceb9104232932d68d579cc8440bd1c2f005773acce5a2fcfcad20734927434b7f3e0aa7b49205d4a619e8480bdd94ca8c89cb729a6cd7cfe9bcbe7c13d831a4b0374c3bd7b1520abe3a7327d54f07f387900cf3f6a3be59550da22c9279d44499094194c45d57f666032a41f967737d75122ca5d0b06de9e996da34a86e51dd5b45cff00ea0d88082ac6e3d4ba526b0eedc50c0d7c781db3c6e5fe1f302f3ce7aecab3f6ea9006ad36bf991b2b2955c72bda72e7afcd06e2308b2bac2ff2d55e1cc20641ff5e3a70a2d20a97799b6b1da1fb72b5b9fc7e845d89afb64ea0857c61034d20af677b679c054f4153d9115a41ebc96365f61b0e8ddba55eacb0c5be73d56b00001b22f1c9fb39a3d655117eec07a7c87922cba12d5667bd4eccfac5f53e521023300aa936baac8ca5b243d1d68498eb552a79793bfd7d90f929be7f0e636a3f13ea18395ddbb879d98b7263b17f32fe7d046ecb6032d9f1ac44de5db1b73227822c12a1726158090ff8cdc45af9491eaddf269c06acc3ec727a7d17bd1505dc593f62405eafa963f93ec3d827efc9f97106750ad4f95f5c44958225df037144a1d65aaba1d31fdb8b7e386d4a89bb74d3ca3ca26972b45480fd9db7fd3ab7fae2e6e32ce32fb7b0d9a145b86982ada12646142a99adc42d5bdca59191de5ee33c40dd90f8a03296cfe632df8b12747be95ce0da70556c4cc4a68b794b50944c4ed12027ecacce071f33114ee7d0cc188bb0600ab2e334cded47e2691940343c842da0c954ff3cd79d477a0a734daf8586121eb004e7df29693b4f583f69be26f7074efd49c6a826a5454bc492f145a364233d86ef517202f75dedbafd42e9315ca81896b89ece648a300548adb71c3abbc6ea15cd0b493f38d848de4d26fc8ff9ac6ac6530b6d2a25c29135cb45e0714f8b47b36dd39c9b329c6d463b443e3407f006e73e72791225555fc693a0a44c52c04cad45da569375b2651a1a8398f746486412320e2ed9b621c490fdab93cc1f6eb2f994bc4c65b1a078d8e9bf56da9276add18d29f1a7f01416fdccef7f8e755fd759d7b73acef4f09bfe96bf7510e0e2d878609e38d1b70487c10c3b29302a139fac460fbca5d9e194754e995410b28f9aa109243e7808dd54a9ac24183d0a4978dc7932904595ffea85a34c1c4b169a1000c697a5a4b51c4b40b26fd145c5f15f8f7505ec75305a683ac860e945da9d596ffc573aa985232be6a0becbe936a6184271e434379d383ee1bd406e7e9fb566beeda09900caf84917330170a4f046b9f1f1e597bd4d070f91cbe641eea8caa07fdeb58fc2a6d77c692266048af382b76a2db232f53688fec33f322a2d205fa05c669a65f736bf2e53cc9e23bec381e894c4739496949f6ddbddb6fd7212f80ca5347edabfaedced56b64b8761d0c522921ae8e2ec18120fd41f2f00f97d5f87971188188f5264f05ba903a3e13a95376b30e4adfc43f56d1f49914ea03eab16608db50637ac62af4bd83ad20c02f1685336e70e758dfd4f2009eadaccab91550d8eb23db8131f9e05ab0cc61b4d565e5bfee741d557e77b4cb91e76c73007d77b671c6f6b749d4ac8a5217270f7b02e44daae56f3c198518aa199c89eab9807d30c20d95582b35f649f5c678d9e76af4ef19f4b5a10cd6624622ac427fc78f91b9ea01a15e6f61cea48f97fbd8b42f1a3cebbc27b1122eecc5209dd5a0cffbbf96d663667bb101dcaea40dacada24d3a684dbafc8d1096de701a660202e75c8d3049280c2924bb1bd2817b15416f7ef1c69829ba22ba014536e3d577dcd6500ea79da60ff8fff0d9bed956665a0a2ea693b603ea348d89ba50e237da560e954b40192d9ab0df63f604bb343eb7b265d5e1b2ad243dac135cd0be9b82ad4b3b11f953fee40166116ffaa168a7f8ad00ec1bb865d067dedef1a3ab8f176013697e03324f5a747ce17c3e516b13d3aca137046ae7999330699bb721d76a279778ac99485684cc922879920cb69fbb139b9de824857526149e77248f58ac8862b8221245efe6acb7ee8c1fd12b8ecbac3619230f4cef3d3867e9d504008a3298fdfce8e37d34a4e752b5a63692253cdd2859e50e1f2a8d73567131c98be69c2495a593b211532b6d471c78d76a4dab957aa8a88b5cbe0f2ffa5f87fc7382f7371719d8e538360c9048236966f19eef79ac680f1583e55618ddd439fffbefce16fc8159343a544545cdf786d861af25891447e38e6b301e6c787c15a7f6b253dbeae713df279aaf6c8f968c59417e8bed6b09f25f5611db5297c188aa2486af8d3ff1d59ef71a5ec8358e4ab428bb8e4911e746c498f302786010599d8cd773a7cae5ff701388e85c0f52dd6fc80da5eaab12a0cb051b2b8c9e251188b0c83e0aa8bf38fa1363e7a8c527b8c8cbc5142c3143e3b22528e032bd026589294efce133e0e62088044a602554c0c9f514c67a9c43db4cce50e4905c31ba935d811fe251874e92e7e9b0e4ca65f1fe3761f490416eeff598a25b2ca2528ff2fb7dba6929c07e6a567e1583fb634f293bd02ee99f7eaab121c85f546c74638f4bf82b90c27468d96439d1aeedd57e462a05a284d8058fc36b3afb73e47b51f5fe4098ab2697a1217d4be00c09bca71373334c26292d95565388f57d83757273136f3414cfcb4aa2407013381670e7bce0b0178b16f45a7962291a61bd2573caeed2005eecb0f158f2fc6b4797c2a2bc1a50d194f6506f516af12165fd617bd1ce9f1501591f99f9dcc74dec679263ab2ae63ab26233c32b2f10d39817f7be317dba040b83a86ebcb426f4e9fe351003a0e3d0ba58bfc502880c939bfebd20674c9ad7fbb80deef53ebc64f8596db14ffc92c4021749f17b35b34bfd047537005af6c21dbe8a85bd0a7f36b06f09a72359253bb2644f65e737017294530fdb6e6d7306f0b5e2e629c0ad9d2a4aa1a545ba90019fd7a3688ff2718d7815b215c6ce2404af3f89df3fa4b18696114c1ec9e2f00507cc1f240726152d36f8a8d2574bdc62bb1c1bb57ae33f46931ba71b0798aabdda2886dbe530047e9ce8a0570681f60e56bba402d9cf81a0b84ae3c3955dba65d9d947170647a4ff9f1e27594db53892d322db03441c693467cd89eefea6a31fba70d7bf77e59aa817805f953a0f371b81cbbda07782809e9704cc285d855da4084f3d3a9050b9d3371a399c9d59aeedbd979c611835739ad3088837174e2b60945887657688befe3f2cd829c1ed92dae43b877d96461230be1d57e31bcac5873415059bc46e78a6523ba40c6f8dc597a2de4884d7d10b30498e1904657e1baa6c6e47e0733fff28ecb845668469144caf18d17dd11eb09bcebc197bddfbf1f328c1888483206be387a4fb87512925543860e290284310047bdcd59ffe59317cf288e7784659c8e75d2dc55f8f561a5f3eceb7c1a691eec680a080a12b9ec491b3d96f61a6a17190033c580530afdb60559c197e58a2d769dc96c72744a7a5a92e65178cdb6ef888c1317a1f1c70f70476ec01d5a47af5918bb19769e7630b471d35bca21daa34242123eb013f770f9db4c0f4fefb38ca191ac9dff2e873dca9aebcc041728c9a9d502e96069d7387c88e7be143818b829cae60c21a7bab3e8d3f632af12e194ecfcf7a5967508ea496bc8246d4e3ba9fba8d4c7fbaeffd494aae82d73ee69f0b29ca537a18910dccf901292612436207d0d4161699fadfae013572537d9ecc6cb36da4f6ce91d7c67b3d5612af1c33259e06855d66df8da02d23e885b501f0756187da39fa61a3f50904152a7e34817a5b870630e0595824fb3e5065ca0c7863cf52418e5860cb3441650ebd4b3aae2cfc83964e1852d46be856b416ea7b31bb4aac92c1e011692d8b65b6bb42f3596d8989b1d1063e6b7c0e7eaf6cbef5139e1b78c19a042960d548abbe4faaf664cec2ee73ca30a021318e52689618a725998dd6187415bb071bc1126c4e74fa0b7d8815b61d0f9f63dadc9bd55695df4ca451bd8fecf29232d118596e4d8929a855a76e40871678e62e380b38fd9c11534946d831e398276de1f5dba90ef4c18e7cdf2ac5bcbcd2f5289c26c2054e3bb2cea1abf327ec163623917cf6448cb9f7d9e3a8312cab0afd383041b02a25107060d2ae266ff8d9c83746f2e11673e568986f081225f70d1be8b2d78030a2f5b51ac846bbce6d726615dfc56f355e5ed96e4dff5d56c4a564f9a9e1ebd1239bbcff471fba52bc4ea7e3f6d481017948da456eb18dcfb23fa9eab669b12ed6ceb800683eb5330b7e7e32010612ed8c471c594337fb9ac068268eff3eadc2f35c21082d81ca0cb5a60d590661ae8778dfce0271fa2dfa34bce8323da42bcd3d907dbb985a4d5fb889b905ed82e442c7d5e518b4b3f095b45252f7251d92c8c26a5ecf63eaf7a9a0828a9b830e332b736fa30e816b3430228524bf4723c733f75f5b959c50d69f358c8244c806efed3514a1ddb172ce4706c140ba00e94621e05e235d6354a305614dc0f2fc3a69d71c40619e75dfdf875e4375d20ac09bb6ef1bb781bf06bceebddce17ca9c81718fa48ee71a37c99d57d3f94cb4c7bf4cd56ccd90f23937bd978dffcc19f6ba92a0e86acf730edcb9bfe48cd1a6e205fd85e4e534a78f1a41007194f28fadc4bce7d573750ee311953e1af1eae9249c92c2cbde01a341222b5f9fcc5f61c313a45d52271c67bc980c3ab696e4fc6cc6ea1c20d8b21d789391b83747bfae0b61a319e20017433fba9289fb0fbeb661592d7c95c4ea490cab3a72eb535ff4f8ddc5d87cf449315768d7c193d296992a42d93f8916f9bd6da396119d12aeac64b06e60ff1188b7023cdc262b4db2e38af9b20bd58162da310ae8a274186ca7a49bff22340eecfac62c2f7b04180be8917b08d9bb8b00cd9d4523ad209abf6340f905b6e6b6f93a5c89132966216445db84e8d6b0f7c749e7063397e5714cbfac29c4e1af8865906efe738a943e8db7c07fe9f1fbad804297bb916e17e79a67377723fee95384b2c858426b352ad7a72305987721b2017c59e2f9592a8d6e433e58158c562042016e7302f6085b1f9efd07f2e8bc3ec588552784fb8226f9235ba94d1b6d7d759be7a2e43952511c17a4d453e4be4547e91c2ece086a8eff9d8ef36cbb4efb06c872ea929d60d438ba419cedaa0445fc2fa188cb4d77be5b294c3327d2ff5e94a2fd212dea59ba023898390ed118bfeda2470d4e217bd91e9e5464b974aaa3cf9fa7a3d9426c1e034a8a37dea325880a5b94facc17156008afb72d22e920bb96e022b67462510898b238f5914900e863800873a1de639bee3884f17dd3c04b62296088323d21db99163c3e7fca9e72affc5678e808c788651b00ad65db3e58e7c557f05c0bafdc3f9c7986f4cd6062dd76f08048c79538a8f4dad7d95578f6b343860628cffbac2b938f4d16da5cd3306cf01f233ea30ade11055b6c380d3f15de84832d2d84bc7483d52477abf14da42362deae1fd3ef4328b677bd434faa9a05ffb873ce0574d368c2c87af5a3973cca38f8caee04545c323886e695a1e1619197f79ac047c858ba33a2cfa23297d5c28e4d6b78bc2c8f3202a666578fdea43d395f9ca100e481d374d479e908f463a7c6b8367b7c7e4fd616df811afd2c09b4af69e49090c2fb4c1e8958d12eaad117b7d1243344471ae5cc4672060239172e3cb314de024b35c78a45b4058f7082cc978eaf68ccdce9f53d96d7b3251774fbe5a01eef1b5586e78183b74ff6924e0b1d532ef1a0478073d1a6b29a6bc5554a70770240d715a5979f34585e24aef0ffebbc4e4b15f713e439aef62e18b9cb0d9065192841bfdc36fe7f5ecf521e75268ef148ef16e6f9ddbe0d4ef25fb63249ddb21ebf3eacb595b5e56ef6356de198643aa12c6810548a4ea12e54fcce7a90e0f37f6357acb90fdf3ba928845f573604518cf5ab5b5111f9ec0ca12a5b9aa50429e23473c3ac0afef7704c8b57111bd07f2aa1d9a71613fb2f300de45291c68b848c254c0d7f92b5851b6a4333fe09f3bcf663577bf9219cbcd02147d8171562544bbca85feae9ed654ef6dcfb08cc6714c30c5600f3079a743307bc68f3ade52e53f8fcebd7c99bf8bc8db6757ea852c19b6a3bac2e33271ed49ec3671793022c7c8e16b6e80a428cd3404a26c409878571d51eff1c93b2e7bc2c692dadd9138e3ec076e4c86c56f44587c7dc2192811804f3ce2a63bca61564fbcb0f5ce680e5b085aaad8c1fd2fdf849a15323f17745becf2bf84c7d3525e2c684c078c92c83110f3db3a43b1b8f3d5d9d58f7a3862a6e1ab6293b816bd539c00eafbbf8668d95086c0abcddda726ce1e0ba43bed741d3b3492524228bf217f4ed608cd8aff731e93985d8c7c3229c702cd3b423225111db63c566f0daa63af7225e5d54aa2e449fb691cc45729079a6dc4a712be0c88ded413f70e93dd912a0557eeefd3762dadd48b4ddbfa48ed122930e515a852c1586c9a7db6ca2a21646d64537e7987548247fc0e819891638177ceb44e2fd2cb548a5f298630f744f02973b30cb965c174ba3cd0b13871a8a7e4ccea85501fdb04e7b3afce1e5f0970ce7d1bbf51bd0281337fe5d56d39ac8df51e134a0421635431802704515586861ab1ef9f0e555c4c786b5562dbae90792f4c42299f100a447a627efba8dd8272b9159b4a7eae573e708138640197f044863f0a1f64b9c011a6f805e1a055b5cb65aaf329bb9b18213ead439930dabd278f87523e4726555560ba195549d4a0020ee18dac609ad4a9e8986a9a9e487b70665aa2f0503776343ba30e0e71631fd716f2df46aeff73c768b3b1c4cd838ac365c46f02ac3ce04220c3016ffbbff234bfa00f25553912464a8a5aa6349597373060ceeeb56f8a66c14f8dea8219bf03044b955249b975b948b42aeb0fc97e571965a447b4204948250c230f8956583e5f5057b0374ac30acf6df8c2cdee0c154b4eb1f51e9e2b579901730fec315ff9ff344f913ba9cc1bebcb0d696217a6f7a1d0c14c23ac2d114a356efc62ad2c48ff456fbdacd15a06180bb2a55c50523fea3f447d11f4319b0e9daec9cb0df121c331bfd05ae7676ce6f8966b855c6c83d016b6517ffcb24be26f1283cd3cb2e8cc4c8b32126dd4b0dd50b63474f6b4cec5de2d05278b25408998e07ef6d74def57f6500beb2c87c2767e1ffb7f9b3d36280d0f0678e9313dae35c3943cb2d69b5bbfb4092dbfdbdc55d7d4ebefb20dc073e6efdfb23fd2d4b9bff2551d98587af13867fb17fdb1e77d95b286539260631bc800bd27f3cf3f6904d81d4cb8a19a924af0dc45253d370c5a1e7dce7a2d1457dbf59eba5e4a17545d1c86acaa4805e4aad" ++ } ++ }, ++ "2" : { ++ "id" : "0x41f547a71d1404f147606491f3b96e49f67d4658", ++ "keys" : { ++ "falcon-512" : "0x09b3f618864123704b78a9552a0b068f395444870c2cbd5d741a0c565554bc2785a691ff502d6ed0e14c925eaa24c075d20949d12f369848e178d50b085e87c9b251f68b61ec506435bf5b53a49d299409f54e906daed0c1a25a63563090f6660380321e786311b492bd7ff684a2650bec34d5bdf071c49f5a050415b2c3579b2994fbaa9a97b7f24a30e7e8bba68145196e0424471de31775aeca732dad506b16ad4f61a325136a6664f439e60687e764a009db3218f706785b98b154a625c168fa2ac541b8dce39682172b95e19424b98ba985622b2a23d8db2d46a7230bcb667372a924aa4d1a9e9cc1a8dc1ae11fe88081d74d857bf63e9814a08c9ce059a4b1ccab23a2fba765086b15bcba135d0937a064b90663ec69ab521746600610bec0a6b3c705277f90d588a00e908dd075059de6c52fe05fd8fa8ba1b3c2cf151cc810225db79aae0328b8ea1e92fc67b7bde405a1442128023128a5f7089722b954f15597ebba3aa3b55ae947be1e659be52af04c3205492387b51e72746a904ff13ae41964281ebd81783528269ccd6d2a7845d790fe4cda8ee58d93de3a3ca28bc4e6e18e812c313452a4468049a86ae39d5fe156fa2a43d29161bc911d515f4cb6b625f4679e37d5b55064a16c3e48a7f3ae10a09d9ab7f0ea4dfa2fba9da412af1978720fc47185c7ae16474833c8d278dca65b822c5526bd4da67c0700166cba95e3d23691e6e1e86ea4e560cddd59af18a689c4dc2b6dc0e114f2a84754498a8e299ac17a12fd199d1fd8d5c31b0a40ef4b2fc9627d16ec11241fddb4fee6c652d0119f7d60e852decd3489cdfb75c10a18f562154e542614427ee7cb0e96b99d74eb9585223760bac37de51697d86403ac877f823451d8c60e84188a8fa6804c3a8298f223169c4c61fe443434a76d6a51ccc1d06df3b962fdba9e27d7723a8390f4672d66dc2f756263ab928d9d14f6d550acb286647ed6dfb091c462cf4756194ebac9c94bdf7ae4ac7b5093ab9cb94455dad8ab15b134d31947df478a1aca5e28e98020dfdb6d4ab750911bb2690104b9606e78c8659c2f511bfa3254d32e65aab180ebb74f9848700a8cba3a1a546b77678a17716f232e57b204157761161670bf654f182a14bbbb1c16b14b652127241167e898e097b6270b062f0607a50bb040868768a24312a8da316dbc547237ace3a160b7835c805061f8f2723386929835251945908058905f625cd9a91eea83c0f693523128c68613038e", ++ "slh-dsa-sha2-128s" : "0x9fc24e59b10d63d59b6c448f79d029745c4f27a31903ad2a6f6fdd09b3abebb1" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39916580739423a110970dbfa8b6f06ebfe827b6503b1629f4008d64024e63c71af7a932f3f29cbf08eae4cca92f36f670de2f3a0a461999f431bd5da16b868d2230d6403158010384f0f98d2b95936e0a132f5b86f5d11e32ecf3cf206ab9d26c1cb7fc93ea3468109a59163b15391795b76ce450813b28d28510767270c1c474632bd6eab70174350d329d0039ef8fa6739b2f665fff021cf669156e3797da72e5913d08c94a48a16d12b5ad7e521b730bef92d7cc277a92b3e4c9f9cfff7cb3896f93dbd495637c2a47835f2afde4222c8dd36d4d6d9cb419b5b5563bcc1a61b640e70bf2c4bed6599c5ec50643fa302c227ae56adc3d4b044926f4bc4b26d58d0d0778e2b8ec5e18b5cb9ecb6d7a26808962082bea23a932afefd0d483a9952f98ea11b629b0ad74c367e09cc016b817b624547ed8fdf360a8a06acf7b5f0d3c92448d9f7e9453a4e29222611490a7188dcd0a8568b67d333228454cd9cb99fdc9d6d945a64d8d96348120295b8f2ea9e95f92d9dddfa2a91b6ea2c44de7b605db8e3e1019dbe5cb464e0b211713cdcc32ef3631caccb48b6b0c968492a5f1288e99ada3a4d8287b5c9f46236b4b3fcfa55135f1ee4b13e3d6765866a316d8cb3ce80d67a518ee974976172f91eff1cf973631ade2a2b81134c39d0f3c72bf4fe546a7bc7d3f1142aaae3f5b4e8f3932d9b516ff1cfd827e7395d576d96cff52f00e76abe5ba3f1f0887fb064ee11096e52d441d1b4dc7a69462acb7296c489f498c456b2336f2f112391bd7e545629697bd096ab373a34147643199222b8f1b05a95bba5877aeed29c43bddecbc814a6f2bb38d1dde30c352e06f19bf52717236488848599eaa1ef17873681e91064430aa2f4a23445fac0a8c8231c8cd7c27f928ca0ebf7ab08feb53", ++ "slh-dsa-sha2-128s" : "0xe922917f6a5d9d49338e445586f4b3bfcdd92b89a013edba38e598aad56f8d10875fa62dddbce6c66865eb7d14067931d640a3b7c5dc448bf7cb6309943c2f0930c78c03fad2cdfa1c21689c6f621bfb1cba1968dd28e66ceb6cd5cd4f10b8797a53a8ad54e93febced4dc1c48fc4bf768b85a811866f86f004fdc340628ccf44b295fb5310898614b6a0341a2456b94930d086ee75f67bb935e62c739fb87407975f78f372ec11c0bf8bce5144abbb2678711850174134e6e5acc3b87f14022d158a57dcc7916a8e75341488af6b1d9c0af90bf2ea86440fd1b8001d7fdb8ecb8cf392498e41f8be5c7aaa81841aba7422c45fcc0caadd52d36d1d56cd02d027b6ed9d122ab3d53597507079bd9fb476105b12e3406c1873a8bf6a5b9479b5cab9c370b79425b1bc7616e2f1f66a398c2e38f7a9ff1077918fb3f7e65f025d4feb8b13397460a753b1999b3d351c5b77ece3751686c02db0ea4ff23727527cdaf038ff060a09689a13fb7dc902cb82844b11f8092625272d8888090e60cb1040b6cc5b0ceb6854a7fa769a77523e7a718a1a9cf56b94be12fe8fc4d319b335757c6b4807e17e9ffdbb486d9910404e675648d069c55e96894c7b2ab17d91aff88f44ad609142ea3747117596c98831338c616cea7439b1754390604188018818a5fd2cac7522b2df5e42c14e77b7383744234da5fe1a02a60e18a178751eb9c0212cd847317d64dabe4407c4a4d2ccb6965eb33699c37c733d42e66f92b01cf8b0ba2c8d737711439de358756ab4ba374e7359f8ec5838f531c984e2903026acbce89ff2935855ba5e5f3d85c82bfc3975ba3d4a9721ffaab1182035bb7526f062466895c5900f854fb52f5913591828cef55cd07d70c5805327cccb9822860f32a8e8f78806e39d36ea7be59186da6ab5f1739b6716323b9379446ce6e50345cfc9b769162ba96929e2cf0693b77a558e5386945fe5c6410a2594805695a4cb602fb25993a0359753f4ecea67d0a1045a80054664a5f589dd823d11b1e440813b3bf141f119c38f9595c1eec85ce74fd0cd69ab783ff7adf32746d3c4db1153df20ca1ff94acfcf3c8ece27b9a7819f7751028435730771a0d7eee4d5a05627e9577de7a1c0d16400a81c6d93fe48990d8d4eb942233b6e81f2606c228423d52fa012ba6de7c24ef446f32ba1e1bee5ab78e79f40ddc3f8279277735564901682f03ffbae6176aa8c2dc6871cdea56cb875f25c88d955ad2e5f560fa25acb5d2130327aff86a324aaa721874c4276667404738fffa534f26e4e0dd67a9d0e5d447c2868af3f5b93dad621f528509fa6c3d2b9a391275396d3db6487ef219bf42088433b79d34ce793f024380319f1a0017c0cf821d998871fd35d2da47b774f6c6664e54090d74d087fa43ca622417314ac0a7f2d23da0e9be5242191b9096ab0e200bcee276a787ecb770a60f975c2935f24600869822ce96462d97f34c23eaa50b443a504670923b260e1698eb12a76a094b9a8b9bc2fb07c38b03b495a70e4976d05477ee88b58e2d66729a91f0fc003e56236c5285869a6eba073b36efdac3999ca0b91408282f83b179629bebabd5355381c4435bb173598ce3496dd8616eba46505a64d29a166b51b1033cafccc0c6cce63afe4f2dff7a2cc62a909853b14b40c418d3a180a922b02243637700c87bd0268e3ba09730a2e2e20065a7310d8cb86ae6b2174454ee4c01fc86c0441cbc51f1801a021da1f1fa4ba6cc0e8e35a11a0e55a4aec60d5c98330ea1822991083deb2a80efaf382d29cd0b04fc2b3289e024814281aad94ffde1a837da103a0022b23f223e63b852ce8bb89d50271b29b5dd805edf1f4339bed98ad4e4fa42cd726f3f70c7c434035cd9180a02ac954a1173c2694f0cd59942291c34a8071803a69552d71b8191c4299add494d05e838803e5e9de4e5a2d7b0f8b4a221ce677b5b365e57284f4b74c973c72a565422b2233a5b3770cf28645a18ce1bf7cd0e726566c382d801e655829a7c5e2aa149217075014492b80533bad2c8013c382aae26cf4dc39a6eace929903894f85c8e97e4be1df2bbd53fc780c46ed384e01fb40c515e88bcbeb2005df6c152f0d169a90ce3a43c2c3469a85a456991996f6e9ffab555233598f767b38307fab61336a8d57c1f6753749d46e1b3032532a5ef11082cb30e12bb6b292d0f37806e6208d4bbb7c7cba1b3b410ec1d29dd35af7d38ba79059999992088f06b587bd9570ad0a1e2352a6133a50a3a45da27fcf63cb7c6fa98e6d3d3d7987447fc596edd9a157d72d0bb60441935481c54f9c163b985c708ea1dc510f35f9aa8768e73843ba5e8621912f43383365f534f3ceef986e90664123079f7355e5a5193b0ca1bce0443e01adc00f18f8f07a9038cfbc672494715221c0b8c5dadf7a66875ad67300e5fd662ae7b4281f2df29aa0f5b7f9f70fd3180d7875aaf784eb3da36f9fd8abfcbf2f156392cd196ab952669a531bf941b48b7d2850cb8a66addeeb1447d89daac2079094bd4163d9e0d8ed52e9a93e31a7d4f5d2afc4b7d2c0b988d41c3e247237363dc05dd16d49d159005b42ab9def7290a51beb7811e9f4fb9961a7af09fd4f291f797f8eeb05bf76884ca340af07f62f587dfcbadb344c1b350960686aeecf772f59d3f5c9f6c01240667d1fa5c3d84dae1f0dc9562543e4636d81a3f0407bc29127bf4b4527d0f6d7815a941fb53e6527d5940739bd369786e710f6b0f69b05b2e0c49bfa51411319b9f7b172fc11d901e41ec54887a0fe5748b1d2403d23ed5494b96639126c1d3fde11d85c8c717fe8b01319a9668b109e2d34a6ef5911aeb31c88b71c32a6723b0ad2a28b2d8c75087a546550b0971dde64d3cd69434914d5544a8828c6e7775cc802fd71e467e0327d692cba302f681fdf0c7425ee580c413d1a3904974e55e7ddb19de793541a7a4310e50990744b4655e72b4eb5a3a8c5fcc09a545198c6475dd26a43338753855ae4dbd845d3122b16063b9d4f1170b0fb1eddbe15bf6a0f935565ea46bbbd6c00491a9ea8288822dbfe8788aec3eb3e5e42140fe3cdf16328587b736242c2aa85828dc84352bea3c6d985ac48437bd72f12adc7fc08d03371992547b91a3061c9f9bc6c32a8555df262c14dba813ae8e2f9c732bf7360b1e94498f5a1248ca4a0c020e381d8c25f4924f91bf0c649207b1314bc0088d2f15f662a2594962596ea66c036677c451e77f051cf9c5f6b83ada58109f68b415af541dff5d6cba732a938ef4d425243a3571f475af0a456a7ea5afc7c78fa195780b270ee1f4d69fca7c93087e103595af8757afa5dd23ed17bd723c1edf8701a1b4bcb2102ab2aaef2df7cf485370d310651f6e897cd2d687375d29c7f101aed941cbbbc12ac7ad60c3147e41fffafb766e548f0e96bc911f38a6d1864277c170fae28e4b06fee1d1925923432bbe28e41f8cc19271f68196bf4724278f8492a6d5c0826e03d8dc1232c0efe5c7598b71be7d6c468ccb1077d7c8bd4630bfa4a108d58d5498e40584f6ab690e27ec8152c1c39bb70ccf7c5f2c33e48af63d536d9e7ba90db931783a9cccc05c22dbfd90f84f75d139aa22b1246a15534f1521ecb9031ff0686c39b728fcf6e0323cda56b641561a88c6f78cb1d880d102d26b20213d03af41c91ba6924a0ae17a92fdb375492fa0b514ce2fe88fb95d72e5b1b11bff99d1b0ea0832a0d3472b5880b3ddef0bc0891833adec1f7797f86fc549b22df2a0a59390a900e588cdd2405e5afea987db98554585c85fa2428cababff59c17713cfb100084192cee9f4ee3855163ce76fc59ebd4b23766b0ca7c2d59754ca42ebe3c997cc4cdcfc2ef455d3afd488474b4da2a6ba278c196616f995c4398710c291efccbe36bb724bff2d097095f440f79917229a6fce31dbd89e58696c4571dce1e535adf5e1b0942fb5d59a13f7fb4eb17647e83e587acc50d920db2951bb48e1495256e10a62a8d43d3cb7719c54c24f546ce4937e2ba7b1911f5684068c365398e41f7153cb1e2b9ac014bb7395a36efff14ee94373dd128d725dd6ae6af408a5da12ee540fd8d2264b24cc7fffdb2859ce5227ec3c3d5e0bae49b5f495a39e5d6b3baf7c967b21a55e3528fb0bda0e9f2a3cdc37904005a76b07d044ce439a345f5ab69a3db8c711d478288df2d4776d53ccfbf49a06d0d0332814d34053c98ee3464bbf46309b763114ddf1073100c34466cbf3414b4bc7b8ee73c44d76c46435c0354a71fba7d8ba8b0248f867cee79a4beacb5dee9c45577e5b423582fd261b6164de192e98aaabb47179a6fff8827221a70c77df46d01357bf27392d4dfe3b8e24abe9854d3109b533edab16f495eaae07562dfb4428cefbffd748f144329f7653931a9f65a3b024bf19d2fe04764d53730df662469a19c4bd966dc925b1ac52d9094ff7dd7268697468135000a8766d8292f9079f9bb5601193df637f8192812a9a97f604015ec15c89fee9f700509cd745da588a86c7c756bc84745c593bcb7c7d9d34bea98d505a57b31a90833e3d1e154c3b686d5d8a20375111bfc6964bdf2f815e160754b56c59fec8fa533cca9e21d4f688ed94cdab427f9e179fd308856ab7f7206d13d65cace5f8d65c8b95270559a7d33c76c81794ec38d75e2b3f9ebd1351e07da0540e3981d447558d6c21ce6b0c32bf61a3f554cae9edac7a92e2e25965037830c57f30a021953d91c8349b94181ca8c3bec9f33327caa08e437e542d4cd9742ea16801aae94e19442030e8c95bd4f23d88ae9a1f1cfe4a80b046f2e54885c54572a215f17bf8359db4edc830c48941153bdff79a6777a67a9ca0ee3c5d2e4497871f4797974c1d932fa3417b909ca5b29dfb315bf1590829f1cfad84b9e068213b8a6e9171c1c41757e262d371b7073d1b90fde5bdbafab76426f486581bf52fb2a53df2fdd0a6d5065afa6148606a3dd311b155dc0dcaf9f741a50d105053225f1c223ad0fd8af47d27db808cd32f733fcc8e2655523fd36a906c6e6a1d6eba56311424458b446bc1b77b866af76be210b9a417e87903a1ba2e431c176a82cc5a71a4ddf29350efa6dd8d1707d3884b31b9b52bc876b6599f40b077c43d815d2e02ba043505abe7ecd7dcf73818ceb77a09ea4e582616f4af11133a80429edc9a434f3cd2b41192edad842b433ee7936fa5c7680023f0727f4337c53912fdf6fc7e6d5c0dda2e0a8722d5b0565ddd8f9349815bf38e8615b5c7ae35622d7feb7907e6423c8aa7bdf57355c0353da377977e180b88ecb1faaeee2d7142f342263e636eb99c78af9cd0ef0314d9b57fe1176bf8b13c221b5a05c1f876194ac26c35b0ddd91a2130276ac402314367d99c2e300a33073c06dc18cdf5361908d58a9553268c6d0ba19ef6f6d0bfbf2b1e2f5d284c74695189d8a3236e927d9598a4be253d0492f98015851be3693b0c1b3c4a73a95ea57c20699240887d501db5d3525e787dd1a583c2a831a9b59886c873b8ea5dcec376ff37fdabfa21b74b3968008dfd9784fec35696779217b4f5507ea15852f751af31243dbf857d66cdbfb2e290b52f67312fe5d93bdba25b1b7dfb0f3488974a7ff0e437cea09d0baaba7bbd2506fcd182cf0dabe7c262a823fa1dcfe00bfaf7cb5f54283763a45134dfabe9927fecacd648ef767fdce12d570693ca6aa10c74c41761f64f31139f3aabbabefe6c7bd79a6a3334cb465f4203604c0288c49db25bd25c6c4c113e09fbd65c0f271f4a373294831c33f7b2ef392e4a4b91a3973d38473b9f3a485cdb04b7f75a833e2c0461c6f27e6d8f518d3a4366ea3bf37f43e4408f00c4c72ca8d0a9fdbf1ac7fc9fed47e8a3f3f33ebcbac25fc2e70bd39a85519181383597ccc3503e597a734c98e98a15be8bf4b37330f585ea138e5a2e4104ec1cb6f5a23df7ad83751c32432033f072e8ee3cdeaae4e7de98f9e58633bcdceab69ff60004cfdf51b54e9a33232e1df86ca9708811a69b8759e5b2daf57eaa8f1f74ae6aedfd9106c105a6cd715b66f561c0a0500a501a9f3d50a0b5540ec96d24fa5f6157f5465d413b204a224e2b752a49322a90aa340e4422e60a449cab5b6106135ad34ae309ada87ce9a99cab959f6c2502b2da99d8ef296884f4255fa88f38908e4294f799afbf3d664900c5230ebbec54328167495caa99942c13e834da5c488f2dcbbe4d2448eea2657a2f82a91a53d09b2b5445de8c8c8ede11f028e067620f2ad83be80d19f3b9a9f3b81bc8a405c233b2b17ce8ee5e0ef05847aeb36f219817d735faf6092d13569cbf069696bcbc50cb50cbef921f8fe76775f1034e73bf04431b696eae4943efd78ef6c19436c76ab389825e57b23f4529fb848233833afa418d85a92fc865e634357071bc415da56078f44bfe306d3b00574c04b2e94d6b801d5e3bc03686d1bb27dc2753112b2c22a43610a4dbe1e78c9f4f6f2b4ca3ccbddc2ce0e78fa34cac5935bf0867bf14f40648c805876e61fa841292ef2d2d53ecc00319a6df0bb6347dc865e39d9da574ad93f9cc910a9eb920986d5e6b331cb29b45ff32ddbc9e09b71eef73c8673307d6684a34ce85ff3a4208741b205d31011555b17b7c5effc210ad9309468a007d76983011b88c818eaeb3d3815a02d76f735433192f1bc99a6c7dbb57e107caf9e986248ebcb2e9c28279ea1e19a8f8027bd6f8728c9aed0b974322254e686526cd9ee0c6720de4eac01cd83e5705570c249856ebd7ec76cddd98cc096fb93db8ed86a5aa0736c36d978c09b915f7b9290cc255ea1a4b355888fb96e506cba34683c6a890c77d92fb01bba6b69f91efb3e4313111dafc3a189db063195bb650e0cf353dd975fb5c286f86b8f7d982ca5f74a78fa0fa3d693980be09298bd41c4ef38874ddb95e928494b9e345525b00e4760a1d6a4d54675e39b1d955e20a58f3ee65ffd1e249eb3558ba348a2be114f396c422c57314ce6df0ae9406dc6bd0bf5f1db49f012a03834b3314dec7839860867033643aa7dab3fe17ee025812ad2c05484abd0bdeb67043be2a57533d294aa03f24ec8afae512537343eaa16b07eabbbd2cf6755261ee473dc457ec36775102e1c8150248e4e51dcaa6abb7753920bd5247ccf6dcfed9dde98c9f37938d1c824fce116f39f0d67ab9c1fbc79e034e8bee6f79715433d485edc70e5c098ef7bcf2972171da06cd2f19cde8f824e0f2bbcd816f7eb87b7bdad659a900f36df708d3446d8e412b92142d8414f3a0508d106473e809a0831953e2064c655519a8f22fd0c517df7ac44d72a0e7b6fb697b188133fdea4d16e51c6da3109f7cec1a43fdf47957a35f4651454ae04da9e9d5a1668f46cbc58422c38fdf204f4e9c0df3b1f0ed2e14d0e008bed642353ede25a5c25684e7d593eee9d14b3a5a81429b30895ff5d1f7f4a124d2fc9bc1eda61e8e4bd73b57ef1a168cdfb1ce1d70955567a3d949bab203c379e3676932f96c04ddd0271a6afa0bd55988134de26bf5d6c725c09e04aaa03d393a82805a366e0d98e4b65bf45e05ce45f4dbdc1f8ec052102df08f5852630b706dcde9a3efebca3852e85cbd7fb6e6e00b4bb397004db1602b7f8c0dd365eb2d946d00eacf0ecedae83d26555a1bef8be88eee9de9f9811074151f0cc747f36d45ea7290d53c18fa8ce73f77f54226e5b1719a9bc911c9d7565693836edeaa6cdb7b2e2f9cc8c86b7c207cc14c261793df6c4c623355db04d5eac01c011677d26b764e9048bff8d76e2b6bdf792c57e044eea4307f5a3a62900df3f57ae88577644e2121134d61bbf3100fedf83371438b7854d06340ffc00383a0a4789a6a85062aaad3761dbb3c77e61c5926b0488f711a77735dce429b6e028373dd341fa2db5394867242331168665b4d7fc4ef96b12a571b8b25d44fb0de64b9820734e5647821a038428d67dbe95885526c3f2b8064e8baa5144b7fabbbf5a133c4b8d7a2f950a4fb69f9cdb37ac28cf0421894f0b771f80db988e25fb4ba9991664c93116bab82ba808693d583a2b697fd2b5eb673f954255da410df58231eb7c89b8257c5a68ca0306d088638b2faecbe3cacbbf77725e1685aa81d965f1ef663f1e474eceecbd52943c2e4e0456b52aa0c7758cd2fe67f3132176113a16dc9bd11d6dc03ee643fe8bd6677f2ec0ea754ab499e00ced482d78147ecb2f91d3154e03b57dfad4e4cdab98e134a609a7512a5a0e7c3c4adc9db444238e0fc3c3586b389d8d090ca46222a9533672eabe4fabcf61beaeb59c507f2941ced1ee4cd2afefee5aebeb354ec33cb85c9695426126f016929b471b9cc07dd6ff787fc2d682cc1e80657bd656acfb865dc91d6b032785cdd7a1d66d4d5463e142b6f028e8fb5bd6c621109e7022818b39197f85fd6ad4785efe48c4509e9a537f10d4fc9d23f275fb9e684c2f827868c9ff3baca8faa59903c829bbe1992541d15d538e64329e886ade0c5517cbab3b15fdb4e82506e27f449e268b488de32fd036fcf80f6c97505a5f33e4d3a004772a8970a3fe54049513cbc57131ffca1c82918a81bcb879b8f48d4300b11cd90069912ec9e59d10b6bebbc24ba1061c62a8762156df586a4aa758f13cab5ab59a3b1ef7d038c68920eb0a3c8a673c27b6fb80e5e8741b3b7fedff0c068a83e72373da07c8d73abbd9fa0084bdc92866917b546dbf7a6304f04b18d9bcebe2b4bcf5ac7ec526abb4a52a19094c8c231668d063c5558bdef0436ac418f42c5f41f2df996d19d48f8bec412de05a6a3b079e5b6ac1be0773814acc3d20166874ef64a6cf27f7fc72e0232031ddef1a6a4ac9897a86605550dd635c995626fe985aaabdd937bafe3e2a4082f0fc875ba7ea963a8e5987ad400423967bba1c0e369263ddf16fefc88901be069fc617ba6dca90608cd4a9d86476f8cbb41fc8197a9ee6fb331aae55959d107bef29b4f6f064651964999fb8dc904b8193dc7582fd47b0b0fb912f1c0c3838dd489c374ba5ea614cc80d4d196291c4a54989ae628dff5beb61612353ea0cdfd75962ab057bac887ce7f5df01861c769b88c7e1682f0ec6f7cea63598c3e6f41093d845db95377654fc56702a4110810917521ffada7432b7b16a64699e6a955a4273fe9220976f8b1ae9ea79678a3a74344a44c32454e7bbbae9a1fc440811693f66d63663c84bf847e0a2e8299fb0a6413194231a666a2efe5ae1c41db1cf12dbd8d58408cbeb1a9507b5b09ebf416f712b0040f8300dc5188e673c5ab1f13156718031f25cd5156beb8e77e95b48f42d1361da25a94cf1bb4a2a5c41f8da5c3f6a30c00e7d0323f7bc14583fe20815f468928fb69a480673b6c775b2d1af6a176abe5f6c679aae41ee1d5c89439a798823b65ef718515ceed5a7ec87eff54479a9afb48d0fcdb9a240e946719598512220d2afb20840e3680689cbbbf096e7d7505d1d854faacf024935a672278c5dfad333373015b11571b2a7329a0d2fa792d838ba3fcbe5303f84cc6d0454b89cf740bb0f83b79c98b38fa17dca42c5d57d8e86cbe16d46c4c0caad1f55ac4a399d9755067b642299b6b023e47ef74343b9d856545a51907f86034397dc1cdeb0856ea9fa753ba82c5f7e44e4423684f1b03ec59e5cdd96c03dbb1421e89bb0d1dd570309d92519e2b90fc83ece91ec6b13134cad1272f0fb1092a21e0066cc0a783e566167b52856fa6ef12aca963dde340e94f04980279f67a1eaec339d0656c09a3fe91a2b1885f1c09e831471ebe78f2af2efa1fe5821034ae172082de7cf5fd8599f7c575311d35248f2b0e6342cf7ac4bbcd19942a74ae9a9ea3ef5641f70ad1746406ad9bc24a1a3ed17dfda75ad54fb920ee9c92b792b76d42cec2c22fd1bb0f7acfa398d82b5f016f2943dfb44ca1d96b2a54ceb7595837379d62feac76dfa610a82ec947047176aa74fa8d58aef3d34e79768ba7b213a8c44c6e9739f05eb197148b2d2f3c5a1dbf0d4ddc4ae2bf0eeb93d2d4d0990c2c21ae34300a3139ccb5cf216b4031f5be4fc61b137a952fd516e45236dc791b692910a09a600fce9c14ce9e429ef1ae3ae737ebe9921d10522a4507d0794fde66f639189cca95923c51f97cfde4d57c718b6e0ee709227fef69a95a229ab54a4ba9d858115ac04dd0a594ee8fba7d29a23d8df53c131dbd6f7f47c6ec482cb2da38e98a8bb51a2878950877408f0892199ae4e94c4c8eeb614eeac1435b2947ba67c30ff52ff4c958eefd318814a17f53c8ae691d3fd91ea8196bd82d4af9fa216e32636d6535d5c68f579d3066654f2cc067873fea5d56f9676800892f210363fc790086a778fb721854a0abf9a2403ac6de964c2eee9011a44cc0d66ced8bb0634cb986a12b0d5d875db0f26f008555f7ff57f42a441250dc5d13dc5342ef36c288127d46b4a2cd85e5189877003589579aa787c46843e47666be2ca6e8aa84e065ec77f0f77e5cee75785e2358a5e1fd7d540ba1d36052964d7a5de9d1598cb71b238c6a6f2a4b6c72d8c5b0a4c2f17342747dcfb2bf7bc52256fa21741e1f8e7c2b749005ef240296ff9935f75e943c2e725e9f54636c3466450a49eadcc6f330558f2146426fe6786f4ac6fed1943d616474f7665e8ecc2612479eac464c8313066de5fb652beb42ee17c0d9eac4496b5a732c3df31d90e24ffa8eacb12b72dc1d393d0880959e0ce9db8141ae1490bb12af9bb2d12da5809a348714024d7beb73dbdeb4d7adcb68c59ada159fd1855ddfaa33e0b985d7bc3f509e64ee52b5057656295dc669939c45d89a07f03c0062e20e309a0388725c993f74cfbb8db38b85f13bae8b27a4da755398f228d79eba2ad5101d80c75eebee608dae268dac0c3a1c63e311fd82cddb78f06fd576314ffbee8ed598818894fffa54b56e7a7be5c20ac553d106609f4bc757acfe7b116f695fa4ac3ac93bd0de4bf87aa6aca5535e467298aa934c11143bbf39c464db663b97ad416b6501daa12fa8d9aaa31334851f36f654356467cf4f42fcf0c4cb239c2acf7c7938c0760a6a8f953e75471881c59293285241f7b73e4b3dd5" ++ } ++ } ++ } ++} +diff --git a/consensus/common/src/test/resources/aere/registry-v3/n13-rotation-unchanged.json b/consensus/common/src/test/resources/aere/registry-v3/n13-rotation-unchanged.json +new file mode 100644 +index 0000000000..76a1d938b9 +--- /dev/null ++++ b/consensus/common/src/test/resources/aere/registry-v3/n13-rotation-unchanged.json +@@ -0,0 +1,55 @@ ++{ ++ "description" : "index 0 did not change its keys and carries a rotation", ++ "chainId" : 28001, ++ "requiredSchemes" : [ "falcon-512", "slh-dsa-sha2-128s" ], ++ "ecdsaRequired" : false, ++ "previous" : "ok-epoch-a", ++ "expect" : "AERE-PQC-REG3-13", ++ "manifest" : { ++ "formatVersion" : 3, ++ "chainId" : 28001, ++ "bindHeight" : 2000, ++ "count" : 3, ++ "0" : { ++ "id" : "0xa5ea2fcff9e3cf29d0c6f5f147b67ff24aec3bd4", ++ "keys" : { ++ "falcon-512" : "0x099202fa37d5e165b88428d963d2a224b8fc82ac0e4b3f6a02376f18218d1aa7d0e910e71586aeeaaddc2a557124d6ab4f9a44b9cad02166413cbeb14b364e13956ea326900eb2900802644167639045d76bbc4e051654cff404dccea94402141ad9fd992cef7a8fa6478b3e6f8912886e9edd1b34c29385b7e964f360e0fb1600787934486f461c95d577d2bc74c4dfeb969b4798565ce0225ad27aac052290a44f844ae233e082c97e4498a31117ac9d02f3605c856e2dde6f611812161f89cb3a54dc936ca1e740a6c659405ed586a9a963b11c89b01746325e39e645c72b0c7e4491b36a17d43ffe38d88c601a5976f5a9636c964a012bfbce5f9b371e7c3b38580d81c6e12b8e8f2aac219f96245d35b4f4afa6c94015b055703b8c4dabaea4ce2577482f5b34fa49e56a912dd58d74580b1f94e1d2056594ea64bcdb696b0baeb33c86b6544761a3ead9ba9888cb1ad51f7027ee52b21e46c5eeaf3f77bc0af7efdc87acbddda7dca00b6acc665002c26447e5b0e0bb5ba261717c68dea7f1576462776954d7249c2fd0886f615ad50d53960ca02d581a4a25517c050ed467c7a820bce6250a9ba2e44fd67fb21bac843bb134c95360dc1c50d54b7280a94440d018181a9d6374bc64d782c84471b47287d8ea748c36cb83cffe053cb89a9e4ae71df497871c2a728ef210903e5b7f39550d0331e15637be7e28b3a2fc05b0a9b0c5a06f9fe81263c3a94403d6c288a561288ebaf788bfe271a578a1a795a85e9d452b61ac204b297090617286922376bf0a8d67dd35fd705b81260b7aad30132b965e39bc3cd64d154c4175951704873992a814814dae5c6bc1e89a83dd91144cd1b88f6ce449900058afdc53bb44bcab63d30cbd6df115a5ee8f5380a127a160e922bebf7b408de82514b2e2550a0931e065565e8dfc389d454823a55b03e5c989b09e3791f656794e8379b7b4b1617aaa9770366d63a657f71ff40c69b1d5da518ef1e2aa42366cfa38e448563f6c2db5e3089bad5520ec26105fc885993630c10db357883f588a5a384cd6de688e1bc3b1200f87ed66ba3d4a4b671b2a500a0436e0955904030d76577aadddb8c1ed21b027f198c072f654c3abb086e7f185980f49d0e109c1a82741809f8afd15ee56a887b392c5b172ba659144a7e99e25ba19792d2a3c0ccb481822839c8c70c65c0943a2994ec9f6085b7ac64ce2b35489a72dd6693d25f2329264e063db26ad4495e3ad00f12df8cf914fd846", ++ "slh-dsa-sha2-128s" : "0x686b5dae4aecd5618b95c3b2a5792888513ba49dd366ac39b7431ef403e04963" ++ }, ++ "pop" : { ++ "falcon-512" : "0x398b261d0e1e172f9837179889a04cb790cd1c950e473360af30a5ffc3104a52fc9954ab058bfeaa8c2461e0173b276340fc57304451188b40f8514af3c4efc0209f2f4eb9aa21374ac202ea39348edb08472f9b4ac6138118ec48d524c7db633331ed4aa0433ef629d183b523fc9d9ea70355ca1bdc41daebfac9cf17d704271d9f36b7a3171faf1c7be709222b643d9b71bcb068ca322959ec8203468ad0ec96db7eea7d5657e59402f31486e27b50667e35ae6acd5a4ad129ee2d164e7b2d9c140efbaa843a5869075588891359098b89b93e5e4e6f006399dd5d2587efc5aebf7445c1e61fc1b530932c6a70ab2586e8de73164a031d345731ea341182e1d9729a0309ba620ccc45ecc27090342645c04066d497e71b7b847f30cb6748b47b75bee56ed101202d8ad0dbca51748f4734b190dd191852127d79b4682cd7081ab2a1100854158f7f6439b6b3058c80c232b2f9c2f8df205f4c93409fb51a4373012c5609c6c567d665d43d0d32253f5238f0d4be0f00e8eb9779371cddf0f1372a93f2ec72e56cc2a2d6eca7cd7d14a630ecda530120317b0a0252f921d8f2a279b4213f3719386681206c88991130d48cd9f9b87d965f9abb0aaf0c59406ff5592675374a38fa87f7384c0b4b5f0ef25cda1cf2df5cf2f51bf82427114ed4aeba3f63830bf6cdee15b91e95b6c86d1ff88683755771b8e8f65e28aafe4c21096e778d196acb2be8cdc1eb81bbb9135ee56bb61553f36cda6f9857b91b39b669d282ccc5a7693cb39952f4c1657f7d02ef18c7288dd6ebe10edf147ccd236bda94abe49724105dd9e3a86f57a78a7c5616464906cbeab453e49d5f75b81f5f778d85843c71e97c520ed6b9d1ccd5a9387e5865695e9261e0d8c748ee9e8155bdb696575f4be0c7d668fb78", ++ "slh-dsa-sha2-128s" : "0xee44a0de25b75a42e32080200c89b82e2f89551d44da272720c816fb144aa42ca29cc7a0045d97c82676d36286a9f1bf4d5b9e44b6855d90f25e03e3370cccc7665f3c7fdeb6f9565b76745a7652f70b7cb18989582559b81160fa32c7db7915f14c657ca37224955d174cc69de41774e4ac576f362306f3383733b322f8b333d9d0dee44d80e36a86491bfb7441a3c66809bc600399ac9788b4d7796604d4ec423c40dc1a6fb2b02db9a0d35072cb5aa617ef769006c504052596186ac0d504561c815617067f669b29757aed1de7a03c9c0410fb8b040dac268aa95232533eef1f69cc0100b33c9726d55af73b5d608b501b0470c4e9340b68251fc645bca481dc2d375de626580faa7b7faba8f8a596f795481cac23240854839a1100cd92a6410291ccd40cfdf1f70981c568b32904a0ad649de41b32299dd5a8bf50c35e5dbbd474c258946881b49e335e01c72ab6654741e657bcc5109fbda7297999cb4b272302739ee07cff0d1c9ef454a5dc5403cb7c170337336f94d56f6ccf563af44bcc8382de301720076a7ac1edc1ad95dba129760d7e9cd4df609bb8f7b389e7ab1e85e1b54fa5e3f2163afd7e24c5e5eb61a9e8e79dccefaed30f5fae83bdbd8a1673b36ce894891720b476652a26401e7890af9199bfc74fd0aeb6622fed8e488b8151a6c51a11bd808702f945ae9f9a016bdd94f45279d4765bb376df7fed5506b52b74c867c087c3386f74b130cacd7bcb4e832b697b50c796fa8fe4881c3f994820799417885af464f4f1a85989e5e3b54c3bd878a7ab054bd08c1ad850c96f3c0105380323908fdc94771609b10e489a8445f751f75a9b617cb1aec4460be2b53920e52f7d85096065fecbc6f19daae458f657dfc894758f3d9a6519fb4276e16b38aaeebcefba89a7686546901c57a29b95266d7ab87155a854ba9b269ac94a279e9c4bb38e6a4928cf6fdc3984b4363cc44e0e3cd7a7edf08388b9ecd5a04c55ac26b98f98cda79cd3f402caba28360899cca559be68d7a825022f9010e65f9a6564fcd0ec1cc4c0f4029086c90288fa83656cf2ca2cf30d5c423342cd15b9197905e9ab30a9d147aa2599abae71070e40058f0787ae39f39d6e5c1a8184b2cb3b1e6e45c40c61d46af8490cc9af6422a439f16adfe93a3cbe88f63df5eb8fcde9ea111ca96ea7be416d030500f2c7cf967dcaa4d3ed76a613b2bcc034ed3aa84f35556e7a65a8798825b576236798318034204f041dc59a9f9c407d34c2ca2d77470700ed6442cea5282ee99ceb71c6bf074423dc0785a39b89b062f89231af868812777536d0b144212d5b4b6fc7b87ea04fcd6f94438704f985b746a13dd519c57260f87150db4dc483b664944b9e805197df797be099940fed468b1e214ae99a68e99c6b5cf3d30fdbb1b3cc009ea58958eb4c4a7b7bad6b34fcea2a87eeafda01dca5223458affe54422ca70ef541ca8437171943d5bcdb70eca8de02b93098653160cae52f4d72fe5a6a7ad51c6465388f0362e6e72a3c96b9cad2248e8d9a2cdf89747444c7e51e2f89eb19daac76da37180e4133e0dcab15fc72c7bb90c1024d03eb2e630fc6d2537a101961b388e32ca5019a626b5a23914b06e7822905a5e3c21369b69fa63fc9f43cf7ecb6749c668c7a940b82f88c71802ce6e3c68b5c10c9249ba356bb3bb0539b581a8bd6ca141e5dc2b5932251746c1fc1c3da475581f3e3717f5d905f5ff3c83f1523f57cb750dabae0404beb55aba1105b995268906131835718cd43240bae9aecb30c794a8b186436cf752179b1de65b2a87917147612e3c95288a3e816238b3fccccae1da8041b4f784ddcb3d37ef3f019ef997bd8a4e172d397106a5adebb166c5f565016bb1c5f7f1a0cbb5bb22cd642fa4390ea640c04a968fb5a49ef929df1cafbb69c124ea58b31bf066be388d7b6d4c52409581da785d6447fd72b54949e4c1ad08fa64b520f2b8df83bbfa417952b87fbf802652a65df0d388ea32dfcab3227f645b6b28b66087819b4339ad171a48760e2bf90f1a01184389e23e7df583eab7c2dce385bb7a4d60ae5573966f916bb84aaec6cafe710f839b103532f9a7a556bfa116a05480386ddefa2858ac7ebdb58664a0e633a53e1685d71d5aad11f5eeb3d9ae30ab120fb88f96f383bb86917b72e02768f071ffca7e3fc2ac79846a36f6bd72c58aff03f9e87fdbeb65c8ce5976255227778cfa40ce0eee943b66a382e172abc814ebbcb0bf49efa75f87ef8621d227224b7be51b73a928c23a8937570e1a046bf1fd4c6993a9c14e552915953776265f78882ac8302f70900f9d612d2e7b7dad88cdedcdce7e615baf89ef249d6d535f92a2ec90a7435785f4d0c7a75812b875ec22e638f4af1705cc362ecf52c67900c888d068dc6f72a161013c30dcaa49cbf25c56e8937aa4897451061dcc7579ca99a25348e76ff121983444553419e820a3d1a41744f4227dca054c454a6497e0762155e2a06d17acb44ea55f54e4d6d2e1631a63d9494cf69c38ba66deb9d95c0ee01950dff8e6a5d1c46fececc7027997b8ec626f8405ae99ac20600898fd7fc422e6cd3f774b4009f371ce38e1f089ec93ec0a48d6bfb90ee79c3bcff321eeea33a44022ab910458984b75c5089cec0d8beec20c4c39311b991154fac7c0461b7d667488dc9f0f5497cf66166782e2dfb69a71031fd0251918e4c1243aa4dfb9fc2b6123b4f02f436c0f8737a6663af2b99fbd22c6af539ca9389bfb4e55da2c9ad42521ca6978f71991f53fc8cb227e228a62f3e22d7c3eca8ecee260e55084ad3ace0d6379d5eaf82bf6d3b69c4e74fade4210114d95b41a4c004858119a9a9b178d5a0cc97386bfed0dc6edbac5281c2842951a0c4d7da10207523973c676b8e6887a087c1c2f156970cc6db9cbd3c8ec1c9c1bec41fcbfdb4e8929b67e6c1939bb990ee2cfec3197b4ce824d25a7b4c765945e85ff2b096037adc4dd763b87850fb39aa98f1d395c9353ae3b5b53842a7056c011fb690e856401fc6f67b1c0a5414fc229284e74c230ced260d4fafc5fad153a5154d35c3bf9c559239ce18ca9810a1254a0a6c2960a53d838431447739261dc3b055a0b115914af263ac9fce2b512884620451156c40cd84b7bb2d449aad243a8aea3859412476ddbb5eb73028bfc6b2a942839e363262f94795aa45f6579680997d6acd7a8c8daeace08362fcd420f2f8a96801c002361b942493cc5ae79884eddee989af9832d55319ec033956660c5f11b9fbff9f1410a18c0e9a38e9261bdd13bc392a18a3df97aa33e7f59c125f88d78c86058f3c7e9a9d3b37bdb1e05d90375de0090b418de3ca761560f079a6ddf328e72cd89dcb63c9dd0357ec736782696241e2095aa6107a8bf7bbcde26d5d14533f28ddad7fe1b3f0c181c0e6d55204f6ce79cfc557cfb2d54cd2f33adf17a837243b51705bca7ad8cc452e5340732e678274f9eb532bfea122cfd2959b2499ad25a18db7dc387e976f8b5510821cfff778be799b80505cf38ab1ba6b01561ff81ef17f7735a1ed6a319a7f571daf92afb7490fc17064ccb6a8453ae6e66a2afdcded0c7359461278c49d342df84c43a0607b7327853db675e4c9ca95c52ae013461ca0763d157ac992e219a6683a547c32374631b53138676f50ae0d30588fb25de808e1d9efd5fb9485192428477c2f64fcaa862761c7f5505cc650910224400e2a2db13fbea0b0cc358d163c6d4a8e6296e4c9554078a55f23e60de9bea12ac199cd19b97babe61b2a3b853860b4441ae8dcd85d59695393816c64bfc074e945452080e15bcf6776cbb6b251c13be63932702468679b2bd7e1693a1d910e1b62be91e177a8dec8e4d7642e88e513e3a871ca502854ab0fb7fb8a099d0e0dfd73064012051af337abc78bbbc6fa2dc7169ebfde2d40167048d78f12cb5e7c130a2137a0b26922553f43aefdcdcec55bdbee0fa752a4787ea9d1c75d1bcd9d28135515a0ecfa9735901a0eb89f915d036e21263f90606f65e62f6e5c8237db14d570612611b3ceb4d026ac13f473e5706cd7975c95d49734253757f9c1e6aca9261cd2b95722098c5f7c74daa6c926ea4867ab54e4605a15bbf7ab94348d9b45c31a1fbdc7f420cccce25abb4249cf413008a01e53296318414dfac822cdc0bfc4298273f65cda3fcd61236e255dedd879fbf20b8c4843e27ef413c7a1ce2c714c88358091abccd7fed337a7d4f725ffbf7856ea4694113d605b1ff7b2bdbaf60f7abf7d43eebb1e82f4b6b7f3f8fc23ae27b09f78a7a3b324c7790431c800293e08fed2fa49aafe8f5670d4e6bff4cf6e7924993d6e18ad87699da99a2f2ca9f3c7b44b3b61dcfa5f041f7a6df94131b8e5c04069678541c87872daeb2943902afa6ff4798e45a75659568a02471afde44f8e116fff4eb7c16053a7aa370bcddbf5229c231ef8f2e642c1a88f90e0a309d24a3ab28d3adc176665e522cf5bda0285baca5bf2a0fb4c0fefff3b8ea1522c9ef29342ea57eb4f16d69bcf948d66247ed2f2cc4e567476f736d170c98398ac7c0d158f294ff33ec8d2794ec1929c57ee6d7f46da8e40337a2b380717227ed82eb13a14d129069e98cdd65bc34472fe1a52dfa7e466e559705c53d73d97239e38bbd600aaab107ced36fe7d8ef2387a05d8548a48a684fdf02b984022aeb28e8c5eccd1941ae19d2cb12a31de296b4fd1409266c43118848962e9e59a41054a52bf2f20b09eb4e77cca72df70cdc4d712d5c0313ddf9ec8df2d901145341b3ccfcbed77288ce3e4afc677ad8681c746eca02e7f7538d0108b68a922a21d6a8c2cfd67d8849ff5779de1c00588133309d4158d1738e508a1a2ba3351a46fd3f86339d66b1244bc2788de3fc60144d03c08b0ef08914088f9ce947d2b230ffb9ce176a4bd45b0c8b100e17ec7829eb1ce10b1a514b5e33d4f40792f0a300a4c3ba7a912db8e19cb72ee02ae8ddafc2caf116df905640d0cb65cd0c61d38e0a9741d3dc2b7677e8ec051d329183c954ff9c0c2d8771182d5550a742ba8147ec6571bde519c2f57f10aeb1c8900f8324f017f3b1dad92fb0d19a76de75c0c7cb67d079c8bc0bd7355fa25752d5d00ab00f9ab332aa23aaf8b5cfa4d2723b2020c9e494208c61a76e18c9a583172d6ddf544a327c931e8b908830e46f184998fc0d34ebe767e4f5d06f99804759c7e2b76a8baa302d6950f90194b0cc694a0d351374cd028ba6b0414377a850ca2f209d13cb7daf43d14f606a0e549ce14189023fc7b45e2b095a3f45930a72296eced3e2da24bf237959c0b966bb88a3a9818932b1cd41e8ee002df515ec94901902b2e67545dae53e08810b99dade7b579b847a6570211687a62a56dcb324bb442c4fc22f9d85e54b3f939937daba84c86fcc36c83ca87de70fc7f4afed335e8f9aae027e854e3a022a053c3b22be3617240f1355be9af3f4c8e9481005cbef07bf1380ddc012412c31b221275b56c3ad52cb2f7a9b340526e6128416025d4fe497f2d502070653d36f924420c0844b5560a8728e4a3be8b1ce67a1541c00e97aef9c808bd77af5aa280690d98f5ec218bf5c9d135d85069405b82c221d834b8285402f481b7d51ecdca91c4c2b27c12f486d382e0c14ec23c2bdf33ea8ff693af551fbe55e46bd84f335a68646bd092f914da4954c57201d7e812f4974a553f043ace9c6ce2c609cb4d90dc1ceacd5d610cf4723024538cfedc1bb22c9663ac541f89f97b37d2e1b4d8073ada1596e684b94e74c2c2f0087251f1eaa6789ece436b2940d3285f297cb7482aa9b8c47118a0b1d2031fc311689828b64855bc17306529e4b0a3326438b42698dd4e2e0c2f624aa510a2363583cbac47fbf9974925d81af9534d0ccb41e2b445eb19569d703cd8ace661139fa344a5e097290c233114370831d4710676f7e93889ed533454928333655b06ac5ae67f301f2b7944d769892ed76374a1f3861c8624b2a302df1a2f1a60d41e61379ab3681d8eee152c251e1b7b0806aab2f287338b752918cb989d864e9acaa92944f5194f8eba19a18a025157d2c3988163baf8b7ca9060edc2227ade8e05348d86d18f9eb633e4f06ee346e4c2912ed1c763a75fd1baf32cffd0c856ff9b44f1470136c0a8ae0b88175a7e7f993d8469cc8ac3f643aa7db36992cc97011be0a42ff1df8aa7cd82e260e05fdd67304644335b386c7825858a438c51b63f877af005f7d95202b54a2130a1f652ff7addfb798daf4415572376fdd910cd099066e8d2fe251a907e41bb950e960fe5116f4a4fc6037273250569b41ac07002ecf3b4b63f8b853f9693badd2e8bff695266095f4b2f38ee4d60428a45e7586d9d47c01c12c5e18d1ca9afedca6f03384567ddc730fb8fed27516eb7c54135cc7447af831f0c37727997ab2b01fdbc5e12c112aa987e95cf5aaaf44be14bf4882f49cd84894d555655d17aff21f077b2cca1ff0922afbcbf4781145cfb87df585e6af1955db04843a763fa735d33b3df836585c5894e5125d500673d5e4d0bdf6708d8d28c80298a9bb47c7430ae8ec52285a4c14371b3f8ac1e21306b34bcb0c1e3aa7a8dc8955cd9cac32a0f69d0fa0aab30abcbeb2c21d655ccdbae1c2040faedfc7a5ef29cd5d9227908335ebd257ae8c410b1916b9a5bf0e72902c2bcf701a18c1fe13695a8435b0d0129f3db883f428acea8b7f274a629865f1849d4c263a1536421875ffacf058f0128f0d012fd60f2b3fa6b71fbb96f3e1e33faa09b1d20b0919018e91a6bd9595e9c16d4fa6665c4d0adbd77a59cbbbd587029a4f306c887277a7a27748a6f289edfa16c7e4042fc81355b85a994cc6784f5fde054f188b9775836594abd82c1309a66db4388ad49f60794d8c8e1fe279f8965312a1e23c2956427bd6e289e55ec728f66c36526d40aed7c44e5352fa3e2b5d27bdc1f7b3bfc4f095d002bc8e7b2df2032daea9bd3e0bed2733e7ba13c6d8b45c492becabbef0e8c62c257480faaf6aefede888ce1546046f04ce7e06936cbda44c5f33c71c07b53fb3ac7a72c3770838471aace69f7ea454d2980fb5462173aaade7964b888606741270f92bc18950284d013b692bad63ec3726d8f6596788a032eee6eba08eecc836202b06ca43fcdb062e65f8ec91f7400963bbb8094de4b4e1042e040e81130a3ff037e1b7e947b0c3e8b7ab5b539f8570ec2cf08971a1bf0d4f3e8311b5c625b7d032fe2e0603ac1a4824432b4c7bb5afa190afa30c36f168d196fc89015aff8229fd4b299206e8183897229e95ba06324edc1a9ac81aad786d5c9d38c87c48fc6159934a8532489f06e1aa314a057d91c0f7218861ec241dfccce63d60bfa624652795229fff21cf5ca61ce05ea0ad6a1763173675377d1f2427564e397683428fbcc4b97495735d075f84b289b73389a1fece959f9d9b4932f4d33a0907202c650ccf65327d24cc24922d0d675fb59621e2bcd2eb31ed1ec5fddc96593d4f936ad42731a50f164e404b93920283bf9fa43f8be5878d18e07cb8813914508532625f71d02a615bf47018e3b3efed72d17e0c974d33df18ae70e3a4a743ac3c955d1c366bc94d789c90a8b3771969210c7f0c4b9b12f9fedca5d2b71b6c04e7024a0a5e3d0d3c7d30cf568a659cc17309b223399b39ee5efd0cdec3a34b0735df8d7e0bafa40a8aefd742b3e0157fc89d113af5fcb0cd136a9cfb82acce406054aeda30b83ade59cb6771c366c86b5d9b016a74f220a967b83254db3e24d3e1f5d5e23b21354420dfca6bd8454575c6b0e528744f44ff8e1b9679b084d083b9ebeff09df273a476332dfa172cb98c79ecbf3ae4a722c25be71a3b206d848f56b02fd04bd32ff959e6931bf6cba042f9fde027d832632cc40d4320166f9644296d2dcc845491ed780cb609c0432408d08dddc70fa2d52884df47a55a8a3e706a24ac6ceb375a894636e1ac121040561ef486ffeebed3c5336d123dc05a5cf221b9e895f6d3ffb24b3674039d50fec114d3648d6dcf4fbc0b503658672d675c4ac64dac4db4615d011e82bcabd9573fe9e2af224103f99c4e6e5acd2196f1eb2260fb4aa61c298f99c20c4ac1c9e70a9a9e28db441c3adf2f2b3a00ca3f1398b5a112126fc3f0e2d11d40db36d0aa47d59cf8ece36df8daa854509e546295bebf92465f32a7edae6af4218b49781034329c22ce9e87258216b4a901b823a227e46f2938df336d3fe03fdbff4efc7b8ff8142b4bb60592abe508675d04081e5eee99468971fd49989eddf4648d3948266b08133b8c22ce3523757821a05f254cf5691848b1532655e85fece5eb186e87fea61936fa63aa047b5cb77c08aeeb2991c26619139b951ba4c2ed487703a6123c9c16d7b6cd3a17ad108fbb7c79fc3706f654be77a6cd8a5213d3976b1a4527144e788b712f37cbfd5f4ea5aa5fcc0f91b98d74ddcacb83fb33e039e1b88811a2138743ffc0dc5eae46c688f48c0be92a7094f92c2d4bae0c1dd95d40ffa113f27b8fd1808178be0c3bf77b677df2a17c9443fb6023c9e43c48614fd7d09a904e7a064125f8b7671fbb7529169138feed4bf3e6c215947efbf44fdb5eb1e3a5700fc8bcd1cf2a393ed438e68b607a1061e6cbd46a0b4f30fb4a492e786c5cc6d4f80542d64d0d271308ba072deaf7b1ff1c5200a2bb24c68aa2a5cd07052ee5760e0ede484e0a9c482cc74ab564654787e1698bef1386fe446106af25cf2fd950a78f4b521d547c83b6e4b6ef652444af342e90bb5761ea0dbf6b8c315996ed3d3a1a9d1e5f2b75ab18d0bcc87ee639299a248406d9deefecbb6883fe81ad12f20d80fc9b3c8962cd84e5da215b96bd457d5146aeb36d08185b2ee021fef7fdd43d0555c0fd16e7b66d1f534ae0b87f6299fc3b8e70236f39c91601564a5c2b3abce248ecd5450096e65df8b69de8b5cd963127f207f0df538f990bf29ff0c2930ab8b378b86d2619b150ab4dde82469e40e9e6e503182882b03442f92cf7449fc2c4b2f7ab91cf5ec57b8b0ebc18b27ad9125da57b6c139edbe7495defc73d68e71019b2b808a1ecb89fde58ed9dfce8b17e072170983e3dc3551149108582b95b2e4bd9552faff0bc7fd13dc0130f62a967761928dd62c9cae970ee447842a15baac31a280b443390bfefb7d4115e8d1c6458e1920485985635b75bf84b6af5226dd9b36c94bcd1a5f3ed99fc3e5adc6f3c4a592d2eaecce02d0e5ae97e6c4c7e101d4138e526fe3f090123c6df8596505b4d28c1be9e0c3f83dd4ac07946617eb553f7688f6724c8d8d34281a8c094740170280cec80b61b07eadb2c63427690ce73233f18593537e07266a71523688e6fdd36943d015c1bde058ebf5fcd12ea00e6b41565d062722941ca346b5949078421cf1f32fd38ce1be52fd65f2e9862bc5c57b45f33581eb72d387f0c212d68f85baf7e42058e41966429b0189da4eb4e58c1104e59d34eb0678a1385c38289210ac86f77cf8bef670b9ed04414875a29c27b79bc97e7febc40c39cc8e201ca56b25cd8c96f1a37ff688fd5d55cf5232d216283169b51cb41c631ca323056f2e8f74d5178a83b3bf43cfbbbb40f2680f338a89b294d4b611b0f275cc60e99bfcf270cb761c1c2a6773503a3c0e03b2a858d0cb5f81b032012bb0e15add080cecf19bedadc4d0c7e9d81fa75b97e7ca5e1c9eec88bcd10afc0d8e48f83aee498633bb260d731e0f900a9b0ae3f0d6e57346b8d3d8019bf079b4f909b6dce5718052416de8b61e9ef317ecf2faec5a64c0ce4bd5aa72b79360ff9b58d4a5f3e0648000d90a947933b0fe71d81ebaa96cd4c54c5d42b941e73423efb1f6626767f0e6dde52cd8796b0db31cedaad75b4ff72b83e0e9ece164c4f4dac170cca65e42db8b7ead0fa6e2f0b2d9576c79d1d73aa4b7ce4b954958dea381a65d4287bb1e02b7b88b33b2f1872d92ec6bf79fbb726aa436434fc7f2e79f0ff8bf243e19c08f680a5012c3c3d0501abb46026c420e485166fff457412a075086266b854aeaf5ac3a300ff5501bfd7ae96ebe56a5df5b7abb5fe2d9bf7ffc0005b6aae9dca8380a66c8c14e884f9f3338346ef1daad62042d09cd774b43016b0339aa208c5d6c2f7373797202ffe680edce71d684030e5841edd57cacb0cd596c63515a1b992de113fd2c8330840915d3409f608c8d43601f09dddeda6c504352e4d8ed932d8b5076a557fa2d87914ccbb0fed61c1f4d9950be0900b2212a82abcc4d9f4466d1f5469939c1e35dcd2d124623e2e1aa2dbe90ce09b958edc4e60d7e7502ed16a8a1d08dfcef84eed8a93d6940441ad41e493ec09abce869a8de0a778fd8df55cd1d9d7f053a72314e786088abdf968a3b1d1427e52427c2313182f51b5556466960017468a35ed2594280ad8493a5d3503ee4c479fd4c8db0141fb6b77331b46fb228f94e213ad372c09ebfc8bbcc79eb074162b4694b7bfb8444a4938a80747d2c15879e28e3cf44a8ac2ef8c5d9f93e9cb42f81cf88035dab96b6c078bceb4fb9cf293dc964b0cc9b722a84f3423bd4fbc57ad1f68a8166e86da595fb3b7a4dd87190dc65756e0f7750b68e3f605def2821619fb4fada9cfd1c41343dd4f5424a1911ca709ca745962a484d981db73a23a85c046a3eb73cb48b085d3286738e689437cd4976cbd3e2c5a4a4e385b3aadd09b08859bcf5506164db33d414caee679c65069543f1db8b242dc424af5a45bcb5ef9b939ce94e4dfe56ca25702d7912c38dc44d94670d90109ab685ccd59988bb7e932ffebc882b7dab274065578c041591d481501797b4039da17684a7242622f4390544b05023d3902949d348a44d9ff421d04a55395cb4248c7cb0f13b697f1423be1342d31fa9b85aab70c16bc62eae5660256d2472dc908768ccb7ff02cc84ffc6059752499711338e41d37f8751d84eec47a51c7daaa273e19c523d3d97ee5f71571def6f7268f24afaae71eafc84986eb8a0bdd50fa553c815939a4b56380b22b650fbb989b525d2862c5d420c83509b5c76b1a9a2105b45c2182331ce72e8f1804efee93b1929338f" ++ }, ++ "rotation" : { ++ "falcon-512" : "0x39f115ea80ab1e9d88aa542ea3b547b6c7ce5e1a0d149a3d6e9254322219553a87ea2ffcfef8b8900dc456a4265d22a81f8ba45edae8b52288b665ce560845f42beeb7194bcc265815e1984a7c4ad9029647d54b124f52b4e814fff6d1fe933730fa52e14fa28c6f8bcb4ca79dc6117da3eb5177779c5915f729898de2d7374260c8219547f1119a9d3c0bcadabd8d5237b4887b65b23b0d197ce1f8f874df9bad08f27a86fca319a4710be8243245af2a997b1e8cee6938470c21238118ab8e4fcd259622e928b86a5343110209a77680c7489d48121ac430a5a6912c60d57719624f3b997481eb8ea664595635cb7ee20b9ccc59f2a62b91ca55b36d22196d3da9f4fa6963dc12991ea11529f883795fb6556e5c9c9ad8e3489ae8d6e57482ad4a1634e92de9fb8d6aed2a90a5a21341f7a756840230a54eb37e76b289376dbc5ac29383612a5528211d0b2b058469ff96436c691944d722ec401af9e32db94013569f5ad2049f07de42d174e524e09329757586c64633f4bb8abfc38cccdfcebc1aa496f9f4af6304eb6d25ca571fe5a24fed2b720194dda6171a0433e1c252e6a7e6e4698eea1b406a4956d1054a500b0ca79d2dd443ecb4dd33fd77963e6d5cfc5376f973590a204d2a492fcc472eb85c4ae7b59112a9fa173b51772e5f7909181f0a1e81146d92048e3d3669de61502948b9d9cf2ff3af2a503788db5d06617a7b9fbdb90025b9c6a0c1a9b60fc5ed512d8ccb7551e33e84b30a8621f8ce4b379450384c652b5f2e31db8bd3a645b26bb2a2babd89c5d61141576265fa4f8198702e2ee2e0e7e6fe1bc7b2086da34d6a00120c91849b1df684dd623085bfd0da56820bef4ab36f27391becced9a82559c1e6eae8d3f4da7d864cf8d1cae4aa44bf37590e777e70cae2d63ed67e7b", ++ "slh-dsa-sha2-128s" : "0xa53ea1956641fe8e10ca42ce4bb87600051834dab4a141d128620fca7fe2c64c2a2a21ada2d9cfeebf5c7ad6d633a405ef6da081433e4f2b173807b7b89a8074de4d6ead4d960d161ce71f31e2e806f0bb0e82ce5a345fa84f6e91cf4df73030c6899feceab88a7a4a62784e855c11581fa66afe6f75e3534a9eafd96cfb3dc0964207607227029d8cc30e1d562ae043eca30ed796cdd7495a8281d04608a388c7f0022dd050a5cb2d17118c07c678b7fef93d02cfb3417498a0b22551ae3789ebc40738930fcb5304f94d65488135f8e636fe541426b03a7c86d4c07bf75dd40c78147b0be6df6040735679f3d5f24d4dfcb2e44da06a730fac46b68cc9025b31bfbadada47102511b94fa735fc8b330ac237448acdcc393da40a6303a3890c3ee0817c23a916a8a328550a120ef1eeb7679ab69ae8cd2070968ae8f8a83a1fb597d7bf777cdd54dff3b34393d5c5b8fe1fa0886b7f7a2bab18ed6593024117c357708eb964b66f163a3fa4b23b554ae3ab58af3743bf714d431c4377106e4a81c4fd23453d6b195bd00dc0bd2cc209428822051c3c58d29ebdf70206e2f116388565b0e32749193affd7e4de644d3b69d4626c8bfde76c75b200c5e0f7fa575e3f867b9bc2f370f37b7662ae2e5c4d86a34ff776cd83f3fc811c1b4db609ad79055cf3abe0cfcc4dda542750f50c1f40a0c5825e017c6e9818be0f0c468b486fd42b8d644ede762a8ab55436dde489f267c7f9e3a565a338270b94c76bde1f453eb0aa4934e6e45f9d7b7004f703e7cd3622dc2d4851ee71e87b2cdc952b3f07d8e28b53e05ad33f09efeb1223373a72380e28c5cb55cf16d18625a8defde8841ce878a0cd8c0aba2ba4613104b68a317910ee52a3f119a8c0835db660ef763a152fd7a9d12adb28572a24f1b9f9a2bab635fef204afc20a686673a471b443f261c9a45ebb64fe23c11dff5f245081dbd5c3ce77f2a9769c96853aedeb3d251697c7ccd5cfa5715c308b05b0e1149edf10e7e62aece96d12dcf818936ec9484b1b4f98ff97c09d16b75e4ad9e6ac8b11e912dcd4bf4163bb9d75cba3317a469cc6b7fdd99146ca182fa81291da9d005a5ba4b794e435b27d491998143f615eaea26f2ca9408cf5fb1ac3633556471bc01c7e5124c0dda64b8c9371bf9cbbc9324fff2761202acaf196529e1294725c9062612626ce5f7020490cf0e9ea90fecc1290dfbd1a5dd1eaeb4fd12e3e7844101e6aecf9a8c8f84745dc6419bf9edeff3045e225732da8bf56ab301581d7f7bc54eb36edfeab87cefa342df02bed2fbcb20dfb37e258424cc0beaecd37806430648464f8fba3f801fb16ff25d9b2c9acc6e4f4edfac10b6f37bd6733ea64d145c84979403a2591281609d0f9a06b35424a01ffbb5c8b5abea5fe29d553ab3d611fd83a2b6cf2dc7986e8b227874a45fed0573c8b48230a0a22e32097657c7dc188e97a7c258bec3e058254132119d68784e28c6a58ac85e3e4b3cf66c4da8c25134039c0748e78bf074c89196585f288e0992796f14825eab121d81351949b366ea6268deb8183620236fe8b6734b78ce6210e439bd27df471d30cc5862277351166aaf481fd3a5c54947aa1d2ebe277157ad1a03cbb2d9751dc9a0efd508c72d661bd878ef3eb9d0b2e334cf1591db86515d91c02de7a05eedf41a677d382513fba69198be0366d76a035b372b183e9a26d3eeddf9bd225a8d03ef910ae58c4d8583d9ed898ac040bbf587a3542e11749b3e343b30e6579ca5717fc3648e5546e88705df59165ecaa2c7e966a5c85359363c3f7689eb9b8cd3e9f672f7c5fa2c9165f044887c620492f8cac4c7e4c6bece51bfcfb2666a69522eb2bc5bd3f30f529c7b139ee2df22e718c6812bfce08c38c863b1dcd977c6a9608c96cf2465c019ade69c76591429097ef54dc26977f2c2987c3c016c3b359b2ed7f174aef9f9703885cca4533d94e747fc41d44e67f0926c9124fd9b5931331466f6c15b4797a302db465f332a01bf3e7923286bb58d624dc67b918e7299fc4701fef78cc2ef5c1c7b44477a85ffd1e344ca95d795747853de95f73feb53e264004d74871cd46b79a1249f63c9d4d57524e637fec7fac85546d9855fd4f6483be332b47a93714f18ff0c06912f92363eb58876f9e23a912d1f86bee005b3763ad1e2b2ede5efcf5cde64ea8eeea8b5a8be2e716fd490ad5983a09fb02ba826bd8a0b9c4cc848d0777473caf70954d0d7dc0c4203a929687769cd22701a698552271ab45364eb6925443702e63bb24c85c1c0d421ddd3c61e78dadbf08b5a05754de1408798c1666b55ce6beed0e17f2fe3b8aef4d07352946df6b19dec49bac5ca5be611683e015e2445c24678a5b3e3592ec6e3420bae389928052cfad9fe9ba31da908c9617a04420e56ea54ab9d28444ad65f9ec8a2e69779bd5e2158925f6dc89fe431d0b174f4e1bf2629629ebabeccc008105cca3dd992273eb3fff1e153936a3f29ba376820966eb81aecae4d4a392732c4259ad08bdea412f9669425f79e645056db58b43233afc2766d9872328d5f6693b4caa05cafb1d09f72d1a4febcdc07589bf58a1cf541ae1befa27c5e755b2ab16d2ebabc8ba0e2c53c019b98c21a93b81eaff42f080fb460478494bce14a43b12aeffd3cda505f388a64f2d7c199ff36c0d9f974680ab2619493dd3777eddf718658014215cc06eab5ebc7440321d60266d224f8a8e3a11188071aa9879c6b2d235ce086c45738faecf7bf9b451d5d257a301f59b952750a6bb31d625e2013d5f9bcc802e6603975c38a7436ec90613d374dbe97f8f750d2f734640acd7928974835d7bbb40569a8affbf3be1662af0bc257ddd77b1c19409093de658b02e4ba9db9ec49b0406877a66d429589de6bc478e74b946e55b0dcbcf25936bc5d7f21ab9862b4aa1ac41f9e3ae3120ba6d88bba007c599b82e7bdb7b1e58f8538cb60af18d419311695b480f6ee3373bcad379acf155aabbae67d020b7f9828e38626ceac93462494d82c1972f9eb473175835bedb0047624ccb0817814ad1326238d2f6fecffa7a66f4871e47c12a678d4ce72fc0980c3fb355de325bb42f4507bf7c359162158ee2044edca11b3e6b14a2c57376078d6a539453b31380a1a2b42c977e0f1a7412fbfdff53d817cff7b6ff9ae1df1c6a2e4143998d8ee70dd5791efb642c7df7feea73c877cc60418bf69ca32b340442dec14a482c9534acc1bbb981db0c2e3d24d516bba78411bb0888a9b29b44eec576ac6367216991cf89bd5c2c7cdd7dfe962a24be494606bc7dc974ba365c0be85be339aa03fcaf4e1a7a48e93c1ac6cd86e8af6becc6e1790c9bec9d3e127531d1e6cc30d6754a81f85214c13790df04dc5b94482dae16905882745a1464a84459cfc96fa9f4095d5b892407aa464fc1bcf0ea241c11237469df6051ed0621232385ad34ded98d7eb47a85297cadef9cf009f82788ddd13c1889102015114849c7454bcfea6b9870fb4d26adf3ab267df389acf6e87496aa216cd0d9502580884bbcbf46ff5d3038f2d1bd7a96f39369a7f85b0a4c433c47582b1bbfef049830b62df062db6beef32e1641295c392c28c34e73cef38b7b9e82215474a428e744b98c384d12065444c395e6e3f9fbbc7e902dd65b6a06715723944e16e59da6554d1af6ecf45bb41b9afbddd2e42a098c47e71b701e2551f753eca08e5496509319bd97ee98cd2609c4d6b998598b2ebd8c010dfcc9be7f29f3f195c5b55ccaf9af13300d9c8a22b33d85094038faf4a66112e9782b2ef19095ec73a79d8524a9d847e1ae6725b9a758467c1cddf9b9b9021289767e4c60a159167d2697ff6420454ae0727d855355f82afb67bc8675edae3a31e6fcb5140850667d3a23416c7c448f64938f068cab7ffa2b27735ccacf621a219924a53e69216d4f0f88ffa9e2afa4810f948a8159926886255dbe53a6275aaec7e66b2daea93ecf8a504334ccca6cb0d157b0e1cf8e2aaebd004b7edd54a8a43c6600fa77f067c3e6e7416ca70051ea1bdda14bab7fbaf5bb31f9871542185ee8476c7a79d200ab30825018e472c92ab4eb26b1de4119577c3443f274ab3bef4d2bbd19161c4c9818a36ec6670cf7345786105b83c5eb8215d0050ea184332a437a10aa6a340e07d34af8e54a6f2133ce65a4f724c08acf8c43ada3b4c79ccd5e86a3368e12d131632068c7c2ab59e1658897bf184c1eee536989ebd0cbc4eafe744451ff93a6de2274736e0819242262b695b5d468395ed212e356b617157026d2b9cac918081fa4c05c7f96a0d621992346592abaf018b8a7c6bb9ba48209512ee45b0bb5f2ea7e9f5ec0417d785b65abc0ae322c065ab7686b4b19afe7b96d55afedc9be68c9904407d7a0163b33004d1ebf5a1ddef1633143ee6be90654512885ce8f9d56223daa81db625ebbfecad98f389d34415cc70c58e9a4398aca7228639eb375589a8b8bc440999ab671c5993b9c9e7f3aae7d89298212ac0e29796b99ee8ff6432fc892524a84e0c86bedcd7c3665102f57604404c7eb002a74f5b5864b137ce326a9ade8ee00d7691d5e18d75c91e07c666cf8d32b3a066d4a094bb6d443b05e2172f1907f061d32d3f54db0156b3829d780ebe7530174201c8f82e0c9afe944e9211c2547bf39fe3ff1310a2816d75a3e15e37d5cb826fd41a3d7aed8b23252a41aaaabdf6941445cca1020fa172267fdc5c0415d20b3121ede3fd34988375cbc2d752a066efaa3baa2432a7eebb6793c3da39cd4ec5411150044de744fa7f7dd505b03625d9f9be9c4881d10b706f9dc67fc323f0aa2df04db2b5bbcfc91724a1eaa120369831f9d7ea0e31ae897c0f38afc79cf00141257e18598ba63ad92544e59b4c341bd7d64073180ceea8372a732d53d9f9641e7d290d06be30c8fd8a4b891b1eecdadae64e3f2bd94df87adbb9b4d5bd830f264e1d9d727cd48eb3af754e5b7d00035a93ccac36ec31f9a917548c7ba876656f6561d8002cd17521958c78df3604b3354a29e0cdbcc0377f0a936f81fe04e8cdbe850935036c28330702a39a07bff578a854e31ffa8f5ee282cafa1f088dd3714083c2c38999b2601883d02c083da105655c9adc62a429e883988638365bea25eba6ae7d006719551ce6126edb4750a38e3d78ca6e15357cca3265d036daea984d9dfe93e2fd6ae32e3ffb835b3d6103c806852509bf869a4a06d62e28a51eb1ddf06a83166509c8e138a7241e3750eb0ca4fe66b301fd537ba1d6d8a00e171a82792e5ba782f60c77586d1780fdad08cbd515d01e56cdc022d910b17c22d97f232bc16f5c44c4e28e2c2e14afafa49af61c4bf81714a15e6ad0d6cb3122ef288d4cdeeff8091322c57997dd6064a60748f7d686be7e0e877a5d9a00b06a11a6c436f9b0eae1a45175b3327640073f4a20030edcf2467550a43e2a808b37023b1dc9fbfb3762bd8c3f7705098273b62e6afff7bc8eb05b1a84047b306db8f54a1a48417223a68ba50f6514ffa915e3c0a879ca13bddfca5cf857f82c200109966edff38b092f7cbe07b8dc337ea8c77631f00e589cf86a4ceab5c6bef95bfca407d237ae7accb93a9844bb7eb76346ac1f2876e89051bbfa3fe829b65441e31bec66c813774d0f9877ef1d268305626babbd2bb01d3775ee7a3e86d92c4b96b367812b088fe2497df7ba4e30f0a63475a94343001f011b675d62ab72732914ba96610413a9c7761f35386947faa78dc71b9e3cfd3a1b0ccd7d86b66c02b3fd299608ff3d3429ea4acaebb02b11c9928784a558daa68cfef4c4b042576cd83ef204260231e1fd41946701d60dc124038a42e7112a8c0c776d3545f41d7f8107e86e09efa5de3db87f6df0dc28d9477497312536a3920d843c76125bc2fc2e64b62f2867bc4d51a733525a703730bb076da6b88e78626718af21813e113cc9b282e2c0440b6437c1825300826ca0e212a71c586339e726702c73178cbeb07a51751b28229f6b9ce5dcbba20632e05cd0860506daa291884cfdba3940abe879eef15441d0bda745e44813a403df52f3f43f0dae7a29252f7d41d49e75d0fd1c1fb60ce8d8c02838fbf1377e814a3c56d42dbdb9d4004069e886d548cdf9c14c2a0a96c346238cac08246718655b861d591533c71bf9d339781568fe473f770066caa5ef3c162d57a9885f97f02751994f79fd72e1b875132decc54f2c4e79ad1099cdcb7aa7c1b841f609dfd7da7b8a95aaae31955c28063d2ef4d9be8c9228eaad0b8690f43c776b1e9990b6affa797963a09e1cb0989b2af93c4e6c03076a4f42ba450fe2f9e1273365abcac6b560347d9747629581a7b618900acbc5bb258a4279d3c97754ca1de1b0c020fa3f54eab9ba30bbf5d68c356c660d053628887886660be12780497d786a940bab5dbfc47afcc19b050aa9ea5ab975b155afa0b32ca74e43e6d9f6702b033ec252d03acc4b23aa7c184cd6cd699174fc5ea2b3981b7205501427a5bcd6ed558b614b1b03edd4264bd9c6d12d792bf6c3739143e9ac09218b4bcb7ae03101e82147701ddb469f5ec87b8e4dc6f35b80b02e37a67a3d130813f6afe2006ec481f789c5b6e103ab55375eee8ebb3b5f4ca2028ea0b8dd5d76e3bd892a25d503d2d2c616c5b51f843ef173414b9c1178a623eaf87b9694d5c6676e702c89526c7e6ace13d1a406b99753c0df0c4124578c189a5911f5fad1ee13c85c4beea785a2c7d0ef08521de31ae4742e5f680b25e0c7d8d3457fb7a52d828014d5eca16ecada44bac06e75560a14161ff6401fa8d3312d4a903585fa940e0150fef558127b7ea4a81a099d629e82e7d8ecc4bafbea67e1746c94a458500b2024a6cee488afa305a7d997f5663fda179ccfb2c7a52d3c49c4303ce21832b1e8bb0bd1200d0a0750108da7a21e2a001f30f4691e5e6a2a5d833529316f3cd5fe573ef91d0aa6ef8ee0c230bb2d997a9b9de7bbd340dc6b2fc7d0d375f7284e511ea278f74af92f79c9821a26ea69e944d81b9da5cab728c1c3eb638fa69499a8d5ff8eee14ceab145df68ccdf49814c8c58adfa7a0942e5e126c7d1ca254dd5d2d88a7498e5b280aff9d76e7b6cd85ed81e03af2bdc710b75ae07bfaa09f11d493b53ea17f2a7c427def0056b0d0f235d792c8ee6af097d4358f4799d4ae39a596b095e19ad54a4aa19900ee5599f80675baf516d151034e92e0e032356098f3860e3ceee81234576e393fd8e0e115d813584f5764dde2aabf5326ec8279e3b8cd9a0b7aa08051fa1f6dcc814486e8b68b5ae13e999ec3b71b802b443934dc7d39c999fe3b31b47012b13cd95abd12283ad0fb615b3bd071dc6474e26fe0c1c67c099ec017f4ae703a77b645932d9f309c843b23f7f03b8b6bc818c3ce067036001ce72fe7d65dd454e3467792e8338c389749d80f37af2a54dbed9bd0993a942c88629249d5a7a94e8b8731aa44cb8cf0b3cb619e7a6e9414439fe03d157c64e06e851803703f78de4923c76367e409ebc7f6573e65f6dc1f8eac9922960e2bc318ef2989b2a87fd0182c0e11f5a7c6f50c68bfcc1e813001a7c7af84b0e104415cce4edefd565fcedbb7b5d2cfe3601d91d567d72ed385f34cd32a222b46864bf51fa77969247fe7df40325909c3b2bf7dbf7ea2d2bd873035be6de1cade7911b431ca33835a497fa588e75f36e026d040958aec12752d7b0d5e0b23d8087f4064b8cf57dde3385d43b0b419d147ccd179c4da58d026987504b358077af9528f9826b2afa5a544f9bd0f3f7b80774a47b1a67093e38725286f97066532bc86b444a8f7add918f9bbaaf7d90ff93c092647e137c8e798e714d62313ceffdb104010fe0c8feb379826bd12f7fa165def9682327265e4f5ac242517abae23602be183b568eb91c20ebecf4b31785d92ad00ef32ed72cb680c8439b0f31b2a5603c0183f28f7d59c16957e0315335d7babd3a7cf9e5b84d03b207f88b12265d8caff8ded8d8f69f7423b74acece7b0a77a6f153a28788ee017be1d47c08a3405cb172e2aa375a586b361ac28c8a8d167bab8dbd8f4207c97d6dc7b2b1ca6f4ce5b96cacfe8616a0af16efe67998fc46b0417f89e233f89cacabee5ea435d7fde8005ec2f7c0b95ef47594bf85fd1b8c56b478683d07ff30851096715e3d79af9942f609f31ae35a6dbf4ddc6256c33a69e65deaf0e30974c3439f7f512dfbb4c23a1c6bcf2e2e5c263d15af3adef79549fb3133bf232a13960d08ec5f64f04e9018cd8e1149b8b0f909ed24e155c29f6c39afc1006d38ca85bdd4715e745043bf0f4bf29a509e2282aff60e5947103645741c0daea3bdf7e330587d77d8d57967487eaf6ff6535bd6ff8746bd44171396093fe669f8f7b7d436ab1ca7e0bdfb1d75a2230ee6ac795c05110b909fe648dba2a6fe6c0dd7ae4a1c0011f48ded446208f88ef297b19ddd65b54e26886250c544dc3732358e43b6776df1dcbf2ed72e74d25830f4a61147e07507537159683113d7b8ea61cb0ff3eaa673381f8160d77d7cd142039d89e1bd957befd7ac7d41a2608aee47da6b97a42e9f169c347d7f4b309f4f51b3c47966b5c1ff5d0e368916a9d162a11f9f62daf90994ef05259ebb761d8d562f682552d0cce1fe4b3cde1bec80835705315d5df80b642f83836ecfa2da743555ceb7e06c7098c6694ef402f081b7323bbbe36f7ae231412b8a87916091742fd40ffad6c0453a30f69c45f3d026c3157a608666c776421afc525cc40570e61b7ef8a77d7dd59325da65b2beb1f9e2d3d95785366f34ff48a13c343db5cbaef44a3962816d0b4e09993e810078dd43cba3df88fe4efd28f5180991632f2c8bf83c0d9bf8cce723c42f6ed830c3899891e7e6e0c09c2a57c6307deffced4f91fc73aab9864cec18fa3b9d0c2f9595ab4d6fd5449ce44c81b169a18af80f0db8309c70168687057497699f66961e0c8fb5a7d5039fa251ec40e1f1249a89475093f607b19f354b4af78af2cc538116ae79f1d2aff8358fca0ccb270979a57109d20bad7b530cce37e4ba757f3673239becbf79749d6242dfc2c64006ce0d884a456d07a61d0e4c0fe396d544f6aba340b5d8163c99d230428cd4b3e46127e38786060edf6963c4196b61441e0d551d7dafbe19ee2bd28a53bf249c2064c64a4e60ba99ec4104ebe4909c36b8b6d36ad55e0dcbf257da83a775787254c4f0a0dcd563c6dedb2fbcdd56f11fb13cf9b90be8fd471a635ba85b36627ba2ce559c06e3cee092351f0867e6ad097fa73be4c8b3cc2af033768251a893a0169bd265c9aeb3dad7dba93063e5ae734c1a27ab1f2572b88c5302c1d1c059cd7fee85ef1f2dca147bb4477f5bad06ba4113ef70535af54972d3e140495820ade812a448205a157dd12c5b6a28b31c6d31740163da10c85894f6ee607b8b9a0346df5de0c5d5f420556dc158131d4d17ee5ed6881917de2c212809dbc4978b1ca69572d97e8cf3a773db80e911bfdbb0de20f9b439e026b88f2314c0f360add286857c11bd74e911b1b7cb46556c72b00facd4976ecc1fc45bcd5d261eb479f9666683a6d75cc3c693e15194fe902cc3673269ec9fde63fd787e32833520aa10c99478a8c1bd650cba3da7dc983cedf0051667a328cb343243e8ecac0da160de5858146c355b967402c2e96e3bac53e5ba8e5311bc16a22602146d2d39722fdb7db2e068d6b04fc46f76a92c869c0fe3bc132090847a72c4b434a0991afe6f294619d32c4c2a473d5c1202053fd23b6f21a103dbd45afe7a75c7248ee9d5c0c805290e8f259526e65904a18739cd87d55310caa18119a87098666f60e97d91c4b2ab71aff6e876c554d0ba5dc34a18f5e79dfa1d2b35da90cb53ff5158a91f3586ab0cb43634d02cf4e5a06dbe190f74de0b55b48f0c571eccb977ad01c0c352c455172ead2bd01ec28a489e80754bd7b2a3c07e46117e7f1354abf94f27341df0bafe7588e0a2d2735eef759b8d30efbba3d856a121cf8ae6a017d5d2e2223713875dd8e209aa0cfca3f660535e62b2b3d70a30ccdb471ba649f111f34f1a622d65a0aa5202c02498019a7664c48087e4c4e5941ea4cb3a9c1818d8663c0eb5e80479dfe3a7abffba62085ff7553f8e7a645cb479c570f0cdda505c0528b5ab1e9c0558f90c291e836b9548b4de93bfab2d97aa7f755e6f7bea85662c0b61ab0050a85adde2d514aaf6e5a938d4656917cb056ecc186ce4ec079196dd5179615e0ab1487b960c95254e98ea97b8248b382543975fd7e2fdfc48686e8e6d41b80faa92676d428e70b99ba78788f1b35a87a982a2ebc267561a91054d293fdb88964585d5212cca1a76acd00f418798faaab9bedcd339b3f39fe64aff41f3378aaec32b99948d2ac4845f9b574008ecfe8cfe01be788b7b7f30706d523f12b84adffa5e1ddef70582e27a6c32b058f2654b5dac30ae68cdbd57fa1b3983fe1c9083a3c03e73a452b4da00436d2bc8a6156baa14cb4f2e42818b3a763b000987a555903bc4b11f0e0f08e0ba99284462013766fc2379c1d93cca728183a970b712d9a9181d1b4b99cfe8d3dabb09a3c8321d94924b0b3ffd6199c5f07cbf9414fbc758661cf5654f9ea6bbf256992cacfe54ba9f2b2a7a39b2fdd5bd2613e8926ce4af2faf335d8f9e8e0ea25a4313b7ed01d71801f58037295c1862644b7b079d926d93670ee984857d323d5fad43916fd2d859b43713c7262ed85375959ea8fe01b8070441ab0fe48e551c67d10704db973ced0636dcfdc324401cb9f3a36a8d381adb5f2e0046999d26f157ea648abe0a1c2ab5ae0fa63b6404423c4d2d8d4326787f1b0eb375e26160f535b00973e795e27e35f27ed4f7c4683105fc6e2d655480abaa4ef403e1392603ff3b3a69058e2861eaede45effb4a6f27e55b01704cba7cd10fdfa574bee7293d06809e47d64bee751cd7c2de89d9c14a67a8f80e5047f3fb79aea411627a1cbaf56260d17e308caabcf653a4ec3fdfbdc13ceb919aba3822b1c0311b115c861290fc333c32aa74f38f7ee4c1fbc3f1ddff350c7393a48dcceb1e9ca" ++ } ++ }, ++ "1" : { ++ "id" : "0x690a7fd66157e5b777256ea5214f634f61b3a72d", ++ "keys" : { ++ "falcon-512" : "0x09a89834aba90aa88f605981578667395d730a408f3d112231997200c28865ec37a4a1f044c8817949cfc8a4fd9028832fc406f1bb919789f2099629c2c8d6bd128de4f51c02a73c49dbf17883ef90a9dbc0350aa67e024a893e555b4f989780a45320af4858421346445f66aa86e4954c0bce0debc896f21bc960e4fbd4eebed93e943a40387210ecda652c36b6da73570500adae1a2a03284dc47f1e370570a07007d8c5a64089e81e2c4d45eb6ca01530884070d46f4605ffe139457d5155c8e9ce8f201715ce7b9d18755304ddb6871551498985ab400cdc4349c6b5ed10b76b425e70376e39a6167622eb5d4b7cbd932aeeaca53b3e28ea06c44780b01684e66eed712559543cea677f1d9807e2ad0312c42e43d399302a0c4c506da7cba37000c3ecd10b58922889e5c8d31a9882ab8ae4b69d3d3d3abc6450881e9b79d9e2ac51085f61ddcfde73e57c1784a6a766ee2bc434d4973a9667c1c8e00eba0c544a36c593a764f519de83251ec48fb45a63e00ad4aaf01d1a295eda0eb95b27fc364c33e3482f4e5256cd622242840d0630194316033219c3051258f548a23c08d205a7b15199ba8d6507565d06a1f20db367183d56d9dcfd2e12c36bed83d239ddbda9efe8507451542942033282bce486f002a215c2ef599a6619247888a81782b005acb3d550988c1f22c6b186038bbfe1c583d165588e00c7f0f7e462a778e6a8126be71ee0dae7b5cfc6145aa6e65c8c136d34f7b45252652995898150cbf177f47ca8d16b583ce5b0e809567c08b99c06095c879b4d945b13c8a62429966347946b606dd78803a3c8113a431761dc868ba2e2541c66b39f30ee21b0ee3fba5eee922d56f49ea60c25a1094381908a69b351e325357d9b4b9e2d040d8be7795891ad46a334a057b0aebdb2e5a9cd760b02c774f60df240e05ed3708840b1663cb435adf9929c138b9fd15461d86328d5895d8778ada79d9b567386a6302b67b4b99a37f4362dea36fa2fa1f1ee2f4f8293b131c57595468aa5ba62a03dfadc9784c8190559887603c4b50b7487e795285705f07f90d8a9ca50e4abf0905d7487f04549132cb3a62ac2e490d6d5bfde20568290b693681218426fa0458eb356b198b41bc60505afdf7219ce5959124e4d1a56ba63345f91ab39afd970997895689c8397c023b1c8b774f92f0e5940c764abe3bd609a0d50a98dfe291e1677e6232896ccdea3d047f35c558daa130ff53cc66aa03ca5687a2006cb7c8c3f", ++ "slh-dsa-sha2-128s" : "0x3345627b00d77c13ce3ebdd12964c45d0bec4dcaea60b64fbf6cbe7b897b8136" ++ }, ++ "pop" : { ++ "falcon-512" : "0x394f68dbc8384822df8d4fd86c22e55256ce421178ceafde6e1a5f6437900ed2a86a72cd648af5e2ec15c79027aaf194847efd5855472b428c647a7db9d6e97dd15f70c3992480431ac6919e5b11c9154ea5dd9ac630f866c589a54b84a4c9fc57b86f2b5c835d3f6fac9de77d1f08abd507f514df6e7ba1c33518d3d1e447638eecc8a4b7cea388c2a57a6640fc599e73aedfb4ce6b3f147591b9bdd10fc7539fae4b2931eec267fbe70a5c6dd8b24bc98276db5d8da487bc38298d17aa7fa5facef7cddfdfd6eecbaf7e8086cab1df3c8f3be1913d30892aea7bd03d7ec1296247593835d8a74f467806259280a4e652f7e1bce11aaed31fbe2e155964f7c37243a59dad5c8d19c3c6b9d0f62d59ac39578dacf29d9ac2c0d5f160f7bece5902417ea82a0736bed8a4d078599134506a7b0f8a3ea8d6749fce0d749722f7c5198c340f53af2b4e1054fd97239109aea654bd2be0307a2d868570fc34f56a95ef5ecca1995681cbfd52a0e309e9db779ae71aa921796ba86a2aabdf6a39250bc71cdf8ad4d94fd6a758f29c90a7dc44839761f4a1a9c6d1905dd18d0532832867e48e91156ca67f2e2731bcc949d8140a850a8aaf9dfeeb9aa339b453bc906fe07f0a3e30f59a941d9f4f7b723a639e5e10f39cacce38936fa58e36746b0cbdece2a9122a110099104543f066515aa7750ae0080462d9254f58b5064a55b23a06dbff5875966598a7ef2417a8f32231c630c7b3d574584c2344e2fb38d8bd4d9437aecd68dc690b8f1e93f0109ee3747bae997419d1255a5c14fb1ed17b112ace324a41dc34a5ab81630fdb178641536da5268d928d19daa49507a5c81aca3e061b4b5c490310b13292385bb341b0550cfff7d8c72de94a6462defd1e6596b351ef32ca474b61c951ca5bc4f919e4", ++ "slh-dsa-sha2-128s" : "0x6e16547734391aae71d29745c3ac8cdfbc98f07ad9a8470650f0a0085883ff970643e21b67d6ffe83653a99f2198f821cc080dd7f0cd1a612ab5c6f18d9903ecce34a5cdf069ac66483448219c06b131b377900b999f9aecf637713feedd8c7d4beb03ee11bb297bf4a97959ac5c85c0c83b48147fa9a3be7543ce1050394e83ed745f9ec0c555328d3786da46acac3074c0611667ce5bb4613436dac210c2e9cb186e9540d7d43ceed7f278363811083368d50f6d258a46a32c8df5d62c42c4f6f34c627076169428e646774dd6dfe6924e2240e720fd4d53dee8f880c782862de1ff96fc5204a17625ca008781cb120f74caa37a36dd20136567c05e8e7723a2e21569f065d4fc631811ed0b2d9bb67d2c82b755d14cdeaccb797f207427d572419360af1c443fa68064a653b1e21a2b83fbd93e38c7cfa5046eda9b86c68f3855c61cee9f799ba02e611a1b7df6a15fdc4b4b09e51b3b5e1101d0dc90a213cfa0522e93808fc4ab3d8cef74d279b98069988f6b8c6b4c8d3d62fe2a5a62f1a7fb0fbac7fb36529dd85416a330f35a7e4e161757a83282ad50ddf92c6096cc1fe071952dae4540e0c9d0507d4b61ad34751ce17fdf2e99c3e54cb523d3ffe2cbe8a5c58b84bdde119175e9599df6b2666a7721e246305457cdb5ff5ab4ec9d04bca439d59989253bbfd9a91cb10a9fac3134d85ef28f1e4d4f884aa195216a4811be7617c0d6004c7833088851fb7758aa5aac838ddc5e3a51d122fbb03b0b5d0a3593b2b97eb69c2266eb236bcf3134414536ff36895bb081e9fdd2e5a9f9ba71310af0fa126eddac07ca67020ddd4caafc9b102afd4d0bcae2a957bd65d0a15762b98f4dc7b548cfb463ae10ec3da3b5a4e9976b8f05405904aff74d3d536f9a321b41e0c1d5e4fdbbf61b42d868602e112b53552b8199a6618723e5638273822fe0afc5e6fe068d117bd5af3a1c1e8bb4ea9ae639674b51a523d19f950629a76e9a52c673dd153915863d0ad166d357f8d23b85010aa0b8263de0f253a0ec29b0973af15e4419d965164b5fc6a0e782716d86bfeedfabf4d9705e7093373819a814a45b245cdd13a667b31f1724b5cbffe3b5ed3087118715a0ee68af333bf26f1ac1ff13eaad6a5edd5e760e89518e24a982af4f44386c6d92db7a2229bc9c4df23274cb0f10d348f2373a79f55ee05e3dcb256df464c5f3e54ab790f1fdc585cbacd93c775e50bd02f451b69972728bdce813b46742ebe9e45d45c8bc23d4b298b5956e03b48c0a11c602ccdebace8f92e2521cb346f291717cc1881b0fe3a2e23d4ac694b7f1cd296b32b7f2f139877a129079a524d7e3c4f9c36b5836346a6944c49967796d8564ac8d2ed5e804a14c655ef235fcac5a8cf0372f7df952af0de7e4319089b54ea3f718b539a9bca631ea0bcc9259c64626d252245d541d90179364072b081d70da0a7e561ba2902e8ce864a398dccf55a4f583df7b6f6ad6738813eef6815f8f67936b7b842ed7dcc48808156d236d70a9ecba41994bc0296c3a236f2772c747db6ad62723c4457bf8a2e526f306d8012e04adcff0015a88167d199029ecbd333a6ea35f5b9dc2eaf11a14fd09b35bb2842a4e610da4afef15f332d5d1e82c7b0b452b7564eb45193af060595975d496ee59151e3c0f1545ef2694eeb1a2e38d4e008c0943c8e7f181a258c35e5068df39376aad6ef356e0010303d9a0dbcab91dc708b8e9482f50aa18f88f45864d539dc0818148149aa259eeb270a474b0a117de91b6834672a5cb4b5fb7c2ea0ea7e3bc9884163887986aff1cd89c49a6ca417dff067da528dd33dcd1f7db96ed50820bd72dc41984ed5c767478b79d8f61cb7b417893a3a4451129525a915b1e999086e6db74ef627534015206953ed3a5e2bbc5c629b00f3f3b22a37519426c20b2a10c60087ea32fe606d81c6457a02bdcadd8d56360dbd278ced2d4cb9af64af4ec77989475882f3c1c0b9f9e0b6528b9834e34024dbbd64dc19fab35f3bfda66c086f4c0ff06a29e9fe881340d1c0719ef568e3f8f683282b963005e93620c01de327adc0af4ea7f968fa987cb8f38350ebbb3b91192ebb009f9fa85657e06cca6f71edd3d0dbcfafcc11b908cfc38a08ba288910fcb14f97746ac20ff6e6c43eb099d09a717ac03f5e0600f0bb611d6972626999f5661e048476aa999c83e3f476e77e7ae09c6fb7c343a196e1846ef061be75fd8b662932fdd2c7d8784c6e498d4d828c910eca00ac199957fb44d572d4bd2c599fa6c7c2a166d96aaf4959c561d1e9dacf502f76b050c836194fe1897d54a017944a973f49b2ea59b66c24d18f13048e093e83af249854da9fd6b4974b4db3e8e65684b3b6a0a11d942ad5bb667460dd98ab54319cc2ab704a7a57c1583b8289477f5557d2da684aecf66eec3a54da742e2d24a6935ffc4f439d4a8abc21921087df93da2bbdc3a0f61729b397faf12bfe59c85a6af75c9f4ce4af19239840b57c3a4ead6096f2910da23bdfd02ee4f3676897f475d625d0e9a9cc930116bb2327232dacbd0ff32cfaa40aed89024b9ccfacdb76bae77a87b569582442ad2230c8fb3e0dca3937dea5685c46aff9ae6e16438e0e9ea8ba299936a42d68967926edeb3ef955d95c5a0b74a13edd280bdcb462dfc2d82e7ec89377edf6760450e1ebc61f035fff661173de5fc80dc66b8e3d38c67f4ef8c25c2c5626dd2875e10d870f12b3f36f749eaa0c82e94b2f30686cda1da606e0c815a35fe6fd671915483e1b2b48fab000ae560dca0119be7a0a3dfb347ef95c7fcd9a78e76911cb5bd438a7e96562e437e32eb399782a9498ac992716bd9f3d7d4e35a1f1821f9008f547d171ce2b69b007b5e377a3244092396acf958932616bc5cb95059762f48468a94f9f897736b11bec2ce0af9ebaed9add43bf5c262106a96083ad967b7fcb127012b1b37970a6be14cd9088f6ea927a66a76c35e1320452848bf7496fadbc613b2e122e55634f0491397ee5d211d780971998244f303802d7630837d05f3dcc588d8ca32e02f16d2297aa577576ea5c1b90d6d330a18444dba772d7aa94d0bf2000d598a069d03e7873f114cab9174af2f28e257ef2c0e44925da7ccb593d6183fdd37a1abfd7107ce02c655e7966286b72d65394f312d72505803bd53621a08100a041210cb912d5aef260b84e39faa7b5d8a539b6392b32ce6287e1a619804677b3f69ac46fbec010e726f3eb3458433e68e6417ee375dc70c2b2ee16b2cd9b228d6a46f92ba66a8c5b08cbd284dd759478c9f690c5e1e16d6332b5a0b9aeee43ac8ce3eb0c3eb6940b61a65bf7c3348d8dd15302b8b7bf6b6257e074d0af3eda088f7c22e6778c8cfef1f15d9f86c76a4b05c9afa228bc4f116ee8adb959b4ed9afb2307f2252b10baa436795028629d05277ea2722ffc14d9a5fd56e6cd6f0ba218675df025e50586e46429f1c6028e305d22b5479dd045d98a93fa30de08bec1576ea692bfe6b657b4be65578fa2dfcc197212643ec9a1a8de5971c07023abd8767c528025281f9854145e3d9c47e01bd37dc3a35b76639e4716465b862b705ebaf674a64313641de333828d75c16d4f6ebc4193fc2c92e5a3373fc79dcdd8505a8ea7ef8be6ffcecbb2e80017b6fe401e49193ab31e67a56e8163cce767abc393608e7485f41983ce27b9b1de1a0281f237d685d401641f860f8f11d10805fbf0c7125deaf583458787c6f2850b0cc8c62053e069df241192c6af9018158c27e30574a9025af5af73bd956bc008efe84b31fd9a49c110b803947fc939faeb773cd3c33d1b6a96fca0c079f2eeb4e3ff768bbe1cbada9ad22c2d97928389e5f7145a346931e4138d66319f0154cdf3b28cc9bc04139f92e421efb522d0639f02935e228d6eacf3ccf0356b32c163dff6b597d51b64a13c8c93f60f150f445271489db644665ed1208c025b35dcebe82e73034561704c602d1b24e04c08e4ca8fab21c5136b6d4b7af05cf8ed62961b4bc1c2883154116a0ca8933e36042eb98d851be695d8c4de2c2530372c606c93bab254d6b00e59fdaaec98c56415da26ea8449061e12bd22743a1a0e0e1e117a4a9448d75b3a9dfe6f213460ca639632d404af60c764d91405391137ab9ec4e8519d11e3dcae18dfad0404ce14ea4dd36dc3ee24b7a15709410818ed0a42091a01ed9b7f39f7c87d60d2b3dcbba880001a519fb7de152ec06c73d35c08b3e375b9186752931b6108a4b84189fe07a7165e18357a94962dc2761f4eff0df829427646d2210b55915be710e2a1bb413df2055e7aa0b0b9a4067d35881f22c08e61b587a59ef82ed4df267afbcd4c62f22435167f2d7a4a939eaf28a6f1903c8c046b2d7719b7134834cd56964ba860e60ebb6fbf4605a11b52aac2d595cf3b6533fe2452b65dfa0fff71aff39124a88e3e02977d6063a8370f98e3cb8c80f35260a8541b9584b1d2bcb315b394d7641ca56539b4ca8bd9e4fbc594b0a3bf1ed678be2f9a18d31d610b55ee175514738717d47e4821150a799ebce655d0c75228c2160aa1936dd42f9923de2ac97d0dc3ea062d41d5beffdd1d69672b73490d6a5e14a655228bc39ffc8f1e862fd39dc950dfe648e0ff87807e543d02c40411ddfc6c1f8eed733750557c9f68d830c83af737c9d8c3ff0d23987a8e09e6293d707940eef4cc838365775046af35dd26acfbb4264a9ab84818a71c5a13d8e615c5675656671e5fc2e91b682e91eca76ebfeb1c09334e962496f583affefc56dc144873c79d4df77da394845fa29ff348007c8ee7f23f2944c121ee3177879e6938eb043a0abb75991b3e789571e3eff009cf089acee93612e97be85e1cd83da9ff5006c14151afa67fddbd9262667f98df52dfded25f28b36fa32ec662cd5a6b0f844030dbe1c87e9e2d435fca1a81045b8de5b8ccc411a839064bfd133731f55ee2ed2ee727d9382d130ced8a48942ea295bcf75fc74e24204b808956bfc171392f18554764aa80e75a539941d90a4afbce1f981f0c35bcfc78330ecf3d416d0683c7682cbca066a10c43273a0f85495cb4916ec0eee9952431a11717cadc95c7626436953fdd5fbfbf9ffe329159d1bd79499807796d75c458c3e3914d1f73f656e9fa273244615710c3eee84553a7ca0250e97a0b8895695bf86408d2f3cb2fbffffd62c8583af5b25b7e2a38e266c9623429f8d80ab8fdda6774df598f966b86ac228639af66cd0e3ee7ad7714b4ecb42876c31eb2608fab0c6ee26e97fca305aceeee80bbe22cb5e9819322aedff05cdb78b1fb3060ef18ce0385ae0fe6803b414aaf0b340eef94a7517e5cc3df4bd273f92120b8ce73281cab96821ddaab08b41b97708dbc7d0edc49cb362759905ce8d42743f83a0d75878596c4c5ca878b7aae6fee6ca7b20f2ee60ea773499a781b958f4353ceb078e5c04b0fef3e0112dd0e3a7ef19e4c63a202fdcb8ea56d15b2fb0deee4198a19c9aa59c1ef2b3de73f291445c248779eb5fc76953137adce5dff20f2198cc9e729be4adf385e0f25f67f68c04b4cc26987c133b987f477d89977621b8313d6d18a5ff6a76c73ed608f5e4adb860e2e8a6cdf237d4871a98f0c448668bb42f29ccad560fc1e571f8abb3c75665a65a212fe9d2c1c48eae9b92bd0a8b7b3d2fef99ffaf7942f5834533a592423d2cd66aa793e85bc8351876946a1e49e13ee374609932ec1af8d4d3f52e00f783368aa2bba882cc91c5fc6eeb657f3682dca8e9d63f319df3bd1cf52c511f600a6c815e4ad59426d9e1f32831dc5d8b0673c7c58e8bc1601d241bcb76c1306ddd5aea847dc903f376bc4d8e73a55f0a5ad331f57bee70533b29e6b8493d9f11ce4f27f9605f693c05487bd43882ebe8a1090a95abcfc186d74a3708ce3351ce7226183a21c08497dcf52727b7de08ad6a970b2c9f314bc7b33995ffc77a9a36ab46c7a05f61315d18b3f2217703be5753b4ee1670eba3af00e90a94664039aac93e89dcaa59d4566bf286f33c740feb763d0a385855f4410052c52abcfc972298ce03ddcb2e65dca251afbbb75c516ba77001dcaad8470f61e3391c1c68b1b7dfac9e50d53d2ad12876ba96419b39d7f94fd88b58ac1c123790bca733b12dadec6922384c6f3b7284334bed918acc06ecac7674428d56496e9d2e8f0175b3c7e384218380b6d59dc93541ac0a7419eb0ced7ca8c12a487fef9ea50280b7f7067a8855e784362e85703f6b848ddcd4bd31293baecda021fcaa7198b27d37900ac192d71de4e5124089bc1c8234fc455fe71171fc44494395b323fe3575ac720af5cff428326cca56ceb0c47e20e1432018a769f467405f5a8b71e15e0bd32f027640212d893678ec6fa16e5c00bf5c0eaf2de0333126ebba6b2306211cbc731a6baa8fc5a64a30141a8bde237c217161e384af3355b4a253d35766a55cc69be97abead95dc2ccdb4d243f64aa6d74330cbb2fc9fffa79fb6b6baf99e5ba9abd7966efc1586e72bd25f6563fbe125abec67f24e3510bcaa34c49499811ad2425c25593ff362c90c5c4fb3c4c45a4c63c46cae8cb1759ff2d82ac2726b60b4f094b6344191f3828c78d369956b7a28f650f63260c2dcdfa66d1df4731866efa6a335281d1cf2ce3635eb4294c8b2e1d4b7ced7b4b58a10d693e9f5a269b9d3451198735697af3a7b4b630b835e3b56e252f71f9aa6dcdfddfae13668bbbe3538d5aca766dbab6655c4aa906e0106640d21c30f1a241f4f5dedd526e8f579848f1b64808afb54bd2737a18d9a0e4a078705847b59a1ca4b2b554d03304daedca50726cd23326a6507393b2dff27921b5d7d322cb9901e0efce9bfd95039bb3bf6a99282f9dfb1e90289e986a657b3aa212cec6e611423eb3e4523f4723302b1b4ea5db2cc3fe3a7f0f3add38eaf228a6f0c02b9237e4078b438c01a0856d64053427af9f84eb04f022fd12986287b48cde73554b014f75a04d01f7d3fc6285347be643ce214b72c911e6c5360909ec590ffec8b4395fe271e97af852edd3801ccf04d3ed6684c66c67278cf331ac7c9b748e2dff377cafc7fc6732352245aabc9f5f25cc29d8f7f211a88a7aac750e488ad0304b7907bb063e29fccb16dd7ca0b78fc3962046a83f9c7138d49df3b765df47829e5f56e5155dba194d5128648b92e4f5c11bdc9232725faea4b87d6d940b9bd7cead9462736c7ef605336c40c9a053a000ac390b6340dc85a6905d35dc83c2d13786d233952ca8777b5981b761376f4ce2c5bec0587c2b28aecf39371b8899d227dd58c054aea7257dcfd838c32d6053362842a0baee7f967b6a4f5e1cac240896a8ec8fabbc4a551a55e674dc8cede1b9cee3874ff9fd3b91db433a12e78904aa3ec84d57a0169f1719297b467c46b278f671f74b8bb3c2c0cc2a093cf93439c1267e3be38b12e9b5881c27ab47bb01397c6470b80174ede3df34ee51ac116bad6fba58f8b8e2c7e0d1dde184460a5bce9e1d853d11ac017001fccfd5b767afb69691844e8327d39660c06b8916e918f5587f5abcd0f0bc45328ac01b1ace66405ed6c7a5080f5795f2ba0c0d9e5d05f462d89aaa230f240fa47c5c0de0b2099e93ae8c0f94a45f0513ce2797cddccb5216bad88333f6fec5805e0b9474a18ff562e78dfe325c1a6bb3648b41595690cab5ca9805eaa8e13526d036f4233f8181aa8efc76e14031d343bd5d9023fd6cd6b32947e173807883b6a964d398d3fdf9f34a44bc5fe41c5d72ffe5fedaa13fa1da68e19656ed70771529cfe822fc694be1445c79a041eff9753cf47a48ebe9f2c9f1546117b97a1c2bd6e375b957fe38cfcbb29f8eb726f18bc6131b1e27316064980e35d95fd913583b9735c6bfb03ec86e935024e60679a61d972b4aa296189fbc268552acb6cd890c68e50e325719d2f2c99b8105bc92fb582eafc1d618b4e88070e6d8df4924a1780f63ee216c0e937073725353b0c97acae72ebe521fb05fa78a4d6ecb7ba2b860190b6a5c340c83249919c26466c9cf4a9b774fc823141f65196df32edddad59fb05ba24738d81734004c42a7f92f5234b7f4fc0d605b032b08eda4cdfa3b03a3b805ecf5e4ad667a8cf399efb3c1d6822d9d5bb5eece6e08a515cd75c4485537eed6cbd55efb0a3d393d2cdcf44846f0c27cf6a664c70dbd54fd56b20bcc482de2eba84163375b1bccd43da63467557828b791dfb0a976628206e26e9eb10f1e9b9fc34571cc1a38f54909a1ee0b097e0f22f3ca58b56c631708e9baa52d7eb551bd327a6e0014fe98f04d7b0544fadc06c16a5652ea16b6c92a014bdeb2c070843152847293a0a925cf3c22bc9ac23464919ba6340cf233990690c94601876bc30bd5283f97cfdee757caee7b7b41fc265fb2ca9751e3b523e8498d665151d1c67624a084571f6c29973e624703d2e87f1ae5a5e0dbeeb96f46698223e063d10d85fd13fa0deb3891359844ad5e8100036d9b70b3b7831ae78c927a5e2c2ec62992cc424894ccd6f064e9ac307e6a2dd092deed179cf60b4bdc6c56c32a538d477d7917f7203f898659104ad5aab3e520a9f21d9c01b581cc968a68a77648cd95f66b5a1eb1b9d60b0a73c2eb05873f279c4ce43409853df2c8db254fd5b63af900c764ad4a0aeb4641e1a4e4089967e83603cef0317d06d1b990354c11b17c83c2a78cb9152615b9eed33e20f61a83179748ed4044a65edf285b155d41c735a883a481fa07c4941865b86d3cbd54c345d7933e32daa90a1291211191e0a3a5015f0f60d2ff07782606c164485aa469bc97f74dbf1345ea631bacb972be00547074759fab2b98a78cc43b7e4fee587e40e23d9f8ecaf03337d47d27bce633ccd97c0b18509afe35d54b1761a4ecbff6c44dba5402f3111eb671183b5e6bdcd69398056b980c35628f03214e0cb4ee5364e51de27843ad6c24b1e972889d54ed2a31d74000c32fc90b3c96dc3761c9649305c5f5e75f5b5ab7eaee213dbdda1039d4f3f450c77e6434752b74a55c42c98719836fd91fceb27be449d65c89a823218e882b987277622ce62fd0b46130760f10be6b49ec57e25cf6584a99433cedb1ecb1ce25cbf5e2b6eb716c12064f2cc45f4989c4c1b6c1ebd390c44195a16da16340d3a8588754ae676a990df1eaf04336b3252a5177ca3b3b2afd8e7555e92be6f6d7e64bea52c8d25adce3c580b5731574729107afe0e1025e6da2f2b05d6cc223778ac7de1202566098d43d0e4db6df8d242b57353cbadc0711030c6612cb92a9f9685c88856a0739e61d08c8fc5864fb9d8f41b27b43152ec15b3307e2c6f20e00254984e6284763acc977d9e16ffd4ca8be3ba7a289e3c5863371c132b8300f59d50f9efd344d1cf51c5ac64f29210740be2dfb720397941e2ba939e31c9ed563a674628b6ec3c8983be01e41eca61f869b920bf08db3255cc04a1f459653a4a3c204e6ec5496af1984f5e47caf56993bce1124bbfdb5d7081895a96170241307f000ed22ba92d5f5d920ab39d3ad1e288abb76ec3acbda6a7779be4c65e99bc7d7d5aa57d08ca1774e0fb146cd3a894beac12715bf322febeb256518addf26df507db3c79cb2883e6bb1e4716e185026cd760c76038d52a2e0695d76b3bf9da7df9f4dea5323f7dddc8ea1a0031851928e354e703651f7a21df505a4e7f9f7a8a398582aaa9f504510c0bc6f9af8942601bb3a6df3faf2e97c9df28268e1dd466857d413fa0bab4ff017f12554dd317455d6c716f9449c5273ffc959f147d7e0da0c2eab432b83f96f7d2de7b1ebc41eaf2128f8eb8f9c09c7b3fb4e95bb3424b216232406b81abd4c0afe11835a8425304376b08a4442c6eb0e88a51bc67a49b143bb35416c9ce613538483c091bf181d322efe10b2204aa0f0e01507a7cb809cb54b5cca5f44c20da32b2b7ec52098e53de672795b68a44ba667bccac558210307ac27bc5c203a2e6a264e7cf3028cb4ed41e29bc46985c1440187155b8bd737fbf9480749d62481d805463d75ec17c7ba83c60cc7020fe4b110ab1a248f6fbfda3e5b8a688a280f87a53ea7154311951c2001a7894eee171a64cba9b19a21e09540dc5ba85b1b2880efc39c8886dee72e64f045d00d99a90ffc81fc957ee65b7bb93e113717e7e7a275814404198f9e9d33f45335908f1ae917e0322b3d12c3d298ee814d22f8a57304faa93c18a14fdf53f05499239b66498512a6856ea194705521857a1724bc2925ba34f0e2707c84ee234c3436b4d3ab46cab863a28a011236e564ddbab3d49baf77be49ff2f5f2ca75252971a421aa2d4975aeacedba6cd3629efef8b2322b516c60ecca2541112b59d73b88177cd3be06163a463306cac2c0c1b11f84ab9b2fb6ab776bf0dc0fcb381975e4c1a0198b41bf6c1587bf6ca7272d8c722a581bce4494be5431cc5e3038ec33d843b9049b018fffa03cb3ff58e5da6bd6d49ffa6f776a5c4fee3cb258c4bf92e5e4079e38437f321e0c29d608cf5f69129e705e66a7036d67d43fd4a2919271fe07052fd30c049b793d2af0dec2431ea687077cb7a7a5badc21fcb0c2ac10bb37247207596d33d1c2232fc2a225acb9f30be7fe6da19514def9b595929c1c0c4b146099bcd980356b601ed0701299ca1a5547d62badd0475bc76fe51d0565b95b52a801f14e1f1ca62526cf8931f0706e3a478d20ce7eb1b1088454beac15277a72c90dd95f6146f961e41caccb2cddb2cd0680760731bb6db221944eab186425b0c2caedd840be5a2575d8dfd5810c4db5403d4491304130bbc564cb578d814d952706570e56641e8ce6232a2d4b18941c35301cd5c29211237c274dfb1aae379e25efdf827ff6e41cade1d57ed229a6ba76bf98de6592e5ae3ffcd481b53071e452a0b25f12919003474bf4ad2f36138d3d7c23c89b5b41a25c3622bf1dab6762cfa86a5bdeb6f2baa9cb3ea7dfdf9bdc700f4062ce8fdf477a17088bb2bf654e2eb9ab943472dadd73e3b63a4fdcf90fffa98983130e16d512b54aa0d4acbb1604d00fb2adc4a88e87d466237ee7b0fb33e5f384656a8759143db4c377e2cd264259" ++ }, ++ "rotation" : { ++ "falcon-512" : "0x3981b03586d7884dfe64c33f5b7b388f166ace48916b895ced22b34d428da6cb1bf0b0f292968d77e45343982d586dc6c556f8ac4afea15682ff6aa72683367a22398495006bf5ac0e830f10559bca255d2149a0740e61f05322d4acfe3a86645817823db5c1524f27b71c99374eaaf72ac0f59033a05ca55c563d1d2b58ccff25c58e779666306e18c1a9a4bcfdd7b47d34f68a96f3c18ab227b263566951271db2b7d6e20d9febc759c0bff4189c59f6add4708f3d8e532d58660cbc12ff5ab24a6525d98e4ff50f2a2b14f041e5cd6f0b1c4be47ae745ab7a59e8a220e5fc390c92ea8b085334d6cdb33fdaf1d7cf3c477367f96a54c46f9aa448cc53ae521bd73dd8c6a652f69373c3c7fb18af3211b3969ae922a3ad33babe49c88116a97125ae74780644f6c2d31dfc5987f550e2ad8c798d4f0f5a05b356dae5a73949b876f37355793ae6b0c6729ea2d70b12c74c2884d76844faa866ac685de8c74f0bb2f5ee9027d731aa55b2e9b1ef5a13dd33656699333004392ca27769c6a91d5b26f3ac3d65d74f9219d938f2b02f5fab2079e2ebe905915224480b53e2a89beebe3ed153b1bf1f8e296b6128388a5625ad48640cac171c30e689dc6593eb24b8f575e09438162d4ed215083142fd8df2f1a67770ba392d92a11fba399348aec782c16af5a41168b17eb6104fe43b49a7dbc01a4766fb962cd20eab637aa3e420a6f9aec4a2f9697ca26ceca1718843fa445abf3910cd92d877cba165d6bbf86aa5536f5ebbe450e62b06f2a3a8cb03dc5c198f5c6d90f5337789924ea67fbb0a07c8a06ff158d72f86daecaf9c96f12bc0b30a5e39c7e926bbe241f0ab69930aec2ec3ade0746f55fe3b18c536132cff870ac4f9bd0efe7d84df72fa1b6cd5334e8e2324e18da66ba979091080", ++ "slh-dsa-sha2-128s" : "0x563b16e5f93863fb9479ecda8e51da4c5e0b8c2ab218e682251dbdc02341a70a0bc0a8bfcd7fe676b4a88ed00ab7bad29a5226e6bec830015cc98a88e82d8907e4b66e4b39fab840bc60df099fa85f9e079a4afc0fb91c1ff5f8bc18679ec741add6e6a35870278fba0fb69e912c6dd01dbab121ae9568e4fb8d2be66f506b4094ad1e4a249a01fd55d6956780c0252f978308118de5a33edf8b1de9ecd158c4c1be63cc25aab2b1137868c2cc9e5c5bda02cb50e7a5ac5cbd6c3500c755bfad4f65bd913f3e8faf204a3851410354c9beaf9ac2b69ac726a1b61a9bf625e9bba4d3ece8511f6f2aeadf08fca28d772bc1511a4f3b659b0a8f3c6c8376531540a9866870faa1b3306ad1a8d26022a08bc2a90a4dae1a3b67491357c619df90d0b25d7329fba316d7e845f1c324f99a3f4dd60a0f58ee0f2f0d28efc4642ec3374bff548d20d150c31bebf560805bb61b8638fb8940def864a2e38402257a0fb446cee1e38e000bae954fbf1f4f26db7631bf01089f0d81d4bdab306e142bd1e1f356de670679e7d0f3713216064b14bb0f85a56e9b90dfbf0b1c81aa4968a855fd9d60cdf4ad35090e2dbdf8de9224d9fe53902bc02abb46bb568a0ad2db5a73673746ad968780621277519e39053252c9e8fb46d44fdcbbc973875ef2e3c991eb5ee02671cd1580d2ec9e8c8035638d2f5409b0343173a071b2a72a237f8bd4ccb5d080fe6510ba2b355b9d39b3ca12ae06f2766d634457455d72d519bbaccb2efd04a142c7ede443d0db7b44c2d5cd0a3a468932a9a5370853bc475c622bb5c8c52eba04325d20a396ed36e5d4a59e1c00861f3d0b0e08a9f778c70c7e8ceb448ca4a52f6e0bef75b34a5471a3bd668d5d693f370048c93657adb1e5bd768b5b38f6efe11f315b3e6e62358c28894ad8ff475f98584ae32ca9c56b39f4a9f3aece99d8e3ce5d2443441e183e479964a18d53aa867d07ab6f6d9d019160421f283678a0e7774820005020b98fc058076fbe1c65d188c4d5bdea7cf0a5d67fc39820c80726e72837bbccbe1c396a79ee29c0c23ef9871795f25afefc81ba91aedc3d6799a093a0c0d533e094d5f1fa60c6ef72a4122ed34f3ee5ba6992b419ca1de2a9585bbbecb2a705386096e929e7bff99ba7a5e33805288c8ac315f1679e7f055d1c63d3229a206736ec1f7585653c0bcdcb2974d9bcf9fb805a89aa2ff4f57e98194ddf8bed97e4c985313b6487ff4a4131bf0a3e86837eaf9caac911548f3a60a3e1bf04d6720b1e4d60685b6db4ccca66123d23e17f2f004354bff43c4d61ceff52748c197296ae3c8c6380baba17d00531bea8f4c1becf6eb6e9fd50c86bdbade0f4da4015f486f970a812c778fe413841f0171743044d6e77789f1bafd6abd4234aff922148f3dba40f3c194053713b9b9a3d7047bb849cb5a806740d9424288bea002261fddc12a6123fbfc3c8dfa26753e92e2f6fd14e4f1895ec36d90f572198427f65e92a1ccf92bed4f56cfaddd747cb2a0a6237325eefd74da45cb52df13c7e78e2c60bdc332d118fe51e3f17cb85edb9d5070a8addaea082767ad40a9778e46a61803c733d1f27e36a4d1810d4cc77757509622ba4464ebc3a2f8bc9c9e49a650450f0ea57619c179e94eae7dba9c66cd079f160398a0ed40f685bf1a405752f9b2820525dbf697e5c198905f09106dfcbca5a5bc62a72b2dc8b85e991871a8e4d7091fb097e0ef13c63f59a939c02b94c58ed9ef9cba75db728d88c81619c86d95710c5b51733a84b9a8cf068869464c35d27bfb1daaf140d65afdee9b7ccdde62d5d4e2d83ce670dc49ade7b85d1d8167893d0c68faa29d159ef95d4381bdc6a4234ead47a472e7f9740db9e1d8c5a4c66a84907a056d625b6f8e192a89b10f6d4b655e74ca6b01e6fbb2b187ed75b0da052713862e7cb3457df4202bb8df95fe309b8eb87a711767afb1a3003ace4cb01cf3de67cf13e24e6d166e763a8962ee7f47d5ae9a82b951362ff226ec3bfe12b188ab659d8fbdc38e0ac6d0a8c68c5ea7a273cde1b53d5063c5c9bb6b80e803261ba27bd88330cbe619a580f2554171173f046ad43e2e5be710517889ef08cc9ba4018b68edf3e843ce09d0cb226a2f84ef49b60e0cf97b70dcb84a353adc79bf8dd7682bb18ace2282b0d78ab1854bc7294e3889c8eac041dc31ddf581e9697256428c469fe3d2c68d6ab627bc9e8e730632c518837a25d4e89aebe1cddb015b57a88ac7c3c6a2f62f2aed77ad8e19edfed15551941e87b560f05b24b3f261230ef1c3566b8cf121271611632e111756ce0346ad9ff9ce3c8caa1796641f5e019420273243dc1ca62721a62c7f182a53eecf09acbf08afc58907814f0ef90675f634b6c4e565a157bf4acacab2c01e6cf62f0d47eb3ab93ad79f2d1661b1aff34065e6d7e39746b3d94d92670c7c78e04f16b63891675667b83fe689d18b348d640cd5dc302c0b7a149eb562f29ef317218d5958763685bf2d86f756853538a5e699bb3f0e58c1934892cacb9854e25211ac4dc4fb6eeb2f59d99d2dae281f2592f0ab8f1f4e59708751da251342bdd5864e7a9b563e12c74e7ea762fa2db1bb5cac5c2b02b680f27f7372e7bb7914403f267c0e5a8a8e7f59b4f28fd0254b570c158917245d976bf85419d8778a3f03c02f99f853185882ad19d3aeb2382185ae6ce0349ff3ab4b7b419c6647b0edf74588365339b4c22c54bae1522c82318225c44aff5341b13a09df32eeed978da9069fe9795cda0763c78ff688c1c456a550ff450bc29df105407859dfb13655d8e6063eabcfb209a9af22f4dabeba0e151563ee2a20605573c3e5bce979c420928688be7c5ca0c66d6c4760299fd0699a7b96be126bd16c8b57d2b3da3a31e44ccb85626c1a5845926564305db1575137fa505389c17c736d648c96f1f529b100123d7535cfd9e6636d167083b1f2f6462ff227116ceae90240515329fdfd232762aee1d9bbd50fbae995cc4c27f34cfe21c924a603564bd3443ae0c2a6a78599705cda7d8c1224adfaf1cb0f1b7cbf6b2f8e1d3e69e200947a8cbac5704613c041b9eec1a947a5a45a855651275c63bf96d0bc26c964cd283e5cc2e81f7b13db18d58fe5c31da90bcd5e03ccbd9b7cf4af67897e031a73f7661289907c57455bc2e77237d6959328445b2c666bfaa5073914220324c8ae9043548f2cb28167d6d22d919f6ef05c0b71704fbf0e6ef338290b043319013eba466edb620c14c27ec65c853d0f07e55d56e12295e7e0b2c7d0cd342a428580645511780193dcced94a2dadfaa90e789775f42a5220f13a7757b966219da9ebddbafa76281fb4e4f10fad3b2c59bc1279e7892cba7c78f0492b683d6ad565ce4cbcc8678cd7cc8db72b2111bfc5881042c1eecf57ecace2a45e83dd10b60deec32830a8edba51a31bd72abaa26e47a59d7db74612a52544f05e3989d93f0c25a3a3802d86f025afaad0c8f9383b02bbd671d5b308f7416cfd3caaabc7875241e5f13643022e2e80eada5895a48d2d4fb5dc190f197837463b6ea5d8cda125dce4e9a1c20dbdaeafd6d5c14220b49ecb149848c9714d41e9324226e6daff80949fc51cd0eda6290a75d757200fd1832fe20a3fcac026cc04bc75f91310e6959d417a1370cf88e132333439d5a71c9165ff1a6f1193b2335eacb42b5ba5540def54d6d0960fa1b37b655040b594c57ec6984b273c58228a9bde8614b8f6bcc874e7dbde109fbdc41684051fe05c4de5dc0bafee37fb2be501e36e4d8ea55864432cc554a01c4c202531edc612f41dfbd0c220ca5b603c7ed47e9be4145b1490161e31a2e6c82eace746e62bb8862a1b85d35af5286587c3ea6bb72444dad67abee707a9d583455181c0b246fd0c33d3522458ca4abceaae209ea5464d294837e7678150add9a37f3405a76baeceb0eef3f3fe7038980e96652c5e53d77b15dd8197f304bab443ca94d66f43d69f4c7ec1c7bdc57093893a67d20d89e587a9988e873457cef966d9270216e65f1eae2ad0d3bff25650d884ec197a69e5c76d39d77f7e5e1c623bd664645ed7df0b69e8dc3aa7e6260ed481ed07cce4405de34313561fa30bd3a78a7bed156fa773c0405cf20d4b0fd1cb60d58a2eb136dfac1e388def9e81a9d1f1f769be49d1627f206364c61c5a09d9d35d7ae05f8eab1d0cd633cc4d92fe1fb58ec4845c16e1578e80c0702471577e49dc9e106dc59c02b534f59b0c449a2ddca0f5590d4c34c5f877503094256f017c9a4a0ba613d136e07d7eeb3a4cc23121a934ee84249820bd64987ec55351d3602cc7afd1ba272557e531b3371b99df3528dec1f8d1d4eb6d49ddf94027b9390eae72f740ff649a4438448463778df7d5a0a5f764336a2efe509afef92610de6dbf22cf51381a3243171cfa9ca8caf6ac9f4e0ea6238cd7ef7bbd5fb06d3426aafe2bc94c8776f5ee74725b2f7f1e91b533ad9ebc626cfc5d2a6eee2c792602be3e838f4fe43e1851940a1e21d2c4fec3fd672b0c7d3e266bec169315a9960c7c433517484693894f71328b5738127fa6e51a6b0145f7316f5677581146028bfc4a6e3399037e6cd038cb993bd1e63b7c5c9020ddb57dd78da6b80b9593eb0252b499e66c0d3526ae41d19f9430ea7de2c8dcff825ab026e4bdc2da80340d14415f22a009bc7b325d615855a98b403a22939ddefe7d82f9b48814c09f4a121ed92575cfe32e04df38cd041fcaf0b1e572fc18992c182cc8ebe05969d90970ca0ee9b651fd65a4d002490f04639bfce86058cd1ed219457242c4c233e5a4b84cf3e62f45cf2f2e308b43ea17839640a7e93570a4ae3760ac79ee0a61290944fe47ad43c67f01be52d639c85b3b5b07a9aa98b2e7cb3dddb82d2a0edf88c38b4119bba29cf812970bf79629d295c2764a3d3c8b20743e939102f6584458ddd1da577b5667dfdbb350b596f565d64040eb16e6b00a1c76af2e6ccc18273c3075b5bad660017506a24b8fe728cfb6531c16c92f6726127e93e919bc4a018b29cab8b098ec0390106d37e73e14d647c00a723191ac447819457e1882e7930e147aa05c6a6648d073baf7e0a379cf4a079cc2aa7111ea0b81b6737a50e2a02c3e862fed198020f295b1f0a2fd42a19d69599f3ea4263b01d0899cf13509bc2f0490c78c69cc8182d009bab3a84d12287890ce43424ec7fbbfd0daa76f08fb3e0bfee27688ef5ffcc366701539cc87446ae2a0d910664626992cfb8cef95990e59ab088db3cf5d8303820ab67a3f463c8a38c054e1791c1d07e9f2e14ee8d1138ba4b2f9763fb9faeac3679a777c60048341a9c3f370b855d4125e9597db28248e3d38313d18e5ead92def8d04f7b286c4f05064a0137a1821f5e5da38e69297b9fce7ee55b595ea05272509dd1dc96fb28e35547e2179808d333aa357fe87dabe64cf1c3fd4dd75bf30b9bc7d4135d3432df069f5b60e152b287e3be28f552aa867b58e47574cbc5facfee6dd2f585356bfffdf2abfbb13cc957a56b0e47225b9df42c4bc44f7da0cee1b64d4bea4d7142dc18851a86eba8ca3a632820088d1d0f277612181d33e66554a538228cfbb163174114fe8b5b143edee891d6cfc697b0dc486b384db8cbd20d1b48d43d254a5174adfa368a793f060c922a59bf309954546648d174ad56f045f9712d2a064ab37b05f92b71f3e11cee5d6709e8c79b501b103db8261574533fcde6bc4c26b257ec4f0a3a237b9ef488e17ad5af95fcd176452d1b7e20106a2119508d9e74de932ad79c4c608f1ac76e95b9ffbf9637cc0267b8ced6d139103528fde29e1df10e5adf50882053986d1670d420bcaa3365fb662e0d433508db556ca2a5913eba6cdef737e856c2a24be7007aed60ed10fb77b7e9b339a1c7da723b3ffc12fa12a012cac3b0be1e4a317b17247b5f1102e006c745fda650ab1ace51adbf3bed3c15281ff975e2e7cc58b7998ae0dfde1e0c1376343d0dd0aadd07d8919c296a7cbd4c8265ab3e0a4f5c1f6da51d946f9bb2b00bcbd134335691ff4e797e9d07779493d88e1e91b033479207e36e76f1d4264f551ee2a9a95c33f4c588e5f3d366e2f187d8eb77ebb3f9acd757d7384aadd90392aac2b230804502cfaafaf2328420a41c173d903996cdd87366a33efdf9d565cb0ac0078b2f40cdbf773b86ea3f44eff5b86e822b536dcd72006123a4e11b26d21120d8b250b8dec716b091b1eb150857bc64759f31d7add4b058841193c58417c33e9238f4741804f9f148096b15ce8cec22dd2c4636a39e86eb1325dfa7ac87e58d34950a309b4c513a7e14f00cb5c8b6bbbf3487b3bf9f29ce445a9cdcd1eb402724b2f092ea52ffcc3b24a482a24d19f89d44afc6e166082bcebafd24d54bb5022a08a2469e1633edd7832e6c74e5d9976beebb6928620c9e865991d093313f4f24d7e8d7e63bce3e4bc8ef79be24f2b7278dd84e80801d304cf3d775e53e8f670fb0ad4dada5fca06536f31ab452a7d1dbfa032c2bed87b66d0a7fcce064a4a28b60a7e626605385b44fd54286ce871212268ab65415f69ad0f60062f8f7e46702d5f54895d9b2e7c219c30f1a32e061fcbb5875af955f73f2bb31db7b282aa12dd0fba2c8e469aacc6914c230d499c8b7ba92572b19dfbc2ebaf4ebec1842ec54ac05d95cca796beb8cf14f5fbdd8e4baaf2d59833b5a329e4fc3f32c730d5fe55124b1a7e4fb7f64f63f74cf928552e4b5eb1f2976a99198925c0ccf5ba8ecaec313d216e7adfb1fcca3693b9e74b326551a0528c5097e1f34247b5eda7bbacbeb21fe6491ce67c3c7764cd798b1fa813454bda9e017b1c8981d95b3e65782f89514d93a0ae33ed10e6c8897a3cdb9d01cd0e0e12f3b398ec72409a4adcb18c7f6091823079782cd68ac017edd272464805f3e831e06f02ad1e1da0acb7cd6807a9b80c29fa3b2ae5b1b75b43425041bc26cffd0c9bd4372925f3ebca751480063084a888fc9c0bb5243dfda4b4a9d4f8dae59f4eeb768788e4db8a601082ffd3e09d9336d5f339a825676c3e3367b161ceb3a6cdd80ce650fa711452e886b1aab4f4a92f07141ea3c28bbffce0bbc4b4587d4cbe42b3dc7d92d0d3298dc751aa71ff7aaf353a75ae3f23363cd925247660562bfd43348a7fd2fe33b2c46196a0b7f30ae843f32c3141e7cd523963162eaa726a8ba34b6f34d8980d8a69df2a103e0462d9d57faffd6c1bb3967b877b9e319ad357fa05c25c27c823025f246086de0f60d668930a5ffc304a026dd3c06a1ca2ff6328dc9046c28664087cab513358de893da3fadb740618b5e0086ae17aa8ae59c2a31592e21287e600fd14a4c57b285991398298944729029d979811d3784484e2d09a883636be1cebad5ae042187b62fb858e47ee7b66eb0303c3ad215f3f1877e6298bd439d10dfe2055655c68527efe9fb5188a3345959a36d49e3fa5f05d1bf880cba1827de4be26ff650daa1f0a4727383b2601168996303c550cb8ba0fed5d739905adf7ca5655d34a953cd6a6f47110fe9330b831bfdb79213a898f1e1e719786407e10bea78527c94799458c64706afc3931426326bbcf2490db4fc85960da9431b9028eac16664559c32e55ceb99c020126d65943eb4eaacf0fd642a1fdc2885a749a53e27eec2dd4927ca58cef7be2fddbe7e3c6a9b7f8a1a047e1720b36f92cee110c5cd35fe4e5fd88902feccb964953059a00c783d7f8e480955bdaf448170d2003e14ed223c2b9938744e1c14a619bd67c306df9bb00620cb300882c2c48de11e512fe4e249ba69aa527cd718faae2989b9306144e63ff75543e2a8ebaa92b19754a32ef4d4174c8c25648aec0336af2ea17f85096dce5affd0a6da6079cfa04c1acadda7f91f1a15f4d2fae5b3516a69c4bc0664066ba697de2de4ef233143119f5ff216c68d9a37b6ac5d24f334851c147657f0de1926c1b026b7028d54578e46383b4d83feb0fd1e366e682aedd5eef12b35ff8e192f82d59db1e82adaef5f0e3138d5b408e5948048df66f20501013b5cf09755484236c6e20e98e9deadc7c6280c463c002c274243b85fbf8434200f8f6621e754a8b1dca5a366bbab3fed0e22cb235ee6d8756908fc49a72cae7800e9cbbde623963e12a1b1c01e2129d65ff53d6e363da80b47323d15cfe7f45bb9f3c1619c59053584cc4d68d586c35540a907d590b7e076176609687af7f06f811c6393436ec08767fbdfe08145165869dca0ad295de1d4b170bb30b0184e92f40b3b0225aefee2ff8d3a9a94827bb185d48bb9dbeb2169a377b9a9ea40666eb61009a41756c7190cff6db52152119e97c919f9a327bce47b0c8ed157207cadaecd89375155c9ede0ec95dc336e038cfcc3fa6a14ec85371cff3a5e28086437c5b4f343faf76f77980f2f35d9592b9549eb94cc402855d1a88bf04a67484e9a7b7425179ffc5d5f8eb6474dd76d5f64c7cdad8e002d65bf34b9a7f597a515e47060a21ec853eba88bb8152ba22e682ece98da7b90b085a80dceab5920668cbebed0acaee891d7b16c5a5075fc007a63f954a5b8ecad07ef54ea9ae6d67305591f6042fa1fc5d092300da6c97492653d2a4b1fc3611f9e7222451ebf33a836d153869433466957717d5a88abd01f94783102efd01116d4f25a5a64d8ad5946f4e798e9c4cf7ce615aeb0bda6f7c9deb632f3be4283fe8e7a45a920e15824b8f354144b71dc580fc6c1d5eb5768417eb99149a177f07dd61216fb1f85e100bf2e8c5c4d73055d19ce09e970085d2213617b738ebeebfb386b0765e2a5d0de3cf7cf147859cd9b5e28e388f2b9d1de6987fdce0fcd20ecc563331290fe28a4e1de9c327829c4c69bd18745a8ac8f9a0a8e4ad65b07495a63b20f4b2f4c8dd49cc43d9474072781ca60637837eef9a2c9596701b607aefd8c679a3c714fcd9a85f73108c87662a37376f67e623bebe30995f02855d216a4493315ef3ebe9160d9ee0c05cad991f7f42def8d662a144d5222a1f3cdcffc0ec111b3ea555de6726fbc4d0893bc87ddff378628049f1fba03647d13ee4f98815843c619b9f02faed2d3fe3da8bcd4e839ed749e3c5834597ce1e2892ed0d443d8d983aeb8fc69ad80184e69791cfeb634b98949a17ceabbf7cb2e85f7d3d771d5c9a23f327c4ebf8ad8495830d2f2f43b0a500476c5a37ceb9d475a23f15c69e07d03129265dd70a83ce8a5cd40e929c2494830897e41c62de0ff8c8dc9afdff4844b28d4acc376abf59dbb0d08a2f01e7b622c702dc514bc277a1129619cfe00cdec4bc9a60383f43b79587efd3eb9bba9637641068430ff7e7c62ce572f1679962ddc524d200c07d427e6db62657ddf872200751be788d462723d1712e06017f6fec18ecd978ad377d8db8661478d2cf60847baa34dc43e1910482d42c02c1eabf8f3a3fa7fa8566dc61756c246c44a2bbdc6378ffd6dc8e35242a057c7b2751d8f537f6596426be24bf89cec38c7133fd1ee024e53321bd787aa1d253b608e52328240618da5d45af03710cd1613211f87768ab518bc4f1cd01254cce9c151b2ab653c1451c72b9530142fff1bd6f409d8f4b4cb2c589b7bd65a73aac8980d9dc807856e37edb7c31e27fc7eb812d5c39d8f95ef26626ba580b03390c180fbdfb2a3ab2d6fb563c51f49e9a10f25f46289e74981e019e02775918fbe9a8cef65586cac7b9020bfed88ff27d60174f73570053b1bfda473050b015427b14d561f773c2f5b4ff4e7eca0e4e7177e811e6eb60bd72b1c0459d1ef6615e5038d7fe06847ab24a7f41d1593acb4b54d8c2fddb6ef23d62b0246cea17a1cb2dabaeda2625b1a64b9da3b88496349c41b33935e39700913b23ca60b565d961442cc8c7a8991afe7734965774eed9fd267fa62ecec64f32792d9d0fb19d8e666d852466da5a73ce68275785b983d16ff3849ade8adfa672743d923858e886fb344f653a0247d40c7b0b87a7469c48d6056c340eb8d7e2a04b90930801424c6b9b2547486595f505a89e1492d015e082957168fb103d11bab79cc4852638193a855fbf35294ac690bd295f6fbc28aaf194e13e4b76c6d05772a6b2f8513ce2c03d884fad0df46228e19b940398ffb09c3d5300b4ece8e71bb25485d0d44bdbfee6655bec314759e46e8b826b98692b31bfe2c817e4f5d6cc87e4964770adc9c60178e5590b31e9880c80ac9125a972b04f4e24b1eaad78a691f70823dea467f61a7b308f8191f2b8b7c006e92d950ca5b8238f20ef75c28f81180ce3ae09e72db1700740e7a252ca957ad52c4a74eb8207d3eb9d053febbe48b8640585a2106857144a1c2dc3d12af55a97bd93db5dea31a28bb94a64a54947f9443c762eb8efe68499c9ead28cdeadc913828f00c82fc4bd96aa32ff31975daa9c61b4b6349496292d9b75a6f0012280eadd9853ee4d0130cc57b0d24a0b8115fb5241037e91b93142810ba2daeb6e2ce3647f367111082dbf7083854d395b47999026d112aaf90db3109aaecf7ce10e72ca13d5f6da166e9a938fe439230abb58abf47d72f39ea60436f0b8f939d76832abdf58f07d90776f29101b99c808d44ccc7fb60ce155cb3d2a38e5d4f215a7ff552cbcb64d964f1c9e32242bef9175437cd507daf55dee7e3d48f4c0c5799f2a692005c7783d11eb84a533e79a1dae908b2e8b8924b0c9819f190b3f8ce61bd3236b2d48025b2e707a2a64401a821603b79329d390c3a75aa4de23ecbcf7d90d32d6a42c160e02843ed80134c3c542e16791b0a60ac2d3df46e9079d3eb37b7d220513a636c9437945022c8b9305d90953d478bcb956c28556066200109faaccb090c4084ae2e8126bc01c9d07a7f6cc2407d0c4a56f11b2d69780ad0c6295cefa259169800019908cee9d52804c16fa34b4c5e7feae98aa5e1ce7c7365ba499fa1622bb5338b1fd951134e48e4bfabd055263bccb2f204a710dc531c7abc412c92cde71b096c9d4d2ebf98d33ff42c3a30699d14f111062a78b5090bd27f3cf3f6904d81d4cb8a19a924af0dc45253d370c5a1e7dce7a2d1457dbf59eba5e4a17545d1c86acaa4805e4aad" ++ } ++ }, ++ "2" : { ++ "id" : "0x41f547a71d1404f147606491f3b96e49f67d4658", ++ "keys" : { ++ "falcon-512" : "0x09b3f618864123704b78a9552a0b068f395444870c2cbd5d741a0c565554bc2785a691ff502d6ed0e14c925eaa24c075d20949d12f369848e178d50b085e87c9b251f68b61ec506435bf5b53a49d299409f54e906daed0c1a25a63563090f6660380321e786311b492bd7ff684a2650bec34d5bdf071c49f5a050415b2c3579b2994fbaa9a97b7f24a30e7e8bba68145196e0424471de31775aeca732dad506b16ad4f61a325136a6664f439e60687e764a009db3218f706785b98b154a625c168fa2ac541b8dce39682172b95e19424b98ba985622b2a23d8db2d46a7230bcb667372a924aa4d1a9e9cc1a8dc1ae11fe88081d74d857bf63e9814a08c9ce059a4b1ccab23a2fba765086b15bcba135d0937a064b90663ec69ab521746600610bec0a6b3c705277f90d588a00e908dd075059de6c52fe05fd8fa8ba1b3c2cf151cc810225db79aae0328b8ea1e92fc67b7bde405a1442128023128a5f7089722b954f15597ebba3aa3b55ae947be1e659be52af04c3205492387b51e72746a904ff13ae41964281ebd81783528269ccd6d2a7845d790fe4cda8ee58d93de3a3ca28bc4e6e18e812c313452a4468049a86ae39d5fe156fa2a43d29161bc911d515f4cb6b625f4679e37d5b55064a16c3e48a7f3ae10a09d9ab7f0ea4dfa2fba9da412af1978720fc47185c7ae16474833c8d278dca65b822c5526bd4da67c0700166cba95e3d23691e6e1e86ea4e560cddd59af18a689c4dc2b6dc0e114f2a84754498a8e299ac17a12fd199d1fd8d5c31b0a40ef4b2fc9627d16ec11241fddb4fee6c652d0119f7d60e852decd3489cdfb75c10a18f562154e542614427ee7cb0e96b99d74eb9585223760bac37de51697d86403ac877f823451d8c60e84188a8fa6804c3a8298f223169c4c61fe443434a76d6a51ccc1d06df3b962fdba9e27d7723a8390f4672d66dc2f756263ab928d9d14f6d550acb286647ed6dfb091c462cf4756194ebac9c94bdf7ae4ac7b5093ab9cb94455dad8ab15b134d31947df478a1aca5e28e98020dfdb6d4ab750911bb2690104b9606e78c8659c2f511bfa3254d32e65aab180ebb74f9848700a8cba3a1a546b77678a17716f232e57b204157761161670bf654f182a14bbbb1c16b14b652127241167e898e097b6270b062f0607a50bb040868768a24312a8da316dbc547237ace3a160b7835c805061f8f2723386929835251945908058905f625cd9a91eea83c0f693523128c68613038e", ++ "slh-dsa-sha2-128s" : "0x9fc24e59b10d63d59b6c448f79d029745c4f27a31903ad2a6f6fdd09b3abebb1" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39916580739423a110970dbfa8b6f06ebfe827b6503b1629f4008d64024e63c71af7a932f3f29cbf08eae4cca92f36f670de2f3a0a461999f431bd5da16b868d2230d6403158010384f0f98d2b95936e0a132f5b86f5d11e32ecf3cf206ab9d26c1cb7fc93ea3468109a59163b15391795b76ce450813b28d28510767270c1c474632bd6eab70174350d329d0039ef8fa6739b2f665fff021cf669156e3797da72e5913d08c94a48a16d12b5ad7e521b730bef92d7cc277a92b3e4c9f9cfff7cb3896f93dbd495637c2a47835f2afde4222c8dd36d4d6d9cb419b5b5563bcc1a61b640e70bf2c4bed6599c5ec50643fa302c227ae56adc3d4b044926f4bc4b26d58d0d0778e2b8ec5e18b5cb9ecb6d7a26808962082bea23a932afefd0d483a9952f98ea11b629b0ad74c367e09cc016b817b624547ed8fdf360a8a06acf7b5f0d3c92448d9f7e9453a4e29222611490a7188dcd0a8568b67d333228454cd9cb99fdc9d6d945a64d8d96348120295b8f2ea9e95f92d9dddfa2a91b6ea2c44de7b605db8e3e1019dbe5cb464e0b211713cdcc32ef3631caccb48b6b0c968492a5f1288e99ada3a4d8287b5c9f46236b4b3fcfa55135f1ee4b13e3d6765866a316d8cb3ce80d67a518ee974976172f91eff1cf973631ade2a2b81134c39d0f3c72bf4fe546a7bc7d3f1142aaae3f5b4e8f3932d9b516ff1cfd827e7395d576d96cff52f00e76abe5ba3f1f0887fb064ee11096e52d441d1b4dc7a69462acb7296c489f498c456b2336f2f112391bd7e545629697bd096ab373a34147643199222b8f1b05a95bba5877aeed29c43bddecbc814a6f2bb38d1dde30c352e06f19bf52717236488848599eaa1ef17873681e91064430aa2f4a23445fac0a8c8231c8cd7c27f928ca0ebf7ab08feb53", ++ "slh-dsa-sha2-128s" : "0xe922917f6a5d9d49338e445586f4b3bfcdd92b89a013edba38e598aad56f8d10875fa62dddbce6c66865eb7d14067931d640a3b7c5dc448bf7cb6309943c2f0930c78c03fad2cdfa1c21689c6f621bfb1cba1968dd28e66ceb6cd5cd4f10b8797a53a8ad54e93febced4dc1c48fc4bf768b85a811866f86f004fdc340628ccf44b295fb5310898614b6a0341a2456b94930d086ee75f67bb935e62c739fb87407975f78f372ec11c0bf8bce5144abbb2678711850174134e6e5acc3b87f14022d158a57dcc7916a8e75341488af6b1d9c0af90bf2ea86440fd1b8001d7fdb8ecb8cf392498e41f8be5c7aaa81841aba7422c45fcc0caadd52d36d1d56cd02d027b6ed9d122ab3d53597507079bd9fb476105b12e3406c1873a8bf6a5b9479b5cab9c370b79425b1bc7616e2f1f66a398c2e38f7a9ff1077918fb3f7e65f025d4feb8b13397460a753b1999b3d351c5b77ece3751686c02db0ea4ff23727527cdaf038ff060a09689a13fb7dc902cb82844b11f8092625272d8888090e60cb1040b6cc5b0ceb6854a7fa769a77523e7a718a1a9cf56b94be12fe8fc4d319b335757c6b4807e17e9ffdbb486d9910404e675648d069c55e96894c7b2ab17d91aff88f44ad609142ea3747117596c98831338c616cea7439b1754390604188018818a5fd2cac7522b2df5e42c14e77b7383744234da5fe1a02a60e18a178751eb9c0212cd847317d64dabe4407c4a4d2ccb6965eb33699c37c733d42e66f92b01cf8b0ba2c8d737711439de358756ab4ba374e7359f8ec5838f531c984e2903026acbce89ff2935855ba5e5f3d85c82bfc3975ba3d4a9721ffaab1182035bb7526f062466895c5900f854fb52f5913591828cef55cd07d70c5805327cccb9822860f32a8e8f78806e39d36ea7be59186da6ab5f1739b6716323b9379446ce6e50345cfc9b769162ba96929e2cf0693b77a558e5386945fe5c6410a2594805695a4cb602fb25993a0359753f4ecea67d0a1045a80054664a5f589dd823d11b1e440813b3bf141f119c38f9595c1eec85ce74fd0cd69ab783ff7adf32746d3c4db1153df20ca1ff94acfcf3c8ece27b9a7819f7751028435730771a0d7eee4d5a05627e9577de7a1c0d16400a81c6d93fe48990d8d4eb942233b6e81f2606c228423d52fa012ba6de7c24ef446f32ba1e1bee5ab78e79f40ddc3f8279277735564901682f03ffbae6176aa8c2dc6871cdea56cb875f25c88d955ad2e5f560fa25acb5d2130327aff86a324aaa721874c4276667404738fffa534f26e4e0dd67a9d0e5d447c2868af3f5b93dad621f528509fa6c3d2b9a391275396d3db6487ef219bf42088433b79d34ce793f024380319f1a0017c0cf821d998871fd35d2da47b774f6c6664e54090d74d087fa43ca622417314ac0a7f2d23da0e9be5242191b9096ab0e200bcee276a787ecb770a60f975c2935f24600869822ce96462d97f34c23eaa50b443a504670923b260e1698eb12a76a094b9a8b9bc2fb07c38b03b495a70e4976d05477ee88b58e2d66729a91f0fc003e56236c5285869a6eba073b36efdac3999ca0b91408282f83b179629bebabd5355381c4435bb173598ce3496dd8616eba46505a64d29a166b51b1033cafccc0c6cce63afe4f2dff7a2cc62a909853b14b40c418d3a180a922b02243637700c87bd0268e3ba09730a2e2e20065a7310d8cb86ae6b2174454ee4c01fc86c0441cbc51f1801a021da1f1fa4ba6cc0e8e35a11a0e55a4aec60d5c98330ea1822991083deb2a80efaf382d29cd0b04fc2b3289e024814281aad94ffde1a837da103a0022b23f223e63b852ce8bb89d50271b29b5dd805edf1f4339bed98ad4e4fa42cd726f3f70c7c434035cd9180a02ac954a1173c2694f0cd59942291c34a8071803a69552d71b8191c4299add494d05e838803e5e9de4e5a2d7b0f8b4a221ce677b5b365e57284f4b74c973c72a565422b2233a5b3770cf28645a18ce1bf7cd0e726566c382d801e655829a7c5e2aa149217075014492b80533bad2c8013c382aae26cf4dc39a6eace929903894f85c8e97e4be1df2bbd53fc780c46ed384e01fb40c515e88bcbeb2005df6c152f0d169a90ce3a43c2c3469a85a456991996f6e9ffab555233598f767b38307fab61336a8d57c1f6753749d46e1b3032532a5ef11082cb30e12bb6b292d0f37806e6208d4bbb7c7cba1b3b410ec1d29dd35af7d38ba79059999992088f06b587bd9570ad0a1e2352a6133a50a3a45da27fcf63cb7c6fa98e6d3d3d7987447fc596edd9a157d72d0bb60441935481c54f9c163b985c708ea1dc510f35f9aa8768e73843ba5e8621912f43383365f534f3ceef986e90664123079f7355e5a5193b0ca1bce0443e01adc00f18f8f07a9038cfbc672494715221c0b8c5dadf7a66875ad67300e5fd662ae7b4281f2df29aa0f5b7f9f70fd3180d7875aaf784eb3da36f9fd8abfcbf2f156392cd196ab952669a531bf941b48b7d2850cb8a66addeeb1447d89daac2079094bd4163d9e0d8ed52e9a93e31a7d4f5d2afc4b7d2c0b988d41c3e247237363dc05dd16d49d159005b42ab9def7290a51beb7811e9f4fb9961a7af09fd4f291f797f8eeb05bf76884ca340af07f62f587dfcbadb344c1b350960686aeecf772f59d3f5c9f6c01240667d1fa5c3d84dae1f0dc9562543e4636d81a3f0407bc29127bf4b4527d0f6d7815a941fb53e6527d5940739bd369786e710f6b0f69b05b2e0c49bfa51411319b9f7b172fc11d901e41ec54887a0fe5748b1d2403d23ed5494b96639126c1d3fde11d85c8c717fe8b01319a9668b109e2d34a6ef5911aeb31c88b71c32a6723b0ad2a28b2d8c75087a546550b0971dde64d3cd69434914d5544a8828c6e7775cc802fd71e467e0327d692cba302f681fdf0c7425ee580c413d1a3904974e55e7ddb19de793541a7a4310e50990744b4655e72b4eb5a3a8c5fcc09a545198c6475dd26a43338753855ae4dbd845d3122b16063b9d4f1170b0fb1eddbe15bf6a0f935565ea46bbbd6c00491a9ea8288822dbfe8788aec3eb3e5e42140fe3cdf16328587b736242c2aa85828dc84352bea3c6d985ac48437bd72f12adc7fc08d03371992547b91a3061c9f9bc6c32a8555df262c14dba813ae8e2f9c732bf7360b1e94498f5a1248ca4a0c020e381d8c25f4924f91bf0c649207b1314bc0088d2f15f662a2594962596ea66c036677c451e77f051cf9c5f6b83ada58109f68b415af541dff5d6cba732a938ef4d425243a3571f475af0a456a7ea5afc7c78fa195780b270ee1f4d69fca7c93087e103595af8757afa5dd23ed17bd723c1edf8701a1b4bcb2102ab2aaef2df7cf485370d310651f6e897cd2d687375d29c7f101aed941cbbbc12ac7ad60c3147e41fffafb766e548f0e96bc911f38a6d1864277c170fae28e4b06fee1d1925923432bbe28e41f8cc19271f68196bf4724278f8492a6d5c0826e03d8dc1232c0efe5c7598b71be7d6c468ccb1077d7c8bd4630bfa4a108d58d5498e40584f6ab690e27ec8152c1c39bb70ccf7c5f2c33e48af63d536d9e7ba90db931783a9cccc05c22dbfd90f84f75d139aa22b1246a15534f1521ecb9031ff0686c39b728fcf6e0323cda56b641561a88c6f78cb1d880d102d26b20213d03af41c91ba6924a0ae17a92fdb375492fa0b514ce2fe88fb95d72e5b1b11bff99d1b0ea0832a0d3472b5880b3ddef0bc0891833adec1f7797f86fc549b22df2a0a59390a900e588cdd2405e5afea987db98554585c85fa2428cababff59c17713cfb100084192cee9f4ee3855163ce76fc59ebd4b23766b0ca7c2d59754ca42ebe3c997cc4cdcfc2ef455d3afd488474b4da2a6ba278c196616f995c4398710c291efccbe36bb724bff2d097095f440f79917229a6fce31dbd89e58696c4571dce1e535adf5e1b0942fb5d59a13f7fb4eb17647e83e587acc50d920db2951bb48e1495256e10a62a8d43d3cb7719c54c24f546ce4937e2ba7b1911f5684068c365398e41f7153cb1e2b9ac014bb7395a36efff14ee94373dd128d725dd6ae6af408a5da12ee540fd8d2264b24cc7fffdb2859ce5227ec3c3d5e0bae49b5f495a39e5d6b3baf7c967b21a55e3528fb0bda0e9f2a3cdc37904005a76b07d044ce439a345f5ab69a3db8c711d478288df2d4776d53ccfbf49a06d0d0332814d34053c98ee3464bbf46309b763114ddf1073100c34466cbf3414b4bc7b8ee73c44d76c46435c0354a71fba7d8ba8b0248f867cee79a4beacb5dee9c45577e5b423582fd261b6164de192e98aaabb47179a6fff8827221a70c77df46d01357bf27392d4dfe3b8e24abe9854d3109b533edab16f495eaae07562dfb4428cefbffd748f144329f7653931a9f65a3b024bf19d2fe04764d53730df662469a19c4bd966dc925b1ac52d9094ff7dd7268697468135000a8766d8292f9079f9bb5601193df637f8192812a9a97f604015ec15c89fee9f700509cd745da588a86c7c756bc84745c593bcb7c7d9d34bea98d505a57b31a90833e3d1e154c3b686d5d8a20375111bfc6964bdf2f815e160754b56c59fec8fa533cca9e21d4f688ed94cdab427f9e179fd308856ab7f7206d13d65cace5f8d65c8b95270559a7d33c76c81794ec38d75e2b3f9ebd1351e07da0540e3981d447558d6c21ce6b0c32bf61a3f554cae9edac7a92e2e25965037830c57f30a021953d91c8349b94181ca8c3bec9f33327caa08e437e542d4cd9742ea16801aae94e19442030e8c95bd4f23d88ae9a1f1cfe4a80b046f2e54885c54572a215f17bf8359db4edc830c48941153bdff79a6777a67a9ca0ee3c5d2e4497871f4797974c1d932fa3417b909ca5b29dfb315bf1590829f1cfad84b9e068213b8a6e9171c1c41757e262d371b7073d1b90fde5bdbafab76426f486581bf52fb2a53df2fdd0a6d5065afa6148606a3dd311b155dc0dcaf9f741a50d105053225f1c223ad0fd8af47d27db808cd32f733fcc8e2655523fd36a906c6e6a1d6eba56311424458b446bc1b77b866af76be210b9a417e87903a1ba2e431c176a82cc5a71a4ddf29350efa6dd8d1707d3884b31b9b52bc876b6599f40b077c43d815d2e02ba043505abe7ecd7dcf73818ceb77a09ea4e582616f4af11133a80429edc9a434f3cd2b41192edad842b433ee7936fa5c7680023f0727f4337c53912fdf6fc7e6d5c0dda2e0a8722d5b0565ddd8f9349815bf38e8615b5c7ae35622d7feb7907e6423c8aa7bdf57355c0353da377977e180b88ecb1faaeee2d7142f342263e636eb99c78af9cd0ef0314d9b57fe1176bf8b13c221b5a05c1f876194ac26c35b0ddd91a2130276ac402314367d99c2e300a33073c06dc18cdf5361908d58a9553268c6d0ba19ef6f6d0bfbf2b1e2f5d284c74695189d8a3236e927d9598a4be253d0492f98015851be3693b0c1b3c4a73a95ea57c20699240887d501db5d3525e787dd1a583c2a831a9b59886c873b8ea5dcec376ff37fdabfa21b74b3968008dfd9784fec35696779217b4f5507ea15852f751af31243dbf857d66cdbfb2e290b52f67312fe5d93bdba25b1b7dfb0f3488974a7ff0e437cea09d0baaba7bbd2506fcd182cf0dabe7c262a823fa1dcfe00bfaf7cb5f54283763a45134dfabe9927fecacd648ef767fdce12d570693ca6aa10c74c41761f64f31139f3aabbabefe6c7bd79a6a3334cb465f4203604c0288c49db25bd25c6c4c113e09fbd65c0f271f4a373294831c33f7b2ef392e4a4b91a3973d38473b9f3a485cdb04b7f75a833e2c0461c6f27e6d8f518d3a4366ea3bf37f43e4408f00c4c72ca8d0a9fdbf1ac7fc9fed47e8a3f3f33ebcbac25fc2e70bd39a85519181383597ccc3503e597a734c98e98a15be8bf4b37330f585ea138e5a2e4104ec1cb6f5a23df7ad83751c32432033f072e8ee3cdeaae4e7de98f9e58633bcdceab69ff60004cfdf51b54e9a33232e1df86ca9708811a69b8759e5b2daf57eaa8f1f74ae6aedfd9106c105a6cd715b66f561c0a0500a501a9f3d50a0b5540ec96d24fa5f6157f5465d413b204a224e2b752a49322a90aa340e4422e60a449cab5b6106135ad34ae309ada87ce9a99cab959f6c2502b2da99d8ef296884f4255fa88f38908e4294f799afbf3d664900c5230ebbec54328167495caa99942c13e834da5c488f2dcbbe4d2448eea2657a2f82a91a53d09b2b5445de8c8c8ede11f028e067620f2ad83be80d19f3b9a9f3b81bc8a405c233b2b17ce8ee5e0ef05847aeb36f219817d735faf6092d13569cbf069696bcbc50cb50cbef921f8fe76775f1034e73bf04431b696eae4943efd78ef6c19436c76ab389825e57b23f4529fb848233833afa418d85a92fc865e634357071bc415da56078f44bfe306d3b00574c04b2e94d6b801d5e3bc03686d1bb27dc2753112b2c22a43610a4dbe1e78c9f4f6f2b4ca3ccbddc2ce0e78fa34cac5935bf0867bf14f40648c805876e61fa841292ef2d2d53ecc00319a6df0bb6347dc865e39d9da574ad93f9cc910a9eb920986d5e6b331cb29b45ff32ddbc9e09b71eef73c8673307d6684a34ce85ff3a4208741b205d31011555b17b7c5effc210ad9309468a007d76983011b88c818eaeb3d3815a02d76f735433192f1bc99a6c7dbb57e107caf9e986248ebcb2e9c28279ea1e19a8f8027bd6f8728c9aed0b974322254e686526cd9ee0c6720de4eac01cd83e5705570c249856ebd7ec76cddd98cc096fb93db8ed86a5aa0736c36d978c09b915f7b9290cc255ea1a4b355888fb96e506cba34683c6a890c77d92fb01bba6b69f91efb3e4313111dafc3a189db063195bb650e0cf353dd975fb5c286f86b8f7d982ca5f74a78fa0fa3d693980be09298bd41c4ef38874ddb95e928494b9e345525b00e4760a1d6a4d54675e39b1d955e20a58f3ee65ffd1e249eb3558ba348a2be114f396c422c57314ce6df0ae9406dc6bd0bf5f1db49f012a03834b3314dec7839860867033643aa7dab3fe17ee025812ad2c05484abd0bdeb67043be2a57533d294aa03f24ec8afae512537343eaa16b07eabbbd2cf6755261ee473dc457ec36775102e1c8150248e4e51dcaa6abb7753920bd5247ccf6dcfed9dde98c9f37938d1c824fce116f39f0d67ab9c1fbc79e034e8bee6f79715433d485edc70e5c098ef7bcf2972171da06cd2f19cde8f824e0f2bbcd816f7eb87b7bdad659a900f36df708d3446d8e412b92142d8414f3a0508d106473e809a0831953e2064c655519a8f22fd0c517df7ac44d72a0e7b6fb697b188133fdea4d16e51c6da3109f7cec1a43fdf47957a35f4651454ae04da9e9d5a1668f46cbc58422c38fdf204f4e9c0df3b1f0ed2e14d0e008bed642353ede25a5c25684e7d593eee9d14b3a5a81429b30895ff5d1f7f4a124d2fc9bc1eda61e8e4bd73b57ef1a168cdfb1ce1d70955567a3d949bab203c379e3676932f96c04ddd0271a6afa0bd55988134de26bf5d6c725c09e04aaa03d393a82805a366e0d98e4b65bf45e05ce45f4dbdc1f8ec052102df08f5852630b706dcde9a3efebca3852e85cbd7fb6e6e00b4bb397004db1602b7f8c0dd365eb2d946d00eacf0ecedae83d26555a1bef8be88eee9de9f9811074151f0cc747f36d45ea7290d53c18fa8ce73f77f54226e5b1719a9bc911c9d7565693836edeaa6cdb7b2e2f9cc8c86b7c207cc14c261793df6c4c623355db04d5eac01c011677d26b764e9048bff8d76e2b6bdf792c57e044eea4307f5a3a62900df3f57ae88577644e2121134d61bbf3100fedf83371438b7854d06340ffc00383a0a4789a6a85062aaad3761dbb3c77e61c5926b0488f711a77735dce429b6e028373dd341fa2db5394867242331168665b4d7fc4ef96b12a571b8b25d44fb0de64b9820734e5647821a038428d67dbe95885526c3f2b8064e8baa5144b7fabbbf5a133c4b8d7a2f950a4fb69f9cdb37ac28cf0421894f0b771f80db988e25fb4ba9991664c93116bab82ba808693d583a2b697fd2b5eb673f954255da410df58231eb7c89b8257c5a68ca0306d088638b2faecbe3cacbbf77725e1685aa81d965f1ef663f1e474eceecbd52943c2e4e0456b52aa0c7758cd2fe67f3132176113a16dc9bd11d6dc03ee643fe8bd6677f2ec0ea754ab499e00ced482d78147ecb2f91d3154e03b57dfad4e4cdab98e134a609a7512a5a0e7c3c4adc9db444238e0fc3c3586b389d8d090ca46222a9533672eabe4fabcf61beaeb59c507f2941ced1ee4cd2afefee5aebeb354ec33cb85c9695426126f016929b471b9cc07dd6ff787fc2d682cc1e80657bd656acfb865dc91d6b032785cdd7a1d66d4d5463e142b6f028e8fb5bd6c621109e7022818b39197f85fd6ad4785efe48c4509e9a537f10d4fc9d23f275fb9e684c2f827868c9ff3baca8faa59903c829bbe1992541d15d538e64329e886ade0c5517cbab3b15fdb4e82506e27f449e268b488de32fd036fcf80f6c97505a5f33e4d3a004772a8970a3fe54049513cbc57131ffca1c82918a81bcb879b8f48d4300b11cd90069912ec9e59d10b6bebbc24ba1061c62a8762156df586a4aa758f13cab5ab59a3b1ef7d038c68920eb0a3c8a673c27b6fb80e5e8741b3b7fedff0c068a83e72373da07c8d73abbd9fa0084bdc92866917b546dbf7a6304f04b18d9bcebe2b4bcf5ac7ec526abb4a52a19094c8c231668d063c5558bdef0436ac418f42c5f41f2df996d19d48f8bec412de05a6a3b079e5b6ac1be0773814acc3d20166874ef64a6cf27f7fc72e0232031ddef1a6a4ac9897a86605550dd635c995626fe985aaabdd937bafe3e2a4082f0fc875ba7ea963a8e5987ad400423967bba1c0e369263ddf16fefc88901be069fc617ba6dca90608cd4a9d86476f8cbb41fc8197a9ee6fb331aae55959d107bef29b4f6f064651964999fb8dc904b8193dc7582fd47b0b0fb912f1c0c3838dd489c374ba5ea614cc80d4d196291c4a54989ae628dff5beb61612353ea0cdfd75962ab057bac887ce7f5df01861c769b88c7e1682f0ec6f7cea63598c3e6f41093d845db95377654fc56702a4110810917521ffada7432b7b16a64699e6a955a4273fe9220976f8b1ae9ea79678a3a74344a44c32454e7bbbae9a1fc440811693f66d63663c84bf847e0a2e8299fb0a6413194231a666a2efe5ae1c41db1cf12dbd8d58408cbeb1a9507b5b09ebf416f712b0040f8300dc5188e673c5ab1f13156718031f25cd5156beb8e77e95b48f42d1361da25a94cf1bb4a2a5c41f8da5c3f6a30c00e7d0323f7bc14583fe20815f468928fb69a480673b6c775b2d1af6a176abe5f6c679aae41ee1d5c89439a798823b65ef718515ceed5a7ec87eff54479a9afb48d0fcdb9a240e946719598512220d2afb20840e3680689cbbbf096e7d7505d1d854faacf024935a672278c5dfad333373015b11571b2a7329a0d2fa792d838ba3fcbe5303f84cc6d0454b89cf740bb0f83b79c98b38fa17dca42c5d57d8e86cbe16d46c4c0caad1f55ac4a399d9755067b642299b6b023e47ef74343b9d856545a51907f86034397dc1cdeb0856ea9fa753ba82c5f7e44e4423684f1b03ec59e5cdd96c03dbb1421e89bb0d1dd570309d92519e2b90fc83ece91ec6b13134cad1272f0fb1092a21e0066cc0a783e566167b52856fa6ef12aca963dde340e94f04980279f67a1eaec339d0656c09a3fe91a2b1885f1c09e831471ebe78f2af2efa1fe5821034ae172082de7cf5fd8599f7c575311d35248f2b0e6342cf7ac4bbcd19942a74ae9a9ea3ef5641f70ad1746406ad9bc24a1a3ed17dfda75ad54fb920ee9c92b792b76d42cec2c22fd1bb0f7acfa398d82b5f016f2943dfb44ca1d96b2a54ceb7595837379d62feac76dfa610a82ec947047176aa74fa8d58aef3d34e79768ba7b213a8c44c6e9739f05eb197148b2d2f3c5a1dbf0d4ddc4ae2bf0eeb93d2d4d0990c2c21ae34300a3139ccb5cf216b4031f5be4fc61b137a952fd516e45236dc791b692910a09a600fce9c14ce9e429ef1ae3ae737ebe9921d10522a4507d0794fde66f639189cca95923c51f97cfde4d57c718b6e0ee709227fef69a95a229ab54a4ba9d858115ac04dd0a594ee8fba7d29a23d8df53c131dbd6f7f47c6ec482cb2da38e98a8bb51a2878950877408f0892199ae4e94c4c8eeb614eeac1435b2947ba67c30ff52ff4c958eefd318814a17f53c8ae691d3fd91ea8196bd82d4af9fa216e32636d6535d5c68f579d3066654f2cc067873fea5d56f9676800892f210363fc790086a778fb721854a0abf9a2403ac6de964c2eee9011a44cc0d66ced8bb0634cb986a12b0d5d875db0f26f008555f7ff57f42a441250dc5d13dc5342ef36c288127d46b4a2cd85e5189877003589579aa787c46843e47666be2ca6e8aa84e065ec77f0f77e5cee75785e2358a5e1fd7d540ba1d36052964d7a5de9d1598cb71b238c6a6f2a4b6c72d8c5b0a4c2f17342747dcfb2bf7bc52256fa21741e1f8e7c2b749005ef240296ff9935f75e943c2e725e9f54636c3466450a49eadcc6f330558f2146426fe6786f4ac6fed1943d616474f7665e8ecc2612479eac464c8313066de5fb652beb42ee17c0d9eac4496b5a732c3df31d90e24ffa8eacb12b72dc1d393d0880959e0ce9db8141ae1490bb12af9bb2d12da5809a348714024d7beb73dbdeb4d7adcb68c59ada159fd1855ddfaa33e0b985d7bc3f509e64ee52b5057656295dc669939c45d89a07f03c0062e20e309a0388725c993f74cfbb8db38b85f13bae8b27a4da755398f228d79eba2ad5101d80c75eebee608dae268dac0c3a1c63e311fd82cddb78f06fd576314ffbee8ed598818894fffa54b56e7a7be5c20ac553d106609f4bc757acfe7b116f695fa4ac3ac93bd0de4bf87aa6aca5535e467298aa934c11143bbf39c464db663b97ad416b6501daa12fa8d9aaa31334851f36f654356467cf4f42fcf0c4cb239c2acf7c7938c0760a6a8f953e75471881c59293285241f7b73e4b3dd5" ++ } ++ } ++ } ++} +diff --git a/consensus/common/src/test/resources/aere/registry-v3/n14-ecdsa-wrong-key.json b/consensus/common/src/test/resources/aere/registry-v3/n14-ecdsa-wrong-key.json +new file mode 100644 +index 0000000000..1c69cd6382 +--- /dev/null ++++ b/consensus/common/src/test/resources/aere/registry-v3/n14-ecdsa-wrong-key.json +@@ -0,0 +1,62 @@ ++{ ++ "description" : "row 1 claim signed by another validator's key", ++ "chainId" : 28001, ++ "requiredSchemes" : [ "falcon-512", "slh-dsa-sha2-128s" ], ++ "ecdsaRequired" : true, ++ "previous" : null, ++ "expect" : "AERE-PQC-REG3-14", ++ "manifest" : { ++ "formatVersion" : 3, ++ "chainId" : 28001, ++ "bindHeight" : 1000, ++ "count" : 3, ++ "0" : { ++ "id" : "0xaaddb4dde09de5718a906d83be7db3d58e0ae32a", ++ "keys" : { ++ "falcon-512" : "0x09501c96d2f5cf0b28fa00c726e5359c5d36a1fa069971f854b7d914fb2f1295e68b2c6fa91d82f7d287f55ad493c87320bf7ca2a5d5e79d7212e8a540c166b588dc03f73b83be060525b367d9f40f5e77e7798c60b6499767586770722820b3b9e6013cad3eab5fe5de96089a29f34919a2e9ebcb3fa03a3e714593b7a3356d11ffb3441ab40ad94474da662a71aa2419dcd50668cd5d8a9017662cb60998b34ab5b7929c58a94d5e133ebbdadb2b0279543067f76bcc4cb6d7e0a5edb7625467e3ddc92a01206e1b8dce69be31928687d8af4d26633a07e73c2830d5299b878977691cf65700b65b6ea2463e51b6136888c544545e59fe8cf190a7944e215a785b682623c95a79eda28e25e0e1b91b49ac89deaec3b14a3c431d9046a663170111ee541d81b43aa91f29dc147c6fc97739b3a63fad1ca84843d0a65b8d9396f28e9b11f9a41453ab18a2309ae8db03253a09fac8f0cd634c76a5e938a44719660944a95dff056cee43ea99592c3899c2880d7181ee3dd5c04baeb60e1369a69430a66031e3cb10e392622f5246a71761760cf417dcb40ad65f60704fb74ad26f26c3af7513a42f806895e0298c25c049187aa536e0eba21998912e621846c2ca0e323744ba930a29850fdb385c8241382296ba28dd4df05ddb1e61fe525949034b59929a784406de240f8086b4074825f419d5472a28a0b157500be37e9f64897db2b645d3807c48dc143266c99e7cc1638ae278772493a2a4ecf74e526a514bc9119d7129c5a0d115a450ccf4dce05b76d4b6149fdab028006df7ec2209923117abf7578a082128cad42aa66b69eb63acee4456bebeb537ca57bb3d3487f95e4f06c5cb29f292d3b6284e5a162cb83151cd9ae56aebbfda150b7edd5065302ccab70892733a1e096ba0da5f51b42764ad23060eb197d5460425fd9c7a26e7dc3cfd40eac3643539feea72c9ed41569111a7976d2c345ac2183fa2271b424526709fd9aae558a23a5cca29f4e2f31629746a71d904612e95ad9977bbe74fa32e90fac62625838cac49f50e5aed4e8879e2ce2e5651c4f4ba0c96583af9e1612b5ff1a6fac5027c0a308815e592308170b915b4a2de1e8d48e9a5730680ea9db8f3326c430241153b3b218d5347d5c843570cf80ee813871ae10f6b8ce4ab7e4c5197045e85b1cb4977f44c33eb85894b6555b4bd288a50c1b656936841048983c00a01631f10a84522cd613fed0d4beaa4aa4b3e9f30c324108d909e59a80150", ++ "slh-dsa-sha2-128s" : "0x47a0b70170dda85f843607f6c6fcbe6e6acc7c22980c108996a3fe72dc9f61a6" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39c8813cd3b34be58eaab900555a67486034b1923e0b00e435661230cab85f07690a5958a5f5e9c84f033a3dc2039a5296443093fb7fe8d41895fa73be3fb34cefc6cc36750d534e6a3c47307294694729d6cdedb633e8efe8979a9aee486eaa66136e342c578761241192610185feb2d3c196bea0e79222437b6a8e08cb09778d053b29552df96507b1cdaede8e9aa7abc18902f29937f30e7cee6868f349f7ae33738237dcaf86b8e8e01238f3d8ea6fd4090a8161db65dabeb5ded5499e8cc8a5b32607abc291b36a4b34b327d30cdef18c1825232e69a2b09d539ed84dd2a4756efa64f864c563943b3db825824f294c1bbfa2157347b0fb0e7f8a56ec253b39ca9b6cb1ef7d3d7c93a6cb220a7dc50c365905ea5a71575c3aeab25b33523e4fefbaf66137f45c3d96db719a12d2e2d42fbd6cdda58c5a1b958b28c2a8f2cca297871a147dda92a7f008a359027a9288e42ebcd6ea9542f10b66dbbce6e7bb914206122f866d9adc1c89cbf8bbad9bc9517c2ea9018b61d4d2df9abff1dd9f3a0a6faa72a449af9c97e8c4090f3bbd9824298e61599c13c7eb89677c0e845ca2907c728d9296c24e96b6a348dbea7cac62671c9a78a531463614ce321e28ca2f093094ba5f69881e6cd766874622ca769ea556ae757cb7f9546d99f5c90c25e7b8e14f3b7f270861398800b0604ec2a3374659277a23cf6131c63148a41b05b3c06e2a98a268f1b9f0df7969addef17179ca2261d3c229ae3db0c490834564c45f7b8ff6d3bf70784779d75915fb2e2d5bc147bc941b9e249af188f63f39b028547cf080b7674b228e20a600e3b167610f814daf105226f3c1ce5e07834fd33dfe46315546e926fd5be83fd4d47ccd5bb8ae736ac745daabb59c87b9edf9a45c9a1d1617ee84e588f27d12235c59ffd9", ++ "slh-dsa-sha2-128s" : "0x0e8f9bdc22cad3613ed07fba30ed04219b9528f9b657119e2f0886dc71cda4afa7d462fe8bb108feb58d998b370b2f7e162390713d1a17eb7de781a604041cbed13d00effd3b24f2ff87cac74f61e7b7f7aa6a259dc283485179ab4bb966793be018c4bbf4475bf7a69e600a37246908f662813813d4b0f4f83757f4064c5c0713870a0b98b5bb99025dace06100497fda8c73d7385d123afd4953961066e7c8544de3fb620ef5e23174327c2b64089b3fe6df3eb86e83b12634a0c9cc0d7844c894ba6d83afed6becb6f5abcfff397c5cea8064e5e153ea4253abe599dec1614b449329ebb25861b69a9b22228d1a03ba51532ea64ebe7603474a15a2806d3dafa29d57d27c5fa894da673b85b4674ce835fcfbd391d328ef83504101432bbb0c83d7be462b265911aad862118af6f4cea4df0f1dd38969c69428fe438d59d22736fbc7dd5faf6758905b26ec4c99d71e4b8fcc562a694ead91569c9a916df5ad693cb2ad0b7ae4c4f3c5b7322f56612c5449e0339dbd367460c76ab89b6f44942cd33f35eaf33c2ddc0c6af793556d5202fd1fb0f9fa1b7ed45c6ca68d904e476477b71a0bc6ebe248c9b4585da0c7bb186600691269bb4c836667a6d73a455b97127d898b7fae17e1acc6dcc3bac3ecb14da131d5f8adaa64b054e2f569d9bdb164792038e107848882de9bbeff295905c2af68d4c6dcc8cf718c2de872ab6b3d18e00d527166f8ced642281302e2acf4cf4489072a2dc3d55ff8716619cde494be1763dce925438b33ff1b91b35eb511645832720ed92552d4880ae53ff6516cfaeb1d48c923648e502e4038676f7c82e532ea713c6b9348c80ce3c5735f437491d3a8b1765294868c14123af2e9ff61e394216e630c71ff976072d2a1c50cfd8ee1ce27aba5bcf9aaed4a51521bad5e5d5e66abc7a95b215fc8004364aa4df2b8b97b14e3950f521b6327a55fdff9139fb0bd35237b022e3aa128d36c8a60f4621d25d28c59a97418c7dbfc15d900ba626d283632732631ec4a948f66dd9db3bee8c2cf60dfdacbb5ad4c0b2b31f8428868cca035e79c95bcacaba40a9351b2b44cb29753b6b9da0a751bd5af84c9094d5fe91e97501d4f075392290e8516ed5e41b41b00e09793353707fe5c1d942395074637f3ee0a0f105876d6f28a74f9558c5f360e98f047a99af35ccedef8d5cd299365e81e7e91f28a01eb265219e21aa7f7ce56b62f9d2a61560f9fa39f2765f5b50920658100a638aad03482a687905cd27dca02f1deffd1bc49a1be1ea7ff1a505da74fd932937d8f6a8bd75ef456d5f7b71ca5357bc66db6cf14368c4faddf4996363251e6a6113ec64d642c319dd85830d8b4c7ee1437ebfefe01f27709ba0c412c266530f5b6bbb005994774e8935f1d91069f9e7a8cd2bb7ad6527768473affe24709c10294eb588aafca85b379bedf0b142b109e1b186e635b0625c4e59576266acb5f71040c44035fc9480b13932bc657cf332b12da1cd7d5c3977f51d5fa742974cd256e8e3662dc698e0516d615d0a05ea9caf12338d0dcb6151e07f184c9cbd5e59bc40b12ed6372e2d6bd42aa0eb6c3c888f264a8c0d3332631d4919c921cdada6bffbd01ca5445de0779f9723577ebd7e33ab0e5f577843aaa6cb8cb5f0508c33b63913a44d02b76bbb1eabae325581738fbddb5d4fdef8dcb8597bd29c6ecc631839118c44f66ef8dedeca65e58941c30e0423c40bf064b8d19d28dab3787238781d492720236a7ae0695ccc867fbb1cf207ebecc64f84daea66b6745515b9ac9b725061bb9958ed79ad6161318a262528004401633d47a023c645683e36413b8653fa4864fe98c501197c10226b1732337842a1322bb788a00a0de86758139c2d9ea3c5b26bf5d7a4a92cab4cb686c580e3e6cca488136f0da9279073b3dbef9519168ba02588fa29cc60d02273805b425b919a7e2e89c9086609982163e09d5f6eb9c66267ac7be363aadd4617d398d4bdeca37a838d650b0919faf13b78642a058b1bb96b2ed1482cef9bc6e8b2e061e6815936e15a9c754353aaa786ab141e95e5f6c464a41b8bf29e28e764abd638abcfb342b54d08c15ba7e24e6fcb69b844e16cdb5cf4f50db60ff0699f969d8e68511fcc9e16a58e100f80671af6b04ff3edda3a4f05f9183c0c3bb7c1061fee2d3f04e33fe75f1354e6de54f582da914da0138e8565ff45ef52f638cbc33a24bae863fe91e58d7c5da34273438f15e10d4f59db16e505620d97d3fa4862a4097a659925d0e5f4e073103ed29a600b051b83b1f3a21381f4b871c18d262d7e43842c34ed80661438c064aa2fd858a8f3bcb035b5e942baace7b50e4de5a73d5c51fc0843cdc163958a62d333078f4c7d883bd7055a602e04c853f9215c9d7f798403c007fcee124cf6099322629c449ad4ef84b7356110798dd87aa4d98ebb47abc6cc8748dd381d588b77db7f4e7550f6ee1ef4360dac6d6c7037a65297d4a0ea7999a5632b90ad48fba0a916846a216941fbd13d62ab36e1066e24990c19592944078435c52d7717b3556595b645cd2359ad151dbb67e92b14168cac12fb2cc5422582a50bf6e99f116751171c9b78744ef719282f1b84bf95b4092514f4c68fb82a1526e0942ca50e186632cd9b0b8b8d91e84f85e35f30f815601798fcae676da6a2d38eab62f22445099694804a36a34142150fb795afb445e78c241f0b645209037a8871cb5487c975975ac997a540b709e3df6bf208d9d8017f9688b152c9ee2b934f65393de8403244b7437108e6d8c973aa723285555d9eb92509b1747977105cbac7fc33e658fd51cd374d21fc2bf229928948292c1698db7934d0f9be44b137514d0a5fbb659bba83861931e03698a61cd20a449d0358a5fce7f288e18bb3eb62b7ba0ae75feeec634fc90fc45ce45239c5e3179309f0c202cfc53d9f42a617f7aaae586e7161a0723ccebb7e8586cd40e1fa12d3ee89b400dba8073b0080ffaab1182e8243afd93318df15bbf3ce179f21804fbb8882e855ef9e0739ce1536d8ebfe9856aefa9874b4e102e705a40ca4c3ab0ab7df63ba525189b518796590035ca780d348de49f0ba8f28456ca6f3e3cff7e761d961ad98b8cf01e855797c88fe2f811e41e787f3e4becb0ef42ca3b9979356020b447294ef295543e0ef512a247e4d356bfe3deacca8ddc5255e6ad047121eaeafe61d71e7f31395cf78890add4f8c688e4eb065479a63ccb3d0c09028bf60c700fe9d19195c26fcbd4130e6feceb52e192a2aa2343c05b43b276f51a7c55dff7233ea512942291900d93315438a96af08e25ea5b9ce656c54e71ed60d1eeb1665ddaa9e42378c930e21d93484b9a4099b7ddd71d983b4c42c6b1f62907ce84b24321422b08b847f1ea97befaa4ec30a794ad7f340210c800cf185ee2c6c72e844cc5671964e1e1ec58953500f149f0f0f25c34d5592de421c2e31535040020237b907e86d753094dd4532e1ab9d821e7583d4a21e1041fa7ad711f29ee3721a2aec6b0c46866a2de71ee850d8122f722898e533848e2bb851ed24cff9ca83badcfad88a171b4be064007aef4d759d93ae9b67b446f3c6fe504f5b4fe851b8312fec86b46ec3cfcb36e0f682e65e117702b888ab8566c9cc716a3a86106d2323c0f7f20fbc1fcd110bed4492a750befbfcbbe16820077dee281bcdf14509b93137a3998b2fdabc2a375b38857bed12bb8a9c67bcae7934d02d6ff89620fa8946c8aa524fde99c12fec0e25bd79788e2c15fc31fa3f27502cb952b9f9482580cf18ecabd92c55113ec4c4470c4dc06d8ca27a10474594eff708209e8f376b6f17915c2966dbeb0e35ac2f02419692c0d232e133b3907059d3a56ff169e7e61915c8b1067e183337b40bc1136241e862eb3ab3f2c6a72b18511c4107ed063d1e2303d0fe6842fb01c204d1bffad7e90bb44a365e62945a7f631811c9c37ffa5ac39c16b4835798686da5baa8e1eb6aa76b42f6b86863c30669486a175d6b3bc5bc47c5eb05b240bd921007fa39506c6605bfbefc9c8c493973bf3f0767817fd8ce126a301c5b8fba79628a9b3a03cad0c491a5f487dc5e89269e5d3bcdc2998a136a012486c5bce2e6c6dc595aeee2ebd5a36dd06919396184aafb2301d1889b668c4d701c7ca01b95f9508f47d4c411cc0397c244ed4e3e3ad7f97d86b6f8834b13b1b2df0625e6b4eae9e439815e65baf2da767d3b1700fc461fad6297fe4e8ed02bfb65b750c2d2801b7308aba9657df3c3ed7d548687f55e85c22343d1db343bc2dbe222fb76fbb3cf490cee7a99ab3a337c626a148fb303b2f8651651588dd4859fd65c95820ee2af85adf4e8fc2c03828ea7427e7c6b0d4a1b0ccd424df6d1450ee436c01351d8b6bffd4ba072756315968845ab7976813d93d0f0f2be1c00faab3ccafa71cd26c5837e87292870cf768c7837e18ddc3c513820c660870b339fc42c5211d33d892ef22b475cea3be20f5e47206efbfdbeac208e26e97c400edfd41f063aaa6b85a0cf86e23fb11274b405f4f796eb10cb97e70783909ad492ad9207ae7b3d204e59d69c886f91bc82a107d0be3ae85797a7cba747b8e2640ec49384f53c785a84cf8de37dd4048dd4b879c58768bd131ad7226506113c446fbf13d769794f1535d58e9c52e23c1bd55e13c647d304e297d968c759a378f1d594897a026e3271aa6b4daabe174d6a35665b35193379f0ee465df7827299c18e1012ac69913a0a5bb5142e99b051763de3e98d5af8b62133e25b32f4f12b787bef7e21dec42de8e4d99a0adc8f365d8cd3e6a5ff3064ca18965ffdc6b383f7ad08186d735a099bb0ee14506388c1a37f7a766d286d748d404457226b952ca6cb3f317b0f4399006b5b8c6eb89f6b8cfa023cec4d2dedde3e31b9a633c0888989b44ab182a5aba30ba78640f477ef1202f6496fafc2a18e283b2e4e8bc60415a1c9a7fd68f15cc1ea0299e3b26f5755ad9f13481a0563a524c6735942f5069dc1d6a070b3c3698e9c503f67a11efe59413e937062668d3439a5dbef197d24ebdc79944b17c549b0648af9b1349cad83c2a0a9e55fd893cffe2aff4626662ebc5014e70baaf7cdbbdfd3f92fcc5eed863fa8afd87f88873f726a0a2eafe41fa81edd5833f5520cf93b0fbf0660e48eb0258d313bafb87dc9b0d0d9349f22fa2d960238f67457ad644bdc60fb5eafd1c88dd2a74db4da0f723a03df08af6c64883f275395020341d9dd3c7fa049ab2bebb4d8af2bb8dc1340d1a80088c4b2c26bfe7314926ee64bf239306c05dc2ec6e6c5e0ed4f6dbe51f5ee09533f558d29ca6fd27092c20dd892c89c83223752006b23e5abecfdc733aaa59c8549e89e5ab0eae1b44189f58cf9cc18de0c2a2f46a9235fbe42c641a890039cf6aad820f1f844edc24e69bc3bd0c22cfad3804d876edf5491e88cf891c347ed5f24464f2df439bb30742e1f9a4a7eabd9346c6a5f93af22e67becc494cadac82cf9cb693acf44560672cb9227eea2575f90b0e28431684ae12ff2e86fded0be3a099f9ddd32a7285531de8963c9a03355f1d9cef88d7ed9b842d0066ccacdb698d42ff9f8a4f000b9764a9aab1f3146f9f95e6636fdfc9ef91c4d060a54ed7f32167e7ac50590dae3a2904d5d2eeaeff2930bd4cad7166fc17edd2c30e6738157eeb0b441491e5dfdc17a7fbb2bdc6426b2cfb26cf2a7e20013f1b3e33a6d6821928443cc7893f7e4a5268a8b94a6ca6097d25be17b214ea4301e9a723194983bbce286f4363a53afd9e94dda9c761481d9d20c7687a2ff85d42436b9d557d5dc6c5e24ea21d5231487df9fc7986100664edbbc51ad4921c5ec9fbb407ab33ef5c3b3bc81f113e68f38d73f0db0261b656fc344d2d23b93446845d69cee1704834d98737848d405f52f5a7bda3dbdfcd3af3881484579d2d2f3ef976cb35c9cbb76252f2e00019363273489b39943d212ccecc647413c56de69e0087532223cf9b28ce3f77fed30bc3ae6a0842b546e0e1a8b6f6ee1ca0ef1b78c3ed829af817099426f94a447f67229cbca3c07b7a8ce547c5eebcf168248e0a0b9fbeb398e5ed2d0dcacb441f95f9e30c108c725507e459d34c1ec01b67065e5e202d685502d6ff015d46c20bbeef1db38c29df7df585b95d79f5687474e71fff162c0ec0c96c94c507f8a0292a8c32168dacd2fff78b5c7dc145e10fee1b25c478172af8f3ea132fdcad75dc22856deb2576a5ff3e8911842c811d1d57ec203c77b82da3658cbfee18d140ac341d38a30f1af298cf60f2a88d0dfbd3e079ae64a07abb4947cc042925fd5c64bb5d4467589f8c495b0097073c081517bc4504dcd7442bad7e7acafc894fcf34f535979364cf5e908a84e0e141ae47e2ae4dc95462b4f345b12b0629502c7bd65579ec66b2d0a951302ba6da1d1176db6aa0c0ea1fa88195dd2248990fa4aba88490b1da4ea405649203f6ff6f734693f40deabdad59ac62e3296cdcbd74061474dd7b63c46bcfe6ea2b0ddb0f7e77fcff3599892c82425b05ae7aa1a2ac1dfddfc67e11921ff4f2c8f6297881dd5e38ccc4076cac8015c59cdd6023ffbd62b887b33ef8d917446a8941d9563acb66a6226fa4d3f2cc21604c080b3f83e73c093d8f2f7067c392671020c7a7eb6fd0d97af0d63032a3116c408b708d4b2f711c1134b88a91aa359608550f0049af2bb97688afc4352a45c4f6d30d4634e70e82515ff1d5f77851ee857e42b486d5e1f3e0406227dded6c5f47eda30d94f44d978322891dc729eb6ae95d29d22c8a5d649193d5d2aaba782fa16ae488f645a7ed90a566e182f97bc62049724f4cb5fc71f6bc7be57f07a7afb9933f6706cc83483cd7dc4182768cd35bc42f1e9b54d5454d3a17e734475ff58fc66d75419d3d122eff05f7b0548188682f1318ec32c5bbea87c8624cc1e548bf18a6b102e7a43e6bafb579e4e84275fe07d8c63ace449a44cace5d9305ff756cbf40e5a6a20334d5b4a74ab0483e31593f2277e90341fa8036496c2bc6d2b7b10b0b354c86d666d65cacc593d1d7349e71b0360d823453011ee16b6280f5c048111b99b185af99e9d901d4eaffd8a96b1ff394b66208ddc1e7e53420fa965bfc4e630d73ad97b9c5c6ea884c619bc24ac3f46234e7d8d35a12b0cad7220d7a0945cdc64fee9d8852bff872c43f359e7aadf8fa3de3551fb716704af68a18f79d03b3c7d90cf21eb4bbdcbb4004f8ba15ff0bbd2d0918ee78e9bde980e4f3cc13558e6fdb40ca71ad2c10f5e5587784bacc6b925f72da12528216895e0ca4b350d078fdf534fe01bc86b45e0c8e2b35799d268a457f8768ed782dfb56abecfd2b9db00cd10e189c6164f82f5ccab423277e3465ec72d76b696cafc1cfa9a7fe47d142fd6672d9c5b77751b40801af07fc53b1c9da0fe6981ea75e066572f7272baef8fc54bfa7cd71cd0fbc5d6cd717e9aa07808496ad2b4b4005a320c9312c73385afd61193581dbae99df6c25f1b9da17093ccfb108b0a26c5ae4963183533ce2f0ade01bf5e818af613416433578522b1b1e5aa7c791570c8c8b26ded266399116f5789a8233fee128e54ca8ce63fd56c1a146c3006316d200e05715993d1d97907ca83d7fd42ef7e7222eebd74f9c86b6cefc82e614a53976272c8801bdcfd882e34d86b39142ac05088a4c47010a71107bc72a380bb3e5122981d1795256beec20a0fe568002d79a4b1577903fe8682f268eeeed0a97861337ffb6861bf378eba1e0957111c7f9fcfeb55a95238005b40e13ce40efe846ddb86d14c9ad2c46cca74baa364ed08da3a3079fae3a36346ac949e2174c661b8801a051423e95dcab6a0f9c965e8744bdd0e629bd3c1a1241e99951ddde184eb8f354209f24c04fcf10fa8f4e43cb55c922c28be041213ddcfad65c86e1ab9b615f91d5fb11e4cdec5b7e25f8e9811c82c2ed457d012e4967b555f228baf4f1648854c624e0525e36e5f4d1961bfbbc3621d79bd6bea72924d8e0146d0965c239a768b417ea4c33237a60fff2760a9dbfb1113a37b01b598f3e06987d99518bd9f1ec96cd7050863898c8664f793ef29114bbeeb9afab8ed09358d1227d7de2aaac0ab2391cb2013028ca5f4d1de6425ec5feb17d95df358572fa27fcd51d14c363a36bc37c7497a0f964a6c004561f68349f828d30d4633e87bdce6b6d92384c9c1c540c8295ea621e9a8006a8d7c163b988853071e06c78f1b9a0246db052e8484a65cbdced3a587e45d9e2b49a5501590cf768d08b6a043971110e9c9dc96abe855abbb7aee2c38bbb77e5c68d61f01f2376b6122450117240532c7c840e3739395dd6c9e80a432423fc5e3a6dce9dcd58eb418e16d7aa507b4d67dd6fe2af4042a5c7398ba4f87c650926084efbfdc9430a4bc2be544880ecdf7361aea06a25e4f592104b0d74312f2729a4db5876b675bc0fa68f6e41e014b7caaf6f49b8ef704b6243df410dce94ad2c51d328fb90b9cf2f5df645015f489a262f57a5aceba40a56d343403b660928cd7a9d165f4a5bc289c0d28f33dac85c9c2a5c79b5ddd22c744a0388a5daf4bab84d7c77685053c912c9a24b5a0664c6253febbcf552c4ff38bbaf2f7e0c9f06e69a91cff9138c2745b99367e00ff6b6a920b1812e17ba44175c033df0e58d1b5c0b7d146f861b62e812ecbe99d638219e0dba4dd88089005977bcc90634c4dfa95f87370d905d32f613358fba2efcface0b9a414ce33b09e271a647b911843933c5d1008fb0717ab59739eb8eb844a4b34bb1a8f635c5895afa285ddc43720e78dc81eee7db822896bd9bd6ae3e7fe2988ba560d58f02592870647b94aad1dbb0d0cb60e28135ceb72e0a6f4b7893a56eae83f9d9a4c549d53d17c6a00f5d6c266d23e7a1d13e22a5fede3a7082dffb34296f8fe9f3bfe525ee1da81efde3aef9b6de8457a10fd4340809e1dafbfb9e2719c327a3c3a4c51d4d5600e8a01ebd5c537a4cd7c4519e963de06de6c83a9b968b01f79e08b5415c5a9d6a92a633d6ae969b80cbb2cf4d6d1ab2c3b94e7c12df27ea89bff4014d92add41a3e961006a194ae3ea4a6b38c2827f6185ae636f6846b1c8401289696fb10c765fa93e58d068bdcd8c9dc95df572f096d65f5de42bae639d41ce7e1ee0f48ba4faf856c0cdd728956d7e4babd6d9d6389ff41d76c5fbd6380f351b05a37022dbce0a6a47ab7168c82c77a2810c80b1882f825ebf86cb7f6d0f54025fddc9b9120802514c797d1d3968631dae95297a857890ff1dee408909223d012925dc08b7d1119fefca7466392a019d4121ea76c8b4c3bd103a820557e4b2283e262af32f1edbffaa253c47d5873bfd0219b8be86c7e64ada2d87ab6b7f428a7d8fb3ae09b05aee71054355eb83ad76c05d836a9f1a65511b1553927ef1b19ab1576d7185af61be6104de1df218918179c6321846085a83bd1217aa63d0b03996ac1fb4018a8ab54fcf635f7d5a8ade95894f0d407e5d4691920f21094c6f632f1661402a0b3351f168f16a13d3a31ad48e89230cffad272926487f36c7a2584c9387623df6227be8c96088db4a21c93b1c88ee756e960f60e614b30bb6ff757c20f3674a7ae7f6ff6a9115a0a6d444513ccc0be5dcd557430e0ee8db3ed5b3e8c405110500b9bf7f6eb7748de4988a1db94bcb16fe33479f64762c53a1e2965363452063d7bc14386ca7b4d46ebcf08489c64ab413ec0f1ddee8719f5fe978d38438ca3059961ecc8480908cfaf139d88db2facb5e7a88a43a67dcb0f97a17f9bd5b09b8369803ccc7ab6d41238e59e43762965814c10c36fa4b6e61bf2e83c0243f20ee8aab62dfa9827aec06f99c5c565c1bc75291292d3113503a202851c26d1a8bde54bb30f0301e555374b71e278925a2afb29b0209c08ecb89601bf612ce811a493abe2bff78e7fd02ee13c5db6b3edce7c87559410b9be3be95465468e33af224d6508a44728cdffde4cb14fb96a0d2ab9c7f597541f9963775c32ac613af9beab89e0ff7a5e35613751061b0511532b10b3947802901505c8e33bae67ce0e28da760af7e80b730811bdf17abfce39d35def51d73a084119449038c2b0f1c86d844123c6e71f28b7038053e279dd11c088dfa11c547a4ce13b19453e88e5b74962101412490cfb68e21d8952db509cd3a814387b67339fd04ddd2163177589146409934f0eceb10db2d90a9e3f6691eb75e84d5e66bc3228baeadcba200f3d11e0cae090ffbb800f5da7032c35ab572de55beea37258bee6f191addf01739a26efaa612991cb2a3c6d1bbb03de0ee1fcf9b7f6c51e452b21c0819a9aad93162eb2dcc189bf355ecd2c3e504713dab24bfe3ed86a4194611029f7f6216cd469fe1f7d35d56b6c8c2045011e238f9cbc0a19b8914d74329e2472f15d0b7d60511814ad2736d6be168aac01868c2a675549c849fe05e05a76f077130b46896735db5490277b76bba43545de6b8ecb53fd20398eb94dd884951fb48d5690ce4bcd0b836615cd9340ff0cdee1122743accfef343811a71c7d14d1369fa49ce47784a6ff8adc26c151edd4969dba513ade6a9b1f009e57c3d6aa845ddee275169ce58e1f04b564ffb6d0eec75f7172e5e8fb814cd702c9fbea8a783bff637db8667d4b6b48a264135bf60acf335936105abacff0351ba9aeac88e9522cf7ed80069822a7db1a5d8221d9492e02ca893e1f15965fb82a80ee2ec491027bbc8906e71cf931fc21e1c0865ee06a79c023929625b4d232c7b3e2e4a4e5dde28fab675391befe583c95dadae71dbaa43e09d8d65ba36d148aa85d1a2a35dc51719ac0311ea72c1237c78a8b1542c59de3b743087245e54d3111c585b5e5e7642f625c8d44c6d9cff50d8d071f6fa573df937d9e7457302d8b293d8fd94ebd3023c55f8b260c3454e93f58f16d0f451189bf41c9f9b91d3c3918adbf98e4ca5aa0eb6314041521ef880ce18f0ce296721a06b329bb5fbb3024e424b46400e03caf0105877465285fcb41a93844fb90b7fc1924883ace6ca8a37c9905068c633761163affae39d0ba55b67fdc6bcf0908ee3a42af286c" ++ }, ++ "transport" : { ++ "secp256k1Address" : "0xe23c5bba38d809fcb2d3384f210e9a6405beb498" ++ }, ++ "ecdsa" : { ++ "addr" : "0x48fcd978ac4d42ff52dd81fcd17e93190f35e5e0", ++ "claim" : "0x2dee91bd2cbfa906aefa3a8ae6e2de773f55dbd28e77bc329d28215183068585601ab9a7f9ff0c48095407474d502a3af3f059a666e5ed1e27468466d69914e801" ++ } ++ }, ++ "1" : { ++ "id" : "0x690a7fd66157e5b777256ea5214f634f61b3a72d", ++ "keys" : { ++ "falcon-512" : "0x09a6d094d9a3a0865864e9a16b477236f1ca26c888fd0c918db331c87a478519c41085cdac7e6cd0d89190a41a3bd6f4d6300995d591f5e22a7b7147caab1f9c7a85a4ba74d47c7b227326ac17535de039a7e604225d3daac7f75b9544654b73f79f5825825ad6e6c45d13e6d385a644633e1c8806d3a0a551c98f032583c95fb13997e52a6b02192d26b5a47fb22ee52999ec92b75c70774a4ae0481a79113ac72346263e53d5dcde708668d317dd00552d5a40ad47e59a501b10a50bdc52c5c2b2c920fa0e3dc9b8eca54b10aa5ab1168c88287dcf80ecd880a8fdec85b6d63a15b9f453845421a5d9b898e6149b60454828eb9dad6442ec62ad27ed72215014f3d17539085ea3f668b0a9183ab96e9db996801c72a0920b02a249911924f181e8dda515d114beb83b075ce7e7a0902a6971e31420ee4921f5cfc123f29dc7775017aefe99a7e326119cb925f6f603ac3bb137313609498d5a2000c426cb332c82500dcfd80d70a5e2d156844a683b313266af6d60216bd9e9998bda53c0028f387ebd21a5fca6c0607d54b1e95724746d15f25f16e45845926a83c7598646a0a0d3a8f8307c1a401b823f1656ca41e5499684150a954318da076af9131fcc93361d9bf0ae035f617e02cb5e1224a982b3591b24013ff80dbb61160d2ba4ce85a4260c8a3a3218e0ec869796b1b04a82079cfc0ac26da03b04a11950b2a3331ecd0026ea9737bd20e6ea3045b56e3c71278d2a8c72c8014b769da9319e19dbe762b1943e5a4be15aa84d0da831eddbb10bd05f35d55b6211d02a61c5d9247e69cab6c112acb568ea51f345a5bf16f84782e04220e217722da71d634e1a68b796376c8a49a965c592b87d06702fe42dac12da108d24ee42a109e8e4cfd3bed6ada5e3de50301696bab0564292864f1b9f47d5a53cc0c5f9cc3d57051065fd57064d08764892ef4c4a92b475184a4cb4ce1f3a0e6da0402414db5a9db34632b9717586e799b06e870b81a330da7be6a45ddfb000fd337a24a29e164449f96be015818c53aaaf09b9a565d7d9d735b9493885e7cb49a5f1985977cd6824fd62f51d2a1e60289dbaeaea148a44dd8876cb58b8ca2f29f6455f354e4e76aa13290f2979b78b22afa0e65c696c21497e94bf0141ac6298aac70b5ea843848a2264fc057abd3593cb17465e06d41731b7153b71f8f0f7a06d362fbd09845f0815794050460b41ad003c9396a86eaab240555ac8c75f85c0ab972c1a0b94b67b1aee2fa3", ++ "slh-dsa-sha2-128s" : "0x2b2fea4a0edd5dcc2f653eb2dd000aecd87deffbce8818aae72d7862b506bac7" ++ }, ++ "pop" : { ++ "falcon-512" : "0x3968f2999d69a9c28ae792a90a47363e689bd4b349e75c5f837181fc7b16d3d04489bbc32252d750d750417770630c5b65b88cef918ad23e33892a58458e9e63ea591596d3b898f65e1a5be3d36650c3d9834e1ec725426960d337b8f25878525ee3c3798b5afc9add5bec82c8e139c59738aba9ed5f42d11c886472e81cedfdb5b910eb73e884e0d4cc218b87cd9bcc0bc107af586c65b3949460a25892d9607efa341f232e478f3c9fc2d05f324ee6eb7bcddb72af371d47c36856f488872249ffdd322d3de7d12b62b1ec595187b5b363e36cc714b765f0ad5616488300f6e56811e88e359365d5698ab123b917bb32f56566958b154f6fe052b894ccc1fcd99d65d19e8117a8ca4887e01f36f181461a433fb9bbc1790d8b14e34a097b149f0c5c075ecae3501944935f3caa76f0b9370ebe6b90390b4d059f9029ee4af98dad33b9050877d49c3d4f2beaa4b5861a21af95b8c52f9ab4b0eb115357f5b1d25fb66a36b9baaa4d6cc5a4f5fb5462432bd82734d7393cd22c68f52493eb3434c3b88fa255baae5c46c650cae17ebe59827cd6645c6d377b3cdee3aa6a758ad3a96d103bf6ab8ae03b72b53f3aebdda359288c32ff5461a158962924a97a24af29f6c976762e8de9363485ada49c445566e71ac75379aaf7bf190a81c671115e842b5280a05bfb2ef3724bb74487068d5b5ab2d089ebea7ffb4381a7e96233f0915f295d3b71db872393bb990b9c74717bc3d72f6271bc248e54828a1e090f6da56de3643b083e9695db7d0a32bb42355e245e5cc2ed57354d82220b449e10cca1cbf6fbe796d141591d6f71e4eb6770a3c7dfcee509c3c28f2f1988eeca61833b6681e6766790c2a6f043b4f67e145b908ba7f03361cd9d435d054e11edd9667e4f9d12c2d74f2832b619", ++ "slh-dsa-sha2-128s" : "0x39254afc16b1dd8d4fbfff766819460253653dfc6a8e29abed55ffe91325afd578ebfa2dbe74d46b48b381e69d269b5bbe24ca1b85767bd71c744065fa47c646e3603b44261731b50f2d20a7a327e98b84c5ece73697739c8057f99d6ecbc54cf891649fa78b7bcd824972f3b27820ffda3629f481b1193b922cefc907bde3ab1c78b5ac97ff26986f3a553556d0b158e936450b4f41bf006c90a9758e0efb327f67408a7b803ede993522cd9042db4a672c89d4765a0fff8c6e8bf6882a8de432229dee08ae13def90f9fd0a40c99f3d93873a41d74871aaf407b0927a817b476eb93c645254bbc77d131e0bd35a2541248172993b1064d5b26b921396c8c1664178051810961039b15790862415338806329a45a266aece5904312afb1cfbeac1e816fb96256fc6e2b059c25af1966b0bf261bfb72afd8652feaedd6e0e4bf829a75188708ac9c623d4d6699281913bb563b96818f9307b66f7cf4aa9591e30c65a0b0885c22b5d17ff610f40bf2e0a9a32173b2fa7d66c14784402885d84f33fc75afd8f743cd10f5ad6dcce5b33a8f0c0365de2ce1b69aa86df2482a2c2d3746c6f0ee4e6fdbeef5738d809f6b0ef3cc703b0d29e93e198b68d62a5be657e69c33459fe4b163a5ecd72a90f1e53fc00bc8c698af7ae3cc5b07e36cb74088066a54138d6df4ef6e159ce5924b6903346a5fe115272cc951e8713d4b6f96f78d67a542c3bb402e69bdb3c2b06e189186c227927b2aba52b29c14e837b37798321fd000ed3bc0e386ad6e5d3a48494f57109322f0a87f7dd752d862dbf772498154804b09eca84c305595cc1e6654b1b2e94d5b88feda176aa144d3895a249754bb2ea99b2efb4f61b828f265638866a49dd3437c70016347d5aae64c79957ed394a85cfe06b10b98b6e83801728645529537a1102bb04ada4226688594cc28aefb24fbb0d1a60c7b826dadd23f301517e862c67fd88d0f6a5ac08e7f966ae375b468e57f01521b43fc24c761838c174ac106c4e1f435b7ead5e79aa1b303222f6b45c5515d497d8e7b05901bee96945652d304ad9ebae2153321885f19e7ad08c9da73ccc22a66c26c4cdc9360c36e307310714ac44c80887f42a2575305ef649378d76d297dc6faa904377b2037618f23b8be496fbc680645dfb80a76bfc060c6b2aee4ac5537e79b7dc7deeca0ca38041dc877b875cab1a297190269c987dcc46ff34e5bc154e2572695e463542be79d61fd5e96a4be2b07f5beb71b882f99de317116fd0b36131a88ff9707eb25594fec74cf76c2859ba6ba2b968d41479adf8857f4b0f4a26f49f0f04fbae0e2f3c2ab6aefdf01855a7a5a4b8bf516f4551a393a33d3920ca3ec403b4d37c2106d777e3d5dfa768614513885d857ce95b9bc3b992808e7ad71575e5e91b8107c5802043b221c74d73c7bbfa7a191945bbc5ed69e20016b16e2e2987818cfa80695e58950b0c1bbb8c474f861d1447161744c75d99dc8240338c43a5c19a8a9f46d80f6b4b6c1cb57f5a3350bfc35a0522f89e3470ccd71a458968c629c93336af6b5b091f569d1fc9492eb6b976376b8ff19ad9318f5cb1361954a0471419b4207dd9dace8c0545e74dfbb19ce3fdb5d456a1c1bff7383c6fd96dde3a92daf0ff5a315714c74711e3c05e0c59ba525c64ebd17fa20f8e143c5931b3c77da193415e6506c2db27e0e773a6a5b5d47ad95760b8d471d06d5dfe000a2d47e6e4e6abe7219750f1f7892f4e09fe88d13c2e3b53dc904ad58eaed856a4abb0c10830b96bfc1b5764f9e4b34b0072be314608fdea8c5005d40ef99806d4d3edb72e73541fb828d4b2adc38855e09e974293de25da6907f5ea97810eff1be37f88ea879e545bb5a70d2187edec81bd57a95c0314df4ad08a864156579d50826d0cfa511d335ff722e246151a7afce94126232f6bac89b13c142d29e7521479866e35b17c15f16ee89d798ee8bfac5868e505031586b81bfadef4aafc2ecdbde649f63e07eb6026d09910d9d3613a9871b5d1523cf5958124f96b5304d5225b4bbb03aeeef87753d0b6ab51a287df1e9031f56f755d3fe5a20f79b7f0f467fa97eac5bc09a1adc6ec285c8f80ec5c184b8b5eae326300a5bce0b1d757c8e4f27ca2822e73745009291f0d9032051e15b567511908f3ec68840cb6ec6018a9a0e30f2e34759743ef0bc9e12c9b32f29f4b70a998cb8893af2dcf17e0eb4f48e7ba367f68aea5516e7248c8be1d1f896d7e8446fadd9603012dc13126878300f0868bc512221154a5104882621f831e60b49d04fa8a701256b3a413b9db4abc5af10a3f8f4c26cd0b3c2f55a58c9380143d835b759bac7fef824515a18d79b6dbd361541047c79653ab4af5473b7b7e67a6755add78d5c14c0a9edc6c7dd42c3d0359d9f2f6961f8930458a34c4f12478ae45c20969c4c18654d31a7ae73902757b3b8a4eedfd16d6c0d22548d7b8ba77aeb4c1e3f3766b6ea802ee9bd92c5f98d00be80c15e7e3a82eb0d100436c398781607dacbefa98c87b3558f363b3ecb1ff313655838f864c1b2e0f6d6369bae4eb8cef98f564108ab2f763e590a9e9201f4e28ef1971438c30f4376c55cfce9b9910f448e31d06c2e456eb798476d56a890660e45616840377ea0574d1c066ae2fcc46f41cfbb511e5efc4b5c60e00e4846e157bbee5fe3bcd77408e3bf721bf871c05971a70cf7a13c782bb4afbdb1ef800a414260243fd828b67f49007eaf60b3e32f4e2b8186291075a0b1c0a528abb9da7974b3b1e8b20d337161ce234db66ce82a88ae1dc880933343961267cb4932b36aacc5f136cb474bbdb5e4c4be4cd74868775d80317bfba00ca4e58a39d04e63bb797de366c45efe2e356672f567ed1f7b2741df7543d6faa7227601eb7cff367d5a1ff320ca71fa2a1a42866239cc3fa5eba400ee4060266a05b8fe1e729908b95ba6aff8fd76b5e7df547df62cb89f0605c1207c869d7214e4e6972ea6e47b18235855d6f28265a737b4f64f0d215943f13d219292036c1cfc46bc61679f034919e4fea80d882a5121cb3096a50f2112eab265ebf75b607b93e14ceda4e08152221bd368cd1503ce375188d23514dd0936bf980d4282eaa6fe8f38f5eb00c34e3557ae363538a2c15b560b9f9322d1f17446e8f3fd317126986afc2c5e9fbb96f8ca7148f53cd75a4b845a28034c8679baf1f5406564b6e4b8fa8e681b5a9d208f3a1b28e84d6d52d4baa152524908d50d71d9c0d11bb5665c8a6bad669dbf303027bd0d534434f9e76f2c300326e25d00bd8d3bb1debe1c3984961c0ea8dc547e8cb83a8f3b044b673f4a08882d103d6eb143a9645a9a00fab6f1167a2c09015d6ff2dbe4aa4025f604a63eb32330f832162b6dd9364f4ad6afbd86c8d26f56d7d9028dbb3051c85a0c86ec0d7961fd6008f87dbe8347fd5ed1dc4c27285364f63650f161321daa83ad41fbc3412bff800c062a78cc5caea330cd58e63ea9a9d6de2ee069732799f52f49d513c658a44a2122b8427a405d706f740600f855130a0ea720f76b3111dafddf0e2ebbd13f60640379993889089ce508b1343f485457cb8e0c09760d3199b4ea940d584417259e41f2c66853ae4235b6f010cceca3859952b3daaab55da14adff0e421e862f138872c2577637b3e12b00384cd32fb3b9c97b0d59e51f2488e379065d79f5a834b076ab5b35fe4c47f2c4c4f43e622527abb8f682fe9f262d2883fce5c9f16b7566c4e078b67611abf72cb8a0263ba12a6c23b1a04458c759f2bdf6dbcc460bc5df48146468073b61aa5ab4a9c5f6c006f54f1bfdd85373f33af29d68580eba4cb6dd88054c81b3bb7f2be8186e380bee0b32a1b84ef6319798079828080361bcc27473a9634c23652ed6b2b2c8f8d5a6721551c780870f1787726b121263e74c9464a76282dca27249b4532e49455a7485e2cda4ccca823f62d3b2869602197a6f1ecfc9d92ab6e231996e603e81e3dc648aebdfb900a3d929502ff0bbb3dff813660c9d5a417d857c19754ee04e50f1241831517fc2d2a71c5e238a944992cc50b7106aabb5482fc7e0a2e6b5b11bb6845f34ede98a18d5f07759e61603de502b5eaabe59a4d2c69f4b0f8e73a9bc85b8950a54bd91bcd0366dffaa0df736dbbbc35d6accb5ab8b22a870374521f2035c1878718d7d3b025838da75d8bfa3ff36b2a10a3cdef1b150abf3b6be95a5c096a921a3eced20f509dac4ba43f2f515af2b65d3b2ebd0da2d7a58500157a666b387b1814d0a3e84f64d0fc44507b0b6792c0c6bd90ab62e0f75b66d50b6f842cfdbecf1fd043d642c5d5b5fe5cb68af62e6e23cc6f0f9b1cf3cbd0233ce48a996296b6609be1c9e7a027cf76615dd11208f1fde119099352cc17e1c9a22f4b71c3e628d72b620f3cb4bd40e4294ff8dfe19480b5b758b874a737e6092254638a222c83aac52fe0f66670454c313adb0dba2b4e95741d27104bbff159e999e23103c00470a7feee6f4a35f764ec81a8ef520cf1e8623fed3c06b63c022e40e7638db269b8add119fec50456b33224c14486f705e5b3339c6f38aa4ba6dec8b098c27447185ca50cd70772e5389ba703a4a9f8649946671a238e1f005aba0b3a18c8ceda9daf4cede6782d27931c638af3f6083b2bf10ff0a632ebd4dd528da3aa2b7a8bddff2901d902b26d518a058921eb0178ef08e24f7075f77ea0c0d0e72f29847ac7826230c0ddb5e7fc8552ff92c007e9141f51384a12e218da4fbfa9a7a4a1bf266aa975949e120db1b6755ff04adb07c66ba9619b40396072e7cc01dc3dd56f7a2f928a82c8906be416f6d5c41354881f9a6c66a927292f8cc2887aee86e90da32fa3bd9d72bc26dfd334f943305fbe4b645df83fb72c565f61860a480dc0f2f3360368ec3715c2c4a312bd2653051c8f29fc14e0c3d1f515e04b75ec02cac2aad8d411306969d9a8da08c3477eb6201bd54c6ee643d87a89c78a5c8ad48590b7a499cc44ccb812866a4c48ec2da5f1e0aac741464b26988459f3724ea4cf103c27e4a43e5a5fbbf94908878894f8b62995aebc20e632d924c82d9669f64b2093cfe023cdd1542c8f9d19e5e7ad6ed7920ba6834cb0cb91bce48fa94be47c1833c6ada4090509ba38defab7d56dde8168bac8021fb5a2aead00809f1881d53d26fa9cbc824488e16062fd9f68726c837234a82d518e3d10c9931295d20d9affa5fd18c0b2dda299cf1d6fe0c6e6959440af9b397f3441bb9881ba1d2df295d12686ef6b0bfe52fb2bef06620721374328551040d2fa434b161648b058b74df2a7ccacd7609b93421f44a136079c79a3e63bd3b4f79717f3c121ceec2c3918464f5619b1a2e83a7709fdf6d1004b0ee51c73e740b20e329847304a82802e02170db386e360dc6027aa7ba1ee35d7eeddb41ffde093073d92899d568bedee914627c8c48427376e7b5d5ebdab30e58147dac5638090e9c71921431f025f1d4e3ba3c68437555357c651336b326c9c519544363d5f4faa91914195314cc873ef97068d928a6b4e5c6ad70ea7a7b09b3108fd5696aaab800eafe463ee52a3f29e1bbe8a968e84b762484a13714ee260759b4492b749c46ab6603c13ece34e301c13bea57d9de706edc839f55b432b9299d2d6643817cd9d32d0d9ddbdbb23acef51992b62db024365ac2db4c432c531cc1ad18c807cf1ee39dcd842aa9a09b232cfd09bfce33277a8ed09953ab3b5d24e5a8a02fb4a02ceed705185880ecc47cb245665cf640ded4015b4afda053a5d1dff77e390c8105961cb3a954c28ddbb9efd759080dea99e94e69b03b928c8667fa4797dbb3cc6ed093bed107c817780f60729036f13346f05491fb837ef1ffc61be7b61d0b7f8dabfd49ec24cfcee088de38daaae6b4e740ab4faf16eaebf89962331a99f17ca5955b15dd1fa493b91e7cd218aebbfaa7d348b1ceea26951209137448caa93fa466ca32eda497a5b9a4fdbd23a10d9742e74c511a1648d00bca3ca23abcd4f18b7cdeb362e020c73888b76b83e70d26ee358c06933f77d1221a8ff0647200e451e971fe45c23aff60a88baf46f59a0bf94e99ab9337b0336ffacf8e79db92067d2b744134cefac1241dfda288f5c6ab293df7469ae0926c166e999ac99c8871e571eab03f82de73e9de2d8f4deea3724f795480cd47e304f27f2567cd94cbed52e06f1f1cf7af2feaeba8b95927eff950bfc26aa0cc3e46ec7bd5d4aa43374500f8cad4f153cb586620b9a0deeec2cb12ba48bbc8655c7fa70ccf94aa6891b5cc8a3c98b482d906d72e9d425301d0cc6fb4ec9c4a5bcdfdd74fdcef68f05fdb78f2a1c5ae32c28c43ee900738f31ac1fd337ce95966b3f557a727e0c3ada6c6aa61219d92fd5cf68fcd9b444f6b4fb6178b9c74238d2575f442a298127f282b5ad416cf6a365a214048489139918f93ec07f2cd864f5482c418c7336ca4590a7da8a20d33ffb7be19934c80b64f4b982a55b129f4896685534b83251d54e46a2971c0bf49ded9b13a77ade3de9a61f2204a46ed9cd7bc444801381994c8ca5a66abd70936f8d11e2a2fed78fe9fe8889dfcb979c9a3f11f2c2c1aa371d1e98c4fbdaa95d58c6b22410c0d3d3460077dce654a1decfc829f117bc407d06ad9ee6aa06bf818ea2f25312b1cbbb5de527ce9b5c5ddcb0df21e3442ffd149b24af5e59eb4d7e18f68b02b26e57fdf23e7af4fde3e672990295c37186ca67b2abdff6b46e1ff106f041279b61560ea2eae64649c65be22f9070c3239b0cf7929b0778c43dae5391d8d3b8c335ceac672376588a34d3b9c61833578e8d5a9e6e9f72748d860d7af98f7616431d1ae1ca20db3db6ec99d59fa98c25a1cf478e1b4a643c2fc9d3e482d56bedb1b7a1fc9c3e788d9de281c7356b82e3c9e1c9414a0d14cd07fea5364b6a22dcb3b69b6f447343822098548e3ca7e88a83187db145bda17f7c48cb00e6ce36d53e2d1e4c169569ee3fa03620a7131bd5c033062bb82cedd0d0ebc1025937b2d85a3cbcf6ef4458a57525a66244be3a62b582bf2b88549431cdce09f6407e1bee83d3fbe205f585cc7cf9c1eaba047a01f51e13bbe0715a9112c451f1daf6074a1af051d8b98863b6fd03238ebe295995d60e7a26d2f95a2b4b0d617af299133bf357518b84e942bc36a88b4030d91a7067e7a2ed7bbf4e9abda8c6887ecdfebda04dedabb9ea833123507835e0357ca1513b471da73102605ed03297b5e3eb7d3bd01c670f992a7f19962b706e8d0ae0f073638d633b34a1229b6979b8e90f2a536cb6024c644e1f7ef211451dc509e061b294c28be188c96246614a1fbf52db8d9a99f7100c878c1b9da98ee9e9eddf7fcb386061ddf46807c60b24d665f0fe7fde205f91021bfb87c8f4c89b5da254d185bda9cc2f48303b483ecbf934575aa45d0d58cea64662f0fda4d97790bbcfa237984cfb45a9cd611b533dc0ea997d191d14d307c68db318aee8f99544fd48fb86f041fe249a14263e6657a5ee732f7c5c9c97a8924bfdddfd75dc67da65042e711a3cc144f46d10a1a9fdac1b1b321eacd235299a1fab390df24acb739d61bd60c6907b9a3827958198e6e2b5a1c90cb9b44cf8db9b6e45f710d7a39c230ec9cd855af797555fb1d73492e29d17da0b6dac59c2ccde0715565efa1f62898c9b26438c60fc3b9f859bbd33a8e05e1d3d5a762bf19bc7c32cf7d4c6bce26fec6e5c8c537608a1c2aea2e1e5cca5bdbb45a8ed048514ef3d298e7dfb9c5408d941ded6220a44c184dc90c922a3ae31c9248c5f31627389770a59f9431fd0139c5ac0f08f69151a75a5a6a0355b7beab6be9829146ada371aa5791c861dc77598f09448af20deca73cf98a399f35c36f1167ba426c6cf4b8b9b8a22b961bca83e45bade098e20782a9f70bd54fb8eb6eda3acd3a5bbb553438cfe37e1f7fabf15729d6bd562cfe379d586181b71b3d3c4b360852003c4363a8d473198130642972eb3434c3a5ca9b497ec7000e821c3419aae75866496bb1b0a9ac6cf92f799071e06809f1f3f904cd18f32629e2093664755803f62f45942f5a358cb1e925a8694998cb14cfc52733c356cfd739c3976712ca7b007e08841639da14e429c102a8fba3191cd36c1c56eb06bf69afe3f2afc4ebf137c617faacda6baf5cfdcc6462ad02f63e8a5375288d0de5700d0f9f4ca82a65bfdc405d3f96fc663658f0aad91305b86ead3b21bd6561a40db0f2c5b0937ba5e1ecbe91e9c50b1dd6bd83a8145b033a7bb6a4ad4896e0ab160e8a52d39d2756b1c8d8570f7081ba217fd8803954290788882befde24b4971723b0ecbeea14d23c92eb6a0d7022a84aca072729d7ab1a88927a25f19a2086f846a44a2726ea26cf1b69c58243e219c756d06c361e1e161bdff0eca10bd30d23782b3374ed421f50cb66c9ee063ca622fa78c8cede932848f0f8f91bd7a0eaa324377c109808bd66ff463a72389c4b49f2e349be70d07fcb56b28549fca65ad853d70df66b587390febdf6b1881cce6c1ca9e9fdbc9f1ad68ccaff97234325d3c972b57ae5723fd73f975ba640f90e717e9284c111b76367c6797399452d37df6b8b8d22ed5e7dc1481a415fadc06673ce4eb6435d31acb6af68775436629a57db7a0aa192310e8427468e8e310bd3426b7ffab00110324c0c7e04ac6649b6f167fa8b928b3fe12ac162db3f2bc355295650fa2d976c64df69a8017034683bb4bd4baacf1cd8502dff20430d48c907107acfc4e29c584cb497b7a471fbde90aabab25290d853b8ebd2c0d49c2c201eca42a68a15879cf391671946319427b237472cd35431128ea7ab6d545617321592c07b09fff93e71596da30689b3c15368a1c3a57890e0ee5752bb4356290024fd1bd2ebfa19f7f3ca57c36d296ae61ec5581ceb77618dde2821460553ba0dd6dd68026b911f4af1be3986198966f90ab757aca2f5143f1937d09c3a08047b797781d1639db4030f9e59f8c5b71a71787cc84ade5a385ebceb1946177a056179aefb49e1f69ed0aa67901b2d6b2152b6c1fd1db67f358093180fcb8f96483fd35a87fa14825d3849dbf479be493bb2d1c639674bd195b5ea3caf49c2b78eb0e953dbf8fb909910c87efc6f9b6592c020333e00f83bea4bdebef4e107798f9a8e89fa5d063d69f88f31a53548ba2406407251f18c3d1ca6e392fb81a46107191e6d906b487469d0002afdb0f32c39873872a49eee649250d4d5d3a7687fde2952291c8ba78fd9b962060df12d212033303691b05eef0ae0e7f31b7e395576708d211d70281e9501618673afac20a93e82f060135e51b29132a0c9244551814bdf399b746651279ed135d162e366f39d40e3a49e907f72bf7c66fcb4ba75b1f447fbc3ae3f390ab4c10963d755ee188a9b0129416161995adcab12177976208e1c93ef48d3ef55ad22bbd97781dc7035c9f5fe25f47b703b1ed50dba311d24154ab05dd88ccbb5a8cd96d4665829c4dca5d5b22affbfd7e842ffe5e87bf4326f957392229bbc893b1fde9e4b2191a3345490d418e9298179661104f70bf6cf9a0094f9d37be98b82d98497573512d8f6fb4b0b0aa334a9120a5afef20e0379197ac7ec78da3688d2c9b590e40fcf866acbd1d857546522788d1f3ae73f330aad045c5bfd59b8a399ae626fd67d9797b32d6a279d42eec3ec8a2888258728f7c329c4efd0f71b730e57f9bd87204d40ac1ea6032a4b8ee3a338aad58c2f3c9795819af4cb652dedd475e5662d9c0cd23e72a8f4e86f1a63e5683c814a99a6595b779e5d715ac91ba62c1ae4ca1651581506ba80c2ee0d3f97b979758cfe93f373873f4775c882fb3b5815b9274595bf50488b935c82e0fb4ae4d078d30bf0843c89e484bf5a24d5de602649e336fb2b79da6131f96ef1b5f82cbd668f4599fc9a92b4e9ffe3468e39e4c8bd90531952327da74a522e479c66b7b1554c9a72a2e6db58fcd45588c9ff4f48be5ddc994913833b668c275174b9d862dbe8fd01535ff2bcff6ea030842ed3a4d105ba07feb0098e39f61a4cbc06bfa153c598c10c5de57caa413752878c7599e5db8482b6f275db2185c505bc0c9670fa0afe37031eab994120acb935bf9dbe6cee6ba336dce1b44732c4267ee77f5db890041e547bde486335b9a0b85d6640f6534d84b3729b3436ac1c0551d687ddd8da9abc18689e7e932d5d0e787ab5ee5f36eb53789b9ba2b71d7a4f7994e56b056d4a042bd2cac79ad12d87726ef8cb97342e616269e9f87493e95dcebdd91763b134019c0a76e8b12789b026ebd1d9caf1930010aa1a5c348ae2e6273c885ffdf8731b34d87c293e77e9ef14709c2e3b739dec85d5bdb8f5ebc9eb610240576435c8d222ae0c8ebe5844980560bcfd45cacff143a5c208add9011bf9770b7803fa90bbaa10f58d856250b37e481f325c538e473dee7863957121374bf12172321b9c99975078e43a0e1e40138f9c31d6dbe5e06fc881de840e64899c0cf342a806916147de3cc342832a9514eae9550d2cd1166e823f404a05b418e5f9ffa84352cba3007f9d37e5b00049d7c099346257fb53e86b919b45a9c6cd8b67cb3c4e383fcfd5789f2cc087d6b459e2a7dc96d08c826c43410b3df22021855c7d413d9cfe7ca79fa860918a74941e08511595fc9a3bec2e2e0c6dad05781c0a0d6b6609837ca8f78b0368b1217b121cd6ced8fa48dc131709434eed65523269abe95f338bc5e3fce0046ecb24dc1ad8c8fa68b5f9263361e4952ca1aee9229811a5ea85c9c4452235639d1eb8105ff88c048beddc0f7efd3690da8b9bbccbbcfeddcf3e3c9e3ea7b46a5b40098fb85a25842911e42a714c2dd0fab403340ddc1af9484843b33c7f5bed80fbecf68180c9b397ed85c51d39cf08c5c0336b149e6d1747360541e84a93224ae88c1b62384b938ae25ce17d656b9ae52fcd9100a40dd7793ca67357f3fb00621863a490373f0db49b1aebaff7284d450922f1e5243bb7fb5f7230dd7cb8db1e08893696908cad4a45711eadfce8b0b42a9aa937cd011bd5c4a8c3a2ec771b3ee4959eba5e4a17545d1c86acaa4805e4aad" ++ }, ++ "ecdsa" : { ++ "addr" : "0xa16c987b93f1b3c51fa8a9833c8932eeaa566ce0", ++ "claim" : "0x8029e6ba97e0cfbd9ab4ee6578e3ef471375d5e3e592955eb6b947715ab035a31e58951dafe664e6de6e5fc6aae761a26890e81114e2c4429c5da4221c0e283701" ++ } ++ }, ++ "2" : { ++ "id" : "0xa5ea2fcff9e3cf29d0c6f5f147b67ff24aec3bd4", ++ "keys" : { ++ "falcon-512" : "0x099202fa37d5e165b88428d963d2a224b8fc82ac0e4b3f6a02376f18218d1aa7d0e910e71586aeeaaddc2a557124d6ab4f9a44b9cad02166413cbeb14b364e13956ea326900eb2900802644167639045d76bbc4e051654cff404dccea94402141ad9fd992cef7a8fa6478b3e6f8912886e9edd1b34c29385b7e964f360e0fb1600787934486f461c95d577d2bc74c4dfeb969b4798565ce0225ad27aac052290a44f844ae233e082c97e4498a31117ac9d02f3605c856e2dde6f611812161f89cb3a54dc936ca1e740a6c659405ed586a9a963b11c89b01746325e39e645c72b0c7e4491b36a17d43ffe38d88c601a5976f5a9636c964a012bfbce5f9b371e7c3b38580d81c6e12b8e8f2aac219f96245d35b4f4afa6c94015b055703b8c4dabaea4ce2577482f5b34fa49e56a912dd58d74580b1f94e1d2056594ea64bcdb696b0baeb33c86b6544761a3ead9ba9888cb1ad51f7027ee52b21e46c5eeaf3f77bc0af7efdc87acbddda7dca00b6acc665002c26447e5b0e0bb5ba261717c68dea7f1576462776954d7249c2fd0886f615ad50d53960ca02d581a4a25517c050ed467c7a820bce6250a9ba2e44fd67fb21bac843bb134c95360dc1c50d54b7280a94440d018181a9d6374bc64d782c84471b47287d8ea748c36cb83cffe053cb89a9e4ae71df497871c2a728ef210903e5b7f39550d0331e15637be7e28b3a2fc05b0a9b0c5a06f9fe81263c3a94403d6c288a561288ebaf788bfe271a578a1a795a85e9d452b61ac204b297090617286922376bf0a8d67dd35fd705b81260b7aad30132b965e39bc3cd64d154c4175951704873992a814814dae5c6bc1e89a83dd91144cd1b88f6ce449900058afdc53bb44bcab63d30cbd6df115a5ee8f5380a127a160e922bebf7b408de82514b2e2550a0931e065565e8dfc389d454823a55b03e5c989b09e3791f656794e8379b7b4b1617aaa9770366d63a657f71ff40c69b1d5da518ef1e2aa42366cfa38e448563f6c2db5e3089bad5520ec26105fc885993630c10db357883f588a5a384cd6de688e1bc3b1200f87ed66ba3d4a4b671b2a500a0436e0955904030d76577aadddb8c1ed21b027f198c072f654c3abb086e7f185980f49d0e109c1a82741809f8afd15ee56a887b392c5b172ba659144a7e99e25ba19792d2a3c0ccb481822839c8c70c65c0943a2994ec9f6085b7ac64ce2b35489a72dd6693d25f2329264e063db26ad4495e3ad00f12df8cf914fd846", ++ "slh-dsa-sha2-128s" : "0x686b5dae4aecd5618b95c3b2a5792888513ba49dd366ac39b7431ef403e04963" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39cf29ab9b80215a9947b975d8c6097e53b39d1483c885ff7527d7fccdd2ca3dafc32bfbc0a19c857fa8be7e52e25064d69c3b7dde6e77eee96ec77011fee440c8bca99a45b432b5468715a0aeff9d61375393b3ca40b9140e1a2bc2a52c3c8a85292f4c9e87d1e0c12fbe4d7236ba7921b8b83bd10ad554179dcebf0791c4b593c8a1bae836883d5094499cf2ba41b00c8c36c77a83466c263a0b01e773f08ec66d46e97caf0f9785943f98e159e353f0d91d5ab526279477a5509129f7a1b8b07ba82a1ccb4acd5be5e40de088f2600e06a8bcf35f54663279f04c74838294048a8f8692904d4f9eaab49635068df74d1f5ed238f6b895acf1364544747bb10ce333a957599594d766ac5d1a3ceecf8a6696cdaa95f824ace18cc551e1f4ec12f345283b366314515849feb5bf81fd203a6c73b5bab7c01b5c1131d442dadcb6bce32d6e13c5a3e77b66eb8f5b2912c0938d89ed9e20a455066d151a973e4509b03f5d66ff7ffb8b362e0c09b969e21173693d9977ba06d48bd3b85657119f9dc3533c91965ed81d1eba72b46cfcff285131f84306fec7b271a02dd22982cb6399a9060d286aa18a3f97666810937f8a5667c94959a4c27299d55e94564dba27ea3d98cb3a9db6197c842eafb237649de3fab72a9d56098b5c1228e70dc062617a8a6b44d46b7899dc1e53a77b700925ed1b438c59458c15e9b91fa2c2164b9661a976720eee2864efc5363d90beea9789a6d3b0628bf4695a853251c7f70ba1ebcea06cb35cb47d72d2340bb9412edc49626d6c78be644c4ab1c539d1469d1cc63f092ccac45f66917d89274af9c84d7f1108b1bd738408e499efa63f1a87c8730400ec19f9a59d241032e9ab78670e85e8da24310b13e89ad521ad4fae3deb9d438dd7eac72b79496c7b65061314ae", ++ "slh-dsa-sha2-128s" : "0xb8f14bb6630512c51d227c12a04ce7b316bfc0d255f5a5d1dec3e1ce5f5cc92927070079430990b4364200dc6d389fde89c78649e21d8fd3a17dd2de7444e77ac3e8c70eda15f2247300fd8e37e1e3c2afcc3e8dd674823106b4297ecedc924ca948a9f80afd7ca1bb85dc0e60e1ccd5d97eb21062b2fabfe94827b4ce5f0e396e5a891fbfc61bb827cd305012515d0a182f163c1a5ee3827aff289ec526cdafd2874c457947e8a6c8332ee7172197cde7388303992be248892e727b559c0d74a2c65d46b6686a48f0b814bbf031d1bde17f55b888e7cbaa7fd6dcf428b13ca43f77d80c3804bd2840e5768c2aa17f6dc773b71f83eb7803fd9e1f1a2e3e158f7e823e9667cebe136d333316fc670442a8c662930a00f72dd2dbda9b19c3dcfdd09c60ba55d9ffb5d5b3384d719d153566bc0b6da89d8dd869fb8c4113258014cd48a67a3591d37f9ba767ad70a554ec98bb59275ce163364915051411db73833a88cab0d3fdb7c491b8580baca2bc44a7bcfc3a51c28ae0a1fc12bb53b2b948c571397a348e664522ea749890d1c7ea7e9561596a3e930bca68377e4d4c0e0301472c8017c1fd5702cd6dd4c3f5881ec4cafb98967a57837c3869720268b61f37836d0c9c5ddac850a835318b17758a6f97df4d4966d516ef100b7e61271c45aeb89242ac7d2b8ee45a08f4081727d54cc08ec0f8af9e16bdf6f6d6797b9f5fcff9686f15efc4e8e34b363d562dba239908a3992b3548566a30cf04c424383b5bea0a5011ac620ee384f6363fca87daa30fa88763146bcfe0a160c071d79dd8de0b11e034fddc032e522b7ee47f318cc6f3f2b6c9b6efa0aaa9b9a9c1243750ea31ac01f087d5f4f5fb97b8296b0953a606c49025f5bedba6773804b15fb3638e72ffffe38ac20486e18eb21059f419b0af9071be12e309a953ac82c0a5a620a7b5c850027b39cdeb5d728522a15c1557e4ebc3f4f09914b3a99e291a814504ff7171c23eb825d2df1bad1ff29144f8a3babcc882258e8a6060272e95c4393fed0ad86698554515e77340ae806746ed859ff9730cd718c767e320ef54fae5e0cb8ba331bdb920229d6047a6db8bad147b75d376c3e72e06fbc6a542f51a312ec831c704099b2eb0f801b68631b464ef484eee077cb7fd9ea951a0307e08dc5fb4ed5a6e62048b010ede39efc5462ccedef2a4c61ffdff63fb3aae19b28ca48593532f051c716835a61f2fbbd5c25883f4a85b48d81658b6d7cc4227f90a81e961c5fd8a388c9efb78da1c9bc50d53a41d2d336232e84e3eb3444389caa3457ef9e3560c25033ed45242d0b4bed69fda4a4f1695830c843e63147b6c2d3f9bc2608b0671e59d827dc1e3876e5fc6075bcdf95223f73dfd11d64399333f7bebdda7f5c2838c072f7baf753a36a1ae8987773fd0ae5acec41d7666c84c1125190f432a4d82ad9b78e22d6536a8135d80a3d1715d17a673033d37104857278a75c2cbcbfe0159343dad8e98e42874e2b001bdb469c9faf79759c4cb3e3f2ccaa16bb29d3e4dc81627441d07469dfb9f545ed83d9c20ce586370be092f3a90b18f30866336c6db9d53e2e0fe1f98c655f1961997e41c25089a518f05270ce06cc115b6c2e9c04f6ba9bf7ce3abfedfada8580ef89f2fea98e8a19c58a0f3ffb89dadb05dbdf05c44b79ad5e1d259d5aa6086cb295341dc40ff800b460a5ac602a687d6feaf66393dd2be22264498509c9d39033aaa22eb248780a3661ecf0a05cb6629ea3d91eb0f68465485e8fa3fad3fc4315a118e4eb2ebc6e9b07284697cacf0257edf67c20b7b0311d3094f4647da567385a508addc9b25a66db1f1544dbced87886946989682b2f2db1363dc635e4cc3c67ad83bd311437d22d8f60a2cb7833c952bab293c9e20ec2b44e1f1f42a797421eecb2e9e9f5e47105b9e7f5d7bd796c360ea39dab45ad701eef0a76b7773c55e7af7909d456c213b0db14f985d0f73652bdf39a6402cee104a168749466e477d8a399469992d65656b607fffbdf73ca1bf4976d3a0c0c64cf5d260d6d3e0198f0b86c451b9ff5840968a2b60a8ec286c81fb55741d7bc9714177c9a77219d3a39dc1d6d7adecb7f8f85af366ed653cd81408b509d0f56b5dccdcd1d982d115754364ca3f14a6f100c54ed8ebfce6b0dc3de4435507acb0c4d974ae3f2453867a70d5ba078a17db34844ea410af4f842dd4a9879a7706b18ddbf94c7b43ba137f7f9b8b3924b4d917f8e0262ad10d083c4dd3b99b70560377ad31784a587cf0ea1f99d6faf0f04a909179f3f93c96aaeae014ea1e74d9d7ccd0eb5ab466a6caf8ed0fae75cba902ae05244e0dde35b8c0bdbb3354ac60875c454ab11f49e47e2d180db319a113a5869bad3ef4580bc7402b0d6bac10a7a4e81403634fd1cd272076074e714b14a6efefc902126df6091330ae387e161789198680b0258c341b6f3ec0b09c7674e9ae8f88699fb7b2f88fdf2461e11ad483ee11fe4e3ddd48ede0ef0a1e54a318ae12473993a8456dbbe8b5ded40232b8d2474a90424281830da7bb36091ebcf591947b04739846d8a600946c2b892e2bf3353b09b08e3a141f33f6ef83d022666d380da43991d3eae4e62dd3f9432678e8be1cd4b9569fa2fa84e95195449716423688aa920e2ba1cd41cd5538907ebdf3ff15df27900ba7ee09f3e9194e1d8cdc0703d6f38b2b887a89b10787986013f688f9a355c6a362f4797576ba022e4f1d1d74e2e31dd98f1b617b99516c944bfa5bb474857fe74a09976cc29c71a7f5b6fa529f3e0c00c33c2f0700064fd507461535a35c0dbc5b69d413fd6ae9af49ccc5d02d7abac88ef02bbd40475595176fa3b68d602469a89afc03359b032fc1f0ae255d623fbf9525bfa36ef98467d5eb2f80cf7c72a04b557e40995471c7adb8701409830b232693bf2fe905ef8b1a32c4b8fe3300bfc5654acfcde685547d5c1b0c213294235b31417da91464619822f3535c93549ab4649a59dc3620e7f4a3327c0e421c5d1a28a2b4c3ba8ab02950631ed54690cee35bc4147aaa8477cae505a1d1757d85251bda5fc91cf65772e1b543bccee1a2cd0c26cd33015533a0e72c815be8634efbb50ceb0ec3c8a3bc6c84638ae371809ab87eec54b934343ee9ed1bebca488d9399a1e347b1647d108652243cf2531a4685c282e0b9e526688a3ae1d10060a78467e6804b705c143d073af664cb72ce657a7d210240011d539cb3144e9411758a211238a872eb4be615d4813b64b8df446d2741db7c9f0af2cc4dc83c0febc41adb5d8413b7ce54ed564e899c0a5a4abcd1cb44c84505915afaaf93751b11bc8e96610216f71cac8d3c9ddb7282f0f864400bdee42c3e5645aea1aa5649485435ffec9e43d43e4341d967c9a89eaaea9cca12e2089f3de222e1a5034baa32372582023b5564909fbb67acfd2a40d5ba40de2d7a31cddac717f5702648c0346e197f99598dc83edda7ad335f9e711a0835c75d4c32e3305e4db9dfafe171181551a8dd5bff89f8a9fb819eca7a171d1be47fbea0e2838a1f1d01f4e68c3d0045da0ed7d3689c17319ef5f5d178e6cf1628402c40d2095c91f7bfe6b837d8f86c5b2585653beb650fc29096f13617ce6d36fd6107ac83c7d7f5a8639e519b161581dd58018ace297bddc3421d358be70179b14bdff66f229a50a329bc30b054a95d0f43e7914a9137055f4dda000357fdb5e2afa3d61b9816c03697168cc022f0418ee5ad7aa71617103fe17e7f47ecf7ef9bf779f157eea74c3caf3821791ab628fe8cba64c12d3226877c48b746d725c46b0ccf5a18f869e6680f1e5ef3c5e7fc2a18915dfd8bc12676ab94ff4401ed22133ac1e1ba0c0352a30156bd80b63eed4a7fe9c948921e1a9843127f1191751312180b75f06e33694853a05a24ee30cae0b02a0be49db16f6f06630ced9b5e57cad548dcff70b1620ffb17e8bf8c247a962d6b2a6fbd4fb3c89e3aa4381e15b92f7245ea700e76ba99678f4b0c998ac90bf3e4b9ba5b52140e15e4b5a38e25462c1b61953cc2068d0b9ebe014db6b8fbdb2fc05751667659f40ba1cafcc2055c364116a058e286f084c2bb73096d46f6736de541b750ad437c27a92ea51baf3478837e99faee73f2a2745918f81547c45f2b7083befc6387a73366c175d2be22314a1fa73f11571395c7fe9df062740c58b56b4982240c63b8a0d5886a3ddbf6ffcbd705d3bf3713a0e1b74497b8c1f34e204ad81b63f27cfa5215d275597599f60d02bbf6cbb229088b56c96d73d09fb3c36fb3f05f4266221984fe8559619da67bb7314ca66405cef4bd3086940c4a7346243776a6fa128cd9b6181d8f584f482c502fce3339f87e4fc5e3593b7a0a64c19fe76c51a29ef776e478ecdd5e093b2aad0ab3cff0baf73f4e09d63e9ccfd4aeaaff147ddf2e9f1e3e6cb3bc9757c57072a1a8076e179e50b0a03dc94de86fbb99f0e92338f26b6ed7c863830f325d3606189b80c8df5a763f422f26436f753168b53bce965c562c2554081cb4eb42d48daf8573206f818ae66d62bafd151e9784d6a9304996b4b82cef081af9b106b42ca4b6b0b2401dc21d8875f9801591234dec266f1f218959af60351178049b487b2784183349e0a7ab361f575fd0237d9f483590a23401f9085b111ac3d740ff4c3eae0b7dca3d149243e3b1fbabdc7431a579652d522bef7023e1c6579d2f6852f1acb9b7f20e3956af8dfbf14617f14981f40b1b2430920be14284dd5f2771f73091adaf9179b8396c6ad2a3579befa1e323177fa2598a3ef80ff5785dc2677f87e9299c6bb16ef2b2080e91f6fcf1b9189e256985e631a05cbfb6427eac995e683f494751f7ae888bb0dfd23aad7fbe942b8100d4daf62b6b8e4d647c818ee7edf0d4d64293edc3b7b6e08a8b9b71a7c38f55ca76593d35770185637fb473da423069de005363ec25235ce816f4df3070ff567f919f47dc4fcf57c168032ef8d7e3fdc5a6a1dace2513fc24f0829e8e4b964d37333febb1eeaa7b81aafe30d16fe64b6ac037ddec2dd9b372c657120df4372504cd14be89d3719c5aa6d545030423fc50e277eaa401e8bb02d70b6614e9768a7e42ba9b35af8f9e3f7dcf175609f7b91a16fdcd65a151c0e85d92dc8a06cddd1ff77d150ccb62c612c90abdad156ced839e837c79b79f456156a28c45f3287cb86a9ca664a13313332a1ed9ef4b3a3df864eda7bd55a6d8705567bd8d1d732f65a324aa6c77f6dd82517d5274343a4e16fc8f41f5a3809e9f2cdec445b88309c9d1de684032a10f8944157a3dc3d4d8d59721f4f9cc0b0e1e7a97b7b066523f7498e0902ac5aa462d9bd096e13c14407bef96b59297391032a4aef8c543cc8b60217ddd5a5d815c4ea1e21625b52e2323b42b4851b0bbc461abad9b71805e8b1b2a16c811be69140d3a6d32d7aa9d5321adb57570fc2e62618cac60a4cce2b011a4c8ddd4dd521b6864c7c4562d8270dbbceec91bf1cd7be926d6b66bf370839bbb22856d1f0c7b2b7119ecea6278793186c50b045d09a1aae7c5bd2ec54df1087cbd1d8094293392605321bd39ffdbbe510f0e8760bd35074c4b0453604ca1f5bee056175ae7943183212ad527e125d2ae113d83c5a4ca1e63e8d89ba07ce8fac8257fe1c603031a1fe2e41bf922d7ffa0a610e0b91eb8c3147262fd228a4ab54fb520b49c91ca268d3954029be8677229af3ed232628e7d3a752e66c2171d1746b7e31d2dc8d1781af454822f36b3ff40f7683fcddc5aec46b13890a6c7c9531f30eeca923f198f4b57112a94e34673c88c70bcf80ee115de27ef5268a753c6f827e71254b5bea2a4f27c8e0e2d0c3f72d051558700196e80abbdf452bd70116c24f635d1850f9466282ae761f1a38a8a0fb5a02a9e1b99df55616f0a7c031fc34f190dfe5cdd4f2442d16ccb49187823fa90f3f87dc0966c4cebbb7472d8184e37522acb165f5d3b508f6a62623def48edddeff361d5ff37fdfddb2b324c4f545bfd5cb98d258edee6ee6170bd41135ddf4c9e358433330a5b590b25fbb276a2284b2df18550270b32b65d9b483fc42e9610537f27715e9f451bccb73e1ce017aaa39b65db4e86c86a50d0379398e57e0c34fa64f73acc0d2b4e953a89ca2f8c01b10135c2af5c234dfaa17ef97941aacb7cce96cd05fb246b76f15275e4d2a8545e52726a48f269d1a558aa12588cc78919a5edf6c0e9e576ed58c92b67d00e4197905d74dbdb3700fbde85d26de20cc652581608ce1d1084b507842a0373fd8830c8d3f68dabe93fb19e3189e486840715f92ae4d916a9ff3424b45ded24780b31fb7f76d506339d9f9a545fe0547c675bde44a3b490bd3b52e3b30842624ab5e8986161be4ef9da785bf537954d3c716da5597a859ef7adb40fd8030611d3ac6581e424ff636aff72f4dcd9f315744a3dae6cd386b2f9945140071a5a49f05e8f979115678eea7d6d884a92e4f14ff94dc102355c3aaa93e02723a92417ff49fe8cdbefee7e6c5e952ad240fa7eab4c7941f6ae8d2a1086e1f2ca73eb8ca5fbe3588ae51bdaf18646ed04bd185a19bdad69394ac15d130297c0fce9d8fce8ea2729dde117facb274f9865ffb4f2c7248102dbd96767483cb7fb764fe667d484a3143db514f08577cad8bcf695b0d953e2a3c8710d8979952929d59c8b8ae62ff678815130e68c85d4714e832733da40b933b7133725a40a12534753eb4877c65fe4c75542f28d6f9e805789995adaaff6fce3929e6027338281c6d0c33aac092fe0eb1797dcd953fc1f815df794249dad7b28407c50371a8c81625f6e7e08ed59a98758a9859c41f7436f937885ad35102b0eea85f3dc4bb9a6260f4e091ed983b1009275d43e4960f9422dddeddd09e9990d545cb67dc3f1061238dffec3ce01376259262b4c32c6173a6f1e239f4502cfb0900bbb7e3b4883ca3c64c8ba91cfd80b2bec6aea25b01124ae11a56ab3e4d448038795ff62e9d5ea5cfdb99c5901a8b8f8731c772690dd964cda343bfd020e920b32910a68b433ddd01d117a833242fd695a54f33fce28b506d931adba499373b0a6182e54323f032f1e7b8bad58dabcffdd1cae831c70e87b2c6fee3494dedaacccfdc93fa23ee1a4273f16adbbbcc21f5d02d8645951b93287732cbca4c61a0d0549345160537501b8c0dfc97128035875e73db7eebec24813d03d11cbcc089929b0f6e2440a26d90cffb6295e8fccf65b4d676abb8ff66709913775e611bc843302a475488c9a9310c0c8885b78d5db5cbb1a919683cfd9bd010cf2f1206ab327122ac87d8e2899cc1ac684e72c91f2d36c7bcc3491b768aac86e92aeb106d22b3e85112a2a871bb8c9d0a0dd15c89d113910f8babf15f27a13b10200ec7078d362773f17286228b0d5a58d6654b0fb4f60c81ee581e507f17a044e6bcad4bb6ddc66bdde7d311810d79ac031086d7b0c334cd3a8a496591aeda23b2c0097cefdb6894b352395dfc79b74a6e4d086656b0cd9c95a48640cc8b3d188189ec0b98c8618b0def4b0175f11369cb2f107e89c4a67a75396cfcbe899334a5d5df5927fef2eb8bd836a27a2834a7ab94813d30fa8431da3178da4ae56caaeeee66cf545537ea260ea6af56d4ba048076ace08ff2a446080a6b688a916a13b43b933e506ad187b1f829a1d54ae261651563874cae19c490004205765b43c3cca4cd8a309fb1bfd7520bcc07794cf7c03d9b1d1ae0cf646534f5a97106925ee96dcb7fc1f74e62c01d382fde19fe027a4b9b7627c08e690abe3ab076f184210acbb4229d483f7471ad551eb614c35e019a8a894b5f92f5371fd6c457f135ae8377c5781a8f3a6dadd2c00697bd8399b6f168dd64b2d2d66d5aebae90fa5f904af9f950f450d8be919ae3f02cb5c0be9687560cfab2d2161db61e978ef46304de248383dc3a99e30573bb66f873ef1e54f523ff8ff79e8c05e7f8143cebd1bdd9d2186ebdbd3b66a0a3dee79475cda2890720ac5bc33f8cd3e817d82bd7c52c34d491e1e9d1d307eec17c0c7679af3626e7b96bbe6ba2550f44de7d1d88b3e4c220b8f185b459f1f882a97248cdfc3d42209ff44806837750b3dd21ac5891254f6c7f6938aef3caca6c55b633770772c2c06734f84612a59aa8cfd4f347267e631658cfc4ff89cea84550bd43699c1d8840655f39e3449ea0d2abba1d81196413302719bc9b39cea85cb7db6ab7f00683842cc480503004c1c819ab80e121d9d21f46f362614a5f2cf80cb2c8d3fda82447cd0155fd7e0ec7589a6df2e6614671071f0f956143c762d51172da46e9f61e588fbf74cb3ceb74bf2ce4ec4ae26a28245f98ae91f09cae77c4660d6dabe7cad33ac506db3000d742f683e08bbd0a7cb9eec72a1a976546ec926b9faba5084e00d66475a514a73f01fbe1e79c0ee0066f4b724e4977f3c1518d28ddc918c573693e9b3fb69b426df0640c5ee42cd5533655f9a82c6843516298d05cd970f34dafa886995545c37b3b939e0dfa3647fb3f330bbd3e69307be3d469a99c24382acdcac76c6cb71decb4b7b11cb5f2e63d112767a7d6467c51f1c0c27900803180337f463e64f507ce245f606f8c1f1df836c7fd02502bd3127424804c69f1d066ec3acd9c4374e857c4607b711f532867cef2c1c8a7d7051a440eb7a8507500d86f11567e2fc812a27e63e5599059af1ee90444497f69add7862b93ea050f100e48df7a578d55b6d6321e70ef7a7625ed89054ab010850912088fdc21551b89397c35ab582aed6c215e00d398a857090e2f7cac21c7b51f34054a45f36157edc603b5d6e76ce20f2dfd2c20158943efd2349560666ca38505cc6af776e0720af2d5f6a7d98f385854700fc0c749dafb597e94d7ac54aedf34840ea778e8873d6f1fd7f53de7c06327d08d34a03b38315efd8eb52683ec1f9abbe2bcf096fa4f379f41e09b8bc67ae4685e68ce456465b38892a238b18358714fee41da0aac8dd729e2c3f17488470648df81040272b2e927e896a4eaf6a11c457938421288ff074da8db60d37c6d022e86952341f2b8d262cba0c5a6efb51925517a8c817a152499ae7ee56d36df86253e6b2d93079c89fc922014b03da3941509e979ff8dede44165ca4cb698924fd12bcb02a35deaad608ff3358d455a49e12e944dbb11ac7e9571476bfa856f3bcf90ca9bac6d57d5c1755104b348d2924ba9b14e9ffb750cafb6edeca6dfb79d73b9839092032035ea700d81f19d035e38bdde754a5098dae1c163f9c473b0681858004ab9d9c2c57282ebd7e57c474b8f7aa091d1048b95e7ef887767f49d2a7f6b410922da142ab8605e735ff6ea9e3f36a29380ec43dd009d98d8c20f4052d81fedfee6cb018b2da59d63b5fc153d5b0948d613415a6b8a2b7338897188582d2930480d897d55bec899723b285dec9abf819ac7e6f39d8c35c484ca13f129fa4b334979bac7715bbf5e52a9926568f359dd3e3e000958b561527bbd52025918ef75228c423da41861396be4f829aa4bb6f94f65e662e6ac91e828d721b741d7333a8e3050f136a463af537ee97af4b42456d65e1e2324f72267c07acb88c91d0cd602ef765f858f69fcd44ddc73dc7c5f8825f3fe04affee769f3ab5486232e35df8fdb75db79721906907ffad83c57a364ab85d93bc03ace8998ede749d88985ae41cef163a3d00f568d43115992362c581745f723a2955ed925cfc7c83c5b5188812fa2dc016dc21844f923b2362afa5ac5f2a6c9355b2eaf724606333f152a01c330ed88f7028e716043330a280c5ee458f2032c8163f5548428ce4c529d487a16ca0e58cbf41dc4dc802cc5ea7fad6a50de0c0f2c2be49c3dd2806911ab1322a30acd4fd8937b8930069fc1a6de86f9ef90f407b2563594adad581b49ad1d19b30ad13efb0ddd8e6f26dc43a36ff8d14d1c99b073f5f1ce8923d3100bb04488b86cd4e89f7b9f5b9cbbb3f86ee03b498ae255e09eeaaba3e4e4d68f1ee4d50f699e460a922e17ea8f0ceef9794e944f128efe835f281a7662f959054aa994afa3982f7a310f46f53d5ffc07884aa91bbdcb3f3779ebdd7f90801e96222f56df39ed9c2bff5d4a11be1da7482835e494b0856ea7c695cc1b53acf3b2e2d1846fff50bf55be65e16548c4fc436f20c50c119ca8eba4cdeda8c7e4d33734a0355586629ca5a7c3591ea4b15428a81b6d91529485004cbbf60e75208579ac354dc705edc7bccb32f23030e733d3f549fbb841329a01f5c5d263ce635a57aa9c69432e5213b155a07c34fe19cee737cb993fdc82ff38eafbeb734f04f58d367e34df15dd6044591983b9b45d4ffd87e2a6b478c7d1e86b4b974991b930370d5eaf5edbb53c3dcda643fb992b5fb0725a8aaf8a9e7c4012311f197179cf1293884e2356fc5b624cd46358d3c7bed1fed6b0305114cd11675aa49c1b9e6569817d34fd60c1105833d78dd00117284cd1722074a60655dfc428072b0d2eb881b93d6c367952a4bd59eb902032cfbf9189bf65f7bff592032c77d61dbf778986b491e297ad0da5b367c8a10c9071b8d509b246393fe04a290b3e2291f04eb750285674ae3e9c7b76a01b679787a4006836dcee956185d3b0ce16c4567fab862d3634b93079305008e2f99ed425489bcf5447699b7a7212fe2196d3999b39191e750fda742c6ffb5509e3806f38edccacbb8bc73c96cd46f0f400c4012f1205813d69a48bbd1f55724c7de917ab56d4188716b96653ebe4fd1b6d5d252f5599f9c53a4683ae60c8c31b86982f32bf73401a328891804daab93a155140fdd41ec87e392c8397c9ecbc48f26acee4e3cc279cfd67d75b5e0b6484274484c18f72c2532b4064cdcc309df796c802c17480428c3b5a5467b38aabce03de2a266c8a22d3b0158beb913d50615a1002fcbaf91edc529b0cd38f35138bd71dcfef1b6b90adb4e68a594de40199724c158db9c85ca78ce3a19378ee90dac98b23e1515324fe18472a4ca93b004295b7abd3c146109da707f5ef37886fe1a8966ff1e96375fd64536eece72ae3433a697492955cb182331ce72e8f1804efee93b1929338f" ++ }, ++ "ecdsa" : { ++ "addr" : "0x5e13d369c8adbd8079272b624343ee1edfa4a560", ++ "claim" : "0x197e55da82eb1daa23a5478ed230c6d0452d3c1920df15e10a8d37a7430a7f2b69eb474bfe0c44a6e4a55db9d5a0e0b74549c044ae22778ce30f47a9fd1eba4100" ++ } ++ } ++ } ++} +diff --git a/consensus/common/src/test/resources/aere/registry-v3/n14b-ecdsa-missing.json b/consensus/common/src/test/resources/aere/registry-v3/n14b-ecdsa-missing.json +new file mode 100644 +index 0000000000..360ef92ee2 +--- /dev/null ++++ b/consensus/common/src/test/resources/aere/registry-v3/n14b-ecdsa-missing.json +@@ -0,0 +1,58 @@ ++{ ++ "description" : "row 1 has no ecdsa link in the switch epoch", ++ "chainId" : 28001, ++ "requiredSchemes" : [ "falcon-512", "slh-dsa-sha2-128s" ], ++ "ecdsaRequired" : true, ++ "previous" : null, ++ "expect" : "AERE-PQC-REG3-14", ++ "manifest" : { ++ "formatVersion" : 3, ++ "chainId" : 28001, ++ "bindHeight" : 1000, ++ "count" : 3, ++ "0" : { ++ "id" : "0xaaddb4dde09de5718a906d83be7db3d58e0ae32a", ++ "keys" : { ++ "falcon-512" : "0x09501c96d2f5cf0b28fa00c726e5359c5d36a1fa069971f854b7d914fb2f1295e68b2c6fa91d82f7d287f55ad493c87320bf7ca2a5d5e79d7212e8a540c166b588dc03f73b83be060525b367d9f40f5e77e7798c60b6499767586770722820b3b9e6013cad3eab5fe5de96089a29f34919a2e9ebcb3fa03a3e714593b7a3356d11ffb3441ab40ad94474da662a71aa2419dcd50668cd5d8a9017662cb60998b34ab5b7929c58a94d5e133ebbdadb2b0279543067f76bcc4cb6d7e0a5edb7625467e3ddc92a01206e1b8dce69be31928687d8af4d26633a07e73c2830d5299b878977691cf65700b65b6ea2463e51b6136888c544545e59fe8cf190a7944e215a785b682623c95a79eda28e25e0e1b91b49ac89deaec3b14a3c431d9046a663170111ee541d81b43aa91f29dc147c6fc97739b3a63fad1ca84843d0a65b8d9396f28e9b11f9a41453ab18a2309ae8db03253a09fac8f0cd634c76a5e938a44719660944a95dff056cee43ea99592c3899c2880d7181ee3dd5c04baeb60e1369a69430a66031e3cb10e392622f5246a71761760cf417dcb40ad65f60704fb74ad26f26c3af7513a42f806895e0298c25c049187aa536e0eba21998912e621846c2ca0e323744ba930a29850fdb385c8241382296ba28dd4df05ddb1e61fe525949034b59929a784406de240f8086b4074825f419d5472a28a0b157500be37e9f64897db2b645d3807c48dc143266c99e7cc1638ae278772493a2a4ecf74e526a514bc9119d7129c5a0d115a450ccf4dce05b76d4b6149fdab028006df7ec2209923117abf7578a082128cad42aa66b69eb63acee4456bebeb537ca57bb3d3487f95e4f06c5cb29f292d3b6284e5a162cb83151cd9ae56aebbfda150b7edd5065302ccab70892733a1e096ba0da5f51b42764ad23060eb197d5460425fd9c7a26e7dc3cfd40eac3643539feea72c9ed41569111a7976d2c345ac2183fa2271b424526709fd9aae558a23a5cca29f4e2f31629746a71d904612e95ad9977bbe74fa32e90fac62625838cac49f50e5aed4e8879e2ce2e5651c4f4ba0c96583af9e1612b5ff1a6fac5027c0a308815e592308170b915b4a2de1e8d48e9a5730680ea9db8f3326c430241153b3b218d5347d5c843570cf80ee813871ae10f6b8ce4ab7e4c5197045e85b1cb4977f44c33eb85894b6555b4bd288a50c1b656936841048983c00a01631f10a84522cd613fed0d4beaa4aa4b3e9f30c324108d909e59a80150", ++ "slh-dsa-sha2-128s" : "0x47a0b70170dda85f843607f6c6fcbe6e6acc7c22980c108996a3fe72dc9f61a6" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39c8813cd3b34be58eaab900555a67486034b1923e0b00e435661230cab85f07690a5958a5f5e9c84f033a3dc2039a5296443093fb7fe8d41895fa73be3fb34cefc6cc36750d534e6a3c47307294694729d6cdedb633e8efe8979a9aee486eaa66136e342c578761241192610185feb2d3c196bea0e79222437b6a8e08cb09778d053b29552df96507b1cdaede8e9aa7abc18902f29937f30e7cee6868f349f7ae33738237dcaf86b8e8e01238f3d8ea6fd4090a8161db65dabeb5ded5499e8cc8a5b32607abc291b36a4b34b327d30cdef18c1825232e69a2b09d539ed84dd2a4756efa64f864c563943b3db825824f294c1bbfa2157347b0fb0e7f8a56ec253b39ca9b6cb1ef7d3d7c93a6cb220a7dc50c365905ea5a71575c3aeab25b33523e4fefbaf66137f45c3d96db719a12d2e2d42fbd6cdda58c5a1b958b28c2a8f2cca297871a147dda92a7f008a359027a9288e42ebcd6ea9542f10b66dbbce6e7bb914206122f866d9adc1c89cbf8bbad9bc9517c2ea9018b61d4d2df9abff1dd9f3a0a6faa72a449af9c97e8c4090f3bbd9824298e61599c13c7eb89677c0e845ca2907c728d9296c24e96b6a348dbea7cac62671c9a78a531463614ce321e28ca2f093094ba5f69881e6cd766874622ca769ea556ae757cb7f9546d99f5c90c25e7b8e14f3b7f270861398800b0604ec2a3374659277a23cf6131c63148a41b05b3c06e2a98a268f1b9f0df7969addef17179ca2261d3c229ae3db0c490834564c45f7b8ff6d3bf70784779d75915fb2e2d5bc147bc941b9e249af188f63f39b028547cf080b7674b228e20a600e3b167610f814daf105226f3c1ce5e07834fd33dfe46315546e926fd5be83fd4d47ccd5bb8ae736ac745daabb59c87b9edf9a45c9a1d1617ee84e588f27d12235c59ffd9", ++ "slh-dsa-sha2-128s" : "0x0e8f9bdc22cad3613ed07fba30ed04219b9528f9b657119e2f0886dc71cda4afa7d462fe8bb108feb58d998b370b2f7e162390713d1a17eb7de781a604041cbed13d00effd3b24f2ff87cac74f61e7b7f7aa6a259dc283485179ab4bb966793be018c4bbf4475bf7a69e600a37246908f662813813d4b0f4f83757f4064c5c0713870a0b98b5bb99025dace06100497fda8c73d7385d123afd4953961066e7c8544de3fb620ef5e23174327c2b64089b3fe6df3eb86e83b12634a0c9cc0d7844c894ba6d83afed6becb6f5abcfff397c5cea8064e5e153ea4253abe599dec1614b449329ebb25861b69a9b22228d1a03ba51532ea64ebe7603474a15a2806d3dafa29d57d27c5fa894da673b85b4674ce835fcfbd391d328ef83504101432bbb0c83d7be462b265911aad862118af6f4cea4df0f1dd38969c69428fe438d59d22736fbc7dd5faf6758905b26ec4c99d71e4b8fcc562a694ead91569c9a916df5ad693cb2ad0b7ae4c4f3c5b7322f56612c5449e0339dbd367460c76ab89b6f44942cd33f35eaf33c2ddc0c6af793556d5202fd1fb0f9fa1b7ed45c6ca68d904e476477b71a0bc6ebe248c9b4585da0c7bb186600691269bb4c836667a6d73a455b97127d898b7fae17e1acc6dcc3bac3ecb14da131d5f8adaa64b054e2f569d9bdb164792038e107848882de9bbeff295905c2af68d4c6dcc8cf718c2de872ab6b3d18e00d527166f8ced642281302e2acf4cf4489072a2dc3d55ff8716619cde494be1763dce925438b33ff1b91b35eb511645832720ed92552d4880ae53ff6516cfaeb1d48c923648e502e4038676f7c82e532ea713c6b9348c80ce3c5735f437491d3a8b1765294868c14123af2e9ff61e394216e630c71ff976072d2a1c50cfd8ee1ce27aba5bcf9aaed4a51521bad5e5d5e66abc7a95b215fc8004364aa4df2b8b97b14e3950f521b6327a55fdff9139fb0bd35237b022e3aa128d36c8a60f4621d25d28c59a97418c7dbfc15d900ba626d283632732631ec4a948f66dd9db3bee8c2cf60dfdacbb5ad4c0b2b31f8428868cca035e79c95bcacaba40a9351b2b44cb29753b6b9da0a751bd5af84c9094d5fe91e97501d4f075392290e8516ed5e41b41b00e09793353707fe5c1d942395074637f3ee0a0f105876d6f28a74f9558c5f360e98f047a99af35ccedef8d5cd299365e81e7e91f28a01eb265219e21aa7f7ce56b62f9d2a61560f9fa39f2765f5b50920658100a638aad03482a687905cd27dca02f1deffd1bc49a1be1ea7ff1a505da74fd932937d8f6a8bd75ef456d5f7b71ca5357bc66db6cf14368c4faddf4996363251e6a6113ec64d642c319dd85830d8b4c7ee1437ebfefe01f27709ba0c412c266530f5b6bbb005994774e8935f1d91069f9e7a8cd2bb7ad6527768473affe24709c10294eb588aafca85b379bedf0b142b109e1b186e635b0625c4e59576266acb5f71040c44035fc9480b13932bc657cf332b12da1cd7d5c3977f51d5fa742974cd256e8e3662dc698e0516d615d0a05ea9caf12338d0dcb6151e07f184c9cbd5e59bc40b12ed6372e2d6bd42aa0eb6c3c888f264a8c0d3332631d4919c921cdada6bffbd01ca5445de0779f9723577ebd7e33ab0e5f577843aaa6cb8cb5f0508c33b63913a44d02b76bbb1eabae325581738fbddb5d4fdef8dcb8597bd29c6ecc631839118c44f66ef8dedeca65e58941c30e0423c40bf064b8d19d28dab3787238781d492720236a7ae0695ccc867fbb1cf207ebecc64f84daea66b6745515b9ac9b725061bb9958ed79ad6161318a262528004401633d47a023c645683e36413b8653fa4864fe98c501197c10226b1732337842a1322bb788a00a0de86758139c2d9ea3c5b26bf5d7a4a92cab4cb686c580e3e6cca488136f0da9279073b3dbef9519168ba02588fa29cc60d02273805b425b919a7e2e89c9086609982163e09d5f6eb9c66267ac7be363aadd4617d398d4bdeca37a838d650b0919faf13b78642a058b1bb96b2ed1482cef9bc6e8b2e061e6815936e15a9c754353aaa786ab141e95e5f6c464a41b8bf29e28e764abd638abcfb342b54d08c15ba7e24e6fcb69b844e16cdb5cf4f50db60ff0699f969d8e68511fcc9e16a58e100f80671af6b04ff3edda3a4f05f9183c0c3bb7c1061fee2d3f04e33fe75f1354e6de54f582da914da0138e8565ff45ef52f638cbc33a24bae863fe91e58d7c5da34273438f15e10d4f59db16e505620d97d3fa4862a4097a659925d0e5f4e073103ed29a600b051b83b1f3a21381f4b871c18d262d7e43842c34ed80661438c064aa2fd858a8f3bcb035b5e942baace7b50e4de5a73d5c51fc0843cdc163958a62d333078f4c7d883bd7055a602e04c853f9215c9d7f798403c007fcee124cf6099322629c449ad4ef84b7356110798dd87aa4d98ebb47abc6cc8748dd381d588b77db7f4e7550f6ee1ef4360dac6d6c7037a65297d4a0ea7999a5632b90ad48fba0a916846a216941fbd13d62ab36e1066e24990c19592944078435c52d7717b3556595b645cd2359ad151dbb67e92b14168cac12fb2cc5422582a50bf6e99f116751171c9b78744ef719282f1b84bf95b4092514f4c68fb82a1526e0942ca50e186632cd9b0b8b8d91e84f85e35f30f815601798fcae676da6a2d38eab62f22445099694804a36a34142150fb795afb445e78c241f0b645209037a8871cb5487c975975ac997a540b709e3df6bf208d9d8017f9688b152c9ee2b934f65393de8403244b7437108e6d8c973aa723285555d9eb92509b1747977105cbac7fc33e658fd51cd374d21fc2bf229928948292c1698db7934d0f9be44b137514d0a5fbb659bba83861931e03698a61cd20a449d0358a5fce7f288e18bb3eb62b7ba0ae75feeec634fc90fc45ce45239c5e3179309f0c202cfc53d9f42a617f7aaae586e7161a0723ccebb7e8586cd40e1fa12d3ee89b400dba8073b0080ffaab1182e8243afd93318df15bbf3ce179f21804fbb8882e855ef9e0739ce1536d8ebfe9856aefa9874b4e102e705a40ca4c3ab0ab7df63ba525189b518796590035ca780d348de49f0ba8f28456ca6f3e3cff7e761d961ad98b8cf01e855797c88fe2f811e41e787f3e4becb0ef42ca3b9979356020b447294ef295543e0ef512a247e4d356bfe3deacca8ddc5255e6ad047121eaeafe61d71e7f31395cf78890add4f8c688e4eb065479a63ccb3d0c09028bf60c700fe9d19195c26fcbd4130e6feceb52e192a2aa2343c05b43b276f51a7c55dff7233ea512942291900d93315438a96af08e25ea5b9ce656c54e71ed60d1eeb1665ddaa9e42378c930e21d93484b9a4099b7ddd71d983b4c42c6b1f62907ce84b24321422b08b847f1ea97befaa4ec30a794ad7f340210c800cf185ee2c6c72e844cc5671964e1e1ec58953500f149f0f0f25c34d5592de421c2e31535040020237b907e86d753094dd4532e1ab9d821e7583d4a21e1041fa7ad711f29ee3721a2aec6b0c46866a2de71ee850d8122f722898e533848e2bb851ed24cff9ca83badcfad88a171b4be064007aef4d759d93ae9b67b446f3c6fe504f5b4fe851b8312fec86b46ec3cfcb36e0f682e65e117702b888ab8566c9cc716a3a86106d2323c0f7f20fbc1fcd110bed4492a750befbfcbbe16820077dee281bcdf14509b93137a3998b2fdabc2a375b38857bed12bb8a9c67bcae7934d02d6ff89620fa8946c8aa524fde99c12fec0e25bd79788e2c15fc31fa3f27502cb952b9f9482580cf18ecabd92c55113ec4c4470c4dc06d8ca27a10474594eff708209e8f376b6f17915c2966dbeb0e35ac2f02419692c0d232e133b3907059d3a56ff169e7e61915c8b1067e183337b40bc1136241e862eb3ab3f2c6a72b18511c4107ed063d1e2303d0fe6842fb01c204d1bffad7e90bb44a365e62945a7f631811c9c37ffa5ac39c16b4835798686da5baa8e1eb6aa76b42f6b86863c30669486a175d6b3bc5bc47c5eb05b240bd921007fa39506c6605bfbefc9c8c493973bf3f0767817fd8ce126a301c5b8fba79628a9b3a03cad0c491a5f487dc5e89269e5d3bcdc2998a136a012486c5bce2e6c6dc595aeee2ebd5a36dd06919396184aafb2301d1889b668c4d701c7ca01b95f9508f47d4c411cc0397c244ed4e3e3ad7f97d86b6f8834b13b1b2df0625e6b4eae9e439815e65baf2da767d3b1700fc461fad6297fe4e8ed02bfb65b750c2d2801b7308aba9657df3c3ed7d548687f55e85c22343d1db343bc2dbe222fb76fbb3cf490cee7a99ab3a337c626a148fb303b2f8651651588dd4859fd65c95820ee2af85adf4e8fc2c03828ea7427e7c6b0d4a1b0ccd424df6d1450ee436c01351d8b6bffd4ba072756315968845ab7976813d93d0f0f2be1c00faab3ccafa71cd26c5837e87292870cf768c7837e18ddc3c513820c660870b339fc42c5211d33d892ef22b475cea3be20f5e47206efbfdbeac208e26e97c400edfd41f063aaa6b85a0cf86e23fb11274b405f4f796eb10cb97e70783909ad492ad9207ae7b3d204e59d69c886f91bc82a107d0be3ae85797a7cba747b8e2640ec49384f53c785a84cf8de37dd4048dd4b879c58768bd131ad7226506113c446fbf13d769794f1535d58e9c52e23c1bd55e13c647d304e297d968c759a378f1d594897a026e3271aa6b4daabe174d6a35665b35193379f0ee465df7827299c18e1012ac69913a0a5bb5142e99b051763de3e98d5af8b62133e25b32f4f12b787bef7e21dec42de8e4d99a0adc8f365d8cd3e6a5ff3064ca18965ffdc6b383f7ad08186d735a099bb0ee14506388c1a37f7a766d286d748d404457226b952ca6cb3f317b0f4399006b5b8c6eb89f6b8cfa023cec4d2dedde3e31b9a633c0888989b44ab182a5aba30ba78640f477ef1202f6496fafc2a18e283b2e4e8bc60415a1c9a7fd68f15cc1ea0299e3b26f5755ad9f13481a0563a524c6735942f5069dc1d6a070b3c3698e9c503f67a11efe59413e937062668d3439a5dbef197d24ebdc79944b17c549b0648af9b1349cad83c2a0a9e55fd893cffe2aff4626662ebc5014e70baaf7cdbbdfd3f92fcc5eed863fa8afd87f88873f726a0a2eafe41fa81edd5833f5520cf93b0fbf0660e48eb0258d313bafb87dc9b0d0d9349f22fa2d960238f67457ad644bdc60fb5eafd1c88dd2a74db4da0f723a03df08af6c64883f275395020341d9dd3c7fa049ab2bebb4d8af2bb8dc1340d1a80088c4b2c26bfe7314926ee64bf239306c05dc2ec6e6c5e0ed4f6dbe51f5ee09533f558d29ca6fd27092c20dd892c89c83223752006b23e5abecfdc733aaa59c8549e89e5ab0eae1b44189f58cf9cc18de0c2a2f46a9235fbe42c641a890039cf6aad820f1f844edc24e69bc3bd0c22cfad3804d876edf5491e88cf891c347ed5f24464f2df439bb30742e1f9a4a7eabd9346c6a5f93af22e67becc494cadac82cf9cb693acf44560672cb9227eea2575f90b0e28431684ae12ff2e86fded0be3a099f9ddd32a7285531de8963c9a03355f1d9cef88d7ed9b842d0066ccacdb698d42ff9f8a4f000b9764a9aab1f3146f9f95e6636fdfc9ef91c4d060a54ed7f32167e7ac50590dae3a2904d5d2eeaeff2930bd4cad7166fc17edd2c30e6738157eeb0b441491e5dfdc17a7fbb2bdc6426b2cfb26cf2a7e20013f1b3e33a6d6821928443cc7893f7e4a5268a8b94a6ca6097d25be17b214ea4301e9a723194983bbce286f4363a53afd9e94dda9c761481d9d20c7687a2ff85d42436b9d557d5dc6c5e24ea21d5231487df9fc7986100664edbbc51ad4921c5ec9fbb407ab33ef5c3b3bc81f113e68f38d73f0db0261b656fc344d2d23b93446845d69cee1704834d98737848d405f52f5a7bda3dbdfcd3af3881484579d2d2f3ef976cb35c9cbb76252f2e00019363273489b39943d212ccecc647413c56de69e0087532223cf9b28ce3f77fed30bc3ae6a0842b546e0e1a8b6f6ee1ca0ef1b78c3ed829af817099426f94a447f67229cbca3c07b7a8ce547c5eebcf168248e0a0b9fbeb398e5ed2d0dcacb441f95f9e30c108c725507e459d34c1ec01b67065e5e202d685502d6ff015d46c20bbeef1db38c29df7df585b95d79f5687474e71fff162c0ec0c96c94c507f8a0292a8c32168dacd2fff78b5c7dc145e10fee1b25c478172af8f3ea132fdcad75dc22856deb2576a5ff3e8911842c811d1d57ec203c77b82da3658cbfee18d140ac341d38a30f1af298cf60f2a88d0dfbd3e079ae64a07abb4947cc042925fd5c64bb5d4467589f8c495b0097073c081517bc4504dcd7442bad7e7acafc894fcf34f535979364cf5e908a84e0e141ae47e2ae4dc95462b4f345b12b0629502c7bd65579ec66b2d0a951302ba6da1d1176db6aa0c0ea1fa88195dd2248990fa4aba88490b1da4ea405649203f6ff6f734693f40deabdad59ac62e3296cdcbd74061474dd7b63c46bcfe6ea2b0ddb0f7e77fcff3599892c82425b05ae7aa1a2ac1dfddfc67e11921ff4f2c8f6297881dd5e38ccc4076cac8015c59cdd6023ffbd62b887b33ef8d917446a8941d9563acb66a6226fa4d3f2cc21604c080b3f83e73c093d8f2f7067c392671020c7a7eb6fd0d97af0d63032a3116c408b708d4b2f711c1134b88a91aa359608550f0049af2bb97688afc4352a45c4f6d30d4634e70e82515ff1d5f77851ee857e42b486d5e1f3e0406227dded6c5f47eda30d94f44d978322891dc729eb6ae95d29d22c8a5d649193d5d2aaba782fa16ae488f645a7ed90a566e182f97bc62049724f4cb5fc71f6bc7be57f07a7afb9933f6706cc83483cd7dc4182768cd35bc42f1e9b54d5454d3a17e734475ff58fc66d75419d3d122eff05f7b0548188682f1318ec32c5bbea87c8624cc1e548bf18a6b102e7a43e6bafb579e4e84275fe07d8c63ace449a44cace5d9305ff756cbf40e5a6a20334d5b4a74ab0483e31593f2277e90341fa8036496c2bc6d2b7b10b0b354c86d666d65cacc593d1d7349e71b0360d823453011ee16b6280f5c048111b99b185af99e9d901d4eaffd8a96b1ff394b66208ddc1e7e53420fa965bfc4e630d73ad97b9c5c6ea884c619bc24ac3f46234e7d8d35a12b0cad7220d7a0945cdc64fee9d8852bff872c43f359e7aadf8fa3de3551fb716704af68a18f79d03b3c7d90cf21eb4bbdcbb4004f8ba15ff0bbd2d0918ee78e9bde980e4f3cc13558e6fdb40ca71ad2c10f5e5587784bacc6b925f72da12528216895e0ca4b350d078fdf534fe01bc86b45e0c8e2b35799d268a457f8768ed782dfb56abecfd2b9db00cd10e189c6164f82f5ccab423277e3465ec72d76b696cafc1cfa9a7fe47d142fd6672d9c5b77751b40801af07fc53b1c9da0fe6981ea75e066572f7272baef8fc54bfa7cd71cd0fbc5d6cd717e9aa07808496ad2b4b4005a320c9312c73385afd61193581dbae99df6c25f1b9da17093ccfb108b0a26c5ae4963183533ce2f0ade01bf5e818af613416433578522b1b1e5aa7c791570c8c8b26ded266399116f5789a8233fee128e54ca8ce63fd56c1a146c3006316d200e05715993d1d97907ca83d7fd42ef7e7222eebd74f9c86b6cefc82e614a53976272c8801bdcfd882e34d86b39142ac05088a4c47010a71107bc72a380bb3e5122981d1795256beec20a0fe568002d79a4b1577903fe8682f268eeeed0a97861337ffb6861bf378eba1e0957111c7f9fcfeb55a95238005b40e13ce40efe846ddb86d14c9ad2c46cca74baa364ed08da3a3079fae3a36346ac949e2174c661b8801a051423e95dcab6a0f9c965e8744bdd0e629bd3c1a1241e99951ddde184eb8f354209f24c04fcf10fa8f4e43cb55c922c28be041213ddcfad65c86e1ab9b615f91d5fb11e4cdec5b7e25f8e9811c82c2ed457d012e4967b555f228baf4f1648854c624e0525e36e5f4d1961bfbbc3621d79bd6bea72924d8e0146d0965c239a768b417ea4c33237a60fff2760a9dbfb1113a37b01b598f3e06987d99518bd9f1ec96cd7050863898c8664f793ef29114bbeeb9afab8ed09358d1227d7de2aaac0ab2391cb2013028ca5f4d1de6425ec5feb17d95df358572fa27fcd51d14c363a36bc37c7497a0f964a6c004561f68349f828d30d4633e87bdce6b6d92384c9c1c540c8295ea621e9a8006a8d7c163b988853071e06c78f1b9a0246db052e8484a65cbdced3a587e45d9e2b49a5501590cf768d08b6a043971110e9c9dc96abe855abbb7aee2c38bbb77e5c68d61f01f2376b6122450117240532c7c840e3739395dd6c9e80a432423fc5e3a6dce9dcd58eb418e16d7aa507b4d67dd6fe2af4042a5c7398ba4f87c650926084efbfdc9430a4bc2be544880ecdf7361aea06a25e4f592104b0d74312f2729a4db5876b675bc0fa68f6e41e014b7caaf6f49b8ef704b6243df410dce94ad2c51d328fb90b9cf2f5df645015f489a262f57a5aceba40a56d343403b660928cd7a9d165f4a5bc289c0d28f33dac85c9c2a5c79b5ddd22c744a0388a5daf4bab84d7c77685053c912c9a24b5a0664c6253febbcf552c4ff38bbaf2f7e0c9f06e69a91cff9138c2745b99367e00ff6b6a920b1812e17ba44175c033df0e58d1b5c0b7d146f861b62e812ecbe99d638219e0dba4dd88089005977bcc90634c4dfa95f87370d905d32f613358fba2efcface0b9a414ce33b09e271a647b911843933c5d1008fb0717ab59739eb8eb844a4b34bb1a8f635c5895afa285ddc43720e78dc81eee7db822896bd9bd6ae3e7fe2988ba560d58f02592870647b94aad1dbb0d0cb60e28135ceb72e0a6f4b7893a56eae83f9d9a4c549d53d17c6a00f5d6c266d23e7a1d13e22a5fede3a7082dffb34296f8fe9f3bfe525ee1da81efde3aef9b6de8457a10fd4340809e1dafbfb9e2719c327a3c3a4c51d4d5600e8a01ebd5c537a4cd7c4519e963de06de6c83a9b968b01f79e08b5415c5a9d6a92a633d6ae969b80cbb2cf4d6d1ab2c3b94e7c12df27ea89bff4014d92add41a3e961006a194ae3ea4a6b38c2827f6185ae636f6846b1c8401289696fb10c765fa93e58d068bdcd8c9dc95df572f096d65f5de42bae639d41ce7e1ee0f48ba4faf856c0cdd728956d7e4babd6d9d6389ff41d76c5fbd6380f351b05a37022dbce0a6a47ab7168c82c77a2810c80b1882f825ebf86cb7f6d0f54025fddc9b9120802514c797d1d3968631dae95297a857890ff1dee408909223d012925dc08b7d1119fefca7466392a019d4121ea76c8b4c3bd103a820557e4b2283e262af32f1edbffaa253c47d5873bfd0219b8be86c7e64ada2d87ab6b7f428a7d8fb3ae09b05aee71054355eb83ad76c05d836a9f1a65511b1553927ef1b19ab1576d7185af61be6104de1df218918179c6321846085a83bd1217aa63d0b03996ac1fb4018a8ab54fcf635f7d5a8ade95894f0d407e5d4691920f21094c6f632f1661402a0b3351f168f16a13d3a31ad48e89230cffad272926487f36c7a2584c9387623df6227be8c96088db4a21c93b1c88ee756e960f60e614b30bb6ff757c20f3674a7ae7f6ff6a9115a0a6d444513ccc0be5dcd557430e0ee8db3ed5b3e8c405110500b9bf7f6eb7748de4988a1db94bcb16fe33479f64762c53a1e2965363452063d7bc14386ca7b4d46ebcf08489c64ab413ec0f1ddee8719f5fe978d38438ca3059961ecc8480908cfaf139d88db2facb5e7a88a43a67dcb0f97a17f9bd5b09b8369803ccc7ab6d41238e59e43762965814c10c36fa4b6e61bf2e83c0243f20ee8aab62dfa9827aec06f99c5c565c1bc75291292d3113503a202851c26d1a8bde54bb30f0301e555374b71e278925a2afb29b0209c08ecb89601bf612ce811a493abe2bff78e7fd02ee13c5db6b3edce7c87559410b9be3be95465468e33af224d6508a44728cdffde4cb14fb96a0d2ab9c7f597541f9963775c32ac613af9beab89e0ff7a5e35613751061b0511532b10b3947802901505c8e33bae67ce0e28da760af7e80b730811bdf17abfce39d35def51d73a084119449038c2b0f1c86d844123c6e71f28b7038053e279dd11c088dfa11c547a4ce13b19453e88e5b74962101412490cfb68e21d8952db509cd3a814387b67339fd04ddd2163177589146409934f0eceb10db2d90a9e3f6691eb75e84d5e66bc3228baeadcba200f3d11e0cae090ffbb800f5da7032c35ab572de55beea37258bee6f191addf01739a26efaa612991cb2a3c6d1bbb03de0ee1fcf9b7f6c51e452b21c0819a9aad93162eb2dcc189bf355ecd2c3e504713dab24bfe3ed86a4194611029f7f6216cd469fe1f7d35d56b6c8c2045011e238f9cbc0a19b8914d74329e2472f15d0b7d60511814ad2736d6be168aac01868c2a675549c849fe05e05a76f077130b46896735db5490277b76bba43545de6b8ecb53fd20398eb94dd884951fb48d5690ce4bcd0b836615cd9340ff0cdee1122743accfef343811a71c7d14d1369fa49ce47784a6ff8adc26c151edd4969dba513ade6a9b1f009e57c3d6aa845ddee275169ce58e1f04b564ffb6d0eec75f7172e5e8fb814cd702c9fbea8a783bff637db8667d4b6b48a264135bf60acf335936105abacff0351ba9aeac88e9522cf7ed80069822a7db1a5d8221d9492e02ca893e1f15965fb82a80ee2ec491027bbc8906e71cf931fc21e1c0865ee06a79c023929625b4d232c7b3e2e4a4e5dde28fab675391befe583c95dadae71dbaa43e09d8d65ba36d148aa85d1a2a35dc51719ac0311ea72c1237c78a8b1542c59de3b743087245e54d3111c585b5e5e7642f625c8d44c6d9cff50d8d071f6fa573df937d9e7457302d8b293d8fd94ebd3023c55f8b260c3454e93f58f16d0f451189bf41c9f9b91d3c3918adbf98e4ca5aa0eb6314041521ef880ce18f0ce296721a06b329bb5fbb3024e424b46400e03caf0105877465285fcb41a93844fb90b7fc1924883ace6ca8a37c9905068c633761163affae39d0ba55b67fdc6bcf0908ee3a42af286c" ++ }, ++ "transport" : { ++ "secp256k1Address" : "0xe23c5bba38d809fcb2d3384f210e9a6405beb498" ++ }, ++ "ecdsa" : { ++ "addr" : "0x48fcd978ac4d42ff52dd81fcd17e93190f35e5e0", ++ "claim" : "0x2dee91bd2cbfa906aefa3a8ae6e2de773f55dbd28e77bc329d28215183068585601ab9a7f9ff0c48095407474d502a3af3f059a666e5ed1e27468466d69914e801" ++ } ++ }, ++ "1" : { ++ "id" : "0x690a7fd66157e5b777256ea5214f634f61b3a72d", ++ "keys" : { ++ "falcon-512" : "0x09a6d094d9a3a0865864e9a16b477236f1ca26c888fd0c918db331c87a478519c41085cdac7e6cd0d89190a41a3bd6f4d6300995d591f5e22a7b7147caab1f9c7a85a4ba74d47c7b227326ac17535de039a7e604225d3daac7f75b9544654b73f79f5825825ad6e6c45d13e6d385a644633e1c8806d3a0a551c98f032583c95fb13997e52a6b02192d26b5a47fb22ee52999ec92b75c70774a4ae0481a79113ac72346263e53d5dcde708668d317dd00552d5a40ad47e59a501b10a50bdc52c5c2b2c920fa0e3dc9b8eca54b10aa5ab1168c88287dcf80ecd880a8fdec85b6d63a15b9f453845421a5d9b898e6149b60454828eb9dad6442ec62ad27ed72215014f3d17539085ea3f668b0a9183ab96e9db996801c72a0920b02a249911924f181e8dda515d114beb83b075ce7e7a0902a6971e31420ee4921f5cfc123f29dc7775017aefe99a7e326119cb925f6f603ac3bb137313609498d5a2000c426cb332c82500dcfd80d70a5e2d156844a683b313266af6d60216bd9e9998bda53c0028f387ebd21a5fca6c0607d54b1e95724746d15f25f16e45845926a83c7598646a0a0d3a8f8307c1a401b823f1656ca41e5499684150a954318da076af9131fcc93361d9bf0ae035f617e02cb5e1224a982b3591b24013ff80dbb61160d2ba4ce85a4260c8a3a3218e0ec869796b1b04a82079cfc0ac26da03b04a11950b2a3331ecd0026ea9737bd20e6ea3045b56e3c71278d2a8c72c8014b769da9319e19dbe762b1943e5a4be15aa84d0da831eddbb10bd05f35d55b6211d02a61c5d9247e69cab6c112acb568ea51f345a5bf16f84782e04220e217722da71d634e1a68b796376c8a49a965c592b87d06702fe42dac12da108d24ee42a109e8e4cfd3bed6ada5e3de50301696bab0564292864f1b9f47d5a53cc0c5f9cc3d57051065fd57064d08764892ef4c4a92b475184a4cb4ce1f3a0e6da0402414db5a9db34632b9717586e799b06e870b81a330da7be6a45ddfb000fd337a24a29e164449f96be015818c53aaaf09b9a565d7d9d735b9493885e7cb49a5f1985977cd6824fd62f51d2a1e60289dbaeaea148a44dd8876cb58b8ca2f29f6455f354e4e76aa13290f2979b78b22afa0e65c696c21497e94bf0141ac6298aac70b5ea843848a2264fc057abd3593cb17465e06d41731b7153b71f8f0f7a06d362fbd09845f0815794050460b41ad003c9396a86eaab240555ac8c75f85c0ab972c1a0b94b67b1aee2fa3", ++ "slh-dsa-sha2-128s" : "0x2b2fea4a0edd5dcc2f653eb2dd000aecd87deffbce8818aae72d7862b506bac7" ++ }, ++ "pop" : { ++ "falcon-512" : "0x3968f2999d69a9c28ae792a90a47363e689bd4b349e75c5f837181fc7b16d3d04489bbc32252d750d750417770630c5b65b88cef918ad23e33892a58458e9e63ea591596d3b898f65e1a5be3d36650c3d9834e1ec725426960d337b8f25878525ee3c3798b5afc9add5bec82c8e139c59738aba9ed5f42d11c886472e81cedfdb5b910eb73e884e0d4cc218b87cd9bcc0bc107af586c65b3949460a25892d9607efa341f232e478f3c9fc2d05f324ee6eb7bcddb72af371d47c36856f488872249ffdd322d3de7d12b62b1ec595187b5b363e36cc714b765f0ad5616488300f6e56811e88e359365d5698ab123b917bb32f56566958b154f6fe052b894ccc1fcd99d65d19e8117a8ca4887e01f36f181461a433fb9bbc1790d8b14e34a097b149f0c5c075ecae3501944935f3caa76f0b9370ebe6b90390b4d059f9029ee4af98dad33b9050877d49c3d4f2beaa4b5861a21af95b8c52f9ab4b0eb115357f5b1d25fb66a36b9baaa4d6cc5a4f5fb5462432bd82734d7393cd22c68f52493eb3434c3b88fa255baae5c46c650cae17ebe59827cd6645c6d377b3cdee3aa6a758ad3a96d103bf6ab8ae03b72b53f3aebdda359288c32ff5461a158962924a97a24af29f6c976762e8de9363485ada49c445566e71ac75379aaf7bf190a81c671115e842b5280a05bfb2ef3724bb74487068d5b5ab2d089ebea7ffb4381a7e96233f0915f295d3b71db872393bb990b9c74717bc3d72f6271bc248e54828a1e090f6da56de3643b083e9695db7d0a32bb42355e245e5cc2ed57354d82220b449e10cca1cbf6fbe796d141591d6f71e4eb6770a3c7dfcee509c3c28f2f1988eeca61833b6681e6766790c2a6f043b4f67e145b908ba7f03361cd9d435d054e11edd9667e4f9d12c2d74f2832b619", ++ "slh-dsa-sha2-128s" : "0x39254afc16b1dd8d4fbfff766819460253653dfc6a8e29abed55ffe91325afd578ebfa2dbe74d46b48b381e69d269b5bbe24ca1b85767bd71c744065fa47c646e3603b44261731b50f2d20a7a327e98b84c5ece73697739c8057f99d6ecbc54cf891649fa78b7bcd824972f3b27820ffda3629f481b1193b922cefc907bde3ab1c78b5ac97ff26986f3a553556d0b158e936450b4f41bf006c90a9758e0efb327f67408a7b803ede993522cd9042db4a672c89d4765a0fff8c6e8bf6882a8de432229dee08ae13def90f9fd0a40c99f3d93873a41d74871aaf407b0927a817b476eb93c645254bbc77d131e0bd35a2541248172993b1064d5b26b921396c8c1664178051810961039b15790862415338806329a45a266aece5904312afb1cfbeac1e816fb96256fc6e2b059c25af1966b0bf261bfb72afd8652feaedd6e0e4bf829a75188708ac9c623d4d6699281913bb563b96818f9307b66f7cf4aa9591e30c65a0b0885c22b5d17ff610f40bf2e0a9a32173b2fa7d66c14784402885d84f33fc75afd8f743cd10f5ad6dcce5b33a8f0c0365de2ce1b69aa86df2482a2c2d3746c6f0ee4e6fdbeef5738d809f6b0ef3cc703b0d29e93e198b68d62a5be657e69c33459fe4b163a5ecd72a90f1e53fc00bc8c698af7ae3cc5b07e36cb74088066a54138d6df4ef6e159ce5924b6903346a5fe115272cc951e8713d4b6f96f78d67a542c3bb402e69bdb3c2b06e189186c227927b2aba52b29c14e837b37798321fd000ed3bc0e386ad6e5d3a48494f57109322f0a87f7dd752d862dbf772498154804b09eca84c305595cc1e6654b1b2e94d5b88feda176aa144d3895a249754bb2ea99b2efb4f61b828f265638866a49dd3437c70016347d5aae64c79957ed394a85cfe06b10b98b6e83801728645529537a1102bb04ada4226688594cc28aefb24fbb0d1a60c7b826dadd23f301517e862c67fd88d0f6a5ac08e7f966ae375b468e57f01521b43fc24c761838c174ac106c4e1f435b7ead5e79aa1b303222f6b45c5515d497d8e7b05901bee96945652d304ad9ebae2153321885f19e7ad08c9da73ccc22a66c26c4cdc9360c36e307310714ac44c80887f42a2575305ef649378d76d297dc6faa904377b2037618f23b8be496fbc680645dfb80a76bfc060c6b2aee4ac5537e79b7dc7deeca0ca38041dc877b875cab1a297190269c987dcc46ff34e5bc154e2572695e463542be79d61fd5e96a4be2b07f5beb71b882f99de317116fd0b36131a88ff9707eb25594fec74cf76c2859ba6ba2b968d41479adf8857f4b0f4a26f49f0f04fbae0e2f3c2ab6aefdf01855a7a5a4b8bf516f4551a393a33d3920ca3ec403b4d37c2106d777e3d5dfa768614513885d857ce95b9bc3b992808e7ad71575e5e91b8107c5802043b221c74d73c7bbfa7a191945bbc5ed69e20016b16e2e2987818cfa80695e58950b0c1bbb8c474f861d1447161744c75d99dc8240338c43a5c19a8a9f46d80f6b4b6c1cb57f5a3350bfc35a0522f89e3470ccd71a458968c629c93336af6b5b091f569d1fc9492eb6b976376b8ff19ad9318f5cb1361954a0471419b4207dd9dace8c0545e74dfbb19ce3fdb5d456a1c1bff7383c6fd96dde3a92daf0ff5a315714c74711e3c05e0c59ba525c64ebd17fa20f8e143c5931b3c77da193415e6506c2db27e0e773a6a5b5d47ad95760b8d471d06d5dfe000a2d47e6e4e6abe7219750f1f7892f4e09fe88d13c2e3b53dc904ad58eaed856a4abb0c10830b96bfc1b5764f9e4b34b0072be314608fdea8c5005d40ef99806d4d3edb72e73541fb828d4b2adc38855e09e974293de25da6907f5ea97810eff1be37f88ea879e545bb5a70d2187edec81bd57a95c0314df4ad08a864156579d50826d0cfa511d335ff722e246151a7afce94126232f6bac89b13c142d29e7521479866e35b17c15f16ee89d798ee8bfac5868e505031586b81bfadef4aafc2ecdbde649f63e07eb6026d09910d9d3613a9871b5d1523cf5958124f96b5304d5225b4bbb03aeeef87753d0b6ab51a287df1e9031f56f755d3fe5a20f79b7f0f467fa97eac5bc09a1adc6ec285c8f80ec5c184b8b5eae326300a5bce0b1d757c8e4f27ca2822e73745009291f0d9032051e15b567511908f3ec68840cb6ec6018a9a0e30f2e34759743ef0bc9e12c9b32f29f4b70a998cb8893af2dcf17e0eb4f48e7ba367f68aea5516e7248c8be1d1f896d7e8446fadd9603012dc13126878300f0868bc512221154a5104882621f831e60b49d04fa8a701256b3a413b9db4abc5af10a3f8f4c26cd0b3c2f55a58c9380143d835b759bac7fef824515a18d79b6dbd361541047c79653ab4af5473b7b7e67a6755add78d5c14c0a9edc6c7dd42c3d0359d9f2f6961f8930458a34c4f12478ae45c20969c4c18654d31a7ae73902757b3b8a4eedfd16d6c0d22548d7b8ba77aeb4c1e3f3766b6ea802ee9bd92c5f98d00be80c15e7e3a82eb0d100436c398781607dacbefa98c87b3558f363b3ecb1ff313655838f864c1b2e0f6d6369bae4eb8cef98f564108ab2f763e590a9e9201f4e28ef1971438c30f4376c55cfce9b9910f448e31d06c2e456eb798476d56a890660e45616840377ea0574d1c066ae2fcc46f41cfbb511e5efc4b5c60e00e4846e157bbee5fe3bcd77408e3bf721bf871c05971a70cf7a13c782bb4afbdb1ef800a414260243fd828b67f49007eaf60b3e32f4e2b8186291075a0b1c0a528abb9da7974b3b1e8b20d337161ce234db66ce82a88ae1dc880933343961267cb4932b36aacc5f136cb474bbdb5e4c4be4cd74868775d80317bfba00ca4e58a39d04e63bb797de366c45efe2e356672f567ed1f7b2741df7543d6faa7227601eb7cff367d5a1ff320ca71fa2a1a42866239cc3fa5eba400ee4060266a05b8fe1e729908b95ba6aff8fd76b5e7df547df62cb89f0605c1207c869d7214e4e6972ea6e47b18235855d6f28265a737b4f64f0d215943f13d219292036c1cfc46bc61679f034919e4fea80d882a5121cb3096a50f2112eab265ebf75b607b93e14ceda4e08152221bd368cd1503ce375188d23514dd0936bf980d4282eaa6fe8f38f5eb00c34e3557ae363538a2c15b560b9f9322d1f17446e8f3fd317126986afc2c5e9fbb96f8ca7148f53cd75a4b845a28034c8679baf1f5406564b6e4b8fa8e681b5a9d208f3a1b28e84d6d52d4baa152524908d50d71d9c0d11bb5665c8a6bad669dbf303027bd0d534434f9e76f2c300326e25d00bd8d3bb1debe1c3984961c0ea8dc547e8cb83a8f3b044b673f4a08882d103d6eb143a9645a9a00fab6f1167a2c09015d6ff2dbe4aa4025f604a63eb32330f832162b6dd9364f4ad6afbd86c8d26f56d7d9028dbb3051c85a0c86ec0d7961fd6008f87dbe8347fd5ed1dc4c27285364f63650f161321daa83ad41fbc3412bff800c062a78cc5caea330cd58e63ea9a9d6de2ee069732799f52f49d513c658a44a2122b8427a405d706f740600f855130a0ea720f76b3111dafddf0e2ebbd13f60640379993889089ce508b1343f485457cb8e0c09760d3199b4ea940d584417259e41f2c66853ae4235b6f010cceca3859952b3daaab55da14adff0e421e862f138872c2577637b3e12b00384cd32fb3b9c97b0d59e51f2488e379065d79f5a834b076ab5b35fe4c47f2c4c4f43e622527abb8f682fe9f262d2883fce5c9f16b7566c4e078b67611abf72cb8a0263ba12a6c23b1a04458c759f2bdf6dbcc460bc5df48146468073b61aa5ab4a9c5f6c006f54f1bfdd85373f33af29d68580eba4cb6dd88054c81b3bb7f2be8186e380bee0b32a1b84ef6319798079828080361bcc27473a9634c23652ed6b2b2c8f8d5a6721551c780870f1787726b121263e74c9464a76282dca27249b4532e49455a7485e2cda4ccca823f62d3b2869602197a6f1ecfc9d92ab6e231996e603e81e3dc648aebdfb900a3d929502ff0bbb3dff813660c9d5a417d857c19754ee04e50f1241831517fc2d2a71c5e238a944992cc50b7106aabb5482fc7e0a2e6b5b11bb6845f34ede98a18d5f07759e61603de502b5eaabe59a4d2c69f4b0f8e73a9bc85b8950a54bd91bcd0366dffaa0df736dbbbc35d6accb5ab8b22a870374521f2035c1878718d7d3b025838da75d8bfa3ff36b2a10a3cdef1b150abf3b6be95a5c096a921a3eced20f509dac4ba43f2f515af2b65d3b2ebd0da2d7a58500157a666b387b1814d0a3e84f64d0fc44507b0b6792c0c6bd90ab62e0f75b66d50b6f842cfdbecf1fd043d642c5d5b5fe5cb68af62e6e23cc6f0f9b1cf3cbd0233ce48a996296b6609be1c9e7a027cf76615dd11208f1fde119099352cc17e1c9a22f4b71c3e628d72b620f3cb4bd40e4294ff8dfe19480b5b758b874a737e6092254638a222c83aac52fe0f66670454c313adb0dba2b4e95741d27104bbff159e999e23103c00470a7feee6f4a35f764ec81a8ef520cf1e8623fed3c06b63c022e40e7638db269b8add119fec50456b33224c14486f705e5b3339c6f38aa4ba6dec8b098c27447185ca50cd70772e5389ba703a4a9f8649946671a238e1f005aba0b3a18c8ceda9daf4cede6782d27931c638af3f6083b2bf10ff0a632ebd4dd528da3aa2b7a8bddff2901d902b26d518a058921eb0178ef08e24f7075f77ea0c0d0e72f29847ac7826230c0ddb5e7fc8552ff92c007e9141f51384a12e218da4fbfa9a7a4a1bf266aa975949e120db1b6755ff04adb07c66ba9619b40396072e7cc01dc3dd56f7a2f928a82c8906be416f6d5c41354881f9a6c66a927292f8cc2887aee86e90da32fa3bd9d72bc26dfd334f943305fbe4b645df83fb72c565f61860a480dc0f2f3360368ec3715c2c4a312bd2653051c8f29fc14e0c3d1f515e04b75ec02cac2aad8d411306969d9a8da08c3477eb6201bd54c6ee643d87a89c78a5c8ad48590b7a499cc44ccb812866a4c48ec2da5f1e0aac741464b26988459f3724ea4cf103c27e4a43e5a5fbbf94908878894f8b62995aebc20e632d924c82d9669f64b2093cfe023cdd1542c8f9d19e5e7ad6ed7920ba6834cb0cb91bce48fa94be47c1833c6ada4090509ba38defab7d56dde8168bac8021fb5a2aead00809f1881d53d26fa9cbc824488e16062fd9f68726c837234a82d518e3d10c9931295d20d9affa5fd18c0b2dda299cf1d6fe0c6e6959440af9b397f3441bb9881ba1d2df295d12686ef6b0bfe52fb2bef06620721374328551040d2fa434b161648b058b74df2a7ccacd7609b93421f44a136079c79a3e63bd3b4f79717f3c121ceec2c3918464f5619b1a2e83a7709fdf6d1004b0ee51c73e740b20e329847304a82802e02170db386e360dc6027aa7ba1ee35d7eeddb41ffde093073d92899d568bedee914627c8c48427376e7b5d5ebdab30e58147dac5638090e9c71921431f025f1d4e3ba3c68437555357c651336b326c9c519544363d5f4faa91914195314cc873ef97068d928a6b4e5c6ad70ea7a7b09b3108fd5696aaab800eafe463ee52a3f29e1bbe8a968e84b762484a13714ee260759b4492b749c46ab6603c13ece34e301c13bea57d9de706edc839f55b432b9299d2d6643817cd9d32d0d9ddbdbb23acef51992b62db024365ac2db4c432c531cc1ad18c807cf1ee39dcd842aa9a09b232cfd09bfce33277a8ed09953ab3b5d24e5a8a02fb4a02ceed705185880ecc47cb245665cf640ded4015b4afda053a5d1dff77e390c8105961cb3a954c28ddbb9efd759080dea99e94e69b03b928c8667fa4797dbb3cc6ed093bed107c817780f60729036f13346f05491fb837ef1ffc61be7b61d0b7f8dabfd49ec24cfcee088de38daaae6b4e740ab4faf16eaebf89962331a99f17ca5955b15dd1fa493b91e7cd218aebbfaa7d348b1ceea26951209137448caa93fa466ca32eda497a5b9a4fdbd23a10d9742e74c511a1648d00bca3ca23abcd4f18b7cdeb362e020c73888b76b83e70d26ee358c06933f77d1221a8ff0647200e451e971fe45c23aff60a88baf46f59a0bf94e99ab9337b0336ffacf8e79db92067d2b744134cefac1241dfda288f5c6ab293df7469ae0926c166e999ac99c8871e571eab03f82de73e9de2d8f4deea3724f795480cd47e304f27f2567cd94cbed52e06f1f1cf7af2feaeba8b95927eff950bfc26aa0cc3e46ec7bd5d4aa43374500f8cad4f153cb586620b9a0deeec2cb12ba48bbc8655c7fa70ccf94aa6891b5cc8a3c98b482d906d72e9d425301d0cc6fb4ec9c4a5bcdfdd74fdcef68f05fdb78f2a1c5ae32c28c43ee900738f31ac1fd337ce95966b3f557a727e0c3ada6c6aa61219d92fd5cf68fcd9b444f6b4fb6178b9c74238d2575f442a298127f282b5ad416cf6a365a214048489139918f93ec07f2cd864f5482c418c7336ca4590a7da8a20d33ffb7be19934c80b64f4b982a55b129f4896685534b83251d54e46a2971c0bf49ded9b13a77ade3de9a61f2204a46ed9cd7bc444801381994c8ca5a66abd70936f8d11e2a2fed78fe9fe8889dfcb979c9a3f11f2c2c1aa371d1e98c4fbdaa95d58c6b22410c0d3d3460077dce654a1decfc829f117bc407d06ad9ee6aa06bf818ea2f25312b1cbbb5de527ce9b5c5ddcb0df21e3442ffd149b24af5e59eb4d7e18f68b02b26e57fdf23e7af4fde3e672990295c37186ca67b2abdff6b46e1ff106f041279b61560ea2eae64649c65be22f9070c3239b0cf7929b0778c43dae5391d8d3b8c335ceac672376588a34d3b9c61833578e8d5a9e6e9f72748d860d7af98f7616431d1ae1ca20db3db6ec99d59fa98c25a1cf478e1b4a643c2fc9d3e482d56bedb1b7a1fc9c3e788d9de281c7356b82e3c9e1c9414a0d14cd07fea5364b6a22dcb3b69b6f447343822098548e3ca7e88a83187db145bda17f7c48cb00e6ce36d53e2d1e4c169569ee3fa03620a7131bd5c033062bb82cedd0d0ebc1025937b2d85a3cbcf6ef4458a57525a66244be3a62b582bf2b88549431cdce09f6407e1bee83d3fbe205f585cc7cf9c1eaba047a01f51e13bbe0715a9112c451f1daf6074a1af051d8b98863b6fd03238ebe295995d60e7a26d2f95a2b4b0d617af299133bf357518b84e942bc36a88b4030d91a7067e7a2ed7bbf4e9abda8c6887ecdfebda04dedabb9ea833123507835e0357ca1513b471da73102605ed03297b5e3eb7d3bd01c670f992a7f19962b706e8d0ae0f073638d633b34a1229b6979b8e90f2a536cb6024c644e1f7ef211451dc509e061b294c28be188c96246614a1fbf52db8d9a99f7100c878c1b9da98ee9e9eddf7fcb386061ddf46807c60b24d665f0fe7fde205f91021bfb87c8f4c89b5da254d185bda9cc2f48303b483ecbf934575aa45d0d58cea64662f0fda4d97790bbcfa237984cfb45a9cd611b533dc0ea997d191d14d307c68db318aee8f99544fd48fb86f041fe249a14263e6657a5ee732f7c5c9c97a8924bfdddfd75dc67da65042e711a3cc144f46d10a1a9fdac1b1b321eacd235299a1fab390df24acb739d61bd60c6907b9a3827958198e6e2b5a1c90cb9b44cf8db9b6e45f710d7a39c230ec9cd855af797555fb1d73492e29d17da0b6dac59c2ccde0715565efa1f62898c9b26438c60fc3b9f859bbd33a8e05e1d3d5a762bf19bc7c32cf7d4c6bce26fec6e5c8c537608a1c2aea2e1e5cca5bdbb45a8ed048514ef3d298e7dfb9c5408d941ded6220a44c184dc90c922a3ae31c9248c5f31627389770a59f9431fd0139c5ac0f08f69151a75a5a6a0355b7beab6be9829146ada371aa5791c861dc77598f09448af20deca73cf98a399f35c36f1167ba426c6cf4b8b9b8a22b961bca83e45bade098e20782a9f70bd54fb8eb6eda3acd3a5bbb553438cfe37e1f7fabf15729d6bd562cfe379d586181b71b3d3c4b360852003c4363a8d473198130642972eb3434c3a5ca9b497ec7000e821c3419aae75866496bb1b0a9ac6cf92f799071e06809f1f3f904cd18f32629e2093664755803f62f45942f5a358cb1e925a8694998cb14cfc52733c356cfd739c3976712ca7b007e08841639da14e429c102a8fba3191cd36c1c56eb06bf69afe3f2afc4ebf137c617faacda6baf5cfdcc6462ad02f63e8a5375288d0de5700d0f9f4ca82a65bfdc405d3f96fc663658f0aad91305b86ead3b21bd6561a40db0f2c5b0937ba5e1ecbe91e9c50b1dd6bd83a8145b033a7bb6a4ad4896e0ab160e8a52d39d2756b1c8d8570f7081ba217fd8803954290788882befde24b4971723b0ecbeea14d23c92eb6a0d7022a84aca072729d7ab1a88927a25f19a2086f846a44a2726ea26cf1b69c58243e219c756d06c361e1e161bdff0eca10bd30d23782b3374ed421f50cb66c9ee063ca622fa78c8cede932848f0f8f91bd7a0eaa324377c109808bd66ff463a72389c4b49f2e349be70d07fcb56b28549fca65ad853d70df66b587390febdf6b1881cce6c1ca9e9fdbc9f1ad68ccaff97234325d3c972b57ae5723fd73f975ba640f90e717e9284c111b76367c6797399452d37df6b8b8d22ed5e7dc1481a415fadc06673ce4eb6435d31acb6af68775436629a57db7a0aa192310e8427468e8e310bd3426b7ffab00110324c0c7e04ac6649b6f167fa8b928b3fe12ac162db3f2bc355295650fa2d976c64df69a8017034683bb4bd4baacf1cd8502dff20430d48c907107acfc4e29c584cb497b7a471fbde90aabab25290d853b8ebd2c0d49c2c201eca42a68a15879cf391671946319427b237472cd35431128ea7ab6d545617321592c07b09fff93e71596da30689b3c15368a1c3a57890e0ee5752bb4356290024fd1bd2ebfa19f7f3ca57c36d296ae61ec5581ceb77618dde2821460553ba0dd6dd68026b911f4af1be3986198966f90ab757aca2f5143f1937d09c3a08047b797781d1639db4030f9e59f8c5b71a71787cc84ade5a385ebceb1946177a056179aefb49e1f69ed0aa67901b2d6b2152b6c1fd1db67f358093180fcb8f96483fd35a87fa14825d3849dbf479be493bb2d1c639674bd195b5ea3caf49c2b78eb0e953dbf8fb909910c87efc6f9b6592c020333e00f83bea4bdebef4e107798f9a8e89fa5d063d69f88f31a53548ba2406407251f18c3d1ca6e392fb81a46107191e6d906b487469d0002afdb0f32c39873872a49eee649250d4d5d3a7687fde2952291c8ba78fd9b962060df12d212033303691b05eef0ae0e7f31b7e395576708d211d70281e9501618673afac20a93e82f060135e51b29132a0c9244551814bdf399b746651279ed135d162e366f39d40e3a49e907f72bf7c66fcb4ba75b1f447fbc3ae3f390ab4c10963d755ee188a9b0129416161995adcab12177976208e1c93ef48d3ef55ad22bbd97781dc7035c9f5fe25f47b703b1ed50dba311d24154ab05dd88ccbb5a8cd96d4665829c4dca5d5b22affbfd7e842ffe5e87bf4326f957392229bbc893b1fde9e4b2191a3345490d418e9298179661104f70bf6cf9a0094f9d37be98b82d98497573512d8f6fb4b0b0aa334a9120a5afef20e0379197ac7ec78da3688d2c9b590e40fcf866acbd1d857546522788d1f3ae73f330aad045c5bfd59b8a399ae626fd67d9797b32d6a279d42eec3ec8a2888258728f7c329c4efd0f71b730e57f9bd87204d40ac1ea6032a4b8ee3a338aad58c2f3c9795819af4cb652dedd475e5662d9c0cd23e72a8f4e86f1a63e5683c814a99a6595b779e5d715ac91ba62c1ae4ca1651581506ba80c2ee0d3f97b979758cfe93f373873f4775c882fb3b5815b9274595bf50488b935c82e0fb4ae4d078d30bf0843c89e484bf5a24d5de602649e336fb2b79da6131f96ef1b5f82cbd668f4599fc9a92b4e9ffe3468e39e4c8bd90531952327da74a522e479c66b7b1554c9a72a2e6db58fcd45588c9ff4f48be5ddc994913833b668c275174b9d862dbe8fd01535ff2bcff6ea030842ed3a4d105ba07feb0098e39f61a4cbc06bfa153c598c10c5de57caa413752878c7599e5db8482b6f275db2185c505bc0c9670fa0afe37031eab994120acb935bf9dbe6cee6ba336dce1b44732c4267ee77f5db890041e547bde486335b9a0b85d6640f6534d84b3729b3436ac1c0551d687ddd8da9abc18689e7e932d5d0e787ab5ee5f36eb53789b9ba2b71d7a4f7994e56b056d4a042bd2cac79ad12d87726ef8cb97342e616269e9f87493e95dcebdd91763b134019c0a76e8b12789b026ebd1d9caf1930010aa1a5c348ae2e6273c885ffdf8731b34d87c293e77e9ef14709c2e3b739dec85d5bdb8f5ebc9eb610240576435c8d222ae0c8ebe5844980560bcfd45cacff143a5c208add9011bf9770b7803fa90bbaa10f58d856250b37e481f325c538e473dee7863957121374bf12172321b9c99975078e43a0e1e40138f9c31d6dbe5e06fc881de840e64899c0cf342a806916147de3cc342832a9514eae9550d2cd1166e823f404a05b418e5f9ffa84352cba3007f9d37e5b00049d7c099346257fb53e86b919b45a9c6cd8b67cb3c4e383fcfd5789f2cc087d6b459e2a7dc96d08c826c43410b3df22021855c7d413d9cfe7ca79fa860918a74941e08511595fc9a3bec2e2e0c6dad05781c0a0d6b6609837ca8f78b0368b1217b121cd6ced8fa48dc131709434eed65523269abe95f338bc5e3fce0046ecb24dc1ad8c8fa68b5f9263361e4952ca1aee9229811a5ea85c9c4452235639d1eb8105ff88c048beddc0f7efd3690da8b9bbccbbcfeddcf3e3c9e3ea7b46a5b40098fb85a25842911e42a714c2dd0fab403340ddc1af9484843b33c7f5bed80fbecf68180c9b397ed85c51d39cf08c5c0336b149e6d1747360541e84a93224ae88c1b62384b938ae25ce17d656b9ae52fcd9100a40dd7793ca67357f3fb00621863a490373f0db49b1aebaff7284d450922f1e5243bb7fb5f7230dd7cb8db1e08893696908cad4a45711eadfce8b0b42a9aa937cd011bd5c4a8c3a2ec771b3ee4959eba5e4a17545d1c86acaa4805e4aad" ++ } ++ }, ++ "2" : { ++ "id" : "0xa5ea2fcff9e3cf29d0c6f5f147b67ff24aec3bd4", ++ "keys" : { ++ "falcon-512" : "0x099202fa37d5e165b88428d963d2a224b8fc82ac0e4b3f6a02376f18218d1aa7d0e910e71586aeeaaddc2a557124d6ab4f9a44b9cad02166413cbeb14b364e13956ea326900eb2900802644167639045d76bbc4e051654cff404dccea94402141ad9fd992cef7a8fa6478b3e6f8912886e9edd1b34c29385b7e964f360e0fb1600787934486f461c95d577d2bc74c4dfeb969b4798565ce0225ad27aac052290a44f844ae233e082c97e4498a31117ac9d02f3605c856e2dde6f611812161f89cb3a54dc936ca1e740a6c659405ed586a9a963b11c89b01746325e39e645c72b0c7e4491b36a17d43ffe38d88c601a5976f5a9636c964a012bfbce5f9b371e7c3b38580d81c6e12b8e8f2aac219f96245d35b4f4afa6c94015b055703b8c4dabaea4ce2577482f5b34fa49e56a912dd58d74580b1f94e1d2056594ea64bcdb696b0baeb33c86b6544761a3ead9ba9888cb1ad51f7027ee52b21e46c5eeaf3f77bc0af7efdc87acbddda7dca00b6acc665002c26447e5b0e0bb5ba261717c68dea7f1576462776954d7249c2fd0886f615ad50d53960ca02d581a4a25517c050ed467c7a820bce6250a9ba2e44fd67fb21bac843bb134c95360dc1c50d54b7280a94440d018181a9d6374bc64d782c84471b47287d8ea748c36cb83cffe053cb89a9e4ae71df497871c2a728ef210903e5b7f39550d0331e15637be7e28b3a2fc05b0a9b0c5a06f9fe81263c3a94403d6c288a561288ebaf788bfe271a578a1a795a85e9d452b61ac204b297090617286922376bf0a8d67dd35fd705b81260b7aad30132b965e39bc3cd64d154c4175951704873992a814814dae5c6bc1e89a83dd91144cd1b88f6ce449900058afdc53bb44bcab63d30cbd6df115a5ee8f5380a127a160e922bebf7b408de82514b2e2550a0931e065565e8dfc389d454823a55b03e5c989b09e3791f656794e8379b7b4b1617aaa9770366d63a657f71ff40c69b1d5da518ef1e2aa42366cfa38e448563f6c2db5e3089bad5520ec26105fc885993630c10db357883f588a5a384cd6de688e1bc3b1200f87ed66ba3d4a4b671b2a500a0436e0955904030d76577aadddb8c1ed21b027f198c072f654c3abb086e7f185980f49d0e109c1a82741809f8afd15ee56a887b392c5b172ba659144a7e99e25ba19792d2a3c0ccb481822839c8c70c65c0943a2994ec9f6085b7ac64ce2b35489a72dd6693d25f2329264e063db26ad4495e3ad00f12df8cf914fd846", ++ "slh-dsa-sha2-128s" : "0x686b5dae4aecd5618b95c3b2a5792888513ba49dd366ac39b7431ef403e04963" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39cf29ab9b80215a9947b975d8c6097e53b39d1483c885ff7527d7fccdd2ca3dafc32bfbc0a19c857fa8be7e52e25064d69c3b7dde6e77eee96ec77011fee440c8bca99a45b432b5468715a0aeff9d61375393b3ca40b9140e1a2bc2a52c3c8a85292f4c9e87d1e0c12fbe4d7236ba7921b8b83bd10ad554179dcebf0791c4b593c8a1bae836883d5094499cf2ba41b00c8c36c77a83466c263a0b01e773f08ec66d46e97caf0f9785943f98e159e353f0d91d5ab526279477a5509129f7a1b8b07ba82a1ccb4acd5be5e40de088f2600e06a8bcf35f54663279f04c74838294048a8f8692904d4f9eaab49635068df74d1f5ed238f6b895acf1364544747bb10ce333a957599594d766ac5d1a3ceecf8a6696cdaa95f824ace18cc551e1f4ec12f345283b366314515849feb5bf81fd203a6c73b5bab7c01b5c1131d442dadcb6bce32d6e13c5a3e77b66eb8f5b2912c0938d89ed9e20a455066d151a973e4509b03f5d66ff7ffb8b362e0c09b969e21173693d9977ba06d48bd3b85657119f9dc3533c91965ed81d1eba72b46cfcff285131f84306fec7b271a02dd22982cb6399a9060d286aa18a3f97666810937f8a5667c94959a4c27299d55e94564dba27ea3d98cb3a9db6197c842eafb237649de3fab72a9d56098b5c1228e70dc062617a8a6b44d46b7899dc1e53a77b700925ed1b438c59458c15e9b91fa2c2164b9661a976720eee2864efc5363d90beea9789a6d3b0628bf4695a853251c7f70ba1ebcea06cb35cb47d72d2340bb9412edc49626d6c78be644c4ab1c539d1469d1cc63f092ccac45f66917d89274af9c84d7f1108b1bd738408e499efa63f1a87c8730400ec19f9a59d241032e9ab78670e85e8da24310b13e89ad521ad4fae3deb9d438dd7eac72b79496c7b65061314ae", ++ "slh-dsa-sha2-128s" : "0xb8f14bb6630512c51d227c12a04ce7b316bfc0d255f5a5d1dec3e1ce5f5cc92927070079430990b4364200dc6d389fde89c78649e21d8fd3a17dd2de7444e77ac3e8c70eda15f2247300fd8e37e1e3c2afcc3e8dd674823106b4297ecedc924ca948a9f80afd7ca1bb85dc0e60e1ccd5d97eb21062b2fabfe94827b4ce5f0e396e5a891fbfc61bb827cd305012515d0a182f163c1a5ee3827aff289ec526cdafd2874c457947e8a6c8332ee7172197cde7388303992be248892e727b559c0d74a2c65d46b6686a48f0b814bbf031d1bde17f55b888e7cbaa7fd6dcf428b13ca43f77d80c3804bd2840e5768c2aa17f6dc773b71f83eb7803fd9e1f1a2e3e158f7e823e9667cebe136d333316fc670442a8c662930a00f72dd2dbda9b19c3dcfdd09c60ba55d9ffb5d5b3384d719d153566bc0b6da89d8dd869fb8c4113258014cd48a67a3591d37f9ba767ad70a554ec98bb59275ce163364915051411db73833a88cab0d3fdb7c491b8580baca2bc44a7bcfc3a51c28ae0a1fc12bb53b2b948c571397a348e664522ea749890d1c7ea7e9561596a3e930bca68377e4d4c0e0301472c8017c1fd5702cd6dd4c3f5881ec4cafb98967a57837c3869720268b61f37836d0c9c5ddac850a835318b17758a6f97df4d4966d516ef100b7e61271c45aeb89242ac7d2b8ee45a08f4081727d54cc08ec0f8af9e16bdf6f6d6797b9f5fcff9686f15efc4e8e34b363d562dba239908a3992b3548566a30cf04c424383b5bea0a5011ac620ee384f6363fca87daa30fa88763146bcfe0a160c071d79dd8de0b11e034fddc032e522b7ee47f318cc6f3f2b6c9b6efa0aaa9b9a9c1243750ea31ac01f087d5f4f5fb97b8296b0953a606c49025f5bedba6773804b15fb3638e72ffffe38ac20486e18eb21059f419b0af9071be12e309a953ac82c0a5a620a7b5c850027b39cdeb5d728522a15c1557e4ebc3f4f09914b3a99e291a814504ff7171c23eb825d2df1bad1ff29144f8a3babcc882258e8a6060272e95c4393fed0ad86698554515e77340ae806746ed859ff9730cd718c767e320ef54fae5e0cb8ba331bdb920229d6047a6db8bad147b75d376c3e72e06fbc6a542f51a312ec831c704099b2eb0f801b68631b464ef484eee077cb7fd9ea951a0307e08dc5fb4ed5a6e62048b010ede39efc5462ccedef2a4c61ffdff63fb3aae19b28ca48593532f051c716835a61f2fbbd5c25883f4a85b48d81658b6d7cc4227f90a81e961c5fd8a388c9efb78da1c9bc50d53a41d2d336232e84e3eb3444389caa3457ef9e3560c25033ed45242d0b4bed69fda4a4f1695830c843e63147b6c2d3f9bc2608b0671e59d827dc1e3876e5fc6075bcdf95223f73dfd11d64399333f7bebdda7f5c2838c072f7baf753a36a1ae8987773fd0ae5acec41d7666c84c1125190f432a4d82ad9b78e22d6536a8135d80a3d1715d17a673033d37104857278a75c2cbcbfe0159343dad8e98e42874e2b001bdb469c9faf79759c4cb3e3f2ccaa16bb29d3e4dc81627441d07469dfb9f545ed83d9c20ce586370be092f3a90b18f30866336c6db9d53e2e0fe1f98c655f1961997e41c25089a518f05270ce06cc115b6c2e9c04f6ba9bf7ce3abfedfada8580ef89f2fea98e8a19c58a0f3ffb89dadb05dbdf05c44b79ad5e1d259d5aa6086cb295341dc40ff800b460a5ac602a687d6feaf66393dd2be22264498509c9d39033aaa22eb248780a3661ecf0a05cb6629ea3d91eb0f68465485e8fa3fad3fc4315a118e4eb2ebc6e9b07284697cacf0257edf67c20b7b0311d3094f4647da567385a508addc9b25a66db1f1544dbced87886946989682b2f2db1363dc635e4cc3c67ad83bd311437d22d8f60a2cb7833c952bab293c9e20ec2b44e1f1f42a797421eecb2e9e9f5e47105b9e7f5d7bd796c360ea39dab45ad701eef0a76b7773c55e7af7909d456c213b0db14f985d0f73652bdf39a6402cee104a168749466e477d8a399469992d65656b607fffbdf73ca1bf4976d3a0c0c64cf5d260d6d3e0198f0b86c451b9ff5840968a2b60a8ec286c81fb55741d7bc9714177c9a77219d3a39dc1d6d7adecb7f8f85af366ed653cd81408b509d0f56b5dccdcd1d982d115754364ca3f14a6f100c54ed8ebfce6b0dc3de4435507acb0c4d974ae3f2453867a70d5ba078a17db34844ea410af4f842dd4a9879a7706b18ddbf94c7b43ba137f7f9b8b3924b4d917f8e0262ad10d083c4dd3b99b70560377ad31784a587cf0ea1f99d6faf0f04a909179f3f93c96aaeae014ea1e74d9d7ccd0eb5ab466a6caf8ed0fae75cba902ae05244e0dde35b8c0bdbb3354ac60875c454ab11f49e47e2d180db319a113a5869bad3ef4580bc7402b0d6bac10a7a4e81403634fd1cd272076074e714b14a6efefc902126df6091330ae387e161789198680b0258c341b6f3ec0b09c7674e9ae8f88699fb7b2f88fdf2461e11ad483ee11fe4e3ddd48ede0ef0a1e54a318ae12473993a8456dbbe8b5ded40232b8d2474a90424281830da7bb36091ebcf591947b04739846d8a600946c2b892e2bf3353b09b08e3a141f33f6ef83d022666d380da43991d3eae4e62dd3f9432678e8be1cd4b9569fa2fa84e95195449716423688aa920e2ba1cd41cd5538907ebdf3ff15df27900ba7ee09f3e9194e1d8cdc0703d6f38b2b887a89b10787986013f688f9a355c6a362f4797576ba022e4f1d1d74e2e31dd98f1b617b99516c944bfa5bb474857fe74a09976cc29c71a7f5b6fa529f3e0c00c33c2f0700064fd507461535a35c0dbc5b69d413fd6ae9af49ccc5d02d7abac88ef02bbd40475595176fa3b68d602469a89afc03359b032fc1f0ae255d623fbf9525bfa36ef98467d5eb2f80cf7c72a04b557e40995471c7adb8701409830b232693bf2fe905ef8b1a32c4b8fe3300bfc5654acfcde685547d5c1b0c213294235b31417da91464619822f3535c93549ab4649a59dc3620e7f4a3327c0e421c5d1a28a2b4c3ba8ab02950631ed54690cee35bc4147aaa8477cae505a1d1757d85251bda5fc91cf65772e1b543bccee1a2cd0c26cd33015533a0e72c815be8634efbb50ceb0ec3c8a3bc6c84638ae371809ab87eec54b934343ee9ed1bebca488d9399a1e347b1647d108652243cf2531a4685c282e0b9e526688a3ae1d10060a78467e6804b705c143d073af664cb72ce657a7d210240011d539cb3144e9411758a211238a872eb4be615d4813b64b8df446d2741db7c9f0af2cc4dc83c0febc41adb5d8413b7ce54ed564e899c0a5a4abcd1cb44c84505915afaaf93751b11bc8e96610216f71cac8d3c9ddb7282f0f864400bdee42c3e5645aea1aa5649485435ffec9e43d43e4341d967c9a89eaaea9cca12e2089f3de222e1a5034baa32372582023b5564909fbb67acfd2a40d5ba40de2d7a31cddac717f5702648c0346e197f99598dc83edda7ad335f9e711a0835c75d4c32e3305e4db9dfafe171181551a8dd5bff89f8a9fb819eca7a171d1be47fbea0e2838a1f1d01f4e68c3d0045da0ed7d3689c17319ef5f5d178e6cf1628402c40d2095c91f7bfe6b837d8f86c5b2585653beb650fc29096f13617ce6d36fd6107ac83c7d7f5a8639e519b161581dd58018ace297bddc3421d358be70179b14bdff66f229a50a329bc30b054a95d0f43e7914a9137055f4dda000357fdb5e2afa3d61b9816c03697168cc022f0418ee5ad7aa71617103fe17e7f47ecf7ef9bf779f157eea74c3caf3821791ab628fe8cba64c12d3226877c48b746d725c46b0ccf5a18f869e6680f1e5ef3c5e7fc2a18915dfd8bc12676ab94ff4401ed22133ac1e1ba0c0352a30156bd80b63eed4a7fe9c948921e1a9843127f1191751312180b75f06e33694853a05a24ee30cae0b02a0be49db16f6f06630ced9b5e57cad548dcff70b1620ffb17e8bf8c247a962d6b2a6fbd4fb3c89e3aa4381e15b92f7245ea700e76ba99678f4b0c998ac90bf3e4b9ba5b52140e15e4b5a38e25462c1b61953cc2068d0b9ebe014db6b8fbdb2fc05751667659f40ba1cafcc2055c364116a058e286f084c2bb73096d46f6736de541b750ad437c27a92ea51baf3478837e99faee73f2a2745918f81547c45f2b7083befc6387a73366c175d2be22314a1fa73f11571395c7fe9df062740c58b56b4982240c63b8a0d5886a3ddbf6ffcbd705d3bf3713a0e1b74497b8c1f34e204ad81b63f27cfa5215d275597599f60d02bbf6cbb229088b56c96d73d09fb3c36fb3f05f4266221984fe8559619da67bb7314ca66405cef4bd3086940c4a7346243776a6fa128cd9b6181d8f584f482c502fce3339f87e4fc5e3593b7a0a64c19fe76c51a29ef776e478ecdd5e093b2aad0ab3cff0baf73f4e09d63e9ccfd4aeaaff147ddf2e9f1e3e6cb3bc9757c57072a1a8076e179e50b0a03dc94de86fbb99f0e92338f26b6ed7c863830f325d3606189b80c8df5a763f422f26436f753168b53bce965c562c2554081cb4eb42d48daf8573206f818ae66d62bafd151e9784d6a9304996b4b82cef081af9b106b42ca4b6b0b2401dc21d8875f9801591234dec266f1f218959af60351178049b487b2784183349e0a7ab361f575fd0237d9f483590a23401f9085b111ac3d740ff4c3eae0b7dca3d149243e3b1fbabdc7431a579652d522bef7023e1c6579d2f6852f1acb9b7f20e3956af8dfbf14617f14981f40b1b2430920be14284dd5f2771f73091adaf9179b8396c6ad2a3579befa1e323177fa2598a3ef80ff5785dc2677f87e9299c6bb16ef2b2080e91f6fcf1b9189e256985e631a05cbfb6427eac995e683f494751f7ae888bb0dfd23aad7fbe942b8100d4daf62b6b8e4d647c818ee7edf0d4d64293edc3b7b6e08a8b9b71a7c38f55ca76593d35770185637fb473da423069de005363ec25235ce816f4df3070ff567f919f47dc4fcf57c168032ef8d7e3fdc5a6a1dace2513fc24f0829e8e4b964d37333febb1eeaa7b81aafe30d16fe64b6ac037ddec2dd9b372c657120df4372504cd14be89d3719c5aa6d545030423fc50e277eaa401e8bb02d70b6614e9768a7e42ba9b35af8f9e3f7dcf175609f7b91a16fdcd65a151c0e85d92dc8a06cddd1ff77d150ccb62c612c90abdad156ced839e837c79b79f456156a28c45f3287cb86a9ca664a13313332a1ed9ef4b3a3df864eda7bd55a6d8705567bd8d1d732f65a324aa6c77f6dd82517d5274343a4e16fc8f41f5a3809e9f2cdec445b88309c9d1de684032a10f8944157a3dc3d4d8d59721f4f9cc0b0e1e7a97b7b066523f7498e0902ac5aa462d9bd096e13c14407bef96b59297391032a4aef8c543cc8b60217ddd5a5d815c4ea1e21625b52e2323b42b4851b0bbc461abad9b71805e8b1b2a16c811be69140d3a6d32d7aa9d5321adb57570fc2e62618cac60a4cce2b011a4c8ddd4dd521b6864c7c4562d8270dbbceec91bf1cd7be926d6b66bf370839bbb22856d1f0c7b2b7119ecea6278793186c50b045d09a1aae7c5bd2ec54df1087cbd1d8094293392605321bd39ffdbbe510f0e8760bd35074c4b0453604ca1f5bee056175ae7943183212ad527e125d2ae113d83c5a4ca1e63e8d89ba07ce8fac8257fe1c603031a1fe2e41bf922d7ffa0a610e0b91eb8c3147262fd228a4ab54fb520b49c91ca268d3954029be8677229af3ed232628e7d3a752e66c2171d1746b7e31d2dc8d1781af454822f36b3ff40f7683fcddc5aec46b13890a6c7c9531f30eeca923f198f4b57112a94e34673c88c70bcf80ee115de27ef5268a753c6f827e71254b5bea2a4f27c8e0e2d0c3f72d051558700196e80abbdf452bd70116c24f635d1850f9466282ae761f1a38a8a0fb5a02a9e1b99df55616f0a7c031fc34f190dfe5cdd4f2442d16ccb49187823fa90f3f87dc0966c4cebbb7472d8184e37522acb165f5d3b508f6a62623def48edddeff361d5ff37fdfddb2b324c4f545bfd5cb98d258edee6ee6170bd41135ddf4c9e358433330a5b590b25fbb276a2284b2df18550270b32b65d9b483fc42e9610537f27715e9f451bccb73e1ce017aaa39b65db4e86c86a50d0379398e57e0c34fa64f73acc0d2b4e953a89ca2f8c01b10135c2af5c234dfaa17ef97941aacb7cce96cd05fb246b76f15275e4d2a8545e52726a48f269d1a558aa12588cc78919a5edf6c0e9e576ed58c92b67d00e4197905d74dbdb3700fbde85d26de20cc652581608ce1d1084b507842a0373fd8830c8d3f68dabe93fb19e3189e486840715f92ae4d916a9ff3424b45ded24780b31fb7f76d506339d9f9a545fe0547c675bde44a3b490bd3b52e3b30842624ab5e8986161be4ef9da785bf537954d3c716da5597a859ef7adb40fd8030611d3ac6581e424ff636aff72f4dcd9f315744a3dae6cd386b2f9945140071a5a49f05e8f979115678eea7d6d884a92e4f14ff94dc102355c3aaa93e02723a92417ff49fe8cdbefee7e6c5e952ad240fa7eab4c7941f6ae8d2a1086e1f2ca73eb8ca5fbe3588ae51bdaf18646ed04bd185a19bdad69394ac15d130297c0fce9d8fce8ea2729dde117facb274f9865ffb4f2c7248102dbd96767483cb7fb764fe667d484a3143db514f08577cad8bcf695b0d953e2a3c8710d8979952929d59c8b8ae62ff678815130e68c85d4714e832733da40b933b7133725a40a12534753eb4877c65fe4c75542f28d6f9e805789995adaaff6fce3929e6027338281c6d0c33aac092fe0eb1797dcd953fc1f815df794249dad7b28407c50371a8c81625f6e7e08ed59a98758a9859c41f7436f937885ad35102b0eea85f3dc4bb9a6260f4e091ed983b1009275d43e4960f9422dddeddd09e9990d545cb67dc3f1061238dffec3ce01376259262b4c32c6173a6f1e239f4502cfb0900bbb7e3b4883ca3c64c8ba91cfd80b2bec6aea25b01124ae11a56ab3e4d448038795ff62e9d5ea5cfdb99c5901a8b8f8731c772690dd964cda343bfd020e920b32910a68b433ddd01d117a833242fd695a54f33fce28b506d931adba499373b0a6182e54323f032f1e7b8bad58dabcffdd1cae831c70e87b2c6fee3494dedaacccfdc93fa23ee1a4273f16adbbbcc21f5d02d8645951b93287732cbca4c61a0d0549345160537501b8c0dfc97128035875e73db7eebec24813d03d11cbcc089929b0f6e2440a26d90cffb6295e8fccf65b4d676abb8ff66709913775e611bc843302a475488c9a9310c0c8885b78d5db5cbb1a919683cfd9bd010cf2f1206ab327122ac87d8e2899cc1ac684e72c91f2d36c7bcc3491b768aac86e92aeb106d22b3e85112a2a871bb8c9d0a0dd15c89d113910f8babf15f27a13b10200ec7078d362773f17286228b0d5a58d6654b0fb4f60c81ee581e507f17a044e6bcad4bb6ddc66bdde7d311810d79ac031086d7b0c334cd3a8a496591aeda23b2c0097cefdb6894b352395dfc79b74a6e4d086656b0cd9c95a48640cc8b3d188189ec0b98c8618b0def4b0175f11369cb2f107e89c4a67a75396cfcbe899334a5d5df5927fef2eb8bd836a27a2834a7ab94813d30fa8431da3178da4ae56caaeeee66cf545537ea260ea6af56d4ba048076ace08ff2a446080a6b688a916a13b43b933e506ad187b1f829a1d54ae261651563874cae19c490004205765b43c3cca4cd8a309fb1bfd7520bcc07794cf7c03d9b1d1ae0cf646534f5a97106925ee96dcb7fc1f74e62c01d382fde19fe027a4b9b7627c08e690abe3ab076f184210acbb4229d483f7471ad551eb614c35e019a8a894b5f92f5371fd6c457f135ae8377c5781a8f3a6dadd2c00697bd8399b6f168dd64b2d2d66d5aebae90fa5f904af9f950f450d8be919ae3f02cb5c0be9687560cfab2d2161db61e978ef46304de248383dc3a99e30573bb66f873ef1e54f523ff8ff79e8c05e7f8143cebd1bdd9d2186ebdbd3b66a0a3dee79475cda2890720ac5bc33f8cd3e817d82bd7c52c34d491e1e9d1d307eec17c0c7679af3626e7b96bbe6ba2550f44de7d1d88b3e4c220b8f185b459f1f882a97248cdfc3d42209ff44806837750b3dd21ac5891254f6c7f6938aef3caca6c55b633770772c2c06734f84612a59aa8cfd4f347267e631658cfc4ff89cea84550bd43699c1d8840655f39e3449ea0d2abba1d81196413302719bc9b39cea85cb7db6ab7f00683842cc480503004c1c819ab80e121d9d21f46f362614a5f2cf80cb2c8d3fda82447cd0155fd7e0ec7589a6df2e6614671071f0f956143c762d51172da46e9f61e588fbf74cb3ceb74bf2ce4ec4ae26a28245f98ae91f09cae77c4660d6dabe7cad33ac506db3000d742f683e08bbd0a7cb9eec72a1a976546ec926b9faba5084e00d66475a514a73f01fbe1e79c0ee0066f4b724e4977f3c1518d28ddc918c573693e9b3fb69b426df0640c5ee42cd5533655f9a82c6843516298d05cd970f34dafa886995545c37b3b939e0dfa3647fb3f330bbd3e69307be3d469a99c24382acdcac76c6cb71decb4b7b11cb5f2e63d112767a7d6467c51f1c0c27900803180337f463e64f507ce245f606f8c1f1df836c7fd02502bd3127424804c69f1d066ec3acd9c4374e857c4607b711f532867cef2c1c8a7d7051a440eb7a8507500d86f11567e2fc812a27e63e5599059af1ee90444497f69add7862b93ea050f100e48df7a578d55b6d6321e70ef7a7625ed89054ab010850912088fdc21551b89397c35ab582aed6c215e00d398a857090e2f7cac21c7b51f34054a45f36157edc603b5d6e76ce20f2dfd2c20158943efd2349560666ca38505cc6af776e0720af2d5f6a7d98f385854700fc0c749dafb597e94d7ac54aedf34840ea778e8873d6f1fd7f53de7c06327d08d34a03b38315efd8eb52683ec1f9abbe2bcf096fa4f379f41e09b8bc67ae4685e68ce456465b38892a238b18358714fee41da0aac8dd729e2c3f17488470648df81040272b2e927e896a4eaf6a11c457938421288ff074da8db60d37c6d022e86952341f2b8d262cba0c5a6efb51925517a8c817a152499ae7ee56d36df86253e6b2d93079c89fc922014b03da3941509e979ff8dede44165ca4cb698924fd12bcb02a35deaad608ff3358d455a49e12e944dbb11ac7e9571476bfa856f3bcf90ca9bac6d57d5c1755104b348d2924ba9b14e9ffb750cafb6edeca6dfb79d73b9839092032035ea700d81f19d035e38bdde754a5098dae1c163f9c473b0681858004ab9d9c2c57282ebd7e57c474b8f7aa091d1048b95e7ef887767f49d2a7f6b410922da142ab8605e735ff6ea9e3f36a29380ec43dd009d98d8c20f4052d81fedfee6cb018b2da59d63b5fc153d5b0948d613415a6b8a2b7338897188582d2930480d897d55bec899723b285dec9abf819ac7e6f39d8c35c484ca13f129fa4b334979bac7715bbf5e52a9926568f359dd3e3e000958b561527bbd52025918ef75228c423da41861396be4f829aa4bb6f94f65e662e6ac91e828d721b741d7333a8e3050f136a463af537ee97af4b42456d65e1e2324f72267c07acb88c91d0cd602ef765f858f69fcd44ddc73dc7c5f8825f3fe04affee769f3ab5486232e35df8fdb75db79721906907ffad83c57a364ab85d93bc03ace8998ede749d88985ae41cef163a3d00f568d43115992362c581745f723a2955ed925cfc7c83c5b5188812fa2dc016dc21844f923b2362afa5ac5f2a6c9355b2eaf724606333f152a01c330ed88f7028e716043330a280c5ee458f2032c8163f5548428ce4c529d487a16ca0e58cbf41dc4dc802cc5ea7fad6a50de0c0f2c2be49c3dd2806911ab1322a30acd4fd8937b8930069fc1a6de86f9ef90f407b2563594adad581b49ad1d19b30ad13efb0ddd8e6f26dc43a36ff8d14d1c99b073f5f1ce8923d3100bb04488b86cd4e89f7b9f5b9cbbb3f86ee03b498ae255e09eeaaba3e4e4d68f1ee4d50f699e460a922e17ea8f0ceef9794e944f128efe835f281a7662f959054aa994afa3982f7a310f46f53d5ffc07884aa91bbdcb3f3779ebdd7f90801e96222f56df39ed9c2bff5d4a11be1da7482835e494b0856ea7c695cc1b53acf3b2e2d1846fff50bf55be65e16548c4fc436f20c50c119ca8eba4cdeda8c7e4d33734a0355586629ca5a7c3591ea4b15428a81b6d91529485004cbbf60e75208579ac354dc705edc7bccb32f23030e733d3f549fbb841329a01f5c5d263ce635a57aa9c69432e5213b155a07c34fe19cee737cb993fdc82ff38eafbeb734f04f58d367e34df15dd6044591983b9b45d4ffd87e2a6b478c7d1e86b4b974991b930370d5eaf5edbb53c3dcda643fb992b5fb0725a8aaf8a9e7c4012311f197179cf1293884e2356fc5b624cd46358d3c7bed1fed6b0305114cd11675aa49c1b9e6569817d34fd60c1105833d78dd00117284cd1722074a60655dfc428072b0d2eb881b93d6c367952a4bd59eb902032cfbf9189bf65f7bff592032c77d61dbf778986b491e297ad0da5b367c8a10c9071b8d509b246393fe04a290b3e2291f04eb750285674ae3e9c7b76a01b679787a4006836dcee956185d3b0ce16c4567fab862d3634b93079305008e2f99ed425489bcf5447699b7a7212fe2196d3999b39191e750fda742c6ffb5509e3806f38edccacbb8bc73c96cd46f0f400c4012f1205813d69a48bbd1f55724c7de917ab56d4188716b96653ebe4fd1b6d5d252f5599f9c53a4683ae60c8c31b86982f32bf73401a328891804daab93a155140fdd41ec87e392c8397c9ecbc48f26acee4e3cc279cfd67d75b5e0b6484274484c18f72c2532b4064cdcc309df796c802c17480428c3b5a5467b38aabce03de2a266c8a22d3b0158beb913d50615a1002fcbaf91edc529b0cd38f35138bd71dcfef1b6b90adb4e68a594de40199724c158db9c85ca78ce3a19378ee90dac98b23e1515324fe18472a4ca93b004295b7abd3c146109da707f5ef37886fe1a8966ff1e96375fd64536eece72ae3433a697492955cb182331ce72e8f1804efee93b1929338f" ++ }, ++ "ecdsa" : { ++ "addr" : "0x5e13d369c8adbd8079272b624343ee1edfa4a560", ++ "claim" : "0x197e55da82eb1daa23a5478ed230c6d0452d3c1920df15e10a8d37a7430a7f2b69eb474bfe0c44a6e4a55db9d5a0e0b74549c044ae22778ce30f47a9fd1eba4100" ++ } ++ } ++ } ++} +diff --git a/consensus/common/src/test/resources/aere/registry-v3/n15-transport.json b/consensus/common/src/test/resources/aere/registry-v3/n15-transport.json +new file mode 100644 +index 0000000000..77a8a6b43b +--- /dev/null ++++ b/consensus/common/src/test/resources/aere/registry-v3/n15-transport.json +@@ -0,0 +1,62 @@ ++{ ++ "description" : "row 0 transport is 19 bytes", ++ "chainId" : 28001, ++ "requiredSchemes" : [ "falcon-512", "slh-dsa-sha2-128s" ], ++ "ecdsaRequired" : true, ++ "previous" : null, ++ "expect" : "AERE-PQC-REG3-15", ++ "manifest" : { ++ "formatVersion" : 3, ++ "chainId" : 28001, ++ "bindHeight" : 1000, ++ "count" : 3, ++ "0" : { ++ "id" : "0xaaddb4dde09de5718a906d83be7db3d58e0ae32a", ++ "keys" : { ++ "falcon-512" : "0x09501c96d2f5cf0b28fa00c726e5359c5d36a1fa069971f854b7d914fb2f1295e68b2c6fa91d82f7d287f55ad493c87320bf7ca2a5d5e79d7212e8a540c166b588dc03f73b83be060525b367d9f40f5e77e7798c60b6499767586770722820b3b9e6013cad3eab5fe5de96089a29f34919a2e9ebcb3fa03a3e714593b7a3356d11ffb3441ab40ad94474da662a71aa2419dcd50668cd5d8a9017662cb60998b34ab5b7929c58a94d5e133ebbdadb2b0279543067f76bcc4cb6d7e0a5edb7625467e3ddc92a01206e1b8dce69be31928687d8af4d26633a07e73c2830d5299b878977691cf65700b65b6ea2463e51b6136888c544545e59fe8cf190a7944e215a785b682623c95a79eda28e25e0e1b91b49ac89deaec3b14a3c431d9046a663170111ee541d81b43aa91f29dc147c6fc97739b3a63fad1ca84843d0a65b8d9396f28e9b11f9a41453ab18a2309ae8db03253a09fac8f0cd634c76a5e938a44719660944a95dff056cee43ea99592c3899c2880d7181ee3dd5c04baeb60e1369a69430a66031e3cb10e392622f5246a71761760cf417dcb40ad65f60704fb74ad26f26c3af7513a42f806895e0298c25c049187aa536e0eba21998912e621846c2ca0e323744ba930a29850fdb385c8241382296ba28dd4df05ddb1e61fe525949034b59929a784406de240f8086b4074825f419d5472a28a0b157500be37e9f64897db2b645d3807c48dc143266c99e7cc1638ae278772493a2a4ecf74e526a514bc9119d7129c5a0d115a450ccf4dce05b76d4b6149fdab028006df7ec2209923117abf7578a082128cad42aa66b69eb63acee4456bebeb537ca57bb3d3487f95e4f06c5cb29f292d3b6284e5a162cb83151cd9ae56aebbfda150b7edd5065302ccab70892733a1e096ba0da5f51b42764ad23060eb197d5460425fd9c7a26e7dc3cfd40eac3643539feea72c9ed41569111a7976d2c345ac2183fa2271b424526709fd9aae558a23a5cca29f4e2f31629746a71d904612e95ad9977bbe74fa32e90fac62625838cac49f50e5aed4e8879e2ce2e5651c4f4ba0c96583af9e1612b5ff1a6fac5027c0a308815e592308170b915b4a2de1e8d48e9a5730680ea9db8f3326c430241153b3b218d5347d5c843570cf80ee813871ae10f6b8ce4ab7e4c5197045e85b1cb4977f44c33eb85894b6555b4bd288a50c1b656936841048983c00a01631f10a84522cd613fed0d4beaa4aa4b3e9f30c324108d909e59a80150", ++ "slh-dsa-sha2-128s" : "0x47a0b70170dda85f843607f6c6fcbe6e6acc7c22980c108996a3fe72dc9f61a6" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39c8813cd3b34be58eaab900555a67486034b1923e0b00e435661230cab85f07690a5958a5f5e9c84f033a3dc2039a5296443093fb7fe8d41895fa73be3fb34cefc6cc36750d534e6a3c47307294694729d6cdedb633e8efe8979a9aee486eaa66136e342c578761241192610185feb2d3c196bea0e79222437b6a8e08cb09778d053b29552df96507b1cdaede8e9aa7abc18902f29937f30e7cee6868f349f7ae33738237dcaf86b8e8e01238f3d8ea6fd4090a8161db65dabeb5ded5499e8cc8a5b32607abc291b36a4b34b327d30cdef18c1825232e69a2b09d539ed84dd2a4756efa64f864c563943b3db825824f294c1bbfa2157347b0fb0e7f8a56ec253b39ca9b6cb1ef7d3d7c93a6cb220a7dc50c365905ea5a71575c3aeab25b33523e4fefbaf66137f45c3d96db719a12d2e2d42fbd6cdda58c5a1b958b28c2a8f2cca297871a147dda92a7f008a359027a9288e42ebcd6ea9542f10b66dbbce6e7bb914206122f866d9adc1c89cbf8bbad9bc9517c2ea9018b61d4d2df9abff1dd9f3a0a6faa72a449af9c97e8c4090f3bbd9824298e61599c13c7eb89677c0e845ca2907c728d9296c24e96b6a348dbea7cac62671c9a78a531463614ce321e28ca2f093094ba5f69881e6cd766874622ca769ea556ae757cb7f9546d99f5c90c25e7b8e14f3b7f270861398800b0604ec2a3374659277a23cf6131c63148a41b05b3c06e2a98a268f1b9f0df7969addef17179ca2261d3c229ae3db0c490834564c45f7b8ff6d3bf70784779d75915fb2e2d5bc147bc941b9e249af188f63f39b028547cf080b7674b228e20a600e3b167610f814daf105226f3c1ce5e07834fd33dfe46315546e926fd5be83fd4d47ccd5bb8ae736ac745daabb59c87b9edf9a45c9a1d1617ee84e588f27d12235c59ffd9", ++ "slh-dsa-sha2-128s" : "0x0e8f9bdc22cad3613ed07fba30ed04219b9528f9b657119e2f0886dc71cda4afa7d462fe8bb108feb58d998b370b2f7e162390713d1a17eb7de781a604041cbed13d00effd3b24f2ff87cac74f61e7b7f7aa6a259dc283485179ab4bb966793be018c4bbf4475bf7a69e600a37246908f662813813d4b0f4f83757f4064c5c0713870a0b98b5bb99025dace06100497fda8c73d7385d123afd4953961066e7c8544de3fb620ef5e23174327c2b64089b3fe6df3eb86e83b12634a0c9cc0d7844c894ba6d83afed6becb6f5abcfff397c5cea8064e5e153ea4253abe599dec1614b449329ebb25861b69a9b22228d1a03ba51532ea64ebe7603474a15a2806d3dafa29d57d27c5fa894da673b85b4674ce835fcfbd391d328ef83504101432bbb0c83d7be462b265911aad862118af6f4cea4df0f1dd38969c69428fe438d59d22736fbc7dd5faf6758905b26ec4c99d71e4b8fcc562a694ead91569c9a916df5ad693cb2ad0b7ae4c4f3c5b7322f56612c5449e0339dbd367460c76ab89b6f44942cd33f35eaf33c2ddc0c6af793556d5202fd1fb0f9fa1b7ed45c6ca68d904e476477b71a0bc6ebe248c9b4585da0c7bb186600691269bb4c836667a6d73a455b97127d898b7fae17e1acc6dcc3bac3ecb14da131d5f8adaa64b054e2f569d9bdb164792038e107848882de9bbeff295905c2af68d4c6dcc8cf718c2de872ab6b3d18e00d527166f8ced642281302e2acf4cf4489072a2dc3d55ff8716619cde494be1763dce925438b33ff1b91b35eb511645832720ed92552d4880ae53ff6516cfaeb1d48c923648e502e4038676f7c82e532ea713c6b9348c80ce3c5735f437491d3a8b1765294868c14123af2e9ff61e394216e630c71ff976072d2a1c50cfd8ee1ce27aba5bcf9aaed4a51521bad5e5d5e66abc7a95b215fc8004364aa4df2b8b97b14e3950f521b6327a55fdff9139fb0bd35237b022e3aa128d36c8a60f4621d25d28c59a97418c7dbfc15d900ba626d283632732631ec4a948f66dd9db3bee8c2cf60dfdacbb5ad4c0b2b31f8428868cca035e79c95bcacaba40a9351b2b44cb29753b6b9da0a751bd5af84c9094d5fe91e97501d4f075392290e8516ed5e41b41b00e09793353707fe5c1d942395074637f3ee0a0f105876d6f28a74f9558c5f360e98f047a99af35ccedef8d5cd299365e81e7e91f28a01eb265219e21aa7f7ce56b62f9d2a61560f9fa39f2765f5b50920658100a638aad03482a687905cd27dca02f1deffd1bc49a1be1ea7ff1a505da74fd932937d8f6a8bd75ef456d5f7b71ca5357bc66db6cf14368c4faddf4996363251e6a6113ec64d642c319dd85830d8b4c7ee1437ebfefe01f27709ba0c412c266530f5b6bbb005994774e8935f1d91069f9e7a8cd2bb7ad6527768473affe24709c10294eb588aafca85b379bedf0b142b109e1b186e635b0625c4e59576266acb5f71040c44035fc9480b13932bc657cf332b12da1cd7d5c3977f51d5fa742974cd256e8e3662dc698e0516d615d0a05ea9caf12338d0dcb6151e07f184c9cbd5e59bc40b12ed6372e2d6bd42aa0eb6c3c888f264a8c0d3332631d4919c921cdada6bffbd01ca5445de0779f9723577ebd7e33ab0e5f577843aaa6cb8cb5f0508c33b63913a44d02b76bbb1eabae325581738fbddb5d4fdef8dcb8597bd29c6ecc631839118c44f66ef8dedeca65e58941c30e0423c40bf064b8d19d28dab3787238781d492720236a7ae0695ccc867fbb1cf207ebecc64f84daea66b6745515b9ac9b725061bb9958ed79ad6161318a262528004401633d47a023c645683e36413b8653fa4864fe98c501197c10226b1732337842a1322bb788a00a0de86758139c2d9ea3c5b26bf5d7a4a92cab4cb686c580e3e6cca488136f0da9279073b3dbef9519168ba02588fa29cc60d02273805b425b919a7e2e89c9086609982163e09d5f6eb9c66267ac7be363aadd4617d398d4bdeca37a838d650b0919faf13b78642a058b1bb96b2ed1482cef9bc6e8b2e061e6815936e15a9c754353aaa786ab141e95e5f6c464a41b8bf29e28e764abd638abcfb342b54d08c15ba7e24e6fcb69b844e16cdb5cf4f50db60ff0699f969d8e68511fcc9e16a58e100f80671af6b04ff3edda3a4f05f9183c0c3bb7c1061fee2d3f04e33fe75f1354e6de54f582da914da0138e8565ff45ef52f638cbc33a24bae863fe91e58d7c5da34273438f15e10d4f59db16e505620d97d3fa4862a4097a659925d0e5f4e073103ed29a600b051b83b1f3a21381f4b871c18d262d7e43842c34ed80661438c064aa2fd858a8f3bcb035b5e942baace7b50e4de5a73d5c51fc0843cdc163958a62d333078f4c7d883bd7055a602e04c853f9215c9d7f798403c007fcee124cf6099322629c449ad4ef84b7356110798dd87aa4d98ebb47abc6cc8748dd381d588b77db7f4e7550f6ee1ef4360dac6d6c7037a65297d4a0ea7999a5632b90ad48fba0a916846a216941fbd13d62ab36e1066e24990c19592944078435c52d7717b3556595b645cd2359ad151dbb67e92b14168cac12fb2cc5422582a50bf6e99f116751171c9b78744ef719282f1b84bf95b4092514f4c68fb82a1526e0942ca50e186632cd9b0b8b8d91e84f85e35f30f815601798fcae676da6a2d38eab62f22445099694804a36a34142150fb795afb445e78c241f0b645209037a8871cb5487c975975ac997a540b709e3df6bf208d9d8017f9688b152c9ee2b934f65393de8403244b7437108e6d8c973aa723285555d9eb92509b1747977105cbac7fc33e658fd51cd374d21fc2bf229928948292c1698db7934d0f9be44b137514d0a5fbb659bba83861931e03698a61cd20a449d0358a5fce7f288e18bb3eb62b7ba0ae75feeec634fc90fc45ce45239c5e3179309f0c202cfc53d9f42a617f7aaae586e7161a0723ccebb7e8586cd40e1fa12d3ee89b400dba8073b0080ffaab1182e8243afd93318df15bbf3ce179f21804fbb8882e855ef9e0739ce1536d8ebfe9856aefa9874b4e102e705a40ca4c3ab0ab7df63ba525189b518796590035ca780d348de49f0ba8f28456ca6f3e3cff7e761d961ad98b8cf01e855797c88fe2f811e41e787f3e4becb0ef42ca3b9979356020b447294ef295543e0ef512a247e4d356bfe3deacca8ddc5255e6ad047121eaeafe61d71e7f31395cf78890add4f8c688e4eb065479a63ccb3d0c09028bf60c700fe9d19195c26fcbd4130e6feceb52e192a2aa2343c05b43b276f51a7c55dff7233ea512942291900d93315438a96af08e25ea5b9ce656c54e71ed60d1eeb1665ddaa9e42378c930e21d93484b9a4099b7ddd71d983b4c42c6b1f62907ce84b24321422b08b847f1ea97befaa4ec30a794ad7f340210c800cf185ee2c6c72e844cc5671964e1e1ec58953500f149f0f0f25c34d5592de421c2e31535040020237b907e86d753094dd4532e1ab9d821e7583d4a21e1041fa7ad711f29ee3721a2aec6b0c46866a2de71ee850d8122f722898e533848e2bb851ed24cff9ca83badcfad88a171b4be064007aef4d759d93ae9b67b446f3c6fe504f5b4fe851b8312fec86b46ec3cfcb36e0f682e65e117702b888ab8566c9cc716a3a86106d2323c0f7f20fbc1fcd110bed4492a750befbfcbbe16820077dee281bcdf14509b93137a3998b2fdabc2a375b38857bed12bb8a9c67bcae7934d02d6ff89620fa8946c8aa524fde99c12fec0e25bd79788e2c15fc31fa3f27502cb952b9f9482580cf18ecabd92c55113ec4c4470c4dc06d8ca27a10474594eff708209e8f376b6f17915c2966dbeb0e35ac2f02419692c0d232e133b3907059d3a56ff169e7e61915c8b1067e183337b40bc1136241e862eb3ab3f2c6a72b18511c4107ed063d1e2303d0fe6842fb01c204d1bffad7e90bb44a365e62945a7f631811c9c37ffa5ac39c16b4835798686da5baa8e1eb6aa76b42f6b86863c30669486a175d6b3bc5bc47c5eb05b240bd921007fa39506c6605bfbefc9c8c493973bf3f0767817fd8ce126a301c5b8fba79628a9b3a03cad0c491a5f487dc5e89269e5d3bcdc2998a136a012486c5bce2e6c6dc595aeee2ebd5a36dd06919396184aafb2301d1889b668c4d701c7ca01b95f9508f47d4c411cc0397c244ed4e3e3ad7f97d86b6f8834b13b1b2df0625e6b4eae9e439815e65baf2da767d3b1700fc461fad6297fe4e8ed02bfb65b750c2d2801b7308aba9657df3c3ed7d548687f55e85c22343d1db343bc2dbe222fb76fbb3cf490cee7a99ab3a337c626a148fb303b2f8651651588dd4859fd65c95820ee2af85adf4e8fc2c03828ea7427e7c6b0d4a1b0ccd424df6d1450ee436c01351d8b6bffd4ba072756315968845ab7976813d93d0f0f2be1c00faab3ccafa71cd26c5837e87292870cf768c7837e18ddc3c513820c660870b339fc42c5211d33d892ef22b475cea3be20f5e47206efbfdbeac208e26e97c400edfd41f063aaa6b85a0cf86e23fb11274b405f4f796eb10cb97e70783909ad492ad9207ae7b3d204e59d69c886f91bc82a107d0be3ae85797a7cba747b8e2640ec49384f53c785a84cf8de37dd4048dd4b879c58768bd131ad7226506113c446fbf13d769794f1535d58e9c52e23c1bd55e13c647d304e297d968c759a378f1d594897a026e3271aa6b4daabe174d6a35665b35193379f0ee465df7827299c18e1012ac69913a0a5bb5142e99b051763de3e98d5af8b62133e25b32f4f12b787bef7e21dec42de8e4d99a0adc8f365d8cd3e6a5ff3064ca18965ffdc6b383f7ad08186d735a099bb0ee14506388c1a37f7a766d286d748d404457226b952ca6cb3f317b0f4399006b5b8c6eb89f6b8cfa023cec4d2dedde3e31b9a633c0888989b44ab182a5aba30ba78640f477ef1202f6496fafc2a18e283b2e4e8bc60415a1c9a7fd68f15cc1ea0299e3b26f5755ad9f13481a0563a524c6735942f5069dc1d6a070b3c3698e9c503f67a11efe59413e937062668d3439a5dbef197d24ebdc79944b17c549b0648af9b1349cad83c2a0a9e55fd893cffe2aff4626662ebc5014e70baaf7cdbbdfd3f92fcc5eed863fa8afd87f88873f726a0a2eafe41fa81edd5833f5520cf93b0fbf0660e48eb0258d313bafb87dc9b0d0d9349f22fa2d960238f67457ad644bdc60fb5eafd1c88dd2a74db4da0f723a03df08af6c64883f275395020341d9dd3c7fa049ab2bebb4d8af2bb8dc1340d1a80088c4b2c26bfe7314926ee64bf239306c05dc2ec6e6c5e0ed4f6dbe51f5ee09533f558d29ca6fd27092c20dd892c89c83223752006b23e5abecfdc733aaa59c8549e89e5ab0eae1b44189f58cf9cc18de0c2a2f46a9235fbe42c641a890039cf6aad820f1f844edc24e69bc3bd0c22cfad3804d876edf5491e88cf891c347ed5f24464f2df439bb30742e1f9a4a7eabd9346c6a5f93af22e67becc494cadac82cf9cb693acf44560672cb9227eea2575f90b0e28431684ae12ff2e86fded0be3a099f9ddd32a7285531de8963c9a03355f1d9cef88d7ed9b842d0066ccacdb698d42ff9f8a4f000b9764a9aab1f3146f9f95e6636fdfc9ef91c4d060a54ed7f32167e7ac50590dae3a2904d5d2eeaeff2930bd4cad7166fc17edd2c30e6738157eeb0b441491e5dfdc17a7fbb2bdc6426b2cfb26cf2a7e20013f1b3e33a6d6821928443cc7893f7e4a5268a8b94a6ca6097d25be17b214ea4301e9a723194983bbce286f4363a53afd9e94dda9c761481d9d20c7687a2ff85d42436b9d557d5dc6c5e24ea21d5231487df9fc7986100664edbbc51ad4921c5ec9fbb407ab33ef5c3b3bc81f113e68f38d73f0db0261b656fc344d2d23b93446845d69cee1704834d98737848d405f52f5a7bda3dbdfcd3af3881484579d2d2f3ef976cb35c9cbb76252f2e00019363273489b39943d212ccecc647413c56de69e0087532223cf9b28ce3f77fed30bc3ae6a0842b546e0e1a8b6f6ee1ca0ef1b78c3ed829af817099426f94a447f67229cbca3c07b7a8ce547c5eebcf168248e0a0b9fbeb398e5ed2d0dcacb441f95f9e30c108c725507e459d34c1ec01b67065e5e202d685502d6ff015d46c20bbeef1db38c29df7df585b95d79f5687474e71fff162c0ec0c96c94c507f8a0292a8c32168dacd2fff78b5c7dc145e10fee1b25c478172af8f3ea132fdcad75dc22856deb2576a5ff3e8911842c811d1d57ec203c77b82da3658cbfee18d140ac341d38a30f1af298cf60f2a88d0dfbd3e079ae64a07abb4947cc042925fd5c64bb5d4467589f8c495b0097073c081517bc4504dcd7442bad7e7acafc894fcf34f535979364cf5e908a84e0e141ae47e2ae4dc95462b4f345b12b0629502c7bd65579ec66b2d0a951302ba6da1d1176db6aa0c0ea1fa88195dd2248990fa4aba88490b1da4ea405649203f6ff6f734693f40deabdad59ac62e3296cdcbd74061474dd7b63c46bcfe6ea2b0ddb0f7e77fcff3599892c82425b05ae7aa1a2ac1dfddfc67e11921ff4f2c8f6297881dd5e38ccc4076cac8015c59cdd6023ffbd62b887b33ef8d917446a8941d9563acb66a6226fa4d3f2cc21604c080b3f83e73c093d8f2f7067c392671020c7a7eb6fd0d97af0d63032a3116c408b708d4b2f711c1134b88a91aa359608550f0049af2bb97688afc4352a45c4f6d30d4634e70e82515ff1d5f77851ee857e42b486d5e1f3e0406227dded6c5f47eda30d94f44d978322891dc729eb6ae95d29d22c8a5d649193d5d2aaba782fa16ae488f645a7ed90a566e182f97bc62049724f4cb5fc71f6bc7be57f07a7afb9933f6706cc83483cd7dc4182768cd35bc42f1e9b54d5454d3a17e734475ff58fc66d75419d3d122eff05f7b0548188682f1318ec32c5bbea87c8624cc1e548bf18a6b102e7a43e6bafb579e4e84275fe07d8c63ace449a44cace5d9305ff756cbf40e5a6a20334d5b4a74ab0483e31593f2277e90341fa8036496c2bc6d2b7b10b0b354c86d666d65cacc593d1d7349e71b0360d823453011ee16b6280f5c048111b99b185af99e9d901d4eaffd8a96b1ff394b66208ddc1e7e53420fa965bfc4e630d73ad97b9c5c6ea884c619bc24ac3f46234e7d8d35a12b0cad7220d7a0945cdc64fee9d8852bff872c43f359e7aadf8fa3de3551fb716704af68a18f79d03b3c7d90cf21eb4bbdcbb4004f8ba15ff0bbd2d0918ee78e9bde980e4f3cc13558e6fdb40ca71ad2c10f5e5587784bacc6b925f72da12528216895e0ca4b350d078fdf534fe01bc86b45e0c8e2b35799d268a457f8768ed782dfb56abecfd2b9db00cd10e189c6164f82f5ccab423277e3465ec72d76b696cafc1cfa9a7fe47d142fd6672d9c5b77751b40801af07fc53b1c9da0fe6981ea75e066572f7272baef8fc54bfa7cd71cd0fbc5d6cd717e9aa07808496ad2b4b4005a320c9312c73385afd61193581dbae99df6c25f1b9da17093ccfb108b0a26c5ae4963183533ce2f0ade01bf5e818af613416433578522b1b1e5aa7c791570c8c8b26ded266399116f5789a8233fee128e54ca8ce63fd56c1a146c3006316d200e05715993d1d97907ca83d7fd42ef7e7222eebd74f9c86b6cefc82e614a53976272c8801bdcfd882e34d86b39142ac05088a4c47010a71107bc72a380bb3e5122981d1795256beec20a0fe568002d79a4b1577903fe8682f268eeeed0a97861337ffb6861bf378eba1e0957111c7f9fcfeb55a95238005b40e13ce40efe846ddb86d14c9ad2c46cca74baa364ed08da3a3079fae3a36346ac949e2174c661b8801a051423e95dcab6a0f9c965e8744bdd0e629bd3c1a1241e99951ddde184eb8f354209f24c04fcf10fa8f4e43cb55c922c28be041213ddcfad65c86e1ab9b615f91d5fb11e4cdec5b7e25f8e9811c82c2ed457d012e4967b555f228baf4f1648854c624e0525e36e5f4d1961bfbbc3621d79bd6bea72924d8e0146d0965c239a768b417ea4c33237a60fff2760a9dbfb1113a37b01b598f3e06987d99518bd9f1ec96cd7050863898c8664f793ef29114bbeeb9afab8ed09358d1227d7de2aaac0ab2391cb2013028ca5f4d1de6425ec5feb17d95df358572fa27fcd51d14c363a36bc37c7497a0f964a6c004561f68349f828d30d4633e87bdce6b6d92384c9c1c540c8295ea621e9a8006a8d7c163b988853071e06c78f1b9a0246db052e8484a65cbdced3a587e45d9e2b49a5501590cf768d08b6a043971110e9c9dc96abe855abbb7aee2c38bbb77e5c68d61f01f2376b6122450117240532c7c840e3739395dd6c9e80a432423fc5e3a6dce9dcd58eb418e16d7aa507b4d67dd6fe2af4042a5c7398ba4f87c650926084efbfdc9430a4bc2be544880ecdf7361aea06a25e4f592104b0d74312f2729a4db5876b675bc0fa68f6e41e014b7caaf6f49b8ef704b6243df410dce94ad2c51d328fb90b9cf2f5df645015f489a262f57a5aceba40a56d343403b660928cd7a9d165f4a5bc289c0d28f33dac85c9c2a5c79b5ddd22c744a0388a5daf4bab84d7c77685053c912c9a24b5a0664c6253febbcf552c4ff38bbaf2f7e0c9f06e69a91cff9138c2745b99367e00ff6b6a920b1812e17ba44175c033df0e58d1b5c0b7d146f861b62e812ecbe99d638219e0dba4dd88089005977bcc90634c4dfa95f87370d905d32f613358fba2efcface0b9a414ce33b09e271a647b911843933c5d1008fb0717ab59739eb8eb844a4b34bb1a8f635c5895afa285ddc43720e78dc81eee7db822896bd9bd6ae3e7fe2988ba560d58f02592870647b94aad1dbb0d0cb60e28135ceb72e0a6f4b7893a56eae83f9d9a4c549d53d17c6a00f5d6c266d23e7a1d13e22a5fede3a7082dffb34296f8fe9f3bfe525ee1da81efde3aef9b6de8457a10fd4340809e1dafbfb9e2719c327a3c3a4c51d4d5600e8a01ebd5c537a4cd7c4519e963de06de6c83a9b968b01f79e08b5415c5a9d6a92a633d6ae969b80cbb2cf4d6d1ab2c3b94e7c12df27ea89bff4014d92add41a3e961006a194ae3ea4a6b38c2827f6185ae636f6846b1c8401289696fb10c765fa93e58d068bdcd8c9dc95df572f096d65f5de42bae639d41ce7e1ee0f48ba4faf856c0cdd728956d7e4babd6d9d6389ff41d76c5fbd6380f351b05a37022dbce0a6a47ab7168c82c77a2810c80b1882f825ebf86cb7f6d0f54025fddc9b9120802514c797d1d3968631dae95297a857890ff1dee408909223d012925dc08b7d1119fefca7466392a019d4121ea76c8b4c3bd103a820557e4b2283e262af32f1edbffaa253c47d5873bfd0219b8be86c7e64ada2d87ab6b7f428a7d8fb3ae09b05aee71054355eb83ad76c05d836a9f1a65511b1553927ef1b19ab1576d7185af61be6104de1df218918179c6321846085a83bd1217aa63d0b03996ac1fb4018a8ab54fcf635f7d5a8ade95894f0d407e5d4691920f21094c6f632f1661402a0b3351f168f16a13d3a31ad48e89230cffad272926487f36c7a2584c9387623df6227be8c96088db4a21c93b1c88ee756e960f60e614b30bb6ff757c20f3674a7ae7f6ff6a9115a0a6d444513ccc0be5dcd557430e0ee8db3ed5b3e8c405110500b9bf7f6eb7748de4988a1db94bcb16fe33479f64762c53a1e2965363452063d7bc14386ca7b4d46ebcf08489c64ab413ec0f1ddee8719f5fe978d38438ca3059961ecc8480908cfaf139d88db2facb5e7a88a43a67dcb0f97a17f9bd5b09b8369803ccc7ab6d41238e59e43762965814c10c36fa4b6e61bf2e83c0243f20ee8aab62dfa9827aec06f99c5c565c1bc75291292d3113503a202851c26d1a8bde54bb30f0301e555374b71e278925a2afb29b0209c08ecb89601bf612ce811a493abe2bff78e7fd02ee13c5db6b3edce7c87559410b9be3be95465468e33af224d6508a44728cdffde4cb14fb96a0d2ab9c7f597541f9963775c32ac613af9beab89e0ff7a5e35613751061b0511532b10b3947802901505c8e33bae67ce0e28da760af7e80b730811bdf17abfce39d35def51d73a084119449038c2b0f1c86d844123c6e71f28b7038053e279dd11c088dfa11c547a4ce13b19453e88e5b74962101412490cfb68e21d8952db509cd3a814387b67339fd04ddd2163177589146409934f0eceb10db2d90a9e3f6691eb75e84d5e66bc3228baeadcba200f3d11e0cae090ffbb800f5da7032c35ab572de55beea37258bee6f191addf01739a26efaa612991cb2a3c6d1bbb03de0ee1fcf9b7f6c51e452b21c0819a9aad93162eb2dcc189bf355ecd2c3e504713dab24bfe3ed86a4194611029f7f6216cd469fe1f7d35d56b6c8c2045011e238f9cbc0a19b8914d74329e2472f15d0b7d60511814ad2736d6be168aac01868c2a675549c849fe05e05a76f077130b46896735db5490277b76bba43545de6b8ecb53fd20398eb94dd884951fb48d5690ce4bcd0b836615cd9340ff0cdee1122743accfef343811a71c7d14d1369fa49ce47784a6ff8adc26c151edd4969dba513ade6a9b1f009e57c3d6aa845ddee275169ce58e1f04b564ffb6d0eec75f7172e5e8fb814cd702c9fbea8a783bff637db8667d4b6b48a264135bf60acf335936105abacff0351ba9aeac88e9522cf7ed80069822a7db1a5d8221d9492e02ca893e1f15965fb82a80ee2ec491027bbc8906e71cf931fc21e1c0865ee06a79c023929625b4d232c7b3e2e4a4e5dde28fab675391befe583c95dadae71dbaa43e09d8d65ba36d148aa85d1a2a35dc51719ac0311ea72c1237c78a8b1542c59de3b743087245e54d3111c585b5e5e7642f625c8d44c6d9cff50d8d071f6fa573df937d9e7457302d8b293d8fd94ebd3023c55f8b260c3454e93f58f16d0f451189bf41c9f9b91d3c3918adbf98e4ca5aa0eb6314041521ef880ce18f0ce296721a06b329bb5fbb3024e424b46400e03caf0105877465285fcb41a93844fb90b7fc1924883ace6ca8a37c9905068c633761163affae39d0ba55b67fdc6bcf0908ee3a42af286c" ++ }, ++ "transport" : { ++ "secp256k1Address" : "0x11111111111111111111111111111111111111" ++ }, ++ "ecdsa" : { ++ "addr" : "0x48fcd978ac4d42ff52dd81fcd17e93190f35e5e0", ++ "claim" : "0x2dee91bd2cbfa906aefa3a8ae6e2de773f55dbd28e77bc329d28215183068585601ab9a7f9ff0c48095407474d502a3af3f059a666e5ed1e27468466d69914e801" ++ } ++ }, ++ "1" : { ++ "id" : "0x690a7fd66157e5b777256ea5214f634f61b3a72d", ++ "keys" : { ++ "falcon-512" : "0x09a6d094d9a3a0865864e9a16b477236f1ca26c888fd0c918db331c87a478519c41085cdac7e6cd0d89190a41a3bd6f4d6300995d591f5e22a7b7147caab1f9c7a85a4ba74d47c7b227326ac17535de039a7e604225d3daac7f75b9544654b73f79f5825825ad6e6c45d13e6d385a644633e1c8806d3a0a551c98f032583c95fb13997e52a6b02192d26b5a47fb22ee52999ec92b75c70774a4ae0481a79113ac72346263e53d5dcde708668d317dd00552d5a40ad47e59a501b10a50bdc52c5c2b2c920fa0e3dc9b8eca54b10aa5ab1168c88287dcf80ecd880a8fdec85b6d63a15b9f453845421a5d9b898e6149b60454828eb9dad6442ec62ad27ed72215014f3d17539085ea3f668b0a9183ab96e9db996801c72a0920b02a249911924f181e8dda515d114beb83b075ce7e7a0902a6971e31420ee4921f5cfc123f29dc7775017aefe99a7e326119cb925f6f603ac3bb137313609498d5a2000c426cb332c82500dcfd80d70a5e2d156844a683b313266af6d60216bd9e9998bda53c0028f387ebd21a5fca6c0607d54b1e95724746d15f25f16e45845926a83c7598646a0a0d3a8f8307c1a401b823f1656ca41e5499684150a954318da076af9131fcc93361d9bf0ae035f617e02cb5e1224a982b3591b24013ff80dbb61160d2ba4ce85a4260c8a3a3218e0ec869796b1b04a82079cfc0ac26da03b04a11950b2a3331ecd0026ea9737bd20e6ea3045b56e3c71278d2a8c72c8014b769da9319e19dbe762b1943e5a4be15aa84d0da831eddbb10bd05f35d55b6211d02a61c5d9247e69cab6c112acb568ea51f345a5bf16f84782e04220e217722da71d634e1a68b796376c8a49a965c592b87d06702fe42dac12da108d24ee42a109e8e4cfd3bed6ada5e3de50301696bab0564292864f1b9f47d5a53cc0c5f9cc3d57051065fd57064d08764892ef4c4a92b475184a4cb4ce1f3a0e6da0402414db5a9db34632b9717586e799b06e870b81a330da7be6a45ddfb000fd337a24a29e164449f96be015818c53aaaf09b9a565d7d9d735b9493885e7cb49a5f1985977cd6824fd62f51d2a1e60289dbaeaea148a44dd8876cb58b8ca2f29f6455f354e4e76aa13290f2979b78b22afa0e65c696c21497e94bf0141ac6298aac70b5ea843848a2264fc057abd3593cb17465e06d41731b7153b71f8f0f7a06d362fbd09845f0815794050460b41ad003c9396a86eaab240555ac8c75f85c0ab972c1a0b94b67b1aee2fa3", ++ "slh-dsa-sha2-128s" : "0x2b2fea4a0edd5dcc2f653eb2dd000aecd87deffbce8818aae72d7862b506bac7" ++ }, ++ "pop" : { ++ "falcon-512" : "0x3968f2999d69a9c28ae792a90a47363e689bd4b349e75c5f837181fc7b16d3d04489bbc32252d750d750417770630c5b65b88cef918ad23e33892a58458e9e63ea591596d3b898f65e1a5be3d36650c3d9834e1ec725426960d337b8f25878525ee3c3798b5afc9add5bec82c8e139c59738aba9ed5f42d11c886472e81cedfdb5b910eb73e884e0d4cc218b87cd9bcc0bc107af586c65b3949460a25892d9607efa341f232e478f3c9fc2d05f324ee6eb7bcddb72af371d47c36856f488872249ffdd322d3de7d12b62b1ec595187b5b363e36cc714b765f0ad5616488300f6e56811e88e359365d5698ab123b917bb32f56566958b154f6fe052b894ccc1fcd99d65d19e8117a8ca4887e01f36f181461a433fb9bbc1790d8b14e34a097b149f0c5c075ecae3501944935f3caa76f0b9370ebe6b90390b4d059f9029ee4af98dad33b9050877d49c3d4f2beaa4b5861a21af95b8c52f9ab4b0eb115357f5b1d25fb66a36b9baaa4d6cc5a4f5fb5462432bd82734d7393cd22c68f52493eb3434c3b88fa255baae5c46c650cae17ebe59827cd6645c6d377b3cdee3aa6a758ad3a96d103bf6ab8ae03b72b53f3aebdda359288c32ff5461a158962924a97a24af29f6c976762e8de9363485ada49c445566e71ac75379aaf7bf190a81c671115e842b5280a05bfb2ef3724bb74487068d5b5ab2d089ebea7ffb4381a7e96233f0915f295d3b71db872393bb990b9c74717bc3d72f6271bc248e54828a1e090f6da56de3643b083e9695db7d0a32bb42355e245e5cc2ed57354d82220b449e10cca1cbf6fbe796d141591d6f71e4eb6770a3c7dfcee509c3c28f2f1988eeca61833b6681e6766790c2a6f043b4f67e145b908ba7f03361cd9d435d054e11edd9667e4f9d12c2d74f2832b619", ++ "slh-dsa-sha2-128s" : "0x39254afc16b1dd8d4fbfff766819460253653dfc6a8e29abed55ffe91325afd578ebfa2dbe74d46b48b381e69d269b5bbe24ca1b85767bd71c744065fa47c646e3603b44261731b50f2d20a7a327e98b84c5ece73697739c8057f99d6ecbc54cf891649fa78b7bcd824972f3b27820ffda3629f481b1193b922cefc907bde3ab1c78b5ac97ff26986f3a553556d0b158e936450b4f41bf006c90a9758e0efb327f67408a7b803ede993522cd9042db4a672c89d4765a0fff8c6e8bf6882a8de432229dee08ae13def90f9fd0a40c99f3d93873a41d74871aaf407b0927a817b476eb93c645254bbc77d131e0bd35a2541248172993b1064d5b26b921396c8c1664178051810961039b15790862415338806329a45a266aece5904312afb1cfbeac1e816fb96256fc6e2b059c25af1966b0bf261bfb72afd8652feaedd6e0e4bf829a75188708ac9c623d4d6699281913bb563b96818f9307b66f7cf4aa9591e30c65a0b0885c22b5d17ff610f40bf2e0a9a32173b2fa7d66c14784402885d84f33fc75afd8f743cd10f5ad6dcce5b33a8f0c0365de2ce1b69aa86df2482a2c2d3746c6f0ee4e6fdbeef5738d809f6b0ef3cc703b0d29e93e198b68d62a5be657e69c33459fe4b163a5ecd72a90f1e53fc00bc8c698af7ae3cc5b07e36cb74088066a54138d6df4ef6e159ce5924b6903346a5fe115272cc951e8713d4b6f96f78d67a542c3bb402e69bdb3c2b06e189186c227927b2aba52b29c14e837b37798321fd000ed3bc0e386ad6e5d3a48494f57109322f0a87f7dd752d862dbf772498154804b09eca84c305595cc1e6654b1b2e94d5b88feda176aa144d3895a249754bb2ea99b2efb4f61b828f265638866a49dd3437c70016347d5aae64c79957ed394a85cfe06b10b98b6e83801728645529537a1102bb04ada4226688594cc28aefb24fbb0d1a60c7b826dadd23f301517e862c67fd88d0f6a5ac08e7f966ae375b468e57f01521b43fc24c761838c174ac106c4e1f435b7ead5e79aa1b303222f6b45c5515d497d8e7b05901bee96945652d304ad9ebae2153321885f19e7ad08c9da73ccc22a66c26c4cdc9360c36e307310714ac44c80887f42a2575305ef649378d76d297dc6faa904377b2037618f23b8be496fbc680645dfb80a76bfc060c6b2aee4ac5537e79b7dc7deeca0ca38041dc877b875cab1a297190269c987dcc46ff34e5bc154e2572695e463542be79d61fd5e96a4be2b07f5beb71b882f99de317116fd0b36131a88ff9707eb25594fec74cf76c2859ba6ba2b968d41479adf8857f4b0f4a26f49f0f04fbae0e2f3c2ab6aefdf01855a7a5a4b8bf516f4551a393a33d3920ca3ec403b4d37c2106d777e3d5dfa768614513885d857ce95b9bc3b992808e7ad71575e5e91b8107c5802043b221c74d73c7bbfa7a191945bbc5ed69e20016b16e2e2987818cfa80695e58950b0c1bbb8c474f861d1447161744c75d99dc8240338c43a5c19a8a9f46d80f6b4b6c1cb57f5a3350bfc35a0522f89e3470ccd71a458968c629c93336af6b5b091f569d1fc9492eb6b976376b8ff19ad9318f5cb1361954a0471419b4207dd9dace8c0545e74dfbb19ce3fdb5d456a1c1bff7383c6fd96dde3a92daf0ff5a315714c74711e3c05e0c59ba525c64ebd17fa20f8e143c5931b3c77da193415e6506c2db27e0e773a6a5b5d47ad95760b8d471d06d5dfe000a2d47e6e4e6abe7219750f1f7892f4e09fe88d13c2e3b53dc904ad58eaed856a4abb0c10830b96bfc1b5764f9e4b34b0072be314608fdea8c5005d40ef99806d4d3edb72e73541fb828d4b2adc38855e09e974293de25da6907f5ea97810eff1be37f88ea879e545bb5a70d2187edec81bd57a95c0314df4ad08a864156579d50826d0cfa511d335ff722e246151a7afce94126232f6bac89b13c142d29e7521479866e35b17c15f16ee89d798ee8bfac5868e505031586b81bfadef4aafc2ecdbde649f63e07eb6026d09910d9d3613a9871b5d1523cf5958124f96b5304d5225b4bbb03aeeef87753d0b6ab51a287df1e9031f56f755d3fe5a20f79b7f0f467fa97eac5bc09a1adc6ec285c8f80ec5c184b8b5eae326300a5bce0b1d757c8e4f27ca2822e73745009291f0d9032051e15b567511908f3ec68840cb6ec6018a9a0e30f2e34759743ef0bc9e12c9b32f29f4b70a998cb8893af2dcf17e0eb4f48e7ba367f68aea5516e7248c8be1d1f896d7e8446fadd9603012dc13126878300f0868bc512221154a5104882621f831e60b49d04fa8a701256b3a413b9db4abc5af10a3f8f4c26cd0b3c2f55a58c9380143d835b759bac7fef824515a18d79b6dbd361541047c79653ab4af5473b7b7e67a6755add78d5c14c0a9edc6c7dd42c3d0359d9f2f6961f8930458a34c4f12478ae45c20969c4c18654d31a7ae73902757b3b8a4eedfd16d6c0d22548d7b8ba77aeb4c1e3f3766b6ea802ee9bd92c5f98d00be80c15e7e3a82eb0d100436c398781607dacbefa98c87b3558f363b3ecb1ff313655838f864c1b2e0f6d6369bae4eb8cef98f564108ab2f763e590a9e9201f4e28ef1971438c30f4376c55cfce9b9910f448e31d06c2e456eb798476d56a890660e45616840377ea0574d1c066ae2fcc46f41cfbb511e5efc4b5c60e00e4846e157bbee5fe3bcd77408e3bf721bf871c05971a70cf7a13c782bb4afbdb1ef800a414260243fd828b67f49007eaf60b3e32f4e2b8186291075a0b1c0a528abb9da7974b3b1e8b20d337161ce234db66ce82a88ae1dc880933343961267cb4932b36aacc5f136cb474bbdb5e4c4be4cd74868775d80317bfba00ca4e58a39d04e63bb797de366c45efe2e356672f567ed1f7b2741df7543d6faa7227601eb7cff367d5a1ff320ca71fa2a1a42866239cc3fa5eba400ee4060266a05b8fe1e729908b95ba6aff8fd76b5e7df547df62cb89f0605c1207c869d7214e4e6972ea6e47b18235855d6f28265a737b4f64f0d215943f13d219292036c1cfc46bc61679f034919e4fea80d882a5121cb3096a50f2112eab265ebf75b607b93e14ceda4e08152221bd368cd1503ce375188d23514dd0936bf980d4282eaa6fe8f38f5eb00c34e3557ae363538a2c15b560b9f9322d1f17446e8f3fd317126986afc2c5e9fbb96f8ca7148f53cd75a4b845a28034c8679baf1f5406564b6e4b8fa8e681b5a9d208f3a1b28e84d6d52d4baa152524908d50d71d9c0d11bb5665c8a6bad669dbf303027bd0d534434f9e76f2c300326e25d00bd8d3bb1debe1c3984961c0ea8dc547e8cb83a8f3b044b673f4a08882d103d6eb143a9645a9a00fab6f1167a2c09015d6ff2dbe4aa4025f604a63eb32330f832162b6dd9364f4ad6afbd86c8d26f56d7d9028dbb3051c85a0c86ec0d7961fd6008f87dbe8347fd5ed1dc4c27285364f63650f161321daa83ad41fbc3412bff800c062a78cc5caea330cd58e63ea9a9d6de2ee069732799f52f49d513c658a44a2122b8427a405d706f740600f855130a0ea720f76b3111dafddf0e2ebbd13f60640379993889089ce508b1343f485457cb8e0c09760d3199b4ea940d584417259e41f2c66853ae4235b6f010cceca3859952b3daaab55da14adff0e421e862f138872c2577637b3e12b00384cd32fb3b9c97b0d59e51f2488e379065d79f5a834b076ab5b35fe4c47f2c4c4f43e622527abb8f682fe9f262d2883fce5c9f16b7566c4e078b67611abf72cb8a0263ba12a6c23b1a04458c759f2bdf6dbcc460bc5df48146468073b61aa5ab4a9c5f6c006f54f1bfdd85373f33af29d68580eba4cb6dd88054c81b3bb7f2be8186e380bee0b32a1b84ef6319798079828080361bcc27473a9634c23652ed6b2b2c8f8d5a6721551c780870f1787726b121263e74c9464a76282dca27249b4532e49455a7485e2cda4ccca823f62d3b2869602197a6f1ecfc9d92ab6e231996e603e81e3dc648aebdfb900a3d929502ff0bbb3dff813660c9d5a417d857c19754ee04e50f1241831517fc2d2a71c5e238a944992cc50b7106aabb5482fc7e0a2e6b5b11bb6845f34ede98a18d5f07759e61603de502b5eaabe59a4d2c69f4b0f8e73a9bc85b8950a54bd91bcd0366dffaa0df736dbbbc35d6accb5ab8b22a870374521f2035c1878718d7d3b025838da75d8bfa3ff36b2a10a3cdef1b150abf3b6be95a5c096a921a3eced20f509dac4ba43f2f515af2b65d3b2ebd0da2d7a58500157a666b387b1814d0a3e84f64d0fc44507b0b6792c0c6bd90ab62e0f75b66d50b6f842cfdbecf1fd043d642c5d5b5fe5cb68af62e6e23cc6f0f9b1cf3cbd0233ce48a996296b6609be1c9e7a027cf76615dd11208f1fde119099352cc17e1c9a22f4b71c3e628d72b620f3cb4bd40e4294ff8dfe19480b5b758b874a737e6092254638a222c83aac52fe0f66670454c313adb0dba2b4e95741d27104bbff159e999e23103c00470a7feee6f4a35f764ec81a8ef520cf1e8623fed3c06b63c022e40e7638db269b8add119fec50456b33224c14486f705e5b3339c6f38aa4ba6dec8b098c27447185ca50cd70772e5389ba703a4a9f8649946671a238e1f005aba0b3a18c8ceda9daf4cede6782d27931c638af3f6083b2bf10ff0a632ebd4dd528da3aa2b7a8bddff2901d902b26d518a058921eb0178ef08e24f7075f77ea0c0d0e72f29847ac7826230c0ddb5e7fc8552ff92c007e9141f51384a12e218da4fbfa9a7a4a1bf266aa975949e120db1b6755ff04adb07c66ba9619b40396072e7cc01dc3dd56f7a2f928a82c8906be416f6d5c41354881f9a6c66a927292f8cc2887aee86e90da32fa3bd9d72bc26dfd334f943305fbe4b645df83fb72c565f61860a480dc0f2f3360368ec3715c2c4a312bd2653051c8f29fc14e0c3d1f515e04b75ec02cac2aad8d411306969d9a8da08c3477eb6201bd54c6ee643d87a89c78a5c8ad48590b7a499cc44ccb812866a4c48ec2da5f1e0aac741464b26988459f3724ea4cf103c27e4a43e5a5fbbf94908878894f8b62995aebc20e632d924c82d9669f64b2093cfe023cdd1542c8f9d19e5e7ad6ed7920ba6834cb0cb91bce48fa94be47c1833c6ada4090509ba38defab7d56dde8168bac8021fb5a2aead00809f1881d53d26fa9cbc824488e16062fd9f68726c837234a82d518e3d10c9931295d20d9affa5fd18c0b2dda299cf1d6fe0c6e6959440af9b397f3441bb9881ba1d2df295d12686ef6b0bfe52fb2bef06620721374328551040d2fa434b161648b058b74df2a7ccacd7609b93421f44a136079c79a3e63bd3b4f79717f3c121ceec2c3918464f5619b1a2e83a7709fdf6d1004b0ee51c73e740b20e329847304a82802e02170db386e360dc6027aa7ba1ee35d7eeddb41ffde093073d92899d568bedee914627c8c48427376e7b5d5ebdab30e58147dac5638090e9c71921431f025f1d4e3ba3c68437555357c651336b326c9c519544363d5f4faa91914195314cc873ef97068d928a6b4e5c6ad70ea7a7b09b3108fd5696aaab800eafe463ee52a3f29e1bbe8a968e84b762484a13714ee260759b4492b749c46ab6603c13ece34e301c13bea57d9de706edc839f55b432b9299d2d6643817cd9d32d0d9ddbdbb23acef51992b62db024365ac2db4c432c531cc1ad18c807cf1ee39dcd842aa9a09b232cfd09bfce33277a8ed09953ab3b5d24e5a8a02fb4a02ceed705185880ecc47cb245665cf640ded4015b4afda053a5d1dff77e390c8105961cb3a954c28ddbb9efd759080dea99e94e69b03b928c8667fa4797dbb3cc6ed093bed107c817780f60729036f13346f05491fb837ef1ffc61be7b61d0b7f8dabfd49ec24cfcee088de38daaae6b4e740ab4faf16eaebf89962331a99f17ca5955b15dd1fa493b91e7cd218aebbfaa7d348b1ceea26951209137448caa93fa466ca32eda497a5b9a4fdbd23a10d9742e74c511a1648d00bca3ca23abcd4f18b7cdeb362e020c73888b76b83e70d26ee358c06933f77d1221a8ff0647200e451e971fe45c23aff60a88baf46f59a0bf94e99ab9337b0336ffacf8e79db92067d2b744134cefac1241dfda288f5c6ab293df7469ae0926c166e999ac99c8871e571eab03f82de73e9de2d8f4deea3724f795480cd47e304f27f2567cd94cbed52e06f1f1cf7af2feaeba8b95927eff950bfc26aa0cc3e46ec7bd5d4aa43374500f8cad4f153cb586620b9a0deeec2cb12ba48bbc8655c7fa70ccf94aa6891b5cc8a3c98b482d906d72e9d425301d0cc6fb4ec9c4a5bcdfdd74fdcef68f05fdb78f2a1c5ae32c28c43ee900738f31ac1fd337ce95966b3f557a727e0c3ada6c6aa61219d92fd5cf68fcd9b444f6b4fb6178b9c74238d2575f442a298127f282b5ad416cf6a365a214048489139918f93ec07f2cd864f5482c418c7336ca4590a7da8a20d33ffb7be19934c80b64f4b982a55b129f4896685534b83251d54e46a2971c0bf49ded9b13a77ade3de9a61f2204a46ed9cd7bc444801381994c8ca5a66abd70936f8d11e2a2fed78fe9fe8889dfcb979c9a3f11f2c2c1aa371d1e98c4fbdaa95d58c6b22410c0d3d3460077dce654a1decfc829f117bc407d06ad9ee6aa06bf818ea2f25312b1cbbb5de527ce9b5c5ddcb0df21e3442ffd149b24af5e59eb4d7e18f68b02b26e57fdf23e7af4fde3e672990295c37186ca67b2abdff6b46e1ff106f041279b61560ea2eae64649c65be22f9070c3239b0cf7929b0778c43dae5391d8d3b8c335ceac672376588a34d3b9c61833578e8d5a9e6e9f72748d860d7af98f7616431d1ae1ca20db3db6ec99d59fa98c25a1cf478e1b4a643c2fc9d3e482d56bedb1b7a1fc9c3e788d9de281c7356b82e3c9e1c9414a0d14cd07fea5364b6a22dcb3b69b6f447343822098548e3ca7e88a83187db145bda17f7c48cb00e6ce36d53e2d1e4c169569ee3fa03620a7131bd5c033062bb82cedd0d0ebc1025937b2d85a3cbcf6ef4458a57525a66244be3a62b582bf2b88549431cdce09f6407e1bee83d3fbe205f585cc7cf9c1eaba047a01f51e13bbe0715a9112c451f1daf6074a1af051d8b98863b6fd03238ebe295995d60e7a26d2f95a2b4b0d617af299133bf357518b84e942bc36a88b4030d91a7067e7a2ed7bbf4e9abda8c6887ecdfebda04dedabb9ea833123507835e0357ca1513b471da73102605ed03297b5e3eb7d3bd01c670f992a7f19962b706e8d0ae0f073638d633b34a1229b6979b8e90f2a536cb6024c644e1f7ef211451dc509e061b294c28be188c96246614a1fbf52db8d9a99f7100c878c1b9da98ee9e9eddf7fcb386061ddf46807c60b24d665f0fe7fde205f91021bfb87c8f4c89b5da254d185bda9cc2f48303b483ecbf934575aa45d0d58cea64662f0fda4d97790bbcfa237984cfb45a9cd611b533dc0ea997d191d14d307c68db318aee8f99544fd48fb86f041fe249a14263e6657a5ee732f7c5c9c97a8924bfdddfd75dc67da65042e711a3cc144f46d10a1a9fdac1b1b321eacd235299a1fab390df24acb739d61bd60c6907b9a3827958198e6e2b5a1c90cb9b44cf8db9b6e45f710d7a39c230ec9cd855af797555fb1d73492e29d17da0b6dac59c2ccde0715565efa1f62898c9b26438c60fc3b9f859bbd33a8e05e1d3d5a762bf19bc7c32cf7d4c6bce26fec6e5c8c537608a1c2aea2e1e5cca5bdbb45a8ed048514ef3d298e7dfb9c5408d941ded6220a44c184dc90c922a3ae31c9248c5f31627389770a59f9431fd0139c5ac0f08f69151a75a5a6a0355b7beab6be9829146ada371aa5791c861dc77598f09448af20deca73cf98a399f35c36f1167ba426c6cf4b8b9b8a22b961bca83e45bade098e20782a9f70bd54fb8eb6eda3acd3a5bbb553438cfe37e1f7fabf15729d6bd562cfe379d586181b71b3d3c4b360852003c4363a8d473198130642972eb3434c3a5ca9b497ec7000e821c3419aae75866496bb1b0a9ac6cf92f799071e06809f1f3f904cd18f32629e2093664755803f62f45942f5a358cb1e925a8694998cb14cfc52733c356cfd739c3976712ca7b007e08841639da14e429c102a8fba3191cd36c1c56eb06bf69afe3f2afc4ebf137c617faacda6baf5cfdcc6462ad02f63e8a5375288d0de5700d0f9f4ca82a65bfdc405d3f96fc663658f0aad91305b86ead3b21bd6561a40db0f2c5b0937ba5e1ecbe91e9c50b1dd6bd83a8145b033a7bb6a4ad4896e0ab160e8a52d39d2756b1c8d8570f7081ba217fd8803954290788882befde24b4971723b0ecbeea14d23c92eb6a0d7022a84aca072729d7ab1a88927a25f19a2086f846a44a2726ea26cf1b69c58243e219c756d06c361e1e161bdff0eca10bd30d23782b3374ed421f50cb66c9ee063ca622fa78c8cede932848f0f8f91bd7a0eaa324377c109808bd66ff463a72389c4b49f2e349be70d07fcb56b28549fca65ad853d70df66b587390febdf6b1881cce6c1ca9e9fdbc9f1ad68ccaff97234325d3c972b57ae5723fd73f975ba640f90e717e9284c111b76367c6797399452d37df6b8b8d22ed5e7dc1481a415fadc06673ce4eb6435d31acb6af68775436629a57db7a0aa192310e8427468e8e310bd3426b7ffab00110324c0c7e04ac6649b6f167fa8b928b3fe12ac162db3f2bc355295650fa2d976c64df69a8017034683bb4bd4baacf1cd8502dff20430d48c907107acfc4e29c584cb497b7a471fbde90aabab25290d853b8ebd2c0d49c2c201eca42a68a15879cf391671946319427b237472cd35431128ea7ab6d545617321592c07b09fff93e71596da30689b3c15368a1c3a57890e0ee5752bb4356290024fd1bd2ebfa19f7f3ca57c36d296ae61ec5581ceb77618dde2821460553ba0dd6dd68026b911f4af1be3986198966f90ab757aca2f5143f1937d09c3a08047b797781d1639db4030f9e59f8c5b71a71787cc84ade5a385ebceb1946177a056179aefb49e1f69ed0aa67901b2d6b2152b6c1fd1db67f358093180fcb8f96483fd35a87fa14825d3849dbf479be493bb2d1c639674bd195b5ea3caf49c2b78eb0e953dbf8fb909910c87efc6f9b6592c020333e00f83bea4bdebef4e107798f9a8e89fa5d063d69f88f31a53548ba2406407251f18c3d1ca6e392fb81a46107191e6d906b487469d0002afdb0f32c39873872a49eee649250d4d5d3a7687fde2952291c8ba78fd9b962060df12d212033303691b05eef0ae0e7f31b7e395576708d211d70281e9501618673afac20a93e82f060135e51b29132a0c9244551814bdf399b746651279ed135d162e366f39d40e3a49e907f72bf7c66fcb4ba75b1f447fbc3ae3f390ab4c10963d755ee188a9b0129416161995adcab12177976208e1c93ef48d3ef55ad22bbd97781dc7035c9f5fe25f47b703b1ed50dba311d24154ab05dd88ccbb5a8cd96d4665829c4dca5d5b22affbfd7e842ffe5e87bf4326f957392229bbc893b1fde9e4b2191a3345490d418e9298179661104f70bf6cf9a0094f9d37be98b82d98497573512d8f6fb4b0b0aa334a9120a5afef20e0379197ac7ec78da3688d2c9b590e40fcf866acbd1d857546522788d1f3ae73f330aad045c5bfd59b8a399ae626fd67d9797b32d6a279d42eec3ec8a2888258728f7c329c4efd0f71b730e57f9bd87204d40ac1ea6032a4b8ee3a338aad58c2f3c9795819af4cb652dedd475e5662d9c0cd23e72a8f4e86f1a63e5683c814a99a6595b779e5d715ac91ba62c1ae4ca1651581506ba80c2ee0d3f97b979758cfe93f373873f4775c882fb3b5815b9274595bf50488b935c82e0fb4ae4d078d30bf0843c89e484bf5a24d5de602649e336fb2b79da6131f96ef1b5f82cbd668f4599fc9a92b4e9ffe3468e39e4c8bd90531952327da74a522e479c66b7b1554c9a72a2e6db58fcd45588c9ff4f48be5ddc994913833b668c275174b9d862dbe8fd01535ff2bcff6ea030842ed3a4d105ba07feb0098e39f61a4cbc06bfa153c598c10c5de57caa413752878c7599e5db8482b6f275db2185c505bc0c9670fa0afe37031eab994120acb935bf9dbe6cee6ba336dce1b44732c4267ee77f5db890041e547bde486335b9a0b85d6640f6534d84b3729b3436ac1c0551d687ddd8da9abc18689e7e932d5d0e787ab5ee5f36eb53789b9ba2b71d7a4f7994e56b056d4a042bd2cac79ad12d87726ef8cb97342e616269e9f87493e95dcebdd91763b134019c0a76e8b12789b026ebd1d9caf1930010aa1a5c348ae2e6273c885ffdf8731b34d87c293e77e9ef14709c2e3b739dec85d5bdb8f5ebc9eb610240576435c8d222ae0c8ebe5844980560bcfd45cacff143a5c208add9011bf9770b7803fa90bbaa10f58d856250b37e481f325c538e473dee7863957121374bf12172321b9c99975078e43a0e1e40138f9c31d6dbe5e06fc881de840e64899c0cf342a806916147de3cc342832a9514eae9550d2cd1166e823f404a05b418e5f9ffa84352cba3007f9d37e5b00049d7c099346257fb53e86b919b45a9c6cd8b67cb3c4e383fcfd5789f2cc087d6b459e2a7dc96d08c826c43410b3df22021855c7d413d9cfe7ca79fa860918a74941e08511595fc9a3bec2e2e0c6dad05781c0a0d6b6609837ca8f78b0368b1217b121cd6ced8fa48dc131709434eed65523269abe95f338bc5e3fce0046ecb24dc1ad8c8fa68b5f9263361e4952ca1aee9229811a5ea85c9c4452235639d1eb8105ff88c048beddc0f7efd3690da8b9bbccbbcfeddcf3e3c9e3ea7b46a5b40098fb85a25842911e42a714c2dd0fab403340ddc1af9484843b33c7f5bed80fbecf68180c9b397ed85c51d39cf08c5c0336b149e6d1747360541e84a93224ae88c1b62384b938ae25ce17d656b9ae52fcd9100a40dd7793ca67357f3fb00621863a490373f0db49b1aebaff7284d450922f1e5243bb7fb5f7230dd7cb8db1e08893696908cad4a45711eadfce8b0b42a9aa937cd011bd5c4a8c3a2ec771b3ee4959eba5e4a17545d1c86acaa4805e4aad" ++ }, ++ "ecdsa" : { ++ "addr" : "0xa16c987b93f1b3c51fa8a9833c8932eeaa566ce0", ++ "claim" : "0xb0c578f123a8a0c96354a13f98c4c2cb8a67541f5ccecfdd0cb6e61aa77f7768157dfb3ba59aadbc03350577f6f31b4083bec30291a61ee98ecb3db2536f788e01" ++ } ++ }, ++ "2" : { ++ "id" : "0xa5ea2fcff9e3cf29d0c6f5f147b67ff24aec3bd4", ++ "keys" : { ++ "falcon-512" : "0x099202fa37d5e165b88428d963d2a224b8fc82ac0e4b3f6a02376f18218d1aa7d0e910e71586aeeaaddc2a557124d6ab4f9a44b9cad02166413cbeb14b364e13956ea326900eb2900802644167639045d76bbc4e051654cff404dccea94402141ad9fd992cef7a8fa6478b3e6f8912886e9edd1b34c29385b7e964f360e0fb1600787934486f461c95d577d2bc74c4dfeb969b4798565ce0225ad27aac052290a44f844ae233e082c97e4498a31117ac9d02f3605c856e2dde6f611812161f89cb3a54dc936ca1e740a6c659405ed586a9a963b11c89b01746325e39e645c72b0c7e4491b36a17d43ffe38d88c601a5976f5a9636c964a012bfbce5f9b371e7c3b38580d81c6e12b8e8f2aac219f96245d35b4f4afa6c94015b055703b8c4dabaea4ce2577482f5b34fa49e56a912dd58d74580b1f94e1d2056594ea64bcdb696b0baeb33c86b6544761a3ead9ba9888cb1ad51f7027ee52b21e46c5eeaf3f77bc0af7efdc87acbddda7dca00b6acc665002c26447e5b0e0bb5ba261717c68dea7f1576462776954d7249c2fd0886f615ad50d53960ca02d581a4a25517c050ed467c7a820bce6250a9ba2e44fd67fb21bac843bb134c95360dc1c50d54b7280a94440d018181a9d6374bc64d782c84471b47287d8ea748c36cb83cffe053cb89a9e4ae71df497871c2a728ef210903e5b7f39550d0331e15637be7e28b3a2fc05b0a9b0c5a06f9fe81263c3a94403d6c288a561288ebaf788bfe271a578a1a795a85e9d452b61ac204b297090617286922376bf0a8d67dd35fd705b81260b7aad30132b965e39bc3cd64d154c4175951704873992a814814dae5c6bc1e89a83dd91144cd1b88f6ce449900058afdc53bb44bcab63d30cbd6df115a5ee8f5380a127a160e922bebf7b408de82514b2e2550a0931e065565e8dfc389d454823a55b03e5c989b09e3791f656794e8379b7b4b1617aaa9770366d63a657f71ff40c69b1d5da518ef1e2aa42366cfa38e448563f6c2db5e3089bad5520ec26105fc885993630c10db357883f588a5a384cd6de688e1bc3b1200f87ed66ba3d4a4b671b2a500a0436e0955904030d76577aadddb8c1ed21b027f198c072f654c3abb086e7f185980f49d0e109c1a82741809f8afd15ee56a887b392c5b172ba659144a7e99e25ba19792d2a3c0ccb481822839c8c70c65c0943a2994ec9f6085b7ac64ce2b35489a72dd6693d25f2329264e063db26ad4495e3ad00f12df8cf914fd846", ++ "slh-dsa-sha2-128s" : "0x686b5dae4aecd5618b95c3b2a5792888513ba49dd366ac39b7431ef403e04963" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39cf29ab9b80215a9947b975d8c6097e53b39d1483c885ff7527d7fccdd2ca3dafc32bfbc0a19c857fa8be7e52e25064d69c3b7dde6e77eee96ec77011fee440c8bca99a45b432b5468715a0aeff9d61375393b3ca40b9140e1a2bc2a52c3c8a85292f4c9e87d1e0c12fbe4d7236ba7921b8b83bd10ad554179dcebf0791c4b593c8a1bae836883d5094499cf2ba41b00c8c36c77a83466c263a0b01e773f08ec66d46e97caf0f9785943f98e159e353f0d91d5ab526279477a5509129f7a1b8b07ba82a1ccb4acd5be5e40de088f2600e06a8bcf35f54663279f04c74838294048a8f8692904d4f9eaab49635068df74d1f5ed238f6b895acf1364544747bb10ce333a957599594d766ac5d1a3ceecf8a6696cdaa95f824ace18cc551e1f4ec12f345283b366314515849feb5bf81fd203a6c73b5bab7c01b5c1131d442dadcb6bce32d6e13c5a3e77b66eb8f5b2912c0938d89ed9e20a455066d151a973e4509b03f5d66ff7ffb8b362e0c09b969e21173693d9977ba06d48bd3b85657119f9dc3533c91965ed81d1eba72b46cfcff285131f84306fec7b271a02dd22982cb6399a9060d286aa18a3f97666810937f8a5667c94959a4c27299d55e94564dba27ea3d98cb3a9db6197c842eafb237649de3fab72a9d56098b5c1228e70dc062617a8a6b44d46b7899dc1e53a77b700925ed1b438c59458c15e9b91fa2c2164b9661a976720eee2864efc5363d90beea9789a6d3b0628bf4695a853251c7f70ba1ebcea06cb35cb47d72d2340bb9412edc49626d6c78be644c4ab1c539d1469d1cc63f092ccac45f66917d89274af9c84d7f1108b1bd738408e499efa63f1a87c8730400ec19f9a59d241032e9ab78670e85e8da24310b13e89ad521ad4fae3deb9d438dd7eac72b79496c7b65061314ae", ++ "slh-dsa-sha2-128s" : "0xb8f14bb6630512c51d227c12a04ce7b316bfc0d255f5a5d1dec3e1ce5f5cc92927070079430990b4364200dc6d389fde89c78649e21d8fd3a17dd2de7444e77ac3e8c70eda15f2247300fd8e37e1e3c2afcc3e8dd674823106b4297ecedc924ca948a9f80afd7ca1bb85dc0e60e1ccd5d97eb21062b2fabfe94827b4ce5f0e396e5a891fbfc61bb827cd305012515d0a182f163c1a5ee3827aff289ec526cdafd2874c457947e8a6c8332ee7172197cde7388303992be248892e727b559c0d74a2c65d46b6686a48f0b814bbf031d1bde17f55b888e7cbaa7fd6dcf428b13ca43f77d80c3804bd2840e5768c2aa17f6dc773b71f83eb7803fd9e1f1a2e3e158f7e823e9667cebe136d333316fc670442a8c662930a00f72dd2dbda9b19c3dcfdd09c60ba55d9ffb5d5b3384d719d153566bc0b6da89d8dd869fb8c4113258014cd48a67a3591d37f9ba767ad70a554ec98bb59275ce163364915051411db73833a88cab0d3fdb7c491b8580baca2bc44a7bcfc3a51c28ae0a1fc12bb53b2b948c571397a348e664522ea749890d1c7ea7e9561596a3e930bca68377e4d4c0e0301472c8017c1fd5702cd6dd4c3f5881ec4cafb98967a57837c3869720268b61f37836d0c9c5ddac850a835318b17758a6f97df4d4966d516ef100b7e61271c45aeb89242ac7d2b8ee45a08f4081727d54cc08ec0f8af9e16bdf6f6d6797b9f5fcff9686f15efc4e8e34b363d562dba239908a3992b3548566a30cf04c424383b5bea0a5011ac620ee384f6363fca87daa30fa88763146bcfe0a160c071d79dd8de0b11e034fddc032e522b7ee47f318cc6f3f2b6c9b6efa0aaa9b9a9c1243750ea31ac01f087d5f4f5fb97b8296b0953a606c49025f5bedba6773804b15fb3638e72ffffe38ac20486e18eb21059f419b0af9071be12e309a953ac82c0a5a620a7b5c850027b39cdeb5d728522a15c1557e4ebc3f4f09914b3a99e291a814504ff7171c23eb825d2df1bad1ff29144f8a3babcc882258e8a6060272e95c4393fed0ad86698554515e77340ae806746ed859ff9730cd718c767e320ef54fae5e0cb8ba331bdb920229d6047a6db8bad147b75d376c3e72e06fbc6a542f51a312ec831c704099b2eb0f801b68631b464ef484eee077cb7fd9ea951a0307e08dc5fb4ed5a6e62048b010ede39efc5462ccedef2a4c61ffdff63fb3aae19b28ca48593532f051c716835a61f2fbbd5c25883f4a85b48d81658b6d7cc4227f90a81e961c5fd8a388c9efb78da1c9bc50d53a41d2d336232e84e3eb3444389caa3457ef9e3560c25033ed45242d0b4bed69fda4a4f1695830c843e63147b6c2d3f9bc2608b0671e59d827dc1e3876e5fc6075bcdf95223f73dfd11d64399333f7bebdda7f5c2838c072f7baf753a36a1ae8987773fd0ae5acec41d7666c84c1125190f432a4d82ad9b78e22d6536a8135d80a3d1715d17a673033d37104857278a75c2cbcbfe0159343dad8e98e42874e2b001bdb469c9faf79759c4cb3e3f2ccaa16bb29d3e4dc81627441d07469dfb9f545ed83d9c20ce586370be092f3a90b18f30866336c6db9d53e2e0fe1f98c655f1961997e41c25089a518f05270ce06cc115b6c2e9c04f6ba9bf7ce3abfedfada8580ef89f2fea98e8a19c58a0f3ffb89dadb05dbdf05c44b79ad5e1d259d5aa6086cb295341dc40ff800b460a5ac602a687d6feaf66393dd2be22264498509c9d39033aaa22eb248780a3661ecf0a05cb6629ea3d91eb0f68465485e8fa3fad3fc4315a118e4eb2ebc6e9b07284697cacf0257edf67c20b7b0311d3094f4647da567385a508addc9b25a66db1f1544dbced87886946989682b2f2db1363dc635e4cc3c67ad83bd311437d22d8f60a2cb7833c952bab293c9e20ec2b44e1f1f42a797421eecb2e9e9f5e47105b9e7f5d7bd796c360ea39dab45ad701eef0a76b7773c55e7af7909d456c213b0db14f985d0f73652bdf39a6402cee104a168749466e477d8a399469992d65656b607fffbdf73ca1bf4976d3a0c0c64cf5d260d6d3e0198f0b86c451b9ff5840968a2b60a8ec286c81fb55741d7bc9714177c9a77219d3a39dc1d6d7adecb7f8f85af366ed653cd81408b509d0f56b5dccdcd1d982d115754364ca3f14a6f100c54ed8ebfce6b0dc3de4435507acb0c4d974ae3f2453867a70d5ba078a17db34844ea410af4f842dd4a9879a7706b18ddbf94c7b43ba137f7f9b8b3924b4d917f8e0262ad10d083c4dd3b99b70560377ad31784a587cf0ea1f99d6faf0f04a909179f3f93c96aaeae014ea1e74d9d7ccd0eb5ab466a6caf8ed0fae75cba902ae05244e0dde35b8c0bdbb3354ac60875c454ab11f49e47e2d180db319a113a5869bad3ef4580bc7402b0d6bac10a7a4e81403634fd1cd272076074e714b14a6efefc902126df6091330ae387e161789198680b0258c341b6f3ec0b09c7674e9ae8f88699fb7b2f88fdf2461e11ad483ee11fe4e3ddd48ede0ef0a1e54a318ae12473993a8456dbbe8b5ded40232b8d2474a90424281830da7bb36091ebcf591947b04739846d8a600946c2b892e2bf3353b09b08e3a141f33f6ef83d022666d380da43991d3eae4e62dd3f9432678e8be1cd4b9569fa2fa84e95195449716423688aa920e2ba1cd41cd5538907ebdf3ff15df27900ba7ee09f3e9194e1d8cdc0703d6f38b2b887a89b10787986013f688f9a355c6a362f4797576ba022e4f1d1d74e2e31dd98f1b617b99516c944bfa5bb474857fe74a09976cc29c71a7f5b6fa529f3e0c00c33c2f0700064fd507461535a35c0dbc5b69d413fd6ae9af49ccc5d02d7abac88ef02bbd40475595176fa3b68d602469a89afc03359b032fc1f0ae255d623fbf9525bfa36ef98467d5eb2f80cf7c72a04b557e40995471c7adb8701409830b232693bf2fe905ef8b1a32c4b8fe3300bfc5654acfcde685547d5c1b0c213294235b31417da91464619822f3535c93549ab4649a59dc3620e7f4a3327c0e421c5d1a28a2b4c3ba8ab02950631ed54690cee35bc4147aaa8477cae505a1d1757d85251bda5fc91cf65772e1b543bccee1a2cd0c26cd33015533a0e72c815be8634efbb50ceb0ec3c8a3bc6c84638ae371809ab87eec54b934343ee9ed1bebca488d9399a1e347b1647d108652243cf2531a4685c282e0b9e526688a3ae1d10060a78467e6804b705c143d073af664cb72ce657a7d210240011d539cb3144e9411758a211238a872eb4be615d4813b64b8df446d2741db7c9f0af2cc4dc83c0febc41adb5d8413b7ce54ed564e899c0a5a4abcd1cb44c84505915afaaf93751b11bc8e96610216f71cac8d3c9ddb7282f0f864400bdee42c3e5645aea1aa5649485435ffec9e43d43e4341d967c9a89eaaea9cca12e2089f3de222e1a5034baa32372582023b5564909fbb67acfd2a40d5ba40de2d7a31cddac717f5702648c0346e197f99598dc83edda7ad335f9e711a0835c75d4c32e3305e4db9dfafe171181551a8dd5bff89f8a9fb819eca7a171d1be47fbea0e2838a1f1d01f4e68c3d0045da0ed7d3689c17319ef5f5d178e6cf1628402c40d2095c91f7bfe6b837d8f86c5b2585653beb650fc29096f13617ce6d36fd6107ac83c7d7f5a8639e519b161581dd58018ace297bddc3421d358be70179b14bdff66f229a50a329bc30b054a95d0f43e7914a9137055f4dda000357fdb5e2afa3d61b9816c03697168cc022f0418ee5ad7aa71617103fe17e7f47ecf7ef9bf779f157eea74c3caf3821791ab628fe8cba64c12d3226877c48b746d725c46b0ccf5a18f869e6680f1e5ef3c5e7fc2a18915dfd8bc12676ab94ff4401ed22133ac1e1ba0c0352a30156bd80b63eed4a7fe9c948921e1a9843127f1191751312180b75f06e33694853a05a24ee30cae0b02a0be49db16f6f06630ced9b5e57cad548dcff70b1620ffb17e8bf8c247a962d6b2a6fbd4fb3c89e3aa4381e15b92f7245ea700e76ba99678f4b0c998ac90bf3e4b9ba5b52140e15e4b5a38e25462c1b61953cc2068d0b9ebe014db6b8fbdb2fc05751667659f40ba1cafcc2055c364116a058e286f084c2bb73096d46f6736de541b750ad437c27a92ea51baf3478837e99faee73f2a2745918f81547c45f2b7083befc6387a73366c175d2be22314a1fa73f11571395c7fe9df062740c58b56b4982240c63b8a0d5886a3ddbf6ffcbd705d3bf3713a0e1b74497b8c1f34e204ad81b63f27cfa5215d275597599f60d02bbf6cbb229088b56c96d73d09fb3c36fb3f05f4266221984fe8559619da67bb7314ca66405cef4bd3086940c4a7346243776a6fa128cd9b6181d8f584f482c502fce3339f87e4fc5e3593b7a0a64c19fe76c51a29ef776e478ecdd5e093b2aad0ab3cff0baf73f4e09d63e9ccfd4aeaaff147ddf2e9f1e3e6cb3bc9757c57072a1a8076e179e50b0a03dc94de86fbb99f0e92338f26b6ed7c863830f325d3606189b80c8df5a763f422f26436f753168b53bce965c562c2554081cb4eb42d48daf8573206f818ae66d62bafd151e9784d6a9304996b4b82cef081af9b106b42ca4b6b0b2401dc21d8875f9801591234dec266f1f218959af60351178049b487b2784183349e0a7ab361f575fd0237d9f483590a23401f9085b111ac3d740ff4c3eae0b7dca3d149243e3b1fbabdc7431a579652d522bef7023e1c6579d2f6852f1acb9b7f20e3956af8dfbf14617f14981f40b1b2430920be14284dd5f2771f73091adaf9179b8396c6ad2a3579befa1e323177fa2598a3ef80ff5785dc2677f87e9299c6bb16ef2b2080e91f6fcf1b9189e256985e631a05cbfb6427eac995e683f494751f7ae888bb0dfd23aad7fbe942b8100d4daf62b6b8e4d647c818ee7edf0d4d64293edc3b7b6e08a8b9b71a7c38f55ca76593d35770185637fb473da423069de005363ec25235ce816f4df3070ff567f919f47dc4fcf57c168032ef8d7e3fdc5a6a1dace2513fc24f0829e8e4b964d37333febb1eeaa7b81aafe30d16fe64b6ac037ddec2dd9b372c657120df4372504cd14be89d3719c5aa6d545030423fc50e277eaa401e8bb02d70b6614e9768a7e42ba9b35af8f9e3f7dcf175609f7b91a16fdcd65a151c0e85d92dc8a06cddd1ff77d150ccb62c612c90abdad156ced839e837c79b79f456156a28c45f3287cb86a9ca664a13313332a1ed9ef4b3a3df864eda7bd55a6d8705567bd8d1d732f65a324aa6c77f6dd82517d5274343a4e16fc8f41f5a3809e9f2cdec445b88309c9d1de684032a10f8944157a3dc3d4d8d59721f4f9cc0b0e1e7a97b7b066523f7498e0902ac5aa462d9bd096e13c14407bef96b59297391032a4aef8c543cc8b60217ddd5a5d815c4ea1e21625b52e2323b42b4851b0bbc461abad9b71805e8b1b2a16c811be69140d3a6d32d7aa9d5321adb57570fc2e62618cac60a4cce2b011a4c8ddd4dd521b6864c7c4562d8270dbbceec91bf1cd7be926d6b66bf370839bbb22856d1f0c7b2b7119ecea6278793186c50b045d09a1aae7c5bd2ec54df1087cbd1d8094293392605321bd39ffdbbe510f0e8760bd35074c4b0453604ca1f5bee056175ae7943183212ad527e125d2ae113d83c5a4ca1e63e8d89ba07ce8fac8257fe1c603031a1fe2e41bf922d7ffa0a610e0b91eb8c3147262fd228a4ab54fb520b49c91ca268d3954029be8677229af3ed232628e7d3a752e66c2171d1746b7e31d2dc8d1781af454822f36b3ff40f7683fcddc5aec46b13890a6c7c9531f30eeca923f198f4b57112a94e34673c88c70bcf80ee115de27ef5268a753c6f827e71254b5bea2a4f27c8e0e2d0c3f72d051558700196e80abbdf452bd70116c24f635d1850f9466282ae761f1a38a8a0fb5a02a9e1b99df55616f0a7c031fc34f190dfe5cdd4f2442d16ccb49187823fa90f3f87dc0966c4cebbb7472d8184e37522acb165f5d3b508f6a62623def48edddeff361d5ff37fdfddb2b324c4f545bfd5cb98d258edee6ee6170bd41135ddf4c9e358433330a5b590b25fbb276a2284b2df18550270b32b65d9b483fc42e9610537f27715e9f451bccb73e1ce017aaa39b65db4e86c86a50d0379398e57e0c34fa64f73acc0d2b4e953a89ca2f8c01b10135c2af5c234dfaa17ef97941aacb7cce96cd05fb246b76f15275e4d2a8545e52726a48f269d1a558aa12588cc78919a5edf6c0e9e576ed58c92b67d00e4197905d74dbdb3700fbde85d26de20cc652581608ce1d1084b507842a0373fd8830c8d3f68dabe93fb19e3189e486840715f92ae4d916a9ff3424b45ded24780b31fb7f76d506339d9f9a545fe0547c675bde44a3b490bd3b52e3b30842624ab5e8986161be4ef9da785bf537954d3c716da5597a859ef7adb40fd8030611d3ac6581e424ff636aff72f4dcd9f315744a3dae6cd386b2f9945140071a5a49f05e8f979115678eea7d6d884a92e4f14ff94dc102355c3aaa93e02723a92417ff49fe8cdbefee7e6c5e952ad240fa7eab4c7941f6ae8d2a1086e1f2ca73eb8ca5fbe3588ae51bdaf18646ed04bd185a19bdad69394ac15d130297c0fce9d8fce8ea2729dde117facb274f9865ffb4f2c7248102dbd96767483cb7fb764fe667d484a3143db514f08577cad8bcf695b0d953e2a3c8710d8979952929d59c8b8ae62ff678815130e68c85d4714e832733da40b933b7133725a40a12534753eb4877c65fe4c75542f28d6f9e805789995adaaff6fce3929e6027338281c6d0c33aac092fe0eb1797dcd953fc1f815df794249dad7b28407c50371a8c81625f6e7e08ed59a98758a9859c41f7436f937885ad35102b0eea85f3dc4bb9a6260f4e091ed983b1009275d43e4960f9422dddeddd09e9990d545cb67dc3f1061238dffec3ce01376259262b4c32c6173a6f1e239f4502cfb0900bbb7e3b4883ca3c64c8ba91cfd80b2bec6aea25b01124ae11a56ab3e4d448038795ff62e9d5ea5cfdb99c5901a8b8f8731c772690dd964cda343bfd020e920b32910a68b433ddd01d117a833242fd695a54f33fce28b506d931adba499373b0a6182e54323f032f1e7b8bad58dabcffdd1cae831c70e87b2c6fee3494dedaacccfdc93fa23ee1a4273f16adbbbcc21f5d02d8645951b93287732cbca4c61a0d0549345160537501b8c0dfc97128035875e73db7eebec24813d03d11cbcc089929b0f6e2440a26d90cffb6295e8fccf65b4d676abb8ff66709913775e611bc843302a475488c9a9310c0c8885b78d5db5cbb1a919683cfd9bd010cf2f1206ab327122ac87d8e2899cc1ac684e72c91f2d36c7bcc3491b768aac86e92aeb106d22b3e85112a2a871bb8c9d0a0dd15c89d113910f8babf15f27a13b10200ec7078d362773f17286228b0d5a58d6654b0fb4f60c81ee581e507f17a044e6bcad4bb6ddc66bdde7d311810d79ac031086d7b0c334cd3a8a496591aeda23b2c0097cefdb6894b352395dfc79b74a6e4d086656b0cd9c95a48640cc8b3d188189ec0b98c8618b0def4b0175f11369cb2f107e89c4a67a75396cfcbe899334a5d5df5927fef2eb8bd836a27a2834a7ab94813d30fa8431da3178da4ae56caaeeee66cf545537ea260ea6af56d4ba048076ace08ff2a446080a6b688a916a13b43b933e506ad187b1f829a1d54ae261651563874cae19c490004205765b43c3cca4cd8a309fb1bfd7520bcc07794cf7c03d9b1d1ae0cf646534f5a97106925ee96dcb7fc1f74e62c01d382fde19fe027a4b9b7627c08e690abe3ab076f184210acbb4229d483f7471ad551eb614c35e019a8a894b5f92f5371fd6c457f135ae8377c5781a8f3a6dadd2c00697bd8399b6f168dd64b2d2d66d5aebae90fa5f904af9f950f450d8be919ae3f02cb5c0be9687560cfab2d2161db61e978ef46304de248383dc3a99e30573bb66f873ef1e54f523ff8ff79e8c05e7f8143cebd1bdd9d2186ebdbd3b66a0a3dee79475cda2890720ac5bc33f8cd3e817d82bd7c52c34d491e1e9d1d307eec17c0c7679af3626e7b96bbe6ba2550f44de7d1d88b3e4c220b8f185b459f1f882a97248cdfc3d42209ff44806837750b3dd21ac5891254f6c7f6938aef3caca6c55b633770772c2c06734f84612a59aa8cfd4f347267e631658cfc4ff89cea84550bd43699c1d8840655f39e3449ea0d2abba1d81196413302719bc9b39cea85cb7db6ab7f00683842cc480503004c1c819ab80e121d9d21f46f362614a5f2cf80cb2c8d3fda82447cd0155fd7e0ec7589a6df2e6614671071f0f956143c762d51172da46e9f61e588fbf74cb3ceb74bf2ce4ec4ae26a28245f98ae91f09cae77c4660d6dabe7cad33ac506db3000d742f683e08bbd0a7cb9eec72a1a976546ec926b9faba5084e00d66475a514a73f01fbe1e79c0ee0066f4b724e4977f3c1518d28ddc918c573693e9b3fb69b426df0640c5ee42cd5533655f9a82c6843516298d05cd970f34dafa886995545c37b3b939e0dfa3647fb3f330bbd3e69307be3d469a99c24382acdcac76c6cb71decb4b7b11cb5f2e63d112767a7d6467c51f1c0c27900803180337f463e64f507ce245f606f8c1f1df836c7fd02502bd3127424804c69f1d066ec3acd9c4374e857c4607b711f532867cef2c1c8a7d7051a440eb7a8507500d86f11567e2fc812a27e63e5599059af1ee90444497f69add7862b93ea050f100e48df7a578d55b6d6321e70ef7a7625ed89054ab010850912088fdc21551b89397c35ab582aed6c215e00d398a857090e2f7cac21c7b51f34054a45f36157edc603b5d6e76ce20f2dfd2c20158943efd2349560666ca38505cc6af776e0720af2d5f6a7d98f385854700fc0c749dafb597e94d7ac54aedf34840ea778e8873d6f1fd7f53de7c06327d08d34a03b38315efd8eb52683ec1f9abbe2bcf096fa4f379f41e09b8bc67ae4685e68ce456465b38892a238b18358714fee41da0aac8dd729e2c3f17488470648df81040272b2e927e896a4eaf6a11c457938421288ff074da8db60d37c6d022e86952341f2b8d262cba0c5a6efb51925517a8c817a152499ae7ee56d36df86253e6b2d93079c89fc922014b03da3941509e979ff8dede44165ca4cb698924fd12bcb02a35deaad608ff3358d455a49e12e944dbb11ac7e9571476bfa856f3bcf90ca9bac6d57d5c1755104b348d2924ba9b14e9ffb750cafb6edeca6dfb79d73b9839092032035ea700d81f19d035e38bdde754a5098dae1c163f9c473b0681858004ab9d9c2c57282ebd7e57c474b8f7aa091d1048b95e7ef887767f49d2a7f6b410922da142ab8605e735ff6ea9e3f36a29380ec43dd009d98d8c20f4052d81fedfee6cb018b2da59d63b5fc153d5b0948d613415a6b8a2b7338897188582d2930480d897d55bec899723b285dec9abf819ac7e6f39d8c35c484ca13f129fa4b334979bac7715bbf5e52a9926568f359dd3e3e000958b561527bbd52025918ef75228c423da41861396be4f829aa4bb6f94f65e662e6ac91e828d721b741d7333a8e3050f136a463af537ee97af4b42456d65e1e2324f72267c07acb88c91d0cd602ef765f858f69fcd44ddc73dc7c5f8825f3fe04affee769f3ab5486232e35df8fdb75db79721906907ffad83c57a364ab85d93bc03ace8998ede749d88985ae41cef163a3d00f568d43115992362c581745f723a2955ed925cfc7c83c5b5188812fa2dc016dc21844f923b2362afa5ac5f2a6c9355b2eaf724606333f152a01c330ed88f7028e716043330a280c5ee458f2032c8163f5548428ce4c529d487a16ca0e58cbf41dc4dc802cc5ea7fad6a50de0c0f2c2be49c3dd2806911ab1322a30acd4fd8937b8930069fc1a6de86f9ef90f407b2563594adad581b49ad1d19b30ad13efb0ddd8e6f26dc43a36ff8d14d1c99b073f5f1ce8923d3100bb04488b86cd4e89f7b9f5b9cbbb3f86ee03b498ae255e09eeaaba3e4e4d68f1ee4d50f699e460a922e17ea8f0ceef9794e944f128efe835f281a7662f959054aa994afa3982f7a310f46f53d5ffc07884aa91bbdcb3f3779ebdd7f90801e96222f56df39ed9c2bff5d4a11be1da7482835e494b0856ea7c695cc1b53acf3b2e2d1846fff50bf55be65e16548c4fc436f20c50c119ca8eba4cdeda8c7e4d33734a0355586629ca5a7c3591ea4b15428a81b6d91529485004cbbf60e75208579ac354dc705edc7bccb32f23030e733d3f549fbb841329a01f5c5d263ce635a57aa9c69432e5213b155a07c34fe19cee737cb993fdc82ff38eafbeb734f04f58d367e34df15dd6044591983b9b45d4ffd87e2a6b478c7d1e86b4b974991b930370d5eaf5edbb53c3dcda643fb992b5fb0725a8aaf8a9e7c4012311f197179cf1293884e2356fc5b624cd46358d3c7bed1fed6b0305114cd11675aa49c1b9e6569817d34fd60c1105833d78dd00117284cd1722074a60655dfc428072b0d2eb881b93d6c367952a4bd59eb902032cfbf9189bf65f7bff592032c77d61dbf778986b491e297ad0da5b367c8a10c9071b8d509b246393fe04a290b3e2291f04eb750285674ae3e9c7b76a01b679787a4006836dcee956185d3b0ce16c4567fab862d3634b93079305008e2f99ed425489bcf5447699b7a7212fe2196d3999b39191e750fda742c6ffb5509e3806f38edccacbb8bc73c96cd46f0f400c4012f1205813d69a48bbd1f55724c7de917ab56d4188716b96653ebe4fd1b6d5d252f5599f9c53a4683ae60c8c31b86982f32bf73401a328891804daab93a155140fdd41ec87e392c8397c9ecbc48f26acee4e3cc279cfd67d75b5e0b6484274484c18f72c2532b4064cdcc309df796c802c17480428c3b5a5467b38aabce03de2a266c8a22d3b0158beb913d50615a1002fcbaf91edc529b0cd38f35138bd71dcfef1b6b90adb4e68a594de40199724c158db9c85ca78ce3a19378ee90dac98b23e1515324fe18472a4ca93b004295b7abd3c146109da707f5ef37886fe1a8966ff1e96375fd64536eece72ae3433a697492955cb182331ce72e8f1804efee93b1929338f" ++ }, ++ "ecdsa" : { ++ "addr" : "0x5e13d369c8adbd8079272b624343ee1edfa4a560", ++ "claim" : "0x197e55da82eb1daa23a5478ed230c6d0452d3c1920df15e10a8d37a7430a7f2b69eb474bfe0c44a6e4a55db9d5a0e0b74549c044ae22778ce30f47a9fd1eba4100" ++ } ++ } ++ } ++} +diff --git a/consensus/common/src/test/resources/aere/registry-v3/n16-declared-hash.json b/consensus/common/src/test/resources/aere/registry-v3/n16-declared-hash.json +new file mode 100644 +index 0000000000..2fbca8a3c3 +--- /dev/null ++++ b/consensus/common/src/test/resources/aere/registry-v3/n16-declared-hash.json +@@ -0,0 +1,63 @@ ++{ ++ "description" : "the file declares a registry hash it does not have", ++ "chainId" : 28001, ++ "requiredSchemes" : [ "falcon-512", "slh-dsa-sha2-128s" ], ++ "ecdsaRequired" : true, ++ "previous" : null, ++ "expect" : "AERE-PQC-REG3-16", ++ "manifest" : { ++ "formatVersion" : 3, ++ "chainId" : 28001, ++ "bindHeight" : 1000, ++ "count" : 3, ++ "0" : { ++ "id" : "0xaaddb4dde09de5718a906d83be7db3d58e0ae32a", ++ "keys" : { ++ "falcon-512" : "0x09501c96d2f5cf0b28fa00c726e5359c5d36a1fa069971f854b7d914fb2f1295e68b2c6fa91d82f7d287f55ad493c87320bf7ca2a5d5e79d7212e8a540c166b588dc03f73b83be060525b367d9f40f5e77e7798c60b6499767586770722820b3b9e6013cad3eab5fe5de96089a29f34919a2e9ebcb3fa03a3e714593b7a3356d11ffb3441ab40ad94474da662a71aa2419dcd50668cd5d8a9017662cb60998b34ab5b7929c58a94d5e133ebbdadb2b0279543067f76bcc4cb6d7e0a5edb7625467e3ddc92a01206e1b8dce69be31928687d8af4d26633a07e73c2830d5299b878977691cf65700b65b6ea2463e51b6136888c544545e59fe8cf190a7944e215a785b682623c95a79eda28e25e0e1b91b49ac89deaec3b14a3c431d9046a663170111ee541d81b43aa91f29dc147c6fc97739b3a63fad1ca84843d0a65b8d9396f28e9b11f9a41453ab18a2309ae8db03253a09fac8f0cd634c76a5e938a44719660944a95dff056cee43ea99592c3899c2880d7181ee3dd5c04baeb60e1369a69430a66031e3cb10e392622f5246a71761760cf417dcb40ad65f60704fb74ad26f26c3af7513a42f806895e0298c25c049187aa536e0eba21998912e621846c2ca0e323744ba930a29850fdb385c8241382296ba28dd4df05ddb1e61fe525949034b59929a784406de240f8086b4074825f419d5472a28a0b157500be37e9f64897db2b645d3807c48dc143266c99e7cc1638ae278772493a2a4ecf74e526a514bc9119d7129c5a0d115a450ccf4dce05b76d4b6149fdab028006df7ec2209923117abf7578a082128cad42aa66b69eb63acee4456bebeb537ca57bb3d3487f95e4f06c5cb29f292d3b6284e5a162cb83151cd9ae56aebbfda150b7edd5065302ccab70892733a1e096ba0da5f51b42764ad23060eb197d5460425fd9c7a26e7dc3cfd40eac3643539feea72c9ed41569111a7976d2c345ac2183fa2271b424526709fd9aae558a23a5cca29f4e2f31629746a71d904612e95ad9977bbe74fa32e90fac62625838cac49f50e5aed4e8879e2ce2e5651c4f4ba0c96583af9e1612b5ff1a6fac5027c0a308815e592308170b915b4a2de1e8d48e9a5730680ea9db8f3326c430241153b3b218d5347d5c843570cf80ee813871ae10f6b8ce4ab7e4c5197045e85b1cb4977f44c33eb85894b6555b4bd288a50c1b656936841048983c00a01631f10a84522cd613fed0d4beaa4aa4b3e9f30c324108d909e59a80150", ++ "slh-dsa-sha2-128s" : "0x47a0b70170dda85f843607f6c6fcbe6e6acc7c22980c108996a3fe72dc9f61a6" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39c8813cd3b34be58eaab900555a67486034b1923e0b00e435661230cab85f07690a5958a5f5e9c84f033a3dc2039a5296443093fb7fe8d41895fa73be3fb34cefc6cc36750d534e6a3c47307294694729d6cdedb633e8efe8979a9aee486eaa66136e342c578761241192610185feb2d3c196bea0e79222437b6a8e08cb09778d053b29552df96507b1cdaede8e9aa7abc18902f29937f30e7cee6868f349f7ae33738237dcaf86b8e8e01238f3d8ea6fd4090a8161db65dabeb5ded5499e8cc8a5b32607abc291b36a4b34b327d30cdef18c1825232e69a2b09d539ed84dd2a4756efa64f864c563943b3db825824f294c1bbfa2157347b0fb0e7f8a56ec253b39ca9b6cb1ef7d3d7c93a6cb220a7dc50c365905ea5a71575c3aeab25b33523e4fefbaf66137f45c3d96db719a12d2e2d42fbd6cdda58c5a1b958b28c2a8f2cca297871a147dda92a7f008a359027a9288e42ebcd6ea9542f10b66dbbce6e7bb914206122f866d9adc1c89cbf8bbad9bc9517c2ea9018b61d4d2df9abff1dd9f3a0a6faa72a449af9c97e8c4090f3bbd9824298e61599c13c7eb89677c0e845ca2907c728d9296c24e96b6a348dbea7cac62671c9a78a531463614ce321e28ca2f093094ba5f69881e6cd766874622ca769ea556ae757cb7f9546d99f5c90c25e7b8e14f3b7f270861398800b0604ec2a3374659277a23cf6131c63148a41b05b3c06e2a98a268f1b9f0df7969addef17179ca2261d3c229ae3db0c490834564c45f7b8ff6d3bf70784779d75915fb2e2d5bc147bc941b9e249af188f63f39b028547cf080b7674b228e20a600e3b167610f814daf105226f3c1ce5e07834fd33dfe46315546e926fd5be83fd4d47ccd5bb8ae736ac745daabb59c87b9edf9a45c9a1d1617ee84e588f27d12235c59ffd9", ++ "slh-dsa-sha2-128s" : "0x0e8f9bdc22cad3613ed07fba30ed04219b9528f9b657119e2f0886dc71cda4afa7d462fe8bb108feb58d998b370b2f7e162390713d1a17eb7de781a604041cbed13d00effd3b24f2ff87cac74f61e7b7f7aa6a259dc283485179ab4bb966793be018c4bbf4475bf7a69e600a37246908f662813813d4b0f4f83757f4064c5c0713870a0b98b5bb99025dace06100497fda8c73d7385d123afd4953961066e7c8544de3fb620ef5e23174327c2b64089b3fe6df3eb86e83b12634a0c9cc0d7844c894ba6d83afed6becb6f5abcfff397c5cea8064e5e153ea4253abe599dec1614b449329ebb25861b69a9b22228d1a03ba51532ea64ebe7603474a15a2806d3dafa29d57d27c5fa894da673b85b4674ce835fcfbd391d328ef83504101432bbb0c83d7be462b265911aad862118af6f4cea4df0f1dd38969c69428fe438d59d22736fbc7dd5faf6758905b26ec4c99d71e4b8fcc562a694ead91569c9a916df5ad693cb2ad0b7ae4c4f3c5b7322f56612c5449e0339dbd367460c76ab89b6f44942cd33f35eaf33c2ddc0c6af793556d5202fd1fb0f9fa1b7ed45c6ca68d904e476477b71a0bc6ebe248c9b4585da0c7bb186600691269bb4c836667a6d73a455b97127d898b7fae17e1acc6dcc3bac3ecb14da131d5f8adaa64b054e2f569d9bdb164792038e107848882de9bbeff295905c2af68d4c6dcc8cf718c2de872ab6b3d18e00d527166f8ced642281302e2acf4cf4489072a2dc3d55ff8716619cde494be1763dce925438b33ff1b91b35eb511645832720ed92552d4880ae53ff6516cfaeb1d48c923648e502e4038676f7c82e532ea713c6b9348c80ce3c5735f437491d3a8b1765294868c14123af2e9ff61e394216e630c71ff976072d2a1c50cfd8ee1ce27aba5bcf9aaed4a51521bad5e5d5e66abc7a95b215fc8004364aa4df2b8b97b14e3950f521b6327a55fdff9139fb0bd35237b022e3aa128d36c8a60f4621d25d28c59a97418c7dbfc15d900ba626d283632732631ec4a948f66dd9db3bee8c2cf60dfdacbb5ad4c0b2b31f8428868cca035e79c95bcacaba40a9351b2b44cb29753b6b9da0a751bd5af84c9094d5fe91e97501d4f075392290e8516ed5e41b41b00e09793353707fe5c1d942395074637f3ee0a0f105876d6f28a74f9558c5f360e98f047a99af35ccedef8d5cd299365e81e7e91f28a01eb265219e21aa7f7ce56b62f9d2a61560f9fa39f2765f5b50920658100a638aad03482a687905cd27dca02f1deffd1bc49a1be1ea7ff1a505da74fd932937d8f6a8bd75ef456d5f7b71ca5357bc66db6cf14368c4faddf4996363251e6a6113ec64d642c319dd85830d8b4c7ee1437ebfefe01f27709ba0c412c266530f5b6bbb005994774e8935f1d91069f9e7a8cd2bb7ad6527768473affe24709c10294eb588aafca85b379bedf0b142b109e1b186e635b0625c4e59576266acb5f71040c44035fc9480b13932bc657cf332b12da1cd7d5c3977f51d5fa742974cd256e8e3662dc698e0516d615d0a05ea9caf12338d0dcb6151e07f184c9cbd5e59bc40b12ed6372e2d6bd42aa0eb6c3c888f264a8c0d3332631d4919c921cdada6bffbd01ca5445de0779f9723577ebd7e33ab0e5f577843aaa6cb8cb5f0508c33b63913a44d02b76bbb1eabae325581738fbddb5d4fdef8dcb8597bd29c6ecc631839118c44f66ef8dedeca65e58941c30e0423c40bf064b8d19d28dab3787238781d492720236a7ae0695ccc867fbb1cf207ebecc64f84daea66b6745515b9ac9b725061bb9958ed79ad6161318a262528004401633d47a023c645683e36413b8653fa4864fe98c501197c10226b1732337842a1322bb788a00a0de86758139c2d9ea3c5b26bf5d7a4a92cab4cb686c580e3e6cca488136f0da9279073b3dbef9519168ba02588fa29cc60d02273805b425b919a7e2e89c9086609982163e09d5f6eb9c66267ac7be363aadd4617d398d4bdeca37a838d650b0919faf13b78642a058b1bb96b2ed1482cef9bc6e8b2e061e6815936e15a9c754353aaa786ab141e95e5f6c464a41b8bf29e28e764abd638abcfb342b54d08c15ba7e24e6fcb69b844e16cdb5cf4f50db60ff0699f969d8e68511fcc9e16a58e100f80671af6b04ff3edda3a4f05f9183c0c3bb7c1061fee2d3f04e33fe75f1354e6de54f582da914da0138e8565ff45ef52f638cbc33a24bae863fe91e58d7c5da34273438f15e10d4f59db16e505620d97d3fa4862a4097a659925d0e5f4e073103ed29a600b051b83b1f3a21381f4b871c18d262d7e43842c34ed80661438c064aa2fd858a8f3bcb035b5e942baace7b50e4de5a73d5c51fc0843cdc163958a62d333078f4c7d883bd7055a602e04c853f9215c9d7f798403c007fcee124cf6099322629c449ad4ef84b7356110798dd87aa4d98ebb47abc6cc8748dd381d588b77db7f4e7550f6ee1ef4360dac6d6c7037a65297d4a0ea7999a5632b90ad48fba0a916846a216941fbd13d62ab36e1066e24990c19592944078435c52d7717b3556595b645cd2359ad151dbb67e92b14168cac12fb2cc5422582a50bf6e99f116751171c9b78744ef719282f1b84bf95b4092514f4c68fb82a1526e0942ca50e186632cd9b0b8b8d91e84f85e35f30f815601798fcae676da6a2d38eab62f22445099694804a36a34142150fb795afb445e78c241f0b645209037a8871cb5487c975975ac997a540b709e3df6bf208d9d8017f9688b152c9ee2b934f65393de8403244b7437108e6d8c973aa723285555d9eb92509b1747977105cbac7fc33e658fd51cd374d21fc2bf229928948292c1698db7934d0f9be44b137514d0a5fbb659bba83861931e03698a61cd20a449d0358a5fce7f288e18bb3eb62b7ba0ae75feeec634fc90fc45ce45239c5e3179309f0c202cfc53d9f42a617f7aaae586e7161a0723ccebb7e8586cd40e1fa12d3ee89b400dba8073b0080ffaab1182e8243afd93318df15bbf3ce179f21804fbb8882e855ef9e0739ce1536d8ebfe9856aefa9874b4e102e705a40ca4c3ab0ab7df63ba525189b518796590035ca780d348de49f0ba8f28456ca6f3e3cff7e761d961ad98b8cf01e855797c88fe2f811e41e787f3e4becb0ef42ca3b9979356020b447294ef295543e0ef512a247e4d356bfe3deacca8ddc5255e6ad047121eaeafe61d71e7f31395cf78890add4f8c688e4eb065479a63ccb3d0c09028bf60c700fe9d19195c26fcbd4130e6feceb52e192a2aa2343c05b43b276f51a7c55dff7233ea512942291900d93315438a96af08e25ea5b9ce656c54e71ed60d1eeb1665ddaa9e42378c930e21d93484b9a4099b7ddd71d983b4c42c6b1f62907ce84b24321422b08b847f1ea97befaa4ec30a794ad7f340210c800cf185ee2c6c72e844cc5671964e1e1ec58953500f149f0f0f25c34d5592de421c2e31535040020237b907e86d753094dd4532e1ab9d821e7583d4a21e1041fa7ad711f29ee3721a2aec6b0c46866a2de71ee850d8122f722898e533848e2bb851ed24cff9ca83badcfad88a171b4be064007aef4d759d93ae9b67b446f3c6fe504f5b4fe851b8312fec86b46ec3cfcb36e0f682e65e117702b888ab8566c9cc716a3a86106d2323c0f7f20fbc1fcd110bed4492a750befbfcbbe16820077dee281bcdf14509b93137a3998b2fdabc2a375b38857bed12bb8a9c67bcae7934d02d6ff89620fa8946c8aa524fde99c12fec0e25bd79788e2c15fc31fa3f27502cb952b9f9482580cf18ecabd92c55113ec4c4470c4dc06d8ca27a10474594eff708209e8f376b6f17915c2966dbeb0e35ac2f02419692c0d232e133b3907059d3a56ff169e7e61915c8b1067e183337b40bc1136241e862eb3ab3f2c6a72b18511c4107ed063d1e2303d0fe6842fb01c204d1bffad7e90bb44a365e62945a7f631811c9c37ffa5ac39c16b4835798686da5baa8e1eb6aa76b42f6b86863c30669486a175d6b3bc5bc47c5eb05b240bd921007fa39506c6605bfbefc9c8c493973bf3f0767817fd8ce126a301c5b8fba79628a9b3a03cad0c491a5f487dc5e89269e5d3bcdc2998a136a012486c5bce2e6c6dc595aeee2ebd5a36dd06919396184aafb2301d1889b668c4d701c7ca01b95f9508f47d4c411cc0397c244ed4e3e3ad7f97d86b6f8834b13b1b2df0625e6b4eae9e439815e65baf2da767d3b1700fc461fad6297fe4e8ed02bfb65b750c2d2801b7308aba9657df3c3ed7d548687f55e85c22343d1db343bc2dbe222fb76fbb3cf490cee7a99ab3a337c626a148fb303b2f8651651588dd4859fd65c95820ee2af85adf4e8fc2c03828ea7427e7c6b0d4a1b0ccd424df6d1450ee436c01351d8b6bffd4ba072756315968845ab7976813d93d0f0f2be1c00faab3ccafa71cd26c5837e87292870cf768c7837e18ddc3c513820c660870b339fc42c5211d33d892ef22b475cea3be20f5e47206efbfdbeac208e26e97c400edfd41f063aaa6b85a0cf86e23fb11274b405f4f796eb10cb97e70783909ad492ad9207ae7b3d204e59d69c886f91bc82a107d0be3ae85797a7cba747b8e2640ec49384f53c785a84cf8de37dd4048dd4b879c58768bd131ad7226506113c446fbf13d769794f1535d58e9c52e23c1bd55e13c647d304e297d968c759a378f1d594897a026e3271aa6b4daabe174d6a35665b35193379f0ee465df7827299c18e1012ac69913a0a5bb5142e99b051763de3e98d5af8b62133e25b32f4f12b787bef7e21dec42de8e4d99a0adc8f365d8cd3e6a5ff3064ca18965ffdc6b383f7ad08186d735a099bb0ee14506388c1a37f7a766d286d748d404457226b952ca6cb3f317b0f4399006b5b8c6eb89f6b8cfa023cec4d2dedde3e31b9a633c0888989b44ab182a5aba30ba78640f477ef1202f6496fafc2a18e283b2e4e8bc60415a1c9a7fd68f15cc1ea0299e3b26f5755ad9f13481a0563a524c6735942f5069dc1d6a070b3c3698e9c503f67a11efe59413e937062668d3439a5dbef197d24ebdc79944b17c549b0648af9b1349cad83c2a0a9e55fd893cffe2aff4626662ebc5014e70baaf7cdbbdfd3f92fcc5eed863fa8afd87f88873f726a0a2eafe41fa81edd5833f5520cf93b0fbf0660e48eb0258d313bafb87dc9b0d0d9349f22fa2d960238f67457ad644bdc60fb5eafd1c88dd2a74db4da0f723a03df08af6c64883f275395020341d9dd3c7fa049ab2bebb4d8af2bb8dc1340d1a80088c4b2c26bfe7314926ee64bf239306c05dc2ec6e6c5e0ed4f6dbe51f5ee09533f558d29ca6fd27092c20dd892c89c83223752006b23e5abecfdc733aaa59c8549e89e5ab0eae1b44189f58cf9cc18de0c2a2f46a9235fbe42c641a890039cf6aad820f1f844edc24e69bc3bd0c22cfad3804d876edf5491e88cf891c347ed5f24464f2df439bb30742e1f9a4a7eabd9346c6a5f93af22e67becc494cadac82cf9cb693acf44560672cb9227eea2575f90b0e28431684ae12ff2e86fded0be3a099f9ddd32a7285531de8963c9a03355f1d9cef88d7ed9b842d0066ccacdb698d42ff9f8a4f000b9764a9aab1f3146f9f95e6636fdfc9ef91c4d060a54ed7f32167e7ac50590dae3a2904d5d2eeaeff2930bd4cad7166fc17edd2c30e6738157eeb0b441491e5dfdc17a7fbb2bdc6426b2cfb26cf2a7e20013f1b3e33a6d6821928443cc7893f7e4a5268a8b94a6ca6097d25be17b214ea4301e9a723194983bbce286f4363a53afd9e94dda9c761481d9d20c7687a2ff85d42436b9d557d5dc6c5e24ea21d5231487df9fc7986100664edbbc51ad4921c5ec9fbb407ab33ef5c3b3bc81f113e68f38d73f0db0261b656fc344d2d23b93446845d69cee1704834d98737848d405f52f5a7bda3dbdfcd3af3881484579d2d2f3ef976cb35c9cbb76252f2e00019363273489b39943d212ccecc647413c56de69e0087532223cf9b28ce3f77fed30bc3ae6a0842b546e0e1a8b6f6ee1ca0ef1b78c3ed829af817099426f94a447f67229cbca3c07b7a8ce547c5eebcf168248e0a0b9fbeb398e5ed2d0dcacb441f95f9e30c108c725507e459d34c1ec01b67065e5e202d685502d6ff015d46c20bbeef1db38c29df7df585b95d79f5687474e71fff162c0ec0c96c94c507f8a0292a8c32168dacd2fff78b5c7dc145e10fee1b25c478172af8f3ea132fdcad75dc22856deb2576a5ff3e8911842c811d1d57ec203c77b82da3658cbfee18d140ac341d38a30f1af298cf60f2a88d0dfbd3e079ae64a07abb4947cc042925fd5c64bb5d4467589f8c495b0097073c081517bc4504dcd7442bad7e7acafc894fcf34f535979364cf5e908a84e0e141ae47e2ae4dc95462b4f345b12b0629502c7bd65579ec66b2d0a951302ba6da1d1176db6aa0c0ea1fa88195dd2248990fa4aba88490b1da4ea405649203f6ff6f734693f40deabdad59ac62e3296cdcbd74061474dd7b63c46bcfe6ea2b0ddb0f7e77fcff3599892c82425b05ae7aa1a2ac1dfddfc67e11921ff4f2c8f6297881dd5e38ccc4076cac8015c59cdd6023ffbd62b887b33ef8d917446a8941d9563acb66a6226fa4d3f2cc21604c080b3f83e73c093d8f2f7067c392671020c7a7eb6fd0d97af0d63032a3116c408b708d4b2f711c1134b88a91aa359608550f0049af2bb97688afc4352a45c4f6d30d4634e70e82515ff1d5f77851ee857e42b486d5e1f3e0406227dded6c5f47eda30d94f44d978322891dc729eb6ae95d29d22c8a5d649193d5d2aaba782fa16ae488f645a7ed90a566e182f97bc62049724f4cb5fc71f6bc7be57f07a7afb9933f6706cc83483cd7dc4182768cd35bc42f1e9b54d5454d3a17e734475ff58fc66d75419d3d122eff05f7b0548188682f1318ec32c5bbea87c8624cc1e548bf18a6b102e7a43e6bafb579e4e84275fe07d8c63ace449a44cace5d9305ff756cbf40e5a6a20334d5b4a74ab0483e31593f2277e90341fa8036496c2bc6d2b7b10b0b354c86d666d65cacc593d1d7349e71b0360d823453011ee16b6280f5c048111b99b185af99e9d901d4eaffd8a96b1ff394b66208ddc1e7e53420fa965bfc4e630d73ad97b9c5c6ea884c619bc24ac3f46234e7d8d35a12b0cad7220d7a0945cdc64fee9d8852bff872c43f359e7aadf8fa3de3551fb716704af68a18f79d03b3c7d90cf21eb4bbdcbb4004f8ba15ff0bbd2d0918ee78e9bde980e4f3cc13558e6fdb40ca71ad2c10f5e5587784bacc6b925f72da12528216895e0ca4b350d078fdf534fe01bc86b45e0c8e2b35799d268a457f8768ed782dfb56abecfd2b9db00cd10e189c6164f82f5ccab423277e3465ec72d76b696cafc1cfa9a7fe47d142fd6672d9c5b77751b40801af07fc53b1c9da0fe6981ea75e066572f7272baef8fc54bfa7cd71cd0fbc5d6cd717e9aa07808496ad2b4b4005a320c9312c73385afd61193581dbae99df6c25f1b9da17093ccfb108b0a26c5ae4963183533ce2f0ade01bf5e818af613416433578522b1b1e5aa7c791570c8c8b26ded266399116f5789a8233fee128e54ca8ce63fd56c1a146c3006316d200e05715993d1d97907ca83d7fd42ef7e7222eebd74f9c86b6cefc82e614a53976272c8801bdcfd882e34d86b39142ac05088a4c47010a71107bc72a380bb3e5122981d1795256beec20a0fe568002d79a4b1577903fe8682f268eeeed0a97861337ffb6861bf378eba1e0957111c7f9fcfeb55a95238005b40e13ce40efe846ddb86d14c9ad2c46cca74baa364ed08da3a3079fae3a36346ac949e2174c661b8801a051423e95dcab6a0f9c965e8744bdd0e629bd3c1a1241e99951ddde184eb8f354209f24c04fcf10fa8f4e43cb55c922c28be041213ddcfad65c86e1ab9b615f91d5fb11e4cdec5b7e25f8e9811c82c2ed457d012e4967b555f228baf4f1648854c624e0525e36e5f4d1961bfbbc3621d79bd6bea72924d8e0146d0965c239a768b417ea4c33237a60fff2760a9dbfb1113a37b01b598f3e06987d99518bd9f1ec96cd7050863898c8664f793ef29114bbeeb9afab8ed09358d1227d7de2aaac0ab2391cb2013028ca5f4d1de6425ec5feb17d95df358572fa27fcd51d14c363a36bc37c7497a0f964a6c004561f68349f828d30d4633e87bdce6b6d92384c9c1c540c8295ea621e9a8006a8d7c163b988853071e06c78f1b9a0246db052e8484a65cbdced3a587e45d9e2b49a5501590cf768d08b6a043971110e9c9dc96abe855abbb7aee2c38bbb77e5c68d61f01f2376b6122450117240532c7c840e3739395dd6c9e80a432423fc5e3a6dce9dcd58eb418e16d7aa507b4d67dd6fe2af4042a5c7398ba4f87c650926084efbfdc9430a4bc2be544880ecdf7361aea06a25e4f592104b0d74312f2729a4db5876b675bc0fa68f6e41e014b7caaf6f49b8ef704b6243df410dce94ad2c51d328fb90b9cf2f5df645015f489a262f57a5aceba40a56d343403b660928cd7a9d165f4a5bc289c0d28f33dac85c9c2a5c79b5ddd22c744a0388a5daf4bab84d7c77685053c912c9a24b5a0664c6253febbcf552c4ff38bbaf2f7e0c9f06e69a91cff9138c2745b99367e00ff6b6a920b1812e17ba44175c033df0e58d1b5c0b7d146f861b62e812ecbe99d638219e0dba4dd88089005977bcc90634c4dfa95f87370d905d32f613358fba2efcface0b9a414ce33b09e271a647b911843933c5d1008fb0717ab59739eb8eb844a4b34bb1a8f635c5895afa285ddc43720e78dc81eee7db822896bd9bd6ae3e7fe2988ba560d58f02592870647b94aad1dbb0d0cb60e28135ceb72e0a6f4b7893a56eae83f9d9a4c549d53d17c6a00f5d6c266d23e7a1d13e22a5fede3a7082dffb34296f8fe9f3bfe525ee1da81efde3aef9b6de8457a10fd4340809e1dafbfb9e2719c327a3c3a4c51d4d5600e8a01ebd5c537a4cd7c4519e963de06de6c83a9b968b01f79e08b5415c5a9d6a92a633d6ae969b80cbb2cf4d6d1ab2c3b94e7c12df27ea89bff4014d92add41a3e961006a194ae3ea4a6b38c2827f6185ae636f6846b1c8401289696fb10c765fa93e58d068bdcd8c9dc95df572f096d65f5de42bae639d41ce7e1ee0f48ba4faf856c0cdd728956d7e4babd6d9d6389ff41d76c5fbd6380f351b05a37022dbce0a6a47ab7168c82c77a2810c80b1882f825ebf86cb7f6d0f54025fddc9b9120802514c797d1d3968631dae95297a857890ff1dee408909223d012925dc08b7d1119fefca7466392a019d4121ea76c8b4c3bd103a820557e4b2283e262af32f1edbffaa253c47d5873bfd0219b8be86c7e64ada2d87ab6b7f428a7d8fb3ae09b05aee71054355eb83ad76c05d836a9f1a65511b1553927ef1b19ab1576d7185af61be6104de1df218918179c6321846085a83bd1217aa63d0b03996ac1fb4018a8ab54fcf635f7d5a8ade95894f0d407e5d4691920f21094c6f632f1661402a0b3351f168f16a13d3a31ad48e89230cffad272926487f36c7a2584c9387623df6227be8c96088db4a21c93b1c88ee756e960f60e614b30bb6ff757c20f3674a7ae7f6ff6a9115a0a6d444513ccc0be5dcd557430e0ee8db3ed5b3e8c405110500b9bf7f6eb7748de4988a1db94bcb16fe33479f64762c53a1e2965363452063d7bc14386ca7b4d46ebcf08489c64ab413ec0f1ddee8719f5fe978d38438ca3059961ecc8480908cfaf139d88db2facb5e7a88a43a67dcb0f97a17f9bd5b09b8369803ccc7ab6d41238e59e43762965814c10c36fa4b6e61bf2e83c0243f20ee8aab62dfa9827aec06f99c5c565c1bc75291292d3113503a202851c26d1a8bde54bb30f0301e555374b71e278925a2afb29b0209c08ecb89601bf612ce811a493abe2bff78e7fd02ee13c5db6b3edce7c87559410b9be3be95465468e33af224d6508a44728cdffde4cb14fb96a0d2ab9c7f597541f9963775c32ac613af9beab89e0ff7a5e35613751061b0511532b10b3947802901505c8e33bae67ce0e28da760af7e80b730811bdf17abfce39d35def51d73a084119449038c2b0f1c86d844123c6e71f28b7038053e279dd11c088dfa11c547a4ce13b19453e88e5b74962101412490cfb68e21d8952db509cd3a814387b67339fd04ddd2163177589146409934f0eceb10db2d90a9e3f6691eb75e84d5e66bc3228baeadcba200f3d11e0cae090ffbb800f5da7032c35ab572de55beea37258bee6f191addf01739a26efaa612991cb2a3c6d1bbb03de0ee1fcf9b7f6c51e452b21c0819a9aad93162eb2dcc189bf355ecd2c3e504713dab24bfe3ed86a4194611029f7f6216cd469fe1f7d35d56b6c8c2045011e238f9cbc0a19b8914d74329e2472f15d0b7d60511814ad2736d6be168aac01868c2a675549c849fe05e05a76f077130b46896735db5490277b76bba43545de6b8ecb53fd20398eb94dd884951fb48d5690ce4bcd0b836615cd9340ff0cdee1122743accfef343811a71c7d14d1369fa49ce47784a6ff8adc26c151edd4969dba513ade6a9b1f009e57c3d6aa845ddee275169ce58e1f04b564ffb6d0eec75f7172e5e8fb814cd702c9fbea8a783bff637db8667d4b6b48a264135bf60acf335936105abacff0351ba9aeac88e9522cf7ed80069822a7db1a5d8221d9492e02ca893e1f15965fb82a80ee2ec491027bbc8906e71cf931fc21e1c0865ee06a79c023929625b4d232c7b3e2e4a4e5dde28fab675391befe583c95dadae71dbaa43e09d8d65ba36d148aa85d1a2a35dc51719ac0311ea72c1237c78a8b1542c59de3b743087245e54d3111c585b5e5e7642f625c8d44c6d9cff50d8d071f6fa573df937d9e7457302d8b293d8fd94ebd3023c55f8b260c3454e93f58f16d0f451189bf41c9f9b91d3c3918adbf98e4ca5aa0eb6314041521ef880ce18f0ce296721a06b329bb5fbb3024e424b46400e03caf0105877465285fcb41a93844fb90b7fc1924883ace6ca8a37c9905068c633761163affae39d0ba55b67fdc6bcf0908ee3a42af286c" ++ }, ++ "transport" : { ++ "secp256k1Address" : "0xe23c5bba38d809fcb2d3384f210e9a6405beb498" ++ }, ++ "ecdsa" : { ++ "addr" : "0x48fcd978ac4d42ff52dd81fcd17e93190f35e5e0", ++ "claim" : "0x2dee91bd2cbfa906aefa3a8ae6e2de773f55dbd28e77bc329d28215183068585601ab9a7f9ff0c48095407474d502a3af3f059a666e5ed1e27468466d69914e801" ++ } ++ }, ++ "1" : { ++ "id" : "0x690a7fd66157e5b777256ea5214f634f61b3a72d", ++ "keys" : { ++ "falcon-512" : "0x09a6d094d9a3a0865864e9a16b477236f1ca26c888fd0c918db331c87a478519c41085cdac7e6cd0d89190a41a3bd6f4d6300995d591f5e22a7b7147caab1f9c7a85a4ba74d47c7b227326ac17535de039a7e604225d3daac7f75b9544654b73f79f5825825ad6e6c45d13e6d385a644633e1c8806d3a0a551c98f032583c95fb13997e52a6b02192d26b5a47fb22ee52999ec92b75c70774a4ae0481a79113ac72346263e53d5dcde708668d317dd00552d5a40ad47e59a501b10a50bdc52c5c2b2c920fa0e3dc9b8eca54b10aa5ab1168c88287dcf80ecd880a8fdec85b6d63a15b9f453845421a5d9b898e6149b60454828eb9dad6442ec62ad27ed72215014f3d17539085ea3f668b0a9183ab96e9db996801c72a0920b02a249911924f181e8dda515d114beb83b075ce7e7a0902a6971e31420ee4921f5cfc123f29dc7775017aefe99a7e326119cb925f6f603ac3bb137313609498d5a2000c426cb332c82500dcfd80d70a5e2d156844a683b313266af6d60216bd9e9998bda53c0028f387ebd21a5fca6c0607d54b1e95724746d15f25f16e45845926a83c7598646a0a0d3a8f8307c1a401b823f1656ca41e5499684150a954318da076af9131fcc93361d9bf0ae035f617e02cb5e1224a982b3591b24013ff80dbb61160d2ba4ce85a4260c8a3a3218e0ec869796b1b04a82079cfc0ac26da03b04a11950b2a3331ecd0026ea9737bd20e6ea3045b56e3c71278d2a8c72c8014b769da9319e19dbe762b1943e5a4be15aa84d0da831eddbb10bd05f35d55b6211d02a61c5d9247e69cab6c112acb568ea51f345a5bf16f84782e04220e217722da71d634e1a68b796376c8a49a965c592b87d06702fe42dac12da108d24ee42a109e8e4cfd3bed6ada5e3de50301696bab0564292864f1b9f47d5a53cc0c5f9cc3d57051065fd57064d08764892ef4c4a92b475184a4cb4ce1f3a0e6da0402414db5a9db34632b9717586e799b06e870b81a330da7be6a45ddfb000fd337a24a29e164449f96be015818c53aaaf09b9a565d7d9d735b9493885e7cb49a5f1985977cd6824fd62f51d2a1e60289dbaeaea148a44dd8876cb58b8ca2f29f6455f354e4e76aa13290f2979b78b22afa0e65c696c21497e94bf0141ac6298aac70b5ea843848a2264fc057abd3593cb17465e06d41731b7153b71f8f0f7a06d362fbd09845f0815794050460b41ad003c9396a86eaab240555ac8c75f85c0ab972c1a0b94b67b1aee2fa3", ++ "slh-dsa-sha2-128s" : "0x2b2fea4a0edd5dcc2f653eb2dd000aecd87deffbce8818aae72d7862b506bac7" ++ }, ++ "pop" : { ++ "falcon-512" : "0x3968f2999d69a9c28ae792a90a47363e689bd4b349e75c5f837181fc7b16d3d04489bbc32252d750d750417770630c5b65b88cef918ad23e33892a58458e9e63ea591596d3b898f65e1a5be3d36650c3d9834e1ec725426960d337b8f25878525ee3c3798b5afc9add5bec82c8e139c59738aba9ed5f42d11c886472e81cedfdb5b910eb73e884e0d4cc218b87cd9bcc0bc107af586c65b3949460a25892d9607efa341f232e478f3c9fc2d05f324ee6eb7bcddb72af371d47c36856f488872249ffdd322d3de7d12b62b1ec595187b5b363e36cc714b765f0ad5616488300f6e56811e88e359365d5698ab123b917bb32f56566958b154f6fe052b894ccc1fcd99d65d19e8117a8ca4887e01f36f181461a433fb9bbc1790d8b14e34a097b149f0c5c075ecae3501944935f3caa76f0b9370ebe6b90390b4d059f9029ee4af98dad33b9050877d49c3d4f2beaa4b5861a21af95b8c52f9ab4b0eb115357f5b1d25fb66a36b9baaa4d6cc5a4f5fb5462432bd82734d7393cd22c68f52493eb3434c3b88fa255baae5c46c650cae17ebe59827cd6645c6d377b3cdee3aa6a758ad3a96d103bf6ab8ae03b72b53f3aebdda359288c32ff5461a158962924a97a24af29f6c976762e8de9363485ada49c445566e71ac75379aaf7bf190a81c671115e842b5280a05bfb2ef3724bb74487068d5b5ab2d089ebea7ffb4381a7e96233f0915f295d3b71db872393bb990b9c74717bc3d72f6271bc248e54828a1e090f6da56de3643b083e9695db7d0a32bb42355e245e5cc2ed57354d82220b449e10cca1cbf6fbe796d141591d6f71e4eb6770a3c7dfcee509c3c28f2f1988eeca61833b6681e6766790c2a6f043b4f67e145b908ba7f03361cd9d435d054e11edd9667e4f9d12c2d74f2832b619", ++ "slh-dsa-sha2-128s" : "0x39254afc16b1dd8d4fbfff766819460253653dfc6a8e29abed55ffe91325afd578ebfa2dbe74d46b48b381e69d269b5bbe24ca1b85767bd71c744065fa47c646e3603b44261731b50f2d20a7a327e98b84c5ece73697739c8057f99d6ecbc54cf891649fa78b7bcd824972f3b27820ffda3629f481b1193b922cefc907bde3ab1c78b5ac97ff26986f3a553556d0b158e936450b4f41bf006c90a9758e0efb327f67408a7b803ede993522cd9042db4a672c89d4765a0fff8c6e8bf6882a8de432229dee08ae13def90f9fd0a40c99f3d93873a41d74871aaf407b0927a817b476eb93c645254bbc77d131e0bd35a2541248172993b1064d5b26b921396c8c1664178051810961039b15790862415338806329a45a266aece5904312afb1cfbeac1e816fb96256fc6e2b059c25af1966b0bf261bfb72afd8652feaedd6e0e4bf829a75188708ac9c623d4d6699281913bb563b96818f9307b66f7cf4aa9591e30c65a0b0885c22b5d17ff610f40bf2e0a9a32173b2fa7d66c14784402885d84f33fc75afd8f743cd10f5ad6dcce5b33a8f0c0365de2ce1b69aa86df2482a2c2d3746c6f0ee4e6fdbeef5738d809f6b0ef3cc703b0d29e93e198b68d62a5be657e69c33459fe4b163a5ecd72a90f1e53fc00bc8c698af7ae3cc5b07e36cb74088066a54138d6df4ef6e159ce5924b6903346a5fe115272cc951e8713d4b6f96f78d67a542c3bb402e69bdb3c2b06e189186c227927b2aba52b29c14e837b37798321fd000ed3bc0e386ad6e5d3a48494f57109322f0a87f7dd752d862dbf772498154804b09eca84c305595cc1e6654b1b2e94d5b88feda176aa144d3895a249754bb2ea99b2efb4f61b828f265638866a49dd3437c70016347d5aae64c79957ed394a85cfe06b10b98b6e83801728645529537a1102bb04ada4226688594cc28aefb24fbb0d1a60c7b826dadd23f301517e862c67fd88d0f6a5ac08e7f966ae375b468e57f01521b43fc24c761838c174ac106c4e1f435b7ead5e79aa1b303222f6b45c5515d497d8e7b05901bee96945652d304ad9ebae2153321885f19e7ad08c9da73ccc22a66c26c4cdc9360c36e307310714ac44c80887f42a2575305ef649378d76d297dc6faa904377b2037618f23b8be496fbc680645dfb80a76bfc060c6b2aee4ac5537e79b7dc7deeca0ca38041dc877b875cab1a297190269c987dcc46ff34e5bc154e2572695e463542be79d61fd5e96a4be2b07f5beb71b882f99de317116fd0b36131a88ff9707eb25594fec74cf76c2859ba6ba2b968d41479adf8857f4b0f4a26f49f0f04fbae0e2f3c2ab6aefdf01855a7a5a4b8bf516f4551a393a33d3920ca3ec403b4d37c2106d777e3d5dfa768614513885d857ce95b9bc3b992808e7ad71575e5e91b8107c5802043b221c74d73c7bbfa7a191945bbc5ed69e20016b16e2e2987818cfa80695e58950b0c1bbb8c474f861d1447161744c75d99dc8240338c43a5c19a8a9f46d80f6b4b6c1cb57f5a3350bfc35a0522f89e3470ccd71a458968c629c93336af6b5b091f569d1fc9492eb6b976376b8ff19ad9318f5cb1361954a0471419b4207dd9dace8c0545e74dfbb19ce3fdb5d456a1c1bff7383c6fd96dde3a92daf0ff5a315714c74711e3c05e0c59ba525c64ebd17fa20f8e143c5931b3c77da193415e6506c2db27e0e773a6a5b5d47ad95760b8d471d06d5dfe000a2d47e6e4e6abe7219750f1f7892f4e09fe88d13c2e3b53dc904ad58eaed856a4abb0c10830b96bfc1b5764f9e4b34b0072be314608fdea8c5005d40ef99806d4d3edb72e73541fb828d4b2adc38855e09e974293de25da6907f5ea97810eff1be37f88ea879e545bb5a70d2187edec81bd57a95c0314df4ad08a864156579d50826d0cfa511d335ff722e246151a7afce94126232f6bac89b13c142d29e7521479866e35b17c15f16ee89d798ee8bfac5868e505031586b81bfadef4aafc2ecdbde649f63e07eb6026d09910d9d3613a9871b5d1523cf5958124f96b5304d5225b4bbb03aeeef87753d0b6ab51a287df1e9031f56f755d3fe5a20f79b7f0f467fa97eac5bc09a1adc6ec285c8f80ec5c184b8b5eae326300a5bce0b1d757c8e4f27ca2822e73745009291f0d9032051e15b567511908f3ec68840cb6ec6018a9a0e30f2e34759743ef0bc9e12c9b32f29f4b70a998cb8893af2dcf17e0eb4f48e7ba367f68aea5516e7248c8be1d1f896d7e8446fadd9603012dc13126878300f0868bc512221154a5104882621f831e60b49d04fa8a701256b3a413b9db4abc5af10a3f8f4c26cd0b3c2f55a58c9380143d835b759bac7fef824515a18d79b6dbd361541047c79653ab4af5473b7b7e67a6755add78d5c14c0a9edc6c7dd42c3d0359d9f2f6961f8930458a34c4f12478ae45c20969c4c18654d31a7ae73902757b3b8a4eedfd16d6c0d22548d7b8ba77aeb4c1e3f3766b6ea802ee9bd92c5f98d00be80c15e7e3a82eb0d100436c398781607dacbefa98c87b3558f363b3ecb1ff313655838f864c1b2e0f6d6369bae4eb8cef98f564108ab2f763e590a9e9201f4e28ef1971438c30f4376c55cfce9b9910f448e31d06c2e456eb798476d56a890660e45616840377ea0574d1c066ae2fcc46f41cfbb511e5efc4b5c60e00e4846e157bbee5fe3bcd77408e3bf721bf871c05971a70cf7a13c782bb4afbdb1ef800a414260243fd828b67f49007eaf60b3e32f4e2b8186291075a0b1c0a528abb9da7974b3b1e8b20d337161ce234db66ce82a88ae1dc880933343961267cb4932b36aacc5f136cb474bbdb5e4c4be4cd74868775d80317bfba00ca4e58a39d04e63bb797de366c45efe2e356672f567ed1f7b2741df7543d6faa7227601eb7cff367d5a1ff320ca71fa2a1a42866239cc3fa5eba400ee4060266a05b8fe1e729908b95ba6aff8fd76b5e7df547df62cb89f0605c1207c869d7214e4e6972ea6e47b18235855d6f28265a737b4f64f0d215943f13d219292036c1cfc46bc61679f034919e4fea80d882a5121cb3096a50f2112eab265ebf75b607b93e14ceda4e08152221bd368cd1503ce375188d23514dd0936bf980d4282eaa6fe8f38f5eb00c34e3557ae363538a2c15b560b9f9322d1f17446e8f3fd317126986afc2c5e9fbb96f8ca7148f53cd75a4b845a28034c8679baf1f5406564b6e4b8fa8e681b5a9d208f3a1b28e84d6d52d4baa152524908d50d71d9c0d11bb5665c8a6bad669dbf303027bd0d534434f9e76f2c300326e25d00bd8d3bb1debe1c3984961c0ea8dc547e8cb83a8f3b044b673f4a08882d103d6eb143a9645a9a00fab6f1167a2c09015d6ff2dbe4aa4025f604a63eb32330f832162b6dd9364f4ad6afbd86c8d26f56d7d9028dbb3051c85a0c86ec0d7961fd6008f87dbe8347fd5ed1dc4c27285364f63650f161321daa83ad41fbc3412bff800c062a78cc5caea330cd58e63ea9a9d6de2ee069732799f52f49d513c658a44a2122b8427a405d706f740600f855130a0ea720f76b3111dafddf0e2ebbd13f60640379993889089ce508b1343f485457cb8e0c09760d3199b4ea940d584417259e41f2c66853ae4235b6f010cceca3859952b3daaab55da14adff0e421e862f138872c2577637b3e12b00384cd32fb3b9c97b0d59e51f2488e379065d79f5a834b076ab5b35fe4c47f2c4c4f43e622527abb8f682fe9f262d2883fce5c9f16b7566c4e078b67611abf72cb8a0263ba12a6c23b1a04458c759f2bdf6dbcc460bc5df48146468073b61aa5ab4a9c5f6c006f54f1bfdd85373f33af29d68580eba4cb6dd88054c81b3bb7f2be8186e380bee0b32a1b84ef6319798079828080361bcc27473a9634c23652ed6b2b2c8f8d5a6721551c780870f1787726b121263e74c9464a76282dca27249b4532e49455a7485e2cda4ccca823f62d3b2869602197a6f1ecfc9d92ab6e231996e603e81e3dc648aebdfb900a3d929502ff0bbb3dff813660c9d5a417d857c19754ee04e50f1241831517fc2d2a71c5e238a944992cc50b7106aabb5482fc7e0a2e6b5b11bb6845f34ede98a18d5f07759e61603de502b5eaabe59a4d2c69f4b0f8e73a9bc85b8950a54bd91bcd0366dffaa0df736dbbbc35d6accb5ab8b22a870374521f2035c1878718d7d3b025838da75d8bfa3ff36b2a10a3cdef1b150abf3b6be95a5c096a921a3eced20f509dac4ba43f2f515af2b65d3b2ebd0da2d7a58500157a666b387b1814d0a3e84f64d0fc44507b0b6792c0c6bd90ab62e0f75b66d50b6f842cfdbecf1fd043d642c5d5b5fe5cb68af62e6e23cc6f0f9b1cf3cbd0233ce48a996296b6609be1c9e7a027cf76615dd11208f1fde119099352cc17e1c9a22f4b71c3e628d72b620f3cb4bd40e4294ff8dfe19480b5b758b874a737e6092254638a222c83aac52fe0f66670454c313adb0dba2b4e95741d27104bbff159e999e23103c00470a7feee6f4a35f764ec81a8ef520cf1e8623fed3c06b63c022e40e7638db269b8add119fec50456b33224c14486f705e5b3339c6f38aa4ba6dec8b098c27447185ca50cd70772e5389ba703a4a9f8649946671a238e1f005aba0b3a18c8ceda9daf4cede6782d27931c638af3f6083b2bf10ff0a632ebd4dd528da3aa2b7a8bddff2901d902b26d518a058921eb0178ef08e24f7075f77ea0c0d0e72f29847ac7826230c0ddb5e7fc8552ff92c007e9141f51384a12e218da4fbfa9a7a4a1bf266aa975949e120db1b6755ff04adb07c66ba9619b40396072e7cc01dc3dd56f7a2f928a82c8906be416f6d5c41354881f9a6c66a927292f8cc2887aee86e90da32fa3bd9d72bc26dfd334f943305fbe4b645df83fb72c565f61860a480dc0f2f3360368ec3715c2c4a312bd2653051c8f29fc14e0c3d1f515e04b75ec02cac2aad8d411306969d9a8da08c3477eb6201bd54c6ee643d87a89c78a5c8ad48590b7a499cc44ccb812866a4c48ec2da5f1e0aac741464b26988459f3724ea4cf103c27e4a43e5a5fbbf94908878894f8b62995aebc20e632d924c82d9669f64b2093cfe023cdd1542c8f9d19e5e7ad6ed7920ba6834cb0cb91bce48fa94be47c1833c6ada4090509ba38defab7d56dde8168bac8021fb5a2aead00809f1881d53d26fa9cbc824488e16062fd9f68726c837234a82d518e3d10c9931295d20d9affa5fd18c0b2dda299cf1d6fe0c6e6959440af9b397f3441bb9881ba1d2df295d12686ef6b0bfe52fb2bef06620721374328551040d2fa434b161648b058b74df2a7ccacd7609b93421f44a136079c79a3e63bd3b4f79717f3c121ceec2c3918464f5619b1a2e83a7709fdf6d1004b0ee51c73e740b20e329847304a82802e02170db386e360dc6027aa7ba1ee35d7eeddb41ffde093073d92899d568bedee914627c8c48427376e7b5d5ebdab30e58147dac5638090e9c71921431f025f1d4e3ba3c68437555357c651336b326c9c519544363d5f4faa91914195314cc873ef97068d928a6b4e5c6ad70ea7a7b09b3108fd5696aaab800eafe463ee52a3f29e1bbe8a968e84b762484a13714ee260759b4492b749c46ab6603c13ece34e301c13bea57d9de706edc839f55b432b9299d2d6643817cd9d32d0d9ddbdbb23acef51992b62db024365ac2db4c432c531cc1ad18c807cf1ee39dcd842aa9a09b232cfd09bfce33277a8ed09953ab3b5d24e5a8a02fb4a02ceed705185880ecc47cb245665cf640ded4015b4afda053a5d1dff77e390c8105961cb3a954c28ddbb9efd759080dea99e94e69b03b928c8667fa4797dbb3cc6ed093bed107c817780f60729036f13346f05491fb837ef1ffc61be7b61d0b7f8dabfd49ec24cfcee088de38daaae6b4e740ab4faf16eaebf89962331a99f17ca5955b15dd1fa493b91e7cd218aebbfaa7d348b1ceea26951209137448caa93fa466ca32eda497a5b9a4fdbd23a10d9742e74c511a1648d00bca3ca23abcd4f18b7cdeb362e020c73888b76b83e70d26ee358c06933f77d1221a8ff0647200e451e971fe45c23aff60a88baf46f59a0bf94e99ab9337b0336ffacf8e79db92067d2b744134cefac1241dfda288f5c6ab293df7469ae0926c166e999ac99c8871e571eab03f82de73e9de2d8f4deea3724f795480cd47e304f27f2567cd94cbed52e06f1f1cf7af2feaeba8b95927eff950bfc26aa0cc3e46ec7bd5d4aa43374500f8cad4f153cb586620b9a0deeec2cb12ba48bbc8655c7fa70ccf94aa6891b5cc8a3c98b482d906d72e9d425301d0cc6fb4ec9c4a5bcdfdd74fdcef68f05fdb78f2a1c5ae32c28c43ee900738f31ac1fd337ce95966b3f557a727e0c3ada6c6aa61219d92fd5cf68fcd9b444f6b4fb6178b9c74238d2575f442a298127f282b5ad416cf6a365a214048489139918f93ec07f2cd864f5482c418c7336ca4590a7da8a20d33ffb7be19934c80b64f4b982a55b129f4896685534b83251d54e46a2971c0bf49ded9b13a77ade3de9a61f2204a46ed9cd7bc444801381994c8ca5a66abd70936f8d11e2a2fed78fe9fe8889dfcb979c9a3f11f2c2c1aa371d1e98c4fbdaa95d58c6b22410c0d3d3460077dce654a1decfc829f117bc407d06ad9ee6aa06bf818ea2f25312b1cbbb5de527ce9b5c5ddcb0df21e3442ffd149b24af5e59eb4d7e18f68b02b26e57fdf23e7af4fde3e672990295c37186ca67b2abdff6b46e1ff106f041279b61560ea2eae64649c65be22f9070c3239b0cf7929b0778c43dae5391d8d3b8c335ceac672376588a34d3b9c61833578e8d5a9e6e9f72748d860d7af98f7616431d1ae1ca20db3db6ec99d59fa98c25a1cf478e1b4a643c2fc9d3e482d56bedb1b7a1fc9c3e788d9de281c7356b82e3c9e1c9414a0d14cd07fea5364b6a22dcb3b69b6f447343822098548e3ca7e88a83187db145bda17f7c48cb00e6ce36d53e2d1e4c169569ee3fa03620a7131bd5c033062bb82cedd0d0ebc1025937b2d85a3cbcf6ef4458a57525a66244be3a62b582bf2b88549431cdce09f6407e1bee83d3fbe205f585cc7cf9c1eaba047a01f51e13bbe0715a9112c451f1daf6074a1af051d8b98863b6fd03238ebe295995d60e7a26d2f95a2b4b0d617af299133bf357518b84e942bc36a88b4030d91a7067e7a2ed7bbf4e9abda8c6887ecdfebda04dedabb9ea833123507835e0357ca1513b471da73102605ed03297b5e3eb7d3bd01c670f992a7f19962b706e8d0ae0f073638d633b34a1229b6979b8e90f2a536cb6024c644e1f7ef211451dc509e061b294c28be188c96246614a1fbf52db8d9a99f7100c878c1b9da98ee9e9eddf7fcb386061ddf46807c60b24d665f0fe7fde205f91021bfb87c8f4c89b5da254d185bda9cc2f48303b483ecbf934575aa45d0d58cea64662f0fda4d97790bbcfa237984cfb45a9cd611b533dc0ea997d191d14d307c68db318aee8f99544fd48fb86f041fe249a14263e6657a5ee732f7c5c9c97a8924bfdddfd75dc67da65042e711a3cc144f46d10a1a9fdac1b1b321eacd235299a1fab390df24acb739d61bd60c6907b9a3827958198e6e2b5a1c90cb9b44cf8db9b6e45f710d7a39c230ec9cd855af797555fb1d73492e29d17da0b6dac59c2ccde0715565efa1f62898c9b26438c60fc3b9f859bbd33a8e05e1d3d5a762bf19bc7c32cf7d4c6bce26fec6e5c8c537608a1c2aea2e1e5cca5bdbb45a8ed048514ef3d298e7dfb9c5408d941ded6220a44c184dc90c922a3ae31c9248c5f31627389770a59f9431fd0139c5ac0f08f69151a75a5a6a0355b7beab6be9829146ada371aa5791c861dc77598f09448af20deca73cf98a399f35c36f1167ba426c6cf4b8b9b8a22b961bca83e45bade098e20782a9f70bd54fb8eb6eda3acd3a5bbb553438cfe37e1f7fabf15729d6bd562cfe379d586181b71b3d3c4b360852003c4363a8d473198130642972eb3434c3a5ca9b497ec7000e821c3419aae75866496bb1b0a9ac6cf92f799071e06809f1f3f904cd18f32629e2093664755803f62f45942f5a358cb1e925a8694998cb14cfc52733c356cfd739c3976712ca7b007e08841639da14e429c102a8fba3191cd36c1c56eb06bf69afe3f2afc4ebf137c617faacda6baf5cfdcc6462ad02f63e8a5375288d0de5700d0f9f4ca82a65bfdc405d3f96fc663658f0aad91305b86ead3b21bd6561a40db0f2c5b0937ba5e1ecbe91e9c50b1dd6bd83a8145b033a7bb6a4ad4896e0ab160e8a52d39d2756b1c8d8570f7081ba217fd8803954290788882befde24b4971723b0ecbeea14d23c92eb6a0d7022a84aca072729d7ab1a88927a25f19a2086f846a44a2726ea26cf1b69c58243e219c756d06c361e1e161bdff0eca10bd30d23782b3374ed421f50cb66c9ee063ca622fa78c8cede932848f0f8f91bd7a0eaa324377c109808bd66ff463a72389c4b49f2e349be70d07fcb56b28549fca65ad853d70df66b587390febdf6b1881cce6c1ca9e9fdbc9f1ad68ccaff97234325d3c972b57ae5723fd73f975ba640f90e717e9284c111b76367c6797399452d37df6b8b8d22ed5e7dc1481a415fadc06673ce4eb6435d31acb6af68775436629a57db7a0aa192310e8427468e8e310bd3426b7ffab00110324c0c7e04ac6649b6f167fa8b928b3fe12ac162db3f2bc355295650fa2d976c64df69a8017034683bb4bd4baacf1cd8502dff20430d48c907107acfc4e29c584cb497b7a471fbde90aabab25290d853b8ebd2c0d49c2c201eca42a68a15879cf391671946319427b237472cd35431128ea7ab6d545617321592c07b09fff93e71596da30689b3c15368a1c3a57890e0ee5752bb4356290024fd1bd2ebfa19f7f3ca57c36d296ae61ec5581ceb77618dde2821460553ba0dd6dd68026b911f4af1be3986198966f90ab757aca2f5143f1937d09c3a08047b797781d1639db4030f9e59f8c5b71a71787cc84ade5a385ebceb1946177a056179aefb49e1f69ed0aa67901b2d6b2152b6c1fd1db67f358093180fcb8f96483fd35a87fa14825d3849dbf479be493bb2d1c639674bd195b5ea3caf49c2b78eb0e953dbf8fb909910c87efc6f9b6592c020333e00f83bea4bdebef4e107798f9a8e89fa5d063d69f88f31a53548ba2406407251f18c3d1ca6e392fb81a46107191e6d906b487469d0002afdb0f32c39873872a49eee649250d4d5d3a7687fde2952291c8ba78fd9b962060df12d212033303691b05eef0ae0e7f31b7e395576708d211d70281e9501618673afac20a93e82f060135e51b29132a0c9244551814bdf399b746651279ed135d162e366f39d40e3a49e907f72bf7c66fcb4ba75b1f447fbc3ae3f390ab4c10963d755ee188a9b0129416161995adcab12177976208e1c93ef48d3ef55ad22bbd97781dc7035c9f5fe25f47b703b1ed50dba311d24154ab05dd88ccbb5a8cd96d4665829c4dca5d5b22affbfd7e842ffe5e87bf4326f957392229bbc893b1fde9e4b2191a3345490d418e9298179661104f70bf6cf9a0094f9d37be98b82d98497573512d8f6fb4b0b0aa334a9120a5afef20e0379197ac7ec78da3688d2c9b590e40fcf866acbd1d857546522788d1f3ae73f330aad045c5bfd59b8a399ae626fd67d9797b32d6a279d42eec3ec8a2888258728f7c329c4efd0f71b730e57f9bd87204d40ac1ea6032a4b8ee3a338aad58c2f3c9795819af4cb652dedd475e5662d9c0cd23e72a8f4e86f1a63e5683c814a99a6595b779e5d715ac91ba62c1ae4ca1651581506ba80c2ee0d3f97b979758cfe93f373873f4775c882fb3b5815b9274595bf50488b935c82e0fb4ae4d078d30bf0843c89e484bf5a24d5de602649e336fb2b79da6131f96ef1b5f82cbd668f4599fc9a92b4e9ffe3468e39e4c8bd90531952327da74a522e479c66b7b1554c9a72a2e6db58fcd45588c9ff4f48be5ddc994913833b668c275174b9d862dbe8fd01535ff2bcff6ea030842ed3a4d105ba07feb0098e39f61a4cbc06bfa153c598c10c5de57caa413752878c7599e5db8482b6f275db2185c505bc0c9670fa0afe37031eab994120acb935bf9dbe6cee6ba336dce1b44732c4267ee77f5db890041e547bde486335b9a0b85d6640f6534d84b3729b3436ac1c0551d687ddd8da9abc18689e7e932d5d0e787ab5ee5f36eb53789b9ba2b71d7a4f7994e56b056d4a042bd2cac79ad12d87726ef8cb97342e616269e9f87493e95dcebdd91763b134019c0a76e8b12789b026ebd1d9caf1930010aa1a5c348ae2e6273c885ffdf8731b34d87c293e77e9ef14709c2e3b739dec85d5bdb8f5ebc9eb610240576435c8d222ae0c8ebe5844980560bcfd45cacff143a5c208add9011bf9770b7803fa90bbaa10f58d856250b37e481f325c538e473dee7863957121374bf12172321b9c99975078e43a0e1e40138f9c31d6dbe5e06fc881de840e64899c0cf342a806916147de3cc342832a9514eae9550d2cd1166e823f404a05b418e5f9ffa84352cba3007f9d37e5b00049d7c099346257fb53e86b919b45a9c6cd8b67cb3c4e383fcfd5789f2cc087d6b459e2a7dc96d08c826c43410b3df22021855c7d413d9cfe7ca79fa860918a74941e08511595fc9a3bec2e2e0c6dad05781c0a0d6b6609837ca8f78b0368b1217b121cd6ced8fa48dc131709434eed65523269abe95f338bc5e3fce0046ecb24dc1ad8c8fa68b5f9263361e4952ca1aee9229811a5ea85c9c4452235639d1eb8105ff88c048beddc0f7efd3690da8b9bbccbbcfeddcf3e3c9e3ea7b46a5b40098fb85a25842911e42a714c2dd0fab403340ddc1af9484843b33c7f5bed80fbecf68180c9b397ed85c51d39cf08c5c0336b149e6d1747360541e84a93224ae88c1b62384b938ae25ce17d656b9ae52fcd9100a40dd7793ca67357f3fb00621863a490373f0db49b1aebaff7284d450922f1e5243bb7fb5f7230dd7cb8db1e08893696908cad4a45711eadfce8b0b42a9aa937cd011bd5c4a8c3a2ec771b3ee4959eba5e4a17545d1c86acaa4805e4aad" ++ }, ++ "ecdsa" : { ++ "addr" : "0xa16c987b93f1b3c51fa8a9833c8932eeaa566ce0", ++ "claim" : "0xb0c578f123a8a0c96354a13f98c4c2cb8a67541f5ccecfdd0cb6e61aa77f7768157dfb3ba59aadbc03350577f6f31b4083bec30291a61ee98ecb3db2536f788e01" ++ } ++ }, ++ "2" : { ++ "id" : "0xa5ea2fcff9e3cf29d0c6f5f147b67ff24aec3bd4", ++ "keys" : { ++ "falcon-512" : "0x099202fa37d5e165b88428d963d2a224b8fc82ac0e4b3f6a02376f18218d1aa7d0e910e71586aeeaaddc2a557124d6ab4f9a44b9cad02166413cbeb14b364e13956ea326900eb2900802644167639045d76bbc4e051654cff404dccea94402141ad9fd992cef7a8fa6478b3e6f8912886e9edd1b34c29385b7e964f360e0fb1600787934486f461c95d577d2bc74c4dfeb969b4798565ce0225ad27aac052290a44f844ae233e082c97e4498a31117ac9d02f3605c856e2dde6f611812161f89cb3a54dc936ca1e740a6c659405ed586a9a963b11c89b01746325e39e645c72b0c7e4491b36a17d43ffe38d88c601a5976f5a9636c964a012bfbce5f9b371e7c3b38580d81c6e12b8e8f2aac219f96245d35b4f4afa6c94015b055703b8c4dabaea4ce2577482f5b34fa49e56a912dd58d74580b1f94e1d2056594ea64bcdb696b0baeb33c86b6544761a3ead9ba9888cb1ad51f7027ee52b21e46c5eeaf3f77bc0af7efdc87acbddda7dca00b6acc665002c26447e5b0e0bb5ba261717c68dea7f1576462776954d7249c2fd0886f615ad50d53960ca02d581a4a25517c050ed467c7a820bce6250a9ba2e44fd67fb21bac843bb134c95360dc1c50d54b7280a94440d018181a9d6374bc64d782c84471b47287d8ea748c36cb83cffe053cb89a9e4ae71df497871c2a728ef210903e5b7f39550d0331e15637be7e28b3a2fc05b0a9b0c5a06f9fe81263c3a94403d6c288a561288ebaf788bfe271a578a1a795a85e9d452b61ac204b297090617286922376bf0a8d67dd35fd705b81260b7aad30132b965e39bc3cd64d154c4175951704873992a814814dae5c6bc1e89a83dd91144cd1b88f6ce449900058afdc53bb44bcab63d30cbd6df115a5ee8f5380a127a160e922bebf7b408de82514b2e2550a0931e065565e8dfc389d454823a55b03e5c989b09e3791f656794e8379b7b4b1617aaa9770366d63a657f71ff40c69b1d5da518ef1e2aa42366cfa38e448563f6c2db5e3089bad5520ec26105fc885993630c10db357883f588a5a384cd6de688e1bc3b1200f87ed66ba3d4a4b671b2a500a0436e0955904030d76577aadddb8c1ed21b027f198c072f654c3abb086e7f185980f49d0e109c1a82741809f8afd15ee56a887b392c5b172ba659144a7e99e25ba19792d2a3c0ccb481822839c8c70c65c0943a2994ec9f6085b7ac64ce2b35489a72dd6693d25f2329264e063db26ad4495e3ad00f12df8cf914fd846", ++ "slh-dsa-sha2-128s" : "0x686b5dae4aecd5618b95c3b2a5792888513ba49dd366ac39b7431ef403e04963" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39cf29ab9b80215a9947b975d8c6097e53b39d1483c885ff7527d7fccdd2ca3dafc32bfbc0a19c857fa8be7e52e25064d69c3b7dde6e77eee96ec77011fee440c8bca99a45b432b5468715a0aeff9d61375393b3ca40b9140e1a2bc2a52c3c8a85292f4c9e87d1e0c12fbe4d7236ba7921b8b83bd10ad554179dcebf0791c4b593c8a1bae836883d5094499cf2ba41b00c8c36c77a83466c263a0b01e773f08ec66d46e97caf0f9785943f98e159e353f0d91d5ab526279477a5509129f7a1b8b07ba82a1ccb4acd5be5e40de088f2600e06a8bcf35f54663279f04c74838294048a8f8692904d4f9eaab49635068df74d1f5ed238f6b895acf1364544747bb10ce333a957599594d766ac5d1a3ceecf8a6696cdaa95f824ace18cc551e1f4ec12f345283b366314515849feb5bf81fd203a6c73b5bab7c01b5c1131d442dadcb6bce32d6e13c5a3e77b66eb8f5b2912c0938d89ed9e20a455066d151a973e4509b03f5d66ff7ffb8b362e0c09b969e21173693d9977ba06d48bd3b85657119f9dc3533c91965ed81d1eba72b46cfcff285131f84306fec7b271a02dd22982cb6399a9060d286aa18a3f97666810937f8a5667c94959a4c27299d55e94564dba27ea3d98cb3a9db6197c842eafb237649de3fab72a9d56098b5c1228e70dc062617a8a6b44d46b7899dc1e53a77b700925ed1b438c59458c15e9b91fa2c2164b9661a976720eee2864efc5363d90beea9789a6d3b0628bf4695a853251c7f70ba1ebcea06cb35cb47d72d2340bb9412edc49626d6c78be644c4ab1c539d1469d1cc63f092ccac45f66917d89274af9c84d7f1108b1bd738408e499efa63f1a87c8730400ec19f9a59d241032e9ab78670e85e8da24310b13e89ad521ad4fae3deb9d438dd7eac72b79496c7b65061314ae", ++ "slh-dsa-sha2-128s" : "0xb8f14bb6630512c51d227c12a04ce7b316bfc0d255f5a5d1dec3e1ce5f5cc92927070079430990b4364200dc6d389fde89c78649e21d8fd3a17dd2de7444e77ac3e8c70eda15f2247300fd8e37e1e3c2afcc3e8dd674823106b4297ecedc924ca948a9f80afd7ca1bb85dc0e60e1ccd5d97eb21062b2fabfe94827b4ce5f0e396e5a891fbfc61bb827cd305012515d0a182f163c1a5ee3827aff289ec526cdafd2874c457947e8a6c8332ee7172197cde7388303992be248892e727b559c0d74a2c65d46b6686a48f0b814bbf031d1bde17f55b888e7cbaa7fd6dcf428b13ca43f77d80c3804bd2840e5768c2aa17f6dc773b71f83eb7803fd9e1f1a2e3e158f7e823e9667cebe136d333316fc670442a8c662930a00f72dd2dbda9b19c3dcfdd09c60ba55d9ffb5d5b3384d719d153566bc0b6da89d8dd869fb8c4113258014cd48a67a3591d37f9ba767ad70a554ec98bb59275ce163364915051411db73833a88cab0d3fdb7c491b8580baca2bc44a7bcfc3a51c28ae0a1fc12bb53b2b948c571397a348e664522ea749890d1c7ea7e9561596a3e930bca68377e4d4c0e0301472c8017c1fd5702cd6dd4c3f5881ec4cafb98967a57837c3869720268b61f37836d0c9c5ddac850a835318b17758a6f97df4d4966d516ef100b7e61271c45aeb89242ac7d2b8ee45a08f4081727d54cc08ec0f8af9e16bdf6f6d6797b9f5fcff9686f15efc4e8e34b363d562dba239908a3992b3548566a30cf04c424383b5bea0a5011ac620ee384f6363fca87daa30fa88763146bcfe0a160c071d79dd8de0b11e034fddc032e522b7ee47f318cc6f3f2b6c9b6efa0aaa9b9a9c1243750ea31ac01f087d5f4f5fb97b8296b0953a606c49025f5bedba6773804b15fb3638e72ffffe38ac20486e18eb21059f419b0af9071be12e309a953ac82c0a5a620a7b5c850027b39cdeb5d728522a15c1557e4ebc3f4f09914b3a99e291a814504ff7171c23eb825d2df1bad1ff29144f8a3babcc882258e8a6060272e95c4393fed0ad86698554515e77340ae806746ed859ff9730cd718c767e320ef54fae5e0cb8ba331bdb920229d6047a6db8bad147b75d376c3e72e06fbc6a542f51a312ec831c704099b2eb0f801b68631b464ef484eee077cb7fd9ea951a0307e08dc5fb4ed5a6e62048b010ede39efc5462ccedef2a4c61ffdff63fb3aae19b28ca48593532f051c716835a61f2fbbd5c25883f4a85b48d81658b6d7cc4227f90a81e961c5fd8a388c9efb78da1c9bc50d53a41d2d336232e84e3eb3444389caa3457ef9e3560c25033ed45242d0b4bed69fda4a4f1695830c843e63147b6c2d3f9bc2608b0671e59d827dc1e3876e5fc6075bcdf95223f73dfd11d64399333f7bebdda7f5c2838c072f7baf753a36a1ae8987773fd0ae5acec41d7666c84c1125190f432a4d82ad9b78e22d6536a8135d80a3d1715d17a673033d37104857278a75c2cbcbfe0159343dad8e98e42874e2b001bdb469c9faf79759c4cb3e3f2ccaa16bb29d3e4dc81627441d07469dfb9f545ed83d9c20ce586370be092f3a90b18f30866336c6db9d53e2e0fe1f98c655f1961997e41c25089a518f05270ce06cc115b6c2e9c04f6ba9bf7ce3abfedfada8580ef89f2fea98e8a19c58a0f3ffb89dadb05dbdf05c44b79ad5e1d259d5aa6086cb295341dc40ff800b460a5ac602a687d6feaf66393dd2be22264498509c9d39033aaa22eb248780a3661ecf0a05cb6629ea3d91eb0f68465485e8fa3fad3fc4315a118e4eb2ebc6e9b07284697cacf0257edf67c20b7b0311d3094f4647da567385a508addc9b25a66db1f1544dbced87886946989682b2f2db1363dc635e4cc3c67ad83bd311437d22d8f60a2cb7833c952bab293c9e20ec2b44e1f1f42a797421eecb2e9e9f5e47105b9e7f5d7bd796c360ea39dab45ad701eef0a76b7773c55e7af7909d456c213b0db14f985d0f73652bdf39a6402cee104a168749466e477d8a399469992d65656b607fffbdf73ca1bf4976d3a0c0c64cf5d260d6d3e0198f0b86c451b9ff5840968a2b60a8ec286c81fb55741d7bc9714177c9a77219d3a39dc1d6d7adecb7f8f85af366ed653cd81408b509d0f56b5dccdcd1d982d115754364ca3f14a6f100c54ed8ebfce6b0dc3de4435507acb0c4d974ae3f2453867a70d5ba078a17db34844ea410af4f842dd4a9879a7706b18ddbf94c7b43ba137f7f9b8b3924b4d917f8e0262ad10d083c4dd3b99b70560377ad31784a587cf0ea1f99d6faf0f04a909179f3f93c96aaeae014ea1e74d9d7ccd0eb5ab466a6caf8ed0fae75cba902ae05244e0dde35b8c0bdbb3354ac60875c454ab11f49e47e2d180db319a113a5869bad3ef4580bc7402b0d6bac10a7a4e81403634fd1cd272076074e714b14a6efefc902126df6091330ae387e161789198680b0258c341b6f3ec0b09c7674e9ae8f88699fb7b2f88fdf2461e11ad483ee11fe4e3ddd48ede0ef0a1e54a318ae12473993a8456dbbe8b5ded40232b8d2474a90424281830da7bb36091ebcf591947b04739846d8a600946c2b892e2bf3353b09b08e3a141f33f6ef83d022666d380da43991d3eae4e62dd3f9432678e8be1cd4b9569fa2fa84e95195449716423688aa920e2ba1cd41cd5538907ebdf3ff15df27900ba7ee09f3e9194e1d8cdc0703d6f38b2b887a89b10787986013f688f9a355c6a362f4797576ba022e4f1d1d74e2e31dd98f1b617b99516c944bfa5bb474857fe74a09976cc29c71a7f5b6fa529f3e0c00c33c2f0700064fd507461535a35c0dbc5b69d413fd6ae9af49ccc5d02d7abac88ef02bbd40475595176fa3b68d602469a89afc03359b032fc1f0ae255d623fbf9525bfa36ef98467d5eb2f80cf7c72a04b557e40995471c7adb8701409830b232693bf2fe905ef8b1a32c4b8fe3300bfc5654acfcde685547d5c1b0c213294235b31417da91464619822f3535c93549ab4649a59dc3620e7f4a3327c0e421c5d1a28a2b4c3ba8ab02950631ed54690cee35bc4147aaa8477cae505a1d1757d85251bda5fc91cf65772e1b543bccee1a2cd0c26cd33015533a0e72c815be8634efbb50ceb0ec3c8a3bc6c84638ae371809ab87eec54b934343ee9ed1bebca488d9399a1e347b1647d108652243cf2531a4685c282e0b9e526688a3ae1d10060a78467e6804b705c143d073af664cb72ce657a7d210240011d539cb3144e9411758a211238a872eb4be615d4813b64b8df446d2741db7c9f0af2cc4dc83c0febc41adb5d8413b7ce54ed564e899c0a5a4abcd1cb44c84505915afaaf93751b11bc8e96610216f71cac8d3c9ddb7282f0f864400bdee42c3e5645aea1aa5649485435ffec9e43d43e4341d967c9a89eaaea9cca12e2089f3de222e1a5034baa32372582023b5564909fbb67acfd2a40d5ba40de2d7a31cddac717f5702648c0346e197f99598dc83edda7ad335f9e711a0835c75d4c32e3305e4db9dfafe171181551a8dd5bff89f8a9fb819eca7a171d1be47fbea0e2838a1f1d01f4e68c3d0045da0ed7d3689c17319ef5f5d178e6cf1628402c40d2095c91f7bfe6b837d8f86c5b2585653beb650fc29096f13617ce6d36fd6107ac83c7d7f5a8639e519b161581dd58018ace297bddc3421d358be70179b14bdff66f229a50a329bc30b054a95d0f43e7914a9137055f4dda000357fdb5e2afa3d61b9816c03697168cc022f0418ee5ad7aa71617103fe17e7f47ecf7ef9bf779f157eea74c3caf3821791ab628fe8cba64c12d3226877c48b746d725c46b0ccf5a18f869e6680f1e5ef3c5e7fc2a18915dfd8bc12676ab94ff4401ed22133ac1e1ba0c0352a30156bd80b63eed4a7fe9c948921e1a9843127f1191751312180b75f06e33694853a05a24ee30cae0b02a0be49db16f6f06630ced9b5e57cad548dcff70b1620ffb17e8bf8c247a962d6b2a6fbd4fb3c89e3aa4381e15b92f7245ea700e76ba99678f4b0c998ac90bf3e4b9ba5b52140e15e4b5a38e25462c1b61953cc2068d0b9ebe014db6b8fbdb2fc05751667659f40ba1cafcc2055c364116a058e286f084c2bb73096d46f6736de541b750ad437c27a92ea51baf3478837e99faee73f2a2745918f81547c45f2b7083befc6387a73366c175d2be22314a1fa73f11571395c7fe9df062740c58b56b4982240c63b8a0d5886a3ddbf6ffcbd705d3bf3713a0e1b74497b8c1f34e204ad81b63f27cfa5215d275597599f60d02bbf6cbb229088b56c96d73d09fb3c36fb3f05f4266221984fe8559619da67bb7314ca66405cef4bd3086940c4a7346243776a6fa128cd9b6181d8f584f482c502fce3339f87e4fc5e3593b7a0a64c19fe76c51a29ef776e478ecdd5e093b2aad0ab3cff0baf73f4e09d63e9ccfd4aeaaff147ddf2e9f1e3e6cb3bc9757c57072a1a8076e179e50b0a03dc94de86fbb99f0e92338f26b6ed7c863830f325d3606189b80c8df5a763f422f26436f753168b53bce965c562c2554081cb4eb42d48daf8573206f818ae66d62bafd151e9784d6a9304996b4b82cef081af9b106b42ca4b6b0b2401dc21d8875f9801591234dec266f1f218959af60351178049b487b2784183349e0a7ab361f575fd0237d9f483590a23401f9085b111ac3d740ff4c3eae0b7dca3d149243e3b1fbabdc7431a579652d522bef7023e1c6579d2f6852f1acb9b7f20e3956af8dfbf14617f14981f40b1b2430920be14284dd5f2771f73091adaf9179b8396c6ad2a3579befa1e323177fa2598a3ef80ff5785dc2677f87e9299c6bb16ef2b2080e91f6fcf1b9189e256985e631a05cbfb6427eac995e683f494751f7ae888bb0dfd23aad7fbe942b8100d4daf62b6b8e4d647c818ee7edf0d4d64293edc3b7b6e08a8b9b71a7c38f55ca76593d35770185637fb473da423069de005363ec25235ce816f4df3070ff567f919f47dc4fcf57c168032ef8d7e3fdc5a6a1dace2513fc24f0829e8e4b964d37333febb1eeaa7b81aafe30d16fe64b6ac037ddec2dd9b372c657120df4372504cd14be89d3719c5aa6d545030423fc50e277eaa401e8bb02d70b6614e9768a7e42ba9b35af8f9e3f7dcf175609f7b91a16fdcd65a151c0e85d92dc8a06cddd1ff77d150ccb62c612c90abdad156ced839e837c79b79f456156a28c45f3287cb86a9ca664a13313332a1ed9ef4b3a3df864eda7bd55a6d8705567bd8d1d732f65a324aa6c77f6dd82517d5274343a4e16fc8f41f5a3809e9f2cdec445b88309c9d1de684032a10f8944157a3dc3d4d8d59721f4f9cc0b0e1e7a97b7b066523f7498e0902ac5aa462d9bd096e13c14407bef96b59297391032a4aef8c543cc8b60217ddd5a5d815c4ea1e21625b52e2323b42b4851b0bbc461abad9b71805e8b1b2a16c811be69140d3a6d32d7aa9d5321adb57570fc2e62618cac60a4cce2b011a4c8ddd4dd521b6864c7c4562d8270dbbceec91bf1cd7be926d6b66bf370839bbb22856d1f0c7b2b7119ecea6278793186c50b045d09a1aae7c5bd2ec54df1087cbd1d8094293392605321bd39ffdbbe510f0e8760bd35074c4b0453604ca1f5bee056175ae7943183212ad527e125d2ae113d83c5a4ca1e63e8d89ba07ce8fac8257fe1c603031a1fe2e41bf922d7ffa0a610e0b91eb8c3147262fd228a4ab54fb520b49c91ca268d3954029be8677229af3ed232628e7d3a752e66c2171d1746b7e31d2dc8d1781af454822f36b3ff40f7683fcddc5aec46b13890a6c7c9531f30eeca923f198f4b57112a94e34673c88c70bcf80ee115de27ef5268a753c6f827e71254b5bea2a4f27c8e0e2d0c3f72d051558700196e80abbdf452bd70116c24f635d1850f9466282ae761f1a38a8a0fb5a02a9e1b99df55616f0a7c031fc34f190dfe5cdd4f2442d16ccb49187823fa90f3f87dc0966c4cebbb7472d8184e37522acb165f5d3b508f6a62623def48edddeff361d5ff37fdfddb2b324c4f545bfd5cb98d258edee6ee6170bd41135ddf4c9e358433330a5b590b25fbb276a2284b2df18550270b32b65d9b483fc42e9610537f27715e9f451bccb73e1ce017aaa39b65db4e86c86a50d0379398e57e0c34fa64f73acc0d2b4e953a89ca2f8c01b10135c2af5c234dfaa17ef97941aacb7cce96cd05fb246b76f15275e4d2a8545e52726a48f269d1a558aa12588cc78919a5edf6c0e9e576ed58c92b67d00e4197905d74dbdb3700fbde85d26de20cc652581608ce1d1084b507842a0373fd8830c8d3f68dabe93fb19e3189e486840715f92ae4d916a9ff3424b45ded24780b31fb7f76d506339d9f9a545fe0547c675bde44a3b490bd3b52e3b30842624ab5e8986161be4ef9da785bf537954d3c716da5597a859ef7adb40fd8030611d3ac6581e424ff636aff72f4dcd9f315744a3dae6cd386b2f9945140071a5a49f05e8f979115678eea7d6d884a92e4f14ff94dc102355c3aaa93e02723a92417ff49fe8cdbefee7e6c5e952ad240fa7eab4c7941f6ae8d2a1086e1f2ca73eb8ca5fbe3588ae51bdaf18646ed04bd185a19bdad69394ac15d130297c0fce9d8fce8ea2729dde117facb274f9865ffb4f2c7248102dbd96767483cb7fb764fe667d484a3143db514f08577cad8bcf695b0d953e2a3c8710d8979952929d59c8b8ae62ff678815130e68c85d4714e832733da40b933b7133725a40a12534753eb4877c65fe4c75542f28d6f9e805789995adaaff6fce3929e6027338281c6d0c33aac092fe0eb1797dcd953fc1f815df794249dad7b28407c50371a8c81625f6e7e08ed59a98758a9859c41f7436f937885ad35102b0eea85f3dc4bb9a6260f4e091ed983b1009275d43e4960f9422dddeddd09e9990d545cb67dc3f1061238dffec3ce01376259262b4c32c6173a6f1e239f4502cfb0900bbb7e3b4883ca3c64c8ba91cfd80b2bec6aea25b01124ae11a56ab3e4d448038795ff62e9d5ea5cfdb99c5901a8b8f8731c772690dd964cda343bfd020e920b32910a68b433ddd01d117a833242fd695a54f33fce28b506d931adba499373b0a6182e54323f032f1e7b8bad58dabcffdd1cae831c70e87b2c6fee3494dedaacccfdc93fa23ee1a4273f16adbbbcc21f5d02d8645951b93287732cbca4c61a0d0549345160537501b8c0dfc97128035875e73db7eebec24813d03d11cbcc089929b0f6e2440a26d90cffb6295e8fccf65b4d676abb8ff66709913775e611bc843302a475488c9a9310c0c8885b78d5db5cbb1a919683cfd9bd010cf2f1206ab327122ac87d8e2899cc1ac684e72c91f2d36c7bcc3491b768aac86e92aeb106d22b3e85112a2a871bb8c9d0a0dd15c89d113910f8babf15f27a13b10200ec7078d362773f17286228b0d5a58d6654b0fb4f60c81ee581e507f17a044e6bcad4bb6ddc66bdde7d311810d79ac031086d7b0c334cd3a8a496591aeda23b2c0097cefdb6894b352395dfc79b74a6e4d086656b0cd9c95a48640cc8b3d188189ec0b98c8618b0def4b0175f11369cb2f107e89c4a67a75396cfcbe899334a5d5df5927fef2eb8bd836a27a2834a7ab94813d30fa8431da3178da4ae56caaeeee66cf545537ea260ea6af56d4ba048076ace08ff2a446080a6b688a916a13b43b933e506ad187b1f829a1d54ae261651563874cae19c490004205765b43c3cca4cd8a309fb1bfd7520bcc07794cf7c03d9b1d1ae0cf646534f5a97106925ee96dcb7fc1f74e62c01d382fde19fe027a4b9b7627c08e690abe3ab076f184210acbb4229d483f7471ad551eb614c35e019a8a894b5f92f5371fd6c457f135ae8377c5781a8f3a6dadd2c00697bd8399b6f168dd64b2d2d66d5aebae90fa5f904af9f950f450d8be919ae3f02cb5c0be9687560cfab2d2161db61e978ef46304de248383dc3a99e30573bb66f873ef1e54f523ff8ff79e8c05e7f8143cebd1bdd9d2186ebdbd3b66a0a3dee79475cda2890720ac5bc33f8cd3e817d82bd7c52c34d491e1e9d1d307eec17c0c7679af3626e7b96bbe6ba2550f44de7d1d88b3e4c220b8f185b459f1f882a97248cdfc3d42209ff44806837750b3dd21ac5891254f6c7f6938aef3caca6c55b633770772c2c06734f84612a59aa8cfd4f347267e631658cfc4ff89cea84550bd43699c1d8840655f39e3449ea0d2abba1d81196413302719bc9b39cea85cb7db6ab7f00683842cc480503004c1c819ab80e121d9d21f46f362614a5f2cf80cb2c8d3fda82447cd0155fd7e0ec7589a6df2e6614671071f0f956143c762d51172da46e9f61e588fbf74cb3ceb74bf2ce4ec4ae26a28245f98ae91f09cae77c4660d6dabe7cad33ac506db3000d742f683e08bbd0a7cb9eec72a1a976546ec926b9faba5084e00d66475a514a73f01fbe1e79c0ee0066f4b724e4977f3c1518d28ddc918c573693e9b3fb69b426df0640c5ee42cd5533655f9a82c6843516298d05cd970f34dafa886995545c37b3b939e0dfa3647fb3f330bbd3e69307be3d469a99c24382acdcac76c6cb71decb4b7b11cb5f2e63d112767a7d6467c51f1c0c27900803180337f463e64f507ce245f606f8c1f1df836c7fd02502bd3127424804c69f1d066ec3acd9c4374e857c4607b711f532867cef2c1c8a7d7051a440eb7a8507500d86f11567e2fc812a27e63e5599059af1ee90444497f69add7862b93ea050f100e48df7a578d55b6d6321e70ef7a7625ed89054ab010850912088fdc21551b89397c35ab582aed6c215e00d398a857090e2f7cac21c7b51f34054a45f36157edc603b5d6e76ce20f2dfd2c20158943efd2349560666ca38505cc6af776e0720af2d5f6a7d98f385854700fc0c749dafb597e94d7ac54aedf34840ea778e8873d6f1fd7f53de7c06327d08d34a03b38315efd8eb52683ec1f9abbe2bcf096fa4f379f41e09b8bc67ae4685e68ce456465b38892a238b18358714fee41da0aac8dd729e2c3f17488470648df81040272b2e927e896a4eaf6a11c457938421288ff074da8db60d37c6d022e86952341f2b8d262cba0c5a6efb51925517a8c817a152499ae7ee56d36df86253e6b2d93079c89fc922014b03da3941509e979ff8dede44165ca4cb698924fd12bcb02a35deaad608ff3358d455a49e12e944dbb11ac7e9571476bfa856f3bcf90ca9bac6d57d5c1755104b348d2924ba9b14e9ffb750cafb6edeca6dfb79d73b9839092032035ea700d81f19d035e38bdde754a5098dae1c163f9c473b0681858004ab9d9c2c57282ebd7e57c474b8f7aa091d1048b95e7ef887767f49d2a7f6b410922da142ab8605e735ff6ea9e3f36a29380ec43dd009d98d8c20f4052d81fedfee6cb018b2da59d63b5fc153d5b0948d613415a6b8a2b7338897188582d2930480d897d55bec899723b285dec9abf819ac7e6f39d8c35c484ca13f129fa4b334979bac7715bbf5e52a9926568f359dd3e3e000958b561527bbd52025918ef75228c423da41861396be4f829aa4bb6f94f65e662e6ac91e828d721b741d7333a8e3050f136a463af537ee97af4b42456d65e1e2324f72267c07acb88c91d0cd602ef765f858f69fcd44ddc73dc7c5f8825f3fe04affee769f3ab5486232e35df8fdb75db79721906907ffad83c57a364ab85d93bc03ace8998ede749d88985ae41cef163a3d00f568d43115992362c581745f723a2955ed925cfc7c83c5b5188812fa2dc016dc21844f923b2362afa5ac5f2a6c9355b2eaf724606333f152a01c330ed88f7028e716043330a280c5ee458f2032c8163f5548428ce4c529d487a16ca0e58cbf41dc4dc802cc5ea7fad6a50de0c0f2c2be49c3dd2806911ab1322a30acd4fd8937b8930069fc1a6de86f9ef90f407b2563594adad581b49ad1d19b30ad13efb0ddd8e6f26dc43a36ff8d14d1c99b073f5f1ce8923d3100bb04488b86cd4e89f7b9f5b9cbbb3f86ee03b498ae255e09eeaaba3e4e4d68f1ee4d50f699e460a922e17ea8f0ceef9794e944f128efe835f281a7662f959054aa994afa3982f7a310f46f53d5ffc07884aa91bbdcb3f3779ebdd7f90801e96222f56df39ed9c2bff5d4a11be1da7482835e494b0856ea7c695cc1b53acf3b2e2d1846fff50bf55be65e16548c4fc436f20c50c119ca8eba4cdeda8c7e4d33734a0355586629ca5a7c3591ea4b15428a81b6d91529485004cbbf60e75208579ac354dc705edc7bccb32f23030e733d3f549fbb841329a01f5c5d263ce635a57aa9c69432e5213b155a07c34fe19cee737cb993fdc82ff38eafbeb734f04f58d367e34df15dd6044591983b9b45d4ffd87e2a6b478c7d1e86b4b974991b930370d5eaf5edbb53c3dcda643fb992b5fb0725a8aaf8a9e7c4012311f197179cf1293884e2356fc5b624cd46358d3c7bed1fed6b0305114cd11675aa49c1b9e6569817d34fd60c1105833d78dd00117284cd1722074a60655dfc428072b0d2eb881b93d6c367952a4bd59eb902032cfbf9189bf65f7bff592032c77d61dbf778986b491e297ad0da5b367c8a10c9071b8d509b246393fe04a290b3e2291f04eb750285674ae3e9c7b76a01b679787a4006836dcee956185d3b0ce16c4567fab862d3634b93079305008e2f99ed425489bcf5447699b7a7212fe2196d3999b39191e750fda742c6ffb5509e3806f38edccacbb8bc73c96cd46f0f400c4012f1205813d69a48bbd1f55724c7de917ab56d4188716b96653ebe4fd1b6d5d252f5599f9c53a4683ae60c8c31b86982f32bf73401a328891804daab93a155140fdd41ec87e392c8397c9ecbc48f26acee4e3cc279cfd67d75b5e0b6484274484c18f72c2532b4064cdcc309df796c802c17480428c3b5a5467b38aabce03de2a266c8a22d3b0158beb913d50615a1002fcbaf91edc529b0cd38f35138bd71dcfef1b6b90adb4e68a594de40199724c158db9c85ca78ce3a19378ee90dac98b23e1515324fe18472a4ca93b004295b7abd3c146109da707f5ef37886fe1a8966ff1e96375fd64536eece72ae3433a697492955cb182331ce72e8f1804efee93b1929338f" ++ }, ++ "ecdsa" : { ++ "addr" : "0x5e13d369c8adbd8079272b624343ee1edfa4a560", ++ "claim" : "0x197e55da82eb1daa23a5478ed230c6d0452d3c1920df15e10a8d37a7430a7f2b69eb474bfe0c44a6e4a55db9d5a0e0b74549c044ae22778ce30f47a9fd1eba4100" ++ } ++ }, ++ "registryHash" : "0x0000000000000000000000000000000000000000000000000000000000000000" ++ } ++} +diff --git a/consensus/common/src/test/resources/aere/registry-v3/ok-epoch-a.json b/consensus/common/src/test/resources/aere/registry-v3/ok-epoch-a.json +new file mode 100644 +index 0000000000..f92d845f50 +--- /dev/null ++++ b/consensus/common/src/test/resources/aere/registry-v3/ok-epoch-a.json +@@ -0,0 +1,71 @@ ++{ ++ "description" : "epoch A: 3 rows, falcon-512 + slh-dsa-sha2-128s, the switch epoch", ++ "chainId" : 28001, ++ "requiredSchemes" : [ "falcon-512", "slh-dsa-sha2-128s" ], ++ "ecdsaRequired" : true, ++ "previous" : null, ++ "expect" : "ok", ++ "manifest" : { ++ "formatVersion" : 3, ++ "chainId" : 28001, ++ "bindHeight" : 1000, ++ "count" : 3, ++ "0" : { ++ "id" : "0xaaddb4dde09de5718a906d83be7db3d58e0ae32a", ++ "keys" : { ++ "falcon-512" : "0x09501c96d2f5cf0b28fa00c726e5359c5d36a1fa069971f854b7d914fb2f1295e68b2c6fa91d82f7d287f55ad493c87320bf7ca2a5d5e79d7212e8a540c166b588dc03f73b83be060525b367d9f40f5e77e7798c60b6499767586770722820b3b9e6013cad3eab5fe5de96089a29f34919a2e9ebcb3fa03a3e714593b7a3356d11ffb3441ab40ad94474da662a71aa2419dcd50668cd5d8a9017662cb60998b34ab5b7929c58a94d5e133ebbdadb2b0279543067f76bcc4cb6d7e0a5edb7625467e3ddc92a01206e1b8dce69be31928687d8af4d26633a07e73c2830d5299b878977691cf65700b65b6ea2463e51b6136888c544545e59fe8cf190a7944e215a785b682623c95a79eda28e25e0e1b91b49ac89deaec3b14a3c431d9046a663170111ee541d81b43aa91f29dc147c6fc97739b3a63fad1ca84843d0a65b8d9396f28e9b11f9a41453ab18a2309ae8db03253a09fac8f0cd634c76a5e938a44719660944a95dff056cee43ea99592c3899c2880d7181ee3dd5c04baeb60e1369a69430a66031e3cb10e392622f5246a71761760cf417dcb40ad65f60704fb74ad26f26c3af7513a42f806895e0298c25c049187aa536e0eba21998912e621846c2ca0e323744ba930a29850fdb385c8241382296ba28dd4df05ddb1e61fe525949034b59929a784406de240f8086b4074825f419d5472a28a0b157500be37e9f64897db2b645d3807c48dc143266c99e7cc1638ae278772493a2a4ecf74e526a514bc9119d7129c5a0d115a450ccf4dce05b76d4b6149fdab028006df7ec2209923117abf7578a082128cad42aa66b69eb63acee4456bebeb537ca57bb3d3487f95e4f06c5cb29f292d3b6284e5a162cb83151cd9ae56aebbfda150b7edd5065302ccab70892733a1e096ba0da5f51b42764ad23060eb197d5460425fd9c7a26e7dc3cfd40eac3643539feea72c9ed41569111a7976d2c345ac2183fa2271b424526709fd9aae558a23a5cca29f4e2f31629746a71d904612e95ad9977bbe74fa32e90fac62625838cac49f50e5aed4e8879e2ce2e5651c4f4ba0c96583af9e1612b5ff1a6fac5027c0a308815e592308170b915b4a2de1e8d48e9a5730680ea9db8f3326c430241153b3b218d5347d5c843570cf80ee813871ae10f6b8ce4ab7e4c5197045e85b1cb4977f44c33eb85894b6555b4bd288a50c1b656936841048983c00a01631f10a84522cd613fed0d4beaa4aa4b3e9f30c324108d909e59a80150", ++ "slh-dsa-sha2-128s" : "0x47a0b70170dda85f843607f6c6fcbe6e6acc7c22980c108996a3fe72dc9f61a6" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39c8813cd3b34be58eaab900555a67486034b1923e0b00e435661230cab85f07690a5958a5f5e9c84f033a3dc2039a5296443093fb7fe8d41895fa73be3fb34cefc6cc36750d534e6a3c47307294694729d6cdedb633e8efe8979a9aee486eaa66136e342c578761241192610185feb2d3c196bea0e79222437b6a8e08cb09778d053b29552df96507b1cdaede8e9aa7abc18902f29937f30e7cee6868f349f7ae33738237dcaf86b8e8e01238f3d8ea6fd4090a8161db65dabeb5ded5499e8cc8a5b32607abc291b36a4b34b327d30cdef18c1825232e69a2b09d539ed84dd2a4756efa64f864c563943b3db825824f294c1bbfa2157347b0fb0e7f8a56ec253b39ca9b6cb1ef7d3d7c93a6cb220a7dc50c365905ea5a71575c3aeab25b33523e4fefbaf66137f45c3d96db719a12d2e2d42fbd6cdda58c5a1b958b28c2a8f2cca297871a147dda92a7f008a359027a9288e42ebcd6ea9542f10b66dbbce6e7bb914206122f866d9adc1c89cbf8bbad9bc9517c2ea9018b61d4d2df9abff1dd9f3a0a6faa72a449af9c97e8c4090f3bbd9824298e61599c13c7eb89677c0e845ca2907c728d9296c24e96b6a348dbea7cac62671c9a78a531463614ce321e28ca2f093094ba5f69881e6cd766874622ca769ea556ae757cb7f9546d99f5c90c25e7b8e14f3b7f270861398800b0604ec2a3374659277a23cf6131c63148a41b05b3c06e2a98a268f1b9f0df7969addef17179ca2261d3c229ae3db0c490834564c45f7b8ff6d3bf70784779d75915fb2e2d5bc147bc941b9e249af188f63f39b028547cf080b7674b228e20a600e3b167610f814daf105226f3c1ce5e07834fd33dfe46315546e926fd5be83fd4d47ccd5bb8ae736ac745daabb59c87b9edf9a45c9a1d1617ee84e588f27d12235c59ffd9", ++ "slh-dsa-sha2-128s" : "0x0e8f9bdc22cad3613ed07fba30ed04219b9528f9b657119e2f0886dc71cda4afa7d462fe8bb108feb58d998b370b2f7e162390713d1a17eb7de781a604041cbed13d00effd3b24f2ff87cac74f61e7b7f7aa6a259dc283485179ab4bb966793be018c4bbf4475bf7a69e600a37246908f662813813d4b0f4f83757f4064c5c0713870a0b98b5bb99025dace06100497fda8c73d7385d123afd4953961066e7c8544de3fb620ef5e23174327c2b64089b3fe6df3eb86e83b12634a0c9cc0d7844c894ba6d83afed6becb6f5abcfff397c5cea8064e5e153ea4253abe599dec1614b449329ebb25861b69a9b22228d1a03ba51532ea64ebe7603474a15a2806d3dafa29d57d27c5fa894da673b85b4674ce835fcfbd391d328ef83504101432bbb0c83d7be462b265911aad862118af6f4cea4df0f1dd38969c69428fe438d59d22736fbc7dd5faf6758905b26ec4c99d71e4b8fcc562a694ead91569c9a916df5ad693cb2ad0b7ae4c4f3c5b7322f56612c5449e0339dbd367460c76ab89b6f44942cd33f35eaf33c2ddc0c6af793556d5202fd1fb0f9fa1b7ed45c6ca68d904e476477b71a0bc6ebe248c9b4585da0c7bb186600691269bb4c836667a6d73a455b97127d898b7fae17e1acc6dcc3bac3ecb14da131d5f8adaa64b054e2f569d9bdb164792038e107848882de9bbeff295905c2af68d4c6dcc8cf718c2de872ab6b3d18e00d527166f8ced642281302e2acf4cf4489072a2dc3d55ff8716619cde494be1763dce925438b33ff1b91b35eb511645832720ed92552d4880ae53ff6516cfaeb1d48c923648e502e4038676f7c82e532ea713c6b9348c80ce3c5735f437491d3a8b1765294868c14123af2e9ff61e394216e630c71ff976072d2a1c50cfd8ee1ce27aba5bcf9aaed4a51521bad5e5d5e66abc7a95b215fc8004364aa4df2b8b97b14e3950f521b6327a55fdff9139fb0bd35237b022e3aa128d36c8a60f4621d25d28c59a97418c7dbfc15d900ba626d283632732631ec4a948f66dd9db3bee8c2cf60dfdacbb5ad4c0b2b31f8428868cca035e79c95bcacaba40a9351b2b44cb29753b6b9da0a751bd5af84c9094d5fe91e97501d4f075392290e8516ed5e41b41b00e09793353707fe5c1d942395074637f3ee0a0f105876d6f28a74f9558c5f360e98f047a99af35ccedef8d5cd299365e81e7e91f28a01eb265219e21aa7f7ce56b62f9d2a61560f9fa39f2765f5b50920658100a638aad03482a687905cd27dca02f1deffd1bc49a1be1ea7ff1a505da74fd932937d8f6a8bd75ef456d5f7b71ca5357bc66db6cf14368c4faddf4996363251e6a6113ec64d642c319dd85830d8b4c7ee1437ebfefe01f27709ba0c412c266530f5b6bbb005994774e8935f1d91069f9e7a8cd2bb7ad6527768473affe24709c10294eb588aafca85b379bedf0b142b109e1b186e635b0625c4e59576266acb5f71040c44035fc9480b13932bc657cf332b12da1cd7d5c3977f51d5fa742974cd256e8e3662dc698e0516d615d0a05ea9caf12338d0dcb6151e07f184c9cbd5e59bc40b12ed6372e2d6bd42aa0eb6c3c888f264a8c0d3332631d4919c921cdada6bffbd01ca5445de0779f9723577ebd7e33ab0e5f577843aaa6cb8cb5f0508c33b63913a44d02b76bbb1eabae325581738fbddb5d4fdef8dcb8597bd29c6ecc631839118c44f66ef8dedeca65e58941c30e0423c40bf064b8d19d28dab3787238781d492720236a7ae0695ccc867fbb1cf207ebecc64f84daea66b6745515b9ac9b725061bb9958ed79ad6161318a262528004401633d47a023c645683e36413b8653fa4864fe98c501197c10226b1732337842a1322bb788a00a0de86758139c2d9ea3c5b26bf5d7a4a92cab4cb686c580e3e6cca488136f0da9279073b3dbef9519168ba02588fa29cc60d02273805b425b919a7e2e89c9086609982163e09d5f6eb9c66267ac7be363aadd4617d398d4bdeca37a838d650b0919faf13b78642a058b1bb96b2ed1482cef9bc6e8b2e061e6815936e15a9c754353aaa786ab141e95e5f6c464a41b8bf29e28e764abd638abcfb342b54d08c15ba7e24e6fcb69b844e16cdb5cf4f50db60ff0699f969d8e68511fcc9e16a58e100f80671af6b04ff3edda3a4f05f9183c0c3bb7c1061fee2d3f04e33fe75f1354e6de54f582da914da0138e8565ff45ef52f638cbc33a24bae863fe91e58d7c5da34273438f15e10d4f59db16e505620d97d3fa4862a4097a659925d0e5f4e073103ed29a600b051b83b1f3a21381f4b871c18d262d7e43842c34ed80661438c064aa2fd858a8f3bcb035b5e942baace7b50e4de5a73d5c51fc0843cdc163958a62d333078f4c7d883bd7055a602e04c853f9215c9d7f798403c007fcee124cf6099322629c449ad4ef84b7356110798dd87aa4d98ebb47abc6cc8748dd381d588b77db7f4e7550f6ee1ef4360dac6d6c7037a65297d4a0ea7999a5632b90ad48fba0a916846a216941fbd13d62ab36e1066e24990c19592944078435c52d7717b3556595b645cd2359ad151dbb67e92b14168cac12fb2cc5422582a50bf6e99f116751171c9b78744ef719282f1b84bf95b4092514f4c68fb82a1526e0942ca50e186632cd9b0b8b8d91e84f85e35f30f815601798fcae676da6a2d38eab62f22445099694804a36a34142150fb795afb445e78c241f0b645209037a8871cb5487c975975ac997a540b709e3df6bf208d9d8017f9688b152c9ee2b934f65393de8403244b7437108e6d8c973aa723285555d9eb92509b1747977105cbac7fc33e658fd51cd374d21fc2bf229928948292c1698db7934d0f9be44b137514d0a5fbb659bba83861931e03698a61cd20a449d0358a5fce7f288e18bb3eb62b7ba0ae75feeec634fc90fc45ce45239c5e3179309f0c202cfc53d9f42a617f7aaae586e7161a0723ccebb7e8586cd40e1fa12d3ee89b400dba8073b0080ffaab1182e8243afd93318df15bbf3ce179f21804fbb8882e855ef9e0739ce1536d8ebfe9856aefa9874b4e102e705a40ca4c3ab0ab7df63ba525189b518796590035ca780d348de49f0ba8f28456ca6f3e3cff7e761d961ad98b8cf01e855797c88fe2f811e41e787f3e4becb0ef42ca3b9979356020b447294ef295543e0ef512a247e4d356bfe3deacca8ddc5255e6ad047121eaeafe61d71e7f31395cf78890add4f8c688e4eb065479a63ccb3d0c09028bf60c700fe9d19195c26fcbd4130e6feceb52e192a2aa2343c05b43b276f51a7c55dff7233ea512942291900d93315438a96af08e25ea5b9ce656c54e71ed60d1eeb1665ddaa9e42378c930e21d93484b9a4099b7ddd71d983b4c42c6b1f62907ce84b24321422b08b847f1ea97befaa4ec30a794ad7f340210c800cf185ee2c6c72e844cc5671964e1e1ec58953500f149f0f0f25c34d5592de421c2e31535040020237b907e86d753094dd4532e1ab9d821e7583d4a21e1041fa7ad711f29ee3721a2aec6b0c46866a2de71ee850d8122f722898e533848e2bb851ed24cff9ca83badcfad88a171b4be064007aef4d759d93ae9b67b446f3c6fe504f5b4fe851b8312fec86b46ec3cfcb36e0f682e65e117702b888ab8566c9cc716a3a86106d2323c0f7f20fbc1fcd110bed4492a750befbfcbbe16820077dee281bcdf14509b93137a3998b2fdabc2a375b38857bed12bb8a9c67bcae7934d02d6ff89620fa8946c8aa524fde99c12fec0e25bd79788e2c15fc31fa3f27502cb952b9f9482580cf18ecabd92c55113ec4c4470c4dc06d8ca27a10474594eff708209e8f376b6f17915c2966dbeb0e35ac2f02419692c0d232e133b3907059d3a56ff169e7e61915c8b1067e183337b40bc1136241e862eb3ab3f2c6a72b18511c4107ed063d1e2303d0fe6842fb01c204d1bffad7e90bb44a365e62945a7f631811c9c37ffa5ac39c16b4835798686da5baa8e1eb6aa76b42f6b86863c30669486a175d6b3bc5bc47c5eb05b240bd921007fa39506c6605bfbefc9c8c493973bf3f0767817fd8ce126a301c5b8fba79628a9b3a03cad0c491a5f487dc5e89269e5d3bcdc2998a136a012486c5bce2e6c6dc595aeee2ebd5a36dd06919396184aafb2301d1889b668c4d701c7ca01b95f9508f47d4c411cc0397c244ed4e3e3ad7f97d86b6f8834b13b1b2df0625e6b4eae9e439815e65baf2da767d3b1700fc461fad6297fe4e8ed02bfb65b750c2d2801b7308aba9657df3c3ed7d548687f55e85c22343d1db343bc2dbe222fb76fbb3cf490cee7a99ab3a337c626a148fb303b2f8651651588dd4859fd65c95820ee2af85adf4e8fc2c03828ea7427e7c6b0d4a1b0ccd424df6d1450ee436c01351d8b6bffd4ba072756315968845ab7976813d93d0f0f2be1c00faab3ccafa71cd26c5837e87292870cf768c7837e18ddc3c513820c660870b339fc42c5211d33d892ef22b475cea3be20f5e47206efbfdbeac208e26e97c400edfd41f063aaa6b85a0cf86e23fb11274b405f4f796eb10cb97e70783909ad492ad9207ae7b3d204e59d69c886f91bc82a107d0be3ae85797a7cba747b8e2640ec49384f53c785a84cf8de37dd4048dd4b879c58768bd131ad7226506113c446fbf13d769794f1535d58e9c52e23c1bd55e13c647d304e297d968c759a378f1d594897a026e3271aa6b4daabe174d6a35665b35193379f0ee465df7827299c18e1012ac69913a0a5bb5142e99b051763de3e98d5af8b62133e25b32f4f12b787bef7e21dec42de8e4d99a0adc8f365d8cd3e6a5ff3064ca18965ffdc6b383f7ad08186d735a099bb0ee14506388c1a37f7a766d286d748d404457226b952ca6cb3f317b0f4399006b5b8c6eb89f6b8cfa023cec4d2dedde3e31b9a633c0888989b44ab182a5aba30ba78640f477ef1202f6496fafc2a18e283b2e4e8bc60415a1c9a7fd68f15cc1ea0299e3b26f5755ad9f13481a0563a524c6735942f5069dc1d6a070b3c3698e9c503f67a11efe59413e937062668d3439a5dbef197d24ebdc79944b17c549b0648af9b1349cad83c2a0a9e55fd893cffe2aff4626662ebc5014e70baaf7cdbbdfd3f92fcc5eed863fa8afd87f88873f726a0a2eafe41fa81edd5833f5520cf93b0fbf0660e48eb0258d313bafb87dc9b0d0d9349f22fa2d960238f67457ad644bdc60fb5eafd1c88dd2a74db4da0f723a03df08af6c64883f275395020341d9dd3c7fa049ab2bebb4d8af2bb8dc1340d1a80088c4b2c26bfe7314926ee64bf239306c05dc2ec6e6c5e0ed4f6dbe51f5ee09533f558d29ca6fd27092c20dd892c89c83223752006b23e5abecfdc733aaa59c8549e89e5ab0eae1b44189f58cf9cc18de0c2a2f46a9235fbe42c641a890039cf6aad820f1f844edc24e69bc3bd0c22cfad3804d876edf5491e88cf891c347ed5f24464f2df439bb30742e1f9a4a7eabd9346c6a5f93af22e67becc494cadac82cf9cb693acf44560672cb9227eea2575f90b0e28431684ae12ff2e86fded0be3a099f9ddd32a7285531de8963c9a03355f1d9cef88d7ed9b842d0066ccacdb698d42ff9f8a4f000b9764a9aab1f3146f9f95e6636fdfc9ef91c4d060a54ed7f32167e7ac50590dae3a2904d5d2eeaeff2930bd4cad7166fc17edd2c30e6738157eeb0b441491e5dfdc17a7fbb2bdc6426b2cfb26cf2a7e20013f1b3e33a6d6821928443cc7893f7e4a5268a8b94a6ca6097d25be17b214ea4301e9a723194983bbce286f4363a53afd9e94dda9c761481d9d20c7687a2ff85d42436b9d557d5dc6c5e24ea21d5231487df9fc7986100664edbbc51ad4921c5ec9fbb407ab33ef5c3b3bc81f113e68f38d73f0db0261b656fc344d2d23b93446845d69cee1704834d98737848d405f52f5a7bda3dbdfcd3af3881484579d2d2f3ef976cb35c9cbb76252f2e00019363273489b39943d212ccecc647413c56de69e0087532223cf9b28ce3f77fed30bc3ae6a0842b546e0e1a8b6f6ee1ca0ef1b78c3ed829af817099426f94a447f67229cbca3c07b7a8ce547c5eebcf168248e0a0b9fbeb398e5ed2d0dcacb441f95f9e30c108c725507e459d34c1ec01b67065e5e202d685502d6ff015d46c20bbeef1db38c29df7df585b95d79f5687474e71fff162c0ec0c96c94c507f8a0292a8c32168dacd2fff78b5c7dc145e10fee1b25c478172af8f3ea132fdcad75dc22856deb2576a5ff3e8911842c811d1d57ec203c77b82da3658cbfee18d140ac341d38a30f1af298cf60f2a88d0dfbd3e079ae64a07abb4947cc042925fd5c64bb5d4467589f8c495b0097073c081517bc4504dcd7442bad7e7acafc894fcf34f535979364cf5e908a84e0e141ae47e2ae4dc95462b4f345b12b0629502c7bd65579ec66b2d0a951302ba6da1d1176db6aa0c0ea1fa88195dd2248990fa4aba88490b1da4ea405649203f6ff6f734693f40deabdad59ac62e3296cdcbd74061474dd7b63c46bcfe6ea2b0ddb0f7e77fcff3599892c82425b05ae7aa1a2ac1dfddfc67e11921ff4f2c8f6297881dd5e38ccc4076cac8015c59cdd6023ffbd62b887b33ef8d917446a8941d9563acb66a6226fa4d3f2cc21604c080b3f83e73c093d8f2f7067c392671020c7a7eb6fd0d97af0d63032a3116c408b708d4b2f711c1134b88a91aa359608550f0049af2bb97688afc4352a45c4f6d30d4634e70e82515ff1d5f77851ee857e42b486d5e1f3e0406227dded6c5f47eda30d94f44d978322891dc729eb6ae95d29d22c8a5d649193d5d2aaba782fa16ae488f645a7ed90a566e182f97bc62049724f4cb5fc71f6bc7be57f07a7afb9933f6706cc83483cd7dc4182768cd35bc42f1e9b54d5454d3a17e734475ff58fc66d75419d3d122eff05f7b0548188682f1318ec32c5bbea87c8624cc1e548bf18a6b102e7a43e6bafb579e4e84275fe07d8c63ace449a44cace5d9305ff756cbf40e5a6a20334d5b4a74ab0483e31593f2277e90341fa8036496c2bc6d2b7b10b0b354c86d666d65cacc593d1d7349e71b0360d823453011ee16b6280f5c048111b99b185af99e9d901d4eaffd8a96b1ff394b66208ddc1e7e53420fa965bfc4e630d73ad97b9c5c6ea884c619bc24ac3f46234e7d8d35a12b0cad7220d7a0945cdc64fee9d8852bff872c43f359e7aadf8fa3de3551fb716704af68a18f79d03b3c7d90cf21eb4bbdcbb4004f8ba15ff0bbd2d0918ee78e9bde980e4f3cc13558e6fdb40ca71ad2c10f5e5587784bacc6b925f72da12528216895e0ca4b350d078fdf534fe01bc86b45e0c8e2b35799d268a457f8768ed782dfb56abecfd2b9db00cd10e189c6164f82f5ccab423277e3465ec72d76b696cafc1cfa9a7fe47d142fd6672d9c5b77751b40801af07fc53b1c9da0fe6981ea75e066572f7272baef8fc54bfa7cd71cd0fbc5d6cd717e9aa07808496ad2b4b4005a320c9312c73385afd61193581dbae99df6c25f1b9da17093ccfb108b0a26c5ae4963183533ce2f0ade01bf5e818af613416433578522b1b1e5aa7c791570c8c8b26ded266399116f5789a8233fee128e54ca8ce63fd56c1a146c3006316d200e05715993d1d97907ca83d7fd42ef7e7222eebd74f9c86b6cefc82e614a53976272c8801bdcfd882e34d86b39142ac05088a4c47010a71107bc72a380bb3e5122981d1795256beec20a0fe568002d79a4b1577903fe8682f268eeeed0a97861337ffb6861bf378eba1e0957111c7f9fcfeb55a95238005b40e13ce40efe846ddb86d14c9ad2c46cca74baa364ed08da3a3079fae3a36346ac949e2174c661b8801a051423e95dcab6a0f9c965e8744bdd0e629bd3c1a1241e99951ddde184eb8f354209f24c04fcf10fa8f4e43cb55c922c28be041213ddcfad65c86e1ab9b615f91d5fb11e4cdec5b7e25f8e9811c82c2ed457d012e4967b555f228baf4f1648854c624e0525e36e5f4d1961bfbbc3621d79bd6bea72924d8e0146d0965c239a768b417ea4c33237a60fff2760a9dbfb1113a37b01b598f3e06987d99518bd9f1ec96cd7050863898c8664f793ef29114bbeeb9afab8ed09358d1227d7de2aaac0ab2391cb2013028ca5f4d1de6425ec5feb17d95df358572fa27fcd51d14c363a36bc37c7497a0f964a6c004561f68349f828d30d4633e87bdce6b6d92384c9c1c540c8295ea621e9a8006a8d7c163b988853071e06c78f1b9a0246db052e8484a65cbdced3a587e45d9e2b49a5501590cf768d08b6a043971110e9c9dc96abe855abbb7aee2c38bbb77e5c68d61f01f2376b6122450117240532c7c840e3739395dd6c9e80a432423fc5e3a6dce9dcd58eb418e16d7aa507b4d67dd6fe2af4042a5c7398ba4f87c650926084efbfdc9430a4bc2be544880ecdf7361aea06a25e4f592104b0d74312f2729a4db5876b675bc0fa68f6e41e014b7caaf6f49b8ef704b6243df410dce94ad2c51d328fb90b9cf2f5df645015f489a262f57a5aceba40a56d343403b660928cd7a9d165f4a5bc289c0d28f33dac85c9c2a5c79b5ddd22c744a0388a5daf4bab84d7c77685053c912c9a24b5a0664c6253febbcf552c4ff38bbaf2f7e0c9f06e69a91cff9138c2745b99367e00ff6b6a920b1812e17ba44175c033df0e58d1b5c0b7d146f861b62e812ecbe99d638219e0dba4dd88089005977bcc90634c4dfa95f87370d905d32f613358fba2efcface0b9a414ce33b09e271a647b911843933c5d1008fb0717ab59739eb8eb844a4b34bb1a8f635c5895afa285ddc43720e78dc81eee7db822896bd9bd6ae3e7fe2988ba560d58f02592870647b94aad1dbb0d0cb60e28135ceb72e0a6f4b7893a56eae83f9d9a4c549d53d17c6a00f5d6c266d23e7a1d13e22a5fede3a7082dffb34296f8fe9f3bfe525ee1da81efde3aef9b6de8457a10fd4340809e1dafbfb9e2719c327a3c3a4c51d4d5600e8a01ebd5c537a4cd7c4519e963de06de6c83a9b968b01f79e08b5415c5a9d6a92a633d6ae969b80cbb2cf4d6d1ab2c3b94e7c12df27ea89bff4014d92add41a3e961006a194ae3ea4a6b38c2827f6185ae636f6846b1c8401289696fb10c765fa93e58d068bdcd8c9dc95df572f096d65f5de42bae639d41ce7e1ee0f48ba4faf856c0cdd728956d7e4babd6d9d6389ff41d76c5fbd6380f351b05a37022dbce0a6a47ab7168c82c77a2810c80b1882f825ebf86cb7f6d0f54025fddc9b9120802514c797d1d3968631dae95297a857890ff1dee408909223d012925dc08b7d1119fefca7466392a019d4121ea76c8b4c3bd103a820557e4b2283e262af32f1edbffaa253c47d5873bfd0219b8be86c7e64ada2d87ab6b7f428a7d8fb3ae09b05aee71054355eb83ad76c05d836a9f1a65511b1553927ef1b19ab1576d7185af61be6104de1df218918179c6321846085a83bd1217aa63d0b03996ac1fb4018a8ab54fcf635f7d5a8ade95894f0d407e5d4691920f21094c6f632f1661402a0b3351f168f16a13d3a31ad48e89230cffad272926487f36c7a2584c9387623df6227be8c96088db4a21c93b1c88ee756e960f60e614b30bb6ff757c20f3674a7ae7f6ff6a9115a0a6d444513ccc0be5dcd557430e0ee8db3ed5b3e8c405110500b9bf7f6eb7748de4988a1db94bcb16fe33479f64762c53a1e2965363452063d7bc14386ca7b4d46ebcf08489c64ab413ec0f1ddee8719f5fe978d38438ca3059961ecc8480908cfaf139d88db2facb5e7a88a43a67dcb0f97a17f9bd5b09b8369803ccc7ab6d41238e59e43762965814c10c36fa4b6e61bf2e83c0243f20ee8aab62dfa9827aec06f99c5c565c1bc75291292d3113503a202851c26d1a8bde54bb30f0301e555374b71e278925a2afb29b0209c08ecb89601bf612ce811a493abe2bff78e7fd02ee13c5db6b3edce7c87559410b9be3be95465468e33af224d6508a44728cdffde4cb14fb96a0d2ab9c7f597541f9963775c32ac613af9beab89e0ff7a5e35613751061b0511532b10b3947802901505c8e33bae67ce0e28da760af7e80b730811bdf17abfce39d35def51d73a084119449038c2b0f1c86d844123c6e71f28b7038053e279dd11c088dfa11c547a4ce13b19453e88e5b74962101412490cfb68e21d8952db509cd3a814387b67339fd04ddd2163177589146409934f0eceb10db2d90a9e3f6691eb75e84d5e66bc3228baeadcba200f3d11e0cae090ffbb800f5da7032c35ab572de55beea37258bee6f191addf01739a26efaa612991cb2a3c6d1bbb03de0ee1fcf9b7f6c51e452b21c0819a9aad93162eb2dcc189bf355ecd2c3e504713dab24bfe3ed86a4194611029f7f6216cd469fe1f7d35d56b6c8c2045011e238f9cbc0a19b8914d74329e2472f15d0b7d60511814ad2736d6be168aac01868c2a675549c849fe05e05a76f077130b46896735db5490277b76bba43545de6b8ecb53fd20398eb94dd884951fb48d5690ce4bcd0b836615cd9340ff0cdee1122743accfef343811a71c7d14d1369fa49ce47784a6ff8adc26c151edd4969dba513ade6a9b1f009e57c3d6aa845ddee275169ce58e1f04b564ffb6d0eec75f7172e5e8fb814cd702c9fbea8a783bff637db8667d4b6b48a264135bf60acf335936105abacff0351ba9aeac88e9522cf7ed80069822a7db1a5d8221d9492e02ca893e1f15965fb82a80ee2ec491027bbc8906e71cf931fc21e1c0865ee06a79c023929625b4d232c7b3e2e4a4e5dde28fab675391befe583c95dadae71dbaa43e09d8d65ba36d148aa85d1a2a35dc51719ac0311ea72c1237c78a8b1542c59de3b743087245e54d3111c585b5e5e7642f625c8d44c6d9cff50d8d071f6fa573df937d9e7457302d8b293d8fd94ebd3023c55f8b260c3454e93f58f16d0f451189bf41c9f9b91d3c3918adbf98e4ca5aa0eb6314041521ef880ce18f0ce296721a06b329bb5fbb3024e424b46400e03caf0105877465285fcb41a93844fb90b7fc1924883ace6ca8a37c9905068c633761163affae39d0ba55b67fdc6bcf0908ee3a42af286c" ++ }, ++ "transport" : { ++ "secp256k1Address" : "0xe23c5bba38d809fcb2d3384f210e9a6405beb498" ++ }, ++ "ecdsa" : { ++ "addr" : "0x48fcd978ac4d42ff52dd81fcd17e93190f35e5e0", ++ "claim" : "0x2dee91bd2cbfa906aefa3a8ae6e2de773f55dbd28e77bc329d28215183068585601ab9a7f9ff0c48095407474d502a3af3f059a666e5ed1e27468466d69914e801" ++ } ++ }, ++ "1" : { ++ "id" : "0x690a7fd66157e5b777256ea5214f634f61b3a72d", ++ "keys" : { ++ "falcon-512" : "0x09a6d094d9a3a0865864e9a16b477236f1ca26c888fd0c918db331c87a478519c41085cdac7e6cd0d89190a41a3bd6f4d6300995d591f5e22a7b7147caab1f9c7a85a4ba74d47c7b227326ac17535de039a7e604225d3daac7f75b9544654b73f79f5825825ad6e6c45d13e6d385a644633e1c8806d3a0a551c98f032583c95fb13997e52a6b02192d26b5a47fb22ee52999ec92b75c70774a4ae0481a79113ac72346263e53d5dcde708668d317dd00552d5a40ad47e59a501b10a50bdc52c5c2b2c920fa0e3dc9b8eca54b10aa5ab1168c88287dcf80ecd880a8fdec85b6d63a15b9f453845421a5d9b898e6149b60454828eb9dad6442ec62ad27ed72215014f3d17539085ea3f668b0a9183ab96e9db996801c72a0920b02a249911924f181e8dda515d114beb83b075ce7e7a0902a6971e31420ee4921f5cfc123f29dc7775017aefe99a7e326119cb925f6f603ac3bb137313609498d5a2000c426cb332c82500dcfd80d70a5e2d156844a683b313266af6d60216bd9e9998bda53c0028f387ebd21a5fca6c0607d54b1e95724746d15f25f16e45845926a83c7598646a0a0d3a8f8307c1a401b823f1656ca41e5499684150a954318da076af9131fcc93361d9bf0ae035f617e02cb5e1224a982b3591b24013ff80dbb61160d2ba4ce85a4260c8a3a3218e0ec869796b1b04a82079cfc0ac26da03b04a11950b2a3331ecd0026ea9737bd20e6ea3045b56e3c71278d2a8c72c8014b769da9319e19dbe762b1943e5a4be15aa84d0da831eddbb10bd05f35d55b6211d02a61c5d9247e69cab6c112acb568ea51f345a5bf16f84782e04220e217722da71d634e1a68b796376c8a49a965c592b87d06702fe42dac12da108d24ee42a109e8e4cfd3bed6ada5e3de50301696bab0564292864f1b9f47d5a53cc0c5f9cc3d57051065fd57064d08764892ef4c4a92b475184a4cb4ce1f3a0e6da0402414db5a9db34632b9717586e799b06e870b81a330da7be6a45ddfb000fd337a24a29e164449f96be015818c53aaaf09b9a565d7d9d735b9493885e7cb49a5f1985977cd6824fd62f51d2a1e60289dbaeaea148a44dd8876cb58b8ca2f29f6455f354e4e76aa13290f2979b78b22afa0e65c696c21497e94bf0141ac6298aac70b5ea843848a2264fc057abd3593cb17465e06d41731b7153b71f8f0f7a06d362fbd09845f0815794050460b41ad003c9396a86eaab240555ac8c75f85c0ab972c1a0b94b67b1aee2fa3", ++ "slh-dsa-sha2-128s" : "0x2b2fea4a0edd5dcc2f653eb2dd000aecd87deffbce8818aae72d7862b506bac7" ++ }, ++ "pop" : { ++ "falcon-512" : "0x3968f2999d69a9c28ae792a90a47363e689bd4b349e75c5f837181fc7b16d3d04489bbc32252d750d750417770630c5b65b88cef918ad23e33892a58458e9e63ea591596d3b898f65e1a5be3d36650c3d9834e1ec725426960d337b8f25878525ee3c3798b5afc9add5bec82c8e139c59738aba9ed5f42d11c886472e81cedfdb5b910eb73e884e0d4cc218b87cd9bcc0bc107af586c65b3949460a25892d9607efa341f232e478f3c9fc2d05f324ee6eb7bcddb72af371d47c36856f488872249ffdd322d3de7d12b62b1ec595187b5b363e36cc714b765f0ad5616488300f6e56811e88e359365d5698ab123b917bb32f56566958b154f6fe052b894ccc1fcd99d65d19e8117a8ca4887e01f36f181461a433fb9bbc1790d8b14e34a097b149f0c5c075ecae3501944935f3caa76f0b9370ebe6b90390b4d059f9029ee4af98dad33b9050877d49c3d4f2beaa4b5861a21af95b8c52f9ab4b0eb115357f5b1d25fb66a36b9baaa4d6cc5a4f5fb5462432bd82734d7393cd22c68f52493eb3434c3b88fa255baae5c46c650cae17ebe59827cd6645c6d377b3cdee3aa6a758ad3a96d103bf6ab8ae03b72b53f3aebdda359288c32ff5461a158962924a97a24af29f6c976762e8de9363485ada49c445566e71ac75379aaf7bf190a81c671115e842b5280a05bfb2ef3724bb74487068d5b5ab2d089ebea7ffb4381a7e96233f0915f295d3b71db872393bb990b9c74717bc3d72f6271bc248e54828a1e090f6da56de3643b083e9695db7d0a32bb42355e245e5cc2ed57354d82220b449e10cca1cbf6fbe796d141591d6f71e4eb6770a3c7dfcee509c3c28f2f1988eeca61833b6681e6766790c2a6f043b4f67e145b908ba7f03361cd9d435d054e11edd9667e4f9d12c2d74f2832b619", ++ "slh-dsa-sha2-128s" : "0x39254afc16b1dd8d4fbfff766819460253653dfc6a8e29abed55ffe91325afd578ebfa2dbe74d46b48b381e69d269b5bbe24ca1b85767bd71c744065fa47c646e3603b44261731b50f2d20a7a327e98b84c5ece73697739c8057f99d6ecbc54cf891649fa78b7bcd824972f3b27820ffda3629f481b1193b922cefc907bde3ab1c78b5ac97ff26986f3a553556d0b158e936450b4f41bf006c90a9758e0efb327f67408a7b803ede993522cd9042db4a672c89d4765a0fff8c6e8bf6882a8de432229dee08ae13def90f9fd0a40c99f3d93873a41d74871aaf407b0927a817b476eb93c645254bbc77d131e0bd35a2541248172993b1064d5b26b921396c8c1664178051810961039b15790862415338806329a45a266aece5904312afb1cfbeac1e816fb96256fc6e2b059c25af1966b0bf261bfb72afd8652feaedd6e0e4bf829a75188708ac9c623d4d6699281913bb563b96818f9307b66f7cf4aa9591e30c65a0b0885c22b5d17ff610f40bf2e0a9a32173b2fa7d66c14784402885d84f33fc75afd8f743cd10f5ad6dcce5b33a8f0c0365de2ce1b69aa86df2482a2c2d3746c6f0ee4e6fdbeef5738d809f6b0ef3cc703b0d29e93e198b68d62a5be657e69c33459fe4b163a5ecd72a90f1e53fc00bc8c698af7ae3cc5b07e36cb74088066a54138d6df4ef6e159ce5924b6903346a5fe115272cc951e8713d4b6f96f78d67a542c3bb402e69bdb3c2b06e189186c227927b2aba52b29c14e837b37798321fd000ed3bc0e386ad6e5d3a48494f57109322f0a87f7dd752d862dbf772498154804b09eca84c305595cc1e6654b1b2e94d5b88feda176aa144d3895a249754bb2ea99b2efb4f61b828f265638866a49dd3437c70016347d5aae64c79957ed394a85cfe06b10b98b6e83801728645529537a1102bb04ada4226688594cc28aefb24fbb0d1a60c7b826dadd23f301517e862c67fd88d0f6a5ac08e7f966ae375b468e57f01521b43fc24c761838c174ac106c4e1f435b7ead5e79aa1b303222f6b45c5515d497d8e7b05901bee96945652d304ad9ebae2153321885f19e7ad08c9da73ccc22a66c26c4cdc9360c36e307310714ac44c80887f42a2575305ef649378d76d297dc6faa904377b2037618f23b8be496fbc680645dfb80a76bfc060c6b2aee4ac5537e79b7dc7deeca0ca38041dc877b875cab1a297190269c987dcc46ff34e5bc154e2572695e463542be79d61fd5e96a4be2b07f5beb71b882f99de317116fd0b36131a88ff9707eb25594fec74cf76c2859ba6ba2b968d41479adf8857f4b0f4a26f49f0f04fbae0e2f3c2ab6aefdf01855a7a5a4b8bf516f4551a393a33d3920ca3ec403b4d37c2106d777e3d5dfa768614513885d857ce95b9bc3b992808e7ad71575e5e91b8107c5802043b221c74d73c7bbfa7a191945bbc5ed69e20016b16e2e2987818cfa80695e58950b0c1bbb8c474f861d1447161744c75d99dc8240338c43a5c19a8a9f46d80f6b4b6c1cb57f5a3350bfc35a0522f89e3470ccd71a458968c629c93336af6b5b091f569d1fc9492eb6b976376b8ff19ad9318f5cb1361954a0471419b4207dd9dace8c0545e74dfbb19ce3fdb5d456a1c1bff7383c6fd96dde3a92daf0ff5a315714c74711e3c05e0c59ba525c64ebd17fa20f8e143c5931b3c77da193415e6506c2db27e0e773a6a5b5d47ad95760b8d471d06d5dfe000a2d47e6e4e6abe7219750f1f7892f4e09fe88d13c2e3b53dc904ad58eaed856a4abb0c10830b96bfc1b5764f9e4b34b0072be314608fdea8c5005d40ef99806d4d3edb72e73541fb828d4b2adc38855e09e974293de25da6907f5ea97810eff1be37f88ea879e545bb5a70d2187edec81bd57a95c0314df4ad08a864156579d50826d0cfa511d335ff722e246151a7afce94126232f6bac89b13c142d29e7521479866e35b17c15f16ee89d798ee8bfac5868e505031586b81bfadef4aafc2ecdbde649f63e07eb6026d09910d9d3613a9871b5d1523cf5958124f96b5304d5225b4bbb03aeeef87753d0b6ab51a287df1e9031f56f755d3fe5a20f79b7f0f467fa97eac5bc09a1adc6ec285c8f80ec5c184b8b5eae326300a5bce0b1d757c8e4f27ca2822e73745009291f0d9032051e15b567511908f3ec68840cb6ec6018a9a0e30f2e34759743ef0bc9e12c9b32f29f4b70a998cb8893af2dcf17e0eb4f48e7ba367f68aea5516e7248c8be1d1f896d7e8446fadd9603012dc13126878300f0868bc512221154a5104882621f831e60b49d04fa8a701256b3a413b9db4abc5af10a3f8f4c26cd0b3c2f55a58c9380143d835b759bac7fef824515a18d79b6dbd361541047c79653ab4af5473b7b7e67a6755add78d5c14c0a9edc6c7dd42c3d0359d9f2f6961f8930458a34c4f12478ae45c20969c4c18654d31a7ae73902757b3b8a4eedfd16d6c0d22548d7b8ba77aeb4c1e3f3766b6ea802ee9bd92c5f98d00be80c15e7e3a82eb0d100436c398781607dacbefa98c87b3558f363b3ecb1ff313655838f864c1b2e0f6d6369bae4eb8cef98f564108ab2f763e590a9e9201f4e28ef1971438c30f4376c55cfce9b9910f448e31d06c2e456eb798476d56a890660e45616840377ea0574d1c066ae2fcc46f41cfbb511e5efc4b5c60e00e4846e157bbee5fe3bcd77408e3bf721bf871c05971a70cf7a13c782bb4afbdb1ef800a414260243fd828b67f49007eaf60b3e32f4e2b8186291075a0b1c0a528abb9da7974b3b1e8b20d337161ce234db66ce82a88ae1dc880933343961267cb4932b36aacc5f136cb474bbdb5e4c4be4cd74868775d80317bfba00ca4e58a39d04e63bb797de366c45efe2e356672f567ed1f7b2741df7543d6faa7227601eb7cff367d5a1ff320ca71fa2a1a42866239cc3fa5eba400ee4060266a05b8fe1e729908b95ba6aff8fd76b5e7df547df62cb89f0605c1207c869d7214e4e6972ea6e47b18235855d6f28265a737b4f64f0d215943f13d219292036c1cfc46bc61679f034919e4fea80d882a5121cb3096a50f2112eab265ebf75b607b93e14ceda4e08152221bd368cd1503ce375188d23514dd0936bf980d4282eaa6fe8f38f5eb00c34e3557ae363538a2c15b560b9f9322d1f17446e8f3fd317126986afc2c5e9fbb96f8ca7148f53cd75a4b845a28034c8679baf1f5406564b6e4b8fa8e681b5a9d208f3a1b28e84d6d52d4baa152524908d50d71d9c0d11bb5665c8a6bad669dbf303027bd0d534434f9e76f2c300326e25d00bd8d3bb1debe1c3984961c0ea8dc547e8cb83a8f3b044b673f4a08882d103d6eb143a9645a9a00fab6f1167a2c09015d6ff2dbe4aa4025f604a63eb32330f832162b6dd9364f4ad6afbd86c8d26f56d7d9028dbb3051c85a0c86ec0d7961fd6008f87dbe8347fd5ed1dc4c27285364f63650f161321daa83ad41fbc3412bff800c062a78cc5caea330cd58e63ea9a9d6de2ee069732799f52f49d513c658a44a2122b8427a405d706f740600f855130a0ea720f76b3111dafddf0e2ebbd13f60640379993889089ce508b1343f485457cb8e0c09760d3199b4ea940d584417259e41f2c66853ae4235b6f010cceca3859952b3daaab55da14adff0e421e862f138872c2577637b3e12b00384cd32fb3b9c97b0d59e51f2488e379065d79f5a834b076ab5b35fe4c47f2c4c4f43e622527abb8f682fe9f262d2883fce5c9f16b7566c4e078b67611abf72cb8a0263ba12a6c23b1a04458c759f2bdf6dbcc460bc5df48146468073b61aa5ab4a9c5f6c006f54f1bfdd85373f33af29d68580eba4cb6dd88054c81b3bb7f2be8186e380bee0b32a1b84ef6319798079828080361bcc27473a9634c23652ed6b2b2c8f8d5a6721551c780870f1787726b121263e74c9464a76282dca27249b4532e49455a7485e2cda4ccca823f62d3b2869602197a6f1ecfc9d92ab6e231996e603e81e3dc648aebdfb900a3d929502ff0bbb3dff813660c9d5a417d857c19754ee04e50f1241831517fc2d2a71c5e238a944992cc50b7106aabb5482fc7e0a2e6b5b11bb6845f34ede98a18d5f07759e61603de502b5eaabe59a4d2c69f4b0f8e73a9bc85b8950a54bd91bcd0366dffaa0df736dbbbc35d6accb5ab8b22a870374521f2035c1878718d7d3b025838da75d8bfa3ff36b2a10a3cdef1b150abf3b6be95a5c096a921a3eced20f509dac4ba43f2f515af2b65d3b2ebd0da2d7a58500157a666b387b1814d0a3e84f64d0fc44507b0b6792c0c6bd90ab62e0f75b66d50b6f842cfdbecf1fd043d642c5d5b5fe5cb68af62e6e23cc6f0f9b1cf3cbd0233ce48a996296b6609be1c9e7a027cf76615dd11208f1fde119099352cc17e1c9a22f4b71c3e628d72b620f3cb4bd40e4294ff8dfe19480b5b758b874a737e6092254638a222c83aac52fe0f66670454c313adb0dba2b4e95741d27104bbff159e999e23103c00470a7feee6f4a35f764ec81a8ef520cf1e8623fed3c06b63c022e40e7638db269b8add119fec50456b33224c14486f705e5b3339c6f38aa4ba6dec8b098c27447185ca50cd70772e5389ba703a4a9f8649946671a238e1f005aba0b3a18c8ceda9daf4cede6782d27931c638af3f6083b2bf10ff0a632ebd4dd528da3aa2b7a8bddff2901d902b26d518a058921eb0178ef08e24f7075f77ea0c0d0e72f29847ac7826230c0ddb5e7fc8552ff92c007e9141f51384a12e218da4fbfa9a7a4a1bf266aa975949e120db1b6755ff04adb07c66ba9619b40396072e7cc01dc3dd56f7a2f928a82c8906be416f6d5c41354881f9a6c66a927292f8cc2887aee86e90da32fa3bd9d72bc26dfd334f943305fbe4b645df83fb72c565f61860a480dc0f2f3360368ec3715c2c4a312bd2653051c8f29fc14e0c3d1f515e04b75ec02cac2aad8d411306969d9a8da08c3477eb6201bd54c6ee643d87a89c78a5c8ad48590b7a499cc44ccb812866a4c48ec2da5f1e0aac741464b26988459f3724ea4cf103c27e4a43e5a5fbbf94908878894f8b62995aebc20e632d924c82d9669f64b2093cfe023cdd1542c8f9d19e5e7ad6ed7920ba6834cb0cb91bce48fa94be47c1833c6ada4090509ba38defab7d56dde8168bac8021fb5a2aead00809f1881d53d26fa9cbc824488e16062fd9f68726c837234a82d518e3d10c9931295d20d9affa5fd18c0b2dda299cf1d6fe0c6e6959440af9b397f3441bb9881ba1d2df295d12686ef6b0bfe52fb2bef06620721374328551040d2fa434b161648b058b74df2a7ccacd7609b93421f44a136079c79a3e63bd3b4f79717f3c121ceec2c3918464f5619b1a2e83a7709fdf6d1004b0ee51c73e740b20e329847304a82802e02170db386e360dc6027aa7ba1ee35d7eeddb41ffde093073d92899d568bedee914627c8c48427376e7b5d5ebdab30e58147dac5638090e9c71921431f025f1d4e3ba3c68437555357c651336b326c9c519544363d5f4faa91914195314cc873ef97068d928a6b4e5c6ad70ea7a7b09b3108fd5696aaab800eafe463ee52a3f29e1bbe8a968e84b762484a13714ee260759b4492b749c46ab6603c13ece34e301c13bea57d9de706edc839f55b432b9299d2d6643817cd9d32d0d9ddbdbb23acef51992b62db024365ac2db4c432c531cc1ad18c807cf1ee39dcd842aa9a09b232cfd09bfce33277a8ed09953ab3b5d24e5a8a02fb4a02ceed705185880ecc47cb245665cf640ded4015b4afda053a5d1dff77e390c8105961cb3a954c28ddbb9efd759080dea99e94e69b03b928c8667fa4797dbb3cc6ed093bed107c817780f60729036f13346f05491fb837ef1ffc61be7b61d0b7f8dabfd49ec24cfcee088de38daaae6b4e740ab4faf16eaebf89962331a99f17ca5955b15dd1fa493b91e7cd218aebbfaa7d348b1ceea26951209137448caa93fa466ca32eda497a5b9a4fdbd23a10d9742e74c511a1648d00bca3ca23abcd4f18b7cdeb362e020c73888b76b83e70d26ee358c06933f77d1221a8ff0647200e451e971fe45c23aff60a88baf46f59a0bf94e99ab9337b0336ffacf8e79db92067d2b744134cefac1241dfda288f5c6ab293df7469ae0926c166e999ac99c8871e571eab03f82de73e9de2d8f4deea3724f795480cd47e304f27f2567cd94cbed52e06f1f1cf7af2feaeba8b95927eff950bfc26aa0cc3e46ec7bd5d4aa43374500f8cad4f153cb586620b9a0deeec2cb12ba48bbc8655c7fa70ccf94aa6891b5cc8a3c98b482d906d72e9d425301d0cc6fb4ec9c4a5bcdfdd74fdcef68f05fdb78f2a1c5ae32c28c43ee900738f31ac1fd337ce95966b3f557a727e0c3ada6c6aa61219d92fd5cf68fcd9b444f6b4fb6178b9c74238d2575f442a298127f282b5ad416cf6a365a214048489139918f93ec07f2cd864f5482c418c7336ca4590a7da8a20d33ffb7be19934c80b64f4b982a55b129f4896685534b83251d54e46a2971c0bf49ded9b13a77ade3de9a61f2204a46ed9cd7bc444801381994c8ca5a66abd70936f8d11e2a2fed78fe9fe8889dfcb979c9a3f11f2c2c1aa371d1e98c4fbdaa95d58c6b22410c0d3d3460077dce654a1decfc829f117bc407d06ad9ee6aa06bf818ea2f25312b1cbbb5de527ce9b5c5ddcb0df21e3442ffd149b24af5e59eb4d7e18f68b02b26e57fdf23e7af4fde3e672990295c37186ca67b2abdff6b46e1ff106f041279b61560ea2eae64649c65be22f9070c3239b0cf7929b0778c43dae5391d8d3b8c335ceac672376588a34d3b9c61833578e8d5a9e6e9f72748d860d7af98f7616431d1ae1ca20db3db6ec99d59fa98c25a1cf478e1b4a643c2fc9d3e482d56bedb1b7a1fc9c3e788d9de281c7356b82e3c9e1c9414a0d14cd07fea5364b6a22dcb3b69b6f447343822098548e3ca7e88a83187db145bda17f7c48cb00e6ce36d53e2d1e4c169569ee3fa03620a7131bd5c033062bb82cedd0d0ebc1025937b2d85a3cbcf6ef4458a57525a66244be3a62b582bf2b88549431cdce09f6407e1bee83d3fbe205f585cc7cf9c1eaba047a01f51e13bbe0715a9112c451f1daf6074a1af051d8b98863b6fd03238ebe295995d60e7a26d2f95a2b4b0d617af299133bf357518b84e942bc36a88b4030d91a7067e7a2ed7bbf4e9abda8c6887ecdfebda04dedabb9ea833123507835e0357ca1513b471da73102605ed03297b5e3eb7d3bd01c670f992a7f19962b706e8d0ae0f073638d633b34a1229b6979b8e90f2a536cb6024c644e1f7ef211451dc509e061b294c28be188c96246614a1fbf52db8d9a99f7100c878c1b9da98ee9e9eddf7fcb386061ddf46807c60b24d665f0fe7fde205f91021bfb87c8f4c89b5da254d185bda9cc2f48303b483ecbf934575aa45d0d58cea64662f0fda4d97790bbcfa237984cfb45a9cd611b533dc0ea997d191d14d307c68db318aee8f99544fd48fb86f041fe249a14263e6657a5ee732f7c5c9c97a8924bfdddfd75dc67da65042e711a3cc144f46d10a1a9fdac1b1b321eacd235299a1fab390df24acb739d61bd60c6907b9a3827958198e6e2b5a1c90cb9b44cf8db9b6e45f710d7a39c230ec9cd855af797555fb1d73492e29d17da0b6dac59c2ccde0715565efa1f62898c9b26438c60fc3b9f859bbd33a8e05e1d3d5a762bf19bc7c32cf7d4c6bce26fec6e5c8c537608a1c2aea2e1e5cca5bdbb45a8ed048514ef3d298e7dfb9c5408d941ded6220a44c184dc90c922a3ae31c9248c5f31627389770a59f9431fd0139c5ac0f08f69151a75a5a6a0355b7beab6be9829146ada371aa5791c861dc77598f09448af20deca73cf98a399f35c36f1167ba426c6cf4b8b9b8a22b961bca83e45bade098e20782a9f70bd54fb8eb6eda3acd3a5bbb553438cfe37e1f7fabf15729d6bd562cfe379d586181b71b3d3c4b360852003c4363a8d473198130642972eb3434c3a5ca9b497ec7000e821c3419aae75866496bb1b0a9ac6cf92f799071e06809f1f3f904cd18f32629e2093664755803f62f45942f5a358cb1e925a8694998cb14cfc52733c356cfd739c3976712ca7b007e08841639da14e429c102a8fba3191cd36c1c56eb06bf69afe3f2afc4ebf137c617faacda6baf5cfdcc6462ad02f63e8a5375288d0de5700d0f9f4ca82a65bfdc405d3f96fc663658f0aad91305b86ead3b21bd6561a40db0f2c5b0937ba5e1ecbe91e9c50b1dd6bd83a8145b033a7bb6a4ad4896e0ab160e8a52d39d2756b1c8d8570f7081ba217fd8803954290788882befde24b4971723b0ecbeea14d23c92eb6a0d7022a84aca072729d7ab1a88927a25f19a2086f846a44a2726ea26cf1b69c58243e219c756d06c361e1e161bdff0eca10bd30d23782b3374ed421f50cb66c9ee063ca622fa78c8cede932848f0f8f91bd7a0eaa324377c109808bd66ff463a72389c4b49f2e349be70d07fcb56b28549fca65ad853d70df66b587390febdf6b1881cce6c1ca9e9fdbc9f1ad68ccaff97234325d3c972b57ae5723fd73f975ba640f90e717e9284c111b76367c6797399452d37df6b8b8d22ed5e7dc1481a415fadc06673ce4eb6435d31acb6af68775436629a57db7a0aa192310e8427468e8e310bd3426b7ffab00110324c0c7e04ac6649b6f167fa8b928b3fe12ac162db3f2bc355295650fa2d976c64df69a8017034683bb4bd4baacf1cd8502dff20430d48c907107acfc4e29c584cb497b7a471fbde90aabab25290d853b8ebd2c0d49c2c201eca42a68a15879cf391671946319427b237472cd35431128ea7ab6d545617321592c07b09fff93e71596da30689b3c15368a1c3a57890e0ee5752bb4356290024fd1bd2ebfa19f7f3ca57c36d296ae61ec5581ceb77618dde2821460553ba0dd6dd68026b911f4af1be3986198966f90ab757aca2f5143f1937d09c3a08047b797781d1639db4030f9e59f8c5b71a71787cc84ade5a385ebceb1946177a056179aefb49e1f69ed0aa67901b2d6b2152b6c1fd1db67f358093180fcb8f96483fd35a87fa14825d3849dbf479be493bb2d1c639674bd195b5ea3caf49c2b78eb0e953dbf8fb909910c87efc6f9b6592c020333e00f83bea4bdebef4e107798f9a8e89fa5d063d69f88f31a53548ba2406407251f18c3d1ca6e392fb81a46107191e6d906b487469d0002afdb0f32c39873872a49eee649250d4d5d3a7687fde2952291c8ba78fd9b962060df12d212033303691b05eef0ae0e7f31b7e395576708d211d70281e9501618673afac20a93e82f060135e51b29132a0c9244551814bdf399b746651279ed135d162e366f39d40e3a49e907f72bf7c66fcb4ba75b1f447fbc3ae3f390ab4c10963d755ee188a9b0129416161995adcab12177976208e1c93ef48d3ef55ad22bbd97781dc7035c9f5fe25f47b703b1ed50dba311d24154ab05dd88ccbb5a8cd96d4665829c4dca5d5b22affbfd7e842ffe5e87bf4326f957392229bbc893b1fde9e4b2191a3345490d418e9298179661104f70bf6cf9a0094f9d37be98b82d98497573512d8f6fb4b0b0aa334a9120a5afef20e0379197ac7ec78da3688d2c9b590e40fcf866acbd1d857546522788d1f3ae73f330aad045c5bfd59b8a399ae626fd67d9797b32d6a279d42eec3ec8a2888258728f7c329c4efd0f71b730e57f9bd87204d40ac1ea6032a4b8ee3a338aad58c2f3c9795819af4cb652dedd475e5662d9c0cd23e72a8f4e86f1a63e5683c814a99a6595b779e5d715ac91ba62c1ae4ca1651581506ba80c2ee0d3f97b979758cfe93f373873f4775c882fb3b5815b9274595bf50488b935c82e0fb4ae4d078d30bf0843c89e484bf5a24d5de602649e336fb2b79da6131f96ef1b5f82cbd668f4599fc9a92b4e9ffe3468e39e4c8bd90531952327da74a522e479c66b7b1554c9a72a2e6db58fcd45588c9ff4f48be5ddc994913833b668c275174b9d862dbe8fd01535ff2bcff6ea030842ed3a4d105ba07feb0098e39f61a4cbc06bfa153c598c10c5de57caa413752878c7599e5db8482b6f275db2185c505bc0c9670fa0afe37031eab994120acb935bf9dbe6cee6ba336dce1b44732c4267ee77f5db890041e547bde486335b9a0b85d6640f6534d84b3729b3436ac1c0551d687ddd8da9abc18689e7e932d5d0e787ab5ee5f36eb53789b9ba2b71d7a4f7994e56b056d4a042bd2cac79ad12d87726ef8cb97342e616269e9f87493e95dcebdd91763b134019c0a76e8b12789b026ebd1d9caf1930010aa1a5c348ae2e6273c885ffdf8731b34d87c293e77e9ef14709c2e3b739dec85d5bdb8f5ebc9eb610240576435c8d222ae0c8ebe5844980560bcfd45cacff143a5c208add9011bf9770b7803fa90bbaa10f58d856250b37e481f325c538e473dee7863957121374bf12172321b9c99975078e43a0e1e40138f9c31d6dbe5e06fc881de840e64899c0cf342a806916147de3cc342832a9514eae9550d2cd1166e823f404a05b418e5f9ffa84352cba3007f9d37e5b00049d7c099346257fb53e86b919b45a9c6cd8b67cb3c4e383fcfd5789f2cc087d6b459e2a7dc96d08c826c43410b3df22021855c7d413d9cfe7ca79fa860918a74941e08511595fc9a3bec2e2e0c6dad05781c0a0d6b6609837ca8f78b0368b1217b121cd6ced8fa48dc131709434eed65523269abe95f338bc5e3fce0046ecb24dc1ad8c8fa68b5f9263361e4952ca1aee9229811a5ea85c9c4452235639d1eb8105ff88c048beddc0f7efd3690da8b9bbccbbcfeddcf3e3c9e3ea7b46a5b40098fb85a25842911e42a714c2dd0fab403340ddc1af9484843b33c7f5bed80fbecf68180c9b397ed85c51d39cf08c5c0336b149e6d1747360541e84a93224ae88c1b62384b938ae25ce17d656b9ae52fcd9100a40dd7793ca67357f3fb00621863a490373f0db49b1aebaff7284d450922f1e5243bb7fb5f7230dd7cb8db1e08893696908cad4a45711eadfce8b0b42a9aa937cd011bd5c4a8c3a2ec771b3ee4959eba5e4a17545d1c86acaa4805e4aad" ++ }, ++ "ecdsa" : { ++ "addr" : "0xa16c987b93f1b3c51fa8a9833c8932eeaa566ce0", ++ "claim" : "0xb0c578f123a8a0c96354a13f98c4c2cb8a67541f5ccecfdd0cb6e61aa77f7768157dfb3ba59aadbc03350577f6f31b4083bec30291a61ee98ecb3db2536f788e01" ++ } ++ }, ++ "2" : { ++ "id" : "0xa5ea2fcff9e3cf29d0c6f5f147b67ff24aec3bd4", ++ "keys" : { ++ "falcon-512" : "0x099202fa37d5e165b88428d963d2a224b8fc82ac0e4b3f6a02376f18218d1aa7d0e910e71586aeeaaddc2a557124d6ab4f9a44b9cad02166413cbeb14b364e13956ea326900eb2900802644167639045d76bbc4e051654cff404dccea94402141ad9fd992cef7a8fa6478b3e6f8912886e9edd1b34c29385b7e964f360e0fb1600787934486f461c95d577d2bc74c4dfeb969b4798565ce0225ad27aac052290a44f844ae233e082c97e4498a31117ac9d02f3605c856e2dde6f611812161f89cb3a54dc936ca1e740a6c659405ed586a9a963b11c89b01746325e39e645c72b0c7e4491b36a17d43ffe38d88c601a5976f5a9636c964a012bfbce5f9b371e7c3b38580d81c6e12b8e8f2aac219f96245d35b4f4afa6c94015b055703b8c4dabaea4ce2577482f5b34fa49e56a912dd58d74580b1f94e1d2056594ea64bcdb696b0baeb33c86b6544761a3ead9ba9888cb1ad51f7027ee52b21e46c5eeaf3f77bc0af7efdc87acbddda7dca00b6acc665002c26447e5b0e0bb5ba261717c68dea7f1576462776954d7249c2fd0886f615ad50d53960ca02d581a4a25517c050ed467c7a820bce6250a9ba2e44fd67fb21bac843bb134c95360dc1c50d54b7280a94440d018181a9d6374bc64d782c84471b47287d8ea748c36cb83cffe053cb89a9e4ae71df497871c2a728ef210903e5b7f39550d0331e15637be7e28b3a2fc05b0a9b0c5a06f9fe81263c3a94403d6c288a561288ebaf788bfe271a578a1a795a85e9d452b61ac204b297090617286922376bf0a8d67dd35fd705b81260b7aad30132b965e39bc3cd64d154c4175951704873992a814814dae5c6bc1e89a83dd91144cd1b88f6ce449900058afdc53bb44bcab63d30cbd6df115a5ee8f5380a127a160e922bebf7b408de82514b2e2550a0931e065565e8dfc389d454823a55b03e5c989b09e3791f656794e8379b7b4b1617aaa9770366d63a657f71ff40c69b1d5da518ef1e2aa42366cfa38e448563f6c2db5e3089bad5520ec26105fc885993630c10db357883f588a5a384cd6de688e1bc3b1200f87ed66ba3d4a4b671b2a500a0436e0955904030d76577aadddb8c1ed21b027f198c072f654c3abb086e7f185980f49d0e109c1a82741809f8afd15ee56a887b392c5b172ba659144a7e99e25ba19792d2a3c0ccb481822839c8c70c65c0943a2994ec9f6085b7ac64ce2b35489a72dd6693d25f2329264e063db26ad4495e3ad00f12df8cf914fd846", ++ "slh-dsa-sha2-128s" : "0x686b5dae4aecd5618b95c3b2a5792888513ba49dd366ac39b7431ef403e04963" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39cf29ab9b80215a9947b975d8c6097e53b39d1483c885ff7527d7fccdd2ca3dafc32bfbc0a19c857fa8be7e52e25064d69c3b7dde6e77eee96ec77011fee440c8bca99a45b432b5468715a0aeff9d61375393b3ca40b9140e1a2bc2a52c3c8a85292f4c9e87d1e0c12fbe4d7236ba7921b8b83bd10ad554179dcebf0791c4b593c8a1bae836883d5094499cf2ba41b00c8c36c77a83466c263a0b01e773f08ec66d46e97caf0f9785943f98e159e353f0d91d5ab526279477a5509129f7a1b8b07ba82a1ccb4acd5be5e40de088f2600e06a8bcf35f54663279f04c74838294048a8f8692904d4f9eaab49635068df74d1f5ed238f6b895acf1364544747bb10ce333a957599594d766ac5d1a3ceecf8a6696cdaa95f824ace18cc551e1f4ec12f345283b366314515849feb5bf81fd203a6c73b5bab7c01b5c1131d442dadcb6bce32d6e13c5a3e77b66eb8f5b2912c0938d89ed9e20a455066d151a973e4509b03f5d66ff7ffb8b362e0c09b969e21173693d9977ba06d48bd3b85657119f9dc3533c91965ed81d1eba72b46cfcff285131f84306fec7b271a02dd22982cb6399a9060d286aa18a3f97666810937f8a5667c94959a4c27299d55e94564dba27ea3d98cb3a9db6197c842eafb237649de3fab72a9d56098b5c1228e70dc062617a8a6b44d46b7899dc1e53a77b700925ed1b438c59458c15e9b91fa2c2164b9661a976720eee2864efc5363d90beea9789a6d3b0628bf4695a853251c7f70ba1ebcea06cb35cb47d72d2340bb9412edc49626d6c78be644c4ab1c539d1469d1cc63f092ccac45f66917d89274af9c84d7f1108b1bd738408e499efa63f1a87c8730400ec19f9a59d241032e9ab78670e85e8da24310b13e89ad521ad4fae3deb9d438dd7eac72b79496c7b65061314ae", ++ "slh-dsa-sha2-128s" : "0xb8f14bb6630512c51d227c12a04ce7b316bfc0d255f5a5d1dec3e1ce5f5cc92927070079430990b4364200dc6d389fde89c78649e21d8fd3a17dd2de7444e77ac3e8c70eda15f2247300fd8e37e1e3c2afcc3e8dd674823106b4297ecedc924ca948a9f80afd7ca1bb85dc0e60e1ccd5d97eb21062b2fabfe94827b4ce5f0e396e5a891fbfc61bb827cd305012515d0a182f163c1a5ee3827aff289ec526cdafd2874c457947e8a6c8332ee7172197cde7388303992be248892e727b559c0d74a2c65d46b6686a48f0b814bbf031d1bde17f55b888e7cbaa7fd6dcf428b13ca43f77d80c3804bd2840e5768c2aa17f6dc773b71f83eb7803fd9e1f1a2e3e158f7e823e9667cebe136d333316fc670442a8c662930a00f72dd2dbda9b19c3dcfdd09c60ba55d9ffb5d5b3384d719d153566bc0b6da89d8dd869fb8c4113258014cd48a67a3591d37f9ba767ad70a554ec98bb59275ce163364915051411db73833a88cab0d3fdb7c491b8580baca2bc44a7bcfc3a51c28ae0a1fc12bb53b2b948c571397a348e664522ea749890d1c7ea7e9561596a3e930bca68377e4d4c0e0301472c8017c1fd5702cd6dd4c3f5881ec4cafb98967a57837c3869720268b61f37836d0c9c5ddac850a835318b17758a6f97df4d4966d516ef100b7e61271c45aeb89242ac7d2b8ee45a08f4081727d54cc08ec0f8af9e16bdf6f6d6797b9f5fcff9686f15efc4e8e34b363d562dba239908a3992b3548566a30cf04c424383b5bea0a5011ac620ee384f6363fca87daa30fa88763146bcfe0a160c071d79dd8de0b11e034fddc032e522b7ee47f318cc6f3f2b6c9b6efa0aaa9b9a9c1243750ea31ac01f087d5f4f5fb97b8296b0953a606c49025f5bedba6773804b15fb3638e72ffffe38ac20486e18eb21059f419b0af9071be12e309a953ac82c0a5a620a7b5c850027b39cdeb5d728522a15c1557e4ebc3f4f09914b3a99e291a814504ff7171c23eb825d2df1bad1ff29144f8a3babcc882258e8a6060272e95c4393fed0ad86698554515e77340ae806746ed859ff9730cd718c767e320ef54fae5e0cb8ba331bdb920229d6047a6db8bad147b75d376c3e72e06fbc6a542f51a312ec831c704099b2eb0f801b68631b464ef484eee077cb7fd9ea951a0307e08dc5fb4ed5a6e62048b010ede39efc5462ccedef2a4c61ffdff63fb3aae19b28ca48593532f051c716835a61f2fbbd5c25883f4a85b48d81658b6d7cc4227f90a81e961c5fd8a388c9efb78da1c9bc50d53a41d2d336232e84e3eb3444389caa3457ef9e3560c25033ed45242d0b4bed69fda4a4f1695830c843e63147b6c2d3f9bc2608b0671e59d827dc1e3876e5fc6075bcdf95223f73dfd11d64399333f7bebdda7f5c2838c072f7baf753a36a1ae8987773fd0ae5acec41d7666c84c1125190f432a4d82ad9b78e22d6536a8135d80a3d1715d17a673033d37104857278a75c2cbcbfe0159343dad8e98e42874e2b001bdb469c9faf79759c4cb3e3f2ccaa16bb29d3e4dc81627441d07469dfb9f545ed83d9c20ce586370be092f3a90b18f30866336c6db9d53e2e0fe1f98c655f1961997e41c25089a518f05270ce06cc115b6c2e9c04f6ba9bf7ce3abfedfada8580ef89f2fea98e8a19c58a0f3ffb89dadb05dbdf05c44b79ad5e1d259d5aa6086cb295341dc40ff800b460a5ac602a687d6feaf66393dd2be22264498509c9d39033aaa22eb248780a3661ecf0a05cb6629ea3d91eb0f68465485e8fa3fad3fc4315a118e4eb2ebc6e9b07284697cacf0257edf67c20b7b0311d3094f4647da567385a508addc9b25a66db1f1544dbced87886946989682b2f2db1363dc635e4cc3c67ad83bd311437d22d8f60a2cb7833c952bab293c9e20ec2b44e1f1f42a797421eecb2e9e9f5e47105b9e7f5d7bd796c360ea39dab45ad701eef0a76b7773c55e7af7909d456c213b0db14f985d0f73652bdf39a6402cee104a168749466e477d8a399469992d65656b607fffbdf73ca1bf4976d3a0c0c64cf5d260d6d3e0198f0b86c451b9ff5840968a2b60a8ec286c81fb55741d7bc9714177c9a77219d3a39dc1d6d7adecb7f8f85af366ed653cd81408b509d0f56b5dccdcd1d982d115754364ca3f14a6f100c54ed8ebfce6b0dc3de4435507acb0c4d974ae3f2453867a70d5ba078a17db34844ea410af4f842dd4a9879a7706b18ddbf94c7b43ba137f7f9b8b3924b4d917f8e0262ad10d083c4dd3b99b70560377ad31784a587cf0ea1f99d6faf0f04a909179f3f93c96aaeae014ea1e74d9d7ccd0eb5ab466a6caf8ed0fae75cba902ae05244e0dde35b8c0bdbb3354ac60875c454ab11f49e47e2d180db319a113a5869bad3ef4580bc7402b0d6bac10a7a4e81403634fd1cd272076074e714b14a6efefc902126df6091330ae387e161789198680b0258c341b6f3ec0b09c7674e9ae8f88699fb7b2f88fdf2461e11ad483ee11fe4e3ddd48ede0ef0a1e54a318ae12473993a8456dbbe8b5ded40232b8d2474a90424281830da7bb36091ebcf591947b04739846d8a600946c2b892e2bf3353b09b08e3a141f33f6ef83d022666d380da43991d3eae4e62dd3f9432678e8be1cd4b9569fa2fa84e95195449716423688aa920e2ba1cd41cd5538907ebdf3ff15df27900ba7ee09f3e9194e1d8cdc0703d6f38b2b887a89b10787986013f688f9a355c6a362f4797576ba022e4f1d1d74e2e31dd98f1b617b99516c944bfa5bb474857fe74a09976cc29c71a7f5b6fa529f3e0c00c33c2f0700064fd507461535a35c0dbc5b69d413fd6ae9af49ccc5d02d7abac88ef02bbd40475595176fa3b68d602469a89afc03359b032fc1f0ae255d623fbf9525bfa36ef98467d5eb2f80cf7c72a04b557e40995471c7adb8701409830b232693bf2fe905ef8b1a32c4b8fe3300bfc5654acfcde685547d5c1b0c213294235b31417da91464619822f3535c93549ab4649a59dc3620e7f4a3327c0e421c5d1a28a2b4c3ba8ab02950631ed54690cee35bc4147aaa8477cae505a1d1757d85251bda5fc91cf65772e1b543bccee1a2cd0c26cd33015533a0e72c815be8634efbb50ceb0ec3c8a3bc6c84638ae371809ab87eec54b934343ee9ed1bebca488d9399a1e347b1647d108652243cf2531a4685c282e0b9e526688a3ae1d10060a78467e6804b705c143d073af664cb72ce657a7d210240011d539cb3144e9411758a211238a872eb4be615d4813b64b8df446d2741db7c9f0af2cc4dc83c0febc41adb5d8413b7ce54ed564e899c0a5a4abcd1cb44c84505915afaaf93751b11bc8e96610216f71cac8d3c9ddb7282f0f864400bdee42c3e5645aea1aa5649485435ffec9e43d43e4341d967c9a89eaaea9cca12e2089f3de222e1a5034baa32372582023b5564909fbb67acfd2a40d5ba40de2d7a31cddac717f5702648c0346e197f99598dc83edda7ad335f9e711a0835c75d4c32e3305e4db9dfafe171181551a8dd5bff89f8a9fb819eca7a171d1be47fbea0e2838a1f1d01f4e68c3d0045da0ed7d3689c17319ef5f5d178e6cf1628402c40d2095c91f7bfe6b837d8f86c5b2585653beb650fc29096f13617ce6d36fd6107ac83c7d7f5a8639e519b161581dd58018ace297bddc3421d358be70179b14bdff66f229a50a329bc30b054a95d0f43e7914a9137055f4dda000357fdb5e2afa3d61b9816c03697168cc022f0418ee5ad7aa71617103fe17e7f47ecf7ef9bf779f157eea74c3caf3821791ab628fe8cba64c12d3226877c48b746d725c46b0ccf5a18f869e6680f1e5ef3c5e7fc2a18915dfd8bc12676ab94ff4401ed22133ac1e1ba0c0352a30156bd80b63eed4a7fe9c948921e1a9843127f1191751312180b75f06e33694853a05a24ee30cae0b02a0be49db16f6f06630ced9b5e57cad548dcff70b1620ffb17e8bf8c247a962d6b2a6fbd4fb3c89e3aa4381e15b92f7245ea700e76ba99678f4b0c998ac90bf3e4b9ba5b52140e15e4b5a38e25462c1b61953cc2068d0b9ebe014db6b8fbdb2fc05751667659f40ba1cafcc2055c364116a058e286f084c2bb73096d46f6736de541b750ad437c27a92ea51baf3478837e99faee73f2a2745918f81547c45f2b7083befc6387a73366c175d2be22314a1fa73f11571395c7fe9df062740c58b56b4982240c63b8a0d5886a3ddbf6ffcbd705d3bf3713a0e1b74497b8c1f34e204ad81b63f27cfa5215d275597599f60d02bbf6cbb229088b56c96d73d09fb3c36fb3f05f4266221984fe8559619da67bb7314ca66405cef4bd3086940c4a7346243776a6fa128cd9b6181d8f584f482c502fce3339f87e4fc5e3593b7a0a64c19fe76c51a29ef776e478ecdd5e093b2aad0ab3cff0baf73f4e09d63e9ccfd4aeaaff147ddf2e9f1e3e6cb3bc9757c57072a1a8076e179e50b0a03dc94de86fbb99f0e92338f26b6ed7c863830f325d3606189b80c8df5a763f422f26436f753168b53bce965c562c2554081cb4eb42d48daf8573206f818ae66d62bafd151e9784d6a9304996b4b82cef081af9b106b42ca4b6b0b2401dc21d8875f9801591234dec266f1f218959af60351178049b487b2784183349e0a7ab361f575fd0237d9f483590a23401f9085b111ac3d740ff4c3eae0b7dca3d149243e3b1fbabdc7431a579652d522bef7023e1c6579d2f6852f1acb9b7f20e3956af8dfbf14617f14981f40b1b2430920be14284dd5f2771f73091adaf9179b8396c6ad2a3579befa1e323177fa2598a3ef80ff5785dc2677f87e9299c6bb16ef2b2080e91f6fcf1b9189e256985e631a05cbfb6427eac995e683f494751f7ae888bb0dfd23aad7fbe942b8100d4daf62b6b8e4d647c818ee7edf0d4d64293edc3b7b6e08a8b9b71a7c38f55ca76593d35770185637fb473da423069de005363ec25235ce816f4df3070ff567f919f47dc4fcf57c168032ef8d7e3fdc5a6a1dace2513fc24f0829e8e4b964d37333febb1eeaa7b81aafe30d16fe64b6ac037ddec2dd9b372c657120df4372504cd14be89d3719c5aa6d545030423fc50e277eaa401e8bb02d70b6614e9768a7e42ba9b35af8f9e3f7dcf175609f7b91a16fdcd65a151c0e85d92dc8a06cddd1ff77d150ccb62c612c90abdad156ced839e837c79b79f456156a28c45f3287cb86a9ca664a13313332a1ed9ef4b3a3df864eda7bd55a6d8705567bd8d1d732f65a324aa6c77f6dd82517d5274343a4e16fc8f41f5a3809e9f2cdec445b88309c9d1de684032a10f8944157a3dc3d4d8d59721f4f9cc0b0e1e7a97b7b066523f7498e0902ac5aa462d9bd096e13c14407bef96b59297391032a4aef8c543cc8b60217ddd5a5d815c4ea1e21625b52e2323b42b4851b0bbc461abad9b71805e8b1b2a16c811be69140d3a6d32d7aa9d5321adb57570fc2e62618cac60a4cce2b011a4c8ddd4dd521b6864c7c4562d8270dbbceec91bf1cd7be926d6b66bf370839bbb22856d1f0c7b2b7119ecea6278793186c50b045d09a1aae7c5bd2ec54df1087cbd1d8094293392605321bd39ffdbbe510f0e8760bd35074c4b0453604ca1f5bee056175ae7943183212ad527e125d2ae113d83c5a4ca1e63e8d89ba07ce8fac8257fe1c603031a1fe2e41bf922d7ffa0a610e0b91eb8c3147262fd228a4ab54fb520b49c91ca268d3954029be8677229af3ed232628e7d3a752e66c2171d1746b7e31d2dc8d1781af454822f36b3ff40f7683fcddc5aec46b13890a6c7c9531f30eeca923f198f4b57112a94e34673c88c70bcf80ee115de27ef5268a753c6f827e71254b5bea2a4f27c8e0e2d0c3f72d051558700196e80abbdf452bd70116c24f635d1850f9466282ae761f1a38a8a0fb5a02a9e1b99df55616f0a7c031fc34f190dfe5cdd4f2442d16ccb49187823fa90f3f87dc0966c4cebbb7472d8184e37522acb165f5d3b508f6a62623def48edddeff361d5ff37fdfddb2b324c4f545bfd5cb98d258edee6ee6170bd41135ddf4c9e358433330a5b590b25fbb276a2284b2df18550270b32b65d9b483fc42e9610537f27715e9f451bccb73e1ce017aaa39b65db4e86c86a50d0379398e57e0c34fa64f73acc0d2b4e953a89ca2f8c01b10135c2af5c234dfaa17ef97941aacb7cce96cd05fb246b76f15275e4d2a8545e52726a48f269d1a558aa12588cc78919a5edf6c0e9e576ed58c92b67d00e4197905d74dbdb3700fbde85d26de20cc652581608ce1d1084b507842a0373fd8830c8d3f68dabe93fb19e3189e486840715f92ae4d916a9ff3424b45ded24780b31fb7f76d506339d9f9a545fe0547c675bde44a3b490bd3b52e3b30842624ab5e8986161be4ef9da785bf537954d3c716da5597a859ef7adb40fd8030611d3ac6581e424ff636aff72f4dcd9f315744a3dae6cd386b2f9945140071a5a49f05e8f979115678eea7d6d884a92e4f14ff94dc102355c3aaa93e02723a92417ff49fe8cdbefee7e6c5e952ad240fa7eab4c7941f6ae8d2a1086e1f2ca73eb8ca5fbe3588ae51bdaf18646ed04bd185a19bdad69394ac15d130297c0fce9d8fce8ea2729dde117facb274f9865ffb4f2c7248102dbd96767483cb7fb764fe667d484a3143db514f08577cad8bcf695b0d953e2a3c8710d8979952929d59c8b8ae62ff678815130e68c85d4714e832733da40b933b7133725a40a12534753eb4877c65fe4c75542f28d6f9e805789995adaaff6fce3929e6027338281c6d0c33aac092fe0eb1797dcd953fc1f815df794249dad7b28407c50371a8c81625f6e7e08ed59a98758a9859c41f7436f937885ad35102b0eea85f3dc4bb9a6260f4e091ed983b1009275d43e4960f9422dddeddd09e9990d545cb67dc3f1061238dffec3ce01376259262b4c32c6173a6f1e239f4502cfb0900bbb7e3b4883ca3c64c8ba91cfd80b2bec6aea25b01124ae11a56ab3e4d448038795ff62e9d5ea5cfdb99c5901a8b8f8731c772690dd964cda343bfd020e920b32910a68b433ddd01d117a833242fd695a54f33fce28b506d931adba499373b0a6182e54323f032f1e7b8bad58dabcffdd1cae831c70e87b2c6fee3494dedaacccfdc93fa23ee1a4273f16adbbbcc21f5d02d8645951b93287732cbca4c61a0d0549345160537501b8c0dfc97128035875e73db7eebec24813d03d11cbcc089929b0f6e2440a26d90cffb6295e8fccf65b4d676abb8ff66709913775e611bc843302a475488c9a9310c0c8885b78d5db5cbb1a919683cfd9bd010cf2f1206ab327122ac87d8e2899cc1ac684e72c91f2d36c7bcc3491b768aac86e92aeb106d22b3e85112a2a871bb8c9d0a0dd15c89d113910f8babf15f27a13b10200ec7078d362773f17286228b0d5a58d6654b0fb4f60c81ee581e507f17a044e6bcad4bb6ddc66bdde7d311810d79ac031086d7b0c334cd3a8a496591aeda23b2c0097cefdb6894b352395dfc79b74a6e4d086656b0cd9c95a48640cc8b3d188189ec0b98c8618b0def4b0175f11369cb2f107e89c4a67a75396cfcbe899334a5d5df5927fef2eb8bd836a27a2834a7ab94813d30fa8431da3178da4ae56caaeeee66cf545537ea260ea6af56d4ba048076ace08ff2a446080a6b688a916a13b43b933e506ad187b1f829a1d54ae261651563874cae19c490004205765b43c3cca4cd8a309fb1bfd7520bcc07794cf7c03d9b1d1ae0cf646534f5a97106925ee96dcb7fc1f74e62c01d382fde19fe027a4b9b7627c08e690abe3ab076f184210acbb4229d483f7471ad551eb614c35e019a8a894b5f92f5371fd6c457f135ae8377c5781a8f3a6dadd2c00697bd8399b6f168dd64b2d2d66d5aebae90fa5f904af9f950f450d8be919ae3f02cb5c0be9687560cfab2d2161db61e978ef46304de248383dc3a99e30573bb66f873ef1e54f523ff8ff79e8c05e7f8143cebd1bdd9d2186ebdbd3b66a0a3dee79475cda2890720ac5bc33f8cd3e817d82bd7c52c34d491e1e9d1d307eec17c0c7679af3626e7b96bbe6ba2550f44de7d1d88b3e4c220b8f185b459f1f882a97248cdfc3d42209ff44806837750b3dd21ac5891254f6c7f6938aef3caca6c55b633770772c2c06734f84612a59aa8cfd4f347267e631658cfc4ff89cea84550bd43699c1d8840655f39e3449ea0d2abba1d81196413302719bc9b39cea85cb7db6ab7f00683842cc480503004c1c819ab80e121d9d21f46f362614a5f2cf80cb2c8d3fda82447cd0155fd7e0ec7589a6df2e6614671071f0f956143c762d51172da46e9f61e588fbf74cb3ceb74bf2ce4ec4ae26a28245f98ae91f09cae77c4660d6dabe7cad33ac506db3000d742f683e08bbd0a7cb9eec72a1a976546ec926b9faba5084e00d66475a514a73f01fbe1e79c0ee0066f4b724e4977f3c1518d28ddc918c573693e9b3fb69b426df0640c5ee42cd5533655f9a82c6843516298d05cd970f34dafa886995545c37b3b939e0dfa3647fb3f330bbd3e69307be3d469a99c24382acdcac76c6cb71decb4b7b11cb5f2e63d112767a7d6467c51f1c0c27900803180337f463e64f507ce245f606f8c1f1df836c7fd02502bd3127424804c69f1d066ec3acd9c4374e857c4607b711f532867cef2c1c8a7d7051a440eb7a8507500d86f11567e2fc812a27e63e5599059af1ee90444497f69add7862b93ea050f100e48df7a578d55b6d6321e70ef7a7625ed89054ab010850912088fdc21551b89397c35ab582aed6c215e00d398a857090e2f7cac21c7b51f34054a45f36157edc603b5d6e76ce20f2dfd2c20158943efd2349560666ca38505cc6af776e0720af2d5f6a7d98f385854700fc0c749dafb597e94d7ac54aedf34840ea778e8873d6f1fd7f53de7c06327d08d34a03b38315efd8eb52683ec1f9abbe2bcf096fa4f379f41e09b8bc67ae4685e68ce456465b38892a238b18358714fee41da0aac8dd729e2c3f17488470648df81040272b2e927e896a4eaf6a11c457938421288ff074da8db60d37c6d022e86952341f2b8d262cba0c5a6efb51925517a8c817a152499ae7ee56d36df86253e6b2d93079c89fc922014b03da3941509e979ff8dede44165ca4cb698924fd12bcb02a35deaad608ff3358d455a49e12e944dbb11ac7e9571476bfa856f3bcf90ca9bac6d57d5c1755104b348d2924ba9b14e9ffb750cafb6edeca6dfb79d73b9839092032035ea700d81f19d035e38bdde754a5098dae1c163f9c473b0681858004ab9d9c2c57282ebd7e57c474b8f7aa091d1048b95e7ef887767f49d2a7f6b410922da142ab8605e735ff6ea9e3f36a29380ec43dd009d98d8c20f4052d81fedfee6cb018b2da59d63b5fc153d5b0948d613415a6b8a2b7338897188582d2930480d897d55bec899723b285dec9abf819ac7e6f39d8c35c484ca13f129fa4b334979bac7715bbf5e52a9926568f359dd3e3e000958b561527bbd52025918ef75228c423da41861396be4f829aa4bb6f94f65e662e6ac91e828d721b741d7333a8e3050f136a463af537ee97af4b42456d65e1e2324f72267c07acb88c91d0cd602ef765f858f69fcd44ddc73dc7c5f8825f3fe04affee769f3ab5486232e35df8fdb75db79721906907ffad83c57a364ab85d93bc03ace8998ede749d88985ae41cef163a3d00f568d43115992362c581745f723a2955ed925cfc7c83c5b5188812fa2dc016dc21844f923b2362afa5ac5f2a6c9355b2eaf724606333f152a01c330ed88f7028e716043330a280c5ee458f2032c8163f5548428ce4c529d487a16ca0e58cbf41dc4dc802cc5ea7fad6a50de0c0f2c2be49c3dd2806911ab1322a30acd4fd8937b8930069fc1a6de86f9ef90f407b2563594adad581b49ad1d19b30ad13efb0ddd8e6f26dc43a36ff8d14d1c99b073f5f1ce8923d3100bb04488b86cd4e89f7b9f5b9cbbb3f86ee03b498ae255e09eeaaba3e4e4d68f1ee4d50f699e460a922e17ea8f0ceef9794e944f128efe835f281a7662f959054aa994afa3982f7a310f46f53d5ffc07884aa91bbdcb3f3779ebdd7f90801e96222f56df39ed9c2bff5d4a11be1da7482835e494b0856ea7c695cc1b53acf3b2e2d1846fff50bf55be65e16548c4fc436f20c50c119ca8eba4cdeda8c7e4d33734a0355586629ca5a7c3591ea4b15428a81b6d91529485004cbbf60e75208579ac354dc705edc7bccb32f23030e733d3f549fbb841329a01f5c5d263ce635a57aa9c69432e5213b155a07c34fe19cee737cb993fdc82ff38eafbeb734f04f58d367e34df15dd6044591983b9b45d4ffd87e2a6b478c7d1e86b4b974991b930370d5eaf5edbb53c3dcda643fb992b5fb0725a8aaf8a9e7c4012311f197179cf1293884e2356fc5b624cd46358d3c7bed1fed6b0305114cd11675aa49c1b9e6569817d34fd60c1105833d78dd00117284cd1722074a60655dfc428072b0d2eb881b93d6c367952a4bd59eb902032cfbf9189bf65f7bff592032c77d61dbf778986b491e297ad0da5b367c8a10c9071b8d509b246393fe04a290b3e2291f04eb750285674ae3e9c7b76a01b679787a4006836dcee956185d3b0ce16c4567fab862d3634b93079305008e2f99ed425489bcf5447699b7a7212fe2196d3999b39191e750fda742c6ffb5509e3806f38edccacbb8bc73c96cd46f0f400c4012f1205813d69a48bbd1f55724c7de917ab56d4188716b96653ebe4fd1b6d5d252f5599f9c53a4683ae60c8c31b86982f32bf73401a328891804daab93a155140fdd41ec87e392c8397c9ecbc48f26acee4e3cc279cfd67d75b5e0b6484274484c18f72c2532b4064cdcc309df796c802c17480428c3b5a5467b38aabce03de2a266c8a22d3b0158beb913d50615a1002fcbaf91edc529b0cd38f35138bd71dcfef1b6b90adb4e68a594de40199724c158db9c85ca78ce3a19378ee90dac98b23e1515324fe18472a4ca93b004295b7abd3c146109da707f5ef37886fe1a8966ff1e96375fd64536eece72ae3433a697492955cb182331ce72e8f1804efee93b1929338f" ++ }, ++ "ecdsa" : { ++ "addr" : "0x5e13d369c8adbd8079272b624343ee1edfa4a560", ++ "claim" : "0x197e55da82eb1daa23a5478ed230c6d0452d3c1920df15e10a8d37a7430a7f2b69eb474bfe0c44a6e4a55db9d5a0e0b74549c044ae22778ce30f47a9fd1eba4100" ++ } ++ } ++ }, ++ "registryHash" : "0xe17a14762fb5a1d59a9b5cdf2a25414190c81bf697435e751a50540fa74ca521", ++ "root" : "0xb78edcaefeec9a1285445fc4fe230e0fe656f360ea839d9c7e31396543f99bdd", ++ "rowHashes" : [ "0x6134be442a48790413f81ba76b4f258529b161988e4da2c03977b1450e16129e", "0x5f62516dee6156d0814cc7ce084b8902d3acef529b2a68f7217f7d61e576d28b", "0x43231e1c19e422e6c2caceaf1a30094e26f2e1cf19d572e94a4791b332928570" ], ++ "merkleProofs" : { ++ "0" : [ "0x5f62516dee6156d0814cc7ce084b8902d3acef529b2a68f7217f7d61e576d28b", "0x1b7dabd6159a5070e03f823f438a70cb6057b20a9585848c2d6841bb1f2f301c" ], ++ "1" : [ "0x6134be442a48790413f81ba76b4f258529b161988e4da2c03977b1450e16129e", "0x1b7dabd6159a5070e03f823f438a70cb6057b20a9585848c2d6841bb1f2f301c" ], ++ "2" : [ "0x43231e1c19e422e6c2caceaf1a30094e26f2e1cf19d572e94a4791b332928570", "0x68df066c46127a7540204925b00d14bb19bacb4ce19d65b8d6d0504337f8cb22" ] ++ }, ++ "ids" : [ "0xaaddb4dde09de5718a906d83be7db3d58e0ae32a", "0x690a7fd66157e5b777256ea5214f634f61b3a72d", "0xa5ea2fcff9e3cf29d0c6f5f147b67ff24aec3bd4" ] ++} +diff --git a/consensus/common/src/test/resources/aere/registry-v3/ok-epoch-b-rotation.json b/consensus/common/src/test/resources/aere/registry-v3/ok-epoch-b-rotation.json +new file mode 100644 +index 0000000000..95d2a953f2 +--- /dev/null ++++ b/consensus/common/src/test/resources/aere/registry-v3/ok-epoch-b-rotation.json +@@ -0,0 +1,60 @@ ++{ ++ "description" : "epoch B after A: index 1 rotates both keys under its id, index 0 unchanged (moved), a new id joins", ++ "chainId" : 28001, ++ "requiredSchemes" : [ "falcon-512", "slh-dsa-sha2-128s" ], ++ "ecdsaRequired" : false, ++ "previous" : "ok-epoch-a", ++ "expect" : "ok", ++ "manifest" : { ++ "formatVersion" : 3, ++ "chainId" : 28001, ++ "bindHeight" : 2000, ++ "count" : 3, ++ "0" : { ++ "id" : "0xa5ea2fcff9e3cf29d0c6f5f147b67ff24aec3bd4", ++ "keys" : { ++ "falcon-512" : "0x099202fa37d5e165b88428d963d2a224b8fc82ac0e4b3f6a02376f18218d1aa7d0e910e71586aeeaaddc2a557124d6ab4f9a44b9cad02166413cbeb14b364e13956ea326900eb2900802644167639045d76bbc4e051654cff404dccea94402141ad9fd992cef7a8fa6478b3e6f8912886e9edd1b34c29385b7e964f360e0fb1600787934486f461c95d577d2bc74c4dfeb969b4798565ce0225ad27aac052290a44f844ae233e082c97e4498a31117ac9d02f3605c856e2dde6f611812161f89cb3a54dc936ca1e740a6c659405ed586a9a963b11c89b01746325e39e645c72b0c7e4491b36a17d43ffe38d88c601a5976f5a9636c964a012bfbce5f9b371e7c3b38580d81c6e12b8e8f2aac219f96245d35b4f4afa6c94015b055703b8c4dabaea4ce2577482f5b34fa49e56a912dd58d74580b1f94e1d2056594ea64bcdb696b0baeb33c86b6544761a3ead9ba9888cb1ad51f7027ee52b21e46c5eeaf3f77bc0af7efdc87acbddda7dca00b6acc665002c26447e5b0e0bb5ba261717c68dea7f1576462776954d7249c2fd0886f615ad50d53960ca02d581a4a25517c050ed467c7a820bce6250a9ba2e44fd67fb21bac843bb134c95360dc1c50d54b7280a94440d018181a9d6374bc64d782c84471b47287d8ea748c36cb83cffe053cb89a9e4ae71df497871c2a728ef210903e5b7f39550d0331e15637be7e28b3a2fc05b0a9b0c5a06f9fe81263c3a94403d6c288a561288ebaf788bfe271a578a1a795a85e9d452b61ac204b297090617286922376bf0a8d67dd35fd705b81260b7aad30132b965e39bc3cd64d154c4175951704873992a814814dae5c6bc1e89a83dd91144cd1b88f6ce449900058afdc53bb44bcab63d30cbd6df115a5ee8f5380a127a160e922bebf7b408de82514b2e2550a0931e065565e8dfc389d454823a55b03e5c989b09e3791f656794e8379b7b4b1617aaa9770366d63a657f71ff40c69b1d5da518ef1e2aa42366cfa38e448563f6c2db5e3089bad5520ec26105fc885993630c10db357883f588a5a384cd6de688e1bc3b1200f87ed66ba3d4a4b671b2a500a0436e0955904030d76577aadddb8c1ed21b027f198c072f654c3abb086e7f185980f49d0e109c1a82741809f8afd15ee56a887b392c5b172ba659144a7e99e25ba19792d2a3c0ccb481822839c8c70c65c0943a2994ec9f6085b7ac64ce2b35489a72dd6693d25f2329264e063db26ad4495e3ad00f12df8cf914fd846", ++ "slh-dsa-sha2-128s" : "0x686b5dae4aecd5618b95c3b2a5792888513ba49dd366ac39b7431ef403e04963" ++ }, ++ "pop" : { ++ "falcon-512" : "0x391de378d9ee4e1d810e6ce145b1819f1b73dab7f6dc2468fa65d1ddc8e2a7e6fd8f185f8945700a938cc0c5afd87bda48c1b8167c3e6607ac864bb2b194a368c33cf8ab6a5eebb9a704d4160b068184264c2e59c4f82b9b4eaa9197c3ba5289c429e0f4c548769279daade1286d354212b1ba2ea4818c974c17770dbb59b65b3b9f891c826721f51a7ce14f94e2ef4cab868cf852ed9bfb17cd33ebdc4d688d6ba12c74aed2c8104d117574642af25e9bc91ba3fdabfdf1ed13c6e59fa1a0a4388925d2254195c666a6c235174a73125790bbdbed463617757fcc17cfd32da7c7f89e755f051aaee186665d9de393a82508d15f88db0271495c959bda6651a81a04dfc2103364f95f5464effde48f3b7ea80af9c1bbee99c9d39b0627984f09ccc6a4c888d121ca34e56760b1c3178e48607325676c484f4d666681f0d2454f7fdc59cca37136c5c06e746987e6a116728f8b0ae1ae9a32efdfcc956fefa55577ac670bc3d66016391bbb833d97f91d3a78696370a6f05efbd77cd50d4697c3df5699277eb1cafc1883776d9ecc72a763e5b65dbdd184efb9696cf58360e73f2d4db5e8bc6ad65bbbe7a8a994f5073fb4b12ad9b5196c450e27a53d8ca231f670966a238a6223b47d90990b1f6796f93eae971d4939d99dfea29d4ba2e3feffb97c0b27d6b6d2ee10751e75c658b44ee71abe9230f74a0d7f232329b165f5b2a3e584dfedaafa9ab477c0c516b6553c58797421f8d1e9236f992b61963c108752b1c43278a9b910926b396292fba67211e9a16b88aa9bab7b6b6db29f30ab5b7ef1568d46a010e8a27144a5e958022be5cf6bf4305f14e10781323acca3bb1d6b567d3fe5f652661dfc54d71ed9e3969289c29bff0c8972899993505cde2fca11c821d9280abfd5c20d4fb53380", ++ "slh-dsa-sha2-128s" : "0xee44a0de25b75a42e32080200c89b82e2f89551d44da272720c816fb144aa42ca29cc7a0045d97c82676d36286a9f1bf4d5b9e44b6855d90f25e03e3370cccc7665f3c7fdeb6f9565b76745a7652f70b7cb18989582559b81160fa32c7db7915f14c657ca37224955d174cc69de41774e4ac576f362306f3383733b322f8b333d9d0dee44d80e36a86491bfb7441a3c66809bc600399ac9788b4d7796604d4ec423c40dc1a6fb2b02db9a0d35072cb5aa617ef769006c504052596186ac0d504561c815617067f669b29757aed1de7a03c9c0410fb8b040dac268aa95232533eef1f69cc0100b33c9726d55af73b5d608b501b0470c4e9340b68251fc645bca481dc2d375de626580faa7b7faba8f8a596f795481cac23240854839a1100cd92a6410291ccd40cfdf1f70981c568b32904a0ad649de41b32299dd5a8bf50c35e5dbbd474c258946881b49e335e01c72ab6654741e657bcc5109fbda7297999cb4b272302739ee07cff0d1c9ef454a5dc5403cb7c170337336f94d56f6ccf563af44bcc8382de301720076a7ac1edc1ad95dba129760d7e9cd4df609bb8f7b389e7ab1e85e1b54fa5e3f2163afd7e24c5e5eb61a9e8e79dccefaed30f5fae83bdbd8a1673b36ce894891720b476652a26401e7890af9199bfc74fd0aeb6622fed8e488b8151a6c51a11bd808702f945ae9f9a016bdd94f45279d4765bb376df7fed5506b52b74c867c087c3386f74b130cacd7bcb4e832b697b50c796fa8fe4881c3f994820799417885af464f4f1a85989e5e3b54c3bd878a7ab054bd08c1ad850c96f3c0105380323908fdc94771609b10e489a8445f751f75a9b617cb1aec4460be2b53920e52f7d85096065fecbc6f19daae458f657dfc894758f3d9a6519fb4276e16b38aaeebcefba89a7686546901c57a29b95266d7ab87155a854ba9b269ac94a279e9c4bb38e6a4928cf6fdc3984b4363cc44e0e3cd7a7edf08388b9ecd5a04c55ac26b98f98cda79cd3f402caba28360899cca559be68d7a825022f9010e65f9a6564fcd0ec1cc4c0f4029086c90288fa83656cf2ca2cf30d5c423342cd15b9197905e9ab30a9d147aa2599abae71070e40058f0787ae39f39d6e5c1a8184b2cb3b1e6e45c40c61d46af8490cc9af6422a439f16adfe93a3cbe88f63df5eb8fcde9ea111ca96ea7be416d030500f2c7cf967dcaa4d3ed76a613b2bcc034ed3aa84f35556e7a65a8798825b576236798318034204f041dc59a9f9c407d34c2ca2d77470700ed6442cea5282ee99ceb71c6bf074423dc0785a39b89b062f89231af868812777536d0b144212d5b4b6fc7b87ea04fcd6f94438704f985b746a13dd519c57260f87150db4dc483b664944b9e805197df797be099940fed468b1e214ae99a68e99c6b5cf3d30fdbb1b3cc009ea58958eb4c4a7b7bad6b34fcea2a87eeafda01dca5223458affe54422ca70ef541ca8437171943d5bcdb70eca8de02b93098653160cae52f4d72fe5a6a7ad51c6465388f0362e6e72a3c96b9cad2248e8d9a2cdf89747444c7e51e2f89eb19daac76da37180e4133e0dcab15fc72c7bb90c1024d03eb2e630fc6d2537a101961b388e32ca5019a626b5a23914b06e7822905a5e3c21369b69fa63fc9f43cf7ecb6749c668c7a940b82f88c71802ce6e3c68b5c10c9249ba356bb3bb0539b581a8bd6ca141e5dc2b5932251746c1fc1c3da475581f3e3717f5d905f5ff3c83f1523f57cb750dabae0404beb55aba1105b995268906131835718cd43240bae9aecb30c794a8b186436cf752179b1de65b2a87917147612e3c95288a3e816238b3fccccae1da8041b4f784ddcb3d37ef3f019ef997bd8a4e172d397106a5adebb166c5f565016bb1c5f7f1a0cbb5bb22cd642fa4390ea640c04a968fb5a49ef929df1cafbb69c124ea58b31bf066be388d7b6d4c52409581da785d6447fd72b54949e4c1ad08fa64b520f2b8df83bbfa417952b87fbf802652a65df0d388ea32dfcab3227f645b6b28b66087819b4339ad171a48760e2bf90f1a01184389e23e7df583eab7c2dce385bb7a4d60ae5573966f916bb84aaec6cafe710f839b103532f9a7a556bfa116a05480386ddefa2858ac7ebdb58664a0e633a53e1685d71d5aad11f5eeb3d9ae30ab120fb88f96f383bb86917b72e02768f071ffca7e3fc2ac79846a36f6bd72c58aff03f9e87fdbeb65c8ce5976255227778cfa40ce0eee943b66a382e172abc814ebbcb0bf49efa75f87ef8621d227224b7be51b73a928c23a8937570e1a046bf1fd4c6993a9c14e552915953776265f78882ac8302f70900f9d612d2e7b7dad88cdedcdce7e615baf89ef249d6d535f92a2ec90a7435785f4d0c7a75812b875ec22e638f4af1705cc362ecf52c67900c888d068dc6f72a161013c30dcaa49cbf25c56e8937aa4897451061dcc7579ca99a25348e76ff121983444553419e820a3d1a41744f4227dca054c454a6497e0762155e2a06d17acb44ea55f54e4d6d2e1631a63d9494cf69c38ba66deb9d95c0ee01950dff8e6a5d1c46fececc7027997b8ec626f8405ae99ac20600898fd7fc422e6cd3f774b4009f371ce38e1f089ec93ec0a48d6bfb90ee79c3bcff321eeea33a44022ab910458984b75c5089cec0d8beec20c4c39311b991154fac7c0461b7d667488dc9f0f5497cf66166782e2dfb69a71031fd0251918e4c1243aa4dfb9fc2b6123b4f02f436c0f8737a6663af2b99fbd22c6af539ca9389bfb4e55da2c9ad42521ca6978f71991f53fc8cb227e228a62f3e22d7c3eca8ecee260e55084ad3ace0d6379d5eaf82bf6d3b69c4e74fade4210114d95b41a4c004858119a9a9b178d5a0cc97386bfed0dc6edbac5281c2842951a0c4d7da10207523973c676b8e6887a087c1c2f156970cc6db9cbd3c8ec1c9c1bec41fcbfdb4e8929b67e6c1939bb990ee2cfec3197b4ce824d25a7b4c765945e85ff2b096037adc4dd763b87850fb39aa98f1d395c9353ae3b5b53842a7056c011fb690e856401fc6f67b1c0a5414fc229284e74c230ced260d4fafc5fad153a5154d35c3bf9c559239ce18ca9810a1254a0a6c2960a53d838431447739261dc3b055a0b115914af263ac9fce2b512884620451156c40cd84b7bb2d449aad243a8aea3859412476ddbb5eb73028bfc6b2a942839e363262f94795aa45f6579680997d6acd7a8c8daeace08362fcd420f2f8a96801c002361b942493cc5ae79884eddee989af9832d55319ec033956660c5f11b9fbff9f1410a18c0e9a38e9261bdd13bc392a18a3df97aa33e7f59c125f88d78c86058f3c7e9a9d3b37bdb1e05d90375de0090b418de3ca761560f079a6ddf328e72cd89dcb63c9dd0357ec736782696241e2095aa6107a8bf7bbcde26d5d14533f28ddad7fe1b3f0c181c0e6d55204f6ce79cfc557cfb2d54cd2f33adf17a837243b51705bca7ad8cc452e5340732e678274f9eb532bfea122cfd2959b2499ad25a18db7dc387e976f8b5510821cfff778be799b80505cf38ab1ba6b01561ff81ef17f7735a1ed6a319a7f571daf92afb7490fc17064ccb6a8453ae6e66a2afdcded0c7359461278c49d342df84c43a0607b7327853db675e4c9ca95c52ae013461ca0763d157ac992e219a6683a547c32374631b53138676f50ae0d30588fb25de808e1d9efd5fb9485192428477c2f64fcaa862761c7f5505cc650910224400e2a2db13fbea0b0cc358d163c6d4a8e6296e4c9554078a55f23e60de9bea12ac199cd19b97babe61b2a3b853860b4441ae8dcd85d59695393816c64bfc074e945452080e15bcf6776cbb6b251c13be63932702468679b2bd7e1693a1d910e1b62be91e177a8dec8e4d7642e88e513e3a871ca502854ab0fb7fb8a099d0e0dfd73064012051af337abc78bbbc6fa2dc7169ebfde2d40167048d78f12cb5e7c130a2137a0b26922553f43aefdcdcec55bdbee0fa752a4787ea9d1c75d1bcd9d28135515a0ecfa9735901a0eb89f915d036e21263f90606f65e62f6e5c8237db14d570612611b3ceb4d026ac13f473e5706cd7975c95d49734253757f9c1e6aca9261cd2b95722098c5f7c74daa6c926ea4867ab54e4605a15bbf7ab94348d9b45c31a1fbdc7f420cccce25abb4249cf413008a01e53296318414dfac822cdc0bfc4298273f65cda3fcd61236e255dedd879fbf20b8c4843e27ef413c7a1ce2c714c88358091abccd7fed337a7d4f725ffbf7856ea4694113d605b1ff7b2bdbaf60f7abf7d43eebb1e82f4b6b7f3f8fc23ae27b09f78a7a3b324c7790431c800293e08fed2fa49aafe8f5670d4e6bff4cf6e7924993d6e18ad87699da99a2f2ca9f3c7b44b3b61dcfa5f041f7a6df94131b8e5c04069678541c87872daeb2943902afa6ff4798e45a75659568a02471afde44f8e116fff4eb7c16053a7aa370bcddbf5229c231ef8f2e642c1a88f90e0a309d24a3ab28d3adc176665e522cf5bda0285baca5bf2a0fb4c0fefff3b8ea1522c9ef29342ea57eb4f16d69bcf948d66247ed2f2cc4e567476f736d170c98398ac7c0d158f294ff33ec8d2794ec1929c57ee6d7f46da8e40337a2b380717227ed82eb13a14d129069e98cdd65bc34472fe1a52dfa7e466e559705c53d73d97239e38bbd600aaab107ced36fe7d8ef2387a05d8548a48a684fdf02b984022aeb28e8c5eccd1941ae19d2cb12a31de296b4fd1409266c43118848962e9e59a41054a52bf2f20b09eb4e77cca72df70cdc4d712d5c0313ddf9ec8df2d901145341b3ccfcbed77288ce3e4afc677ad8681c746eca02e7f7538d0108b68a922a21d6a8c2cfd67d8849ff5779de1c00588133309d4158d1738e508a1a2ba3351a46fd3f86339d66b1244bc2788de3fc60144d03c08b0ef08914088f9ce947d2b230ffb9ce176a4bd45b0c8b100e17ec7829eb1ce10b1a514b5e33d4f40792f0a300a4c3ba7a912db8e19cb72ee02ae8ddafc2caf116df905640d0cb65cd0c61d38e0a9741d3dc2b7677e8ec051d329183c954ff9c0c2d8771182d5550a742ba8147ec6571bde519c2f57f10aeb1c8900f8324f017f3b1dad92fb0d19a76de75c0c7cb67d079c8bc0bd7355fa25752d5d00ab00f9ab332aa23aaf8b5cfa4d2723b2020c9e494208c61a76e18c9a583172d6ddf544a327c931e8b908830e46f184998fc0d34ebe767e4f5d06f99804759c7e2b76a8baa302d6950f90194b0cc694a0d351374cd028ba6b0414377a850ca2f209d13cb7daf43d14f606a0e549ce14189023fc7b45e2b095a3f45930a72296eced3e2da24bf237959c0b966bb88a3a9818932b1cd41e8ee002df515ec94901902b2e67545dae53e08810b99dade7b579b847a6570211687a62a56dcb324bb442c4fc22f9d85e54b3f939937daba84c86fcc36c83ca87de70fc7f4afed335e8f9aae027e854e3a022a053c3b22be3617240f1355be9af3f4c8e9481005cbef07bf1380ddc012412c31b221275b56c3ad52cb2f7a9b340526e6128416025d4fe497f2d502070653d36f924420c0844b5560a8728e4a3be8b1ce67a1541c00e97aef9c808bd77af5aa280690d98f5ec218bf5c9d135d85069405b82c221d834b8285402f481b7d51ecdca91c4c2b27c12f486d382e0c14ec23c2bdf33ea8ff693af551fbe55e46bd84f335a68646bd092f914da4954c57201d7e812f4974a553f043ace9c6ce2c609cb4d90dc1ceacd5d610cf4723024538cfedc1bb22c9663ac541f89f97b37d2e1b4d8073ada1596e684b94e74c2c2f0087251f1eaa6789ece436b2940d3285f297cb7482aa9b8c47118a0b1d2031fc311689828b64855bc17306529e4b0a3326438b42698dd4e2e0c2f624aa510a2363583cbac47fbf9974925d81af9534d0ccb41e2b445eb19569d703cd8ace661139fa344a5e097290c233114370831d4710676f7e93889ed533454928333655b06ac5ae67f301f2b7944d769892ed76374a1f3861c8624b2a302df1a2f1a60d41e61379ab3681d8eee152c251e1b7b0806aab2f287338b752918cb989d864e9acaa92944f5194f8eba19a18a025157d2c3988163baf8b7ca9060edc2227ade8e05348d86d18f9eb633e4f06ee346e4c2912ed1c763a75fd1baf32cffd0c856ff9b44f1470136c0a8ae0b88175a7e7f993d8469cc8ac3f643aa7db36992cc97011be0a42ff1df8aa7cd82e260e05fdd67304644335b386c7825858a438c51b63f877af005f7d95202b54a2130a1f652ff7addfb798daf4415572376fdd910cd099066e8d2fe251a907e41bb950e960fe5116f4a4fc6037273250569b41ac07002ecf3b4b63f8b853f9693badd2e8bff695266095f4b2f38ee4d60428a45e7586d9d47c01c12c5e18d1ca9afedca6f03384567ddc730fb8fed27516eb7c54135cc7447af831f0c37727997ab2b01fdbc5e12c112aa987e95cf5aaaf44be14bf4882f49cd84894d555655d17aff21f077b2cca1ff0922afbcbf4781145cfb87df585e6af1955db04843a763fa735d33b3df836585c5894e5125d500673d5e4d0bdf6708d8d28c80298a9bb47c7430ae8ec52285a4c14371b3f8ac1e21306b34bcb0c1e3aa7a8dc8955cd9cac32a0f69d0fa0aab30abcbeb2c21d655ccdbae1c2040faedfc7a5ef29cd5d9227908335ebd257ae8c410b1916b9a5bf0e72902c2bcf701a18c1fe13695a8435b0d0129f3db883f428acea8b7f274a629865f1849d4c263a1536421875ffacf058f0128f0d012fd60f2b3fa6b71fbb96f3e1e33faa09b1d20b0919018e91a6bd9595e9c16d4fa6665c4d0adbd77a59cbbbd587029a4f306c887277a7a27748a6f289edfa16c7e4042fc81355b85a994cc6784f5fde054f188b9775836594abd82c1309a66db4388ad49f60794d8c8e1fe279f8965312a1e23c2956427bd6e289e55ec728f66c36526d40aed7c44e5352fa3e2b5d27bdc1f7b3bfc4f095d002bc8e7b2df2032daea9bd3e0bed2733e7ba13c6d8b45c492becabbef0e8c62c257480faaf6aefede888ce1546046f04ce7e06936cbda44c5f33c71c07b53fb3ac7a72c3770838471aace69f7ea454d2980fb5462173aaade7964b888606741270f92bc18950284d013b692bad63ec3726d8f6596788a032eee6eba08eecc836202b06ca43fcdb062e65f8ec91f7400963bbb8094de4b4e1042e040e81130a3ff037e1b7e947b0c3e8b7ab5b539f8570ec2cf08971a1bf0d4f3e8311b5c625b7d032fe2e0603ac1a4824432b4c7bb5afa190afa30c36f168d196fc89015aff8229fd4b299206e8183897229e95ba06324edc1a9ac81aad786d5c9d38c87c48fc6159934a8532489f06e1aa314a057d91c0f7218861ec241dfccce63d60bfa624652795229fff21cf5ca61ce05ea0ad6a1763173675377d1f2427564e397683428fbcc4b97495735d075f84b289b73389a1fece959f9d9b4932f4d33a0907202c650ccf65327d24cc24922d0d675fb59621e2bcd2eb31ed1ec5fddc96593d4f936ad42731a50f164e404b93920283bf9fa43f8be5878d18e07cb8813914508532625f71d02a615bf47018e3b3efed72d17e0c974d33df18ae70e3a4a743ac3c955d1c366bc94d789c90a8b3771969210c7f0c4b9b12f9fedca5d2b71b6c04e7024a0a5e3d0d3c7d30cf568a659cc17309b223399b39ee5efd0cdec3a34b0735df8d7e0bafa40a8aefd742b3e0157fc89d113af5fcb0cd136a9cfb82acce406054aeda30b83ade59cb6771c366c86b5d9b016a74f220a967b83254db3e24d3e1f5d5e23b21354420dfca6bd8454575c6b0e528744f44ff8e1b9679b084d083b9ebeff09df273a476332dfa172cb98c79ecbf3ae4a722c25be71a3b206d848f56b02fd04bd32ff959e6931bf6cba042f9fde027d832632cc40d4320166f9644296d2dcc845491ed780cb609c0432408d08dddc70fa2d52884df47a55a8a3e706a24ac6ceb375a894636e1ac121040561ef486ffeebed3c5336d123dc05a5cf221b9e895f6d3ffb24b3674039d50fec114d3648d6dcf4fbc0b503658672d675c4ac64dac4db4615d011e82bcabd9573fe9e2af224103f99c4e6e5acd2196f1eb2260fb4aa61c298f99c20c4ac1c9e70a9a9e28db441c3adf2f2b3a00ca3f1398b5a112126fc3f0e2d11d40db36d0aa47d59cf8ece36df8daa854509e546295bebf92465f32a7edae6af4218b49781034329c22ce9e87258216b4a901b823a227e46f2938df336d3fe03fdbff4efc7b8ff8142b4bb60592abe508675d04081e5eee99468971fd49989eddf4648d3948266b08133b8c22ce3523757821a05f254cf5691848b1532655e85fece5eb186e87fea61936fa63aa047b5cb77c08aeeb2991c26619139b951ba4c2ed487703a6123c9c16d7b6cd3a17ad108fbb7c79fc3706f654be77a6cd8a5213d3976b1a4527144e788b712f37cbfd5f4ea5aa5fcc0f91b98d74ddcacb83fb33e039e1b88811a2138743ffc0dc5eae46c688f48c0be92a7094f92c2d4bae0c1dd95d40ffa113f27b8fd1808178be0c3bf77b677df2a17c9443fb6023c9e43c48614fd7d09a904e7a064125f8b7671fbb7529169138feed4bf3e6c215947efbf44fdb5eb1e3a5700fc8bcd1cf2a393ed438e68b607a1061e6cbd46a0b4f30fb4a492e786c5cc6d4f80542d64d0d271308ba072deaf7b1ff1c5200a2bb24c68aa2a5cd07052ee5760e0ede484e0a9c482cc74ab564654787e1698bef1386fe446106af25cf2fd950a78f4b521d547c83b6e4b6ef652444af342e90bb5761ea0dbf6b8c315996ed3d3a1a9d1e5f2b75ab18d0bcc87ee639299a248406d9deefecbb6883fe81ad12f20d80fc9b3c8962cd84e5da215b96bd457d5146aeb36d08185b2ee021fef7fdd43d0555c0fd16e7b66d1f534ae0b87f6299fc3b8e70236f39c91601564a5c2b3abce248ecd5450096e65df8b69de8b5cd963127f207f0df538f990bf29ff0c2930ab8b378b86d2619b150ab4dde82469e40e9e6e503182882b03442f92cf7449fc2c4b2f7ab91cf5ec57b8b0ebc18b27ad9125da57b6c139edbe7495defc73d68e71019b2b808a1ecb89fde58ed9dfce8b17e072170983e3dc3551149108582b95b2e4bd9552faff0bc7fd13dc0130f62a967761928dd62c9cae970ee447842a15baac31a280b443390bfefb7d4115e8d1c6458e1920485985635b75bf84b6af5226dd9b36c94bcd1a5f3ed99fc3e5adc6f3c4a592d2eaecce02d0e5ae97e6c4c7e101d4138e526fe3f090123c6df8596505b4d28c1be9e0c3f83dd4ac07946617eb553f7688f6724c8d8d34281a8c094740170280cec80b61b07eadb2c63427690ce73233f18593537e07266a71523688e6fdd36943d015c1bde058ebf5fcd12ea00e6b41565d062722941ca346b5949078421cf1f32fd38ce1be52fd65f2e9862bc5c57b45f33581eb72d387f0c212d68f85baf7e42058e41966429b0189da4eb4e58c1104e59d34eb0678a1385c38289210ac86f77cf8bef670b9ed04414875a29c27b79bc97e7febc40c39cc8e201ca56b25cd8c96f1a37ff688fd5d55cf5232d216283169b51cb41c631ca323056f2e8f74d5178a83b3bf43cfbbbb40f2680f338a89b294d4b611b0f275cc60e99bfcf270cb761c1c2a6773503a3c0e03b2a858d0cb5f81b032012bb0e15add080cecf19bedadc4d0c7e9d81fa75b97e7ca5e1c9eec88bcd10afc0d8e48f83aee498633bb260d731e0f900a9b0ae3f0d6e57346b8d3d8019bf079b4f909b6dce5718052416de8b61e9ef317ecf2faec5a64c0ce4bd5aa72b79360ff9b58d4a5f3e0648000d90a947933b0fe71d81ebaa96cd4c54c5d42b941e73423efb1f6626767f0e6dde52cd8796b0db31cedaad75b4ff72b83e0e9ece164c4f4dac170cca65e42db8b7ead0fa6e2f0b2d9576c79d1d73aa4b7ce4b954958dea381a65d4287bb1e02b7b88b33b2f1872d92ec6bf79fbb726aa436434fc7f2e79f0ff8bf243e19c08f680a5012c3c3d0501abb46026c420e485166fff457412a075086266b854aeaf5ac3a300ff5501bfd7ae96ebe56a5df5b7abb5fe2d9bf7ffc0005b6aae9dca8380a66c8c14e884f9f3338346ef1daad62042d09cd774b43016b0339aa208c5d6c2f7373797202ffe680edce71d684030e5841edd57cacb0cd596c63515a1b992de113fd2c8330840915d3409f608c8d43601f09dddeda6c504352e4d8ed932d8b5076a557fa2d87914ccbb0fed61c1f4d9950be0900b2212a82abcc4d9f4466d1f5469939c1e35dcd2d124623e2e1aa2dbe90ce09b958edc4e60d7e7502ed16a8a1d08dfcef84eed8a93d6940441ad41e493ec09abce869a8de0a778fd8df55cd1d9d7f053a72314e786088abdf968a3b1d1427e52427c2313182f51b5556466960017468a35ed2594280ad8493a5d3503ee4c479fd4c8db0141fb6b77331b46fb228f94e213ad372c09ebfc8bbcc79eb074162b4694b7bfb8444a4938a80747d2c15879e28e3cf44a8ac2ef8c5d9f93e9cb42f81cf88035dab96b6c078bceb4fb9cf293dc964b0cc9b722a84f3423bd4fbc57ad1f68a8166e86da595fb3b7a4dd87190dc65756e0f7750b68e3f605def2821619fb4fada9cfd1c41343dd4f5424a1911ca709ca745962a484d981db73a23a85c046a3eb73cb48b085d3286738e689437cd4976cbd3e2c5a4a4e385b3aadd09b08859bcf5506164db33d414caee679c65069543f1db8b242dc424af5a45bcb5ef9b939ce94e4dfe56ca25702d7912c38dc44d94670d90109ab685ccd59988bb7e932ffebc882b7dab274065578c041591d481501797b4039da17684a7242622f4390544b05023d3902949d348a44d9ff421d04a55395cb4248c7cb0f13b697f1423be1342d31fa9b85aab70c16bc62eae5660256d2472dc908768ccb7ff02cc84ffc6059752499711338e41d37f8751d84eec47a51c7daaa273e19c523d3d97ee5f71571def6f7268f24afaae71eafc84986eb8a0bdd50fa553c815939a4b56380b22b650fbb989b525d2862c5d420c83509b5c76b1a9a2105b45c2182331ce72e8f1804efee93b1929338f" ++ } ++ }, ++ "1" : { ++ "id" : "0x690a7fd66157e5b777256ea5214f634f61b3a72d", ++ "keys" : { ++ "falcon-512" : "0x09a89834aba90aa88f605981578667395d730a408f3d112231997200c28865ec37a4a1f044c8817949cfc8a4fd9028832fc406f1bb919789f2099629c2c8d6bd128de4f51c02a73c49dbf17883ef90a9dbc0350aa67e024a893e555b4f989780a45320af4858421346445f66aa86e4954c0bce0debc896f21bc960e4fbd4eebed93e943a40387210ecda652c36b6da73570500adae1a2a03284dc47f1e370570a07007d8c5a64089e81e2c4d45eb6ca01530884070d46f4605ffe139457d5155c8e9ce8f201715ce7b9d18755304ddb6871551498985ab400cdc4349c6b5ed10b76b425e70376e39a6167622eb5d4b7cbd932aeeaca53b3e28ea06c44780b01684e66eed712559543cea677f1d9807e2ad0312c42e43d399302a0c4c506da7cba37000c3ecd10b58922889e5c8d31a9882ab8ae4b69d3d3d3abc6450881e9b79d9e2ac51085f61ddcfde73e57c1784a6a766ee2bc434d4973a9667c1c8e00eba0c544a36c593a764f519de83251ec48fb45a63e00ad4aaf01d1a295eda0eb95b27fc364c33e3482f4e5256cd622242840d0630194316033219c3051258f548a23c08d205a7b15199ba8d6507565d06a1f20db367183d56d9dcfd2e12c36bed83d239ddbda9efe8507451542942033282bce486f002a215c2ef599a6619247888a81782b005acb3d550988c1f22c6b186038bbfe1c583d165588e00c7f0f7e462a778e6a8126be71ee0dae7b5cfc6145aa6e65c8c136d34f7b45252652995898150cbf177f47ca8d16b583ce5b0e809567c08b99c06095c879b4d945b13c8a62429966347946b606dd78803a3c8113a431761dc868ba2e2541c66b39f30ee21b0ee3fba5eee922d56f49ea60c25a1094381908a69b351e325357d9b4b9e2d040d8be7795891ad46a334a057b0aebdb2e5a9cd760b02c774f60df240e05ed3708840b1663cb435adf9929c138b9fd15461d86328d5895d8778ada79d9b567386a6302b67b4b99a37f4362dea36fa2fa1f1ee2f4f8293b131c57595468aa5ba62a03dfadc9784c8190559887603c4b50b7487e795285705f07f90d8a9ca50e4abf0905d7487f04549132cb3a62ac2e490d6d5bfde20568290b693681218426fa0458eb356b198b41bc60505afdf7219ce5959124e4d1a56ba63345f91ab39afd970997895689c8397c023b1c8b774f92f0e5940c764abe3bd609a0d50a98dfe291e1677e6232896ccdea3d047f35c558daa130ff53cc66aa03ca5687a2006cb7c8c3f", ++ "slh-dsa-sha2-128s" : "0x3345627b00d77c13ce3ebdd12964c45d0bec4dcaea60b64fbf6cbe7b897b8136" ++ }, ++ "pop" : { ++ "falcon-512" : "0x394f68dbc8384822df8d4fd86c22e55256ce421178ceafde6e1a5f6437900ed2a86a72cd648af5e2ec15c79027aaf194847efd5855472b428c647a7db9d6e97dd15f70c3992480431ac6919e5b11c9154ea5dd9ac630f866c589a54b84a4c9fc57b86f2b5c835d3f6fac9de77d1f08abd507f514df6e7ba1c33518d3d1e447638eecc8a4b7cea388c2a57a6640fc599e73aedfb4ce6b3f147591b9bdd10fc7539fae4b2931eec267fbe70a5c6dd8b24bc98276db5d8da487bc38298d17aa7fa5facef7cddfdfd6eecbaf7e8086cab1df3c8f3be1913d30892aea7bd03d7ec1296247593835d8a74f467806259280a4e652f7e1bce11aaed31fbe2e155964f7c37243a59dad5c8d19c3c6b9d0f62d59ac39578dacf29d9ac2c0d5f160f7bece5902417ea82a0736bed8a4d078599134506a7b0f8a3ea8d6749fce0d749722f7c5198c340f53af2b4e1054fd97239109aea654bd2be0307a2d868570fc34f56a95ef5ecca1995681cbfd52a0e309e9db779ae71aa921796ba86a2aabdf6a39250bc71cdf8ad4d94fd6a758f29c90a7dc44839761f4a1a9c6d1905dd18d0532832867e48e91156ca67f2e2731bcc949d8140a850a8aaf9dfeeb9aa339b453bc906fe07f0a3e30f59a941d9f4f7b723a639e5e10f39cacce38936fa58e36746b0cbdece2a9122a110099104543f066515aa7750ae0080462d9254f58b5064a55b23a06dbff5875966598a7ef2417a8f32231c630c7b3d574584c2344e2fb38d8bd4d9437aecd68dc690b8f1e93f0109ee3747bae997419d1255a5c14fb1ed17b112ace324a41dc34a5ab81630fdb178641536da5268d928d19daa49507a5c81aca3e061b4b5c490310b13292385bb341b0550cfff7d8c72de94a6462defd1e6596b351ef32ca474b61c951ca5bc4f919e4", ++ "slh-dsa-sha2-128s" : "0x6e16547734391aae71d29745c3ac8cdfbc98f07ad9a8470650f0a0085883ff970643e21b67d6ffe83653a99f2198f821cc080dd7f0cd1a612ab5c6f18d9903ecce34a5cdf069ac66483448219c06b131b377900b999f9aecf637713feedd8c7d4beb03ee11bb297bf4a97959ac5c85c0c83b48147fa9a3be7543ce1050394e83ed745f9ec0c555328d3786da46acac3074c0611667ce5bb4613436dac210c2e9cb186e9540d7d43ceed7f278363811083368d50f6d258a46a32c8df5d62c42c4f6f34c627076169428e646774dd6dfe6924e2240e720fd4d53dee8f880c782862de1ff96fc5204a17625ca008781cb120f74caa37a36dd20136567c05e8e7723a2e21569f065d4fc631811ed0b2d9bb67d2c82b755d14cdeaccb797f207427d572419360af1c443fa68064a653b1e21a2b83fbd93e38c7cfa5046eda9b86c68f3855c61cee9f799ba02e611a1b7df6a15fdc4b4b09e51b3b5e1101d0dc90a213cfa0522e93808fc4ab3d8cef74d279b98069988f6b8c6b4c8d3d62fe2a5a62f1a7fb0fbac7fb36529dd85416a330f35a7e4e161757a83282ad50ddf92c6096cc1fe071952dae4540e0c9d0507d4b61ad34751ce17fdf2e99c3e54cb523d3ffe2cbe8a5c58b84bdde119175e9599df6b2666a7721e246305457cdb5ff5ab4ec9d04bca439d59989253bbfd9a91cb10a9fac3134d85ef28f1e4d4f884aa195216a4811be7617c0d6004c7833088851fb7758aa5aac838ddc5e3a51d122fbb03b0b5d0a3593b2b97eb69c2266eb236bcf3134414536ff36895bb081e9fdd2e5a9f9ba71310af0fa126eddac07ca67020ddd4caafc9b102afd4d0bcae2a957bd65d0a15762b98f4dc7b548cfb463ae10ec3da3b5a4e9976b8f05405904aff74d3d536f9a321b41e0c1d5e4fdbbf61b42d868602e112b53552b8199a6618723e5638273822fe0afc5e6fe068d117bd5af3a1c1e8bb4ea9ae639674b51a523d19f950629a76e9a52c673dd153915863d0ad166d357f8d23b85010aa0b8263de0f253a0ec29b0973af15e4419d965164b5fc6a0e782716d86bfeedfabf4d9705e7093373819a814a45b245cdd13a667b31f1724b5cbffe3b5ed3087118715a0ee68af333bf26f1ac1ff13eaad6a5edd5e760e89518e24a982af4f44386c6d92db7a2229bc9c4df23274cb0f10d348f2373a79f55ee05e3dcb256df464c5f3e54ab790f1fdc585cbacd93c775e50bd02f451b69972728bdce813b46742ebe9e45d45c8bc23d4b298b5956e03b48c0a11c602ccdebace8f92e2521cb346f291717cc1881b0fe3a2e23d4ac694b7f1cd296b32b7f2f139877a129079a524d7e3c4f9c36b5836346a6944c49967796d8564ac8d2ed5e804a14c655ef235fcac5a8cf0372f7df952af0de7e4319089b54ea3f718b539a9bca631ea0bcc9259c64626d252245d541d90179364072b081d70da0a7e561ba2902e8ce864a398dccf55a4f583df7b6f6ad6738813eef6815f8f67936b7b842ed7dcc48808156d236d70a9ecba41994bc0296c3a236f2772c747db6ad62723c4457bf8a2e526f306d8012e04adcff0015a88167d199029ecbd333a6ea35f5b9dc2eaf11a14fd09b35bb2842a4e610da4afef15f332d5d1e82c7b0b452b7564eb45193af060595975d496ee59151e3c0f1545ef2694eeb1a2e38d4e008c0943c8e7f181a258c35e5068df39376aad6ef356e0010303d9a0dbcab91dc708b8e9482f50aa18f88f45864d539dc0818148149aa259eeb270a474b0a117de91b6834672a5cb4b5fb7c2ea0ea7e3bc9884163887986aff1cd89c49a6ca417dff067da528dd33dcd1f7db96ed50820bd72dc41984ed5c767478b79d8f61cb7b417893a3a4451129525a915b1e999086e6db74ef627534015206953ed3a5e2bbc5c629b00f3f3b22a37519426c20b2a10c60087ea32fe606d81c6457a02bdcadd8d56360dbd278ced2d4cb9af64af4ec77989475882f3c1c0b9f9e0b6528b9834e34024dbbd64dc19fab35f3bfda66c086f4c0ff06a29e9fe881340d1c0719ef568e3f8f683282b963005e93620c01de327adc0af4ea7f968fa987cb8f38350ebbb3b91192ebb009f9fa85657e06cca6f71edd3d0dbcfafcc11b908cfc38a08ba288910fcb14f97746ac20ff6e6c43eb099d09a717ac03f5e0600f0bb611d6972626999f5661e048476aa999c83e3f476e77e7ae09c6fb7c343a196e1846ef061be75fd8b662932fdd2c7d8784c6e498d4d828c910eca00ac199957fb44d572d4bd2c599fa6c7c2a166d96aaf4959c561d1e9dacf502f76b050c836194fe1897d54a017944a973f49b2ea59b66c24d18f13048e093e83af249854da9fd6b4974b4db3e8e65684b3b6a0a11d942ad5bb667460dd98ab54319cc2ab704a7a57c1583b8289477f5557d2da684aecf66eec3a54da742e2d24a6935ffc4f439d4a8abc21921087df93da2bbdc3a0f61729b397faf12bfe59c85a6af75c9f4ce4af19239840b57c3a4ead6096f2910da23bdfd02ee4f3676897f475d625d0e9a9cc930116bb2327232dacbd0ff32cfaa40aed89024b9ccfacdb76bae77a87b569582442ad2230c8fb3e0dca3937dea5685c46aff9ae6e16438e0e9ea8ba299936a42d68967926edeb3ef955d95c5a0b74a13edd280bdcb462dfc2d82e7ec89377edf6760450e1ebc61f035fff661173de5fc80dc66b8e3d38c67f4ef8c25c2c5626dd2875e10d870f12b3f36f749eaa0c82e94b2f30686cda1da606e0c815a35fe6fd671915483e1b2b48fab000ae560dca0119be7a0a3dfb347ef95c7fcd9a78e76911cb5bd438a7e96562e437e32eb399782a9498ac992716bd9f3d7d4e35a1f1821f9008f547d171ce2b69b007b5e377a3244092396acf958932616bc5cb95059762f48468a94f9f897736b11bec2ce0af9ebaed9add43bf5c262106a96083ad967b7fcb127012b1b37970a6be14cd9088f6ea927a66a76c35e1320452848bf7496fadbc613b2e122e55634f0491397ee5d211d780971998244f303802d7630837d05f3dcc588d8ca32e02f16d2297aa577576ea5c1b90d6d330a18444dba772d7aa94d0bf2000d598a069d03e7873f114cab9174af2f28e257ef2c0e44925da7ccb593d6183fdd37a1abfd7107ce02c655e7966286b72d65394f312d72505803bd53621a08100a041210cb912d5aef260b84e39faa7b5d8a539b6392b32ce6287e1a619804677b3f69ac46fbec010e726f3eb3458433e68e6417ee375dc70c2b2ee16b2cd9b228d6a46f92ba66a8c5b08cbd284dd759478c9f690c5e1e16d6332b5a0b9aeee43ac8ce3eb0c3eb6940b61a65bf7c3348d8dd15302b8b7bf6b6257e074d0af3eda088f7c22e6778c8cfef1f15d9f86c76a4b05c9afa228bc4f116ee8adb959b4ed9afb2307f2252b10baa436795028629d05277ea2722ffc14d9a5fd56e6cd6f0ba218675df025e50586e46429f1c6028e305d22b5479dd045d98a93fa30de08bec1576ea692bfe6b657b4be65578fa2dfcc197212643ec9a1a8de5971c07023abd8767c528025281f9854145e3d9c47e01bd37dc3a35b76639e4716465b862b705ebaf674a64313641de333828d75c16d4f6ebc4193fc2c92e5a3373fc79dcdd8505a8ea7ef8be6ffcecbb2e80017b6fe401e49193ab31e67a56e8163cce767abc393608e7485f41983ce27b9b1de1a0281f237d685d401641f860f8f11d10805fbf0c7125deaf583458787c6f2850b0cc8c62053e069df241192c6af9018158c27e30574a9025af5af73bd956bc008efe84b31fd9a49c110b803947fc939faeb773cd3c33d1b6a96fca0c079f2eeb4e3ff768bbe1cbada9ad22c2d97928389e5f7145a346931e4138d66319f0154cdf3b28cc9bc04139f92e421efb522d0639f02935e228d6eacf3ccf0356b32c163dff6b597d51b64a13c8c93f60f150f445271489db644665ed1208c025b35dcebe82e73034561704c602d1b24e04c08e4ca8fab21c5136b6d4b7af05cf8ed62961b4bc1c2883154116a0ca8933e36042eb98d851be695d8c4de2c2530372c606c93bab254d6b00e59fdaaec98c56415da26ea8449061e12bd22743a1a0e0e1e117a4a9448d75b3a9dfe6f213460ca639632d404af60c764d91405391137ab9ec4e8519d11e3dcae18dfad0404ce14ea4dd36dc3ee24b7a15709410818ed0a42091a01ed9b7f39f7c87d60d2b3dcbba880001a519fb7de152ec06c73d35c08b3e375b9186752931b6108a4b84189fe07a7165e18357a94962dc2761f4eff0df829427646d2210b55915be710e2a1bb413df2055e7aa0b0b9a4067d35881f22c08e61b587a59ef82ed4df267afbcd4c62f22435167f2d7a4a939eaf28a6f1903c8c046b2d7719b7134834cd56964ba860e60ebb6fbf4605a11b52aac2d595cf3b6533fe2452b65dfa0fff71aff39124a88e3e02977d6063a8370f98e3cb8c80f35260a8541b9584b1d2bcb315b394d7641ca56539b4ca8bd9e4fbc594b0a3bf1ed678be2f9a18d31d610b55ee175514738717d47e4821150a799ebce655d0c75228c2160aa1936dd42f9923de2ac97d0dc3ea062d41d5beffdd1d69672b73490d6a5e14a655228bc39ffc8f1e862fd39dc950dfe648e0ff87807e543d02c40411ddfc6c1f8eed733750557c9f68d830c83af737c9d8c3ff0d23987a8e09e6293d707940eef4cc838365775046af35dd26acfbb4264a9ab84818a71c5a13d8e615c5675656671e5fc2e91b682e91eca76ebfeb1c09334e962496f583affefc56dc144873c79d4df77da394845fa29ff348007c8ee7f23f2944c121ee3177879e6938eb043a0abb75991b3e789571e3eff009cf089acee93612e97be85e1cd83da9ff5006c14151afa67fddbd9262667f98df52dfded25f28b36fa32ec662cd5a6b0f844030dbe1c87e9e2d435fca1a81045b8de5b8ccc411a839064bfd133731f55ee2ed2ee727d9382d130ced8a48942ea295bcf75fc74e24204b808956bfc171392f18554764aa80e75a539941d90a4afbce1f981f0c35bcfc78330ecf3d416d0683c7682cbca066a10c43273a0f85495cb4916ec0eee9952431a11717cadc95c7626436953fdd5fbfbf9ffe329159d1bd79499807796d75c458c3e3914d1f73f656e9fa273244615710c3eee84553a7ca0250e97a0b8895695bf86408d2f3cb2fbffffd62c8583af5b25b7e2a38e266c9623429f8d80ab8fdda6774df598f966b86ac228639af66cd0e3ee7ad7714b4ecb42876c31eb2608fab0c6ee26e97fca305aceeee80bbe22cb5e9819322aedff05cdb78b1fb3060ef18ce0385ae0fe6803b414aaf0b340eef94a7517e5cc3df4bd273f92120b8ce73281cab96821ddaab08b41b97708dbc7d0edc49cb362759905ce8d42743f83a0d75878596c4c5ca878b7aae6fee6ca7b20f2ee60ea773499a781b958f4353ceb078e5c04b0fef3e0112dd0e3a7ef19e4c63a202fdcb8ea56d15b2fb0deee4198a19c9aa59c1ef2b3de73f291445c248779eb5fc76953137adce5dff20f2198cc9e729be4adf385e0f25f67f68c04b4cc26987c133b987f477d89977621b8313d6d18a5ff6a76c73ed608f5e4adb860e2e8a6cdf237d4871a98f0c448668bb42f29ccad560fc1e571f8abb3c75665a65a212fe9d2c1c48eae9b92bd0a8b7b3d2fef99ffaf7942f5834533a592423d2cd66aa793e85bc8351876946a1e49e13ee374609932ec1af8d4d3f52e00f783368aa2bba882cc91c5fc6eeb657f3682dca8e9d63f319df3bd1cf52c511f600a6c815e4ad59426d9e1f32831dc5d8b0673c7c58e8bc1601d241bcb76c1306ddd5aea847dc903f376bc4d8e73a55f0a5ad331f57bee70533b29e6b8493d9f11ce4f27f9605f693c05487bd43882ebe8a1090a95abcfc186d74a3708ce3351ce7226183a21c08497dcf52727b7de08ad6a970b2c9f314bc7b33995ffc77a9a36ab46c7a05f61315d18b3f2217703be5753b4ee1670eba3af00e90a94664039aac93e89dcaa59d4566bf286f33c740feb763d0a385855f4410052c52abcfc972298ce03ddcb2e65dca251afbbb75c516ba77001dcaad8470f61e3391c1c68b1b7dfac9e50d53d2ad12876ba96419b39d7f94fd88b58ac1c123790bca733b12dadec6922384c6f3b7284334bed918acc06ecac7674428d56496e9d2e8f0175b3c7e384218380b6d59dc93541ac0a7419eb0ced7ca8c12a487fef9ea50280b7f7067a8855e784362e85703f6b848ddcd4bd31293baecda021fcaa7198b27d37900ac192d71de4e5124089bc1c8234fc455fe71171fc44494395b323fe3575ac720af5cff428326cca56ceb0c47e20e1432018a769f467405f5a8b71e15e0bd32f027640212d893678ec6fa16e5c00bf5c0eaf2de0333126ebba6b2306211cbc731a6baa8fc5a64a30141a8bde237c217161e384af3355b4a253d35766a55cc69be97abead95dc2ccdb4d243f64aa6d74330cbb2fc9fffa79fb6b6baf99e5ba9abd7966efc1586e72bd25f6563fbe125abec67f24e3510bcaa34c49499811ad2425c25593ff362c90c5c4fb3c4c45a4c63c46cae8cb1759ff2d82ac2726b60b4f094b6344191f3828c78d369956b7a28f650f63260c2dcdfa66d1df4731866efa6a335281d1cf2ce3635eb4294c8b2e1d4b7ced7b4b58a10d693e9f5a269b9d3451198735697af3a7b4b630b835e3b56e252f71f9aa6dcdfddfae13668bbbe3538d5aca766dbab6655c4aa906e0106640d21c30f1a241f4f5dedd526e8f579848f1b64808afb54bd2737a18d9a0e4a078705847b59a1ca4b2b554d03304daedca50726cd23326a6507393b2dff27921b5d7d322cb9901e0efce9bfd95039bb3bf6a99282f9dfb1e90289e986a657b3aa212cec6e611423eb3e4523f4723302b1b4ea5db2cc3fe3a7f0f3add38eaf228a6f0c02b9237e4078b438c01a0856d64053427af9f84eb04f022fd12986287b48cde73554b014f75a04d01f7d3fc6285347be643ce214b72c911e6c5360909ec590ffec8b4395fe271e97af852edd3801ccf04d3ed6684c66c67278cf331ac7c9b748e2dff377cafc7fc6732352245aabc9f5f25cc29d8f7f211a88a7aac750e488ad0304b7907bb063e29fccb16dd7ca0b78fc3962046a83f9c7138d49df3b765df47829e5f56e5155dba194d5128648b92e4f5c11bdc9232725faea4b87d6d940b9bd7cead9462736c7ef605336c40c9a053a000ac390b6340dc85a6905d35dc83c2d13786d233952ca8777b5981b761376f4ce2c5bec0587c2b28aecf39371b8899d227dd58c054aea7257dcfd838c32d6053362842a0baee7f967b6a4f5e1cac240896a8ec8fabbc4a551a55e674dc8cede1b9cee3874ff9fd3b91db433a12e78904aa3ec84d57a0169f1719297b467c46b278f671f74b8bb3c2c0cc2a093cf93439c1267e3be38b12e9b5881c27ab47bb01397c6470b80174ede3df34ee51ac116bad6fba58f8b8e2c7e0d1dde184460a5bce9e1d853d11ac017001fccfd5b767afb69691844e8327d39660c06b8916e918f5587f5abcd0f0bc45328ac01b1ace66405ed6c7a5080f5795f2ba0c0d9e5d05f462d89aaa230f240fa47c5c0de0b2099e93ae8c0f94a45f0513ce2797cddccb5216bad88333f6fec5805e0b9474a18ff562e78dfe325c1a6bb3648b41595690cab5ca9805eaa8e13526d036f4233f8181aa8efc76e14031d343bd5d9023fd6cd6b32947e173807883b6a964d398d3fdf9f34a44bc5fe41c5d72ffe5fedaa13fa1da68e19656ed70771529cfe822fc694be1445c79a041eff9753cf47a48ebe9f2c9f1546117b97a1c2bd6e375b957fe38cfcbb29f8eb726f18bc6131b1e27316064980e35d95fd913583b9735c6bfb03ec86e935024e60679a61d972b4aa296189fbc268552acb6cd890c68e50e325719d2f2c99b8105bc92fb582eafc1d618b4e88070e6d8df4924a1780f63ee216c0e937073725353b0c97acae72ebe521fb05fa78a4d6ecb7ba2b860190b6a5c340c83249919c26466c9cf4a9b774fc823141f65196df32edddad59fb05ba24738d81734004c42a7f92f5234b7f4fc0d605b032b08eda4cdfa3b03a3b805ecf5e4ad667a8cf399efb3c1d6822d9d5bb5eece6e08a515cd75c4485537eed6cbd55efb0a3d393d2cdcf44846f0c27cf6a664c70dbd54fd56b20bcc482de2eba84163375b1bccd43da63467557828b791dfb0a976628206e26e9eb10f1e9b9fc34571cc1a38f54909a1ee0b097e0f22f3ca58b56c631708e9baa52d7eb551bd327a6e0014fe98f04d7b0544fadc06c16a5652ea16b6c92a014bdeb2c070843152847293a0a925cf3c22bc9ac23464919ba6340cf233990690c94601876bc30bd5283f97cfdee757caee7b7b41fc265fb2ca9751e3b523e8498d665151d1c67624a084571f6c29973e624703d2e87f1ae5a5e0dbeeb96f46698223e063d10d85fd13fa0deb3891359844ad5e8100036d9b70b3b7831ae78c927a5e2c2ec62992cc424894ccd6f064e9ac307e6a2dd092deed179cf60b4bdc6c56c32a538d477d7917f7203f898659104ad5aab3e520a9f21d9c01b581cc968a68a77648cd95f66b5a1eb1b9d60b0a73c2eb05873f279c4ce43409853df2c8db254fd5b63af900c764ad4a0aeb4641e1a4e4089967e83603cef0317d06d1b990354c11b17c83c2a78cb9152615b9eed33e20f61a83179748ed4044a65edf285b155d41c735a883a481fa07c4941865b86d3cbd54c345d7933e32daa90a1291211191e0a3a5015f0f60d2ff07782606c164485aa469bc97f74dbf1345ea631bacb972be00547074759fab2b98a78cc43b7e4fee587e40e23d9f8ecaf03337d47d27bce633ccd97c0b18509afe35d54b1761a4ecbff6c44dba5402f3111eb671183b5e6bdcd69398056b980c35628f03214e0cb4ee5364e51de27843ad6c24b1e972889d54ed2a31d74000c32fc90b3c96dc3761c9649305c5f5e75f5b5ab7eaee213dbdda1039d4f3f450c77e6434752b74a55c42c98719836fd91fceb27be449d65c89a823218e882b987277622ce62fd0b46130760f10be6b49ec57e25cf6584a99433cedb1ecb1ce25cbf5e2b6eb716c12064f2cc45f4989c4c1b6c1ebd390c44195a16da16340d3a8588754ae676a990df1eaf04336b3252a5177ca3b3b2afd8e7555e92be6f6d7e64bea52c8d25adce3c580b5731574729107afe0e1025e6da2f2b05d6cc223778ac7de1202566098d43d0e4db6df8d242b57353cbadc0711030c6612cb92a9f9685c88856a0739e61d08c8fc5864fb9d8f41b27b43152ec15b3307e2c6f20e00254984e6284763acc977d9e16ffd4ca8be3ba7a289e3c5863371c132b8300f59d50f9efd344d1cf51c5ac64f29210740be2dfb720397941e2ba939e31c9ed563a674628b6ec3c8983be01e41eca61f869b920bf08db3255cc04a1f459653a4a3c204e6ec5496af1984f5e47caf56993bce1124bbfdb5d7081895a96170241307f000ed22ba92d5f5d920ab39d3ad1e288abb76ec3acbda6a7779be4c65e99bc7d7d5aa57d08ca1774e0fb146cd3a894beac12715bf322febeb256518addf26df507db3c79cb2883e6bb1e4716e185026cd760c76038d52a2e0695d76b3bf9da7df9f4dea5323f7dddc8ea1a0031851928e354e703651f7a21df505a4e7f9f7a8a398582aaa9f504510c0bc6f9af8942601bb3a6df3faf2e97c9df28268e1dd466857d413fa0bab4ff017f12554dd317455d6c716f9449c5273ffc959f147d7e0da0c2eab432b83f96f7d2de7b1ebc41eaf2128f8eb8f9c09c7b3fb4e95bb3424b216232406b81abd4c0afe11835a8425304376b08a4442c6eb0e88a51bc67a49b143bb35416c9ce613538483c091bf181d322efe10b2204aa0f0e01507a7cb809cb54b5cca5f44c20da32b2b7ec52098e53de672795b68a44ba667bccac558210307ac27bc5c203a2e6a264e7cf3028cb4ed41e29bc46985c1440187155b8bd737fbf9480749d62481d805463d75ec17c7ba83c60cc7020fe4b110ab1a248f6fbfda3e5b8a688a280f87a53ea7154311951c2001a7894eee171a64cba9b19a21e09540dc5ba85b1b2880efc39c8886dee72e64f045d00d99a90ffc81fc957ee65b7bb93e113717e7e7a275814404198f9e9d33f45335908f1ae917e0322b3d12c3d298ee814d22f8a57304faa93c18a14fdf53f05499239b66498512a6856ea194705521857a1724bc2925ba34f0e2707c84ee234c3436b4d3ab46cab863a28a011236e564ddbab3d49baf77be49ff2f5f2ca75252971a421aa2d4975aeacedba6cd3629efef8b2322b516c60ecca2541112b59d73b88177cd3be06163a463306cac2c0c1b11f84ab9b2fb6ab776bf0dc0fcb381975e4c1a0198b41bf6c1587bf6ca7272d8c722a581bce4494be5431cc5e3038ec33d843b9049b018fffa03cb3ff58e5da6bd6d49ffa6f776a5c4fee3cb258c4bf92e5e4079e38437f321e0c29d608cf5f69129e705e66a7036d67d43fd4a2919271fe07052fd30c049b793d2af0dec2431ea687077cb7a7a5badc21fcb0c2ac10bb37247207596d33d1c2232fc2a225acb9f30be7fe6da19514def9b595929c1c0c4b146099bcd980356b601ed0701299ca1a5547d62badd0475bc76fe51d0565b95b52a801f14e1f1ca62526cf8931f0706e3a478d20ce7eb1b1088454beac15277a72c90dd95f6146f961e41caccb2cddb2cd0680760731bb6db221944eab186425b0c2caedd840be5a2575d8dfd5810c4db5403d4491304130bbc564cb578d814d952706570e56641e8ce6232a2d4b18941c35301cd5c29211237c274dfb1aae379e25efdf827ff6e41cade1d57ed229a6ba76bf98de6592e5ae3ffcd481b53071e452a0b25f12919003474bf4ad2f36138d3d7c23c89b5b41a25c3622bf1dab6762cfa86a5bdeb6f2baa9cb3ea7dfdf9bdc700f4062ce8fdf477a17088bb2bf654e2eb9ab943472dadd73e3b63a4fdcf90fffa98983130e16d512b54aa0d4acbb1604d00fb2adc4a88e87d466237ee7b0fb33e5f384656a8759143db4c377e2cd264259" ++ }, ++ "rotation" : { ++ "falcon-512" : "0x3981b03586d7884dfe64c33f5b7b388f166ace48916b895ced22b34d428da6cb1bf0b0f292968d77e45343982d586dc6c556f8ac4afea15682ff6aa72683367a22398495006bf5ac0e830f10559bca255d2149a0740e61f05322d4acfe3a86645817823db5c1524f27b71c99374eaaf72ac0f59033a05ca55c563d1d2b58ccff25c58e779666306e18c1a9a4bcfdd7b47d34f68a96f3c18ab227b263566951271db2b7d6e20d9febc759c0bff4189c59f6add4708f3d8e532d58660cbc12ff5ab24a6525d98e4ff50f2a2b14f041e5cd6f0b1c4be47ae745ab7a59e8a220e5fc390c92ea8b085334d6cdb33fdaf1d7cf3c477367f96a54c46f9aa448cc53ae521bd73dd8c6a652f69373c3c7fb18af3211b3969ae922a3ad33babe49c88116a97125ae74780644f6c2d31dfc5987f550e2ad8c798d4f0f5a05b356dae5a73949b876f37355793ae6b0c6729ea2d70b12c74c2884d76844faa866ac685de8c74f0bb2f5ee9027d731aa55b2e9b1ef5a13dd33656699333004392ca27769c6a91d5b26f3ac3d65d74f9219d938f2b02f5fab2079e2ebe905915224480b53e2a89beebe3ed153b1bf1f8e296b6128388a5625ad48640cac171c30e689dc6593eb24b8f575e09438162d4ed215083142fd8df2f1a67770ba392d92a11fba399348aec782c16af5a41168b17eb6104fe43b49a7dbc01a4766fb962cd20eab637aa3e420a6f9aec4a2f9697ca26ceca1718843fa445abf3910cd92d877cba165d6bbf86aa5536f5ebbe450e62b06f2a3a8cb03dc5c198f5c6d90f5337789924ea67fbb0a07c8a06ff158d72f86daecaf9c96f12bc0b30a5e39c7e926bbe241f0ab69930aec2ec3ade0746f55fe3b18c536132cff870ac4f9bd0efe7d84df72fa1b6cd5334e8e2324e18da66ba979091080", ++ "slh-dsa-sha2-128s" : "0x563b16e5f93863fb9479ecda8e51da4c5e0b8c2ab218e682251dbdc02341a70a0bc0a8bfcd7fe676b4a88ed00ab7bad29a5226e6bec830015cc98a88e82d8907e4b66e4b39fab840bc60df099fa85f9e079a4afc0fb91c1ff5f8bc18679ec741add6e6a35870278fba0fb69e912c6dd01dbab121ae9568e4fb8d2be66f506b4094ad1e4a249a01fd55d6956780c0252f978308118de5a33edf8b1de9ecd158c4c1be63cc25aab2b1137868c2cc9e5c5bda02cb50e7a5ac5cbd6c3500c755bfad4f65bd913f3e8faf204a3851410354c9beaf9ac2b69ac726a1b61a9bf625e9bba4d3ece8511f6f2aeadf08fca28d772bc1511a4f3b659b0a8f3c6c8376531540a9866870faa1b3306ad1a8d26022a08bc2a90a4dae1a3b67491357c619df90d0b25d7329fba316d7e845f1c324f99a3f4dd60a0f58ee0f2f0d28efc4642ec3374bff548d20d150c31bebf560805bb61b8638fb8940def864a2e38402257a0fb446cee1e38e000bae954fbf1f4f26db7631bf01089f0d81d4bdab306e142bd1e1f356de670679e7d0f3713216064b14bb0f85a56e9b90dfbf0b1c81aa4968a855fd9d60cdf4ad35090e2dbdf8de9224d9fe53902bc02abb46bb568a0ad2db5a73673746ad968780621277519e39053252c9e8fb46d44fdcbbc973875ef2e3c991eb5ee02671cd1580d2ec9e8c8035638d2f5409b0343173a071b2a72a237f8bd4ccb5d080fe6510ba2b355b9d39b3ca12ae06f2766d634457455d72d519bbaccb2efd04a142c7ede443d0db7b44c2d5cd0a3a468932a9a5370853bc475c622bb5c8c52eba04325d20a396ed36e5d4a59e1c00861f3d0b0e08a9f778c70c7e8ceb448ca4a52f6e0bef75b34a5471a3bd668d5d693f370048c93657adb1e5bd768b5b38f6efe11f315b3e6e62358c28894ad8ff475f98584ae32ca9c56b39f4a9f3aece99d8e3ce5d2443441e183e479964a18d53aa867d07ab6f6d9d019160421f283678a0e7774820005020b98fc058076fbe1c65d188c4d5bdea7cf0a5d67fc39820c80726e72837bbccbe1c396a79ee29c0c23ef9871795f25afefc81ba91aedc3d6799a093a0c0d533e094d5f1fa60c6ef72a4122ed34f3ee5ba6992b419ca1de2a9585bbbecb2a705386096e929e7bff99ba7a5e33805288c8ac315f1679e7f055d1c63d3229a206736ec1f7585653c0bcdcb2974d9bcf9fb805a89aa2ff4f57e98194ddf8bed97e4c985313b6487ff4a4131bf0a3e86837eaf9caac911548f3a60a3e1bf04d6720b1e4d60685b6db4ccca66123d23e17f2f004354bff43c4d61ceff52748c197296ae3c8c6380baba17d00531bea8f4c1becf6eb6e9fd50c86bdbade0f4da4015f486f970a812c778fe413841f0171743044d6e77789f1bafd6abd4234aff922148f3dba40f3c194053713b9b9a3d7047bb849cb5a806740d9424288bea002261fddc12a6123fbfc3c8dfa26753e92e2f6fd14e4f1895ec36d90f572198427f65e92a1ccf92bed4f56cfaddd747cb2a0a6237325eefd74da45cb52df13c7e78e2c60bdc332d118fe51e3f17cb85edb9d5070a8addaea082767ad40a9778e46a61803c733d1f27e36a4d1810d4cc77757509622ba4464ebc3a2f8bc9c9e49a650450f0ea57619c179e94eae7dba9c66cd079f160398a0ed40f685bf1a405752f9b2820525dbf697e5c198905f09106dfcbca5a5bc62a72b2dc8b85e991871a8e4d7091fb097e0ef13c63f59a939c02b94c58ed9ef9cba75db728d88c81619c86d95710c5b51733a84b9a8cf068869464c35d27bfb1daaf140d65afdee9b7ccdde62d5d4e2d83ce670dc49ade7b85d1d8167893d0c68faa29d159ef95d4381bdc6a4234ead47a472e7f9740db9e1d8c5a4c66a84907a056d625b6f8e192a89b10f6d4b655e74ca6b01e6fbb2b187ed75b0da052713862e7cb3457df4202bb8df95fe309b8eb87a711767afb1a3003ace4cb01cf3de67cf13e24e6d166e763a8962ee7f47d5ae9a82b951362ff226ec3bfe12b188ab659d8fbdc38e0ac6d0a8c68c5ea7a273cde1b53d5063c5c9bb6b80e803261ba27bd88330cbe619a580f2554171173f046ad43e2e5be710517889ef08cc9ba4018b68edf3e843ce09d0cb226a2f84ef49b60e0cf97b70dcb84a353adc79bf8dd7682bb18ace2282b0d78ab1854bc7294e3889c8eac041dc31ddf581e9697256428c469fe3d2c68d6ab627bc9e8e730632c518837a25d4e89aebe1cddb015b57a88ac7c3c6a2f62f2aed77ad8e19edfed15551941e87b560f05b24b3f261230ef1c3566b8cf121271611632e111756ce0346ad9ff9ce3c8caa1796641f5e019420273243dc1ca62721a62c7f182a53eecf09acbf08afc58907814f0ef90675f634b6c4e565a157bf4acacab2c01e6cf62f0d47eb3ab93ad79f2d1661b1aff34065e6d7e39746b3d94d92670c7c78e04f16b63891675667b83fe689d18b348d640cd5dc302c0b7a149eb562f29ef317218d5958763685bf2d86f756853538a5e699bb3f0e58c1934892cacb9854e25211ac4dc4fb6eeb2f59d99d2dae281f2592f0ab8f1f4e59708751da251342bdd5864e7a9b563e12c74e7ea762fa2db1bb5cac5c2b02b680f27f7372e7bb7914403f267c0e5a8a8e7f59b4f28fd0254b570c158917245d976bf85419d8778a3f03c02f99f853185882ad19d3aeb2382185ae6ce0349ff3ab4b7b419c6647b0edf74588365339b4c22c54bae1522c82318225c44aff5341b13a09df32eeed978da9069fe9795cda0763c78ff688c1c456a550ff450bc29df105407859dfb13655d8e6063eabcfb209a9af22f4dabeba0e151563ee2a20605573c3e5bce979c420928688be7c5ca0c66d6c4760299fd0699a7b96be126bd16c8b57d2b3da3a31e44ccb85626c1a5845926564305db1575137fa505389c17c736d648c96f1f529b100123d7535cfd9e6636d167083b1f2f6462ff227116ceae90240515329fdfd232762aee1d9bbd50fbae995cc4c27f34cfe21c924a603564bd3443ae0c2a6a78599705cda7d8c1224adfaf1cb0f1b7cbf6b2f8e1d3e69e200947a8cbac5704613c041b9eec1a947a5a45a855651275c63bf96d0bc26c964cd283e5cc2e81f7b13db18d58fe5c31da90bcd5e03ccbd9b7cf4af67897e031a73f7661289907c57455bc2e77237d6959328445b2c666bfaa5073914220324c8ae9043548f2cb28167d6d22d919f6ef05c0b71704fbf0e6ef338290b043319013eba466edb620c14c27ec65c853d0f07e55d56e12295e7e0b2c7d0cd342a428580645511780193dcced94a2dadfaa90e789775f42a5220f13a7757b966219da9ebddbafa76281fb4e4f10fad3b2c59bc1279e7892cba7c78f0492b683d6ad565ce4cbcc8678cd7cc8db72b2111bfc5881042c1eecf57ecace2a45e83dd10b60deec32830a8edba51a31bd72abaa26e47a59d7db74612a52544f05e3989d93f0c25a3a3802d86f025afaad0c8f9383b02bbd671d5b308f7416cfd3caaabc7875241e5f13643022e2e80eada5895a48d2d4fb5dc190f197837463b6ea5d8cda125dce4e9a1c20dbdaeafd6d5c14220b49ecb149848c9714d41e9324226e6daff80949fc51cd0eda6290a75d757200fd1832fe20a3fcac026cc04bc75f91310e6959d417a1370cf88e132333439d5a71c9165ff1a6f1193b2335eacb42b5ba5540def54d6d0960fa1b37b655040b594c57ec6984b273c58228a9bde8614b8f6bcc874e7dbde109fbdc41684051fe05c4de5dc0bafee37fb2be501e36e4d8ea55864432cc554a01c4c202531edc612f41dfbd0c220ca5b603c7ed47e9be4145b1490161e31a2e6c82eace746e62bb8862a1b85d35af5286587c3ea6bb72444dad67abee707a9d583455181c0b246fd0c33d3522458ca4abceaae209ea5464d294837e7678150add9a37f3405a76baeceb0eef3f3fe7038980e96652c5e53d77b15dd8197f304bab443ca94d66f43d69f4c7ec1c7bdc57093893a67d20d89e587a9988e873457cef966d9270216e65f1eae2ad0d3bff25650d884ec197a69e5c76d39d77f7e5e1c623bd664645ed7df0b69e8dc3aa7e6260ed481ed07cce4405de34313561fa30bd3a78a7bed156fa773c0405cf20d4b0fd1cb60d58a2eb136dfac1e388def9e81a9d1f1f769be49d1627f206364c61c5a09d9d35d7ae05f8eab1d0cd633cc4d92fe1fb58ec4845c16e1578e80c0702471577e49dc9e106dc59c02b534f59b0c449a2ddca0f5590d4c34c5f877503094256f017c9a4a0ba613d136e07d7eeb3a4cc23121a934ee84249820bd64987ec55351d3602cc7afd1ba272557e531b3371b99df3528dec1f8d1d4eb6d49ddf94027b9390eae72f740ff649a4438448463778df7d5a0a5f764336a2efe509afef92610de6dbf22cf51381a3243171cfa9ca8caf6ac9f4e0ea6238cd7ef7bbd5fb06d3426aafe2bc94c8776f5ee74725b2f7f1e91b533ad9ebc626cfc5d2a6eee2c792602be3e838f4fe43e1851940a1e21d2c4fec3fd672b0c7d3e266bec169315a9960c7c433517484693894f71328b5738127fa6e51a6b0145f7316f5677581146028bfc4a6e3399037e6cd038cb993bd1e63b7c5c9020ddb57dd78da6b80b9593eb0252b499e66c0d3526ae41d19f9430ea7de2c8dcff825ab026e4bdc2da80340d14415f22a009bc7b325d615855a98b403a22939ddefe7d82f9b48814c09f4a121ed92575cfe32e04df38cd041fcaf0b1e572fc18992c182cc8ebe05969d90970ca0ee9b651fd65a4d002490f04639bfce86058cd1ed219457242c4c233e5a4b84cf3e62f45cf2f2e308b43ea17839640a7e93570a4ae3760ac79ee0a61290944fe47ad43c67f01be52d639c85b3b5b07a9aa98b2e7cb3dddb82d2a0edf88c38b4119bba29cf812970bf79629d295c2764a3d3c8b20743e939102f6584458ddd1da577b5667dfdbb350b596f565d64040eb16e6b00a1c76af2e6ccc18273c3075b5bad660017506a24b8fe728cfb6531c16c92f6726127e93e919bc4a018b29cab8b098ec0390106d37e73e14d647c00a723191ac447819457e1882e7930e147aa05c6a6648d073baf7e0a379cf4a079cc2aa7111ea0b81b6737a50e2a02c3e862fed198020f295b1f0a2fd42a19d69599f3ea4263b01d0899cf13509bc2f0490c78c69cc8182d009bab3a84d12287890ce43424ec7fbbfd0daa76f08fb3e0bfee27688ef5ffcc366701539cc87446ae2a0d910664626992cfb8cef95990e59ab088db3cf5d8303820ab67a3f463c8a38c054e1791c1d07e9f2e14ee8d1138ba4b2f9763fb9faeac3679a777c60048341a9c3f370b855d4125e9597db28248e3d38313d18e5ead92def8d04f7b286c4f05064a0137a1821f5e5da38e69297b9fce7ee55b595ea05272509dd1dc96fb28e35547e2179808d333aa357fe87dabe64cf1c3fd4dd75bf30b9bc7d4135d3432df069f5b60e152b287e3be28f552aa867b58e47574cbc5facfee6dd2f585356bfffdf2abfbb13cc957a56b0e47225b9df42c4bc44f7da0cee1b64d4bea4d7142dc18851a86eba8ca3a632820088d1d0f277612181d33e66554a538228cfbb163174114fe8b5b143edee891d6cfc697b0dc486b384db8cbd20d1b48d43d254a5174adfa368a793f060c922a59bf309954546648d174ad56f045f9712d2a064ab37b05f92b71f3e11cee5d6709e8c79b501b103db8261574533fcde6bc4c26b257ec4f0a3a237b9ef488e17ad5af95fcd176452d1b7e20106a2119508d9e74de932ad79c4c608f1ac76e95b9ffbf9637cc0267b8ced6d139103528fde29e1df10e5adf50882053986d1670d420bcaa3365fb662e0d433508db556ca2a5913eba6cdef737e856c2a24be7007aed60ed10fb77b7e9b339a1c7da723b3ffc12fa12a012cac3b0be1e4a317b17247b5f1102e006c745fda650ab1ace51adbf3bed3c15281ff975e2e7cc58b7998ae0dfde1e0c1376343d0dd0aadd07d8919c296a7cbd4c8265ab3e0a4f5c1f6da51d946f9bb2b00bcbd134335691ff4e797e9d07779493d88e1e91b033479207e36e76f1d4264f551ee2a9a95c33f4c588e5f3d366e2f187d8eb77ebb3f9acd757d7384aadd90392aac2b230804502cfaafaf2328420a41c173d903996cdd87366a33efdf9d565cb0ac0078b2f40cdbf773b86ea3f44eff5b86e822b536dcd72006123a4e11b26d21120d8b250b8dec716b091b1eb150857bc64759f31d7add4b058841193c58417c33e9238f4741804f9f148096b15ce8cec22dd2c4636a39e86eb1325dfa7ac87e58d34950a309b4c513a7e14f00cb5c8b6bbbf3487b3bf9f29ce445a9cdcd1eb402724b2f092ea52ffcc3b24a482a24d19f89d44afc6e166082bcebafd24d54bb5022a08a2469e1633edd7832e6c74e5d9976beebb6928620c9e865991d093313f4f24d7e8d7e63bce3e4bc8ef79be24f2b7278dd84e80801d304cf3d775e53e8f670fb0ad4dada5fca06536f31ab452a7d1dbfa032c2bed87b66d0a7fcce064a4a28b60a7e626605385b44fd54286ce871212268ab65415f69ad0f60062f8f7e46702d5f54895d9b2e7c219c30f1a32e061fcbb5875af955f73f2bb31db7b282aa12dd0fba2c8e469aacc6914c230d499c8b7ba92572b19dfbc2ebaf4ebec1842ec54ac05d95cca796beb8cf14f5fbdd8e4baaf2d59833b5a329e4fc3f32c730d5fe55124b1a7e4fb7f64f63f74cf928552e4b5eb1f2976a99198925c0ccf5ba8ecaec313d216e7adfb1fcca3693b9e74b326551a0528c5097e1f34247b5eda7bbacbeb21fe6491ce67c3c7764cd798b1fa813454bda9e017b1c8981d95b3e65782f89514d93a0ae33ed10e6c8897a3cdb9d01cd0e0e12f3b398ec72409a4adcb18c7f6091823079782cd68ac017edd272464805f3e831e06f02ad1e1da0acb7cd6807a9b80c29fa3b2ae5b1b75b43425041bc26cffd0c9bd4372925f3ebca751480063084a888fc9c0bb5243dfda4b4a9d4f8dae59f4eeb768788e4db8a601082ffd3e09d9336d5f339a825676c3e3367b161ceb3a6cdd80ce650fa711452e886b1aab4f4a92f07141ea3c28bbffce0bbc4b4587d4cbe42b3dc7d92d0d3298dc751aa71ff7aaf353a75ae3f23363cd925247660562bfd43348a7fd2fe33b2c46196a0b7f30ae843f32c3141e7cd523963162eaa726a8ba34b6f34d8980d8a69df2a103e0462d9d57faffd6c1bb3967b877b9e319ad357fa05c25c27c823025f246086de0f60d668930a5ffc304a026dd3c06a1ca2ff6328dc9046c28664087cab513358de893da3fadb740618b5e0086ae17aa8ae59c2a31592e21287e600fd14a4c57b285991398298944729029d979811d3784484e2d09a883636be1cebad5ae042187b62fb858e47ee7b66eb0303c3ad215f3f1877e6298bd439d10dfe2055655c68527efe9fb5188a3345959a36d49e3fa5f05d1bf880cba1827de4be26ff650daa1f0a4727383b2601168996303c550cb8ba0fed5d739905adf7ca5655d34a953cd6a6f47110fe9330b831bfdb79213a898f1e1e719786407e10bea78527c94799458c64706afc3931426326bbcf2490db4fc85960da9431b9028eac16664559c32e55ceb99c020126d65943eb4eaacf0fd642a1fdc2885a749a53e27eec2dd4927ca58cef7be2fddbe7e3c6a9b7f8a1a047e1720b36f92cee110c5cd35fe4e5fd88902feccb964953059a00c783d7f8e480955bdaf448170d2003e14ed223c2b9938744e1c14a619bd67c306df9bb00620cb300882c2c48de11e512fe4e249ba69aa527cd718faae2989b9306144e63ff75543e2a8ebaa92b19754a32ef4d4174c8c25648aec0336af2ea17f85096dce5affd0a6da6079cfa04c1acadda7f91f1a15f4d2fae5b3516a69c4bc0664066ba697de2de4ef233143119f5ff216c68d9a37b6ac5d24f334851c147657f0de1926c1b026b7028d54578e46383b4d83feb0fd1e366e682aedd5eef12b35ff8e192f82d59db1e82adaef5f0e3138d5b408e5948048df66f20501013b5cf09755484236c6e20e98e9deadc7c6280c463c002c274243b85fbf8434200f8f6621e754a8b1dca5a366bbab3fed0e22cb235ee6d8756908fc49a72cae7800e9cbbde623963e12a1b1c01e2129d65ff53d6e363da80b47323d15cfe7f45bb9f3c1619c59053584cc4d68d586c35540a907d590b7e076176609687af7f06f811c6393436ec08767fbdfe08145165869dca0ad295de1d4b170bb30b0184e92f40b3b0225aefee2ff8d3a9a94827bb185d48bb9dbeb2169a377b9a9ea40666eb61009a41756c7190cff6db52152119e97c919f9a327bce47b0c8ed157207cadaecd89375155c9ede0ec95dc336e038cfcc3fa6a14ec85371cff3a5e28086437c5b4f343faf76f77980f2f35d9592b9549eb94cc402855d1a88bf04a67484e9a7b7425179ffc5d5f8eb6474dd76d5f64c7cdad8e002d65bf34b9a7f597a515e47060a21ec853eba88bb8152ba22e682ece98da7b90b085a80dceab5920668cbebed0acaee891d7b16c5a5075fc007a63f954a5b8ecad07ef54ea9ae6d67305591f6042fa1fc5d092300da6c97492653d2a4b1fc3611f9e7222451ebf33a836d153869433466957717d5a88abd01f94783102efd01116d4f25a5a64d8ad5946f4e798e9c4cf7ce615aeb0bda6f7c9deb632f3be4283fe8e7a45a920e15824b8f354144b71dc580fc6c1d5eb5768417eb99149a177f07dd61216fb1f85e100bf2e8c5c4d73055d19ce09e970085d2213617b738ebeebfb386b0765e2a5d0de3cf7cf147859cd9b5e28e388f2b9d1de6987fdce0fcd20ecc563331290fe28a4e1de9c327829c4c69bd18745a8ac8f9a0a8e4ad65b07495a63b20f4b2f4c8dd49cc43d9474072781ca60637837eef9a2c9596701b607aefd8c679a3c714fcd9a85f73108c87662a37376f67e623bebe30995f02855d216a4493315ef3ebe9160d9ee0c05cad991f7f42def8d662a144d5222a1f3cdcffc0ec111b3ea555de6726fbc4d0893bc87ddff378628049f1fba03647d13ee4f98815843c619b9f02faed2d3fe3da8bcd4e839ed749e3c5834597ce1e2892ed0d443d8d983aeb8fc69ad80184e69791cfeb634b98949a17ceabbf7cb2e85f7d3d771d5c9a23f327c4ebf8ad8495830d2f2f43b0a500476c5a37ceb9d475a23f15c69e07d03129265dd70a83ce8a5cd40e929c2494830897e41c62de0ff8c8dc9afdff4844b28d4acc376abf59dbb0d08a2f01e7b622c702dc514bc277a1129619cfe00cdec4bc9a60383f43b79587efd3eb9bba9637641068430ff7e7c62ce572f1679962ddc524d200c07d427e6db62657ddf872200751be788d462723d1712e06017f6fec18ecd978ad377d8db8661478d2cf60847baa34dc43e1910482d42c02c1eabf8f3a3fa7fa8566dc61756c246c44a2bbdc6378ffd6dc8e35242a057c7b2751d8f537f6596426be24bf89cec38c7133fd1ee024e53321bd787aa1d253b608e52328240618da5d45af03710cd1613211f87768ab518bc4f1cd01254cce9c151b2ab653c1451c72b9530142fff1bd6f409d8f4b4cb2c589b7bd65a73aac8980d9dc807856e37edb7c31e27fc7eb812d5c39d8f95ef26626ba580b03390c180fbdfb2a3ab2d6fb563c51f49e9a10f25f46289e74981e019e02775918fbe9a8cef65586cac7b9020bfed88ff27d60174f73570053b1bfda473050b015427b14d561f773c2f5b4ff4e7eca0e4e7177e811e6eb60bd72b1c0459d1ef6615e5038d7fe06847ab24a7f41d1593acb4b54d8c2fddb6ef23d62b0246cea17a1cb2dabaeda2625b1a64b9da3b88496349c41b33935e39700913b23ca60b565d961442cc8c7a8991afe7734965774eed9fd267fa62ecec64f32792d9d0fb19d8e666d852466da5a73ce68275785b983d16ff3849ade8adfa672743d923858e886fb344f653a0247d40c7b0b87a7469c48d6056c340eb8d7e2a04b90930801424c6b9b2547486595f505a89e1492d015e082957168fb103d11bab79cc4852638193a855fbf35294ac690bd295f6fbc28aaf194e13e4b76c6d05772a6b2f8513ce2c03d884fad0df46228e19b940398ffb09c3d5300b4ece8e71bb25485d0d44bdbfee6655bec314759e46e8b826b98692b31bfe2c817e4f5d6cc87e4964770adc9c60178e5590b31e9880c80ac9125a972b04f4e24b1eaad78a691f70823dea467f61a7b308f8191f2b8b7c006e92d950ca5b8238f20ef75c28f81180ce3ae09e72db1700740e7a252ca957ad52c4a74eb8207d3eb9d053febbe48b8640585a2106857144a1c2dc3d12af55a97bd93db5dea31a28bb94a64a54947f9443c762eb8efe68499c9ead28cdeadc913828f00c82fc4bd96aa32ff31975daa9c61b4b6349496292d9b75a6f0012280eadd9853ee4d0130cc57b0d24a0b8115fb5241037e91b93142810ba2daeb6e2ce3647f367111082dbf7083854d395b47999026d112aaf90db3109aaecf7ce10e72ca13d5f6da166e9a938fe439230abb58abf47d72f39ea60436f0b8f939d76832abdf58f07d90776f29101b99c808d44ccc7fb60ce155cb3d2a38e5d4f215a7ff552cbcb64d964f1c9e32242bef9175437cd507daf55dee7e3d48f4c0c5799f2a692005c7783d11eb84a533e79a1dae908b2e8b8924b0c9819f190b3f8ce61bd3236b2d48025b2e707a2a64401a821603b79329d390c3a75aa4de23ecbcf7d90d32d6a42c160e02843ed80134c3c542e16791b0a60ac2d3df46e9079d3eb37b7d220513a636c9437945022c8b9305d90953d478bcb956c28556066200109faaccb090c4084ae2e8126bc01c9d07a7f6cc2407d0c4a56f11b2d69780ad0c6295cefa259169800019908cee9d52804c16fa34b4c5e7feae98aa5e1ce7c7365ba499fa1622bb5338b1fd951134e48e4bfabd055263bccb2f204a710dc531c7abc412c92cde71b096c9d4d2ebf98d33ff42c3a30699d14f111062a78b5090bd27f3cf3f6904d81d4cb8a19a924af0dc45253d370c5a1e7dce7a2d1457dbf59eba5e4a17545d1c86acaa4805e4aad" ++ } ++ }, ++ "2" : { ++ "id" : "0x41f547a71d1404f147606491f3b96e49f67d4658", ++ "keys" : { ++ "falcon-512" : "0x09b3f618864123704b78a9552a0b068f395444870c2cbd5d741a0c565554bc2785a691ff502d6ed0e14c925eaa24c075d20949d12f369848e178d50b085e87c9b251f68b61ec506435bf5b53a49d299409f54e906daed0c1a25a63563090f6660380321e786311b492bd7ff684a2650bec34d5bdf071c49f5a050415b2c3579b2994fbaa9a97b7f24a30e7e8bba68145196e0424471de31775aeca732dad506b16ad4f61a325136a6664f439e60687e764a009db3218f706785b98b154a625c168fa2ac541b8dce39682172b95e19424b98ba985622b2a23d8db2d46a7230bcb667372a924aa4d1a9e9cc1a8dc1ae11fe88081d74d857bf63e9814a08c9ce059a4b1ccab23a2fba765086b15bcba135d0937a064b90663ec69ab521746600610bec0a6b3c705277f90d588a00e908dd075059de6c52fe05fd8fa8ba1b3c2cf151cc810225db79aae0328b8ea1e92fc67b7bde405a1442128023128a5f7089722b954f15597ebba3aa3b55ae947be1e659be52af04c3205492387b51e72746a904ff13ae41964281ebd81783528269ccd6d2a7845d790fe4cda8ee58d93de3a3ca28bc4e6e18e812c313452a4468049a86ae39d5fe156fa2a43d29161bc911d515f4cb6b625f4679e37d5b55064a16c3e48a7f3ae10a09d9ab7f0ea4dfa2fba9da412af1978720fc47185c7ae16474833c8d278dca65b822c5526bd4da67c0700166cba95e3d23691e6e1e86ea4e560cddd59af18a689c4dc2b6dc0e114f2a84754498a8e299ac17a12fd199d1fd8d5c31b0a40ef4b2fc9627d16ec11241fddb4fee6c652d0119f7d60e852decd3489cdfb75c10a18f562154e542614427ee7cb0e96b99d74eb9585223760bac37de51697d86403ac877f823451d8c60e84188a8fa6804c3a8298f223169c4c61fe443434a76d6a51ccc1d06df3b962fdba9e27d7723a8390f4672d66dc2f756263ab928d9d14f6d550acb286647ed6dfb091c462cf4756194ebac9c94bdf7ae4ac7b5093ab9cb94455dad8ab15b134d31947df478a1aca5e28e98020dfdb6d4ab750911bb2690104b9606e78c8659c2f511bfa3254d32e65aab180ebb74f9848700a8cba3a1a546b77678a17716f232e57b204157761161670bf654f182a14bbbb1c16b14b652127241167e898e097b6270b062f0607a50bb040868768a24312a8da316dbc547237ace3a160b7835c805061f8f2723386929835251945908058905f625cd9a91eea83c0f693523128c68613038e", ++ "slh-dsa-sha2-128s" : "0x9fc24e59b10d63d59b6c448f79d029745c4f27a31903ad2a6f6fdd09b3abebb1" ++ }, ++ "pop" : { ++ "falcon-512" : "0x39916580739423a110970dbfa8b6f06ebfe827b6503b1629f4008d64024e63c71af7a932f3f29cbf08eae4cca92f36f670de2f3a0a461999f431bd5da16b868d2230d6403158010384f0f98d2b95936e0a132f5b86f5d11e32ecf3cf206ab9d26c1cb7fc93ea3468109a59163b15391795b76ce450813b28d28510767270c1c474632bd6eab70174350d329d0039ef8fa6739b2f665fff021cf669156e3797da72e5913d08c94a48a16d12b5ad7e521b730bef92d7cc277a92b3e4c9f9cfff7cb3896f93dbd495637c2a47835f2afde4222c8dd36d4d6d9cb419b5b5563bcc1a61b640e70bf2c4bed6599c5ec50643fa302c227ae56adc3d4b044926f4bc4b26d58d0d0778e2b8ec5e18b5cb9ecb6d7a26808962082bea23a932afefd0d483a9952f98ea11b629b0ad74c367e09cc016b817b624547ed8fdf360a8a06acf7b5f0d3c92448d9f7e9453a4e29222611490a7188dcd0a8568b67d333228454cd9cb99fdc9d6d945a64d8d96348120295b8f2ea9e95f92d9dddfa2a91b6ea2c44de7b605db8e3e1019dbe5cb464e0b211713cdcc32ef3631caccb48b6b0c968492a5f1288e99ada3a4d8287b5c9f46236b4b3fcfa55135f1ee4b13e3d6765866a316d8cb3ce80d67a518ee974976172f91eff1cf973631ade2a2b81134c39d0f3c72bf4fe546a7bc7d3f1142aaae3f5b4e8f3932d9b516ff1cfd827e7395d576d96cff52f00e76abe5ba3f1f0887fb064ee11096e52d441d1b4dc7a69462acb7296c489f498c456b2336f2f112391bd7e545629697bd096ab373a34147643199222b8f1b05a95bba5877aeed29c43bddecbc814a6f2bb38d1dde30c352e06f19bf52717236488848599eaa1ef17873681e91064430aa2f4a23445fac0a8c8231c8cd7c27f928ca0ebf7ab08feb53", ++ "slh-dsa-sha2-128s" : "0xe922917f6a5d9d49338e445586f4b3bfcdd92b89a013edba38e598aad56f8d10875fa62dddbce6c66865eb7d14067931d640a3b7c5dc448bf7cb6309943c2f0930c78c03fad2cdfa1c21689c6f621bfb1cba1968dd28e66ceb6cd5cd4f10b8797a53a8ad54e93febced4dc1c48fc4bf768b85a811866f86f004fdc340628ccf44b295fb5310898614b6a0341a2456b94930d086ee75f67bb935e62c739fb87407975f78f372ec11c0bf8bce5144abbb2678711850174134e6e5acc3b87f14022d158a57dcc7916a8e75341488af6b1d9c0af90bf2ea86440fd1b8001d7fdb8ecb8cf392498e41f8be5c7aaa81841aba7422c45fcc0caadd52d36d1d56cd02d027b6ed9d122ab3d53597507079bd9fb476105b12e3406c1873a8bf6a5b9479b5cab9c370b79425b1bc7616e2f1f66a398c2e38f7a9ff1077918fb3f7e65f025d4feb8b13397460a753b1999b3d351c5b77ece3751686c02db0ea4ff23727527cdaf038ff060a09689a13fb7dc902cb82844b11f8092625272d8888090e60cb1040b6cc5b0ceb6854a7fa769a77523e7a718a1a9cf56b94be12fe8fc4d319b335757c6b4807e17e9ffdbb486d9910404e675648d069c55e96894c7b2ab17d91aff88f44ad609142ea3747117596c98831338c616cea7439b1754390604188018818a5fd2cac7522b2df5e42c14e77b7383744234da5fe1a02a60e18a178751eb9c0212cd847317d64dabe4407c4a4d2ccb6965eb33699c37c733d42e66f92b01cf8b0ba2c8d737711439de358756ab4ba374e7359f8ec5838f531c984e2903026acbce89ff2935855ba5e5f3d85c82bfc3975ba3d4a9721ffaab1182035bb7526f062466895c5900f854fb52f5913591828cef55cd07d70c5805327cccb9822860f32a8e8f78806e39d36ea7be59186da6ab5f1739b6716323b9379446ce6e50345cfc9b769162ba96929e2cf0693b77a558e5386945fe5c6410a2594805695a4cb602fb25993a0359753f4ecea67d0a1045a80054664a5f589dd823d11b1e440813b3bf141f119c38f9595c1eec85ce74fd0cd69ab783ff7adf32746d3c4db1153df20ca1ff94acfcf3c8ece27b9a7819f7751028435730771a0d7eee4d5a05627e9577de7a1c0d16400a81c6d93fe48990d8d4eb942233b6e81f2606c228423d52fa012ba6de7c24ef446f32ba1e1bee5ab78e79f40ddc3f8279277735564901682f03ffbae6176aa8c2dc6871cdea56cb875f25c88d955ad2e5f560fa25acb5d2130327aff86a324aaa721874c4276667404738fffa534f26e4e0dd67a9d0e5d447c2868af3f5b93dad621f528509fa6c3d2b9a391275396d3db6487ef219bf42088433b79d34ce793f024380319f1a0017c0cf821d998871fd35d2da47b774f6c6664e54090d74d087fa43ca622417314ac0a7f2d23da0e9be5242191b9096ab0e200bcee276a787ecb770a60f975c2935f24600869822ce96462d97f34c23eaa50b443a504670923b260e1698eb12a76a094b9a8b9bc2fb07c38b03b495a70e4976d05477ee88b58e2d66729a91f0fc003e56236c5285869a6eba073b36efdac3999ca0b91408282f83b179629bebabd5355381c4435bb173598ce3496dd8616eba46505a64d29a166b51b1033cafccc0c6cce63afe4f2dff7a2cc62a909853b14b40c418d3a180a922b02243637700c87bd0268e3ba09730a2e2e20065a7310d8cb86ae6b2174454ee4c01fc86c0441cbc51f1801a021da1f1fa4ba6cc0e8e35a11a0e55a4aec60d5c98330ea1822991083deb2a80efaf382d29cd0b04fc2b3289e024814281aad94ffde1a837da103a0022b23f223e63b852ce8bb89d50271b29b5dd805edf1f4339bed98ad4e4fa42cd726f3f70c7c434035cd9180a02ac954a1173c2694f0cd59942291c34a8071803a69552d71b8191c4299add494d05e838803e5e9de4e5a2d7b0f8b4a221ce677b5b365e57284f4b74c973c72a565422b2233a5b3770cf28645a18ce1bf7cd0e726566c382d801e655829a7c5e2aa149217075014492b80533bad2c8013c382aae26cf4dc39a6eace929903894f85c8e97e4be1df2bbd53fc780c46ed384e01fb40c515e88bcbeb2005df6c152f0d169a90ce3a43c2c3469a85a456991996f6e9ffab555233598f767b38307fab61336a8d57c1f6753749d46e1b3032532a5ef11082cb30e12bb6b292d0f37806e6208d4bbb7c7cba1b3b410ec1d29dd35af7d38ba79059999992088f06b587bd9570ad0a1e2352a6133a50a3a45da27fcf63cb7c6fa98e6d3d3d7987447fc596edd9a157d72d0bb60441935481c54f9c163b985c708ea1dc510f35f9aa8768e73843ba5e8621912f43383365f534f3ceef986e90664123079f7355e5a5193b0ca1bce0443e01adc00f18f8f07a9038cfbc672494715221c0b8c5dadf7a66875ad67300e5fd662ae7b4281f2df29aa0f5b7f9f70fd3180d7875aaf784eb3da36f9fd8abfcbf2f156392cd196ab952669a531bf941b48b7d2850cb8a66addeeb1447d89daac2079094bd4163d9e0d8ed52e9a93e31a7d4f5d2afc4b7d2c0b988d41c3e247237363dc05dd16d49d159005b42ab9def7290a51beb7811e9f4fb9961a7af09fd4f291f797f8eeb05bf76884ca340af07f62f587dfcbadb344c1b350960686aeecf772f59d3f5c9f6c01240667d1fa5c3d84dae1f0dc9562543e4636d81a3f0407bc29127bf4b4527d0f6d7815a941fb53e6527d5940739bd369786e710f6b0f69b05b2e0c49bfa51411319b9f7b172fc11d901e41ec54887a0fe5748b1d2403d23ed5494b96639126c1d3fde11d85c8c717fe8b01319a9668b109e2d34a6ef5911aeb31c88b71c32a6723b0ad2a28b2d8c75087a546550b0971dde64d3cd69434914d5544a8828c6e7775cc802fd71e467e0327d692cba302f681fdf0c7425ee580c413d1a3904974e55e7ddb19de793541a7a4310e50990744b4655e72b4eb5a3a8c5fcc09a545198c6475dd26a43338753855ae4dbd845d3122b16063b9d4f1170b0fb1eddbe15bf6a0f935565ea46bbbd6c00491a9ea8288822dbfe8788aec3eb3e5e42140fe3cdf16328587b736242c2aa85828dc84352bea3c6d985ac48437bd72f12adc7fc08d03371992547b91a3061c9f9bc6c32a8555df262c14dba813ae8e2f9c732bf7360b1e94498f5a1248ca4a0c020e381d8c25f4924f91bf0c649207b1314bc0088d2f15f662a2594962596ea66c036677c451e77f051cf9c5f6b83ada58109f68b415af541dff5d6cba732a938ef4d425243a3571f475af0a456a7ea5afc7c78fa195780b270ee1f4d69fca7c93087e103595af8757afa5dd23ed17bd723c1edf8701a1b4bcb2102ab2aaef2df7cf485370d310651f6e897cd2d687375d29c7f101aed941cbbbc12ac7ad60c3147e41fffafb766e548f0e96bc911f38a6d1864277c170fae28e4b06fee1d1925923432bbe28e41f8cc19271f68196bf4724278f8492a6d5c0826e03d8dc1232c0efe5c7598b71be7d6c468ccb1077d7c8bd4630bfa4a108d58d5498e40584f6ab690e27ec8152c1c39bb70ccf7c5f2c33e48af63d536d9e7ba90db931783a9cccc05c22dbfd90f84f75d139aa22b1246a15534f1521ecb9031ff0686c39b728fcf6e0323cda56b641561a88c6f78cb1d880d102d26b20213d03af41c91ba6924a0ae17a92fdb375492fa0b514ce2fe88fb95d72e5b1b11bff99d1b0ea0832a0d3472b5880b3ddef0bc0891833adec1f7797f86fc549b22df2a0a59390a900e588cdd2405e5afea987db98554585c85fa2428cababff59c17713cfb100084192cee9f4ee3855163ce76fc59ebd4b23766b0ca7c2d59754ca42ebe3c997cc4cdcfc2ef455d3afd488474b4da2a6ba278c196616f995c4398710c291efccbe36bb724bff2d097095f440f79917229a6fce31dbd89e58696c4571dce1e535adf5e1b0942fb5d59a13f7fb4eb17647e83e587acc50d920db2951bb48e1495256e10a62a8d43d3cb7719c54c24f546ce4937e2ba7b1911f5684068c365398e41f7153cb1e2b9ac014bb7395a36efff14ee94373dd128d725dd6ae6af408a5da12ee540fd8d2264b24cc7fffdb2859ce5227ec3c3d5e0bae49b5f495a39e5d6b3baf7c967b21a55e3528fb0bda0e9f2a3cdc37904005a76b07d044ce439a345f5ab69a3db8c711d478288df2d4776d53ccfbf49a06d0d0332814d34053c98ee3464bbf46309b763114ddf1073100c34466cbf3414b4bc7b8ee73c44d76c46435c0354a71fba7d8ba8b0248f867cee79a4beacb5dee9c45577e5b423582fd261b6164de192e98aaabb47179a6fff8827221a70c77df46d01357bf27392d4dfe3b8e24abe9854d3109b533edab16f495eaae07562dfb4428cefbffd748f144329f7653931a9f65a3b024bf19d2fe04764d53730df662469a19c4bd966dc925b1ac52d9094ff7dd7268697468135000a8766d8292f9079f9bb5601193df637f8192812a9a97f604015ec15c89fee9f700509cd745da588a86c7c756bc84745c593bcb7c7d9d34bea98d505a57b31a90833e3d1e154c3b686d5d8a20375111bfc6964bdf2f815e160754b56c59fec8fa533cca9e21d4f688ed94cdab427f9e179fd308856ab7f7206d13d65cace5f8d65c8b95270559a7d33c76c81794ec38d75e2b3f9ebd1351e07da0540e3981d447558d6c21ce6b0c32bf61a3f554cae9edac7a92e2e25965037830c57f30a021953d91c8349b94181ca8c3bec9f33327caa08e437e542d4cd9742ea16801aae94e19442030e8c95bd4f23d88ae9a1f1cfe4a80b046f2e54885c54572a215f17bf8359db4edc830c48941153bdff79a6777a67a9ca0ee3c5d2e4497871f4797974c1d932fa3417b909ca5b29dfb315bf1590829f1cfad84b9e068213b8a6e9171c1c41757e262d371b7073d1b90fde5bdbafab76426f486581bf52fb2a53df2fdd0a6d5065afa6148606a3dd311b155dc0dcaf9f741a50d105053225f1c223ad0fd8af47d27db808cd32f733fcc8e2655523fd36a906c6e6a1d6eba56311424458b446bc1b77b866af76be210b9a417e87903a1ba2e431c176a82cc5a71a4ddf29350efa6dd8d1707d3884b31b9b52bc876b6599f40b077c43d815d2e02ba043505abe7ecd7dcf73818ceb77a09ea4e582616f4af11133a80429edc9a434f3cd2b41192edad842b433ee7936fa5c7680023f0727f4337c53912fdf6fc7e6d5c0dda2e0a8722d5b0565ddd8f9349815bf38e8615b5c7ae35622d7feb7907e6423c8aa7bdf57355c0353da377977e180b88ecb1faaeee2d7142f342263e636eb99c78af9cd0ef0314d9b57fe1176bf8b13c221b5a05c1f876194ac26c35b0ddd91a2130276ac402314367d99c2e300a33073c06dc18cdf5361908d58a9553268c6d0ba19ef6f6d0bfbf2b1e2f5d284c74695189d8a3236e927d9598a4be253d0492f98015851be3693b0c1b3c4a73a95ea57c20699240887d501db5d3525e787dd1a583c2a831a9b59886c873b8ea5dcec376ff37fdabfa21b74b3968008dfd9784fec35696779217b4f5507ea15852f751af31243dbf857d66cdbfb2e290b52f67312fe5d93bdba25b1b7dfb0f3488974a7ff0e437cea09d0baaba7bbd2506fcd182cf0dabe7c262a823fa1dcfe00bfaf7cb5f54283763a45134dfabe9927fecacd648ef767fdce12d570693ca6aa10c74c41761f64f31139f3aabbabefe6c7bd79a6a3334cb465f4203604c0288c49db25bd25c6c4c113e09fbd65c0f271f4a373294831c33f7b2ef392e4a4b91a3973d38473b9f3a485cdb04b7f75a833e2c0461c6f27e6d8f518d3a4366ea3bf37f43e4408f00c4c72ca8d0a9fdbf1ac7fc9fed47e8a3f3f33ebcbac25fc2e70bd39a85519181383597ccc3503e597a734c98e98a15be8bf4b37330f585ea138e5a2e4104ec1cb6f5a23df7ad83751c32432033f072e8ee3cdeaae4e7de98f9e58633bcdceab69ff60004cfdf51b54e9a33232e1df86ca9708811a69b8759e5b2daf57eaa8f1f74ae6aedfd9106c105a6cd715b66f561c0a0500a501a9f3d50a0b5540ec96d24fa5f6157f5465d413b204a224e2b752a49322a90aa340e4422e60a449cab5b6106135ad34ae309ada87ce9a99cab959f6c2502b2da99d8ef296884f4255fa88f38908e4294f799afbf3d664900c5230ebbec54328167495caa99942c13e834da5c488f2dcbbe4d2448eea2657a2f82a91a53d09b2b5445de8c8c8ede11f028e067620f2ad83be80d19f3b9a9f3b81bc8a405c233b2b17ce8ee5e0ef05847aeb36f219817d735faf6092d13569cbf069696bcbc50cb50cbef921f8fe76775f1034e73bf04431b696eae4943efd78ef6c19436c76ab389825e57b23f4529fb848233833afa418d85a92fc865e634357071bc415da56078f44bfe306d3b00574c04b2e94d6b801d5e3bc03686d1bb27dc2753112b2c22a43610a4dbe1e78c9f4f6f2b4ca3ccbddc2ce0e78fa34cac5935bf0867bf14f40648c805876e61fa841292ef2d2d53ecc00319a6df0bb6347dc865e39d9da574ad93f9cc910a9eb920986d5e6b331cb29b45ff32ddbc9e09b71eef73c8673307d6684a34ce85ff3a4208741b205d31011555b17b7c5effc210ad9309468a007d76983011b88c818eaeb3d3815a02d76f735433192f1bc99a6c7dbb57e107caf9e986248ebcb2e9c28279ea1e19a8f8027bd6f8728c9aed0b974322254e686526cd9ee0c6720de4eac01cd83e5705570c249856ebd7ec76cddd98cc096fb93db8ed86a5aa0736c36d978c09b915f7b9290cc255ea1a4b355888fb96e506cba34683c6a890c77d92fb01bba6b69f91efb3e4313111dafc3a189db063195bb650e0cf353dd975fb5c286f86b8f7d982ca5f74a78fa0fa3d693980be09298bd41c4ef38874ddb95e928494b9e345525b00e4760a1d6a4d54675e39b1d955e20a58f3ee65ffd1e249eb3558ba348a2be114f396c422c57314ce6df0ae9406dc6bd0bf5f1db49f012a03834b3314dec7839860867033643aa7dab3fe17ee025812ad2c05484abd0bdeb67043be2a57533d294aa03f24ec8afae512537343eaa16b07eabbbd2cf6755261ee473dc457ec36775102e1c8150248e4e51dcaa6abb7753920bd5247ccf6dcfed9dde98c9f37938d1c824fce116f39f0d67ab9c1fbc79e034e8bee6f79715433d485edc70e5c098ef7bcf2972171da06cd2f19cde8f824e0f2bbcd816f7eb87b7bdad659a900f36df708d3446d8e412b92142d8414f3a0508d106473e809a0831953e2064c655519a8f22fd0c517df7ac44d72a0e7b6fb697b188133fdea4d16e51c6da3109f7cec1a43fdf47957a35f4651454ae04da9e9d5a1668f46cbc58422c38fdf204f4e9c0df3b1f0ed2e14d0e008bed642353ede25a5c25684e7d593eee9d14b3a5a81429b30895ff5d1f7f4a124d2fc9bc1eda61e8e4bd73b57ef1a168cdfb1ce1d70955567a3d949bab203c379e3676932f96c04ddd0271a6afa0bd55988134de26bf5d6c725c09e04aaa03d393a82805a366e0d98e4b65bf45e05ce45f4dbdc1f8ec052102df08f5852630b706dcde9a3efebca3852e85cbd7fb6e6e00b4bb397004db1602b7f8c0dd365eb2d946d00eacf0ecedae83d26555a1bef8be88eee9de9f9811074151f0cc747f36d45ea7290d53c18fa8ce73f77f54226e5b1719a9bc911c9d7565693836edeaa6cdb7b2e2f9cc8c86b7c207cc14c261793df6c4c623355db04d5eac01c011677d26b764e9048bff8d76e2b6bdf792c57e044eea4307f5a3a62900df3f57ae88577644e2121134d61bbf3100fedf83371438b7854d06340ffc00383a0a4789a6a85062aaad3761dbb3c77e61c5926b0488f711a77735dce429b6e028373dd341fa2db5394867242331168665b4d7fc4ef96b12a571b8b25d44fb0de64b9820734e5647821a038428d67dbe95885526c3f2b8064e8baa5144b7fabbbf5a133c4b8d7a2f950a4fb69f9cdb37ac28cf0421894f0b771f80db988e25fb4ba9991664c93116bab82ba808693d583a2b697fd2b5eb673f954255da410df58231eb7c89b8257c5a68ca0306d088638b2faecbe3cacbbf77725e1685aa81d965f1ef663f1e474eceecbd52943c2e4e0456b52aa0c7758cd2fe67f3132176113a16dc9bd11d6dc03ee643fe8bd6677f2ec0ea754ab499e00ced482d78147ecb2f91d3154e03b57dfad4e4cdab98e134a609a7512a5a0e7c3c4adc9db444238e0fc3c3586b389d8d090ca46222a9533672eabe4fabcf61beaeb59c507f2941ced1ee4cd2afefee5aebeb354ec33cb85c9695426126f016929b471b9cc07dd6ff787fc2d682cc1e80657bd656acfb865dc91d6b032785cdd7a1d66d4d5463e142b6f028e8fb5bd6c621109e7022818b39197f85fd6ad4785efe48c4509e9a537f10d4fc9d23f275fb9e684c2f827868c9ff3baca8faa59903c829bbe1992541d15d538e64329e886ade0c5517cbab3b15fdb4e82506e27f449e268b488de32fd036fcf80f6c97505a5f33e4d3a004772a8970a3fe54049513cbc57131ffca1c82918a81bcb879b8f48d4300b11cd90069912ec9e59d10b6bebbc24ba1061c62a8762156df586a4aa758f13cab5ab59a3b1ef7d038c68920eb0a3c8a673c27b6fb80e5e8741b3b7fedff0c068a83e72373da07c8d73abbd9fa0084bdc92866917b546dbf7a6304f04b18d9bcebe2b4bcf5ac7ec526abb4a52a19094c8c231668d063c5558bdef0436ac418f42c5f41f2df996d19d48f8bec412de05a6a3b079e5b6ac1be0773814acc3d20166874ef64a6cf27f7fc72e0232031ddef1a6a4ac9897a86605550dd635c995626fe985aaabdd937bafe3e2a4082f0fc875ba7ea963a8e5987ad400423967bba1c0e369263ddf16fefc88901be069fc617ba6dca90608cd4a9d86476f8cbb41fc8197a9ee6fb331aae55959d107bef29b4f6f064651964999fb8dc904b8193dc7582fd47b0b0fb912f1c0c3838dd489c374ba5ea614cc80d4d196291c4a54989ae628dff5beb61612353ea0cdfd75962ab057bac887ce7f5df01861c769b88c7e1682f0ec6f7cea63598c3e6f41093d845db95377654fc56702a4110810917521ffada7432b7b16a64699e6a955a4273fe9220976f8b1ae9ea79678a3a74344a44c32454e7bbbae9a1fc440811693f66d63663c84bf847e0a2e8299fb0a6413194231a666a2efe5ae1c41db1cf12dbd8d58408cbeb1a9507b5b09ebf416f712b0040f8300dc5188e673c5ab1f13156718031f25cd5156beb8e77e95b48f42d1361da25a94cf1bb4a2a5c41f8da5c3f6a30c00e7d0323f7bc14583fe20815f468928fb69a480673b6c775b2d1af6a176abe5f6c679aae41ee1d5c89439a798823b65ef718515ceed5a7ec87eff54479a9afb48d0fcdb9a240e946719598512220d2afb20840e3680689cbbbf096e7d7505d1d854faacf024935a672278c5dfad333373015b11571b2a7329a0d2fa792d838ba3fcbe5303f84cc6d0454b89cf740bb0f83b79c98b38fa17dca42c5d57d8e86cbe16d46c4c0caad1f55ac4a399d9755067b642299b6b023e47ef74343b9d856545a51907f86034397dc1cdeb0856ea9fa753ba82c5f7e44e4423684f1b03ec59e5cdd96c03dbb1421e89bb0d1dd570309d92519e2b90fc83ece91ec6b13134cad1272f0fb1092a21e0066cc0a783e566167b52856fa6ef12aca963dde340e94f04980279f67a1eaec339d0656c09a3fe91a2b1885f1c09e831471ebe78f2af2efa1fe5821034ae172082de7cf5fd8599f7c575311d35248f2b0e6342cf7ac4bbcd19942a74ae9a9ea3ef5641f70ad1746406ad9bc24a1a3ed17dfda75ad54fb920ee9c92b792b76d42cec2c22fd1bb0f7acfa398d82b5f016f2943dfb44ca1d96b2a54ceb7595837379d62feac76dfa610a82ec947047176aa74fa8d58aef3d34e79768ba7b213a8c44c6e9739f05eb197148b2d2f3c5a1dbf0d4ddc4ae2bf0eeb93d2d4d0990c2c21ae34300a3139ccb5cf216b4031f5be4fc61b137a952fd516e45236dc791b692910a09a600fce9c14ce9e429ef1ae3ae737ebe9921d10522a4507d0794fde66f639189cca95923c51f97cfde4d57c718b6e0ee709227fef69a95a229ab54a4ba9d858115ac04dd0a594ee8fba7d29a23d8df53c131dbd6f7f47c6ec482cb2da38e98a8bb51a2878950877408f0892199ae4e94c4c8eeb614eeac1435b2947ba67c30ff52ff4c958eefd318814a17f53c8ae691d3fd91ea8196bd82d4af9fa216e32636d6535d5c68f579d3066654f2cc067873fea5d56f9676800892f210363fc790086a778fb721854a0abf9a2403ac6de964c2eee9011a44cc0d66ced8bb0634cb986a12b0d5d875db0f26f008555f7ff57f42a441250dc5d13dc5342ef36c288127d46b4a2cd85e5189877003589579aa787c46843e47666be2ca6e8aa84e065ec77f0f77e5cee75785e2358a5e1fd7d540ba1d36052964d7a5de9d1598cb71b238c6a6f2a4b6c72d8c5b0a4c2f17342747dcfb2bf7bc52256fa21741e1f8e7c2b749005ef240296ff9935f75e943c2e725e9f54636c3466450a49eadcc6f330558f2146426fe6786f4ac6fed1943d616474f7665e8ecc2612479eac464c8313066de5fb652beb42ee17c0d9eac4496b5a732c3df31d90e24ffa8eacb12b72dc1d393d0880959e0ce9db8141ae1490bb12af9bb2d12da5809a348714024d7beb73dbdeb4d7adcb68c59ada159fd1855ddfaa33e0b985d7bc3f509e64ee52b5057656295dc669939c45d89a07f03c0062e20e309a0388725c993f74cfbb8db38b85f13bae8b27a4da755398f228d79eba2ad5101d80c75eebee608dae268dac0c3a1c63e311fd82cddb78f06fd576314ffbee8ed598818894fffa54b56e7a7be5c20ac553d106609f4bc757acfe7b116f695fa4ac3ac93bd0de4bf87aa6aca5535e467298aa934c11143bbf39c464db663b97ad416b6501daa12fa8d9aaa31334851f36f654356467cf4f42fcf0c4cb239c2acf7c7938c0760a6a8f953e75471881c59293285241f7b73e4b3dd5" ++ } ++ } ++ }, ++ "registryHash" : "0x05d68cf78b088d589f8b54243857a41c5a42958ae0e5807e3ee2fae9c6501b67", ++ "root" : "0x26da256a0280b55dada254313ab5cc4eee9fbd5ac2b37c229e6c044c73d3519e", ++ "rowHashes" : [ "0xea11f4ef69b54777a682922371576f1109ac0007190892350c1f2b156bdfd047", "0x97cb598a18b30f14e7769ab0a48af96205eee47a865c21ed1a27eff79f173f00", "0x15c5ae7699bc260cce7529044a732ef82e3827233ec01ae245b4ab39064b7fc3" ], ++ "merkleProofs" : { ++ "0" : [ "0x97cb598a18b30f14e7769ab0a48af96205eee47a865c21ed1a27eff79f173f00", "0xa6191a53104eedbcee8e72c8cdea7711bd0892700a46d740759f19ae4aa09c18" ], ++ "1" : [ "0xea11f4ef69b54777a682922371576f1109ac0007190892350c1f2b156bdfd047", "0xa6191a53104eedbcee8e72c8cdea7711bd0892700a46d740759f19ae4aa09c18" ], ++ "2" : [ "0x15c5ae7699bc260cce7529044a732ef82e3827233ec01ae245b4ab39064b7fc3", "0x78a4074ddbd4dda0362d2431f7629b0eb3dc490b4e83306f3e4ebe383d0ec907" ] ++ }, ++ "ids" : [ "0xa5ea2fcff9e3cf29d0c6f5f147b67ff24aec3bd4", "0x690a7fd66157e5b777256ea5214f634f61b3a72d", "0x41f547a71d1404f147606491f3b96e49f67d4658" ] ++} +diff --git a/consensus/common/src/test/resources/vector-slh-dsa-noble-2026-09-03.json b/consensus/common/src/test/resources/vector-slh-dsa-noble-2026-09-03.json +new file mode 100755 +index 0000000000..b5d70db943 +--- /dev/null ++++ b/consensus/common/src/test/resources/vector-slh-dsa-noble-2026-09-03.json +@@ -0,0 +1,10 @@ ++{ ++ "scheme": "slh-dsa-sha2-128s", ++ "form": "FIPS-205 external, empty context", ++ "source": "@noble/post-quantum 0.7.1", ++ "nota": "AERE-SINTETIC: the public key of a test vector generated with @noble/post-quantum for this cross-check; it belongs to no validator and no private key is in this file", ++ "pk": "77868c8946cf36281f0bcd8a5b299c4300d20feb42aa7a08893f402ce0c7b64a", ++ "msg": "616572652d6879627269642d63726f73732d766563746f722d323032362d3039", ++ "sig": "67fed7799e0b273a774c759571734072e3465b9b32becf6d334392143f72f49039f3f2f4e342a003333d1e1da2deacdffe2f52f3552f79487e0e0fd35e2e657152f6ab027523f4eec039a9b22d661efb90c4401d4a008693d862886ca038a1539fc8827667c85f81ce364b2dc12aea515786d606df7db8f9fcb7d1275eaa07051b481be40be4ee4905eb491c1509b2c755af8ec43d6bacbce519a39f19c6cce3de80a0488a3e724a33327ea3e85cbb9165e1395b744f64a637d79d287f17c4d61bb60b9e5bb03e88f73e19e0e81e3ea4a44d482d4f649756e3d0cdda173c372ed55470fab7e47c78fc7b189814ead0024cee40005b4d5b1a0e2729995c003e7c5c0843c47dc9f726ab8d0724377602e79fcf9f8b8e8cf52297251576079fe4d984f758e814c71e88352bf325239a913ffa8b14a3b94124d3ae14eb3c61326f8f1fcb8b7f70b1208cdc509a11a33d86c8d3284b760364f4095a333678ec856abcbdcd1f30867281e384bc4c9861aa82497d5b6bfd05c4c5ccef01d2d6d897aa9987f393916a2fec108e26108198f68693d26989bc93694ce191c00104ad626ef5c1555d38e08758d9211159aead1283e5276365f1e3c57df0d8f09526a8c6543b086f2a4d9ff6ef34333f2ffedb1a7a18f590b349eca3563008279563e6149bc8a87cd111b5f567636e0ba35ef93c6d97aec4b7e319aa9216eafc73336454161c35e31efb6d4c30a200b8186d8e683710ac01d330e3836f2594b5583b00f10ace8d607a3f3e53fef09d92c9ba46648acf78f72d74f6e9a7208b4eaa5a9e152b33c3f27ffa81c0401b399c33feccc21d373794973c12100443d59d71e76f37c8a688fb7c3c4f73a68ebeb204a45dde88d384ab2ef91974f8ef970f2c376107a05c7e4691522481e6ee6dbe478525444231e2bc53c530e652844c2342410214d401f00b5cbe01736c55f0a473434764d568d941e556deed1bd2678e646b41f5c7a6fa11a259849cda323dcf6e64dc64cf76e6734561bbc7dc0b49da4598fc79e2672e1aea7187c2d39a93e50052558e704fac8d963fc7cfbc424ceab9aabea9a151143ae2c25c945cec0d6a696b696ee4c8ce5c4f10248117f08771c002dac825c807adc5395af6ced8e8c687775137dc17319c0b235540f9dd7f0855aee37b1d6cd1b5033eeb824c0c6b25208827d1cd1616b829bcc266d4cab18a90a664c15d24f8f71cb4b744ac1f2aefcb72f9c1dad83cf48a6cf5f0f38857ce139c5d546310778b73488850c0c55354f5ac8649e715c5426fcab890f7c3be3c558e45adcd1bd44e37640a10519338a50f48fa394d9f6669a143821d03abffa7c442f36f09bb83811cbe4999e1cd2cf1276470d7a169e3900fd6e4399df2fc7e6c74d70af5cbe3169ee977f6a68bd29225b775f95cfa7a39bf513924910c194919f92f3e72a46e420f217648bf0492310f1bfeb5e41fb384a4d40988e83418e2e193745cfda92080d755e6d180b922df1eafb440c431d92dc8c6750f564df1ffbd4dbcefc6f1b7fbc3b931726852af11f18e58d4c998d47f985868bd74bc45159036704730db0b279222aab572ff762a6ffddad353cd9149118da44eb732d8fa7e462449ffdd0be5518b63abe26f360b837b5e97f41009a7adab94da2603fb3b7fbe902ca56d4f4a4cf6a2fc426dd75f37c620cf27f18187cc59fb23518cef5450ef0d6117ad5af77d7a436c58b90b9b1adb7aa8accc6f067b598ea2e2a12b1b7c4fca5331133bcdee7337450453548d704c4f35f1a9489413bed593fe90b57434fc22f51dff6de52db277dd83bd157de23106aa62531035ff84daa0dc71b330c84920ca14a922342437e0bdad4a3fa9e8c42639a759cbba77dd49b2a4e19a55cb01ddd7e2a680e37e2d844cf7e25c367009bb9596ed3dfb95d9dab8b6a8ea56979e776945f6ea4af3f4ae474d16c04acb97c8e003be87287d2b1d7a06f680d4419b537d67b20fbe377cbf8401f10eb7e709298a7f06c63b80e818f25b96c862b20327f228ee78178af3075280aad0b216cbca3b3d984c972a3df1984296368e9aeadae0f5604b0b556fa2e4e4df4ef812e5ada45562f3705ab82429506b0667e5015f8ff92b5a7e9f738c1045cce143657ecbad7b61122d7e8392012277e2f2ecb8b49ebb67f34c277004e085b4730d17eba1c1afbafe43f32ee1ea15a5e19613cae33f4dc2970ac31eac84f017622ce2c1ef1f1adf7882861a6f02cfa59c1c19301c628725030c0b43094a6968513152737e0af2f2fe1f1a27cf3a87ea7be403b12e7cfd26930fb0eee15f60048b62ceec6a322d7cc17b53e9bd2e93f22c78598f778eab003d9aeb2bd14ef38786bad3fba86875145b203a26229af48876916b1982cbac1c618d9e084d8eca8ecd0caad4315044126dafa9411af94ebc1f25d97cb27abc75d13eebee3b2186504957c24cbcf004e9b7d22de9dca8d215cb0c43818fe98a69a0e85d40e9892c459f498c8bcc3808724f3cfc8b0094e096cd67d6226c9aa3c4d3510cf16397881ad22fe6e2d9c87bae75cc40f8003b69f78f4676af2268dd982e982742a0ae85951c084ab14a9e34dc6ee509add0d8c6a0a2274135f0eb209652033912e15c28c9c291c30e33e4e2ee423208c66effaf2f4ee4d74774e0a6386c57304fedcf2e3e1044da478a3d33ccfe1cc9f925f2a1ffdba7d2dc30a7fdac96ba2f3c46b52dd8529844fcc8fce29a59aa6ed496b9b50725dddc63acdef7364d11dc6e1d3e04991df87859a304095eca35eb9dd8ad02b890863faae4edf085c8b9f9de3efd898d7e4ff8781121057e3dffd6abaf983266626b205f590903a32027357034d718fda15f8facbe82cfb8875c6c8b6649c2813f315d845e2d430ed0e9011f6493abc58fdbc2043cc592fbf2ed202a3c6202997a71d5ce4c6d746cb9219c32204e276309de853dd37e2eb4be2d27ab24970e2f87a1db15f132835735b66daf7a114428359e982294c82865fd7badeade0a2baf3c2c8f61ca3a22c83a0fa6c09f187a0cf5f70f05586e23ca5b7f648d20b9fc3215013d6b0005adb89589535d79b264acd4309b035c54ff87d38c22c02959d5110ebd80960a0dc2d2416d276278219690acef13f298a19b887b29af6a0cf38c30cecc7a73c64da71bda754ed54ef0cec5208604421fcfc3a79e20d871db9a2a60605cb98d081b965ad75580e5209b1ba9d94c2e626da3caa998e43c72a9998f7c0ba1c521ea3939723fa13cc1262ccf4628ff00ab2d778e99dc125a16c1d894b3cd4bba4bd02085458559a22632aeb9cb2e158332e8b6012a4415e231df0792fb931e2e2857210a3b1af79517b6fa55f6c7ca6dc1c056daec11fa22666c404b1b36cd7f46dea36ffe10ac71100986db369e71bb1c378f77e401eee32ae0e48965fd8b500ad3efac1effbd3c053ba210a2a58a25e7b9d5f0fdf79d58477455cfc0b2604492970885fba5ab2708b2e676acc61642889e958f23b5212e119894b95a9aafc904986db219160de187b0ef33f07f0b598c7a44dfe7c6508c403a91dbedad5dc26dae9bcd21903e4ea9754c42b3f01bb57cc3639b55d3aa40ca3b60591b26ebc5f1e225632d2a8f0a3b20ec1c13c8a80153f9c286f34c719feef85fa5f53ab42bb2f7dc4f02f3e706501bf3dac0d452a002a73d948d04a232439d56568c8d22991fd178ec94dfaca8f1fcc54d9be92d7acb25e27e45a9729b903c80cd94b806ade21db010693923bb45900c55bedc582ae27cdfe2b665dfe6bd6868976035dc85a9e85a7010e457736d00f7c685b0393d4daf163164d76f3004917f0b88417d32b1e79d4006cee735c4eac9fb3e6acb5432fd58495de8d314652fd286f36ccc424f7bffec59df9b9062ca6a38ab8adaec902f7d1b48b5ffab4b5384ed7be957bd2795bfe2a9caa72e69b9a4bcbd106ede1021a8221f47c7f41509c3e3d32fd1888379fd7cce5693ca33bd8810ac0a55a6a771c995d2fdcd2e94e84ce2ad1ab3e490ae9dedd2403335a9925f5f827922e3140dcf347f42f1fa6ac28b5e7afbde06fc100f95a1ca2f8aad4d1bbd789cfe0f0dc9ae8b1d453ef3253435539c9c01146fb60a93323e619e2f7fdfbcae40ccf84fb09633db41d284b2fefe7879a8aa57c8d3d0a96eb287ea865a4e9a15b8004401d6bb3139dd5ada82b2eaa0b44b16129568ef70e35844bf2bedd7cd9d3790b57e6bcbee06a2e9371045b2ea891a82fbae78e13464c6dcf3ea574328d265548f95bd507ee3c0cd5b3dcd3a5f344a334ebcc7892f6bf5f8a63110e148baf16344b09dbec02dca4f6ac5c86d6e1107646150a2edc785d798761f35551196bfb70dc7eaae2bb647197b946d7ba167d0f6e366fd633822fd1188b3c8bbc3a96da6d24d62ae5e85dd07551324c73a6a650c75ffadc0ad9737f4cb214ffe72ab6cf30f2a4aab57c25e5a99eb062e54d7e0aff93adbc2e4767a12796650c6f5b2db7463dbe4d5eef59ef13a0337cd38543d9d95bb66b26e6c8f55844fb4652582271206ef0250d38bbf795c5188a5a82755873871f0211e4f9207a257c5fcdc467913aa644cb9bb7eaca94b3ccd1a6191e94fef075aa482c1f11ab042dcbbad46c796241ab79c2f86bde9dfebddb270ebe7d8bbff3e614b98f54c152a54c7e75f68c8cd0855032e0c206ad25d7519ab3bef49e3fef664d9d0f0af5ea316c983d4a4013743b07203e039ce6e86b35e85d7ad383925cfa8ee6cc44fb5f1601e303657762515905b22ec2bdadaffd109f807667bb61b21162b6b2196a51b87303f8fd968a19426bf92e28d661c52efa2b58d0726539ba61813a3a14ec7f8deb5d13098cd03b1d7b545cfc91d1a2202c7548ca9f85d2ca888107ecbac63981d3c6084a7643d86c0ce773a0f023fad67605bd8606c0e5158879859488d9ba3c056c762fcf13695172205919c71e53097c3404f8566d9903bea68d39d5dd5c5ae04ec9afc682574f488a7b358f57906889fbfa02d451398f8bf433f2fdb0d9ddfe7a11c9fccdc58b9521ea6adaf31c78334decfd7f6a445dd5c08d71292d12c8f58d356cd0a4755a2f205bd1f833aacf31ef9374c30411a470af9d52707cedbf5d7c6677918b16ece8b44020a0ad0108d3d06f42c56492036a16f7ebc1ce146a4ff061c8f28a3393550be8d02e03a753a4de0e7a2c1b034eeeb7dcc25e36a1b3fe8be79032da57fd972c8d460c841315c55aaf47a1aa4118766bc20c5be078f8636779bca218a7b3c67eb231ec92712eb0583dab001d774fc41edbc59d29b66b63c72daa73c7da82e619ae92df376dc5048d484410a42270119a390255cac3bd48509201351cd0975933c402dc2878282108999bf9f0803ba69c1fab3c79dca5d1c48069b6609732dc5662c76a39d5a87bf0238275519bebee2a6843d7da2223e864cadc64e6bc35de75168eea1a4c76a956a5cc38075f019e4ddc9293e1674798913d0cb6b622ec2518bf384dfbee4f0e6530217bac4144bd3481173c37b5db7e25cae689eadeb5e35a40e1c4f33dda61b38bc066fe665e5375f04c5ffd282dd707a3ce8f29094075765de4d199800e38226dc95c91984afcc89a853126be1c747307ba73544b82c7b18b97e717bae81fa61fac001e2408ceac060a6c94bf40f3242bc9782b7f179ece763c73f21b269e7b79303b9c28b08278bab462e017995d9d4b488184af420292c8f08d92e630b34d6cafea52616f0f405934a16ed6515290869f1e853f60d5fa36453cd09c8604f8384be27992200095c3ea208a223de8930dd3248029ef196257cb40024da46188d925d3c0a19b3b01cd96310489b26262361320d8735838691dff538f54f685396fe780f1d3831311a3e77b57113a3a23f747aeb4ebed6aa7c1c16bd92766db04253282da0339fc49e61f1415dc788b8d31db4fc37a79283020029470eb5797fc50d5989f38bd9f46e35428e56c3622eeae2659d427a561493f9236bb197031bcf556825ee30ee98f4f271b8b9846633878b07e2792eeb4177d0ae2e77a6d812c7c8e8e2b7a88a0edcf759958e17789079c35cbe6bbd3114a5682bff4c005e642d3be071d9c07f00339f6bdf771d2d46d84a1712290eb71cd36223fc0fa3d64d6ab0b44aafdb96dab69c490c4e68acab6b228fa528efe7c41b09a93a2827ae0405cd011bf9f516bccf508c995588daf2cef1ea3fe792d21772fd8bab223d740d554fa7fbdfa0d7c2083b6442fc3ac849cd9dd0c13fe031e8b656a2849468b70745eea37fac1b0369959e93675048dc89f6029a378a014c5a65de94c7dedfad0ac0a2b2e6da90a25427fee681ec0e06824e32d9a85db98738ec651b60c71b45c22810d74fd93748c786bab42f8697fef5292ad518af07709dcca4ca2d677a187eeefdb3db719303c2cc3fd1f74e30f882fdbf44c89661306abd6431a22c0bbdf3d1b5f97799ebf29c05e62a5894c12538ea8de88567db9421d2a4b1c7faf0f039d0ace438a7165b989ae86e8c8699e3ce10710b0a04a09335dfebefc7217f3e0a919b57a1db05f81f7baf9443f2d71917eaeb52529c1491711b355caeb821d07238f7bea601109eceaf4e1503b4e0758826454b44357dc1269dc4f4757d8f5c8b2be605f7d7026017523d8b3580b72e43df61ecd5aec07baf3393a8efb18cd7333b1945da07e973b8c5bfcebb053d4b9c73efff86e3c1ae424d2cf3d48b38b6e345c74b8015677da947338276250c0a21db95d5c293966eba2e105acfb77f718845ed143693f6bf39974481393616ac8dce0e9014e07442e9726b3b5f258c6510842b394559e5a5763a19d0847e910afaf1a6dfc5b724bcc9c05c130ad37c1d967b1d07c81301dae7df61b5d62c0d1f7e24b6967cfb673681f1f8e91862f0b53c7b82096e37084772da8398c2f3cd0c704fa3519bcb2aeaf18193d1a8cc8c7ee285878dc665d2eecb857776bd8984a5796703a659effdfd67a1c7c758195f310baef4353804c197fe69b2c53d664e7722a1838c0719a462a4411262b3bec89fd5e6e3e4f1da598154bcd0fb12806903fc9656988f1f7866ddfe3d2d1224cd447422b91479ad69d48c9472f7a669850150f1129c88a8c09ee744169d6c550fb3742b2c225e4a01ce1a12e9affeade7e1df3b865a94b8522aaf79ce42628e3632f41a9d41da0e42b24dc80454a3d79f8f45f83a879acfce73658fe7d447d1f029e4966dccf4bedab315e6b7e265c698e969327042145b981c828eea5f81d6bfc3af770b0ea9ff412c640ce78ee297e0f22db7f71e701215920c7dde71d08060aba05a8c972bf804a4e743d3ad46cab8105ee6a6a718467fbe7a10db8032b611951ad158762436dd373d1d1c033d1b7997f9bd82ac08d12df4afd2003a9c8f40f3b29126e45c05dd325ee5d60f96cd73ef915f091beefa7ab35d39983b3438feb3f56f34bf86d258b04bad97f8b9c2299f1261b21bf2b7daa15a9f0b3c92c39569f71ea198a18115a4bcfd257d4ba98658ddd6a50623bad3f6a5bc1bc1bb665e4a1ea4ab99794515d1daea397420cd53cf2dd7c3002702d1345c2b8c861794bcc27df9e7468ede1608aba2c1504485cbc021698eb44ad5dbc4316ffc4de11edaacabb3904d036e02ed7a728cd29fd95b733bd2b0d0a3a7e0501f57bca4e74f8de6e412a9e21c88b209a9e3a32d3846d12e8db08f08b415e53eccca3cfac362a5da2437dcf9b5c9f89706155fb260bbda8cec5b386d1186daaa1c72f4940e844b3cc9fc7a60ab4e22d481790010ef36be8b8e025b7307d70e1ca3e11e755f4039a6d0ea55ebf86d309e6056d6e1b6732560026258d7b6e0b5ccebd59ab7ad5dd48dc41668b223d1e2d078aa7180176c33cf96bc466719b7fc8d444510e5fa3661e8ebc74d2b515a8d08a280b419ce245a2dad9ec876ffaa02d0474ecdfed995e52e880011a3d5febc5c520aadff075a4f9975eae6c3610e12719ff87d9586a029810dc7d8d4cf1f0ebfbaea18ee6b2ed19e387c18954451a943701d1f3376c9acefff7a841845af834acb99b54e8d14e341ce769242d6d6b558b42e63b62fa55c7ad7482175c81d11d700e1196ae0e3798b4e8893fd194fb0885a9d57c309b3b01a0c7ccc5f0594d12ec1c21eaf2af3ecf90cd5cd364a2edebea6d8dd3865c7cefe2ef66da644a630f955f472c859bff21ccc2ad778c8a6a1fed8428cef29d4aa13c6dc5edb7aef44fbcbd3374bf2ef5a439691929f04054ac5fdba0c564ca98502c5532fd1c8d2aba91788c71acc95f434b93dc4fa7b468a98465b70e766787ce5de56d7d539648aaf2671d8682eada24231e20c55ef7d2995674863ddca495ab5ff36ff2be4e18d20209098ae792e44348ce6138d22a407f1ba24b17b88aa470e889ae4c629a31014c97c8fd5a34042bb548dc90f98332962f61e7ba32cce11898807c263ee68eac042b71a7fd30faec8d462b05a9d9af742de2dde1226d70bb23303d58f0fc5bf072ad7d63cfda8e17be96ba9e319870084c916bc465b110422e5e64134ee5d2e6ab79122e1e39bd7413ce131ec915854e08716d4525849430b74953ed216eb880fb8422fec1c9edfe4da15fbc985ff7e7a4713a71cd219bf20c5b13da12d0e366d6b7542c72801562b383624d19d78bfaef312a0941e925b741460c7dd059e6536d1c94271a660f4311b0fda9a28fc6074bb942ff41f37cf30491db436695189b7aded4b9a7f8f9750eca3521fe64396cd8c0a2543c88d0646549c927c1e97b6663130376d33000542c5ce44b27d9e2602457339d598beed92b204c34645fb5a8e688d08cc32315d3e80b39639e86e6b002a2aae39a22b8eafa742d9cfa62245a60f8b8c72f9e55564b60ed4e557bf862668b49e521f9f61c4364cc9a253097fd1496121e63cb3ae444211fdd29a5d8a7ed2135aa993af4177fdeb424a6afaefe2171651f5aa25411c903bb15e91f829af927ec0feefa7ae7febff1b60c8b39fc55c3fa5baa526a8031a96641e896be98e6436146decb2ff20638f4d0dbb06e0cab890a7bdf9dd47af158ec621312624345041316e65c79e70d714bab7d0ae923772754081a0344f0cd36492c137804de093c2949f0c6e644c26105a6b490cd4f55944129a87c23c6c172be09eabc71d804ce76a8bb092ab05b3d5f563144d40bcc2ebdbbbeb3a185a2ac2c66500000456391574c613b36b23ab7021beaaa702803e01d51074e9f94838c37e4a9f48ffe6544f7f223b33924ed3f8bb096d3927174209d76cec40743ac7a7c45b5697081204b61b7d82136f5c84c97e01e66f98f9abb7e44dc2bb1513574bc2c0a8b96ee8f88520adab32c486f42d36dc62a00bb015fc6590b053295c161868cedb543465d72bd199539c81870bcee27c2063e20ada168c47c9b11f4d7ac2aaf62dcdad0b9b818ccf17d170abb8b0eee17205ba20c4ca128f98d092f4fa8f54a24defc3daaa2fcc9876ba502406664725589ce4392b1888d314a076b2e8bfc9f64cb2ac94b5c868dafc98bcfa36a38a77ea1d4a650b05b3e0c6be7906579f32dc04b8cf4e37f57e64cd0ee5248637c2a034904e9b20428745768e3ddb47dd7efb5e27b02a6008c3d57b3f5d99fb39526f8457e0debb5f170756a2ebbc2a66a5e1396ff2a92376e30a74e7acceafd4c92b04ceadb3c000af2118f2ef3c6ccf7e0e124a80c91916e5b225ea88aadcb4b3e36e62f2f3528d609a942fb08f555ed0c5e42614cf9fcf701d911d956db61449e175ddd1b0bba1b7ee300c7a34e54b42acccf6e7a3a47701a15b4082583dfec947a0ec13749c4435e8a1b44e808a0b8db4674e7ca34c8ce23c593a764a4882f42f0455799767e7a1d75a4419f9c429cc5dc6949cce4c70f90e19fc7942dbdf7f0e3a857c17fb336ae1779e738a1eabd7760546a215e7b419313cb1f8060e2552bf990c3123c6d2764f0b5dbdfeae498bb6f09bb7221b88da1f225c7a9f5a88c19d890a3740e0fdb31738ab32e12b16330fca9457eedd03ba61765f60f39536ef301f8b864486aa9a5b908d24a00abbe4364a1ffed84822906cf7edf72ccd16fc4112d309120af01f7c4b90a747a5536cf57bf94ce530df6e95873f06e42735581231f7f1f312a2bf14a325f1582a9f9dc5b11a77f166966e0cd90e86b511649fc293b50f28cdb4dda769b3ac7d190c7bbd470fe81383973e87a4cbdde34536fcf30ae9ea51c6ee907e6505311c0b4fc854aff34bd22b31c71a02f7296d950a13710e2d62161f97af62a5d92afe4c9c5ae69611c57acf16dd100b626b9230c78aabe2d500e87d427706ddfb5063426a2e8d6b521f671c73935c0d9961925c78111bcb0f421420dce466e5aeb380da9f037e9db535f50c2db0b27f0c77f9ccd0f145e7dc4cf28f600a2cd42728aa476b3c10f4d6580af0ac773410cc3faf34ea5a9a387a1fe90a7885c938f984dc543a1c4a6fcd6760538bde67588963eaa56305368097252a014c01db5ca15d8acdb4fc0b84b8599d82c78907b5eee0c6f07b2c22bb76ed072648ac9ff835f89704dd3f3d63fc32ea03513133e39f9c75e64957d1aa7c5fe7baf0a978e330ad62546c035a8e453e0fbf8f21990bea65f9d33852280f61224a79ff4c8a33138d50bd2bf44f5017ecdde038dd252484bb34be7596b35e76badbb11b2bccbd29869a00bd8efa2410864b661b347e3fa9e89404bc927c81c24c1a218a3d543a7b3b2453565bc55ecc94e86cfb46e28f698b7c47ef5e1d11e9c51d5e98b3936838c33b056dd377c75c661dbaa0a63c1eec52096477912821974ff06f9cbc499d0ab71922fd021ae460bdeaedf6f3cf5f260ca6cde4ca7fed26f99b59ab3113107c686c3e512a3f781078294ba870c911f05c0bde3d1931f62ecf44bfc73038220053db0cf0dcb5448f7e55addf7d65e03eccdddb647a2b28296070271d187a89fb108a03a4633a9c3c4a984034a609dba455116b6e299733dd80e707d8286bc47ef938ff78a64cede408c47efd6f3e4892d79fcf95de4fd284803341868b3af24235d9db7e1cf6455c5c1efe49a5d4eaa6f8f751a992b79595b78e68813e60ea8e72f875b2d82aad56f53281fe5f", ++ "selfVerify": true ++} +diff --git a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/Proposal.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/Proposal.java +index 73bd09f3cf..64ece7de19 100644 +--- a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/Proposal.java ++++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/Proposal.java +@@ -1,33 +1,39 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/aere-bft-bounded-message-lists.patch. + */ + package org.hyperledger.besu.consensus.qbft.core.messagewrappers; + + import org.hyperledger.besu.consensus.common.bft.messagewrappers.BftMessage; + import org.hyperledger.besu.consensus.common.bft.payload.SignedData; + import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; + import org.hyperledger.besu.consensus.qbft.core.payload.ProposalPayload; + import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; + import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock; + import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec; + import org.hyperledger.besu.ethereum.mainnet.block.access.list.BlockAccessList; + import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; + import org.hyperledger.besu.ethereum.rlp.RLP; + import org.hyperledger.besu.ethereum.rlp.RLPInput; + + import java.util.List; + import java.util.Optional; + + import org.apache.tuweni.bytes.Bytes; + +@@ -102,29 +108,29 @@ public class Proposal extends BftMessage { + + rlpOut.endList(); + return rlpOut.encoded(); + } + + /** + * Decode. + * + * @param data the data + * @param blockEncoder the qbft block encoder + * @return the proposal + */ + public static Proposal decode(final Bytes data, final QbftBlockCodec blockEncoder) { + final RLPInput rlpIn = RLP.input(data); + rlpIn.enterList(); + final SignedData payload = + readPayload(rlpIn, rlpInput -> ProposalPayload.readFrom(rlpInput, blockEncoder)); + + rlpIn.enterList(); + final List> roundChanges = +- rlpIn.readList(r -> readPayload(r, RoundChangePayload::readFrom)); ++ rlpIn.readList(r -> readPayload(r, RoundChangePayload::readFrom), MAX_LIST_ENTRIES); + final List> prepares = +- rlpIn.readList(r -> readPayload(r, PreparePayload::readFrom)); ++ rlpIn.readList(r -> readPayload(r, PreparePayload::readFrom), MAX_LIST_ENTRIES); + rlpIn.leaveList(); + + rlpIn.leaveList(); + return new Proposal(payload, roundChanges, prepares); + } + } +diff --git a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/RoundChange.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/RoundChange.java +index 6c922b101f..5d7cfce849 100644 +--- a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/RoundChange.java ++++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/RoundChange.java +@@ -1,33 +1,39 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/aere-bft-bounded-message-lists.patch. + */ + package org.hyperledger.besu.consensus.qbft.core.messagewrappers; + + import org.hyperledger.besu.consensus.common.bft.messagewrappers.BftMessage; + import org.hyperledger.besu.consensus.common.bft.payload.SignedData; + import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; + import org.hyperledger.besu.consensus.qbft.core.payload.PreparedRoundMetadata; + import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; + import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock; + import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec; + import org.hyperledger.besu.ethereum.core.encoding.BlockAccessListDecoder; + import org.hyperledger.besu.ethereum.mainnet.block.access.list.BlockAccessList; + import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; + import org.hyperledger.besu.ethereum.rlp.RLP; + import org.hyperledger.besu.ethereum.rlp.RLPInput; + + import java.util.List; + import java.util.Optional; + + import org.apache.tuweni.bytes.Bytes; +@@ -126,37 +132,37 @@ public class RoundChange extends BftMessage { + * @param blockEncoder the qbft block encoder + * @return the round change + */ + public static RoundChange decode(final Bytes data, final QbftBlockCodec blockEncoder) { + + final RLPInput rlpIn = RLP.input(data); + rlpIn.enterList(); + final SignedData payload = readPayload(rlpIn, RoundChangePayload::readFrom); + + final Optional block; + if (rlpIn.nextIsList() && rlpIn.nextSize() == 0) { + rlpIn.skipNext(); + block = Optional.empty(); + } else { + block = Optional.of(blockEncoder.readFrom(rlpIn)); + } + + final Optional blockAccessList = readBlockAccessList(rlpIn); + + final List> prepares = +- rlpIn.readList(r -> readPayload(r, PreparePayload::readFrom)); ++ rlpIn.readList(r -> readPayload(r, PreparePayload::readFrom), MAX_LIST_ENTRIES); + rlpIn.leaveList(); + + return new RoundChange(payload, block, blockAccessList, blockEncoder, prepares); + } + + private static Optional readBlockAccessList(final RLPInput rlpIn) { + if (rlpIn.isEndOfCurrentList()) { + return Optional.empty(); + } + if (!rlpIn.nextIsNull()) { + return Optional.of(BlockAccessListDecoder.decode(rlpIn)); + } + rlpIn.skipNext(); + return Optional.empty(); + } + } +diff --git a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/network/QbftMessageTransmitter.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/network/QbftMessageTransmitter.java +index 18437e30fd..236b6cb35b 100644 +--- a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/network/QbftMessageTransmitter.java ++++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/network/QbftMessageTransmitter.java +@@ -125,44 +125,44 @@ public class QbftMessageTransmitter { + + multicaster.send(message); + } catch (final SecurityModuleException e) { + LOG.warn("Failed to generate signature for Proposal (not sent): {} ", e.getMessage()); + } + } + + /** + * Multicast prepare. + * + * @param roundIdentifier the round identifier + * @param digest the digest + */ + public void multicastPrepare(final ConsensusRoundIdentifier roundIdentifier, final Hash digest) { + multicastPrepare(roundIdentifier, digest, Optional.empty()); + } + + /** + * Multicast a prepare carrying an OPTIONAL post-quantum seal of this node. + * +- *

    Sigiliul vine GATA CALCULAT de la apelant, si asta nu e comoditate: semnaturile Falcon sunt ++ *

    The seal arrives ALREADY COMPUTED from the caller, and that is not a convenience: Falcon signatures are + * randomized, so signing the same message twice yields two different byte strings. If the local + * copy and the one on the wire each signed their own, the same validator would produce two +- * valide si DIFERITE pentru aceeasi runda. Se calculeaza o data, sus, si se trece prin amandoua. ++ * valid and DIFFERENT for the same round. It is computed once, above, and passed through both. + * + * @param roundIdentifier the round identifier + * @param digest the digest + * @param falconSeal the seal, or empty + */ + public void multicastPrepare( + final ConsensusRoundIdentifier roundIdentifier, + final Hash digest, + final Optional falconSeal) { + try { + final Prepare data = messageFactory.createPrepare(roundIdentifier, digest, falconSeal); + + final PrepareMessageData message = PrepareMessageData.create(data); + + multicaster.send(message); + } catch (final SecurityModuleException e) { + LOG.warn("Failed to generate signature for Prepare (not sent): {} ", e.getMessage()); + } + } + +diff --git a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/CommitPayload.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/CommitPayload.java +index 8b788f499e..cdfaaf24c6 100644 +--- a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/CommitPayload.java ++++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/CommitPayload.java +@@ -5,73 +5,76 @@ + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0003-aere-pq-anchor.patch. + */ + package org.hyperledger.besu.consensus.qbft.core.payload; + + import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; + import org.hyperledger.besu.consensus.common.bft.FalconSeal; ++import org.hyperledger.besu.consensus.common.bft.PqSealed; + import org.hyperledger.besu.consensus.common.bft.PqAnchorV2; + import org.hyperledger.besu.consensus.common.bft.SchemeSeal; + import org.hyperledger.besu.consensus.common.bft.SealSchemes; + import org.hyperledger.besu.consensus.common.bft.payload.Payload; + import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1; + import org.hyperledger.besu.crypto.SECPSignature; + import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; ++import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.datatypes.Hash; ++import org.hyperledger.besu.ethereum.core.Util; + import org.hyperledger.besu.ethereum.rlp.RLPException; + import org.hyperledger.besu.ethereum.rlp.RLPInput; + import org.hyperledger.besu.ethereum.rlp.RLPOutput; + + import java.util.List; + import java.util.Objects; + import java.util.Optional; + import java.util.StringJoiner; + + import org.apache.tuweni.bytes.Bytes; + + /** + * The Commit payload. + * + *

    AERE hybrid PQC extension: a Commit payload MAY carry an OPTIONAL parallel Falcon-512 seal, so + * that every validator's post-quantum seal over the commit hash is GOSSIPED alongside the decisive + * ECDSA commit seal on the same message. The Falcon seal is appended only when present, so a + * Falcon-less Commit encodes byte-for-byte identically to upstream Besu. When present, the whole + * payload (including the Falcon seal) is covered by the author's ECDSA signature, binding the + * claimed Falcon validator index to the sender's identity. + * + *

    AERE FIX-MALEABILITATE: this payload has exactly ONE valid encoding for a given value. See + * {@link #readFrom(RLPInput)}. + */ +-public class CommitPayload extends QbftPayload { ++public class CommitPayload extends QbftPayload implements PqSealed { + private static final int TYPE = QbftV1.COMMIT; + private final ConsensusRoundIdentifier roundIdentifier; + private final Hash digest; + private final SECPSignature commitSeal; + private final Optional falconSeal; + // AERE HIBRID (2026-08-25): the NON-Falcon scheme seals of a hybrid certificate. Falcon keeps + // living in the legacy slot above, so one signature has exactly one home and the wire format of + // a Falcon-only commit is untouched. Empty on every commit the live fleet emits today. + private final List extraSeals; + + /** + * Instantiates a new Commit payload (no Falcon seal). + * + * @param roundIdentifier the round identifier + * @param digest the digest + * @param commitSeal the commit seal + */ + public CommitPayload( + final ConsensusRoundIdentifier roundIdentifier, + final Hash digest, +@@ -306,44 +309,55 @@ public class CommitPayload extends QbftPayload { + * @return the digest + */ + public Hash getDigest() { + return digest; + } + + /** + * Gets commit seal. + * + * @return the commit seal + */ + public SECPSignature getCommitSeal() { + return commitSeal; + } + + /** + * Gets the optional parallel post-quantum Falcon seal. + * + * @return the Falcon seal if this commit carried one, otherwise empty + */ ++ @Override + public Optional getFalconSeal() { + return falconSeal; + } + ++ /** AIP-22 stage 4: the commit seal's signer, recovered as CommitValidator recovers it (empty when it does not recover). */ ++ @Override ++ public Optional

    commitSealSigner() { ++ try { ++ return Optional.ofNullable(Util.signatureToAddress(commitSeal, digest)); ++ } catch (final RuntimeException e) { ++ return Optional.empty(); ++ } ++ } ++ + /** + * Gets the non-Falcon scheme seals of a hybrid certificate. + * + * @return the extra seals, empty for every commit the live fleet emits today + */ + public List getExtraSeals() { + return extraSeals; + } + + @Override + public ConsensusRoundIdentifier getRoundIdentifier() { + return roundIdentifier; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { +diff --git a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/MessageFactory.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/MessageFactory.java +index 11426d6a68..24777b59b7 100644 +--- a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/MessageFactory.java ++++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/MessageFactory.java +@@ -125,44 +125,44 @@ public class MessageFactory { + final QbftBlock block, + final List> roundChanges, + final List> prepares) { + return createProposal(roundIdentifier, block, Optional.empty(), roundChanges, prepares); + } + + /** + * Create Prepare payload. + * + * @param roundIdentifier the round identifier + * @param digest the digest + * @return the prepare + */ + public Prepare createPrepare(final ConsensusRoundIdentifier roundIdentifier, final Hash digest) { + return createPrepare(roundIdentifier, digest, Optional.empty()); + } + + /** + * Create a Prepare carrying an OPTIONAL post-quantum seal of its author. + * +- *

    AERE PQ (2026-08-28), pasul 1: firul poate purta sigiliul, si nimic nu il emite inca - +- * fiecare apel de azi trece prin varianta fara sigiliu de mai sus. Ca la commit, semnatura ECDSA +- * a autorului acopera INTREG payload-ul, deci si sigiliul, ceea ce leaga indexul revendicat de +- * identitatea celui care trimite mesajul. ++ *

    AERE PQ (2026-08-28), step 1: the wire can carry the seal, and nothing emits it yet - ++ * every call today goes through the seal-less variant above. As with commit, the author's ECDSA ++ * signature covers the WHOLE payload, and so the seal too, which binds the claimed index to ++ * the identity of whoever sends the message. + * + * @param roundIdentifier the round identifier + * @param digest the digest + * @param falconSeal the author's post-quantum seal, or empty + * @return the prepare + */ + public Prepare createPrepare( + final ConsensusRoundIdentifier roundIdentifier, + final Hash digest, + final Optional falconSeal) { + final PreparePayload payload = new PreparePayload(roundIdentifier, digest, falconSeal); + return new Prepare(createSignedMessage(payload)); + } + + /** + * Create commit payload. + * + * @param roundIdentifier the round identifier + * @param digest the digest + * @param commitSeal the commit seal +diff --git a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/PreparePayload.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/PreparePayload.java +index 727cbccc81..dea9b70233 100644 +--- a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/PreparePayload.java ++++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/PreparePayload.java +@@ -5,73 +5,76 @@ + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0003-aere-pq-anchor.patch. + */ + package org.hyperledger.besu.consensus.qbft.core.payload; + + import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; + import org.hyperledger.besu.consensus.common.bft.FalconSeal; ++import org.hyperledger.besu.consensus.common.bft.PqAnchor; ++import org.hyperledger.besu.consensus.common.bft.PqSealed; + import org.hyperledger.besu.consensus.common.bft.payload.Payload; + import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1; + import org.hyperledger.besu.datatypes.Hash; + import org.hyperledger.besu.ethereum.rlp.RLPException; + import org.hyperledger.besu.ethereum.rlp.RLPInput; + import org.hyperledger.besu.ethereum.rlp.RLPOutput; + + import java.util.Objects; + import java.util.Optional; + import java.util.StringJoiner; + + import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.bytes.Bytes32; + + /** + * The Prepare payload. + * + *

    AERE PQ (2026-08-28), step 1 of PREPARE-SI-ROUNDCHANGE-SUB-PQ-PROIECTARE-2026-08-28: a PREPARE + * MAY carry an OPTIONAL Falcon-512 seal from its author, appended at the end, exactly as + * {@code CommitPayload} does. A PREPARE without a seal encodes byte for byte as upstream, + * and that is precisely the property that lets the binary be rolled onto a live fleet without a + * flag day. + * + *

    NOTHING EMITS SUCH A PREPARE YET. This file only makes the wire capable of carrying one + * and of refusing a malformed one. Emission is the next step and has its own gate, following the + * rule paid for at commit: first the binary everywhere, then emission, and only much later + * enforcement. + * + *

    What the seal signs is NOT this file's business, and the design note states it: its own + * domain {@code AERE-PQ-PREPARE-1} over (chainId, number, ROUND, digest). If it signed the same + * bytes as a commit seal, a PREPARE seal given honestly could be pasted onto a forged COMMIT and + * the enforcement there would accept it. + */ +-public class PreparePayload extends QbftPayload { ++public class PreparePayload extends QbftPayload implements PqSealed { + private static final int TYPE = QbftV1.PREPARE; + private final ConsensusRoundIdentifier roundIdentifier; + private final Hash digest; + private final Optional falconSeal; + + /** + * Instantiates a new Prepare payload, without a post-quantum seal. Encodes byte-for-byte as + * upstream Besu. + * + * @param roundIdentifier the round identifier + * @param digest the digest + */ + public PreparePayload(final ConsensusRoundIdentifier roundIdentifier, final Hash digest) { + this(roundIdentifier, digest, Optional.empty()); + } + + /** + * Instantiates a new Prepare payload carrying an optional Falcon-512 seal of its author. + * + * @param roundIdentifier the round identifier +@@ -154,44 +157,56 @@ public class PreparePayload extends QbftPayload { + + @Override + public int getMessageType() { + return TYPE; + } + + /** + * Gets digest. + * + * @return the digest + */ + public Hash getDigest() { + return digest; + } + + /** + * The author's post-quantum seal, when the message carries one. + * + * @return the seal, or empty + */ ++ @Override + public Optional getFalconSeal() { + return falconSeal; + } + ++ /** AIP-22 stage 4: the PREPARE seal's message, as PqPrepareEnforcement builds it. */ ++ @Override ++ public Optional pqSealMessage(final long chainId) { ++ return Optional.of( ++ PqAnchor.prepareMessage( ++ chainId, ++ roundIdentifier.getSequenceNumber(), ++ roundIdentifier.getRoundNumber(), ++ digest.getBytes())); ++ } ++ + @Override + public ConsensusRoundIdentifier getRoundIdentifier() { + return roundIdentifier; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final PreparePayload that = (PreparePayload) o; + return Objects.equals(roundIdentifier, that.roundIdentifier) + && Objects.equals(digest, that.digest) + && Objects.equals(falconSeal, that.falconSeal); + } + + @Override +diff --git a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/ProposalPayload.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/ProposalPayload.java +index 813e798a97..ada90e3cd9 100644 +--- a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/ProposalPayload.java ++++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/ProposalPayload.java +@@ -5,82 +5,85 @@ + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0003-aere-pq-anchor.patch. + */ + package org.hyperledger.besu.consensus.qbft.core.payload; + + import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; + import org.hyperledger.besu.consensus.common.bft.FalconSeal; ++import org.hyperledger.besu.consensus.common.bft.PqAnchor; ++import org.hyperledger.besu.consensus.common.bft.PqSealed; + import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1; + import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock; + import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec; + import org.hyperledger.besu.ethereum.core.encoding.BlockAccessListDecoder; + import org.hyperledger.besu.ethereum.mainnet.block.access.list.BlockAccessList; + import org.hyperledger.besu.ethereum.rlp.RLPException; + import org.hyperledger.besu.ethereum.rlp.RLPInput; + import org.hyperledger.besu.ethereum.rlp.RLPOutput; + + import java.util.Objects; + import java.util.Optional; + + import com.google.common.base.MoreObjects; ++import org.apache.tuweni.bytes.Bytes32; + + /** + * The Proposal payload. + * + *

    AERE PQ (2026-08-30), the hot-path step after PREPARE: a PROPOSAL MAY carry an OPTIONAL + * Falcon-512 seal from its proposer, appended after the block-access-list element, exactly as + * {@code PreparePayload} appends its seal. A proposal without a seal encodes byte for byte as + * upstream, which is the property that lets the binary be rolled onto a live fleet without a + * flag day. + * + *

    NOTHING EMITS SUCH A PROPOSAL YET. This file only makes the wire capable of carrying + * one and of refusing a malformed one. Emission has its own gate + * ({@code aere.pq.proposalPq.attachBlock}); enforcement has its own height + * ({@code aere.pq.proposalPq.forkBlock}); both are absent on every node today, and absent means + * never. + * + *

    What the seal signs is NOT this file's business: its own domain + * {@code AERE-PQ-PROPOSAL-1} over (chainId, height, ROUND, digest) - see + * {@code PqAnchor.proposalMessage}. A proposal is an offer, not a vote: with the commit or PREPARE + * domain, a proposal seal given honestly could be pasted onto a forged vote and counted. + * + *

    Why the trailing element is parsed strictly: the payload is AUTHENTICATED - the author + * is recovered from the signature over the encoded payload. A decoder that silently ignored an + * unknown trailing element would re-encode without it, so two different byte strings would + * authenticate to the same proposer. When a fifth element is present it must be exactly a seal, + * and it must be the last element; otherwise the message is refused. Messages of the upstream + * shapes (three or four elements) are read exactly as upstream reads them. + */ +-public class ProposalPayload extends QbftPayload { ++public class ProposalPayload extends QbftPayload implements PqSealed { + + private static final int TYPE = QbftV1.PROPOSAL; + private final ConsensusRoundIdentifier roundIdentifier; + private final QbftBlock proposedBlock; + private final QbftBlockCodec blockEncoder; + private final Optional blockAccessList; + private final Optional falconSeal; + + /** + * Instantiates a new Proposal payload carrying an optional post-quantum seal of its proposer. + * + * @param roundIdentifier the round identifier + * @param proposedBlock the proposed block + * @param blockEncoder the qbft block encoder + * @param blockAccessList the block access list + * @param falconSeal the proposer's post-quantum seal, or empty + */ + public ProposalPayload( + final ConsensusRoundIdentifier roundIdentifier, + final QbftBlock proposedBlock, +@@ -185,44 +188,56 @@ public class ProposalPayload extends QbftPayload { + * @return the proposed block + */ + public QbftBlock getProposedBlock() { + return proposedBlock; + } + + /** + * Gets block access list. + * + * @return the block access list + */ + public Optional getBlockAccessList() { + return blockAccessList; + } + + /** + * The proposer's post-quantum seal, when the message carries one. + * + * @return the seal, or empty + */ ++ @Override + public Optional getFalconSeal() { + return falconSeal; + } + ++ /** AIP-22 stage 4: the PROPOSAL seal's message over the proposed block's hash, as PqProposalEnforcement builds it. */ ++ @Override ++ public Optional pqSealMessage(final long chainId) { ++ return Optional.of( ++ PqAnchor.proposalMessage( ++ chainId, ++ roundIdentifier.getSequenceNumber(), ++ roundIdentifier.getRoundNumber(), ++ proposedBlock.getHash().getBytes())); ++ } ++ + @Override + public int getMessageType() { + return TYPE; + } + + @Override + public ConsensusRoundIdentifier getRoundIdentifier() { + return roundIdentifier; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProposalPayload that = (ProposalPayload) o; + return Objects.equals(roundIdentifier, that.roundIdentifier) +diff --git a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/RoundChangePayload.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/RoundChangePayload.java +index 8804b6a46c..736b9e7299 100644 +--- a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/RoundChangePayload.java ++++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/RoundChangePayload.java +@@ -5,80 +5,83 @@ + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0003-aere-pq-anchor.patch. + */ + package org.hyperledger.besu.consensus.qbft.core.payload; + + import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; + import org.hyperledger.besu.consensus.common.bft.FalconSeal; ++import org.hyperledger.besu.consensus.common.bft.PqAnchor; ++import org.hyperledger.besu.consensus.common.bft.PqSealed; + import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1; + import org.hyperledger.besu.ethereum.rlp.RLPException; + import org.hyperledger.besu.ethereum.rlp.RLPInput; + import org.hyperledger.besu.ethereum.rlp.RLPOutput; + + import java.util.Objects; + import java.util.Optional; + + import com.google.common.base.MoreObjects; ++import org.apache.tuweni.bytes.Bytes32; + + /** + * The Round change payload. + * + *

    AERE PQ (2026-08-31), the LAST hot-path message: a ROUND-CHANGE MAY carry an OPTIONAL + * Falcon-512 seal from its author, appended after the prepared-metadata list, exactly as {@code + * ProposalPayload} appends its seal. A round-change without a seal encodes byte for byte as + * upstream, which is the property that lets the binary be rolled onto a live fleet without a + * flag day. + * + *

    NOTHING EMITS SUCH A ROUND-CHANGE YET. This file only makes the wire capable of + * carrying one and of refusing a malformed one. Emission has its own gate + * ({@code aere.pq.roundChangePq.attachBlock}); enforcement has its own height + * ({@code aere.pq.roundChangePq.forkBlock}); both are absent on every node today, and absent means + * never. + * + *

    What the seal signs is NOT this file's business: its own domain + * {@code AERE-PQ-ROUNDCHANGE-1} over (chainId, height, targetRound, prepared metadata) - see + * {@code PqAnchor.roundChangeMessage}. A round-change STEERS rounds: a quorum of them opens a new + * round, and one claiming a prepared block decides which block gets re-proposed. Its seal must be + * transferable neither onto a vote nor onto a proposal, nor between a bare round-change and one + * with metadata. + * + *

    Why the trailing element is parsed strictly: the payload is AUTHENTICATED - the author + * is recovered from the signature over the encoded payload. A decoder that silently ignored an + * unknown trailing element would re-encode without it, so two different byte strings would + * authenticate to the same author. When a fourth element is present it must be exactly a seal, and + * it must be the last element; otherwise the message is refused. Messages of the upstream shape + * (three elements) are read exactly as upstream reads them. + */ +-public class RoundChangePayload extends QbftPayload { ++public class RoundChangePayload extends QbftPayload implements PqSealed { + private static final int TYPE = QbftV1.ROUND_CHANGE; + private final ConsensusRoundIdentifier roundChangeIdentifier; + private final Optional preparedRoundMetadata; + private final Optional falconSeal; + + /** + * Instantiates a new Round change payload carrying an optional post-quantum seal of its author. + * + * @param roundChangeIdentifier the round change identifier + * @param preparedRoundMetadata the prepared round metadata + * @param falconSeal the author's post-quantum seal, or empty + */ + public RoundChangePayload( + final ConsensusRoundIdentifier roundChangeIdentifier, + final Optional preparedRoundMetadata, + final Optional falconSeal) { + this.roundChangeIdentifier = roundChangeIdentifier; + this.preparedRoundMetadata = preparedRoundMetadata; + this.falconSeal = falconSeal == null ? Optional.empty() : falconSeal; + } +@@ -98,44 +101,61 @@ public class RoundChangePayload extends QbftPayload { + + @Override + public ConsensusRoundIdentifier getRoundIdentifier() { + return roundChangeIdentifier; + } + + /** + * Gets prepared round metadata. + * + * @return the prepared round metadata + */ + public Optional getPreparedRoundMetadata() { + return preparedRoundMetadata; + } + + /** + * The author's post-quantum seal, when the message carries one. + * + * @return the seal, or empty + */ ++ @Override + public Optional getFalconSeal() { + return falconSeal; + } + ++ /** AIP-22 stage 4: the ROUND-CHANGE seal's message, prepared or not, as PqRoundChangeEnforcement builds it. */ ++ @Override ++ public Optional pqSealMessage(final long chainId) { ++ final long height = roundChangeIdentifier.getSequenceNumber(); ++ final int targetRound = roundChangeIdentifier.getRoundNumber(); ++ return Optional.of( ++ preparedRoundMetadata.isPresent() ++ ? PqAnchor.roundChangeMessage( ++ chainId, ++ height, ++ targetRound, ++ preparedRoundMetadata.get().getPreparedRound(), ++ preparedRoundMetadata.get().getPreparedBlockHash().getBytes()) ++ : PqAnchor.roundChangeMessage(chainId, height, targetRound)); ++ } ++ + @Override + public void writeTo(final RLPOutput rlpOutput) { + // RLP encode of the message data content (round identifier and prepared certificate) + rlpOutput.startList(); + writeConsensusRound(rlpOutput); + + rlpOutput.startList(); + preparedRoundMetadata.ifPresent(prm -> prm.writeTo(rlpOutput)); + rlpOutput.endList(); + + // The seal is written only when present, so a seal-less round-change is identical to upstream. + if (falconSeal.isPresent()) { + final FalconSeal fs = falconSeal.get(); + rlpOutput.startList(); + rlpOutput.writeIntScalar(fs.getValidatorIndex()); + rlpOutput.writeBytes(fs.getSignature()); + rlpOutput.endList(); + } + + rlpOutput.endList(); +diff --git a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRound.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRound.java +index 3d0138d9c5..8dc438b412 100644 +--- a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRound.java ++++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRound.java +@@ -5,40 +5,41 @@ + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0003-aere-pq-anchor.patch. + */ + package org.hyperledger.besu.consensus.qbft.core.statemachine; + + import static java.util.Collections.emptyList; + ++import org.hyperledger.besu.consensus.common.bft.AerePqHeaderSeal; + import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; + import org.hyperledger.besu.consensus.common.bft.FalconSeal; + import org.hyperledger.besu.consensus.common.bft.FalconSealSupport; + import org.hyperledger.besu.consensus.common.bft.PqAnchor; + import org.hyperledger.besu.consensus.common.bft.PqAnchorNotReadyException; + import org.hyperledger.besu.consensus.common.bft.PqSealCache; + import org.hyperledger.besu.consensus.common.bft.RoundTimer; + import org.hyperledger.besu.consensus.common.bft.blockcreation.PqAnchorProducer; + import org.hyperledger.besu.consensus.common.bft.payload.SignedData; + import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; + import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; + import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; + import org.hyperledger.besu.consensus.qbft.core.network.QbftMessageTransmitter; + import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; + import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; + import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; + import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock; + import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCreator; + import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCreator.BlockCreationResult; + import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader; +@@ -87,40 +88,60 @@ public class QbftRound { + private final QbftMessageTransmitter transmitter; + + private final QbftBlockHeader parentHeader; + + // AERE hybrid PQC: guards against re-importing once a block has been successfully imported this + // round, while still allowing a retry if an earlier import attempt was rejected (e.g. a post-fork + // Falcon quorum certificate that was not yet complete when the first attempt ran). + private boolean blockImported = false; + + // AERE ANCHOR V2: the ROUND-INDEPENDENT on-chain hash of the block this round is deciding. + // + // Why it is not simply block.getHash(): a proposal block is built with the COMMITTED-SEAL header + // functions, so its hash includes the round number and differs between rounds for one and the + // same block. The certificate carried by the NEXT block is looked up, and its message M is built, + // from the parent's on-chain hash, which excludes both the commit seals and the round. Keying the + // seal cache on anything round dependent would silently produce empty certificates at every round + // change. Replacing the round with 0 in the committed-seal encoding yields byte-for-byte the + // on-chain pre-image, so this is the same hash the parent header will carry once imported. + private Hash pqOnchainHash; + ++ // AERE D-337 (2026-09-28): the post-quantum seals of THIS node's Commit in this round, signed ONCE. ++ // ++ // Two paths emit this node's Commit: accepting the proposal (the local copy, and the wire copy in ++ // the rare case the node is already prepared) and becoming prepared later (the wire copy, the ++ // usual case). Each used to sign on its own, so at the parent of an anchor every Besu validator ++ // made two SLH-DSA signatures back to back on the consensus thread, the first before its Prepare ++ // and the second between "prepared" and its Commit. Measured on 2800 (2026-09-28, import times in ++ // ms measured at a reading node of the network): the anchor-parent slot 1,036 ms against ++ // 599 for the other slots. The message is fixed by (block, commit hash), both fixed for the round ++ // once the proposal is accepted, so the second signing could only produce another valid seal over ++ // the same bytes. It now reuses the first, and the local and wire Commits carry the same seals ++ // (Falcon is randomised: before this, they carried two different valid Falcon seals). ++ // ++ // What is NOT reused: an attempt that produced no Falcon seal, or no extras where extras apply. ++ // Those are retried exactly as before, so a node whose first attempt failed keeps its second chance. ++ private Hash pqSealedCommitHash; ++ private Optional pqSealedFalcon = Optional.empty(); ++ private java.util.List pqSealedExtras = ++ java.util.List.of(); ++ + /** + * Instantiates a new Qbft round. + * + * @param roundState the round state + * @param blockCreator the block creator + * @param blockInterface the block interface + * @param protocolSchedule the protocol schedule + * @param observers the observers + * @param nodeKey the node key + * @param localAddress the local address + * @param messageFactory the message factory + * @param transmitter the transmitter + * @param roundTimer the round timer + * @param parentHeader the parent header + */ + public QbftRound( + final RoundState roundState, + final QbftBlockCreator blockCreator, + final QbftBlockInterface blockInterface, + final QbftProtocolSchedule protocolSchedule, +@@ -411,44 +432,46 @@ public class QbftRound { + + private boolean updateStateWithProposedBlock(final Proposal msg) { + final boolean wasPrepared = roundState.isPrepared(); + final boolean blockAccepted = roundState.setProposedBlock(msg); + + if (blockAccepted) { + final QbftBlock block = roundState.getProposedBlock().get(); + + // AERE hybrid PQC: compute the commit hash once, then produce BOTH the decisive ECDSA commit + // seal and the parallel Falcon-512 seal over the SAME commit hash. The Falcon seal is gossiped + // on the commit message so every validator's post-quantum seal reaches the block assembler. + final Hash commitHash; + final SECPSignature commitSeal; + try { + commitHash = commitHashFor(block); + commitSeal = nodeKey.sign(Bytes32.wrap(commitHash.getBytes())); + } catch (final SecurityModuleException e) { + LOG.warn("Failed to construct commit seal; {}", e.getMessage()); + return true; + } +- final Optional falconSeal = falconSealFor(block, commitHash); +- // AERE HYBRID: the other schemes' extras, over the SAME message; empty on any node today. ++ // AERE HYBRID: the Falcon seal and the other schemes' extras, over the SAME message, signed ++ // once per round (D-337, pqSealCommitOnce). ++ pqSealCommitOnce(block, commitHash); ++ final Optional falconSeal = pqSealedFalcon; + final java.util.List extraSeals = +- falconSeal.isPresent() ? extraSealsFor(block, commitHash) : java.util.List.of(); ++ pqSealedExtras; + + // There are times handling a proposed block is enough to enter prepared. + if (wasPrepared != roundState.isPrepared()) { + LOG.debug("Sending commit message. round={}", roundState.getRoundIdentifier()); + if (!extraSeals.isEmpty()) { + transmitter.multicastCommit( + getRoundIdentifier(), block.getHash(), commitSeal, falconSeal, extraSeals); + } else if (falconSeal.isPresent()) { + transmitter.multicastCommit(getRoundIdentifier(), block.getHash(), commitSeal, falconSeal); + } else { + transmitter.multicastCommit(getRoundIdentifier(), block.getHash(), commitSeal); + } + } + + // can automatically add _our_ commit message to the roundState + // cannot create a prepare message here, as it may be _our_ proposal, and thus we cannot also + // prepare + try { + final Commit localCommitMessage = + falconSeal.isPresent() +@@ -469,44 +492,46 @@ public class QbftRound { + // AERE ANCHOR V2: remember every Falcon seal heard for THIS block, so the proposer of the + // NEXT block can carry a certificate over it. This is the local node's own seal. + pqCacheHeardSeals(block); + + // It is possible sufficient commit seals are now available and the block should be imported + maybeImportBlock(); + } + + return blockAccepted; + } + + private void peerIsPrepared(final Prepare msg) { + final boolean wasPrepared = roundState.isPrepared(); + roundState.addPrepareMessage(msg); + if (wasPrepared != roundState.isPrepared()) { + LOG.debug("Sending commit message. round={}", roundState.getRoundIdentifier()); + final QbftBlock block = roundState.getProposedBlock().get(); + try { + final Hash commitHash = commitHashFor(block); + final SECPSignature commitSeal = nodeKey.sign(Bytes32.wrap(commitHash.getBytes())); +- final Optional falconSeal = falconSealFor(block, commitHash); +- // AERE HIBRID: aceleasi extrase si pe drumul tarziu, ca cele doua locuri sa nu divearga. ++ // AERE HIBRID: aceleasi sigilii si pe drumul tarziu, ca cele doua locuri sa nu divearga; D-337: ++ // chiar ACELEASI, semnate o data la acceptarea propunerii, nu o a doua semnare SLH-DSA aici. ++ pqSealCommitOnce(block, commitHash); ++ final Optional falconSeal = pqSealedFalcon; + final java.util.List extraSeals = +- falconSeal.isPresent() ? extraSealsFor(block, commitHash) : java.util.List.of(); ++ pqSealedExtras; + if (!extraSeals.isEmpty()) { + transmitter.multicastCommit( + getRoundIdentifier(), block.getHash(), commitSeal, falconSeal, extraSeals); + } else if (falconSeal.isPresent()) { + transmitter.multicastCommit(getRoundIdentifier(), block.getHash(), commitSeal, falconSeal); + } else { + transmitter.multicastCommit(getRoundIdentifier(), block.getHash(), commitSeal); + } + // Note: the local-node's commit message was added to RoundState on block acceptance + // and thus does not need to be done again here. + } catch (final SecurityModuleException e) { + LOG.warn("Failed to construct a commit seal: {}", e.getMessage()); + } + } + } + + private void peerIsCommitted(final Commit msg) { + roundState.addCommitMessage(msg); + // AERE ANCHOR V2: top up the seal cache on EVERY commit, including commits that arrive after + // this node has already imported the block. Those late seals are exactly the ones that let a +@@ -522,53 +547,79 @@ public class QbftRound { + maybeImportBlock(); + } + + private void maybeImportBlock() { + if (roundState.isCommitted() && !blockImported) { + importBlockToChain(); + } + } + + private void importBlockToChain() { + + // AERE hybrid PQC: pass the gossiped Falcon seals collected from commit messages so the block + // assembler can embed the post-quantum certificate. When no Falcon seals were gossiped (Falcon + // disabled), fall back to the unchanged ECDSA-only sealing path. + // + // WHAT GETS EMBEDDED, corrected 2026-08-19 (finding D-235): NOT a per-block 2f+1 quorum. The + // assembler writes a certificate only at an anchor height, over the PARENT, and it needs at + // least K valid seals, K being the configured schedule (6 of 9 on chain 2800 today). Between + // anchor heights nothing is written. The older wording here said "a >= 2f+1 Falcon quorum + // certificate" and described the legacy per-block rule, which is retired at the anchor block. ++ // AERE AIP-22 stage 5: from H_hdr the sealed header carries no ECDSA committed seal and the ++ // accepted proposal's post-quantum seal as element 6 (the same bytes on every node). A proposal ++ // without one cannot have been accepted from H_fin <= H_hdr; if it happens anyway nothing is ++ // imported, because the only other header this node could build is one every node refuses. ++ final long aereHeight = roundState.getRoundIdentifier().getSequenceNumber(); ++ if (AerePqHeaderSeal.active(aereHeight)) { ++ final Optional proposerSeal = roundState.getProposalFalconSeal(); ++ if (proposerSeal.isEmpty()) { ++ LOG.error( ++ "AERE-PQC-HDR-02: committed at {} but the accepted proposal carries no post-quantum seal;" ++ + " a header from H_hdr cannot be sealed without it. Not importing.", ++ aereHeight); ++ return; ++ } ++ importSealedBlock( ++ blockCreator.createSealedBlockWithProposerSeal( ++ roundState.getProposedBlock().get(), ++ roundState.getRoundIdentifier().getRoundNumber(), ++ proposerSeal.get())); ++ return; ++ } + final Collection falconSeals = roundState.getFalconSeals(); + final QbftBlock blockToImport = + falconSeals.isEmpty() + ? blockCreator.createSealedBlock( + roundState.getProposedBlock().get(), + roundState.getRoundIdentifier().getRoundNumber(), + roundState.getCommitSeals()) + : blockCreator.createSealedBlock( + roundState.getProposedBlock().get(), + roundState.getRoundIdentifier().getRoundNumber(), + roundState.getCommitSeals(), + falconSeals); + ++ importSealedBlock(blockToImport); ++ } ++ ++ /** Imports a sealed block into the chain (shared by the stage-5 and the ECDSA sealing paths). */ ++ private void importSealedBlock(final QbftBlock blockToImport) { + final long blockNumber = blockToImport.getHeader().getNumber(); + if (getRoundIdentifier().getRoundNumber() > 0) { + LOG.info( + "Importing proposed block to chain. round={}, hash={}", + getRoundIdentifier(), + blockToImport.getHash()); + } else { + LOG.debug( + "Importing proposed block to chain. round={}, hash={}", + getRoundIdentifier(), + blockToImport.getHash()); + } + + final QbftBlockImporter blockImporter = + protocolSchedule.getBlockImporter(blockToImport.getHeader()); + final boolean result = + blockImporter.importBlock(blockToImport, roundState.getProposedBlockAccessList()); + if (!result) { + // Do NOT set blockImported: a post-fork block whose Falcon quorum certificate is not yet + // complete can be retried as more commits (with valid Falcon seals) arrive this round. +@@ -643,93 +694,122 @@ public class QbftRound { + /** + * AERE ANCHOR V2: the round-independent on-chain hash of the block this round is deciding, + * computed once per round. Replacing the round with 0 in the committed-seal encoding produces + * byte-for-byte the on-chain pre-image, because that encoding differs from the on-chain one only + * by writing the real round instead of a forced zero. + */ + private Hash pqOnchainHashOf(final QbftBlock block) { + if (pqOnchainHash == null) { + pqOnchainHash = blockInterface.replaceRoundForCommitBlock(block, 0).getHash(); + } + return pqOnchainHash; + } + + /** + * AERE HIBRID (2026-08-25): the non-Falcon seals of this node's hybrid certificate, over the + * SAME message the Falcon seal signs (the two are one certificate; two messages would be two + * certificates and the verifier could not bind them). Empty on every node that is not + * hybrid-configured, and below the emission gate: {@link HybridSealProducer} never throws and + * never emits half a certificate. + */ +- private java.util.List extraSealsFor( ++ java.util.List extraSealsFor( + final QbftBlock block, final Hash commitHash) { + // ANCHOR PARENTS ONLY (2026-09-03, D-329): an SLH-DSA-128s signature costs seconds here; it is + // only ever used in the next anchor's certificate, which is built over the anchor's parent. So + // the extras are signed only when the block being committed is the parent of an anchor height. + // The same predicate gates the enforcement (PqCommitEnforcement.anchorParentByConfig). + final long number = block.getHeader().getNumber(); +- if (!org.hyperledger.besu.consensus.common.bft.blockcreation.PqAnchorProducer.config() +- .anchorAppliesAt(number + 1L)) { ++ if (!pqExtrasApplyAt(number)) { + return java.util.List.of(); + } + return hybridExtrasOrEmpty(number, pqSealMessageFor(block, commitHash)); + } + ++ /** The anchor-parent predicate of {@link #extraSealsFor}, in one place for it and the D-337 reuse. */ ++ static boolean pqExtrasApplyAt(final long number) { ++ return org.hyperledger.besu.consensus.common.bft.blockcreation.PqAnchorProducer.config() ++ .anchorAppliesAt(number + 1L); ++ } ++ ++ /** ++ * D-337 (2026-09-28): signs this node's Commit seals for this round at most once. A result is ++ * reused only when it is complete - a Falcon seal, and the extras wherever extras apply - so an ++ * attempt that failed is retried on the next path exactly as before this change. ++ * ++ *

    Package-private, with {@link #falconSealFor} and {@link #extraSealsFor}, for the probe that ++ * counts the signings on the two paths (PqCommitSealsSignedOnceTest). ++ * ++ * @param block the proposed block of this round ++ * @param commitHash its commit hash in this round ++ */ ++ void pqSealCommitOnce(final QbftBlock block, final Hash commitHash) { ++ if (commitHash.equals(pqSealedCommitHash) ++ && pqSealedFalcon.isPresent() ++ && (!pqSealedExtras.isEmpty() || !pqExtrasApplyAt(block.getHeader().getNumber()))) { ++ return; ++ } ++ final Optional falcon = falconSealFor(block, commitHash); ++ pqSealedExtras = ++ falcon.isPresent() ? extraSealsFor(block, commitHash) : java.util.List.of(); ++ pqSealedFalcon = falcon; ++ pqSealedCommitHash = commitHash; ++ } ++ + /** + * D-334 (2026-09-03, mainnet 2800, 125 s of halted chain): the hybrid loader is lazy, so a + * registry the container could not read surfaced here, as an exception thrown INTO the QBFT + * state machine, at every anchor parent, on every armed node. Three such nodes plus one node + * restarting left five of nine. A broken hybrid configuration may cost this node its SLH-DSA + * contribution; it must never cost the node its vote. The loader still refuses to START on the + * same defect (QbftBesuControllerBuilder calls it at boot), so this catch is the second net. + * + * @param number the height being committed + * @param message the seal message + * @return the extras, or an empty list with an ERROR line when the hybrid support cannot sign + */ + static java.util.List hybridExtrasOrEmpty( + final long number, final Bytes32 message) { + try { + return org.hyperledger.besu.consensus.common.bft.HybridSealSupport.instance() + .producer() + .sealsFor(number, message); + } catch (final RuntimeException e) { + LOG.error( + "AERE HIBRID: extras NOT signed at height {} - {}. This node keeps voting but contributes no" + + " SLH-DSA seal until the hybrid configuration is repaired (D-334).", + number, + e.getMessage()); + return java.util.List.of(); + } + } + + /** The exact bytes a PQ seal over this block signs; shared by Falcon and the hybrid extras, + * so the two halves of a hybrid certificate can never drift onto different messages. */ + private Bytes32 pqSealMessageFor(final QbftBlock block, final Hash commitHash) { + // AERE D-311 (2026-09-02): the form is decided in ONE place, shared with the verifier + // (MessageValidator.SubsequentMessageValidator). A second copy of this rule drifted once and + // stopped a chain; see PqAnchorProducer.commitSealMessage. + return PqAnchorProducer.commitSealMessage( + block.getHeader().getNumber(), () -> pqOnchainHashOf(block).getBytes(), commitHash); + } + +- private Optional falconSealFor(final QbftBlock block, final Hash commitHash) { ++ Optional falconSealFor(final QbftBlock block, final Hash commitHash) { + // FalconSealSupport.sign never throws (any fault is swallowed and logged), and returns empty + // when this node holds no Falcon signing key, so the ECDSA commit path is never affected. + // + // AERE FIX-OPRIRE-CONSENS (b): the block NUMBER is now a mandatory argument. Seal ATTACHMENT is + // gated on the activation height (and on registry coverage of the whole validator set) inside + // FalconSealSupport.sign, so merely holding a Falcon key no longer makes a node emit a + // Falcon-carrying Commit. There is deliberately no height-less sign() overload left: a call site + // physically cannot bypass the gate. + // + // AERE ANCHOR V2: WHAT IS SIGNED changes one block BEFORE the anchor activates, because the + // certificate carried by block H is made of seals over block H-1. From that height the message + // is M = keccak256(RLP["AERE-PQ-COMMIT-1", chainId, number, ON-CHAIN block hash]) instead of the + // ECDSA committed-seal hash. The committed-seal hash could not be used: it includes the ROUND, + // which is not in the block-hash pre-image, so a validator holding only the parent header could + // not rebuild it. Every node flips at the same height, since the height is a pure function of + // the same configured H; a node configured with a different H emits seals nobody can use, and + // the producer drops them on verification rather than carrying them into a header. + // AERE HIBRID (2026-08-25): mesajul se calculeaza acum intr-UN singur loc, pqSealMessageFor, + // impartit cu extrasele hibride; doua copii ale acestei logici ar fi divergat intr-o zi. + final long blockNumber = block.getHeader().getNumber(); +diff --git a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRoundFactory.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRoundFactory.java +index f9c6cf7734..a7979513de 100644 +--- a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRoundFactory.java ++++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRoundFactory.java +@@ -1,36 +1,43 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/0008-aere-pq-aip22.patch. + */ + package org.hyperledger.besu.consensus.qbft.core.statemachine; + ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; + import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; + import org.hyperledger.besu.consensus.qbft.core.network.QbftMessageTransmitter; + import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; + import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCreator; + import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCreatorFactory; + import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader; + import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockInterface; + import org.hyperledger.besu.consensus.qbft.core.types.QbftFinalState; + import org.hyperledger.besu.consensus.qbft.core.types.QbftMinedBlockObserver; + import org.hyperledger.besu.consensus.qbft.core.types.QbftProtocolSchedule; + import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidatorFactory; + import org.hyperledger.besu.util.Subscribers; + + /** The Qbft round factory. */ + public class QbftRoundFactory { + + private final QbftFinalState finalState; + private final QbftBlockCreatorFactory blockCreatorFactory; + private final QbftBlockInterface blockInterface; + private final QbftProtocolSchedule protocolSchedule; +@@ -91,27 +98,27 @@ public class QbftRoundFactory { + * @param parentHeader the parent header + * @param roundState the round state + * @return the qbft round + */ + public QbftRound createNewRoundWithState( + final QbftBlockHeader parentHeader, final RoundState roundState) { + final QbftBlockCreator blockCreator = + blockCreatorFactory.create(roundState.getRoundIdentifier().getRoundNumber()); + + // TODO(tmm): Why is this created everytime?! + final QbftMessageTransmitter messageTransmitter = + new QbftMessageTransmitter(messageFactory, finalState.getValidatorMulticaster()); + + return new QbftRound( + roundState, + blockCreator, + blockInterface, + protocolSchedule, + minedBlockObservers, + finalState.getNodeKey(), +- finalState.getLocalAddress(), ++ AerePqIdentity.local(finalState.getLocalAddress(), parentHeader.getNumber() + 1L), + messageFactory, + messageTransmitter, + finalState.getRoundTimer(), + parentHeader); + } + } +diff --git a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/RoundState.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/RoundState.java +index 2c798c9e27..b7ba44b5a1 100644 +--- a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/RoundState.java ++++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/RoundState.java +@@ -149,40 +149,50 @@ public class RoundState { + committed = (commitMessages.size() >= quorum) && proposalMessage.isPresent(); + LOG.trace( + "Round state updated prepared={} committed={} preparedQuorum={}/{} committedQuorum={}/{}", + prepared, + committed, + prepareMessages.size(), + quorum, + commitMessages.size(), + quorum); + } + + /** + * Gets proposed block. + * + * @return the proposed block + */ + public Optional getProposedBlock() { + return proposalMessage.map(p -> p.getSignedPayload().getPayload().getProposedBlock()); + } + ++ /** ++ * AIP-22 stage 5: the post-quantum seal of the accepted proposal, which becomes element 6 of the ++ * sealed header from H_hdr (every node writes the same one, the proposer's). ++ * ++ * @return the proposal's seal, or empty ++ */ ++ public Optional getProposalFalconSeal() { ++ return proposalMessage.flatMap(p -> p.getSignedPayload().getPayload().getFalconSeal()); ++ } ++ + /** + * Gets proposed block access list. + * + * @return the block access list + */ + public Optional getProposedBlockAccessList() { + return proposalMessage.flatMap(Proposal::getBlockAccessList); + } + + /** + * Is prepared. + * + * @return the boolean + */ + public boolean isPrepared() { + return prepared; + } + + /** + * Is committed. +diff --git a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/types/QbftBlockCreator.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/types/QbftBlockCreator.java +index c397cab98f..af124c1ed0 100644 +--- a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/types/QbftBlockCreator.java ++++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/types/QbftBlockCreator.java +@@ -62,29 +62,45 @@ public interface QbftBlockCreator { + /** + * Create sealed block, additionally embedding a gossiped parallel Falcon-512 quorum certificate + * (AERE hybrid PQC). The default implementation ignores the Falcon seals and delegates to the + * ECDSA-only sealing, so existing implementations remain valid; the QBFT block creator adaptor + * overrides this to aggregate the Falcon seals into a per-block quorum certificate. + * + * @param block the block + * @param roundNumber the round number + * @param commitSeals the decisive ECDSA commit seals + * @param falconSeals the gossiped parallel Falcon-512 seals collected from commit messages + * @return the block + */ + default QbftBlock createSealedBlock( + final QbftBlock block, + final int roundNumber, + final Collection commitSeals, + final Collection falconSeals) { + return createSealedBlock(block, roundNumber, commitSeals); + } + ++ /** ++ * AIP-22 stage 5: seal a block from H_hdr, with NO ECDSA committed seal and the proposer's ++ * post-quantum seal as element 6, everything else of the proposed header carried over (the anchor ++ * certificate included). An implementation that cannot do this must say so, never seal the old way. ++ * ++ * @param block the proposed block ++ * @param roundNumber the round number ++ * @param proposerSeal the proposal's post-quantum seal ++ * @return the sealed block ++ */ ++ default QbftBlock createSealedBlockWithProposerSeal( ++ final QbftBlock block, final int roundNumber, final FalconSeal proposerSeal) { ++ throw new UnsupportedOperationException( ++ "AERE-PQC-HDR-02: this block creator cannot seal a stage-5 header (proposer seal, no ECDSA seals)"); ++ } ++ + /** + * Convenience empty Falcon seal collection. + * + * @return an empty collection of Falcon seals + */ + static Collection noFalconSeals() { + return Collections.emptyList(); + } + } +diff --git a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/CommitValidator.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/CommitValidator.java +index 918607ad2b..680c53f44a 100644 +--- a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/CommitValidator.java ++++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/CommitValidator.java +@@ -5,40 +5,41 @@ + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change: an OPTIONAL, height-gated post-quantum enforcement + * hook (see PqCommitEnforcement). When no enforcement is supplied, behaviour is byte-for-byte the + * upstream behaviour; the existing constructor keeps that contract for every existing caller. + */ + package org.hyperledger.besu.consensus.qbft.core.validation; + ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; + import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; + import org.hyperledger.besu.consensus.common.bft.payload.SignedData; + import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; + import org.hyperledger.besu.consensus.qbft.core.payload.CommitPayload; + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.datatypes.Hash; + import org.hyperledger.besu.ethereum.core.Util; + + import java.util.Collection; + import java.util.Optional; + + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + + /** The Commit validator. */ + public class CommitValidator { + + private static final String ERROR_PREFIX = "Invalid Commit Message"; + + private static final Logger LOG = LoggerFactory.getLogger(CommitValidator.class); +@@ -190,41 +191,43 @@ public class CommitValidator { + + if (!payload.getRoundIdentifier().equals(targetRound)) { + LOG.info( + "{}: did not target expected round {} was {}", + ERROR_PREFIX, + targetRound, + payload.getRoundIdentifier()); + return false; + } + + if (!payload.getDigest().equals(expectedDigest)) { + LOG.info( + "{}: did not contain expected digest {} was {}", + ERROR_PREFIX, + expectedDigest, + payload.getDigest()); + return false; + } + + final Address commitSealCreator = +- Util.signatureToAddress(payload.getCommitSeal(), expectedCommitDigest); ++ AerePqIdentity.author( ++ Util.signatureToAddress(payload.getCommitSeal(), expectedCommitDigest), ++ targetRound.getSequenceNumber()); + + if (!commitSealCreator.equals(signedPayload.getAuthor())) { + LOG.info( + "{}: Seal was not created by the message transmitter {} was {}", + ERROR_PREFIX, + commitSealCreator, + signedPayload.getAuthor()); + return false; + } + + // AERE full-PQ: above the arming height a commit vote only counts with a valid post-quantum + // seal bound to this very author. Below it (or with no enforcement supplied) nothing changes. + if (pqEnforcement != null) { + final Optional refusal = + pqEnforcement.refusal( + targetRound.getSequenceNumber(), + signedPayload.getAuthor(), + expectedPqSealMessage, + payload.getFalconSeal(), + payload.getExtraSeals()); +diff --git a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/PqCommitEnforcement.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/PqCommitEnforcement.java +index d1aa1be8e1..074459cbe7 100755 +--- a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/PqCommitEnforcement.java ++++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/PqCommitEnforcement.java +@@ -1,40 +1,41 @@ + /* + * AERE full-PQ consensus (TOP 3 list, item 1), step 1: the enforcement core. + * + * WHAT IT DECIDES. From the arming height upward, a Commit message counts toward the 2f+1 + * quorum ONLY if it carries the PQ seal (already transported in CommitPayload, live on the + * fleet) and the seal (a) exists, (b) has its index bound to the VERY author of the message + * through the height-indexed registry, (c) verifies over the commit digest. Without a valid + * PQ seal the vote does not count -- this puts post-quantum into the agreement itself, at the + * layer where the D-235 header rule could not live (headers between anchors carry no seals; + * the commit message can carry them all). + * + * HOW IT IS WIRED (updated the same night). CommitValidator calls it through the production + * constructor, which self-installs from fromSystemConfig(): absent property = null = + * upstream behaviour, DISARMED by default; a broken value = loud refusal, never a silent + * disarm. The core stays purely testable: the registry is injected (the PqSignerRegistry + * interface, which refuses by construction to answer without a height -- the D2 inheritance); + * the singleton enters only through the production factory, exactly like PqAnchorSealsRule. + */ + package org.hyperledger.besu.consensus.qbft.core.validation; + ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; + import org.hyperledger.besu.consensus.common.bft.FalconSeal; + import org.hyperledger.besu.consensus.common.bft.HybridSealSupport; + import org.hyperledger.besu.consensus.common.bft.HybridSignerRegistry; + import org.hyperledger.besu.consensus.common.bft.PqSchemeSchedule; + import org.hyperledger.besu.consensus.common.bft.PqSignerRegistry; + import org.hyperledger.besu.consensus.common.bft.SchemeSeal; + import org.hyperledger.besu.consensus.common.bft.SealScheme; + import org.hyperledger.besu.consensus.common.bft.SealSchemes; + import org.hyperledger.besu.consensus.common.bft.blockcreation.PqAnchorProducer; + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.datatypes.Hash; + + import java.util.List; + import java.util.Optional; + import java.util.Set; + import java.util.function.LongPredicate; + + import org.apache.tuweni.bytes.Bytes; + + /** Height-gated decision: does this Commit's PQ seal let it count toward quorum? */ +@@ -96,40 +97,42 @@ public final class PqCommitEnforcement { + // receives it too, so from the hybrid step of the schedule onward a vote without ALL the + // required schemes does not count. Without the pair, this stays exactly the Falcon + // enforcement we had until now. + final HybridSealSupport hybrid = HybridSealSupport.instance(); + if (hybrid.schedule().isPresent()) { + return new PqCommitEnforcement( + armedFrom, + PqSignerRegistry.falconSealSupport(), + hybrid.schedule().get(), + hybrid.registry().orElseThrow()); + } + return new PqCommitEnforcement(armedFrom, PqSignerRegistry.falconSealSupport()); + } + + private final long armedFromBlock; + private final PqSignerRegistry registry; + // AERE HIBRID: null in Falcon-only mode, which is every node today. + private final PqSchemeSchedule schemeSchedule; + private final HybridSignerRegistry hybridRegistry; + private final LongPredicate extrasRequiredAt; ++ // AIP-22 stage 2: the origin of the anchor grids, read lazily so tests need no live config ++ private final java.util.function.LongSupplier anchorBlock; + + /** + * @param armedFromBlock first block height (inclusive) at which enforcement applies; use + * {@link #DISARMED} for the today-behaviour + * @param registry the height-aware signer registry (injected, never a singleton) + */ + public PqCommitEnforcement(final long armedFromBlock, final PqSignerRegistry registry) { + this(armedFromBlock, registry, null, null); + } + + /** + * Enforcement that also demands the HYBRID schemes a schedule requires at each height. + * + *

    AERE HIBRID (2026-08-25). Above the arming height a vote must carry, besides the Falcon + * seal checked by the Falcon-only path, a valid seal for EVERY other scheme the schedule names + * at that height. The point of a hybrid is that the two families fail independently, so a + * partially satisfied certificate is worth exactly as much as the weakest family present, which + * is why a missing scheme refuses rather than degrades. + * + *

    NO REGISTRY-ALIGNMENT ASSUMPTION. The hybrid registry and the legacy Falcon registry are +@@ -162,45 +165,68 @@ public final class PqCommitEnforcement { + * + * @return the predicate "the block at this height is the parent of an anchor", from the live + * anchor configuration + */ + public static LongPredicate anchorParentByConfig() { + return h -> PqAnchorProducer.config().anchorAppliesAt(h + 1L); + } + + /** + * Full constructor. + * + * @param extrasRequiredAt at which heights the extra (non-Falcon) scheme seals are demanded on a + * commit; production passes {@link #anchorParentByConfig()} + */ + public PqCommitEnforcement( + final long armedFromBlock, + final PqSignerRegistry registry, + final PqSchemeSchedule schemeSchedule, + final HybridSignerRegistry hybridRegistry, + final LongPredicate extrasRequiredAt) { ++ this( ++ armedFromBlock, ++ registry, ++ schemeSchedule, ++ hybridRegistry, ++ extrasRequiredAt, ++ () -> PqAnchorProducer.config().anchorBlock()); ++ } ++ ++ /** ++ * Full constructor with an explicit anchor-grid origin (AIP-22 stage 2), for proofs that run ++ * a per-scheme interval schedule without the process-wide anchor configuration. ++ * ++ * @param anchorBlock supplies the chain's anchor activation height, origin of every grid ++ */ ++ public PqCommitEnforcement( ++ final long armedFromBlock, ++ final PqSignerRegistry registry, ++ final PqSchemeSchedule schemeSchedule, ++ final HybridSignerRegistry hybridRegistry, ++ final LongPredicate extrasRequiredAt, ++ final java.util.function.LongSupplier anchorBlock) { + this.armedFromBlock = armedFromBlock; + this.registry = registry; + this.schemeSchedule = schemeSchedule; + this.hybridRegistry = hybridRegistry; + this.extrasRequiredAt = extrasRequiredAt; ++ this.anchorBlock = anchorBlock; + if ((schemeSchedule == null) != (hybridRegistry == null)) { + // Half a hybrid configuration is the shape that starts a node believing it enforces + // something it does not. Refuse at construction, the same stance as every other AERE gate. + throw new IllegalStateException( + "AERE-PQC-COMMIT-CONF-03: the scheme schedule and the hybrid registry are a PAIR;" + + " configure both or neither."); + } + } + + /** Whether enforcement is active at {@code height}. */ + public boolean armedAt(final long height) { + return height >= armedFromBlock; + } + + /** + * Decide whether a Commit may count toward quorum. + * + * @param height the block height the commit targets (the round's sequence number) + * @param author the RECOVERED author of the signed Commit message (from its ECDSA signature) + * @param commitDigest the commit digest the PQ seal must have signed +@@ -226,88 +252,105 @@ public final class PqCommitEnforcement { + * @return empty when the commit counts; otherwise the refusal, with names and numbers + */ + public Optional refusal( + final long height, + final Address author, + final Hash commitDigest, + final Optional seal, + final List extraSeals) { + final Optional falconVerdict = falconRefusal(height, author, commitDigest, seal); + if (falconVerdict.isPresent() + || !armedAt(height) + || schemeSchedule == null + || !extrasRequiredAt.test(height)) { + return falconVerdict; + } + return hybridRefusal(height, author, commitDigest, seal.orElseThrow(), extraSeals); + } + + /** + * Every scheme the schedule names at this height, other than Falcon, must be present and valid. ++ * The height is an anchor PARENT (that is the only place extras are demanded), so the schemes ++ * are those the anchor at {@code height + 1} requires: with per-scheme intervals (AIP-22 stage ++ * 2) a commit at the parent of a Falcon-only anchor counts without an SLH-DSA seal. + */ + private Optional hybridRefusal( + final long height, + final Address author, + final Hash commitDigest, + final FalconSeal falconSeal, + final List extraSeals) { +- final Set required = schemeSchedule.schemesAt(height); ++ final Set required = ++ schemeSchedule.schemesRequiredForAnchor(height + 1L, anchorBlock.getAsLong()); + for (final String schemeId : required) { + if (SealSchemes.FALCON_512.id().equals(schemeId)) { + continue; // already decided by the Falcon path above + } + final Optional scheme = SealSchemes.byId(schemeId); + if (scheme.isEmpty()) { + return Optional.of( + "AERE HIBRID: the schedule requires scheme '" + schemeId + "' at height " + height + + " and this binary does not implement it - refusing rather than ignoring it"); + } + final byte wire = scheme.get().wireId(); + SchemeSeal found = null; + for (final SchemeSeal candidate : extraSeals) { + if (candidate.getSchemeWireId() == wire) { + found = candidate; + break; + } + } + if (found == null) { + return Optional.of( + "AERE HIBRID: commit at height " + height + " carries no " + schemeId + + " seal, which the schedule requires - the vote does not count"); + } + // One identity per message: the hybrid seal must speak for the same validator as the Falcon + // seal, and that index must be THIS author in the hybrid registry. Neither is assumed. + if (found.getValidatorIndex() != falconSeal.getValidatorIndex()) { + return Optional.of( + "AERE HIBRID: " + schemeId + " seal is index " + found.getValidatorIndex() + + " but the Falcon seal on the same commit is index " + + falconSeal.getValidatorIndex() + " - one commit, one signer"); + } +- final Optional bound = hybridRegistry.address(found.getValidatorIndex()); +- if (bound.isEmpty() +- || !Address.wrap(Bytes.wrap(bound.get())).equals(author)) { ++ // AIP-22 stage 3b: from H_k the keys and the index->author binding are those of the v3 epoch in force, as in the anchor ++ // producer and PqAnchorSealsRule. Paid 2026-09-23 on testnet 28001: this check alone still read the static v2 hybrid ++ // registry, so after the rotation at 3,097,600 the ROTATED row (index 2) signed with its new SLH-DSA key and every one of its ++ // commits at an anchor's parent was refused here; latent while four other validators sufficed, it stopped the chain at ++ // 3,135,679 when the Nethermind validator fell behind. ++ final boolean v3 = AerePqIdentity.keysFromV3(height); ++ final Optional

    boundId = ++ v3 ++ ? AerePqIdentity.v3IdAt(height, found.getValidatorIndex()) ++ : hybridRegistry ++ .address(found.getValidatorIndex()) ++ .map(a -> AerePqIdentity.author(Address.wrap(Bytes.wrap(a)), height)); ++ if (boundId.isEmpty() || !boundId.get().equals(author)) { + return Optional.of( + "AERE HIBRID: index " + found.getValidatorIndex() +- + " is not bound to the commit author " + author + " in the hybrid registry"); ++ + " is not bound to the commit author " + author ++ + (v3 ? " in the v3 epoch in force" : " in the hybrid registry")); + } + final Optional publicKey = +- hybridRegistry.publicKey(found.getValidatorIndex(), schemeId); ++ v3 ++ ? AerePqIdentity.v3KeyAt(height, found.getValidatorIndex(), schemeId) ++ : hybridRegistry.publicKey(found.getValidatorIndex(), schemeId); + if (publicKey.isEmpty()) { + return Optional.of( + "AERE HIBRID: the hybrid registry holds no " + schemeId + " key for index " + + found.getValidatorIndex()); + } + final boolean valid; + try { + valid = + scheme + .get() + .verifyRaw( + publicKey.get(), + commitDigest.getBytes().toArray(), + found.getSignature().toArray()); + } catch (final RuntimeException e) { + return Optional.of( + "AERE HIBRID: " + schemeId + " verification threw at height " + height + ": " + + e.getMessage()); + } + if (!valid) { +diff --git a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/PqFinalityLayersGuard.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/PqFinalityLayersGuard.java +new file mode 100644 +index 0000000000..ea85af1542 +--- /dev/null ++++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/PqFinalityLayersGuard.java +@@ -0,0 +1,181 @@ ++/* ++ * Copyright contributors to Besu / AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.consensus.qbft.core.validation; ++ ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; ++ ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Optional; ++import java.util.function.LongPredicate; ++ ++/** ++ * AIP-22 stage 4: H_fin may be armed only where every post-quantum seal is VERIFIED from H_fin. ++ * ++ *

    From H_fin a message's author is the id of its seal's index ({@code AerePqFinality}), and the ++ * envelope's ECDSA signature is no longer read. For a PROPOSAL, PREPARE or ROUND-CHANGE the author is ++ * given only once the seal verifies; a COMMIT's author is its index's id only when that is the commit ++ * seal signer's id, and what judges the COMMIT's post-quantum seal is the commit layer alone. Each ++ * layer is armed on its own height. With the commit layer unset, or armed above H_fin, a Commit whose ++ * ECDSA commit seal was forged (the adversary stage 4 exists for) would count with any bytes as its ++ * post-quantum seal; and the other three layers are the second judge of what the author already ++ * checked. So this guard refuses to start such a node (AERE-PQC-FIN-02), before the network is up. ++ * Emergency disarming of a layer after H_fin therefore needs H_fin unset too, on every node: one ++ * uniform step back to ECDSA authorship, never a node that trusts unverified seals. ++ */ ++public final class PqFinalityLayersGuard { ++ ++ /** ++ * One seal layer as the guard sees it. ++ * ++ * @param property the property that arms it ++ * @param armedAt whether it is armed at a height; null when the property is set nowhere ++ */ ++ public record Layer(String property, LongPredicate armedAt) {} ++ ++ private PqFinalityLayersGuard() {} ++ ++ /** ++ * The refusal, if any. ++ * ++ * @param hFin H_fin, or {@link AerePqIdentity#NEVER} ++ * @param layers the four seal layers ++ * @return empty when H_fin is unset or every layer is armed at or below it; otherwise the refusal ++ */ ++ public static Optional refusal(final long hFin, final List layers) { ++ if (hFin == AerePqIdentity.NEVER) { ++ return Optional.empty(); ++ } ++ final List missing = new ArrayList<>(); ++ for (final Layer l : layers) { ++ if (l.armedAt() == null || !l.armedAt().test(hFin)) { ++ missing.add(l.property() + (l.armedAt() == null ? " unset" : " armed above " + hFin)); ++ } ++ } ++ if (missing.isEmpty()) { ++ return Optional.empty(); ++ } ++ return Optional.of( ++ "AERE-PQC-FIN-02: aere.pq.finalityBlock=" ++ + hFin ++ + " makes a message's author the id of its post-quantum seal's index, so every seal" ++ + " must be verified from H_fin; not armed at or below it: " ++ + String.join(", ", missing) ++ + ". Arm the four layers at or below H_fin on every node, or unset H_fin on every node."); ++ } ++ ++ /** ++ * The four layers as this node's configuration arms them. ++ * ++ * @return proposal, prepare, commit, round-change ++ */ ++ public static List fromSystemConfig() { ++ final PqProposalEnforcement p = PqProposalEnforcement.fromSystemConfig(); ++ final PqPrepareEnforcement pr = PqPrepareEnforcement.fromSystemConfig(); ++ final PqCommitEnforcement c = PqCommitEnforcement.fromSystemConfig(); ++ final PqRoundChangeEnforcement rc = PqRoundChangeEnforcement.fromSystemConfig(); ++ return List.of( ++ new Layer(PqProposalEnforcement.PROPERTY_FORK_BLOCK, p == null ? null : p::armedAt), ++ new Layer(PqPrepareEnforcement.PROPERTY_FORK_BLOCK, pr == null ? null : pr::armedAt), ++ new Layer(PqCommitEnforcement.PROPERTY_FORK_BLOCK, c == null ? null : c::armedAt), ++ new Layer( ++ PqRoundChangeEnforcement.PROPERTY_FORK_BLOCK, rc == null ? null : rc::armedAt)); ++ } ++ ++ /** ++ * Refuses to start when H_fin is armed over an unverified layer. ++ * ++ * @param hFin H_fin as armed on this node ++ * @throws IllegalStateException AERE-PQC-FIN-02 ++ */ ++ public static void verifyOrAbort(final long hFin) { ++ final Optional r = refusal(hFin, fromSystemConfig()); ++ if (r.isPresent()) { ++ throw new IllegalStateException(r.get()); ++ } ++ } ++ ++ /** ++ * AERE-PQC-FIN-03: from H_fin an unsealed message has no author, so a node that seals (holds its ++ * Falcon key; from H_k every registered validator must, stage 3b-ii) must seal all four messages at ++ * or below H_fin, or it goes mute at H_fin while looking healthy: a loss of liveness, not safety. ++ * ++ * @param hFin H_fin, or {@link AerePqIdentity#NEVER} ++ * @param signs whether this node seals (a reader does not) ++ * @param attachCommit aere.falcon.attachBlock ({@link Long#MAX_VALUE} when unset) ++ * @param attachProposal aere.pq.proposalPq.attachBlock ++ * @param attachPrepare aere.pq.preparePq.attachBlock ++ * @param attachRoundChange aere.pq.roundChangePq.attachBlock ++ * @return the refusal, or empty ++ */ ++ public static Optional emissionRefusal( ++ final long hFin, ++ final boolean signs, ++ final long attachCommit, ++ final long attachProposal, ++ final long attachPrepare, ++ final long attachRoundChange) { ++ if (hFin == AerePqIdentity.NEVER || !signs) { ++ return Optional.empty(); ++ } ++ final List missing = new ArrayList<>(); ++ gate(missing, "aere.falcon.attachBlock", attachCommit, hFin); ++ gate(missing, "aere.pq.proposalPq.attachBlock", attachProposal, hFin); ++ gate(missing, "aere.pq.preparePq.attachBlock", attachPrepare, hFin); ++ gate(missing, "aere.pq.roundChangePq.attachBlock", attachRoundChange, hFin); ++ if (missing.isEmpty()) { ++ return Optional.empty(); ++ } ++ return Optional.of( ++ "AERE-PQC-FIN-03: aere.pq.finalityBlock=" ++ + hFin ++ + " makes an unsealed message authorless, and this node would not seal from H_fin: " ++ + String.join(", ", missing) ++ + ". It would go mute at H_fin. Arm them at or below H_fin, or unset H_fin, on every validator."); ++ } ++ ++ private static void gate(final List missing, final String property, final long h, final long hFin) { ++ if (h < 0 || h == Long.MAX_VALUE) { ++ missing.add(property + " unset"); ++ } else if (h > hFin) { ++ missing.add(property + " armed above H_fin (" + h + ")"); ++ } ++ } ++ ++ /** ++ * Refuses to start when a sealing node would not seal every message from H_fin. ++ * ++ * @param hFin H_fin as armed on this node ++ * @param signs whether this node seals ++ * @param attachCommit commit attachment height ++ * @param attachProposal proposal attachment height ++ * @param attachPrepare prepare attachment height ++ * @param attachRoundChange round-change attachment height ++ * @throws IllegalStateException AERE-PQC-FIN-03 ++ */ ++ public static void verifyEmissionOrAbort( ++ final long hFin, ++ final boolean signs, ++ final long attachCommit, ++ final long attachProposal, ++ final long attachPrepare, ++ final long attachRoundChange) { ++ final Optional r = ++ emissionRefusal(hFin, signs, attachCommit, attachProposal, attachPrepare, attachRoundChange); ++ if (r.isPresent()) { ++ throw new IllegalStateException(r.get()); ++ } ++ } ++} +diff --git a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/RoundChangePayloadValidator.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/RoundChangePayloadValidator.java +old mode 100644 +new mode 100755 +index 8fd9bed3e6..63a94d5ae5 +--- a/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/RoundChangePayloadValidator.java ++++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/RoundChangePayloadValidator.java +@@ -38,40 +38,43 @@ import org.slf4j.LoggerFactory; + * performed elsewhere (eg. the BlockHeightManager) + * + *

    AERE (2026-08-31): an OPTIONAL post-quantum enforcement hook, gated on height (see {@link + * PqRoundChangeEnforcement}). When no enforcement is supplied, behaviour is byte for byte the + * upstream one - and that is the configuration of every node today. Same pattern as the PREPARE, + * commit and PROPOSAL validators, deliberately: a second rendering of the same idea, written + * differently, diverges eventually. + * + *

    The 2-argument constructor - the one production code calls, from both {@code + * MessageValidatorFactory} and {@code ProposalValidator} (the justification path) - wires the + * enforcement itself from the system configuration. That self-wiring is the security property: an + * enforcement that had to be passed in explicitly could be dropped by any refactor without a + * single test failing. It also means round-changes are judged in BOTH places they arrive: + * standalone, and inside a proposal's round-change certificate. + */ + public class RoundChangePayloadValidator { + + private static final String ERROR_PREFIX = "Invalid RoundChange Payload"; + private static final Logger LOG = LoggerFactory.getLogger(RoundChangePayloadValidator.class); + ++ /** maximum allowed round (AERE D-434: ported from upstream 118f8b1920, GHSA-23rh-rrqg-wq82) */ ++ public static final int MAX_ALLOWED_ROUND = 1000; ++ + private final Collection

    validators; + private final long chainHeight; + private final PqRoundChangeEnforcement pqEnforcement; + + /** + * Instantiates a new Round change payload validator, with the post-quantum enforcement wired + * from the system configuration. This is the constructor production code calls. + * + * @param validators the validators + * @param chainHeight the chain height + */ + public RoundChangePayloadValidator(final Collection
    validators, final long chainHeight) { + this(validators, chainHeight, PqRoundChangeEnforcement.fromSystemConfig()); + } + + /** + * Instantiates a new Round change payload validator with an explicit post-quantum enforcement. + * Test seam; production goes through the 2-argument constructor above. + * + * @param validators the validators +@@ -92,42 +95,42 @@ public class RoundChangePayloadValidator { + * Validate. + * + * @param signedPayload the signed payload + * @return the boolean + */ + public boolean validate(final SignedData signedPayload) { + + if (!validators.contains(signedPayload.getAuthor())) { + LOG.info("{}: did not originate from a recognized validator.", ERROR_PREFIX); + return false; + } + + final RoundChangePayload payload = signedPayload.getPayload(); + + if (payload.getRoundIdentifier().getSequenceNumber() != chainHeight) { + LOG.info("{}: did not target expected height", ERROR_PREFIX); + return false; + } + + final int targetRound = payload.getRoundIdentifier().getRoundNumber(); +- if (targetRound <= 0) { +- LOG.info("{}: must contain a positive target round number", ERROR_PREFIX); ++ if (targetRound <= 0 || targetRound > MAX_ALLOWED_ROUND) { ++ LOG.info("{}: target round number out of range [1, {}]", ERROR_PREFIX, MAX_ALLOWED_ROUND); + return false; + } + + if (payload.getPreparedRoundMetadata().isPresent()) { + final PreparedRoundMetadata metadata = payload.getPreparedRoundMetadata().get(); + if (metadata.getPreparedRound() >= targetRound) { + LOG.info("{}: prepared metadata is from a round ahead of target round", ERROR_PREFIX); + return false; + } + + if (metadata.getPreparedRound() < 0) { + LOG.info("{}: prepared metadata is from a negative round number", ERROR_PREFIX); + return false; + } + } + + // AERE full-PQ: from the armed height, a round-change is not accepted without a valid + // post-quantum seal from its OWN author. Below the height, and on every node without the + // property, this is a null check and nothing more - the upstream path, call for call. + if (pqEnforcement != null) { +diff --git a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/AereD434ListBoundsTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/AereD434ListBoundsTest.java +new file mode 100644 +index 0000000000..889e0e7c20 +--- /dev/null ++++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/AereD434ListBoundsTest.java +@@ -0,0 +1,73 @@ ++/* ++ * Copyright contributors to Besu. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Aere Network notice (Apache-2.0 section 4(b)): this file was added by Aere Network, 2026-09-28 (D-434), adapted from the tests of the ++ * ported upstream fix hyperledger/besu dd4101c9ec ("bound prepares/round-change lists at decode"). ++ */ ++package org.hyperledger.besu.consensus.qbft.core.messagewrappers; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++import static org.assertj.core.api.Assertions.assertThatThrownBy; ++ ++import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; ++import org.hyperledger.besu.consensus.common.bft.messagewrappers.BftMessage; ++import org.hyperledger.besu.consensus.common.bft.payload.SignedData; ++import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; ++import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; ++import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec; ++import org.hyperledger.besu.cryptoservices.NodeKey; ++import org.hyperledger.besu.cryptoservices.NodeKeyUtils; ++import org.hyperledger.besu.datatypes.Hash; ++import org.hyperledger.besu.ethereum.rlp.RLPException; ++ ++import java.util.Collections; ++import java.util.Optional; ++ ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.bytes.Bytes32; ++import org.junit.jupiter.api.Test; ++import org.mockito.Mockito; ++ ++/** ++ * AERE D-434: a RoundChange whose prepares list holds more than BftMessage.MAX_LIST_ENTRIES (512) entries is refused at DECODE, before ++ * any signature or author check; before the port any peer could make a node allocate and verify an arbitrarily long list. With ten ++ * validators an honest list never exceeds ten, so the bound never binds an honest network. ++ */ ++class AereD434ListBoundsTest { ++ ++ private static final QbftBlockCodec CODEC = Mockito.mock(QbftBlockCodec.class); ++ ++ private static Bytes roundChangeWith(final int prepares) { ++ final NodeKey key = NodeKeyUtils.generate(); ++ final RoundChangePayload rc = new RoundChangePayload(new ConsensusRoundIdentifier(1, 0), Optional.empty()); ++ final SignedData signedRc = SignedData.create(rc, key.sign(Bytes32.wrap(rc.hashForSignature().getBytes()))); ++ final PreparePayload p = new PreparePayload(new ConsensusRoundIdentifier(1, 0), Hash.ZERO); ++ final SignedData one = SignedData.create(p, key.sign(Bytes32.wrap(p.hashForSignature().getBytes()))); ++ return new RoundChange(signedRc, Optional.empty(), Optional.empty(), CODEC, Collections.nCopies(prepares, one)).encode(); ++ } ++ ++ @Test ++ void aPreparesListAboveTheBoundIsRefusedAtDecode() { ++ final Bytes oversized = roundChangeWith(BftMessage.MAX_LIST_ENTRIES + 1); ++ assertThatThrownBy(() -> RoundChange.decode(oversized, CODEC)) ++ .isInstanceOf(RLPException.class) ++ .hasMessageContaining("exceeds the maximum permitted size"); ++ } ++ ++ @Test ++ void aPreparesListAtTheBoundStillDecodes() { ++ // positive control: the fixture decodes, and the bound is inclusive ++ assertThat(RoundChange.decode(roundChangeWith(BftMessage.MAX_LIST_ENTRIES), CODEC).getPrepares()).hasSize(BftMessage.MAX_LIST_ENTRIES); ++ } ++} +diff --git a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/PqCommitSealsSignedOnceTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/PqCommitSealsSignedOnceTest.java +new file mode 100644 +index 0000000000..daa5ff1d44 +--- /dev/null ++++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/PqCommitSealsSignedOnceTest.java +@@ -0,0 +1,210 @@ ++/* ++ * Copyright contributors to Aere Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in ++ * compliance with the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is ++ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ++ * implied. See the License for the specific language governing permissions and limitations under the ++ * License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.consensus.qbft.core.statemachine; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++import static org.mockito.ArgumentMatchers.any; ++import static org.mockito.ArgumentMatchers.anyInt; ++import static org.mockito.ArgumentMatchers.eq; ++import static org.mockito.Mockito.doReturn; ++import static org.mockito.Mockito.spy; ++import static org.mockito.Mockito.times; ++import static org.mockito.Mockito.verify; ++import static org.mockito.Mockito.when; ++ ++import java.util.Collections; ++import java.util.List; ++import java.util.Optional; ++import org.apache.tuweni.bytes.Bytes; ++import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; ++import org.hyperledger.besu.consensus.common.bft.FalconSeal; ++import org.hyperledger.besu.consensus.common.bft.PqSealCache; ++import org.hyperledger.besu.consensus.common.bft.RoundTimer; ++import org.hyperledger.besu.consensus.common.bft.SchemeSeal; ++import org.hyperledger.besu.consensus.qbft.core.QbftBlockTestFixture; ++import org.hyperledger.besu.consensus.qbft.core.network.QbftMessageTransmitter; ++import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; ++import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock; ++import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec; ++import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCreator; ++import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader; ++import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockInterface; ++import org.hyperledger.besu.consensus.qbft.core.types.QbftMinedBlockObserver; ++import org.hyperledger.besu.consensus.qbft.core.types.QbftProtocolSchedule; ++import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidator; ++import org.hyperledger.besu.consensus.qbft.core.validation.QbftBlockHeaderTestFixture; ++import org.hyperledger.besu.cryptoservices.NodeKey; ++import org.hyperledger.besu.cryptoservices.NodeKeyUtils; ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.util.Subscribers; ++import org.junit.jupiter.api.AfterEach; ++import org.junit.jupiter.api.BeforeEach; ++import org.junit.jupiter.api.Test; ++import org.junit.jupiter.api.extension.ExtendWith; ++import org.mockito.Mock; ++import org.mockito.junit.jupiter.MockitoExtension; ++import org.mockito.junit.jupiter.MockitoSettings; ++import org.mockito.quality.Strictness; ++ ++/** ++ * D-337 (2026-09-28): this node's Commit seals are signed ONCE per round, not once per path. ++ * ++ *

    The measured cost on chain 2800: at the parent of every anchor each Besu validator signed ++ * SLH-DSA twice back to back on the consensus thread - on accepting the proposal (before its ++ * Prepare) and again on becoming prepared (between "prepared" and its Commit) - and the ++ * anchor-parent slot ran at 1,036 ms against 599 for the rest. ++ * ++ *

    The round is driven through the real state machine: a peer's proposal, the local Prepare, a ++ * peer's Prepare that makes the round prepared, and the Commit that goes on the wire. The signers ++ * are stubbed on a spy so the SIGNINGS can be counted; everything between them is the production ++ * code. The pair of the claim is the retry: an attempt that produced no Falcon seal must be signed ++ * again on the second path, exactly as before the change, so the reuse cannot swallow a failure. ++ */ ++@ExtendWith(MockitoExtension.class) ++@MockitoSettings(strictness = Strictness.LENIENT) ++public class PqCommitSealsSignedOnceTest { ++ ++ private static final long HEIGHT = 7L; ++ ++ private final NodeKey nodeKey = NodeKeyUtils.generate(); ++ private final Address localAddress = Address.extract(nodeKey.getPublicKey()); ++ private final NodeKey peerKey = NodeKeyUtils.generate(); ++ private final ConsensusRoundIdentifier roundIdentifier = new ConsensusRoundIdentifier(HEIGHT, 0); ++ private final Subscribers subscribers = Subscribers.create(); ++ private final FalconSeal falcon = new FalconSeal(4, Bytes.fromHexString("0x29aabbcc")); ++ private final SchemeSeal slh = new SchemeSeal((byte) 0x02, 4, Bytes.fromHexString("0x0102030405")); ++ ++ private MessageFactory localFactory; ++ private MessageFactory peerFactory; ++ private QbftBlock proposedBlock; ++ ++ @Mock private QbftBlockCodec blockEncoder; ++ @Mock private QbftProtocolSchedule protocolSchedule; ++ @Mock private QbftMessageTransmitter transmitter; ++ @Mock private MessageValidator messageValidator; ++ @Mock private RoundTimer roundTimer; ++ @Mock private QbftBlockCreator blockCreator; ++ @Mock private QbftBlockInterface blockInterface; ++ ++ private final QbftBlockHeader parentHeader = ++ new QbftBlockHeaderTestFixture().number(HEIGHT - 1).buildHeader(); ++ ++ @BeforeEach ++ public void setup() { ++ PqSealCache.instance().clear(); ++ localFactory = new MessageFactory(nodeKey, blockEncoder); ++ peerFactory = new MessageFactory(peerKey, blockEncoder); ++ when(messageValidator.validateProposal(any())).thenReturn(true); ++ when(messageValidator.validatePrepare(any())).thenReturn(true); ++ when(messageValidator.validateCommit(any())).thenReturn(true); ++ proposedBlock = ++ new QbftBlockTestFixture() ++ .blockHeader(new QbftBlockHeaderTestFixture().number(HEIGHT).buildHeader()) ++ .build(); ++ when(blockInterface.replaceRoundForCommitBlock(any(), anyInt())).thenReturn(proposedBlock); ++ } ++ ++ @AfterEach ++ public void clean() { ++ PqSealCache.instance().clear(); ++ } ++ ++ /** A round of quorum 2: the local Prepare plus ONE peer Prepare make it prepared. */ ++ private QbftRound spiedRound() { ++ final RoundState roundState = new RoundState(roundIdentifier, 2, messageValidator); ++ return spy( ++ new QbftRound( ++ roundState, ++ blockCreator, ++ blockInterface, ++ protocolSchedule, ++ subscribers, ++ nodeKey, ++ localAddress, ++ localFactory, ++ transmitter, ++ roundTimer, ++ parentHeader)); ++ } ++ ++ /** Proposal from the peer, then the peer's Prepare: the second path fires on the second step. */ ++ private void driveToPrepared(final QbftRound round) { ++ round.handleProposalMessage( ++ peerFactory.createProposal( ++ roundIdentifier, proposedBlock, Collections.emptyList(), Collections.emptyList())); ++ assertThat(round.getRoundState().isPrepared()).isFalse(); ++ round.handlePrepareMessage(peerFactory.createPrepare(roundIdentifier, proposedBlock.getHash())); ++ assertThat(round.getRoundState().isPrepared()).isTrue(); ++ } ++ ++ @Test ++ public void anAnchorParentCommitIsSignedOnceAndTheWireCarriesThoseSeals() { ++ final QbftRound round = spiedRound(); ++ doReturn(Optional.of(falcon)).when(round).falconSealFor(any(), any()); ++ doReturn(List.of(slh)).when(round).extraSealsFor(any(), any()); ++ ++ driveToPrepared(round); ++ ++ verify(round, times(1)).falconSealFor(any(), any()); ++ verify(round, times(1)).extraSealsFor(any(), any()); ++ verify(transmitter, times(1)) ++ .multicastCommit( ++ eq(roundIdentifier), ++ eq(proposedBlock.getHash()), ++ any(), ++ eq(Optional.of(falcon)), ++ eq(List.of(slh))); ++ // the local Commit, added on accepting the proposal, carries the very same extras ++ assertThat(round.getRoundState().getExtraSeals()).containsExactly(slh); ++ } ++ ++ @Test ++ public void aFalconOnlyCommitOffTheExtrasGridIsAlsoSignedOnce() { ++ // off the anchor-parent predicate the extras are legitimately empty; a Falcon-only result is ++ // complete there and must be reused too, not re-signed ++ assertThat(QbftRound.pqExtrasApplyAt(HEIGHT)).isFalse(); ++ final QbftRound round = spiedRound(); ++ doReturn(Optional.of(falcon)).when(round).falconSealFor(any(), any()); ++ doReturn(List.of()).when(round).extraSealsFor(any(), any()); ++ ++ driveToPrepared(round); ++ ++ verify(round, times(1)).falconSealFor(any(), any()); ++ verify(transmitter, times(1)) ++ .multicastCommit( ++ eq(roundIdentifier), eq(proposedBlock.getHash()), any(), eq(Optional.of(falcon))); ++ } ++ ++ @Test ++ public void aFirstAttemptWithoutAFalconSealIsSignedAgainOnTheSecondPath() { ++ // the pair: reuse must never swallow a failed attempt; before D-337 the second path signed ++ // anew and could succeed, and it still must ++ final QbftRound round = spiedRound(); ++ doReturn(Optional.empty()).doReturn(Optional.of(falcon)).when(round).falconSealFor(any(), any()); ++ doReturn(List.of(slh)).when(round).extraSealsFor(any(), any()); ++ ++ driveToPrepared(round); ++ ++ verify(round, times(2)).falconSealFor(any(), any()); ++ verify(transmitter, times(1)) ++ .multicastCommit( ++ eq(roundIdentifier), ++ eq(proposedBlock.getHash()), ++ any(), ++ eq(Optional.of(falcon)), ++ eq(List.of(slh))); ++ } ++} +diff --git a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/AereD434RoundCapTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/AereD434RoundCapTest.java +new file mode 100644 +index 0000000000..e719908194 +--- /dev/null ++++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/AereD434RoundCapTest.java +@@ -0,0 +1,61 @@ ++/* ++ * Copyright contributors to Besu. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Aere Network notice (Apache-2.0 section 4(b)): this file was added by Aere Network, 2026-09-28 (D-434), as the regression test of ++ * the ported upstream fix hyperledger/besu 118f8b1920 (GHSA-23rh-rrqg-wq82, "Cap BFT round change number"). ++ */ ++package org.hyperledger.besu.consensus.qbft.core.validation; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++ ++import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; ++import org.hyperledger.besu.consensus.common.bft.payload.SignedData; ++import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; ++import org.hyperledger.besu.cryptoservices.NodeKey; ++ ++import java.util.Optional; ++ ++import org.apache.tuweni.bytes.Bytes32; ++import org.junit.jupiter.api.Test; ++ ++/** ++ * AERE D-434: a RoundChange for a round above RoundChangePayloadValidator.MAX_ALLOWED_ROUND (1000) is refused, as upstream does since ++ * 2026-08-20. Before, any positive round was accepted, so one validator could push the round-change bookkeeping of every node to an ++ * arbitrary round. The worst round the live chains have reached is 6 (2026-09-04), so the cap never binds an honest network. ++ */ ++class AereD434RoundCapTest { ++ ++ private static final long HEIGHT = 5L; ++ ++ private static boolean judge(final int round) { ++ final QbftNodeList validators = QbftNodeList.createNodes(4, null); ++ final RoundChangePayloadValidator v = new RoundChangePayloadValidator(validators.getNodeAddresses(), HEIGHT); ++ final RoundChangePayload payload = new RoundChangePayload(new ConsensusRoundIdentifier(HEIGHT, round), Optional.empty()); ++ final NodeKey key = validators.getNode(0).getNodeKey(); ++ return v.validate(SignedData.create(payload, key.sign(Bytes32.wrap(payload.hashForSignature().getBytes())))); ++ } ++ ++ @Test ++ void aRoundAboveTheCapIsRefused() { ++ assertThat(judge(RoundChangePayloadValidator.MAX_ALLOWED_ROUND + 1)).withFailMessage("round 1001 accepted").isFalse(); ++ assertThat(judge(Integer.MAX_VALUE)).withFailMessage("round 2^31-1 accepted").isFalse(); ++ } ++ ++ @Test ++ void theCapItselfAndOrdinaryRoundsAreStillAccepted() { ++ // positive control: the fixture is valid, and the cap is inclusive ++ assertThat(judge(1)).isTrue(); ++ assertThat(judge(RoundChangePayloadValidator.MAX_ALLOWED_ROUND)).isTrue(); ++ } ++} +diff --git a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/AereFinalityMessageTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/AereFinalityMessageTest.java +new file mode 100644 +index 0000000000..e8df550557 +--- /dev/null ++++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/AereFinalityMessageTest.java +@@ -0,0 +1,204 @@ ++/* ++ * Copyright contributors to Besu / AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.consensus.qbft.core.validation; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++ ++import org.hyperledger.besu.consensus.common.bft.AerePqFinality; ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; ++import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; ++import org.hyperledger.besu.consensus.common.bft.FalconSeal; ++import org.hyperledger.besu.consensus.common.bft.PqAnchor; ++import org.hyperledger.besu.consensus.common.bft.PqRegistryV3; ++import org.hyperledger.besu.consensus.common.bft.SealScheme; ++import org.hyperledger.besu.consensus.common.bft.SealSchemes; ++import org.hyperledger.besu.consensus.common.bft.payload.Payload; ++import org.hyperledger.besu.consensus.common.bft.payload.SignedData; ++import org.hyperledger.besu.consensus.qbft.core.QbftBlockTestFixture; ++import org.hyperledger.besu.consensus.qbft.core.payload.CommitPayload; ++import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; ++import org.hyperledger.besu.consensus.qbft.core.payload.PreparedRoundMetadata; ++import org.hyperledger.besu.consensus.qbft.core.payload.ProposalPayload; ++import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; ++import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock; ++import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec; ++import org.hyperledger.besu.crypto.SECPSignature; ++import org.hyperledger.besu.crypto.SecureRandomProvider; ++import org.hyperledger.besu.cryptoservices.NodeKey; ++import org.hyperledger.besu.cryptoservices.NodeKeyUtils; ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.datatypes.Hash; ++ ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Map; ++import java.util.Optional; ++import java.util.TreeMap; ++ ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.bytes.Bytes32; ++import org.junit.jupiter.api.AfterEach; ++import org.junit.jupiter.api.BeforeEach; ++import org.junit.jupiter.api.Test; ++import org.junit.jupiter.api.extension.ExtendWith; ++import org.mockito.Mock; ++import org.mockito.junit.jupiter.MockitoExtension; ++ ++/** ++ * AIP-22 stage 4 on the REAL QBFT payloads, with real Falcon-512 keys generated for the run: from H_fin ++ * the author of a PREPARE, a PROPOSAL and a ROUND-CHANGE is the id of its seal's index only when the ++ * seal verifies over the message its own layer builds, and a COMMIT's only when that index names the ++ * commit seal signer's id. Every envelope is signed by a FOREIGN node key, so a validator's id can only ++ * come from the seal. Each positive has its negative on the same fixture: another index's seal, a seal ++ * over another round, a ROUND-CHANGE with prepared metadata sealed in the unprepared form, a proposal ++ * sealed over another block, a commit seal of another validator. The runner's negative control plants ++ * "every seal verifies" at run time and these probes turn red. ++ */ ++@ExtendWith(MockitoExtension.class) ++public class AereFinalityMessageTest { ++ ++ private static final long CHAIN = 28001; ++ private static final long BIND = 10; // H_k must be the bindHeight of a v3 epoch at or above H_id ++ private static final long H_ID = 10; ++ private static final long H_FIN = 20; ++ private static final int N = 4; ++ private static final SealScheme FALCON = SealSchemes.FALCON_512; ++ ++ private final Hash digest = Hash.hash(Bytes.of(7)); ++ private final NodeKey foreign = NodeKeyUtils.generate(); ++ private final List ecdsa = new ArrayList<>(); ++ private final List falcon = new ArrayList<>(); ++ private final List

    ids = new ArrayList<>(); ++ private @Mock QbftBlockCodec blockCodec; ++ ++ @BeforeEach ++ public void registry() { ++ final List rows = new ArrayList<>(); ++ for (int i = 0; i < N; i++) { ++ final NodeKey nk = NodeKeyUtils.generate(); ++ ecdsa.add(nk); ++ final SealScheme.GeneratedPair p = FALCON.generate(SecureRandomProvider.createSecureRandom()); ++ falcon.add(p.privateKey()); ++ final byte[] std = new byte[897]; ++ std[0] = 0x09; ++ System.arraycopy(p.publicRegistryForm(), 0, std, 1, 896); ++ final byte[] id = PqRegistryV3.idOf(std); ++ final Bytes32 popMsg = PqRegistryV3.popMessage(CHAIN, BIND, N, i, id, FALCON.wireId(), std); ++ final byte[] pop = FALCON.sign(p.privateKey(), popMsg.toArrayUnsafe()).orElseThrow(); ++ final TreeMap keys = new TreeMap<>(); ++ keys.put(FALCON.wireId() & 0xff, new PqRegistryV3.Key(FALCON, std, pop)); ++ final PqRegistryV3.Row bare = new PqRegistryV3.Row(i, id, keys, null, Map.of(), null, null); ++ final Bytes32 rh = PqRegistryV3.rowHash(CHAIN, BIND, N, bare); ++ final SECPSignature claim = nk.sign(PqRegistryV3.claimDigest(CHAIN, rh)); ++ final Address addr = org.hyperledger.besu.ethereum.core.Util.publicKeyToAddress(nk.getPublicKey()); ++ rows.add( ++ new PqRegistryV3.Row( ++ i, id, keys, null, Map.of(), addr.getBytes().toArrayUnsafe(), ++ claim.encodedBytes().toArrayUnsafe())); ++ ids.add(Address.wrap(Bytes.wrap(id))); ++ } ++ final List hashes = new ArrayList<>(); ++ for (final PqRegistryV3.Row r : rows) { ++ hashes.add(PqRegistryV3.rowHash(CHAIN, BIND, N, r)); ++ } ++ final Bytes32 root = PqRegistryV3.merkleRoot(hashes); ++ final PqRegistryV3.Registry reg = ++ new PqRegistryV3.Registry( ++ CHAIN, BIND, N, rows, hashes, root, PqRegistryV3.registryHash(CHAIN, BIND, N, root)); ++ final TreeMap epochs = new TreeMap<>(); ++ epochs.put(BIND, reg); ++ AerePqFinality.uninstall(); ++ AerePqIdentity.uninstall(); ++ AerePqIdentity.install(new AerePqIdentity.Config(H_ID, epochs, H_ID)); ++ // the production verifier reads the same v3 key from H_k (FalconSealSupport.verifyAtOwnHead) ++ AerePqFinality.install( ++ H_FIN, ++ CHAIN, ++ (h, i, m, s) -> ++ AerePqIdentity.v3KeyAt(h, i, "falcon-512") ++ .map(k -> FALCON.verifyRaw(k, m.toArrayUnsafe(), s.toArrayUnsafe())) ++ .orElse(false)); ++ } ++ ++ @AfterEach ++ public void disarm() { ++ AerePqFinality.uninstall(); ++ AerePqIdentity.uninstall(); ++ } ++ ++ private Optional seal(final int index, final int signer, final Bytes32 message) { ++ return Optional.of( ++ new FalconSeal(index, Bytes.wrap(FALCON.sign(falcon.get(signer), message.toArrayUnsafe()).orElseThrow()))); ++ } ++ ++ private

    Address authorOf(final P payload) { ++ return SignedData.create(payload, foreign.sign(Bytes32.wrap(payload.hashForSignature().getBytes()))) ++ .getAuthor(); ++ } ++ ++ private static ConsensusRoundIdentifier round(final int r) { ++ return new ConsensusRoundIdentifier(H_FIN, r); ++ } ++ ++ @Test ++ public void aPrepareIsAuthoredOnlyByAVerifiedSealOfItsIndex() { ++ final Bytes32 m = PqAnchor.prepareMessage(CHAIN, H_FIN, 0, digest.getBytes()); ++ for (int i = 0; i < N; i++) { ++ assertThat(authorOf(new PreparePayload(round(0), digest, seal(i, i, m)))).as("node %s", i).isEqualTo(ids.get(i)); ++ } ++ // index 0 with node 1's seal; node 0's seal over round 1; no seal ++ assertThat(authorOf(new PreparePayload(round(0), digest, seal(0, 1, m)))).isEqualTo(AerePqFinality.NO_AUTHOR); ++ assertThat( ++ authorOf( ++ new PreparePayload( ++ round(0), digest, seal(0, 0, PqAnchor.prepareMessage(CHAIN, H_FIN, 1, digest.getBytes()))))) ++ .isEqualTo(AerePqFinality.NO_AUTHOR); ++ assertThat(authorOf(new PreparePayload(round(0), digest, Optional.empty()))).isEqualTo(AerePqFinality.NO_AUTHOR); ++ } ++ ++ @Test ++ public void aRoundChangeIsAuthoredOnlyByASealInTheFormItsMetadataNames() { ++ final Bytes32 bare = PqAnchor.roundChangeMessage(CHAIN, H_FIN, 2); ++ assertThat(authorOf(new RoundChangePayload(round(2), Optional.empty(), seal(1, 1, bare)))).isEqualTo(ids.get(1)); ++ final Optional meta = Optional.of(new PreparedRoundMetadata(digest, 1)); ++ final Bytes32 prepared = PqAnchor.roundChangeMessage(CHAIN, H_FIN, 2, 1, digest.getBytes()); ++ assertThat(authorOf(new RoundChangePayload(round(2), meta, seal(1, 1, prepared)))).isEqualTo(ids.get(1)); ++ // the prepared claim sealed in the unprepared form does not author: the seal must cover the claim ++ assertThat(authorOf(new RoundChangePayload(round(2), meta, seal(1, 1, bare)))).isEqualTo(AerePqFinality.NO_AUTHOR); ++ } ++ ++ @Test ++ public void aProposalIsAuthoredOnlyByASealOverItsOwnBlock() { ++ final QbftBlock block = ++ new QbftBlockTestFixture() ++ .blockHeader(new QbftBlockHeaderTestFixture().number(H_FIN).buildHeader()) ++ .build(); ++ final Bytes32 m = PqAnchor.proposalMessage(CHAIN, H_FIN, 0, block.getHash().getBytes()); ++ assertThat(authorOf(new ProposalPayload(round(0), block, blockCodec, Optional.empty(), seal(2, 2, m)))) ++ .isEqualTo(ids.get(2)); ++ final Bytes32 other = PqAnchor.proposalMessage(CHAIN, H_FIN, 0, digest.getBytes()); ++ assertThat(authorOf(new ProposalPayload(round(0), block, blockCodec, Optional.empty(), seal(2, 2, other)))) ++ .isEqualTo(AerePqFinality.NO_AUTHOR); ++ } ++ ++ @Test ++ public void aCommitIsAuthoredByItsIndexOnlyWhenThatIsTheCommitSealSigner() { ++ final Optional any = Optional.of(new FalconSeal(3, Bytes.of(1))); ++ final SECPSignature own = ecdsa.get(3).sign(Bytes32.wrap(digest.getBytes())); ++ final SECPSignature other = ecdsa.get(0).sign(Bytes32.wrap(digest.getBytes())); ++ assertThat(authorOf(new CommitPayload(round(0), digest, own, any))).isEqualTo(ids.get(3)); ++ assertThat(authorOf(new CommitPayload(round(0), digest, other, any))).isEqualTo(AerePqFinality.NO_AUTHOR); ++ } ++} +diff --git a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/AereFinalityVectorsWriter.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/AereFinalityVectorsWriter.java +new file mode 100644 +index 0000000000..b1a6776bb0 +--- /dev/null ++++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/AereFinalityVectorsWriter.java +@@ -0,0 +1,206 @@ ++/* ++ * Copyright contributors to Besu / AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.consensus.qbft.core.validation; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++ ++import org.hyperledger.besu.consensus.common.bft.AerePqFinality; ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; ++import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; ++import org.hyperledger.besu.consensus.common.bft.FalconSeal; ++import org.hyperledger.besu.consensus.common.bft.PqAnchor; ++import org.hyperledger.besu.consensus.common.bft.PqRegistryV3; ++import org.hyperledger.besu.consensus.common.bft.SealScheme; ++import org.hyperledger.besu.consensus.common.bft.SealSchemes; ++import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; ++import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; ++import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; ++import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; ++import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec; ++import org.hyperledger.besu.crypto.SECPSignature; ++import org.hyperledger.besu.crypto.SecureRandomProvider; ++import org.hyperledger.besu.cryptoservices.NodeKey; ++import org.hyperledger.besu.cryptoservices.NodeKeyUtils; ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.datatypes.Hash; ++import org.hyperledger.besu.ethereum.core.Util; ++ ++import java.io.IOException; ++import java.nio.charset.StandardCharsets; ++import java.nio.file.Files; ++import java.nio.file.Path; ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Map; ++import java.util.Optional; ++import java.util.TreeMap; ++ ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.bytes.Bytes32; ++import org.junit.jupiter.api.AfterEach; ++import org.junit.jupiter.api.Test; ++import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; ++import org.mockito.Mockito; ++ ++/** ++ * AIP-22 stage 4: the WRITER of the shared authorship vectors. Real QBFT messages, encoded on the wire ++ * exactly as this client sends them, each ENVELOPE signed by a FOREIGN node key, each carrying a real ++ * Falcon-512 seal (keys generated for the run, nothing here touches a real key): the second client must ++ * decode every one to the SAME author this client gives it. Every expected author is asserted here, at ++ * writing time, through this client's own decoding path (SignedData), so a vector cannot say what this ++ * client does not do. Runs only with AERE_T4_VECTORS_OUT set to the output directory. ++ */ ++@EnabledIfEnvironmentVariable(named = "AERE_T4_VECTORS_OUT", matches = ".+") ++public class AereFinalityVectorsWriter { ++ ++ private static final long CHAIN = 28001; ++ private static final long BIND = 10; ++ private static final long H_ID = 10; ++ private static final long H_FIN = 20; ++ private static final int N = 4; ++ private static final SealScheme FALCON = SealSchemes.FALCON_512; ++ ++ @AfterEach ++ public void disarm() { ++ AerePqFinality.uninstall(); ++ AerePqIdentity.uninstall(); ++ } ++ ++ private static String hex(final Bytes b) { ++ return b.toUnprefixedHexString(); ++ } ++ ++ @Test ++ public void writeTheSharedAuthorshipVectors() throws IOException { ++ final List ecdsa = new ArrayList<>(); ++ final List falcon = new ArrayList<>(); ++ final List std = new ArrayList<>(); ++ final List

    ids = new ArrayList<>(); ++ final List rows = new ArrayList<>(); ++ for (int i = 0; i < N; i++) { ++ final NodeKey nk = NodeKeyUtils.generate(); ++ ecdsa.add(nk); ++ final SealScheme.GeneratedPair p = FALCON.generate(SecureRandomProvider.createSecureRandom()); ++ falcon.add(p.privateKey()); ++ final byte[] s = new byte[897]; ++ s[0] = 0x09; ++ System.arraycopy(p.publicRegistryForm(), 0, s, 1, 896); ++ std.add(s); ++ final byte[] id = PqRegistryV3.idOf(s); ++ final Bytes32 popMsg = PqRegistryV3.popMessage(CHAIN, BIND, N, i, id, FALCON.wireId(), s); ++ final byte[] pop = FALCON.sign(p.privateKey(), popMsg.toArrayUnsafe()).orElseThrow(); ++ final TreeMap keys = new TreeMap<>(); ++ keys.put(FALCON.wireId() & 0xff, new PqRegistryV3.Key(FALCON, s, pop)); ++ final PqRegistryV3.Row bare = new PqRegistryV3.Row(i, id, keys, null, Map.of(), null, null); ++ final SECPSignature claim = nk.sign(PqRegistryV3.claimDigest(CHAIN, PqRegistryV3.rowHash(CHAIN, BIND, N, bare))); ++ rows.add( ++ new PqRegistryV3.Row( ++ i, id, keys, null, Map.of(), ++ Util.publicKeyToAddress(nk.getPublicKey()).getBytes().toArrayUnsafe(), ++ claim.encodedBytes().toArrayUnsafe())); ++ ids.add(Address.wrap(Bytes.wrap(id))); ++ } ++ final List hashes = new ArrayList<>(); ++ for (final PqRegistryV3.Row r : rows) { ++ hashes.add(PqRegistryV3.rowHash(CHAIN, BIND, N, r)); ++ } ++ final Bytes32 root = PqRegistryV3.merkleRoot(hashes); ++ final TreeMap epochs = new TreeMap<>(); ++ epochs.put( ++ BIND, ++ new PqRegistryV3.Registry( ++ CHAIN, BIND, N, rows, hashes, root, PqRegistryV3.registryHash(CHAIN, BIND, N, root))); ++ AerePqIdentity.install(new AerePqIdentity.Config(H_ID, epochs, H_ID)); ++ AerePqFinality.install( ++ H_FIN, ++ CHAIN, ++ (h, i, m, s) -> ++ AerePqIdentity.v3KeyAt(h, i, "falcon-512") ++ .map(k -> FALCON.verifyRaw(k, m.toArrayUnsafe(), s.toArrayUnsafe())) ++ .orElse(false)); ++ ++ final NodeKey foreign = NodeKeyUtils.generate(); ++ final Address foreignAddr = Util.publicKeyToAddress(foreign.getPublicKey()); ++ final MessageFactory mf = new MessageFactory(foreign, Mockito.mock(QbftBlockCodec.class)); ++ final Hash digest = Hash.hash(Bytes.of(7)); ++ final List out = new ArrayList<>(); // name, type, height, wire, expected author ++ ++ // 1. a PREPARE sealed by its own index: the index's id ++ final Bytes32 pm = PqAnchor.prepareMessage(CHAIN, H_FIN, 0, digest.getBytes()); ++ final Prepare p1 = mf.createPrepare(new ConsensusRoundIdentifier(H_FIN, 0), digest, seal(falcon, 1, 1, pm)); ++ assertThat(p1.getAuthor()).isEqualTo(ids.get(1)); ++ out.add(new String[] {"prepare-own-seal", "prepare", Long.toString(H_FIN), hex(p1.encode()), hex(ids.get(1).getBytes())}); ++ // 2. a PREPARE naming index 0 with index 1's seal: no author ++ final Prepare p2 = mf.createPrepare(new ConsensusRoundIdentifier(H_FIN, 0), digest, seal(falcon, 0, 1, pm)); ++ assertThat(p2.getAuthor()).isEqualTo(AerePqFinality.NO_AUTHOR); ++ out.add(new String[] {"prepare-another-index-seal", "prepare", Long.toString(H_FIN), hex(p2.encode()), hex(AerePqFinality.NO_AUTHOR.getBytes())}); ++ // 3. a PREPARE one block below H_fin: the envelope's (foreign) signer ++ final Bytes32 pmb = PqAnchor.prepareMessage(CHAIN, H_FIN - 1, 0, digest.getBytes()); ++ final Prepare p3 = mf.createPrepare(new ConsensusRoundIdentifier(H_FIN - 1, 0), digest, seal(falcon, 1, 1, pmb)); ++ assertThat(p3.getAuthor()).isEqualTo(foreignAddr); ++ out.add(new String[] {"prepare-below-hfin", "prepare", Long.toString(H_FIN - 1), hex(p3.encode()), hex(foreignAddr.getBytes())}); ++ // 4. a ROUND-CHANGE without a prepared claim, sealed by its own index ++ final Bytes32 rm = PqAnchor.roundChangeMessage(CHAIN, H_FIN, 2); ++ final RoundChange r1 = mf.createRoundChange(new ConsensusRoundIdentifier(H_FIN, 2), Optional.empty(), seal(falcon, 2, 2, rm)); ++ assertThat(r1.getAuthor()).isEqualTo(ids.get(2)); ++ out.add(new String[] {"roundchange-own-seal", "roundchange", Long.toString(H_FIN), hex(r1.encode()), hex(ids.get(2).getBytes())}); ++ // 5. a ROUND-CHANGE sealed over another target round: no author ++ final RoundChange r2 = ++ mf.createRoundChange( ++ new ConsensusRoundIdentifier(H_FIN, 2), Optional.empty(), ++ seal(falcon, 2, 2, PqAnchor.roundChangeMessage(CHAIN, H_FIN, 3))); ++ assertThat(r2.getAuthor()).isEqualTo(AerePqFinality.NO_AUTHOR); ++ out.add(new String[] {"roundchange-other-round", "roundchange", Long.toString(H_FIN), hex(r2.encode()), hex(AerePqFinality.NO_AUTHOR.getBytes())}); ++ // 6. a COMMIT naming index 3 with validator 3's commit seal: index 3's id ++ final SECPSignature own = ecdsa.get(3).sign(Bytes32.wrap(digest.getBytes())); ++ final Commit c1 = mf.createCommit(new ConsensusRoundIdentifier(H_FIN, 0), digest, own, Optional.of(new FalconSeal(3, Bytes.of(1)))); ++ assertThat(c1.getAuthor()).isEqualTo(ids.get(3)); ++ out.add(new String[] {"commit-own-commit-seal", "commit", Long.toString(H_FIN), hex(c1.encode()), hex(ids.get(3).getBytes())}); ++ // 7. a COMMIT naming index 3 with validator 0's commit seal: no author ++ final SECPSignature other = ecdsa.get(0).sign(Bytes32.wrap(digest.getBytes())); ++ final Commit c2 = mf.createCommit(new ConsensusRoundIdentifier(H_FIN, 0), digest, other, Optional.of(new FalconSeal(3, Bytes.of(1)))); ++ assertThat(c2.getAuthor()).isEqualTo(AerePqFinality.NO_AUTHOR); ++ out.add(new String[] {"commit-another-commit-seal", "commit", Long.toString(H_FIN), hex(c2.encode()), hex(AerePqFinality.NO_AUTHOR.getBytes())}); ++ ++ final StringBuilder j = new StringBuilder(); ++ j.append("{\n \"note\": \"AIP-22 stage 4 shared authorship vectors, written by AereFinalityVectorsWriter (Besu-derived client); PROBE keys\",\n"); ++ j.append(" \"chainId\": ").append(CHAIN).append(",\n \"bindHeight\": ").append(BIND) ++ .append(",\n \"identityBlock\": ").append(H_ID).append(",\n \"keysFrom\": ").append(H_ID) ++ .append(",\n \"finalityBlock\": ").append(H_FIN).append(",\n \"rows\": [\n"); ++ for (int i = 0; i < N; i++) { ++ j.append(" {\"index\": ").append(i).append(", \"id\": \"").append(hex(ids.get(i).getBytes())) ++ .append("\", \"falcon\": \"").append(hex(Bytes.wrap(std.get(i)))) ++ .append("\", \"ecdsa\": \"").append(hex(Util.publicKeyToAddress(ecdsa.get(i).getPublicKey()).getBytes())) ++ .append("\"}").append(i + 1 < N ? ",\n" : "\n"); ++ } ++ j.append(" ],\n \"messages\": [\n"); ++ for (int k = 0; k < out.size(); k++) { ++ final String[] m = out.get(k); ++ j.append(" {\"name\": \"").append(m[0]).append("\", \"type\": \"").append(m[1]).append("\", \"height\": ").append(m[2]) ++ .append(", \"wire\": \"").append(m[3]).append("\", \"author\": \"").append(m[4]).append("\"}") ++ .append(k + 1 < out.size() ? ",\n" : "\n"); ++ } ++ j.append(" ]\n}\n"); ++ final Path dir = Path.of(System.getenv("AERE_T4_VECTORS_OUT")); ++ Files.createDirectories(dir); ++ Files.writeString(dir.resolve("author-t4.json"), j.toString(), StandardCharsets.UTF_8); ++ } ++ ++ private static Optional seal( ++ final List falcon, final int index, final int signer, final Bytes32 message) { ++ return Optional.of( ++ new FalconSeal(index, Bytes.wrap(FALCON.sign(falcon.get(signer), message.toArrayUnsafe()).orElseThrow()))); ++ } ++} +diff --git a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/AereIdentityMessageTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/AereIdentityMessageTest.java +new file mode 100644 +index 0000000000..9124dc9338 +--- /dev/null ++++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/AereIdentityMessageTest.java +@@ -0,0 +1,165 @@ ++/* ++ * AERE AIP-22 stage 3: the identity switch, measured on real QBFT messages. ++ * ++ * Four upstream test nodes (QbftNodeList: a secp256k1 node key and a message factory each) get a ++ * registry v3 row each (a Falcon-512 key with its possession proof, and the ecdsa link signed by the ++ * node's own key). The validator set given to the upstream validators is the list of their IDS. ++ * ++ * What must hold, each with its negative: ++ * - armed, a Commit (and a Prepare) signed with the node's ECDSA key is accepted against the id set: ++ * the author is translated to the id, and the commit seal's creator is translated the same way; ++ * - DISARMED, the very same message is REFUSED against the id set (its author is an address): the ++ * translation, and nothing else, is what makes it pass; ++ * - armed but BELOW H_id, it is refused against ids and accepted against addresses; ++ * - a node with no row stays an address and is refused. ++ */ ++package org.hyperledger.besu.consensus.qbft.core.validation; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++ ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; ++import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; ++import org.hyperledger.besu.consensus.common.bft.PqRegistryV3; ++import org.hyperledger.besu.consensus.common.bft.SealScheme; ++import org.hyperledger.besu.consensus.common.bft.SealSchemes; ++import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; ++import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; ++import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec; ++import org.hyperledger.besu.crypto.SECPSignature; ++import org.hyperledger.besu.crypto.SecureRandomProvider; ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.datatypes.Hash; ++ ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Map; ++import java.util.TreeMap; ++ ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.bytes.Bytes32; ++import org.junit.jupiter.api.AfterEach; ++import org.junit.jupiter.api.BeforeEach; ++import org.junit.jupiter.api.Test; ++import org.junit.jupiter.api.extension.ExtendWith; ++import org.mockito.Mock; ++import org.mockito.junit.jupiter.MockitoExtension; ++ ++@ExtendWith(MockitoExtension.class) ++public class AereIdentityMessageTest { ++ ++ private static final long CHAIN = 28001; ++ private static final long H_ID = 10; ++ private static final int N = 4; ++ ++ private final Hash expectedHash = Hash.fromHexStringLenient("0x1"); ++ private @Mock QbftBlockCodec qbftBlockCodec; ++ private QbftNodeList nodes; ++ private final List
    ids = new ArrayList<>(); ++ ++ @BeforeEach ++ public void registryForTheNodes() { ++ nodes = QbftNodeList.createNodes(N, qbftBlockCodec); ++ final long bind = 5; ++ final List rows = new ArrayList<>(); ++ for (int i = 0; i < N; i++) { ++ final SealScheme f = SealSchemes.FALCON_512; ++ final SealScheme.GeneratedPair p = f.generate(SecureRandomProvider.createSecureRandom()); ++ final byte[] std = new byte[897]; ++ std[0] = 0x09; ++ System.arraycopy(p.publicRegistryForm(), 0, std, 1, 896); ++ final byte[] id = PqRegistryV3.idOf(std); ++ final Bytes32 popMsg = PqRegistryV3.popMessage(CHAIN, bind, N, i, id, f.wireId(), std); ++ final byte[] pop = f.sign(p.privateKey(), popMsg.toArrayUnsafe()).orElseThrow(); ++ final TreeMap keys = new TreeMap<>(); ++ keys.put(f.wireId() & 0xff, new PqRegistryV3.Key(f, std, pop)); ++ final PqRegistryV3.Row bare = new PqRegistryV3.Row(i, id, keys, null, Map.of(), null, null); ++ final Bytes32 rh = PqRegistryV3.rowHash(CHAIN, bind, N, bare); ++ final SECPSignature claim = ++ nodes.getNode(i).getNodeKey().sign(PqRegistryV3.claimDigest(CHAIN, rh)); ++ rows.add( ++ new PqRegistryV3.Row( ++ i, id, keys, null, Map.of(), ++ nodes.getNode(i).getAddress().getBytes().toArrayUnsafe(), ++ claim.encodedBytes().toArrayUnsafe())); ++ ids.add(Address.wrap(Bytes.wrap(id))); ++ } ++ final List hashes = new ArrayList<>(); ++ for (final PqRegistryV3.Row r : rows) { ++ hashes.add(PqRegistryV3.rowHash(CHAIN, bind, N, r)); ++ } ++ final Bytes32 root = PqRegistryV3.merkleRoot(hashes); ++ final PqRegistryV3.Registry reg = ++ new PqRegistryV3.Registry( ++ CHAIN, bind, N, rows, hashes, root, PqRegistryV3.registryHash(CHAIN, bind, N, root)); ++ final TreeMap epochs = new TreeMap<>(); ++ epochs.put(bind, reg); ++ AerePqIdentity.install(new AerePqIdentity.Config(H_ID, epochs)); ++ } ++ ++ @AfterEach ++ public void disarm() { ++ AerePqIdentity.uninstall(); ++ } ++ ++ private Commit commit(final int node, final ConsensusRoundIdentifier round) { ++ final SECPSignature seal = ++ nodes.getNode(node).getNodeKey().sign(Bytes32.wrap(expectedHash.getBytes())); ++ return nodes.getMessageFactory(node).createCommit(round, expectedHash, seal); ++ } ++ ++ @Test ++ public void armedACommitSignedByTheNodeKeyIsAcceptedAgainstTheIdSet() { ++ final ConsensusRoundIdentifier round = new ConsensusRoundIdentifier(H_ID, 0); ++ final CommitValidator v = new CommitValidator(ids, round, expectedHash, expectedHash); ++ for (int i = 0; i < N; i++) { ++ final Commit c = commit(i, round); ++ assertThat(c.getAuthor()).isEqualTo(ids.get(i)); ++ assertThat(v.validate(c)).as("node " + i).isTrue(); ++ } ++ } ++ ++ @Test ++ public void disarmedTheSameCommitIsRefusedAgainstTheIdSet() { ++ final ConsensusRoundIdentifier round = new ConsensusRoundIdentifier(H_ID, 0); ++ AerePqIdentity.uninstall(); ++ final CommitValidator v = new CommitValidator(ids, round, expectedHash, expectedHash); ++ final Commit c = commit(0, round); ++ assertThat(c.getAuthor()).isEqualTo(nodes.getNode(0).getAddress()); ++ assertThat(v.validate(c)).isFalse(); ++ } ++ ++ @Test ++ public void belowHidTheAuthorIsTheAddress() { ++ final ConsensusRoundIdentifier round = new ConsensusRoundIdentifier(H_ID - 1, 0); ++ final Commit c = commit(1, round); ++ assertThat(c.getAuthor()).isEqualTo(nodes.getNode(1).getAddress()); ++ assertThat(new CommitValidator(ids, round, expectedHash, expectedHash).validate(c)).isFalse(); ++ assertThat( ++ new CommitValidator(nodes.getNodeAddresses(), round, expectedHash, expectedHash) ++ .validate(c)) ++ .isTrue(); ++ } ++ ++ @Test ++ public void aNodeWithoutARowStaysAnAddressAndIsRefused() { ++ final ConsensusRoundIdentifier round = new ConsensusRoundIdentifier(H_ID + 3, 0); ++ final QbftNode stranger = QbftNode.create(qbftBlockCodec); ++ final SECPSignature seal = stranger.getNodeKey().sign(Bytes32.wrap(expectedHash.getBytes())); ++ final Commit c = stranger.getMessageFactory().createCommit(round, expectedHash, seal); ++ assertThat(c.getAuthor()).isEqualTo(stranger.getAddress()); ++ assertThat(new CommitValidator(ids, round, expectedHash, expectedHash).validate(c)).isFalse(); ++ } ++ ++ @Test ++ public void armedAPrepareIsAuthoredByTheId() { ++ final ConsensusRoundIdentifier round = new ConsensusRoundIdentifier(H_ID + 1, 0); ++ for (int i = 0; i < N; i++) { ++ final Prepare p = nodes.getMessageFactory(i).createPrepare(round, expectedHash); ++ assertThat(p.getAuthor()).isEqualTo(ids.get(i)); ++ assertThat(new PrepareValidator(ids, round, expectedHash).validate(p)).isTrue(); ++ } ++ AerePqIdentity.uninstall(); ++ final Prepare p = nodes.getMessageFactory(2).createPrepare(round, expectedHash); ++ assertThat(new PrepareValidator(ids, round, expectedHash).validate(p)).isFalse(); ++ } ++} +diff --git a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/PqFinalityLayersGuardTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/PqFinalityLayersGuardTest.java +new file mode 100644 +index 0000000000..fffe7b61ba +--- /dev/null ++++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/PqFinalityLayersGuardTest.java +@@ -0,0 +1,130 @@ ++/* ++ * Copyright contributors to Besu / AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.consensus.qbft.core.validation; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++import static org.assertj.core.api.Assertions.assertThatThrownBy; ++ ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; ++ ++import java.util.List; ++import java.util.Optional; ++ ++import org.junit.jupiter.api.AfterEach; ++import org.junit.jupiter.api.Test; ++ ++/** ++ * AIP-22 stage 4: H_fin is refused over a seal layer that is not verified from H_fin (AERE-PQC-FIN-02), ++ * named layer by layer; H_fin unset is inert. The last probe goes through the production path (the ++ * four properties the layers really read). The runner's negative control plants "never refuse" at run ++ * time and these probes turn red. ++ */ ++public class PqFinalityLayersGuardTest { ++ ++ private static final long H_FIN = 5_000L; ++ private static final String[] PROPS = { ++ PqProposalEnforcement.PROPERTY_FORK_BLOCK, ++ PqPrepareEnforcement.PROPERTY_FORK_BLOCK, ++ PqCommitEnforcement.PROPERTY_FORK_BLOCK, ++ PqRoundChangeEnforcement.PROPERTY_FORK_BLOCK ++ }; ++ ++ @AfterEach ++ public void clear() { ++ for (final String p : PROPS) { ++ System.clearProperty(p); ++ } ++ } ++ ++ private static PqFinalityLayersGuard.Layer armedFrom(final String property, final long from) { ++ return new PqFinalityLayersGuard.Layer(property, h -> h >= from); ++ } ++ ++ private static List allArmedFrom(final long from) { ++ return List.of( ++ armedFrom(PROPS[0], from), armedFrom(PROPS[1], from), armedFrom(PROPS[2], from), ++ armedFrom(PROPS[3], from)); ++ } ++ ++ @Test ++ public void everyLayerArmedAtOrBelowHfinPassesAndHfinUnsetIsInert() { ++ assertThat(PqFinalityLayersGuard.refusal(H_FIN, allArmedFrom(H_FIN))).isEmpty(); ++ assertThat(PqFinalityLayersGuard.refusal(H_FIN, allArmedFrom(100))).isEmpty(); ++ final List none = ++ List.of( ++ new PqFinalityLayersGuard.Layer(PROPS[0], null), ++ new PqFinalityLayersGuard.Layer(PROPS[1], null), ++ new PqFinalityLayersGuard.Layer(PROPS[2], null), ++ new PqFinalityLayersGuard.Layer(PROPS[3], null)); ++ assertThat(PqFinalityLayersGuard.refusal(AerePqIdentity.NEVER, none)).isEmpty(); ++ } ++ ++ @Test ++ public void aLayerUnsetOrArmedAboveHfinIsRefusedByName() { ++ for (int i = 0; i < PROPS.length; i++) { ++ final List unset = new java.util.ArrayList<>(allArmedFrom(100)); ++ unset.set(i, new PqFinalityLayersGuard.Layer(PROPS[i], null)); ++ final Optional r = PqFinalityLayersGuard.refusal(H_FIN, unset); ++ assertThat(r).as("layer %s unset", PROPS[i]).isPresent(); ++ assertThat(r.get()).startsWith("AERE-PQC-FIN-02").contains(PROPS[i] + " unset"); ++ ++ final List late = new java.util.ArrayList<>(allArmedFrom(100)); ++ late.set(i, armedFrom(PROPS[i], H_FIN + 1)); ++ final Optional r2 = PqFinalityLayersGuard.refusal(H_FIN, late); ++ assertThat(r2).as("layer %s armed one block above H_fin", PROPS[i]).isPresent(); ++ assertThat(r2.get()).contains(PROPS[i] + " armed above " + H_FIN); ++ } ++ } ++ ++ @Test ++ public void productionPathReadsTheFourPropertiesTheLayersRead() { ++ for (final String p : PROPS) { ++ System.setProperty(p, Long.toString(H_FIN - 10)); ++ } ++ PqFinalityLayersGuard.verifyOrAbort(H_FIN); ++ System.clearProperty(PqRoundChangeEnforcement.PROPERTY_FORK_BLOCK); ++ assertThatThrownBy(() -> PqFinalityLayersGuard.verifyOrAbort(H_FIN)) ++ .isInstanceOf(IllegalStateException.class) ++ .hasMessageStartingWith("AERE-PQC-FIN-02") ++ .hasMessageContaining(PqRoundChangeEnforcement.PROPERTY_FORK_BLOCK + " unset"); ++ // H_fin unset: inert whatever the layers ++ PqFinalityLayersGuard.verifyOrAbort(AerePqIdentity.NEVER); ++ } ++ ++ @Test ++ public void aSealingNodeMustSealAllFourMessagesAtOrBelowHfin() { ++ final long never = Long.MAX_VALUE; ++ assertThat(PqFinalityLayersGuard.emissionRefusal(AerePqIdentity.NEVER, true, never, never, never, never)) ++ .as("unset H_fin asks nothing") ++ .isEmpty(); ++ assertThat(PqFinalityLayersGuard.emissionRefusal(H_FIN, false, never, never, never, never)) ++ .as("a reader seals nothing and needs nothing") ++ .isEmpty(); ++ assertThat(PqFinalityLayersGuard.emissionRefusal(H_FIN, true, 32, 200, 200, 200)).isEmpty(); ++ assertThat(PqFinalityLayersGuard.emissionRefusal(H_FIN, true, H_FIN, H_FIN, H_FIN, H_FIN)).isEmpty(); ++ assertThat(PqFinalityLayersGuard.emissionRefusal(H_FIN, true, 32, never, 200, 200)) ++ .hasValueSatisfying( ++ r -> assertThat(r).startsWith("AERE-PQC-FIN-03").contains("aere.pq.proposalPq.attachBlock unset")); ++ assertThat(PqFinalityLayersGuard.emissionRefusal(H_FIN, true, 32, 200, H_FIN + 1, 200)) ++ .hasValueSatisfying(r -> assertThat(r).contains("aere.pq.preparePq.attachBlock armed above H_fin")); ++ assertThat(PqFinalityLayersGuard.emissionRefusal(H_FIN, true, 32, 200, 200, never)) ++ .hasValueSatisfying(r -> assertThat(r).contains("aere.pq.roundChangePq.attachBlock unset")); ++ assertThat(PqFinalityLayersGuard.emissionRefusal(H_FIN, true, H_FIN + 5, 200, 200, 200)) ++ .hasValueSatisfying(r -> assertThat(r).contains("aere.falcon.attachBlock armed above H_fin")); ++ assertThatThrownBy(() -> PqFinalityLayersGuard.verifyEmissionOrAbort(H_FIN, true, 32, never, 200, 200)) ++ .isInstanceOf(IllegalStateException.class) ++ .hasMessageStartingWith("AERE-PQC-FIN-03"); ++ } ++} +diff --git a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/PqHybridEnforcementTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/PqHybridEnforcementTest.java +index cf8c683f01..95b4b667b5 100755 +--- a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/PqHybridEnforcementTest.java ++++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/PqHybridEnforcementTest.java +@@ -173,40 +173,79 @@ public class PqHybridEnforcementTest { + final Optional refusal = + hibrid() + .refusal(H_HIBRID, VALIDATOR_0, DIGEST, Optional.of(sigiliuFalcon(0)), List.of()); + assertThat(refusal).isPresent(); + assertThat(refusal.get()).contains("carries no").contains(SealSchemes.SLH_DSA_128S.id()); + } + + @Test + public void aFullHybridCertificateCounts() { + assertThat( + hibrid() + .refusal( + H_HIBRID, + VALIDATOR_0, + DIGEST, + Optional.of(sigiliuFalcon(0)), + List.of(sigiliuSlh(0, DIGEST)))) + .isEmpty(); + } + ++ // ============================================ intervale per schema (AIP-22 treapta 2) ++ ++ /** ++ * With SLH-DSA on the 128 grid (Falcon on the 32 grid), counted from an activation height of 64, ++ * a commit at the parent of a Falcon-only anchor counts with the Falcon seal alone, and a commit ++ * at the parent of a hybrid anchor does not. The two heights differ in nothing but the grid; the ++ * grid origin is the negative control (read against another origin, the two heights swap). ++ */ ++ @Test ++ public void withPerSchemeIntervalsTheSlhSealIsDemandedOnlyAtParentsOfAnchorsOnItsGrid() { ++ final PqSchemeSchedule cuIntervale = ++ PqSchemeSchedule.parse( ++ H_ARMARE + ":" + SealSchemes.FALCON_512.id() + "/32+" + SealSchemes.SLH_DSA_128S.id() + "/128"); ++ final long origine = 64L; ++ long ancoraHibrida = origine; ++ while (ancoraHibrida <= H_HIBRID) { ++ ancoraHibrida += 128L; ++ } ++ final long ancoraDoarFalcon = ancoraHibrida + 32L; ++ final PqCommitEnforcement e = ++ new PqCommitEnforcement(H_ARMARE, registruFalcon(), cuIntervale, registry, h -> true, () -> origine); ++ assertThat(e.refusal(ancoraDoarFalcon - 1, VALIDATOR_0, DIGEST, Optional.of(sigiliuFalcon(0)), List.of())) ++ .isEmpty(); ++ final Optional refusal = ++ e.refusal(ancoraHibrida - 1, VALIDATOR_0, DIGEST, Optional.of(sigiliuFalcon(0)), List.of()); ++ assertThat(refusal).isPresent(); ++ assertThat(refusal.get()).contains("carries no").contains(SealSchemes.SLH_DSA_128S.id()); ++ assertThat( ++ e.refusal( ++ ancoraHibrida - 1, VALIDATOR_0, DIGEST, Optional.of(sigiliuFalcon(0)), List.of(sigiliuSlh(0, DIGEST)))) ++ .isEmpty(); ++ final PqCommitEnforcement altaOrigine = ++ new PqCommitEnforcement(H_ARMARE, registruFalcon(), cuIntervale, registry, h -> true, () -> origine + 32L); ++ assertThat(altaOrigine.refusal(ancoraHibrida - 1, VALIDATOR_0, DIGEST, Optional.of(sigiliuFalcon(0)), List.of())) ++ .isEmpty(); ++ assertThat(altaOrigine.refusal(ancoraDoarFalcon - 1, VALIDATOR_0, DIGEST, Optional.of(sigiliuFalcon(0)), List.of())) ++ .isPresent(); ++ } ++ + // ============================================================ controalele negative + + @Test + public void aHybridSealOverAnotherDigestDoesNotCount() { + final Hash altul = Hash.hash(Bytes.of(9, 9)); + final Optional refusal = + hibrid() + .refusal( + H_HIBRID, + VALIDATOR_0, + DIGEST, + Optional.of(sigiliuFalcon(0)), + List.of(sigiliuSlh(0, altul))); + assertThat(refusal).isPresent(); + assertThat(refusal.get()).contains("does NOT verify"); + } + + @Test + public void aHybridSealForAnotherIndexIsRefused() { + final Optional refusal = +diff --git a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/PqHybridRotationV3Test.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/PqHybridRotationV3Test.java +new file mode 100644 +index 0000000000..3a3e69691a +--- /dev/null ++++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/PqHybridRotationV3Test.java +@@ -0,0 +1,171 @@ ++/* AIP-22 stage 3b: the hybrid (SLH-DSA) seal of a COMMIT is judged, from H_k, with the key of the v3 epoch in force, not with the ++ * static v2 hybrid registry. ++ * ++ * Paid 2026-09-23 on testnet 28001: after the rotation at 3,097,600 the rotated row (index 2) signed its commits with its NEW ++ * SLH-DSA key, as the v3 epoch says, and PqCommitEnforcement still read the OLD key from the v2 hybrid registry, so every one of its ++ * commits at an anchor's parent was refused for six hours, invisibly while four other validators sufficed, until the chain stopped at ++ * 3,135,679 when the Nethermind validator fell behind. The anchor producer and PqAnchorSealsRule were already on v3. ++ * ++ * Real cryptography (Falcon-512 and SLH-DSA-SHA2-128s generated on every run, TEST keys); a v3 epoch built from the canonical row ++ * bytes; the v2 registry built from properties exactly as in production. The negative control plants, at run time, "keys never from ++ * v3" in PqCommitEnforcement: the two cases from H_k must turn red. */ ++package org.hyperledger.besu.consensus.qbft.core.validation; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++ ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; ++import org.hyperledger.besu.consensus.common.bft.FalconSeal; ++import org.hyperledger.besu.consensus.common.bft.HybridSignerRegistry; ++import org.hyperledger.besu.consensus.common.bft.PqRegistryV3; ++import org.hyperledger.besu.consensus.common.bft.PqSchemeSchedule; ++import org.hyperledger.besu.consensus.common.bft.PqSignerRegistry; ++import org.hyperledger.besu.consensus.common.bft.SchemeSeal; ++import org.hyperledger.besu.consensus.common.bft.SealScheme; ++import org.hyperledger.besu.consensus.common.bft.SealSchemes; ++import org.hyperledger.besu.crypto.SECPSignature; ++import org.hyperledger.besu.crypto.SecureRandomProvider; ++import org.hyperledger.besu.cryptoservices.NodeKey; ++import org.hyperledger.besu.cryptoservices.NodeKeyUtils; ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.datatypes.Hash; ++ ++import java.security.SecureRandom; ++import java.util.List; ++import java.util.Map; ++import java.util.Optional; ++import java.util.Properties; ++import java.util.TreeMap; ++ ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.bytes.Bytes32; ++import org.junit.jupiter.api.AfterEach; ++import org.junit.jupiter.api.BeforeEach; ++import org.junit.jupiter.api.Test; ++ ++public class PqHybridRotationV3Test { ++ private static final long CHAIN = 28001L; ++ private static final long H_ARMARE = 1_000L; ++ private static final long H_HIBRID = 2_000L; ++ private static final long H_K = 3_000L; ++ private static final Hash DIGEST = Hash.hash(Bytes.of(7, 7)); ++ private static final SealScheme FALCON = SealSchemes.FALCON_512; ++ private static final SealScheme SLH = SealSchemes.SLH_DSA_128S; ++ ++ private final SecureRandom random = SecureRandomProvider.createSecureRandom(); ++ private SealScheme.GeneratedPair falcon0; ++ private SealScheme.GeneratedPair slhOld; ++ private SealScheme.GeneratedPair slhNew; ++ private Address addr0; ++ private Address id0; ++ private PqCommitEnforcement enforcement; ++ ++ @BeforeEach ++ public void setup() { ++ falcon0 = FALCON.generate(random); ++ slhOld = SLH.generate(random); ++ slhNew = SLH.generate(random); ++ final NodeKey nk = NodeKeyUtils.generate(); ++ addr0 = org.hyperledger.besu.ethereum.core.Util.publicKeyToAddress(nk.getPublicKey()); ++ ++ // the v2 hybrid registry: index 0 is addr0, with the OLD SLH-DSA key (what the static registry keeps after a v3 rotation) ++ final Properties p = new Properties(); ++ p.setProperty("formatVersion", HybridSignerRegistry.FORMAT_VERSION); ++ p.setProperty("chainId", String.valueOf(CHAIN)); ++ p.setProperty("count", "1"); ++ p.setProperty("0.addr", addr0.toHexString()); ++ p.setProperty("0.key." + FALCON.id(), Bytes.wrap(falcon0.publicRegistryForm()).toHexString()); ++ p.setProperty("0.key." + SLH.id(), Bytes.wrap(slhOld.publicRegistryForm()).toHexString()); ++ final HybridSignerRegistry v2 = HybridSignerRegistry.fromProperties(p, "proba"); ++ ++ // the v3 epoch at H_k: row 0 keeps its Falcon key and carries the NEW SLH-DSA key (a rotation of the hybrid key) ++ final byte[] std = new byte[897]; ++ std[0] = 0x09; ++ System.arraycopy(falcon0.publicRegistryForm(), 0, std, 1, 896); ++ final byte[] id = PqRegistryV3.idOf(std); ++ id0 = Address.wrap(Bytes.wrap(id)); ++ final byte[] slhPub = slhNew.publicRegistryForm(); ++ final byte[] popF = FALCON.sign(falcon0.privateKey(), ++ PqRegistryV3.popMessage(CHAIN, H_K, 1, 0, id, FALCON.wireId(), std).toArrayUnsafe()).orElseThrow(); ++ final byte[] popS = SLH.sign(slhNew.privateKey(), ++ PqRegistryV3.popMessage(CHAIN, H_K, 1, 0, id, SLH.wireId(), slhPub).toArrayUnsafe()).orElseThrow(); ++ final TreeMap keys = new TreeMap<>(); ++ keys.put(FALCON.wireId() & 0xff, new PqRegistryV3.Key(FALCON, std, popF)); ++ keys.put(SLH.wireId() & 0xff, new PqRegistryV3.Key(SLH, slhPub, popS)); ++ final PqRegistryV3.Row bare = new PqRegistryV3.Row(0, id, keys, null, Map.of(), null, null); ++ final SECPSignature claim = nk.sign(PqRegistryV3.claimDigest(CHAIN, PqRegistryV3.rowHash(CHAIN, H_K, 1, bare))); ++ final PqRegistryV3.Row row = ++ new PqRegistryV3.Row(0, id, keys, null, Map.of(), addr0.getBytes().toArrayUnsafe(), claim.encodedBytes().toArrayUnsafe()); ++ final Bytes32 rh = PqRegistryV3.rowHash(CHAIN, H_K, 1, row); ++ final Bytes32 root = PqRegistryV3.merkleRoot(List.of(rh)); ++ final TreeMap epochs = new TreeMap<>(); ++ epochs.put(H_K, new PqRegistryV3.Registry(CHAIN, H_K, 1, List.of(row), List.of(rh), root, ++ PqRegistryV3.registryHash(CHAIN, H_K, 1, root))); ++ AerePqIdentity.uninstall(); ++ AerePqIdentity.install(new AerePqIdentity.Config(H_K, epochs, H_K)); ++ ++ // the Falcon part of the commit check: index 0 is addr0 below H_k and its id from H_k, the Falcon key unchanged ++ final PqSignerRegistry falconReg = ++ new PqSignerRegistry() { ++ @Override ++ public Address addressForIndexAtHistoric(final long h, final int i) { ++ return addressForIndexAtOwnHead(h, i); ++ } ++ ++ @Override ++ public Address addressForIndexAtOwnHead(final long h, final int i) { ++ return i != 0 ? null : (h >= H_K ? id0 : addr0); ++ } ++ ++ @Override ++ public boolean verifyAtHistoric(final long h, final int i, final Bytes m, final Bytes s) { ++ return verifyAtOwnHead(h, i, m, s); ++ } ++ ++ @Override ++ public boolean verifyAtOwnHead(final long h, final int i, final Bytes m, final Bytes s) { ++ return i == 0 && FALCON.verifyRaw(falcon0.publicRegistryForm(), m.toArray(), s.toArray()); ++ } ++ }; ++ final PqSchemeSchedule orar = ++ PqSchemeSchedule.parse(H_ARMARE + ":" + FALCON.id() + "," + H_HIBRID + ":" + FALCON.id() + "+" + SLH.id()); ++ enforcement = new PqCommitEnforcement(H_ARMARE, falconReg, orar, v2, h -> true); ++ } ++ ++ @AfterEach ++ public void disarm() { ++ AerePqIdentity.uninstall(); ++ } ++ ++ private Optional falconSeal() { ++ return Optional.of(new FalconSeal(0, Bytes.wrap(FALCON.sign(falcon0.privateKey(), DIGEST.getBytes().toArray()).orElseThrow()))); ++ } ++ ++ private List slhSeal(final SealScheme.GeneratedPair key) { ++ return List.of(new SchemeSeal(SLH.wireId(), 0, Bytes.wrap(SLH.sign(key.privateKey(), DIGEST.getBytes().toArray()).orElseThrow()))); ++ } ++ ++ @Test ++ public void fromHkTheRotatedSlhKeyOfTheV3EpochCounts() { ++ assertThat(enforcement.refusal(H_K + 5, id0, DIGEST, falconSeal(), slhSeal(slhNew))).isEmpty(); ++ } ++ ++ @Test ++ public void fromHkTheOldSlhKeyOfTheStaticRegistryNoLongerCounts() { ++ final Optional r = enforcement.refusal(H_K + 5, id0, DIGEST, falconSeal(), slhSeal(slhOld)); ++ assertThat(r).isPresent(); ++ assertThat(r.get()).contains("does NOT verify").contains(SLH.id()); ++ } ++ ++ @Test ++ public void belowHkTheStaticRegistryDecidesAsBefore() { ++ assertThat(enforcement.refusal(H_K - 5, addr0, DIGEST, falconSeal(), slhSeal(slhOld))).isEmpty(); ++ assertThat(enforcement.refusal(H_K - 5, addr0, DIGEST, falconSeal(), slhSeal(slhNew))).isPresent(); ++ } ++ ++ @Test ++ public void fromHkTheHybridSealCannotVouchForAnotherAuthor() { ++ final Optional r = ++ enforcement.refusal(H_K + 5, Address.fromHexString("0x" + "cd".repeat(20)), DIGEST, falconSeal(), slhSeal(slhNew)); ++ assertThat(r).isPresent(); ++ } ++} +diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderValidationRulesetFactory.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderValidationRulesetFactory.java +index cfc67a900d..4a2c4f9e0b 100644 +--- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderValidationRulesetFactory.java ++++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderValidationRulesetFactory.java +@@ -10,46 +10,47 @@ + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0003-aere-pq-anchor.patch. + */ + package org.hyperledger.besu.consensus.qbft; + + import static org.hyperledger.besu.ethereum.mainnet.AbstractGasLimitSpecification.DEFAULT_MAX_GAS_LIMIT; + import static org.hyperledger.besu.ethereum.mainnet.AbstractGasLimitSpecification.DEFAULT_MIN_GAS_LIMIT; + + import org.hyperledger.besu.consensus.common.bft.BftHelpers; + import org.hyperledger.besu.consensus.common.bft.FalconSealSupport; + import org.hyperledger.besu.consensus.common.bft.PqAnchorConfig; + import org.hyperledger.besu.consensus.common.bft.headervalidationrules.BftCoinbaseValidationRule; +-import org.hyperledger.besu.consensus.common.bft.headervalidationrules.BftCommitSealsValidationRule; + import org.hyperledger.besu.consensus.qbft.headervalidationrules.AereBaseFeeImportRule; + import org.hyperledger.besu.consensus.qbft.headervalidationrules.FalconSealValidationRule; + import org.hyperledger.besu.consensus.qbft.headervalidationrules.PqAnchorDigestAttachedRule; + import org.hyperledger.besu.consensus.qbft.headervalidationrules.PqAnchorDigestRule; + import org.hyperledger.besu.consensus.qbft.headervalidationrules.PqAnchorSealsRule; ++import org.hyperledger.besu.consensus.qbft.headervalidationrules.PqCheckpointRule; ++import org.hyperledger.besu.consensus.qbft.headervalidationrules.PqHeaderSealRule; + import org.hyperledger.besu.consensus.qbft.headervalidationrules.PqEmergencyShoutRule; + import org.hyperledger.besu.consensus.qbft.headervalidationrules.PqRegistryBindingRule; + import org.hyperledger.besu.consensus.qbft.headervalidationrules.QbftValidatorsValidationRule; + import org.hyperledger.besu.ethereum.core.BlockHeader; + import org.hyperledger.besu.ethereum.mainnet.BlockHeaderValidator; + import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket; + import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.AncestryValidationRule; + import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.ConstantFieldValidationRule; + import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.GasLimitRangeAndDeltaValidationRule; + import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.GasUsageValidationRule; + import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.TimestampBoundedByFutureParameter; + import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.TimestampMoreRecentThanParent; + + import java.time.Duration; + import java.util.Optional; + + import org.apache.tuweni.units.bigints.UInt256; + + /** The Qbft block header validation ruleset factory. */ + public class QbftBlockHeaderValidationRulesetFactory { +@@ -144,61 +145,67 @@ public class QbftBlockHeaderValidationRulesetFactory { + DEFAULT_MIN_GAS_LIMIT, DEFAULT_MAX_GAS_LIMIT, baseFeeMarket)) + .addRule(new TimestampBoundedByFutureParameter(1)) + // AERE D-AMONTE-02: the base-fee rule every non-BFT factory in this jar wires and the + // QBFT one upstream forgot. Height-gated (disarmed = today's behaviour, byte for byte): + // the chain's HISTORY contains blocks this validation would reject (the two floor-less + // days, the lost-threshold window where the fee was not a function of the parent), so + // it must never look below its arming height. Delegates to THIS node's fee market, so + // the AERE 1 Gwei floor is validated too - the check that closes the empty-block + // one-wei divergence measured on the mixed network (STARE-PRODUCATOR 1bis). + .addRule( + new AereBaseFeeImportRule( + AereBaseFeeImportRule.armedFromSystemConfig(), baseFeeMarket)) + .addRule( + new ConstantFieldValidationRule<>( + "MixHash", BlockHeader::getMixHash, BftHelpers.EXPECTED_MIX_HASH)) + .addRule( + new ConstantFieldValidationRule<>( + "Difficulty", BlockHeader::getDifficulty, UInt256.ONE)) + .addRule(new QbftValidatorsValidationRule(useValidatorContract)) + .addRule(new BftCoinbaseValidationRule()) +- .addRule(new BftCommitSealsValidationRule()) ++ // AERE AIP-22 stage 5: upstream's committed seals rule below H_hdr, unchanged; from H_hdr the proposer's ++ // post-quantum seal (element 6) and an EMPTY committed-seal element (PqHeaderSealRule) ++ .addRule(PqHeaderSealRule.forFleet(pqAnchorConfig.chainId())) + // AERE ANCORA-V2: the legacy log-only Falcon rule now stands down at H. With an + // unconfigured anchor this is Long.MAX_VALUE, i.e. it never stands down and behaviour is + // unchanged. + .addRule( + new FalconSealValidationRule(pqAnchorConfig.legacyFalconRuleRetirementBlock())) + // AERE ANCORA-V2 R1: cheap, detached, IN LIGHT VALIDATION. Ordered before R2 so the one + // keccak that binds the certificate to the block hash runs before k Falcon + // verifications are spent on it. + .addRule(new PqAnchorDigestRule(pqAnchorConfig)) + // AERE SINCRONIZARE R1A (2026-08-02): the SAME digest verdict, on the ATTACHED side. + // Measured cause it repairs: SKIP_DETACHED, the mode FullImportBlockStep passes to + // importBlock for every block acquired by sync, keeps exactly the rules that are NOT + // detached, so R1 does not run at import; and DETACHED_ONLY, the mode under which R1 + // does run, is only applied by DownloadHeaderSequenceTask, i.e. only on ranges with a + // closed end. The open-ended range at the tip of a recovery, 199 blocks by default, was + // therefore checked by neither. Ordered immediately before R2 so the one keccak still + // runs before k Falcon verifications are spent. Delegates to R1, so there is one + // definition of the digest and the two paths cannot drift. + .addRule(new PqAnchorDigestAttachedRule(pqAnchorConfig)) + // AERE ANCORA-V2 R2: attached, full validation only. + .addRule(new PqAnchorSealsRule(pqAnchorConfig)) + // AERE A8 per-block half: the registry this node runs must be the registry + // config.pqRegistryHash requires AT THIS HEIGHT. The startup guard answers + // that once, against the head that existed at startup; a rotation entry in + // the schedule can pass underneath a running node and never be noticed. + // Inert when no schedule is configured, which is chain 2800 today. +- .addRule(new PqRegistryBindingRule()); ++ .addRule(new PqRegistryBindingRule()) ++ // AERE AIP-22 stage 4: the checkpoint (aere.pq.checkpoint=:); a header at a ++ // checkpoint height with another hash is refused. Attached, so it runs at import. Inert ++ // when unset, which is every chain today; a malformed value refuses at load. ++ .addRule(PqCheckpointRule.fromSystemConfiguration()); + + // Currently the minimum acceptable time between blocks is 1 second. The timestamp of an + // Ethereum header is stored as seconds since Unix epoch so blocks being produced more + // frequently than once a second cannot pass this validator. For non-production scenarios + // (e.g. for testing block production much more frequently than once a second) Besu has + // an experimental 'xblockperiodmilliseconds' option for BFT chains. If this is enabled + // we cannot apply the TimestampMoreRecentThanParent validation rule so we do not add it + if (minimumTimeBetweenBlocks.compareTo(Duration.ofSeconds(1)) >= 0) { + ruleBuilder.addRule(new TimestampMoreRecentThanParent(minimumTimeBetweenBlocks.toSeconds())); + } + return ruleBuilder; + } + } +diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/QbftExtraDataCodec.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/QbftExtraDataCodec.java +index b3096d3313..d4f6e2d8fc 100644 +--- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/QbftExtraDataCodec.java ++++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/QbftExtraDataCodec.java +@@ -89,40 +89,53 @@ public class QbftExtraDataCodec extends BftExtraDataCodec { + /** + * Create genesis extra data string. + * + * @param validators the validators + * @return the string + */ + public static String createGenesisExtraDataString(final List
    validators) { + return encodeFromAddresses(validators).toString(); + } + + @Override + public BftExtraData decodeRaw(final Bytes input) { + if (input.isEmpty()) { + throw new IllegalArgumentException("Invalid Bytes supplied - Bft Extra Data required."); + } + + final RLPInput rlpInput = new BytesValueRLPInput(input, false); + + rlpInput.enterList(); // This accounts for the "root node" which contains BFT data items. + final Bytes vanityData = rlpInput.readBytes(); ++ // AERE-D415 (2026-09-25): the vanity field is exactly 32 bytes at EVERY height, not only where ++ // the anchor rule looks (PqAnchorDigestRule checks it at anchor heights alone). The second ++ // client's decoder has required 32 from the start, so every header of chains 2800 and 28001, ++ // both geneses included, satisfies it; the differential fuzzer of the stage-5 header rule found ++ // the two clients judging a 0-, 31-, 33- or 64-byte vanity between anchors differently (this ++ // codec admitted it, the second client refused it). One rule, in the codec, for both clients. ++ if (vanityData.size() != EXTRA_VANITY_LENGTH) { ++ throw new RLPException( ++ "AERE-D415: QBFT vanity must be exactly " ++ + EXTRA_VANITY_LENGTH ++ + " bytes, the header carries " ++ + vanityData.size()); ++ } + final List
    validators = rlpInput.readList(Address::readFrom); + + final Optional vote; + if (rlpInput.nextIsList() && rlpInput.nextSize() == 0) { + vote = Optional.empty(); + rlpInput.skipNext(); + } else { + vote = Optional.of(decodeVote(rlpInput)); + } + + final int round = rlpInput.readIntScalar(); + final List seals = + rlpInput.readList( + rlp -> SignatureAlgorithmFactory.getInstance().decodeSignature(rlp.readBytes())); + + // AERE hybrid PQC: an OPTIONAL parallel Falcon-512 seal list may follow the ECDSA seals. + // Backward-tolerant: older/exclude/no-certificate encodings without this element decode to an + // empty list. + final List falconSeals; + final List hybridSeals; +@@ -147,54 +160,69 @@ public class QbftExtraDataCodec extends BftExtraDataCodec { + + e.getMessage()); + } + } else { + hybridSeals = Collections.emptyList(); + falconSeals = + new BytesValueRLPInput(certificateRaw, false) + .readList( + rlp -> { + rlp.enterList(); + final int idx = rlp.readIntScalar(); + final Bytes sig = rlp.readBytes(); + rlp.leaveList(); + return new FalconSeal(idx, sig); + }); + } + } else { + falconSeals = Collections.emptyList(); + hybridSeals = Collections.emptyList(); + } + ++ // AERE AIP-22 stage 5: an OPTIONAL seventh element, the proposer's seal [index, signature], after ++ // the certificate slot. When it is present the certificate slot is ALWAYS written (an empty list ++ // when the header carries no certificate), so the POSITION tells the two apart, never the shape ++ // (a proposer seal from index 2 would otherwise look like the head of a v2 certificate), and the ++ // canonical round trip below keeps every value to exactly one encoding. ++ Optional proposerSeal = Optional.empty(); ++ if (!rlpInput.isEndOfCurrentList()) { ++ rlpInput.enterList(); ++ final int idx = rlpInput.readIntScalar(); ++ final Bytes sig = rlpInput.readBytes(); ++ rlpInput.leaveList(); ++ proposerSeal = Optional.of(new FalconSeal(idx, sig)); ++ } ++ + // AERE FIX-MALEABILITATE-BLOC (2026-08-01), gate 1 of 2: the leave is STRICT. + // + // Upstream ends this decode with leaveListLenient(), which silently discards anything still + // left in the outer list. That is not survivable here, because the QBFT block hash and the + // committed-seal pre-image are BOTH computed from a RE-ENCODE of the decoded BftExtraData + // (BftBlockHashing.calculateHashOfBftBlockOnchain line 84-91, calculateDataHashForCommittedSeal + // line 53-75). Anything the decoder discards is therefore dropped before hashing, so two + // different header byte strings carry the same block hash and the same genuine validator + // seals. leaveList() rejects exactly the inputs that have content left over, and is + // byte-for-byte identical to the lenient leave on every input that has not. + rlpInput.leaveList(); + + final BftExtraData decoded = +- new BftExtraData(vanityData, seals, vote, round, validators, falconSeals, hybridSeals); ++ new BftExtraData( ++ vanityData, seals, vote, round, validators, falconSeals, hybridSeals, proposerSeal); + + // AERE FIX-MALEABILITATE-BLOC (2026-08-01), gate 2 of 2: CANONICAL ROUND TRIP. + // + // The strict leave alone does not close the hole. The Falcon element is OPTIONAL on the wire + // and the encoder omits it when the certificate is empty, so a header carrying an explicit + // EMPTY Falcon list decodes to exactly the same value as a header carrying no Falcon element + // at all: the trailing 0xc0 is CONSUMED, not left over, so no leave, strict or lenient, can + // see it. Requiring the full re-encode to reproduce the received bytes makes the accepted + // encoding unique by construction, and closes every present and future shape of this defect + // rather than the one instance of it we happened to look for. + // + // Backward compatibility: the re-encode used here is the same EncodingType.ALL the block + // producer uses, so every header any Aere or stock Besu node has ever produced round trips + // unchanged. Headers with no Falcon element re-encode with no Falcon element, which is why + // the whole pre-Falcon history of the chain still decodes. + final Bytes canonical = encode(decoded, EncodingType.ALL); + if (!canonical.equals(input)) { + throw new RLPException( + "Non-canonical BFT extra data: the header's extraData is " + + input.size() +@@ -226,40 +254,50 @@ public class QbftExtraDataCodec extends BftExtraDataCodec { + if (encodingType != EncodingType.EXCLUDE_COMMIT_SEALS) { + encoder.writeList( + bftExtraData.getSeals(), (committer, rlp) -> rlp.writeBytes(committer.encodedBytes())); + // AERE hybrid PQC: only the full (stored-header) encoding carries the parallel Falcon + // quorum certificate, and only when it is non-empty. The exclude encodings omit it so the + // committed-seal hash and the on-chain block hash are byte-identical to upstream Besu, and a + // header with no certificate is byte-identical to upstream too, so the Falcon seals are + // never part of any signed pre-image and never disturb the block hash. + if (!bftExtraData.getHybridSeals().isEmpty()) { + // AERE ANCHOR V2: the scheme-tagged certificate, canonical bytes, in the same slot. + encoder.writeRaw(PqAnchorV2.encode(bftExtraData.getHybridSeals())); + } else if (!bftExtraData.getFalconSeals().isEmpty()) { + encoder.writeList( + bftExtraData.getFalconSeals(), + (falconSeal, rlp) -> { + rlp.startList(); + rlp.writeIntScalar(falconSeal.getValidatorIndex()); + rlp.writeBytes(falconSeal.getSignature()); + rlp.endList(); + }); ++ } else if (bftExtraData.getPqProposerSeal().isPresent()) { ++ // AERE AIP-22 stage 5: the certificate slot stays in place, empty, so the seal is element 6 ++ encoder.writeEmptyList(); ++ } ++ if (bftExtraData.getPqProposerSeal().isPresent()) { ++ final FalconSeal ps = bftExtraData.getPqProposerSeal().get(); ++ encoder.startList(); ++ encoder.writeIntScalar(ps.getValidatorIndex()); ++ encoder.writeBytes(ps.getSignature()); ++ encoder.endList(); + } + } else { + encoder.writeEmptyList(); + } + } else { + encoder.writeIntScalar(0); + encoder.writeEmptyList(); + } + encoder.endList(); + + return encoder.encoded(); + } + + /** + * Encode vote. + * + * @param rlpOutput the rlp output + * @param vote the vote + */ + protected void encodeVote(final RLPOutput rlpOutput, final Vote vote) { +diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/adaptor/QbftBlockCreatorAdaptor.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/adaptor/QbftBlockCreatorAdaptor.java +index dd67707b14..24769c3472 100644 +--- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/adaptor/QbftBlockCreatorAdaptor.java ++++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/adaptor/QbftBlockCreatorAdaptor.java +@@ -70,40 +70,72 @@ public class QbftBlockCreatorAdaptor implements QbftBlockCreator { + this.besuBlockCreator = besuBftBlockCreator; + this.bftExtraDataCodec = bftExtraDataCodec; + } + + @Override + public BlockCreationResult createBlock( + final long headerTimeStampSeconds, final QbftBlockHeader parentHeader) { + var blockResult = + besuBlockCreator.createBlock( + headerTimeStampSeconds, AdaptorUtil.toBesuBlockHeader(parentHeader)); + return new BlockCreationResult( + new QbftBlockAdaptor(blockResult.getBlock()), blockResult.getBlockAccessList()); + } + + @Override + public QbftBlock createSealedBlock( + final QbftBlock block, final int roundNumber, final Collection commitSeals) { + return createSealedBlock(block, roundNumber, commitSeals, Collections.emptyList()); + } + ++ /** ++ * AIP-22 stage 5: the stage-5 header, from H_hdr. The proposed header's extraData is carried over ++ * whole (vanity with the anchor digest, validators, vote, the anchor certificate verbatim) through ++ * {@link BftExtraData#withSeals}, so nothing the proposer chose can be dropped here; only the round ++ * is set to the commit round, the ECDSA committed seals are EMPTY and element 6 is the proposal's ++ * post-quantum seal. Every node seals the same bytes: the header is no longer assembled from what ++ * each node heard. ++ */ ++ @Override ++ public QbftBlock createSealedBlockWithProposerSeal( ++ final QbftBlock block, final int roundNumber, final FalconSeal proposerSeal) { ++ final Block besuBlock = AdaptorUtil.toBesuBlock(block); ++ final BftExtraData initial = bftExtraDataCodec.decode(AdaptorUtil.toBesuBlockHeader(block.getHeader())); ++ final BftExtraData withRound = ++ new BftExtraData( ++ initial.getVanityData(), ++ Collections.emptyList(), ++ initial.getVote(), ++ roundNumber, ++ initial.getValidators(), ++ initial.getFalconSeals(), ++ initial.getHybridSeals(), ++ initial.getPqProposerSeal()); ++ final BftExtraData sealed = withRound.withSeals(Collections.emptyList(), Optional.of(proposerSeal)); ++ final BlockHeader header = ++ BlockHeaderBuilder.fromHeader(AdaptorUtil.toBesuBlockHeader(block.getHeader())) ++ .extraData(bftExtraDataCodec.encode(sealed)) ++ .blockHeaderFunctions(BftBlockHeaderFunctions.forOnchainBlock(bftExtraDataCodec)) ++ .buildBlockHeader(); ++ return new QbftBlockAdaptor(new Block(header, besuBlock.getBody())); ++ } ++ + @Override + public QbftBlock createSealedBlock( + final QbftBlock block, + final int roundNumber, + final Collection commitSeals, + final Collection collectedFalconSeals) { + final Block besuBlock = AdaptorUtil.toBesuBlock(block); + final QbftBlockHeader initialHeader = block.getHeader(); + final BftExtraData initialExtraData = + bftExtraDataCodec.decode(AdaptorUtil.toBesuBlockHeader(initialHeader)); + + // AERE ANCHOR V2, THE MEASURED TRAP, CLOSED HERE. Above the activation height element 6 is no + // longer "the seals I heard for THIS block": it is the quorum certificate over the PARENT, + // CHOSEN BY THE PROPOSER, and vanityData carries its digest D. Every node that seals this block + // must therefore carry the proposer's bytes across UNCHANGED. The legacy assembly below would + // overwrite them with what this node heard for the current block, which would leave a header + // whose vanity D no longer matches its own element 6, i.e. a header this node's own digest rule + // rejects. So above the activation height the assembler is skipped outright. + // + // Note what is NOT done here: no re-verification, no re-selection, no comparison against what +diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/adaptor/QbftFinalStateImpl.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/adaptor/QbftFinalStateImpl.java +index 5a3ff17130..03d2c64c9c 100644 +--- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/adaptor/QbftFinalStateImpl.java ++++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/adaptor/QbftFinalStateImpl.java +@@ -1,36 +1,43 @@ + /* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/0008-aere-pq-aip22.patch. + */ + package org.hyperledger.besu.consensus.qbft.adaptor; + ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; + import org.hyperledger.besu.consensus.common.bft.BftHelpers; + import org.hyperledger.besu.consensus.common.bft.BlockTimer; + import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; + import org.hyperledger.besu.consensus.common.bft.RoundTimer; + import org.hyperledger.besu.consensus.common.bft.blockcreation.ProposerSelector; + import org.hyperledger.besu.consensus.common.bft.network.ValidatorMulticaster; + import org.hyperledger.besu.consensus.common.validator.ValidatorProvider; + import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCreatorFactory; + import org.hyperledger.besu.consensus.qbft.core.types.QbftFinalState; + import org.hyperledger.besu.cryptoservices.NodeKey; + import org.hyperledger.besu.datatypes.Address; + + import java.time.Clock; + import java.util.Collection; + + /** Besu implementation of QbftFinalState for maintaining the state of a QBFT network. */ + public class QbftFinalStateImpl implements QbftFinalState { + private final ValidatorProvider validatorProvider; + private final NodeKey nodeKey; + private final Address localAddress; +@@ -105,82 +112,83 @@ public class QbftFinalStateImpl implements QbftFinalState { + return nodeKey; + } + + /** + * Gets local address. + * + * @return the local address + */ + @Override + public Address getLocalAddress() { + return localAddress; + } + + /** + * Is local node validator. + * + * @return the boolean + */ + @Override + public boolean isLocalNodeValidator() { +- return getValidators().contains(localAddress); ++ return getValidators().stream().anyMatch(a -> AerePqIdentity.isLocal(a, localAddress)); + } + + /** + * Gets round timer. + * + * @return the round timer + */ + @Override + public RoundTimer getRoundTimer() { + return roundTimer; + } + + /** + * Gets block creator factory. + * + * @return the block creator factory + */ + @Override + public QbftBlockCreatorFactory getBlockCreatorFactory() { + return blockCreatorFactory; + } + + @Override + public int getQuorum() { + return BftHelpers.calculateRequiredValidatorQuorum(getValidators().size()); + } + + @Override + public BlockTimer getBlockTimer() { + return blockTimer; + } + + /** + * Is local node proposer for round. + * + * @param roundIdentifier the round identifier + * @return the boolean + */ + @Override + public boolean isLocalNodeProposerForRound(final ConsensusRoundIdentifier roundIdentifier) { +- return getProposerForRound(roundIdentifier).equals(localAddress); ++ return getProposerForRound(roundIdentifier) ++ .equals(AerePqIdentity.local(localAddress, roundIdentifier.getSequenceNumber())); + } + + /** + * Gets proposer for round. + * + * @param roundIdentifier the round identifier + * @return the proposer for round + */ + public Address getProposerForRound(final ConsensusRoundIdentifier roundIdentifier) { + return proposerSelector.selectProposerForRound(roundIdentifier); + } + + /** + * Gets clock. + * + * @return the clock + */ + @Override + public Clock getClock() { + return clock; +diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqAnchorDigestRule.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqAnchorDigestRule.java +old mode 100755 +new mode 100644 +index 3b80c4302c..a9ba7a2ef3 +--- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqAnchorDigestRule.java ++++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqAnchorDigestRule.java +@@ -119,79 +119,79 @@ public class PqAnchorDigestRule implements DetachedBlockHeaderValidationRule { + public boolean validate(final BlockHeader header, final BlockHeader parent) { + final long number = header.getNumber(); + + // HEIGHT GATE FIRST. Below H nothing at all happens: no decode, no allocation, no log. This is + // the property that lets a binary built from this code run on a live node before activation and + // behave bit-for-bit as today. From 2026-08-07 the gate also covers the interval: at a height + // that carries no certificate there is nothing to bind, so there is nothing to judge. + // + // THE SAME METHOD AS R2, and not two questions that merely resemble each other. See the note in + // PqAnchorSealsRule. + if (!config.anchorAppliesAt(number)) { + return true; + } + + // SECOND GATE: the named historical windows in which these rules were not in force. Inside one + // of them vanityData carries the client's version string rather than a digest, so there is no + // digest to match and no recomputation can produce one; refusing would stop this node forever + // at a height the whole network holds. See PqAnchorLapse for what happened, how the bounds were + // measured, and why an exception written anywhere other than validation moves the error instead + // of ending it. +- if (PqAnchorLapse.isDisarmed(number)) { ++ if (PqAnchorLapse.isDisarmed(config.chainId(), number)) { + return acceptAsWrittenInsideLapse(header, number); + } + + try { + final BftExtraData extraData = extraDataCodec.decodeRaw(header.getExtraData()); + + final Bytes vanity = extraData.getVanityData(); + if (vanity.size() != BftExtraDataCodec.EXTRA_VANITY_LENGTH) { + LOG.warn( + "AERE PQ ANCHOR (R1): block {} REJECTED - vanityData is {} bytes, expected {}. From H " + + "the whole vanity field is the anchor digest D.", + number, + vanity.size(), + BftExtraDataCodec.EXTRA_VANITY_LENGTH); + return false; + } + + // AERE ANCHOR V2 (2026-09-03): from the v2 height the ONLY accepted form is the scheme-tagged + // certificate under the v2 digest; below it a v2 certificate is refused. Both directions + // are checked so the switch is a clean fork and never a header two nodes read differently. + if (config.anchorV2AppliesAt(number)) { + return judgeV2(number, header, extraData, vanity); + } + if (!extraData.getHybridSeals().isEmpty()) { + LOG.warn( + "AERE PQ ANCHOR (R1): block {} REJECTED - carries a v2 (scheme-tagged) certificate below" + + " the v2 activation height {}.", + number, + config.anchorV2Block()); + return false; + } + final List certificate = List.copyOf(extraData.getFalconSeals()); + // Height aware since 2026-08-11. Inside the one measured historical window the ordering + // requirement relaxes from SORTED to DISTINCT, because 36 canonical headers were written + // unsorted during a production interruption and a node syncing from genesis would otherwise + // stop at the first of them and never pass it. Distinctness is not relaxed at any height, so a + // repeated index stays unrepresentable everywhere. See PqAnchor.hasAcceptableIndices. +- if (!PqAnchor.hasAcceptableIndices(certificate, number)) { ++ if (!PqAnchor.hasAcceptableIndices(config.chainId(), certificate, number)) { + // Checked HERE, not only in the seals rule, so reordering and duplicate indices are caught + // in LIGHT validation too, and so that "the order given" and "sorted" are the same list for + // every header this rule accepts. + LOG.warn( + "AERE PQ ANCHOR (R1): block {} REJECTED - the carried certificate's validator indices " + + "are not strictly increasing ({} seal(s)). Exactly one order is accepted for a " + + "given set, which is also what makes a repeated index unrepresentable.", + number, + certificate.size()); + return false; + } + + final Bytes32 expected = + PqAnchor.anchorDigest( + config.chainId(), number - 1L, header.getParentHash().getBytes(), certificate); + + if (!expected.equals(Bytes32.wrap(vanity))) { + LOG.warn( + "AERE PQ ANCHOR (R1): block {} REJECTED - anchor digest mismatch. vanityData carries " + + "{} but the certificate actually carried in this header ({} seal(s), over parent " +@@ -260,48 +260,48 @@ public class PqAnchorDigestRule implements DetachedBlockHeaderValidationRule { + * history that exists and nothing weaker. + * + *

    Decoding must still succeed. A header this rule cannot parse has not been shown to be one of + * the headers the window is about, so it is refused here as everywhere else in this file. + * + * @param header the header being judged + * @param number its height + * @return true iff the carried certificate decodes and its indices are distinct and non-negative + */ + private boolean acceptAsWrittenInsideLapse(final BlockHeader header, final long number) { + try { + final BftExtraData extraData = extraDataCodec.decodeRaw(header.getExtraData()); + final List certificate = List.copyOf(extraData.getFalconSeals()); + if (!PqAnchor.hasDistinctNonNegativeIndices(certificate)) { + LOG.warn( + "AERE PQ ANCHOR (R1): block {} REJECTED - it falls inside the historical range {} in " + + "which the anchor rules were not in force, but its certificate repeats a " + + "validator index or carries a negative one. That is not a shape any header of " + + "that range has, and it is the one property the exception does not relax.", + number, +- PqAnchorLapse.windowCovering(number).orElse(null)); ++ PqAnchorLapse.windowCovering(config.chainId(), number).orElse(null)); + return false; + } + LOG.debug( + "AERE PQ ANCHOR (R1): block {} accepted as written; it falls inside the historical range " + + "{} in which the anchor rules were not in force, so it carries no digest to bind.", + number, +- PqAnchorLapse.windowCovering(number).orElse(null)); ++ PqAnchorLapse.windowCovering(config.chainId(), number).orElse(null)); + return true; + } catch (final Exception e) { + LOG.warn( + "AERE PQ ANCHOR (R1): block {} REJECTED - it falls inside a historical unenforced range " + + "but its extraData could not be decoded: {}", + number, + e.toString()); + return false; + } + } + + @Override + public boolean includeInLightValidation() { + return true; + } + + @Override + public String toString() { + return "PqAnchorDigest(detached, light, " + + (config.everActive() ? "H=" + config.anchorBlock() : "INACTIVE") +diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqAnchorSealsRule.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqAnchorSealsRule.java +old mode 100755 +new mode 100644 +index 78423af47a..3f58217d1f +--- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqAnchorSealsRule.java ++++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqAnchorSealsRule.java +@@ -1,36 +1,37 @@ + /* + * Copyright contributors to Besu / AERE Network. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + package org.hyperledger.besu.consensus.qbft.headervalidationrules; + ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; + import org.hyperledger.besu.consensus.common.bft.BftContext; + import org.hyperledger.besu.consensus.common.bft.BftExtraData; + import org.hyperledger.besu.consensus.common.bft.FalconSeal; + import org.hyperledger.besu.consensus.common.bft.FalconSealSupport; + import org.hyperledger.besu.consensus.common.bft.HybridSealSupport; + import org.hyperledger.besu.consensus.common.bft.HybridSignerRegistry; + import org.hyperledger.besu.consensus.common.bft.PqAnchor; + import org.hyperledger.besu.consensus.common.bft.PqAnchorConfig; + import org.hyperledger.besu.consensus.common.bft.PqAnchorLapse; + import org.hyperledger.besu.consensus.common.bft.PqAnchorV2; + import org.hyperledger.besu.consensus.common.bft.PqSignerRegistry; + import org.hyperledger.besu.consensus.common.bft.SchemeSeal; + import org.hyperledger.besu.consensus.common.bft.SealScheme; + import org.hyperledger.besu.consensus.common.bft.SealSchemes; + import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.ethereum.ProtocolContext; + import org.hyperledger.besu.ethereum.core.BlockHeader; + import org.hyperledger.besu.ethereum.mainnet.AttachedBlockHeaderValidationRule; + +@@ -125,41 +126,41 @@ public class PqAnchorSealsRule implements AttachedBlockHeaderValidationRule { + public boolean validate( + final BlockHeader header, final BlockHeader parent, final ProtocolContext protocolContext) { + final long number = header.getNumber(); + + // HEIGHT GATE FIRST, same contract as R1: below H this rule does nothing at all, and from + // 2026-08-07 it also does nothing at a height that carries no certificate. + // + // BOTH RULES ASK THE SAME QUESTION, THROUGH THE SAME METHOD, and that is deliberate. + // anchorAppliesAt() = activeAt() AND isAnchorHeight(). If R1 and R2 each asked it their own + // way, a header accepted by one and refused by the other would be a chain break, appearing at + // exactly the first height that is not an anchor height, i.e. the day after activation. + if (!config.anchorAppliesAt(number)) { + return true; + } + + // SECOND GATE, and the SAME method R1 asks, for the same reason both rules share + // anchorAppliesAt: if the two rules each decided this boundary their own way, a header accepted + // by one and refused by the other would be a chain break. Inside a named window the threshold + // was not in force when the header was written and the indices were written in arrival order, + // so neither can be required of it now. +- if (PqAnchorLapse.isDisarmed(number)) { ++ if (PqAnchorLapse.isDisarmed(config.chainId(), number)) { + return acceptAsWrittenInsideLapse(header, number); + } + + try { + if (parent == null) { + LOG.warn( + "AERE PQ ANCHOR (R2): block {} REJECTED - no parent header available, so the " + + "certificate cannot be checked against the parent it claims to attest to.", + number); + return false; + } + // The certificate attests to the parent by NUMBER and HASH, and R1 has already bound the + // digest to header.getParentHash(). If the parent handed to this rule were a different header, + // R1 and R2 would be talking about two different objects. Cheap, and it removes any dependence + // on rule ordering with AncestryValidationRule. + if (!parent.getHash().equals(header.getParentHash()) + || parent.getNumber() != number - 1L) { + LOG.warn( + "AERE PQ ANCHOR (R2): block {} REJECTED - the supplied parent (number {}, hash {}) is " + + "not the parent this header names (number {}, hash {}).", +@@ -187,66 +188,66 @@ public class PqAnchorSealsRule implements AttachedBlockHeaderValidationRule { + } + if (!extraData.getHybridSeals().isEmpty()) { + LOG.warn( + "AERE PQ ANCHOR (R2): block {} REJECTED - carries a v2 (scheme-tagged) certificate below" + + " the v2 activation height {}.", + number, + config.anchorV2Block()); + return false; + } + final List certificate = List.copyOf(extraData.getFalconSeals()); + final int k = certificate.size(); + + // THE THRESHOLD THIS HEIGHT WAS ACTUALLY JUDGED BY. Normally the configured schedule. Inside + // a named historical range it is the LOWER of the schedule and the emergency ceiling that was + // in force when these headers were written, which is the same lever the fleet itself used at + // the time, replayed from a fixed range instead of from a runtime option. Asking a header for + // more than was asked of the proposer that wrote it refuses history that no node can + // reproduce; asking for the ceiling rather than for nothing keeps the strongest claim the + // range supports, and the ceiling is a measured floor, never zero. See PqAnchorLapse. + int required = config.minSealsAt(number); +- final OptionalInt inForce = PqAnchorLapse.historicMinSeals(number); ++ final OptionalInt inForce = PqAnchorLapse.historicMinSeals(config.chainId(), number); + if (inForce.isPresent() && inForce.getAsInt() < required) { + LOG.debug( + "AERE PQ ANCHOR (R2): block {} sits in the historical range {}, so the threshold " + + "applied is the {} that was in force then, not the {} the schedule asks for.", + number, +- PqAnchorLapse.windowCovering(number).orElse(null), ++ PqAnchorLapse.windowCovering(config.chainId(), number).orElse(null), + inForce.getAsInt(), + required); + required = inForce.getAsInt(); + } + + if (k < required) { + LOG.warn( + "AERE PQ ANCHOR (R2): block {} REJECTED - the carried certificate has {} seal(s), " + + "below the threshold K={} in force at this height.", + number, + k, + required); + return false; + } + + // Height aware since 2026-08-11, same measured historical window as rule R1. See + // PqAnchor.hasAcceptableIndices for why the exception sits at VALIDATION and nowhere else, and + // for what it deliberately does NOT relax. +- if (!PqAnchor.hasAcceptableIndices(certificate, number)) { ++ if (!PqAnchor.hasAcceptableIndices(config.chainId(), certificate, number)) { + LOG.warn( + "AERE PQ ANCHOR (R2): block {} REJECTED - the certificate's validator indices are not " + + "strictly increasing.", + number); + return false; + } + + if (k == 0) { + // Legitimate only while K is 0, which is the warm-up stage that starts at H itself, where + // the parent predates the scheme and no certificate can exist. R1 has already checked that + // the vanity digest is the digest OF THE EMPTY certificate, so an empty certificate is not + // an unchecked one. + LOG.debug( + "AERE PQ ANCHOR (R2): block {} carries an empty certificate and K={} at this height.", + number, + required); + return true; + } + + final BftContext bftContext = protocolContext.getConsensusContext(BftContext.class); +@@ -406,79 +407,98 @@ public class PqAnchorSealsRule implements AttachedBlockHeaderValidationRule { + return false; + } + final BftContext bftContext = protocolContext.getConsensusContext(BftContext.class); + final Collection

    parentValidators = + bftContext.getValidatorProvider().getValidatorsForBlock(parent); + if (parentValidators == null || parentValidators.isEmpty()) { + LOG.warn( + "AERE PQ ANCHOR (R2): block {} REJECTED - the validator set of the parent block {} could" + + " not be resolved, so seal eligibility cannot be decided.", + number, + parent.getNumber()); + return false; + } + final Set
    eligible = new HashSet<>(parentValidators); + final Bytes32 message = + PqAnchor.commitMessage(config.chainId(), parent.getNumber(), parent.getHash().getBytes()); + if (!falcon.isEmpty() && !falconSealsVerify(number, parent, eligible, message, falcon)) { + return false; + } + final HybridSealSupport hybrid = HybridSealSupport.instance(); ++ // Two sets, and they differ only with per-scheme intervals (AIP-22 stage 2). NAMED: every scheme ++ // the step at the parent height names; a seal of any other scheme is refused as today. REQUIRED: ++ // the named schemes whose grid THIS anchor height sits on, counted from the chain's anchor ++ // activation height; each must reach K. A seal of a named-but-not-required scheme is a surplus: ++ // verified and counted like any surplus seal, never ignored, never a reason to refuse. ++ final Set namedSchemes = new HashSet<>(); + final Set requiredSchemes = new HashSet<>(); +- hybrid.schedule().ifPresent(sch -> requiredSchemes.addAll(sch.schemesAt(parent.getNumber()))); ++ hybrid ++ .schedule() ++ .ifPresent( ++ sch -> { ++ namedSchemes.addAll(sch.schemesAt(parent.getNumber())); ++ requiredSchemes.addAll(sch.schemesRequiredForAnchor(number, config.anchorBlock())); ++ }); ++ namedSchemes.remove(SealSchemes.FALCON_512.id()); + requiredSchemes.remove(SealSchemes.FALCON_512.id()); + final Map counted = new HashMap<>(); + for (final SchemeSeal s : seals) { + if (s.getSchemeWireId() == SealSchemes.FALCON_512.wireId()) { + continue; + } + final Optional scheme = SealSchemes.byWireId(s.getSchemeWireId()); +- if (scheme.isEmpty() || !requiredSchemes.contains(scheme.get().id())) { ++ if (scheme.isEmpty() || !namedSchemes.contains(scheme.get().id())) { + LOG.warn( + "AERE PQ ANCHOR (R2): block {} REJECTED - the v2 certificate carries a seal of scheme 0x{}," + + " which the scheme schedule does not name at the parent height {} (named: {}).", + number, + Integer.toHexString(s.getSchemeWireId() & 0xff), + parent.getNumber(), +- requiredSchemes); ++ namedSchemes); + return false; + } + if (!falconIndices.contains(s.getValidatorIndex())) { + LOG.warn( + "AERE PQ ANCHOR (R2): block {} REJECTED - a {} seal from index {} is not bound to a Falcon" + + " seal of the same index in this certificate.", + number, + scheme.get().id(), + s.getValidatorIndex()); + return false; + } + final Optional registry = hybrid.registry(); +- if (registry.isEmpty()) { ++ // AERE AIP-22 stage 3b: from H_k the key comes from the v3 epoch in force at the PARENT (the height the ++ // Falcon key of the same certificate is taken at); the hybrid registry is then not the key set any more ++ final boolean v3Keys = AerePqIdentity.keysFromV3(parent.getNumber()); ++ if (registry.isEmpty() && !v3Keys) { + LOG.warn( + "AERE PQ ANCHOR (R2): block {} REJECTED - the certificate carries {} seals and this node" + + " has NO hybrid registry loaded, so it cannot verify them. A node that cannot" + + " verify has not proved the header good.", + number, + scheme.get().id()); + return false; + } +- final Optional pk = registry.get().publicKey(s.getValidatorIndex(), scheme.get().id()); ++ final Optional pk = ++ v3Keys ++ ? AerePqIdentity.v3KeyAt(parent.getNumber(), s.getValidatorIndex(), scheme.get().id()) ++ : registry.get().publicKey(s.getValidatorIndex(), scheme.get().id()); + if (pk.isEmpty()) { + LOG.warn( + "AERE PQ ANCHOR (R2): block {} REJECTED - the hybrid registry holds no {} key for index {}.", + number, + scheme.get().id(), + s.getValidatorIndex()); + return false; + } + if (!scheme.get().verifyRaw(pk.get(), message.toArray(), s.getSignature().toArray())) { + LOG.warn( + "AERE PQ ANCHOR (R2): block {} REJECTED - the {} signature from index {} does not verify" + + " over M(parent {}).", + number, + scheme.get().id(), + s.getValidatorIndex(), + parent.getNumber()); + return false; + } + counted.merge(scheme.get().id(), 1, Integer::sum); + } +@@ -499,49 +519,49 @@ public class PqAnchorSealsRule implements AttachedBlockHeaderValidationRule { + "AERE PQ ANCHOR (R2): block {} accepted with a {}-seal scheme-tagged certificate over parent" + + " {} (K={} per scheme, schemes={}).", + number, + seals.size(), + parent.getNumber(), + required, + requiredSchemes); + return true; + } + + private boolean acceptAsWrittenInsideLapse(final BlockHeader header, final long number) { + try { + final BftExtraData extraData = extraDataCodec.decodeRaw(header.getExtraData()); + final List certificate = List.copyOf(extraData.getFalconSeals()); + if (!PqAnchor.hasDistinctNonNegativeIndices(certificate)) { + LOG.warn( + "AERE PQ ANCHOR (R2): block {} REJECTED - it falls inside the historical range {} in " + + "which the anchor rules were not in force, but its certificate repeats a " + + "validator index or carries a negative one, which no header of that range does.", + number, +- PqAnchorLapse.windowCovering(number).orElse(null)); ++ PqAnchorLapse.windowCovering(config.chainId(), number).orElse(null)); + return false; + } + LOG.debug( + "AERE PQ ANCHOR (R2): block {} accepted as written with {} seal(s); it falls inside the " + + "historical range {} in which neither the threshold nor the ordering was in force.", + number, + certificate.size(), +- PqAnchorLapse.windowCovering(number).orElse(null)); ++ PqAnchorLapse.windowCovering(config.chainId(), number).orElse(null)); + return true; + } catch (final Exception e) { + LOG.warn( + "AERE PQ ANCHOR (R2): block {} REJECTED - it falls inside a historical unenforced range " + + "but its extraData could not be decoded: {}", + number, + e.toString()); + return false; + } + } + + /** + * AERE D-078: hand the parent's validator set to {@link FalconSealSupport} so its registry- + * coverage report is about the height the chain is actually at. Swallows everything: a rule that + * rejected a header because a diagnostic threw would be a worse defect than the one this repairs. + * + * @param parent the parent header + * @param protocolContext the protocol context + */ + private void observeValidatorsForDiagnostics( +diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqCheckpointRule.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqCheckpointRule.java +new file mode 100644 +index 0000000000..d6b46c5396 +--- /dev/null ++++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqCheckpointRule.java +@@ -0,0 +1,133 @@ ++/* ++ * Copyright contributors to Besu / AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.consensus.qbft.headervalidationrules; ++ ++import org.hyperledger.besu.datatypes.Hash; ++import org.hyperledger.besu.ethereum.ProtocolContext; ++import org.hyperledger.besu.ethereum.core.BlockHeader; ++import org.hyperledger.besu.ethereum.mainnet.AttachedBlockHeaderValidationRule; ++ ++import java.util.Collections; ++import java.util.NavigableMap; ++import java.util.TreeMap; ++ ++import com.google.common.base.Splitter; ++import org.slf4j.Logger; ++import org.slf4j.LoggerFactory; ++ ++/** ++ * AERE AIP-22 stage 4 (plan 9.6.7 point iv): the CHECKPOINT, which is how the weak subjectivity of a ++ * finality gadget is handled, stated publicly rather than hidden. A node that synchronises from ++ * genesis without other knowledge can be handed, by an eclipsing neighbour, a fork that ends before ++ * the first certified anchor; it can never reach the honest chain's height with valid certificates, ++ * but the eclipsed node does not know that height. Given a recent anchor from outside (height and ++ * block hash, from the published registry epoch or from its operator), it refuses any header at that ++ * height with another hash, so every chain it accepts runs through the checkpoint, and a rewrite at ++ * any height below it would have to reproduce every certificate above. ++ * ++ *

    {@code aere.pq.checkpoint=:[,:...]}. Unset or blank: ++ * inert (every header passes), which is every chain as it stands. A value it cannot parse refuses at ++ * load (AERE-PQC-CHECKPOINT-01), never silently degrades to "no checkpoint". ATTACHED, so it runs at ++ * import under SKIP_DETACHED, the mode full sync imports with (the same reason R1A exists). ++ */ ++public class PqCheckpointRule implements AttachedBlockHeaderValidationRule { ++ ++ /** The system property that names the checkpoints. */ ++ public static final String PROPERTY = "aere.pq.checkpoint"; ++ ++ private static final Logger LOG = LoggerFactory.getLogger(PqCheckpointRule.class); ++ ++ private final NavigableMap checkpoints; ++ ++ /** ++ * A rule over the given checkpoints (height to block hash). ++ * ++ * @param checkpoints the checkpoints; empty means inert ++ */ ++ public PqCheckpointRule(final NavigableMap checkpoints) { ++ this.checkpoints = Collections.unmodifiableNavigableMap(new TreeMap<>(checkpoints)); ++ } ++ ++ /** ++ * The rule configured on this node by {@link #PROPERTY}. ++ * ++ * @return the rule ++ */ ++ public static PqCheckpointRule fromSystemConfiguration() { ++ return new PqCheckpointRule(parse(System.getProperty(PROPERTY))); ++ } ++ ++ /** ++ * The checkpoints named by this node's configuration. ++ * ++ * @return height to block hash, empty when unset ++ */ ++ public NavigableMap checkpoints() { ++ return checkpoints; ++ } ++ ++ /** ++ * Parses {@code :[,...]}; fail-closed on anything malformed. ++ * ++ * @param value the property value, possibly null ++ * @return height to block hash ++ */ ++ static NavigableMap parse(final String value) { ++ final TreeMap m = new TreeMap<>(); ++ if (value == null || value.isBlank()) { ++ return m; ++ } ++ for (final String part : Splitter.on(',').trimResults().omitEmptyStrings().split(value)) { ++ final int c = part.indexOf(':'); ++ if (c <= 0) { ++ throw new IllegalArgumentException( ++ "AERE-PQC-CHECKPOINT-01: " + PROPERTY + " entry '" + part + "' is not :"); ++ } ++ final long height; ++ final Hash hash; ++ try { ++ height = Long.parseLong(part.substring(0, c).trim()); ++ hash = Hash.fromHexString(part.substring(c + 1).trim()); ++ } catch (final RuntimeException e) { ++ throw new IllegalArgumentException( ++ "AERE-PQC-CHECKPOINT-01: " + PROPERTY + " entry '" + part + "' is not :<32-byte block hash>", e); ++ } ++ if (height < 1) { ++ throw new IllegalArgumentException( ++ "AERE-PQC-CHECKPOINT-01: " + PROPERTY + " height " + height + " must be at least 1"); ++ } ++ if (m.put(height, hash) != null) { ++ throw new IllegalArgumentException( ++ "AERE-PQC-CHECKPOINT-01: " + PROPERTY + " names height " + height + " twice"); ++ } ++ } ++ return m; ++ } ++ ++ @Override ++ public boolean validate( ++ final BlockHeader header, final BlockHeader parent, final ProtocolContext protocolContext) { ++ final Hash want = checkpoints.get(header.getNumber()); ++ if (want == null || want.equals(header.getHash())) { ++ return true; ++ } ++ LOG.warn( ++ "AERE-PQC-CHECKPOINT-02: block {} has hash {} but this node's checkpoint at that height is {}; REFUSED (a chain that does not run through the checkpoint is never adopted)", ++ header.getNumber(), ++ header.getHash(), ++ want); ++ return false; ++ } ++} +diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqHeaderSealRule.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqHeaderSealRule.java +new file mode 100644 +index 0000000000..e292937e50 +--- /dev/null ++++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqHeaderSealRule.java +@@ -0,0 +1,259 @@ ++/* ++ * Copyright contributors to Besu / AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.consensus.qbft.headervalidationrules; ++ ++import org.hyperledger.besu.consensus.common.bft.AerePqFinality; ++import org.hyperledger.besu.consensus.common.bft.AerePqHeaderSeal; ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; ++import org.hyperledger.besu.consensus.common.bft.BftBlockHashing; ++import org.hyperledger.besu.consensus.common.bft.BftExtraData; ++import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; ++import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; ++import org.hyperledger.besu.consensus.common.bft.FalconSeal; ++import org.hyperledger.besu.consensus.common.bft.PqAnchor; ++import org.hyperledger.besu.consensus.common.bft.PqSignerRegistry; ++import org.hyperledger.besu.consensus.common.bft.blockcreation.BftProposerSelector; ++import org.hyperledger.besu.consensus.common.bft.headervalidationrules.BftCommitSealsValidationRule; ++import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.ethereum.ProtocolContext; ++import org.hyperledger.besu.ethereum.core.BlockHeader; ++import org.hyperledger.besu.ethereum.mainnet.AttachedBlockHeaderValidationRule; ++ ++import java.util.Collection; ++import java.util.Optional; ++ ++import org.apache.tuweni.bytes.Bytes32; ++import org.slf4j.Logger; ++import org.slf4j.LoggerFactory; ++ ++/** ++ * AIP-22 stage 5: the seal rule of a header. Below H_hdr it IS the upstream rule (a quorum of ECDSA ++ * committed seals of the parent's validators), unchanged. From H_hdr a header is admitted iff its ECDSA ++ * committed-seal element is EMPTY, its seventh element carries the proposer's Falcon-512 seal, the seal's ++ * index names the header's {@code coinbase} (an id) in the v3 epoch in force at its height, and the seal ++ * verifies over the PROPOSAL message recomputed from the stored header (chain id, height, the round in ++ * element 3, the proposal digest, i.e. the committed-seal hash of the header). Finality stays with the ++ * anchors (AIP-22 section 4); this rule is what admits a header between them. ++ * ++ *

    AERE D-406 (2026-09-25, measured on testnet 28001): a block PREPARED in one round and not ++ * committed before its timer is RE-PROPOSED unchanged in a later round r by the proposer of round r ++ * (QBFT's locked value; only element 3 changes, the coinbase stays the builder's), and every node seals ++ * the header with the accepted proposal's seal, which is the round-r proposer's. Requiring the coinbase ++ * refused every such header on every node: block 3,314,873 stood 128 s (rounds 1 to 4 refused with ++ * "a seal cannot vouch for another proposer", round 5 was the builder's own turn again, N = 5); at ++ * N = 10 the same wait is ten rounds, and with the builder down after the prepare it does not end. So ++ * the seal's id must be the coinbase OR, at a round above zero, the proposer of the round in element 3 ++ * as upstream's proposer selection computes it from the parent's proposer (its coinbase) and the ++ * header's own validator list (the set after the parent, which BftValidatorsValidationRule enforces). ++ * Every header the old rule admitted is admitted unchanged; the new branch only runs where it refused. ++ */ ++public class PqHeaderSealRule implements AttachedBlockHeaderValidationRule { ++ ++ private static final Logger LOG = LoggerFactory.getLogger(PqHeaderSealRule.class); ++ ++ private final AttachedBlockHeaderValidationRule belowHdr; ++ private final BftExtraDataCodec codec; ++ private final long chainId; ++ private final AerePqFinality.SealVerifier verifier; ++ ++ /** ++ * The rule. ++ * ++ * @param belowHdr the rule below H_hdr (upstream's committed seals rule in production) ++ * @param codec the extraData codec ++ * @param chainId the chain id every seal message carries ++ * @param verifier the seal verifier (the anchor rules' historic door in production) ++ */ ++ public PqHeaderSealRule( ++ final AttachedBlockHeaderValidationRule belowHdr, ++ final BftExtraDataCodec codec, ++ final long chainId, ++ final AerePqFinality.SealVerifier verifier) { ++ this.belowHdr = belowHdr; ++ this.codec = codec; ++ this.chainId = chainId; ++ this.verifier = verifier; ++ } ++ ++ /** ++ * The fleet's rule: upstream's committed seals rule below H_hdr, the verifier of the header rules above. ++ * ++ * @param chainId the chain id ++ * @return the rule ++ */ ++ public static PqHeaderSealRule forFleet(final long chainId) { ++ final PqSignerRegistry registry = PqSignerRegistry.falconSealSupport(); ++ return new PqHeaderSealRule( ++ new BftCommitSealsValidationRule(), new QbftExtraDataCodec(), chainId, registry::verifyAtHistoric); ++ } ++ ++ @Override ++ public boolean validate( ++ final BlockHeader header, final BlockHeader parent, final ProtocolContext protocolContext) { ++ if (!AerePqHeaderSeal.active(header.getNumber())) { ++ return belowHdr.validate(header, parent, protocolContext); ++ } ++ final Optional r = refusal(header, parent); ++ r.ifPresent(LOG::info); ++ return r.isEmpty(); ++ } ++ ++ /** ++ * Why a header at or above H_hdr is refused, if it is, judged WITHOUT its parent: only a seal of the ++ * coinbase's index can be admitted (a re-proposed header needs the parent, {@link #refusal(BlockHeader, ++ * BlockHeader)}). ++ * ++ * @param header the header ++ * @return the refusal, or empty ++ */ ++ public Optional refusal(final BlockHeader header) { ++ return refusal(header, null); ++ } ++ ++ /** ++ * AERE D-406: the proposer of the round in element 3, as upstream's selection computes it (changeEachBlock, ++ * as QBFT), from the parent's proposer and the header's validator list. Empty at round 0, without the ++ * parent, or when the list cannot seed a selection. ++ * ++ * @param h the height ++ * @param round the round in element 3 ++ * @param parent the parent header, or null ++ * @param validators the header's validator list ++ * @return the proposer of that round, or empty ++ */ ++ static Optional

    proposerOfRound( ++ final long h, final int round, final BlockHeader parent, final Collection
    validators) { ++ if (round <= 0 || round > MAX_ROUND || parent == null || validators == null || validators.isEmpty()) { ++ return Optional.empty(); ++ } ++ try { ++ return Optional.of( ++ BftProposerSelector.selectProposerForRound( ++ new ConsensusRoundIdentifier(h, round), ++ parent.getCoinbase(), ++ validators, ++ true)); ++ } catch (final RuntimeException e) { ++ return Optional.empty(); ++ } ++ } ++ ++ /** ++ * AERE D-406: the highest round element 3 may carry from H_hdr. No honest round gets near it (the QBFT round timer doubles each ++ * round), and it keeps the rotation arithmetic, which upstream does in int, in range. The second client applies the same bound. ++ */ ++ static final int MAX_ROUND = 1024; ++ ++ /** ++ * AERE D-406: whether {@code coinbase} is the proposer of some round 0..round at this height, i.e. could have BUILT the block ++ * (a block is built by the proposer of the round it is first proposed in, and a re-proposal keeps its coinbase). The rotation is ++ * periodic in n, so rounds 0..min(round, n - 1) cover the set. The second client has required exactly this since D-331. ++ */ ++ static boolean builtByAProposerUpTo( ++ final long h, final int round, final BlockHeader parent, final Collection
    validators, final Address coinbase) { ++ final int last = Math.min(round, validators.size() - 1); ++ for (int r = 0; r <= last; r++) { ++ try { ++ if (BftProposerSelector.selectProposerForRound(new ConsensusRoundIdentifier(h, r), parent.getCoinbase(), validators, true) ++ .equals(coinbase)) { ++ return true; ++ } ++ } catch (final RuntimeException e) { ++ return false; ++ } ++ } ++ return false; ++ } ++ ++ /** ++ * Why a header at or above H_hdr is refused, if it is. ++ * ++ * @param header the header ++ * @param parent its parent, or null (then only the coinbase's seal can be admitted) ++ * @return the refusal, or empty ++ */ ++ public Optional refusal(final BlockHeader header, final BlockHeader parent) { ++ final long h = header.getNumber(); ++ final BftExtraData ed; ++ try { ++ ed = codec.decode(header); ++ } catch (final RuntimeException e) { ++ return Optional.of("AERE PQ HEADER: block " + h + " extraData does not decode: " + e.getMessage()); ++ } ++ if (!ed.getSeals().isEmpty()) { ++ return Optional.of( ++ "AERE PQ HEADER: block " + h + " carries " + ed.getSeals().size() ++ + " ECDSA committed seal(s); from H_hdr " + AerePqHeaderSeal.headerBlock() + " the element MUST be empty"); ++ } ++ if (ed.getPqProposerSeal().isEmpty()) { ++ return Optional.of("AERE PQ HEADER: block " + h + " carries no proposer seal (element 6) from H_hdr"); ++ } ++ // AERE D-406: the round bound, and with the parent, the builder: the coinbase is the proposer of some round up to element 3 ++ if (ed.getRound() < 0 || ed.getRound() > MAX_ROUND) { ++ return Optional.of("AERE PQ HEADER: block " + h + " round " + ed.getRound() + " in element 3 is outside 0.." + MAX_ROUND); ++ } ++ if (parent != null ++ && !ed.getValidators().isEmpty() ++ && !builtByAProposerUpTo(h, ed.getRound(), parent, ed.getValidators(), header.getCoinbase())) { ++ return Optional.of( ++ "AERE PQ HEADER: block " + h + " coinbase " + header.getCoinbase() + " is not the proposer of any round 0.." ++ + ed.getRound() + " at this height, so it did not build the block"); ++ } ++ final FalconSeal ps = ed.getPqProposerSeal().get(); ++ final Optional
    id = AerePqIdentity.v3IdAt(h, ps.getValidatorIndex()); ++ if (id.isEmpty()) { ++ return Optional.of( ++ "AERE PQ HEADER: block " + h + " proposer seal index " + ps.getValidatorIndex() + " names no row of the v3 epoch in force"); ++ } ++ if (!id.get().equals(header.getCoinbase())) { ++ // AERE D-406: a re-proposed block carries the seal of the proposer of the round it was committed in ++ final Optional
    roundProposer = proposerOfRound(h, ed.getRound(), parent, ed.getValidators()); ++ if (roundProposer.isEmpty() || !roundProposer.get().equals(id.get())) { ++ return Optional.of( ++ "AERE PQ HEADER: block " + h + " proposer seal of index " + ps.getValidatorIndex() + " (id " + id.get() ++ + ") but coinbase " + header.getCoinbase() ++ + (ed.getRound() > 0 ++ ? roundProposer ++ .map(p -> " and the proposer of round " + ed.getRound() + " is " + p) ++ .orElse(" and the proposer of round " + ed.getRound() + " is not known without the parent") ++ : "") ++ + " - a seal cannot vouch for another proposer"); ++ } ++ } ++ final Bytes32 message; ++ try { ++ message = ++ PqAnchor.proposalMessage( ++ chainId, h, ed.getRound(), new BftBlockHashing(codec).calculateDataHashForCommittedSeal(header).getBytes()); ++ } catch (final RuntimeException e) { ++ return Optional.of("AERE PQ HEADER: block " + h + " proposal message cannot be built: " + e.getMessage()); ++ } ++ final boolean ok; ++ try { ++ ok = verifier.verify(h, ps.getValidatorIndex(), message, ps.getSignature()); ++ } catch (final RuntimeException e) { ++ return Optional.of("AERE PQ HEADER: block " + h + " proposer seal verification threw: " + e.getMessage()); ++ } ++ return ok ++ ? Optional.empty() ++ : Optional.of("AERE PQ HEADER: block " + h + " proposer seal of index " + ps.getValidatorIndex() + " does not verify"); ++ } ++ ++ @Override ++ public boolean includeInLightValidation() { ++ return belowHdr.includeInLightValidation(); ++ } ++} +diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/AereIdentityHeaderTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/AereIdentityHeaderTest.java +new file mode 100644 +index 0000000000..e51e617a97 +--- /dev/null ++++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/AereIdentityHeaderTest.java +@@ -0,0 +1,144 @@ ++/* ++ * AERE AIP-22 stage 3: the identity switch on the IMPORT path - the committed seals of a real header. ++ * ++ * Four node keys seal a QBFT header (BftExtraDataFixture signs each committed seal over the ++ * committed-seal hash of that very header, as a live committer does). The committers recovered from ++ * it, through BOTH places upstream recovers them (BftBlockInterface.getCommitters for the header ++ * rules, BftBlockHashing.recoverCommitterAddresses for the rest), must be the v3 ids from H_id, and ++ * the classical addresses one block below H_id or with the switch disarmed. That is exactly what lets ++ * BftCommitSealsValidationRule accept a header sealed by ids against a validator set of ids. ++ */ ++package org.hyperledger.besu.consensus.qbft; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++ ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; ++import org.hyperledger.besu.consensus.common.bft.BftBlockHashing; ++import org.hyperledger.besu.consensus.common.bft.BftBlockHeaderFunctions; ++import org.hyperledger.besu.consensus.common.bft.BftBlockInterface; ++import org.hyperledger.besu.consensus.common.bft.BftExtraData; ++import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; ++import org.hyperledger.besu.consensus.common.bft.BftExtraDataFixture; ++import org.hyperledger.besu.consensus.common.bft.PqRegistryV3; ++import org.hyperledger.besu.consensus.common.bft.SealScheme; ++import org.hyperledger.besu.consensus.common.bft.SealSchemes; ++import org.hyperledger.besu.crypto.SECPSignature; ++import org.hyperledger.besu.crypto.SecureRandomProvider; ++import org.hyperledger.besu.cryptoservices.NodeKey; ++import org.hyperledger.besu.cryptoservices.NodeKeyUtils; ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.ethereum.core.BlockHeader; ++import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; ++import org.hyperledger.besu.ethereum.core.Util; ++ ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Map; ++import java.util.Optional; ++import java.util.TreeMap; ++import java.util.TreeSet; ++ ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.bytes.Bytes32; ++import org.junit.jupiter.api.AfterEach; ++import org.junit.jupiter.api.BeforeEach; ++import org.junit.jupiter.api.Test; ++ ++public class AereIdentityHeaderTest { ++ ++ private static final long CHAIN = 28001; ++ private static final long H_ID = 20; ++ private final QbftExtraDataCodec codec = new QbftExtraDataCodec(); ++ private final List keys = new ArrayList<>(); ++ private final List
    addr = new ArrayList<>(); ++ private final List
    ids = new ArrayList<>(); ++ ++ @BeforeEach ++ public void registry() { ++ final long bind = 10; ++ final List rows = new ArrayList<>(); ++ for (int i = 0; i < 4; i++) { ++ final NodeKey k = NodeKeyUtils.generate(); ++ keys.add(k); ++ addr.add(Util.publicKeyToAddress(k.getPublicKey())); ++ final SealScheme f = SealSchemes.FALCON_512; ++ final SealScheme.GeneratedPair p = f.generate(SecureRandomProvider.createSecureRandom()); ++ final byte[] std = new byte[897]; ++ std[0] = 0x09; ++ System.arraycopy(p.publicRegistryForm(), 0, std, 1, 896); ++ final byte[] id = PqRegistryV3.idOf(std); ++ final byte[] pop = ++ f.sign( ++ p.privateKey(), ++ PqRegistryV3.popMessage(CHAIN, bind, 4, i, id, f.wireId(), std).toArrayUnsafe()) ++ .orElseThrow(); ++ final TreeMap km = new TreeMap<>(); ++ km.put(f.wireId() & 0xff, new PqRegistryV3.Key(f, std, pop)); ++ final Bytes32 rh = ++ PqRegistryV3.rowHash( ++ CHAIN, bind, 4, new PqRegistryV3.Row(i, id, km, null, Map.of(), null, null)); ++ final SECPSignature claim = k.sign(PqRegistryV3.claimDigest(CHAIN, rh)); ++ rows.add( ++ new PqRegistryV3.Row( ++ i, id, km, null, Map.of(), addr.get(i).getBytes().toArrayUnsafe(), ++ claim.encodedBytes().toArrayUnsafe())); ++ ids.add(Address.wrap(Bytes.wrap(id))); ++ } ++ final List hashes = new ArrayList<>(); ++ for (final PqRegistryV3.Row r : rows) { ++ hashes.add(PqRegistryV3.rowHash(CHAIN, bind, 4, r)); ++ } ++ final Bytes32 root = PqRegistryV3.merkleRoot(hashes); ++ final TreeMap epochs = new TreeMap<>(); ++ epochs.put( ++ bind, ++ new PqRegistryV3.Registry( ++ CHAIN, bind, 4, rows, hashes, root, PqRegistryV3.registryHash(CHAIN, bind, 4, root))); ++ AerePqIdentity.install(new AerePqIdentity.Config(H_ID, epochs)); ++ } ++ ++ @AfterEach ++ public void disarm() { ++ AerePqIdentity.uninstall(); ++ } ++ ++ /** A header at this height, listing these validators, sealed by all four keys. */ ++ private BlockHeader sealedHeader(final long number, final List
    validators) { ++ final BlockHeaderTestFixture b = new BlockHeaderTestFixture(); ++ b.number(number); ++ b.gasLimit(5000); ++ b.timestamp(6 * number); ++ b.coinbase(validators.get(0)); ++ b.blockHeaderFunctions(BftBlockHeaderFunctions.forCommittedSeal(codec)); ++ final BftExtraData ed = ++ BftExtraDataFixture.createExtraData( ++ b.buildHeader(), ++ Bytes.wrap(new byte[BftExtraDataCodec.EXTRA_VANITY_LENGTH]), ++ Optional.empty(), ++ new ArrayList<>(new TreeSet<>(validators)), ++ keys, ++ 0, ++ codec); ++ b.extraData(codec.encode(ed)); ++ return b.buildHeader(); ++ } ++ ++ @Test ++ public void fromHidTheCommittersOfARealHeaderAreTheIds() { ++ final BlockHeader h = sealedHeader(H_ID, ids); ++ assertThat(new BftBlockInterface(codec).getCommitters(h)).containsExactlyElementsOf(ids); ++ assertThat(new BftBlockHashing(codec).recoverCommitterAddresses(h, codec.decode(h))) ++ .containsExactlyElementsOf(ids); ++ } ++ ++ @Test ++ public void belowHidAndDisarmedTheyAreTheAddresses() { ++ final BlockHeader below = sealedHeader(H_ID - 1, addr); ++ assertThat(new BftBlockInterface(codec).getCommitters(below)).containsExactlyElementsOf(addr); ++ final BlockHeader at = sealedHeader(H_ID, ids); ++ AerePqIdentity.uninstall(); ++ assertThat(new BftBlockInterface(codec).getCommitters(at)).containsExactlyElementsOf(addr); ++ assertThat(new BftBlockHashing(codec).recoverCommitterAddresses(at, codec.decode(at))) ++ .containsExactlyElementsOf(addr); ++ } ++} +diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqAnchorDisarmedWindowTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqAnchorDisarmedWindowTest.java +old mode 100755 +new mode 100644 +index 9451ec7b7f..e7604a4fca +--- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqAnchorDisarmedWindowTest.java ++++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqAnchorDisarmedWindowTest.java +@@ -122,46 +122,46 @@ public class PqAnchorDisarmedWindowTest { + + private final LocalRegistry registry = new LocalRegistry(); + private final PqAnchorDigestRule r1 = new PqAnchorDigestRule(live); + private final PqAnchorSealsRule r2 = new PqAnchorSealsRule(live, registry); + + // ----------------------------------------------------------------------------------------------- + // The heights under test really are anchor heights. Without this the file measures nothing. + // ----------------------------------------------------------------------------------------------- + + @Test + public void everyHeightUnderTestIsAnAnchorHeightOfTheLiveConfiguration() { + for (final long height : + List.of(BEFORE, OFF_FIRST, OFF_MIDDLE, OFF_LAST, LOW_FIRST, LOW_MIDDLE, LOW_LAST, AFTER)) { + assertThat(live.anchorAppliesAt(height)) + .describedAs("height %d must be one the rules judge, or this file proves nothing", height) + .isTrue(); + assertThat(live.minSealsAt(height)) + .describedAs("the schedule asks for three seals at height %d", height) + .isEqualTo(3); + } +- assertThat(PqAnchorLapse.isDisarmed(OFF_FIRST)).isTrue(); +- assertThat(PqAnchorLapse.isDisarmed(OFF_LAST)).isTrue(); +- assertThat(PqAnchorLapse.isDisarmed(BEFORE)).isFalse(); +- assertThat(PqAnchorLapse.isDisarmed(LOW_FIRST)).isFalse(); +- assertThat(PqAnchorLapse.historicMinSeals(LOW_FIRST)).hasValue(1); +- assertThat(PqAnchorLapse.historicMinSeals(AFTER)).isEmpty(); ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, OFF_FIRST)).isTrue(); ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, OFF_LAST)).isTrue(); ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, BEFORE)).isFalse(); ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, LOW_FIRST)).isFalse(); ++ assertThat(PqAnchorLapse.historicMinSeals(PqAnchorLapse.CHAIN_ID, LOW_FIRST)).hasValue(1); ++ assertThat(PqAnchorLapse.historicMinSeals(PqAnchorLapse.CHAIN_ID, AFTER)).isEmpty(); + } + + // ----------------------------------------------------------------------------------------------- + // RANGE 1, nothing in force: a header of the shape the chain holds is accepted by both rules. + // ----------------------------------------------------------------------------------------------- + + @Test + public void r1AcceptsAHeaderOfTheFirstRangeAsWritten() { + for (final long height : List.of(OFF_FIRST, OFF_MIDDLE, OFF_LAST)) { + final BlockHeader parent = parentHeader(height - 1L); + final BlockHeader block = unenforcedHeader(height, parent, ARRIVAL_ORDER); + assertThat(r1.validate(block, parent)) + .describedAs( + "height %d carries the client version string in vanityData and a certificate in " + + "arrival order; that is what the chain holds, and a node syncing from genesis " + + "must be able to pass it", + height) + .isTrue(); + } + } +@@ -366,43 +366,43 @@ public class PqAnchorDisarmedWindowTest { + assertThat(r1.validate(unenforcedHeader(LOW_FIRST, lowParent, ARRIVAL_ORDER), lowParent)) + .isFalse(); + + // And the far end of the lowered range, to one anchor step, on the threshold. + final BlockHeader lowLastParent = parentHeader(LOW_LAST - 1L); + final ProtocolContext context = contextWith(VALIDATORS); + assertThat(r2.validate(honestBlock(LOW_LAST, lowLastParent, List.of(0)), lowLastParent, context)) + .isTrue(); + final BlockHeader afterParent = parentHeader(AFTER - 1L); + assertThat(r2.validate(honestBlock(AFTER, afterParent, List.of(0)), afterParent, context)) + .isFalse(); + } + + @Test + public void theBoundsAreExactToOneBlockOnBothRules() { + // The heights either side of the bounds are not anchor heights, so both rules stand down there + // for the ordinary reason. Asserted so that "accepted" at OFF_FIRST - 1 is not mistaken for the + // exception having leaked one block down. + assertThat(live.anchorAppliesAt(OFF_FIRST - 1L)).isFalse(); + assertThat(live.anchorAppliesAt(OFF_LAST + 1L)).isFalse(); +- assertThat(PqAnchorLapse.isDisarmed(OFF_FIRST - 1L)).isFalse(); +- assertThat(PqAnchorLapse.isDisarmed(OFF_LAST + 1L)).isFalse(); +- assertThat(PqAnchorLapse.historicMinSeals(LOW_LAST + 1L)).isEmpty(); ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, OFF_FIRST - 1L)).isFalse(); ++ assertThat(PqAnchorLapse.isDisarmed(PqAnchorLapse.CHAIN_ID, OFF_LAST + 1L)).isFalse(); ++ assertThat(PqAnchorLapse.historicMinSeals(PqAnchorLapse.CHAIN_ID, LOW_LAST + 1L)).isEmpty(); + } + + // ----------------------------------------------------------------------------------------------- + // What the exception deliberately does NOT relax, at any height. + // ----------------------------------------------------------------------------------------------- + + @Test + public void insideTheFirstRangeARepeatedIndexIsStillRefusedByBothRules() { + // Sortedness fixes one accepted order for a given set; distinctness is what makes "repeat one + // seal to inflate the count" unrepresentable. Measured on every header of the range: distinct + // in all of them. So this refusal costs nothing and keeps the attack unrepresentable. + final BlockHeader parent = parentHeader(OFF_FIRST - 1L); + final BlockHeader repeated = unenforcedHeader(OFF_FIRST, parent, List.of(2, 6, 2)); + assertThat(r1.validate(repeated, parent)).isFalse(); + assertThat(r2.validate(repeated, parent, contextWith(VALIDATORS))).isFalse(); + + // Positive control: the same rule at the same height accepts the distinct version. + final BlockHeader distinct = unenforcedHeader(OFF_FIRST, parent, ARRIVAL_ORDER); + assertThat(r1.validate(distinct, parent)).isTrue(); + assertThat(r2.validate(distinct, parent, contextWith(VALIDATORS))).isTrue(); +@@ -411,72 +411,146 @@ public class PqAnchorDisarmedWindowTest { + @Test + public void insideTheFirstRangeAnUndecodableHeaderIsStillRefused() { + final BlockHeader parent = parentHeader(OFF_FIRST - 1L); + final BlockHeader garbage = + header(OFF_FIRST, parent.getHash(), Bytes.fromHexString("0xdeadbeef")); + assertThat(r1.validate(garbage, parent)).isFalse(); + assertThat(r2.validate(garbage, parent, contextWith(VALIDATORS))).isFalse(); + } + + @Test + public void belowTheActivationHeightNothingIsJudgedAtAll() { + // The ranges sit far above H, so this only restates the height gate; it is here because a + // future edit that moved the range gates ABOVE the height gate would make the rules decode + // headers on the whole existing chain, which is the property that lets this binary be warmed. + final BlockHeader parent = parentHeader(H_LIVE - 2L); + final BlockHeader block = unenforcedHeader(H_LIVE - 1L, parent, ARRIVAL_ORDER); + assertThat(r1.validate(block, parent)).isTrue(); + assertThat(r2.validate(block, parent, contextWith(VALIDATORS))).isTrue(); + } + ++ // ----------------------------------------------------------------------------------------------- ++ // D-428 (2026-09-28): the ranges are facts about chain 2800. The same heights on ANY other chain are ++ // judged by the plain rules, as the second client does. Each case carries its positive control, so a ++ // refusal here cannot come from a signature made for the wrong chain. ++ // ----------------------------------------------------------------------------------------------- ++ ++ private static final long OTHER_CHAIN = 28001L; ++ ++ private final PqAnchorConfig otherChain = ++ new PqAnchorConfig( ++ OTHER_CHAIN, ++ H_LIVE, ++ Map.of(H_LIVE, 0, 13_034_000L, 3), ++ OptionalInt.empty(), ++ false, ++ OptionalInt.empty(), ++ OptionalInt.of(INTERVAL)); ++ ++ private final PqAnchorDigestRule r1Other = new PqAnchorDigestRule(otherChain); ++ private final PqAnchorSealsRule r2Other = new PqAnchorSealsRule(otherChain, registry); ++ ++ @Test ++ public void onAnotherChainTheFirstRangeIsJudgedByThePlainRules() { ++ for (final long height : List.of(OFF_FIRST, OFF_MIDDLE, OFF_LAST)) { ++ final BlockHeader parent = parentHeader(height - 1L); ++ final ProtocolContext context = contextWith(VALIDATORS); ++ final BlockHeader unenforced = unenforcedHeader(height, parent, ARRIVAL_ORDER); ++ assertThat(r1.validate(unenforced, parent)) ++ .describedAs("positive control: on chain 2800 height %d is inside the first range", height) ++ .isTrue(); ++ assertThat(r1Other.validate(unenforced, parent)) ++ .describedAs("on chain %d there was no lapse: no digest must be refused at %d", OTHER_CHAIN, height) ++ .isFalse(); ++ assertThat(r2Other.validate(unenforced, parent, context)) ++ .describedAs("on chain %d the arrival order and the missing digest are refused at %d", OTHER_CHAIN, height) ++ .isFalse(); ++ final BlockHeader honest = honestBlockOn(OTHER_CHAIN, height, parent, List.of(0, 1, 2)); ++ assertThat(r1Other.validate(honest, parent)) ++ .describedAs("positive control: an honest header OF chain %d is accepted at %d", OTHER_CHAIN, height) ++ .isTrue(); ++ assertThat(r2Other.validate(honest, parent, context)).isTrue(); ++ } ++ } ++ ++ @Test ++ public void onAnotherChainTheSecondRangeKeepsTheScheduledThreshold() { ++ for (final long height : List.of(LOW_FIRST, LOW_MIDDLE, LOW_LAST)) { ++ final BlockHeader parent = parentHeader(height - 1L); ++ final ProtocolContext context = contextWith(VALIDATORS); ++ assertThat(r2.validate(honestBlock(height, parent, List.of(5)), parent, context)) ++ .describedAs("positive control: on chain 2800 one seal passes at %d, the threshold in force then", height) ++ .isTrue(); ++ assertThat(r2Other.validate(honestBlockOn(OTHER_CHAIN, height, parent, List.of(5)), parent, context)) ++ .describedAs("on chain %d the threshold at %d is the scheduled three, not the 2800 lapse", OTHER_CHAIN, height) ++ .isFalse(); ++ assertThat(r2Other.validate(honestBlockOn(OTHER_CHAIN, height, parent, List.of(0, 1, 5)), parent, context)) ++ .describedAs("positive control: three seals OF chain %d pass at %d", OTHER_CHAIN, height) ++ .isTrue(); ++ } ++ } ++ + // ----------------------------------------------------------------------------------------------- + // Helpers. + // ----------------------------------------------------------------------------------------------- + + /** + * A header of the shape the first range holds: the client version string in vanityData instead of + * a digest, and the certificate written in the order the commits arrived. + */ + private BlockHeader unenforcedHeader( + final long number, final BlockHeader parent, final List indicesInArrivalOrder) { + return header( + number, parent.getHash(), extraData(CLIENT_VANITY, sealsFor(parent, indicesInArrivalOrder))); + } + + /** A header whose digest is correctly bound but whose indices are left in arrival order. */ + private BlockHeader digestBoundButUnsorted( + final long number, final BlockHeader parent, final List indicesInArrivalOrder) { + final List seals = sealsFor(parent, indicesInArrivalOrder); + final Bytes32 digest = + PqAnchor.anchorDigest(CHAIN_ID, parent.getNumber(), parent.getHash().getBytes(), seals); + return header(number, parent.getHash(), extraData(digest, seals)); + } + + /** A header an honest proposer under the armed rules writes: digest bound, indices sorted. */ + private BlockHeader honestBlock( + final long number, final BlockHeader parent, final List indices) { + final List sorted = PqAnchor.sortedByIndex(sealsFor(parent, indices)); + final Bytes32 digest = + PqAnchor.anchorDigest(CHAIN_ID, parent.getNumber(), parent.getHash().getBytes(), sorted); + return header(number, parent.getHash(), extraData(digest, sorted)); + } + ++ /** An honest header for ANY chain: the digest and the seals are computed for that chain (D-428). */ ++ private BlockHeader honestBlockOn( ++ final long chain, final long number, final BlockHeader parent, final List indices) { ++ final Bytes32 message = PqAnchor.commitMessage(chain, parent.getNumber(), parent.getHash().getBytes()); ++ final List seals = new ArrayList<>(); ++ for (final int index : indices) { ++ seals.add(new FalconSeal(index, LocalRegistry.sign(index, message))); ++ } ++ final List sorted = PqAnchor.sortedByIndex(seals); ++ final Bytes32 digest = PqAnchor.anchorDigest(chain, parent.getNumber(), parent.getHash().getBytes(), sorted); ++ return header(number, parent.getHash(), extraData(digest, sorted)); ++ } ++ + private List sealsFor(final BlockHeader parent, final List indices) { + // One return, one mutability. An early return of an immutable empty list here is what + // errorprone's MixedMutabilityReturnType refuses, and it is refusing something real: the empty + // case is not special, it is the case where the loop runs zero times. + final Bytes32 message = + PqAnchor.commitMessage(CHAIN_ID, parent.getNumber(), parent.getHash().getBytes()); + final List seals = new ArrayList<>(); + for (final int index : indices) { + seals.add(new FalconSeal(index, LocalRegistry.sign(index, message))); + } + return seals; + } + + private ProtocolContext contextWith(final Collection
    parentValidators) { + final ValidatorProvider validatorProvider = + mock(ValidatorProvider.class, withSettings().strictness(Strictness.LENIENT)); + when(validatorProvider.getValidatorsForBlock(any())).thenReturn(parentValidators); + final BftContext bftContext = + mock(BftContext.class, withSettings().strictness(Strictness.LENIENT)); + when(bftContext.getValidatorProvider()).thenReturn(validatorProvider); +diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqAnchorV2RulesTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqAnchorV2RulesTest.java +index 4c542fe876..867b46b6f6 100755 +--- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqAnchorV2RulesTest.java ++++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqAnchorV2RulesTest.java +@@ -180,40 +180,74 @@ public class PqAnchorV2RulesTest { + @Test + public void r1RefusesAV2CertificateBelowTheV2HeightAndAV1CertificateAtIt() { + // v2 below V2: the anchor height V2-1 (interval absent => every height from H is an anchor height) + final BlockHeader parentBelow = parentHeader(V2 - 2L); + final BlockHeader v2Early = honestV2(V2 - 1L, parentBelow, certificate(parentBelow, 5, 5)); + assertThat(r1.validate(v2Early, parentBelow)).isFalse(); + // v1 at V2: an honest v1 header (correct v1 digest) is still refused, the form is wrong + final BlockHeader parent = parentHeader(V2 + 4L); + final BlockHeader v1Late = PqAnchorTestSupport.honestHeader(V2 + 5L, parent.getHash(), + List.of(PqAnchorTestSupport.seal(0), PqAnchorTestSupport.seal(1), PqAnchorTestSupport.seal(2))); + assertThat(r1.validate(v1Late, parent)).isFalse(); + // control: the same v1 header is accepted by a rule whose V2 lies in the future + final PqAnchorConfig v1World = new PqAnchorConfig( + CHAIN_ID, H, Map.of(H, 0, V2, K), OptionalInt.empty(), false, OptionalInt.empty(), + OptionalInt.empty(), V2 + 1_000L); + assertThat(new PqAnchorDigestRule(v1World).validate(v1Late, parent)).isTrue(); + } + + // --------------------------------------------------------------------------------------- R2 + ++ /** ++ * AIP-22 stage 2, per-scheme intervals: Falcon on the 32 grid and SLH-DSA on the 128 grid, both ++ * counted from H. At an anchor on the 128 grid the certificate must reach K SLH-DSA seals; at an ++ * anchor on the 32 grid only, K Falcon seals suffice, and SLH-DSA seals carried there anyway are a ++ * surplus that is VERIFIED (a tampered one still refuses), not ignored and not refused. ++ */ ++ @Test ++ public void r2WithPerSchemeIntervalsDemandsSlhDsaOnlyOnItsGridAndVerifiesSurplus() throws Exception { ++ armHybrid("0:falcon-512/32+" + SLH + "/128"); ++ long hybridAnchor = H; ++ while (hybridAnchor <= V2) { ++ hybridAnchor += 128L; ++ } ++ final long falconOnlyAnchor = hybridAnchor + 32L; ++ final BlockHeader p1 = parentHeader(hybridAnchor - 1L); ++ assertThat(r2.validate(honestV2(hybridAnchor, p1, certificate(p1, K, 0)), p1, context())).isFalse(); ++ assertThat(r2.validate(honestV2(hybridAnchor, p1, certificate(p1, K, K)), p1, context())).isTrue(); ++ final BlockHeader p2 = parentHeader(falconOnlyAnchor - 1L); ++ assertThat(r2.validate(honestV2(falconOnlyAnchor, p2, certificate(p2, K, 0)), p2, context())).isTrue(); ++ assertThat(r2.validate(honestV2(falconOnlyAnchor, p2, certificate(p2, K, K)), p2, context())).isTrue(); ++ final List surplus = new ArrayList<>(certificate(p2, K, K)); ++ for (int i = 0; i < surplus.size(); i++) { ++ final SchemeSeal s = surplus.get(i); ++ if (s.getSchemeWireId() == SealSchemes.SLH_DSA_128S.wireId()) { ++ final byte[] b = s.getSignature().toArray(); ++ b[b.length / 2] ^= 1; ++ surplus.set(i, new SchemeSeal(s.getSchemeWireId(), s.getValidatorIndex(), Bytes.wrap(b))); ++ break; ++ } ++ } ++ surplus.sort(PqAnchorV2.CANONICAL); ++ assertThat(r2.validate(honestV2(falconOnlyAnchor, p2, surplus), p2, context())).isFalse(); ++ } ++ + @Test + public void r2AcceptsTheHonestV2HeaderWithKSealsPerScheme() { + final BlockHeader parent = parentHeader(V2 + 4L); + assertThat(r2.validate(honestV2(V2 + 5L, parent, certificate(parent, K, K)), parent, context())).isTrue(); + // more than K of each is fine too: K is a floor + assertThat(r2.validate(honestV2(V2 + 5L, parent, certificate(parent, 5, 5)), parent, context())).isTrue(); + } + + @Test + public void r2RefusesAnSlhDsaSealFromAnIndexWithoutAFalconSeal() { + final BlockHeader parent = parentHeader(V2 + 4L); + final List tagged = certificate(parent, K, K + 1); // SLH-DSA from index K has no Falcon + assertThat(r2.validate(honestV2(V2 + 5L, parent, tagged), parent, context())).isFalse(); + } + + @Test + public void r2RefusesACertificateShortOfOneScheme() { + final BlockHeader parent = parentHeader(V2 + 4L); + assertThat(r2.validate(honestV2(V2 + 5L, parent, certificate(parent, 5, K - 1)), parent, context())) + .describedAs("K Falcon seals and only K-1 SLH-DSA: the schedule demands K of EVERY scheme") +diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqCheckpointRuleTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqCheckpointRuleTest.java +new file mode 100644 +index 0000000000..dfdc78622c +--- /dev/null ++++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqCheckpointRuleTest.java +@@ -0,0 +1,75 @@ ++/* ++ * Copyright contributors to Besu / AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.consensus.qbft.headervalidationrules; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++import static org.assertj.core.api.Assertions.assertThatThrownBy; ++ ++import org.hyperledger.besu.datatypes.Hash; ++import org.hyperledger.besu.ethereum.core.BlockHeader; ++import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; ++ ++import java.util.TreeMap; ++ ++import org.junit.jupiter.api.Test; ++ ++/** ++ * AIP-22 stage 4: the checkpoint rule. At the checkpoint height only the checkpoint's hash passes; ++ * every other height passes; unset is inert; a malformed value refuses at load with its reason. The ++ * negative control of the runner plants "never refuse" at run time and turns the refusal probe red. ++ */ ++class PqCheckpointRuleTest { ++ ++ private static BlockHeader header(final long number, final long timestamp) { ++ return new BlockHeaderTestFixture().number(number).timestamp(timestamp).buildHeader(); ++ } ++ ++ @Test ++ void atTheCheckpointHeightOnlyTheCheckpointHashPassesAndAnotherHashIsRefused() { ++ final BlockHeader honest = header(2048, 1000); ++ final BlockHeader fork = header(2048, 1001); ++ assertThat(fork.getHash()).isNotEqualTo(honest.getHash()); ++ final TreeMap cp = new TreeMap<>(); ++ cp.put(2048L, honest.getHash()); ++ final PqCheckpointRule rule = new PqCheckpointRule(cp); ++ assertThat(rule.validate(honest, null, null)).isTrue(); ++ assertThat(rule.validate(fork, null, null)).isFalse(); ++ // other heights are not judged by the checkpoint ++ assertThat(rule.validate(header(2047, 999), null, null)).isTrue(); ++ assertThat(rule.validate(header(2049, 1002), null, null)).isTrue(); ++ } ++ ++ @Test ++ void unsetIsInertAndTheParserReadsSeveralCheckpoints() { ++ final PqCheckpointRule inert = new PqCheckpointRule(PqCheckpointRule.parse(null)); ++ assertThat(inert.checkpoints()).isEmpty(); ++ assertThat(inert.validate(header(2048, 1001), null, null)).isTrue(); ++ assertThat(PqCheckpointRule.parse(" ")).isEmpty(); ++ final String h1 = header(10, 1).getHash().toHexString(); ++ final String h2 = header(20, 2).getHash().toHexString(); ++ assertThat(PqCheckpointRule.parse("10:" + h1 + ", 20:" + h2)).hasSize(2).containsKeys(10L, 20L); ++ } ++ ++ @Test ++ void aMalformedValueRefusesAtLoadWithItsReason() { ++ final String h = header(10, 1).getHash().toHexString(); ++ for (final String bad : new String[] {"10", "x:" + h, "10:0x1234", "0:" + h, "10:" + h + ",10:" + h}) { ++ assertThatThrownBy(() -> PqCheckpointRule.parse(bad)) ++ .as(bad) ++ .isInstanceOf(IllegalArgumentException.class) ++ .hasMessageStartingWith("AERE-PQC-CHECKPOINT-01"); ++ } ++ } ++} +diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqHeaderSealStage5Test.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqHeaderSealStage5Test.java +new file mode 100644 +index 0000000000..2a928bda7c +--- /dev/null ++++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/PqHeaderSealStage5Test.java +@@ -0,0 +1,478 @@ ++/* ++ * Copyright contributors to Besu / AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.consensus.qbft.headervalidationrules; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++import static org.assertj.core.api.Assertions.assertThatThrownBy; ++ ++import org.hyperledger.besu.consensus.common.bft.AerePqFinality; ++import org.hyperledger.besu.consensus.common.bft.AerePqHeaderSeal; ++import org.hyperledger.besu.consensus.common.bft.AerePqIdentity; ++import org.hyperledger.besu.consensus.common.bft.BftBlockHashing; ++import org.hyperledger.besu.consensus.common.bft.BftExtraData; ++import org.hyperledger.besu.consensus.common.bft.FalconSeal; ++import org.hyperledger.besu.consensus.common.bft.PqAnchor; ++import org.hyperledger.besu.consensus.common.bft.PqRegistryV3; ++import org.hyperledger.besu.consensus.common.bft.SealScheme; ++import org.hyperledger.besu.consensus.common.bft.SealSchemes; ++import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; ++import org.hyperledger.besu.crypto.SECPSignature; ++import org.hyperledger.besu.crypto.SecureRandomProvider; ++import org.hyperledger.besu.cryptoservices.NodeKey; ++import org.hyperledger.besu.cryptoservices.NodeKeyUtils; ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.ethereum.core.BlockHeader; ++import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; ++import org.hyperledger.besu.ethereum.core.Util; ++import org.hyperledger.besu.ethereum.mainnet.AttachedBlockHeaderValidationRule; ++import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; ++import org.hyperledger.besu.ethereum.rlp.RLPException; ++ ++import java.util.ArrayList; ++import java.util.Collections; ++import java.util.List; ++import java.util.Map; ++import java.util.Optional; ++import java.util.TreeMap; ++ ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.bytes.Bytes32; ++import org.junit.jupiter.api.AfterEach; ++import org.junit.jupiter.api.BeforeEach; ++import org.junit.jupiter.api.Test; ++ ++/** ++ * AIP-22 stage 5 in the Besu-derived client, with real Falcon-512 keys generated for the run: the ++ * seventh extraData element (the proposer's seal) round-trips canonically, stays outside BOTH hashes, ++ * and the header rule admits a header from H_hdr iff its ECDSA committed seals are empty and the seal ++ * of its coinbase's index verifies over the proposal message recomputed from the stored header. Each ++ * refusal is asserted BY ITS REASON. Below H_hdr the upstream rule decides. The runner's negative ++ * control plants "never refuse" in the rule at run time and these probes turn red. ++ */ ++public class PqHeaderSealStage5Test { ++ ++ private static final long CHAIN = 28001; ++ private static final long BIND = 10; ++ private static final long H_ID = 10; ++ private static final long H_FIN = 20; ++ private static final long H_HDR = 30; ++ private static final int N = 4; ++ private static final SealScheme FALCON = SealSchemes.FALCON_512; ++ private static final QbftExtraDataCodec CODEC = new QbftExtraDataCodec(); ++ ++ private final List falcon = new ArrayList<>(); ++ private final List
    ids = new ArrayList<>(); ++ private PqHeaderSealRule rule; ++ ++ @BeforeEach ++ public void arm() { ++ final List rows = new ArrayList<>(); ++ for (int i = 0; i < N; i++) { ++ final NodeKey nk = NodeKeyUtils.generate(); ++ final SealScheme.GeneratedPair p = FALCON.generate(SecureRandomProvider.createSecureRandom()); ++ falcon.add(p.privateKey()); ++ final byte[] std = new byte[897]; ++ std[0] = 0x09; ++ System.arraycopy(p.publicRegistryForm(), 0, std, 1, 896); ++ final byte[] id = PqRegistryV3.idOf(std); ++ final Bytes32 popMsg = PqRegistryV3.popMessage(CHAIN, BIND, N, i, id, FALCON.wireId(), std); ++ final byte[] pop = FALCON.sign(p.privateKey(), popMsg.toArrayUnsafe()).orElseThrow(); ++ final TreeMap keys = new TreeMap<>(); ++ keys.put(FALCON.wireId() & 0xff, new PqRegistryV3.Key(FALCON, std, pop)); ++ final PqRegistryV3.Row bare = new PqRegistryV3.Row(i, id, keys, null, Map.of(), null, null); ++ final SECPSignature claim = nk.sign(PqRegistryV3.claimDigest(CHAIN, PqRegistryV3.rowHash(CHAIN, BIND, N, bare))); ++ rows.add( ++ new PqRegistryV3.Row( ++ i, id, keys, null, Map.of(), ++ Util.publicKeyToAddress(nk.getPublicKey()).getBytes().toArrayUnsafe(), ++ claim.encodedBytes().toArrayUnsafe())); ++ ids.add(Address.wrap(Bytes.wrap(id))); ++ } ++ final List hashes = new ArrayList<>(); ++ for (final PqRegistryV3.Row r : rows) { ++ hashes.add(PqRegistryV3.rowHash(CHAIN, BIND, N, r)); ++ } ++ final Bytes32 root = PqRegistryV3.merkleRoot(hashes); ++ final TreeMap epochs = new TreeMap<>(); ++ epochs.put( ++ BIND, ++ new PqRegistryV3.Registry(CHAIN, BIND, N, rows, hashes, root, PqRegistryV3.registryHash(CHAIN, BIND, N, root))); ++ AerePqHeaderSeal.uninstall(); ++ AerePqFinality.uninstall(); ++ AerePqIdentity.uninstall(); ++ AerePqIdentity.install(new AerePqIdentity.Config(H_ID, epochs, H_ID)); ++ final AerePqFinality.SealVerifier v = ++ (h, i, m, s) -> ++ AerePqIdentity.v3KeyAt(h, i, "falcon-512") ++ .map(k -> FALCON.verifyRaw(k, m.toArrayUnsafe(), s.toArrayUnsafe())) ++ .orElse(false); ++ AerePqFinality.install(H_FIN, CHAIN, v); ++ AerePqHeaderSeal.install(H_HDR); ++ rule = new PqHeaderSealRule(sentinel(false), CODEC, CHAIN, v); ++ } ++ ++ @AfterEach ++ public void disarm() { ++ AerePqHeaderSeal.uninstall(); ++ AerePqFinality.uninstall(); ++ AerePqIdentity.uninstall(); ++ } ++ ++ private static AttachedBlockHeaderValidationRule sentinel(final boolean answer) { ++ return (header, parent, ctx) -> answer; ++ } ++ ++ private BftExtraData extra(final int round, final List seals, final Optional ps) { ++ return new BftExtraData( ++ Bytes.wrap(new byte[32]), seals, Optional.empty(), round, ids, Collections.emptyList(), Collections.emptyList(), ps); ++ } ++ ++ private static BlockHeader header(final long h, final Address coinbase, final BftExtraData ed) { ++ return new BlockHeaderTestFixture().number(h).coinbase(coinbase).extraData(CODEC.encode(ed)).buildHeader(); ++ } ++ ++ /** The proposer seal of {@code signer} over the header's own proposal message (for the index {@code index}). */ ++ private Optional sealOver(final BlockHeader unsealed, final int round, final int index, final int signer) { ++ final Bytes32 m = ++ PqAnchor.proposalMessage( ++ CHAIN, unsealed.getNumber(), round, new BftBlockHashing(CODEC).calculateDataHashForCommittedSeal(unsealed).getBytes()); ++ return Optional.of(new FalconSeal(index, Bytes.wrap(FALCON.sign(falcon.get(signer), m.toArrayUnsafe()).orElseThrow()))); ++ } ++ ++ private BlockHeader sealedHeader(final long h, final int round, final int coinbase, final int index, final int signer) { ++ final BlockHeader unsealed = header(h, ids.get(coinbase), extra(round, List.of(), Optional.empty())); ++ return header(h, ids.get(coinbase), extra(round, List.of(), sealOver(unsealed, round, index, signer))); ++ } ++ ++ @Test ++ public void theProposerSealIsTheSeventhElementCanonicalAndOutsideBothHashes() { ++ final BlockHeader unsealed = header(H_HDR, ids.get(1), extra(2, List.of(), Optional.empty())); ++ final BlockHeader sealed = sealedHeader(H_HDR, 2, 1, 1, 1); ++ final BftExtraData back = CODEC.decode(sealed); ++ assertThat(back.getPqProposerSeal()).isPresent(); ++ assertThat(back.getPqProposerSeal().get().getValidatorIndex()).isEqualTo(1); ++ assertThat(back.getSeals()).isEmpty(); ++ assertThat(back.getRound()).isEqualTo(2); ++ final BftBlockHashing hashing = new BftBlockHashing(CODEC); ++ assertThat(hashing.calculateHashOfBftBlockOnchain(sealed)).isEqualTo(hashing.calculateHashOfBftBlockOnchain(unsealed)); ++ assertThat(hashing.calculateDataHashForCommittedSeal(sealed)).isEqualTo(hashing.calculateDataHashForCommittedSeal(unsealed)); ++ assertThat(sealed.getExtraData().size()).isGreaterThan(unsealed.getExtraData().size() + 600); ++ } ++ ++ @Test ++ public void anEmptyCertificateSlotWithoutTheProposerSealIsNonCanonicalAndRefused() { ++ // six elements whose sixth is an explicit empty list: two encodings of one value, refused as before ++ final BytesValueRLPOutput o = new BytesValueRLPOutput(); ++ o.startList(); ++ o.writeBytes(Bytes.wrap(new byte[32])); ++ o.writeList(ids, (a, rlp) -> rlp.writeBytes(a.getBytes())); ++ o.writeEmptyList(); ++ o.writeIntScalar(0); ++ o.writeEmptyList(); ++ o.writeEmptyList(); ++ o.endList(); ++ assertThatThrownBy(() -> CODEC.decodeRaw(o.encoded())).hasMessageContaining("Non-canonical"); ++ } ++ ++ @Test ++ public void fromHhdrAHeaderWithAVerifiedProposerSealOfItsCoinbaseAndNoEcdsaSealIsAdmitted() { ++ for (int i = 0; i < N; i++) { ++ assertThat(rule.refusal(sealedHeader(H_HDR, 0, i, i, i))).as("proposer %s", i).isEmpty(); ++ } ++ assertThat(rule.validate(sealedHeader(H_HDR + 7, 3, 2, 2, 2), null, null)).isTrue(); ++ } ++ ++ @Test ++ public void fromHhdrEachWayOfBeingWrongIsRefusedByItsReason() { ++ // an ECDSA committed seal present ++ final SECPSignature ecdsa = NodeKeyUtils.generate().sign(Bytes32.ZERO); ++ final BlockHeader unsealed = header(H_HDR, ids.get(0), extra(0, List.of(), Optional.empty())); ++ final BlockHeader withEcdsa = header(H_HDR, ids.get(0), extra(0, List.of(ecdsa), sealOver(unsealed, 0, 0, 0))); ++ assertThat(rule.refusal(withEcdsa)).get().asString().contains("MUST be empty"); ++ // no proposer seal ++ assertThat(rule.refusal(unsealed)).get().asString().contains("no proposer seal"); ++ // index 0 sealed by key 1 ++ assertThat(rule.refusal(sealedHeader(H_HDR, 0, 0, 0, 1))).get().asString().contains("does not verify"); ++ // a valid seal of index 1 on a header whose coinbase is id 0 ++ assertThat(rule.refusal(sealedHeader(H_HDR, 0, 0, 1, 1))).get().asString().contains("cannot vouch"); ++ // an index with no row ++ assertThat(rule.refusal(sealedHeader(H_HDR, 0, 0, N, 0))).get().asString().contains("names no row"); ++ // a seal over another round than the header's ++ final BlockHeader r1 = header(H_HDR, ids.get(0), extra(1, List.of(), Optional.empty())); ++ final BlockHeader sealedAtRound0 = header(H_HDR, ids.get(0), extra(1, List.of(), sealOver(unsealed, 0, 0, 0))); ++ assertThat(rule.refusal(sealedAtRound0)).get().asString().contains("does not verify"); ++ assertThat(rule.refusal(header(H_HDR, ids.get(0), extra(1, List.of(), sealOver(r1, 1, 0, 0))))).isEmpty(); ++ } ++ ++ // ---- AERE D-406 (2026-09-25): a block re-proposed at round r carries the seal of round r's proposer ---- ++ ++ /** The validator list as a real header stores it: ascending. */ ++ private List
    sortedIds() { ++ final List
    s = new ArrayList<>(ids); ++ Collections.sort(s); ++ return s; ++ } ++ ++ /** ++ * The proposer of round r written HERE, independently of the rule (which calls upstream's selector): the ++ * existing-proposer case is list[(indexOf(prev) + 1 + r) mod n], the missing-proposer case seeds from the first ++ * validator strictly above prev (the first if none) with no +1. ++ */ ++ private static Address expectedProposer(final List
    sorted, final Address prev, final int r) { ++ final int n = sorted.size(); ++ final int i = sorted.indexOf(prev); ++ if (i >= 0) { ++ return sorted.get((i + 1 + r) % n); ++ } ++ int seed = 0; ++ for (int k = 0; k < n; k++) { ++ if (sorted.get(k).compareTo(prev) > 0) { ++ seed = k; ++ break; ++ } ++ } ++ return sorted.get((seed + r) % n); ++ } ++ ++ private BlockHeader parentWithCoinbase(final long h, final Address coinbase) { ++ return new BlockHeaderTestFixture().number(h - 1).coinbase(coinbase).buildHeader(); ++ } ++ ++ /** A header at h, round r, built by {@code coinbase}, sealed as index {@code index} by key {@code signer}. */ ++ private BlockHeader reproposed(final long h, final int round, final Address coinbase, final int index, final int signer) { ++ final List
    sorted = sortedIds(); ++ final BftExtraData bare = ++ new BftExtraData( ++ Bytes.wrap(new byte[32]), List.of(), Optional.empty(), round, sorted, Collections.emptyList(), ++ Collections.emptyList(), Optional.empty()); ++ final BlockHeader unsealed = header(h, coinbase, bare); ++ final BftExtraData sealed = ++ new BftExtraData( ++ Bytes.wrap(new byte[32]), List.of(), Optional.empty(), round, sorted, Collections.emptyList(), ++ Collections.emptyList(), sealOver(unsealed, round, index, signer)); ++ return header(h, coinbase, sealed); ++ } ++ ++ @Test ++ public void aReProposedHeaderSealedByTheProposerOfItsRoundIsAdmittedOnlyWithItsParent() { ++ final List
    sorted = sortedIds(); ++ final long h = H_HDR + 5; ++ int judged = 0; ++ for (int p = 0; p < N; p++) { ++ final Address prev = sorted.get(p); ++ final Address builder = expectedProposer(sorted, prev, 0); ++ for (int r = 1; r < 2 * N; r++) { ++ final Address roundProposer = expectedProposer(sorted, prev, r); ++ if (roundProposer.equals(builder)) { ++ continue; ++ } ++ final int idx = ids.indexOf(roundProposer); ++ final BlockHeader hd = reproposed(h, r, builder, idx, idx); ++ final BlockHeader parent = parentWithCoinbase(h, prev); ++ assertThat(rule.refusal(hd, parent)).as("prev %s round %s", p, r).isEmpty(); ++ assertThat(rule.validate(hd, parent, null)).as("prev %s round %s", p, r).isTrue(); ++ // without the parent the round's proposer is not known: refused, and the reason says why ++ assertThat(rule.refusal(hd)).get().asString() ++ .contains("cannot vouch").contains("not known without the parent"); ++ judged++; ++ } ++ } ++ // every (prev, round) pair whose round proposer differs from the builder was judged: 4 x (7 - 1) at N = 4 ++ assertThat(judged).isEqualTo(N * (2 * N - 1 - 1)); ++ } ++ ++ @Test ++ public void aReProposedHeaderSealedByAThirdValidatorIsRefusedAndTheReasonNamesTheRoundsProposer() { ++ final List
    sorted = sortedIds(); ++ final long h = H_HDR + 6; ++ final Address prev = sorted.get(0); ++ final Address builder = expectedProposer(sorted, prev, 0); ++ final int r = 1; ++ final Address roundProposer = expectedProposer(sorted, prev, r); ++ Address third = null; ++ for (final Address a : sorted) { ++ if (!a.equals(builder) && !a.equals(roundProposer)) { ++ third = a; ++ break; ++ } ++ } ++ final int idx = ids.indexOf(third); ++ final Optional why = rule.refusal(reproposed(h, r, builder, idx, idx), parentWithCoinbase(h, prev)); ++ assertThat(why).get().asString() ++ .contains("cannot vouch") ++ .contains("the proposer of round " + r + " is " + roundProposer); ++ // the round proposer's key over ANOTHER round than element 3: the id passes, the signature does not ++ final int rp = ids.indexOf(roundProposer); ++ final List
    s2 = sortedIds(); ++ final BlockHeader atRound0 = ++ header(h, builder, new BftExtraData(Bytes.wrap(new byte[32]), List.of(), Optional.empty(), 0, s2, ++ Collections.emptyList(), Collections.emptyList(), Optional.empty())); ++ final BlockHeader wrongRound = ++ header(h, builder, new BftExtraData(Bytes.wrap(new byte[32]), List.of(), Optional.empty(), r, s2, ++ Collections.emptyList(), Collections.emptyList(), sealOver(atRound0, 0, rp, rp))); ++ assertThat(rule.refusal(wrongRound, parentWithCoinbase(h, prev))).get().asString().contains("does not verify"); ++ } ++ ++ @Test ++ public void theSealMustBeExactlyTheProposerOfRoundRNotOfAnEarlierRound() { ++ // found by the adversarial review of 2026-09-25: an implementation admitting ANY P(r') with r' <= r passed every probe above ++ final List
    sorted = sortedIds(); ++ final long h = H_HDR + 9; ++ final Address prev = sorted.get(0); ++ final Address builder = expectedProposer(sorted, prev, 0); ++ final Address p1 = expectedProposer(sorted, prev, 1); ++ final Address p2 = expectedProposer(sorted, prev, 2); ++ assertThat(p1).isNotEqualTo(p2); ++ final int i1 = ids.indexOf(p1); ++ assertThat(rule.refusal(reproposed(h, 2, builder, i1, i1), parentWithCoinbase(h, prev))).get().asString() ++ .contains("cannot vouch").contains("the proposer of round 2 is " + p2); ++ final int i2 = ids.indexOf(p2); ++ assertThat(rule.refusal(reproposed(h, 2, builder, i2, i2), parentWithCoinbase(h, prev))).isEmpty(); ++ } ++ ++ @Test ++ public void withTheParentTheCoinbaseMustBeTheProposerOfSomeRoundUpToElement3() { ++ // the second client has refused this since D-331; the Besu-derived rule did not, so the two judged such a header differently ++ final List
    sorted = sortedIds(); ++ final long h = H_HDR + 10; ++ final Address prev = sorted.get(0); ++ final Address p1 = expectedProposer(sorted, prev, 1); ++ final Address p3 = expectedProposer(sorted, prev, 3); ++ final int i1 = ids.indexOf(p1); ++ // round 1, built by P(3) (a proposer of a LATER round), sealed by P(1): the seal is the round's, the builder is impossible ++ assertThat(rule.refusal(reproposed(h, 1, p3, i1, i1), parentWithCoinbase(h, prev))).get().asString() ++ .contains("is not the proposer of any round 0..1"); ++ // and a coinbase-sealed header at round 0 whose coinbase is not P(0) ++ final int i3 = ids.indexOf(p3); ++ assertThat(rule.refusal(reproposed(h, 0, p3, i3, i3), parentWithCoinbase(h, prev))).get().asString() ++ .contains("is not the proposer of any round 0..0"); ++ // without the parent the builder cannot be judged, and the coinbase's own seal is admitted as before ++ assertThat(rule.refusal(reproposed(h, 0, p3, i3, i3))).isEmpty(); ++ } ++ ++ @Test ++ public void theRoundInElement3IsBoundedAndTheBoundIsInclusive() { ++ final List
    sorted = sortedIds(); ++ final long h = H_HDR + 11; ++ final Address prev = sorted.get(2); ++ final int max = PqHeaderSealRule.MAX_ROUND; ++ // at the bound: a re-proposal sealed by P(max) is admitted (upstream's int arithmetic stays in range) ++ final Address builder = expectedProposer(sorted, prev, 0); ++ final Address pm = expectedProposer(sorted, prev, max); ++ final int im = ids.indexOf(pm); ++ final int ib = ids.indexOf(builder); ++ final Address sealer = pm.equals(builder) ? builder : pm; ++ final int is = sealer.equals(builder) ? ib : im; ++ assertThat(rule.refusal(reproposed(h, max, builder, is, is), parentWithCoinbase(h, prev))).isEmpty(); ++ // above it: refused by the bound, with or without the parent, whoever sealed ++ assertThat(rule.refusal(reproposed(h, max + 1, builder, ib, ib), parentWithCoinbase(h, prev))).get().asString() ++ .contains("is outside 0.." + max); ++ assertThat(rule.refusal(reproposed(h, max + 1, builder, ib, ib))).get().asString().contains("is outside 0.." + max); ++ } ++ ++ @Test ++ public void atRoundZeroOnlyTheCoinbaseSealIsAdmittedEvenWithTheParent() { ++ final List
    sorted = sortedIds(); ++ final long h = H_HDR + 7; ++ final Address prev = sorted.get(1); ++ final Address builder = expectedProposer(sorted, prev, 0); ++ for (final Address other : sorted) { ++ if (other.equals(builder)) { ++ continue; ++ } ++ final int idx = ids.indexOf(other); ++ final Optional why = rule.refusal(reproposed(h, 0, builder, idx, idx), parentWithCoinbase(h, prev)); ++ assertThat(why).get().asString().contains("cannot vouch").doesNotContain("proposer of round"); ++ } ++ final int b = ids.indexOf(builder); ++ assertThat(rule.refusal(reproposed(h, 0, builder, b, b), parentWithCoinbase(h, prev))).isEmpty(); ++ } ++ ++ @Test ++ public void whenTheParentsProposerLeftTheSetTheRoundsProposerFollowsUpstreamsMissingProposerSeed() { ++ final List
    sorted = sortedIds(); ++ final long h = H_HDR + 8; ++ // a parent proposer below every id (the seed is the first validator) and one above every id (it wraps to the first) ++ final Address below = Address.fromHexString("0x0000000000000000000000000000000000000001"); ++ final Address above = Address.fromHexString("0xffffffffffffffffffffffffffffffffffffffff"); ++ // and one strictly between the second and the third id, so the seed is the third (index 2), not the first ++ final byte[] mid = sorted.get(1).getBytes().toArrayUnsafe().clone(); ++ int k = mid.length - 1; ++ while (k >= 0 && mid[k] == (byte) 0xff) { ++ mid[k--] = 0; ++ } ++ mid[k]++; ++ final Address middle = Address.wrap(Bytes.wrap(mid)); ++ assertThat(middle.compareTo(sorted.get(1)) > 0 && middle.compareTo(sorted.get(2)) < 0).isTrue(); ++ assertThat(expectedProposer(sorted, middle, 0)).isEqualTo(sorted.get(2)); ++ int judged = 0; ++ for (final Address prev : List.of(below, above, middle)) { ++ final Address builder = expectedProposer(sorted, prev, 0); ++ for (int r = 1; r < N; r++) { ++ final Address rp = expectedProposer(sorted, prev, r); ++ final int idx = ids.indexOf(rp); ++ assertThat(rule.refusal(reproposed(h, r, builder, idx, idx), parentWithCoinbase(h, prev))) ++ .as("prev %s round %s", prev, r).isEmpty(); ++ judged++; ++ } ++ } ++ assertThat(judged).isEqualTo(3 * (N - 1)); ++ } ++ ++ // ---- AERE D-415 (2026-09-25): the vanity field is exactly 32 bytes at EVERY height, in the codec, as in the second client ---- ++ ++ /** The genesis extraData of chains 2800 and 28001 (both a 32-zero vanity), as published. */ ++ private static final String GENESIS_2800_EXTRA = ++ "0xf865a00000000000000000000000000000000000000000000000000000000000000000f83f94b5e768cb3117ea25175f51aa956b48691025c2a894f73bbbd26a82dbc769066550d8d4585eab2fc00d944bf6f91d84b37454544279cba152581ed6820044c080c0"; ++ private static final String GENESIS_28001_EXTRA = ++ "0xf87aa00000000000000000000000000000000000000000000000000000000000000000f8549404211fd71c1eae94f560e7e173399c91c15fd9b394070d5e1534a367430307a6e56bef29ddff79c0e394b84ec13c5811264f60a8bc392634709558223ea694fb6be1504acf8262cf98669f7833b9cf1cbfabb9c080c0"; ++ /** A real 32-byte vanity between anchors on 28001 today: the client version string, not a digest. */ ++ private static final String VANITY_VERSIUNE = "0x626573752032362e342e302d616572652e312d643230333230312d7774396239"; ++ ++ private BlockHeader cuVanity(final long h, final Bytes vanity) { ++ final BftExtraData ed = ++ new BftExtraData(vanity, List.of(), Optional.empty(), 0, ids, Collections.emptyList(), Collections.emptyList(), Optional.empty()); ++ return new BlockHeaderTestFixture().number(h).coinbase(ids.get(0)).extraData(CODEC.encode(ed)).buildHeader(); ++ } ++ ++ @Test ++ public void theVanityFieldIsExactly32BytesAtEveryHeightAndBothGenesesStillDecode() { ++ // the two real geneses and a real between-anchors vanity decode as before (the check cannot touch the chain) ++ for (final String g : List.of(GENESIS_2800_EXTRA, GENESIS_28001_EXTRA)) { ++ assertThat(CODEC.decodeRaw(Bytes.fromHexString(g)).getVanityData().size()).as("genesis").isEqualTo(32); ++ } ++ assertThat(CODEC.decode(cuVanity(H_HDR - 5, Bytes.fromHexString(VANITY_VERSIUNE))).getVanityData().size()).isEqualTo(32); ++ // found by the differential fuzzer: a 0-, 31-, 33- or 64-byte vanity between anchors was admitted here and refused by the ++ // second client; now the codec refuses it at any height, above and below H_hdr, and the header rule reports the reason ++ for (final int n : new int[] {0, 31, 33, 64}) { ++ final Bytes v = Bytes.wrap(new byte[n]); ++ assertThatThrownBy(() -> CODEC.decode(cuVanity(H_HDR + 12, v))).as("vanity %s above H_hdr", n) ++ .isInstanceOf(RLPException.class).hasMessageContaining("AERE-D415"); ++ assertThatThrownBy(() -> CODEC.decode(cuVanity(H_HDR - 5, v))).as("vanity %s below H_hdr", n) ++ .isInstanceOf(RLPException.class).hasMessageContaining("AERE-D415"); ++ assertThat(rule.refusal(cuVanity(H_HDR + 12, v))).get().asString().contains("does not decode").contains("AERE-D415"); ++ } ++ } ++ ++ @Test ++ public void belowHhdrTheUpstreamRuleDecidesAndHhdrNeedsHfin() { ++ final BlockHeader below = sealedHeader(H_HDR - 1, 0, 0, 0, 0); ++ assertThat(new PqHeaderSealRule(sentinel(false), CODEC, CHAIN, (h, i, m, s) -> true).validate(below, null, null)).isFalse(); ++ assertThat(new PqHeaderSealRule(sentinel(true), CODEC, CHAIN, (h, i, m, s) -> false).validate(below, null, null)).isTrue(); ++ assertThatThrownBy(() -> AerePqHeaderSeal.install(H_FIN - 1)).hasMessageStartingWith("AERE-PQC-HDR-01"); ++ AerePqFinality.uninstall(); ++ assertThatThrownBy(() -> AerePqHeaderSeal.install(H_HDR)).hasMessageStartingWith("AERE-PQC-HDR-01"); ++ } ++} +diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetBalance.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetBalance.java +index cb1d879a05..5c74d44292 100644 +--- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetBalance.java ++++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetBalance.java +@@ -1,70 +1,86 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/0008-aere-pq-aip22.patch. + */ + package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; + + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.datatypes.Hash; + import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.BlockParameterOrBlockHash; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException; ++import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.Quantity; + import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; + + import java.util.function.Supplier; + + public class EthGetBalance extends AbstractBlockParameterOrBlockHashMethod { + public EthGetBalance(final BlockchainQueries blockchainQueries) { + super(blockchainQueries); + } + + public EthGetBalance(final Supplier blockchainQueries) { + super(blockchainQueries); + } + + @Override + public String getName() { + return RpcMethod.ETH_GET_BALANCE.getMethodName(); + } + + @Override + protected BlockParameterOrBlockHash blockParameterOrBlockHash( + final JsonRpcRequestContext request) { + try { + return request.getRequiredParameter(1, BlockParameterOrBlockHash.class); + } catch (JsonRpcParameterException e) { + throw new InvalidJsonRpcParameters( + "Invalid block or block hash parameter (index 1)", RpcErrorType.INVALID_BLOCK_PARAMS, e); + } + } + ++ // AERE D-FAZA2-04 (2026-09-10): an EMPTY answer from the state query means the world state for that ++ // block is not available (outside the node's state window, or not yet persisted); it never means ++ // "no such account" - fromAccount() fills a default for that. Upstream serialised the empty answer as ++ // a bare JSON null, which every client reads as a value. Here it is the same honest error that ++ // eth_getProof already returns: WORLD_STATE_UNAVAILABLE. + @Override +- protected String resultByBlockHash(final JsonRpcRequestContext request, final Hash blockHash) { ++ protected Object resultByBlockHash(final JsonRpcRequestContext request, final Hash blockHash) { + final Address address; + try { + address = request.getRequiredParameter(0, Address.class); + } catch (JsonRpcParameterException e) { + throw new InvalidJsonRpcParameters( + "Invalid address parameter (index 0)", RpcErrorType.INVALID_ADDRESS_PARAMS, e); + } + return blockchainQueries + .get() + .accountBalance(address, blockHash) + .map(Quantity::create) +- .orElse(null); ++ .map(s -> s) ++ .orElseGet( ++ () -> ++ new JsonRpcErrorResponse( ++ request.getRequest().getId(), RpcErrorType.WORLD_STATE_UNAVAILABLE)); + } + } +diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetCode.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetCode.java +index 0c9194b0b3..52bc65eece 100644 +--- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetCode.java ++++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetCode.java +@@ -1,68 +1,87 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/0008-aere-pq-aip22.patch. + */ + package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; + + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.datatypes.Hash; + import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.BlockParameterOrBlockHash; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException; ++import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; + import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; + + import java.util.function.Supplier; + + import org.apache.tuweni.bytes.Bytes; + + public class EthGetCode extends AbstractBlockParameterOrBlockHashMethod { + + public EthGetCode(final BlockchainQueries blockchainQueries) { + super(blockchainQueries); + } + + public EthGetCode(final Supplier blockchainQueries) { + super(blockchainQueries); + } + + @Override + public String getName() { + return RpcMethod.ETH_GET_CODE.getMethodName(); + } + + @Override + protected BlockParameterOrBlockHash blockParameterOrBlockHash( + final JsonRpcRequestContext request) { + try { + return request.getRequiredParameter(1, BlockParameterOrBlockHash.class); + } catch (JsonRpcParameterException e) { + throw new InvalidJsonRpcParameters( + "Invalid block or block hash parameter (index 1)", RpcErrorType.INVALID_BLOCK_PARAMS, e); + } + } + ++ // AERE D-FAZA2-04 (2026-09-10): an EMPTY answer from the state query means the world state for that ++ // block is not available (outside the node's state window, or not yet persisted); it never means ++ // "no such account" - fromAccount() fills a default for that. Upstream serialised the empty answer as ++ // a bare JSON null, which every client reads as a value. Here it is the same honest error that ++ // eth_getProof already returns: WORLD_STATE_UNAVAILABLE. + @Override +- protected String resultByBlockHash(final JsonRpcRequestContext request, final Hash blockHash) { ++ protected Object resultByBlockHash(final JsonRpcRequestContext request, final Hash blockHash) { + final Address address; + try { + address = request.getRequiredParameter(0, Address.class); + } catch (JsonRpcParameterException e) { + throw new InvalidJsonRpcParameters( + "Invalid address parameter (index 0)", RpcErrorType.INVALID_ADDRESS_PARAMS, e); + } +- return getBlockchainQueries().getCode(address, blockHash).map(Bytes::toString).orElse(null); ++ return getBlockchainQueries() ++ .getCode(address, blockHash) ++ .map(Bytes::toString) ++ .map(s -> s) ++ .orElseGet( ++ () -> ++ new JsonRpcErrorResponse( ++ request.getRequest().getId(), RpcErrorType.WORLD_STATE_UNAVAILABLE)); + } + } +diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetStorageAt.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetStorageAt.java +index 22de0da444..b6a3e95eec 100644 +--- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetStorageAt.java ++++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetStorageAt.java +@@ -1,73 +1,89 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/0008-aere-pq-aip22.patch. + */ + package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; + + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.datatypes.Hash; + import org.hyperledger.besu.datatypes.parameters.UInt256Parameter; + import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.BlockParameterOrBlockHash; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException; ++import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; + import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; + + import org.apache.tuweni.units.bigints.UInt256; + + public class EthGetStorageAt extends AbstractBlockParameterOrBlockHashMethod { + public EthGetStorageAt(final BlockchainQueries blockchainQueries) { + super(blockchainQueries); + } + + @Override + public String getName() { + return RpcMethod.ETH_GET_STORAGE_AT.getMethodName(); + } + + @Override + protected BlockParameterOrBlockHash blockParameterOrBlockHash( + final JsonRpcRequestContext request) { + try { + return request.getRequiredParameter(2, BlockParameterOrBlockHash.class); + } catch (JsonRpcParameterException e) { + throw new InvalidJsonRpcParameters( + "Invalid block or block hash parameter (index 2)", RpcErrorType.INVALID_BLOCK_PARAMS, e); + } + } + + @Override +- protected String resultByBlockHash(final JsonRpcRequestContext request, final Hash blockHash) { ++ // AERE D-FAZA2-04 (2026-09-10): an EMPTY answer from the state query means the world state for that ++ // block is not available (outside the node's state window, or not yet persisted); it never means ++ // "no such account" - fromAccount() fills a default for that. Upstream serialised the empty answer as ++ // a bare JSON null, which every client reads as a value. Here it is the same honest error that ++ // eth_getProof already returns: WORLD_STATE_UNAVAILABLE. ++ protected Object resultByBlockHash(final JsonRpcRequestContext request, final Hash blockHash) { + final Address address; + try { + address = request.getRequiredParameter(0, Address.class); + } catch (JsonRpcParameterException e) { + throw new InvalidJsonRpcParameters( + "Invalid address parameter (index 0)", RpcErrorType.INVALID_ADDRESS_PARAMS, e); + } + final UInt256 position; + try { + position = request.getRequiredParameter(1, UInt256Parameter.class).getValue(); + } catch (JsonRpcParameterException e) { + throw new InvalidJsonRpcParameters( + "Invalid position parameter (index 1)", RpcErrorType.INVALID_POSITION_PARAMS, e); + } + return blockchainQueries + .get() + .storageAt(address, position, blockHash) + .map(UInt256::toHexString) +- .orElse(null); ++ .map(s -> s) ++ .orElseGet( ++ () -> ++ new JsonRpcErrorResponse( ++ request.getRequest().getId(), RpcErrorType.WORLD_STATE_UNAVAILABLE)); + } + } +diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionCount.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionCount.java +index 4e26f8ee98..291056a7af 100644 +--- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionCount.java ++++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionCount.java +@@ -1,43 +1,50 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/0008-aere-pq-aip22.patch. + */ + package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; + + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.datatypes.Hash; + import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.BlockParameterOrBlockHash; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException; ++import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; + import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.Quantity; + import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; + import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; + + import java.util.function.Supplier; + + import com.google.common.base.Suppliers; + + public class EthGetTransactionCount extends AbstractBlockParameterOrBlockHashMethod { + private final Supplier transactionPoolSupplier; + + public EthGetTransactionCount( + final BlockchainQueries blockchain, final TransactionPool transactionPoolSupplier) { + this(Suppliers.ofInstance(blockchain), Suppliers.ofInstance(transactionPoolSupplier)); + } + + public EthGetTransactionCount( + final Supplier blockchain, + final Supplier transactionPoolSupplier) { +@@ -67,34 +74,46 @@ public class EthGetTransactionCount extends AbstractBlockParameterOrBlockHashMet + try { + address = request.getRequiredParameter(0, Address.class); + } catch (JsonRpcParameterException e) { + throw new InvalidJsonRpcParameters( + "Invalid address parameter (index 0)", RpcErrorType.INVALID_ADDRESS_PARAMS, e); + } + final long pendingNonce = + transactionPoolSupplier.get().getNextNonceForSender(address).orElse(0); + final long latestNonce = + getBlockchainQueries() + .getTransactionCount( + address, getBlockchainQueries().getBlockchain().getChainHead().getHash()); + + if (Long.compareUnsigned(pendingNonce, latestNonce) > 0) { + return Quantity.create(pendingNonce); + } + + return Quantity.create(latestNonce); + } + ++ // AERE D-FAZA2-04 (2026-09-10): an EMPTY answer from the state query means the world state for that ++ // block is not available (outside the node's state window, or not yet persisted); it never means ++ // "no such account" - fromAccount() fills a default for that. Upstream serialised the empty answer as ++ // a bare JSON null, which every client reads as a value. Here it is the same honest error that ++ // eth_getProof already returns: WORLD_STATE_UNAVAILABLE. ++ // Upstream folded the missing state into a nonce of 0 (`.orElse(0L)`), a FALSE 0x0 that a wallet ++ // signs with. Here the nonce is asked for as an Optional and the missing state is an error. + @Override +- protected String resultByBlockHash(final JsonRpcRequestContext request, final Hash blockHash) { ++ protected Object resultByBlockHash(final JsonRpcRequestContext request, final Hash blockHash) { + final Address address; + try { + address = request.getRequiredParameter(0, Address.class); + } catch (JsonRpcParameterException e) { + throw new InvalidJsonRpcParameters( + "Invalid address parameter (index 0)", RpcErrorType.INVALID_ADDRESS_PARAMS, e); + } +- final long transactionCount = getBlockchainQueries().getTransactionCount(address, blockHash); +- +- return Quantity.create(transactionCount); ++ return getBlockchainQueries() ++ .getTransactionCountIfStateAvailable(address, blockHash) ++ .map(Quantity::create) ++ .map(s -> s) ++ .orElseGet( ++ () -> ++ new JsonRpcErrorResponse( ++ request.getRequest().getId(), RpcErrorType.WORLD_STATE_UNAVAILABLE)); + } + } +diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java +index caa03d9ce8..b7e4c4524e 100644 +--- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java ++++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java +@@ -1,33 +1,39 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/aere-drop-per-request-console-writes.patch. + */ + package org.hyperledger.besu.ethereum.api.query; + + import static com.google.common.base.Preconditions.checkArgument; + import static org.hyperledger.besu.ethereum.api.query.cache.TransactionLogBloomCacher.BLOCKS_PER_BLOOM_CACHE; + import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator.calculateExcessBlobGasForParent; + import static org.hyperledger.besu.ethereum.trie.pathbased.common.provider.WorldStateQueryParams.withBlockHeaderAndNoUpdateNodeHead; + + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.datatypes.Hash; + import org.hyperledger.besu.datatypes.LogsBloomFilter; + import org.hyperledger.besu.datatypes.Wei; + import org.hyperledger.besu.ethereum.api.ApiConfiguration; + import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration; + import org.hyperledger.besu.ethereum.api.query.cache.TransactionLogBloomCacher; + import org.hyperledger.besu.ethereum.chain.Blockchain; + import org.hyperledger.besu.ethereum.chain.TransactionLocation; + import org.hyperledger.besu.ethereum.core.Block; + import org.hyperledger.besu.ethereum.core.BlockBody; + import org.hyperledger.besu.ethereum.core.BlockHeader; +@@ -320,40 +326,53 @@ public class BlockchainQueries { + final Hash blockHash = + getBlockHeaderByNumber(blockNumber).map(BlockHeader::getHash).orElse(Hash.EMPTY); + + return getTransactionCount(address, blockHash); + } + + /** + * Returns the number of transactions sent from the given address in the block at the given hash. + * + * @param address The address whose sent transactions we want to count. + * @param blockHash The hash of the block being queried. + * @return The number of transactions sent from the given address. + */ + public long getTransactionCount(final Address address, final Hash blockHash) { + return getAndMapWorldState( + blockHash, worldState -> Optional.ofNullable(worldState.get(address))) + .map(Account::getNonce) + .orElse(0L); + } + ++ /** ++ * AERE D-FAZA2-04: the nonce as an Optional that is EMPTY when the world state for the block is not ++ * available, so a caller can tell "state missing" from "nonce zero". {@link #getTransactionCount(Address, ++ * Hash)} keeps upstream's behaviour (0 when missing) for the callers that rely on it. ++ */ ++ public Optional getTransactionCountIfStateAvailable(final Address address, final Hash blockHash) { ++ return getAndMapWorldState( ++ blockHash, ++ worldState -> ++ Optional.of( ++ Optional.ofNullable(worldState.get(address)).map(Account::getNonce).orElse(0L))); ++ } ++ + /** + * Returns the number of transactions sent from the given address in the latest block. + * + * @param address The address whose sent transactions we want to count. + * @return The number of transactions sent from the given address. + */ + public long getTransactionCount(final Address address) { + return getTransactionCount(address, headBlockNumber()); + } + + /** + * Returns the number of ommers in the block at the given height. + * + * @param blockNumber The height of the block being queried. + * @return The number of ommers in the referenced block. + */ + public Optional getOmmerCount(final long blockNumber) { + return blockchain.getBlockHashByNumber(blockNumber).flatMap(this::getOmmerCount); + } + +@@ -905,41 +924,41 @@ public class BlockchainQueries { + for (long pos = offset; pos <= endOffset; pos++) { + BackendQuery.stopIfExpired(isQueryAlive); + try { + raf.readFully(bloomBuff); + } catch (final EOFException e) { + results.addAll( + matchingLogsUncached( + segmentStart + pos, segmentStart + endOffset, query, isQueryAlive)); + break; + } + final LogsBloomFilter logsBloom = new LogsBloomFilter(bytesValue); + if (query.couldMatch(logsBloom)) { + results.addAll( + matchingLogs( + blockchain.getBlockHashByNumber(segmentStart + pos).orElseThrow(), + query, + isQueryAlive)); + } + } + } catch (final IOException e) { +- e.printStackTrace(System.out); ++ // AERE D-434 (fbfb5f9ecd): removed printStackTrace(System.out) on the cached-log-blooms error path; a cheap malformed log query could otherwise spam the process console, bypassing log4j. LOG.error below records the exception. + LOG.error("Error reading cached log blooms", e); + } + return results; + } + + public List matchingLogs( + final Hash blockHash, final LogsQuery query, final Supplier isQueryAlive) { + try { + final Optional blockHeader = getBlockHeader(blockHash, isQueryAlive); + if (blockHeader.isEmpty()) { + return Collections.emptyList(); + } + // receipts and transactions should exist if the header exists, so throwing is ok. + final List receipts = getReceipts(blockHash, isQueryAlive); + final List transactions = getTransactions(blockHash, isQueryAlive); + final long number = blockHeader.get().getNumber(); + final long blockTimestamp = blockHeader.get().getTimestamp(); + final boolean removed = getRemoved(blockHash, isQueryAlive); + + final AtomicInteger logIndexOffset = new AtomicInteger(); +@@ -998,76 +1017,119 @@ public class BlockchainQueries { + final int transactionIndex = transactionWithMetaData.getTransactionIndex().get(); + final int logIndexOffset = + logIndexOffset( + transactionWithMetaData.getTransaction().getHash(), receipts, transactions); + + return LogWithMetadata.generate( + logIndexOffset, + receipts.get(transactionIndex), + number, + blockHash, + blockTimestamp, + transactions.get(transactionIndex).getHash(), + transactionIndex, + removed); + + } catch (final Exception e) { + throw new RuntimeException(e); + } + } + ++ // AERE D-109 (2026-09-10): the world state of a block that has JUST become the chain head is not ++ // available for a few milliseconds (measured on the live readers: 2-96 ms, occasionally >300 ms) ++ // after its header is; a query resolved against 'latest' in that window used to return ++ // Optional.empty, which JSON-RPC serialises as a bare null - a value Besu never returns otherwise ++ // for eth_getCode/getBalance/getStorageAt/getTransactionCount. Measured directly on a reader: ++ // ~1 in 5,000 'latest' queries, always within a few ms of an import, never for older blocks. So ++ // when the lookup fails for a header at (or within HEAD_WINDOW blocks of) the chain head, we look ++ // again a bounded number of times, with short pauses, before giving up. Older blocks are not ++ // retried: for them an empty result is the state window closing, and a retry would only add latency. ++ private static final long AERE_HEAD_WINDOW_BLOCKS = 2; ++ private static final long[] AERE_HEAD_STATE_RETRY_PAUSES_MS = {50, 100, 150, 300}; ++ ++ + /** + * Wraps an operation on MutableWorldState with try-with-resources the corresponding block hash. + * This method provides access to the worldstate via a mapper function in order to ensure all uses + * of the MutableWorldState are subsequently closed, via the try-with-resources block. + * + * @param return type of the operation on the MutableWorldState + * @param blockHash the block hash + * @param mapper Function which performs an operation on a MutableWorldState + * @return the world state at the block number + */ + public Optional getAndMapWorldState( + final Hash blockHash, final Function> mapper) { + + return blockchain + .getBlockHeader(blockHash) + .flatMap( + blockHeader -> { +- try (var ws = +- worldStateArchive +- .getWorldState(withBlockHeaderAndNoUpdateNodeHead(blockHeader)) +- .orElse(null)) { +- if (ws != null) { +- return mapper.apply(ws); ++ int attempts = 0; ++ while (true) { ++ try (var ws = ++ worldStateArchive ++ .getWorldState(withBlockHeaderAndNoUpdateNodeHead(blockHeader)) ++ .orElse(null)) { ++ if (ws != null) { ++ if (attempts > 0) { ++ LOG.info( ++ "AERE-D109: world state for {} became available after {} retr{}", ++ blockHeader.toLogString(), ++ attempts, ++ attempts == 1 ? "y" : "ies"); ++ } ++ return mapper.apply(ws); ++ } ++ } catch (Exception ex) { ++ LOG.error( ++ "failed worldstate query for " + blockHash.getBytes().toShortHexString(), ex); ++ return Optional.empty(); ++ } ++ if (!aereShouldRetryHeadState(blockHeader, attempts)) { ++ break; ++ } ++ try { ++ Thread.sleep(AERE_HEAD_STATE_RETRY_PAUSES_MS[attempts]); ++ } catch (InterruptedException ie) { ++ Thread.currentThread().interrupt(); ++ break; + } +- } catch (Exception ex) { +- LOG.error( +- "failed worldstate query for " + blockHash.getBytes().toShortHexString(), ex); ++ attempts++; + } + LOG.atDebug() + .setMessage("Failed to find worldstate for {}") + .addArgument(blockHeader.toLogString()) + .log(); + return Optional.empty(); + }); + } + ++ // AERE D-109: retry only near the head, and only a bounded number of times. ++ boolean aereShouldRetryHeadState(final BlockHeader blockHeader, final int attempts) { ++ if (attempts >= AERE_HEAD_STATE_RETRY_PAUSES_MS.length) { ++ return false; ++ } ++ final long head = blockchain.getChainHeadBlockNumber(); ++ return head - blockHeader.getNumber() <= AERE_HEAD_WINDOW_BLOCKS; ++ } ++ + /** + * Wraps an operation on MutableWorldState with try-with-resources the corresponding block number + * + * @param return type of the operation on the MutableWorldState + * @param blockNumber the block number + * @param mapper Function which performs an operation on a MutableWorldState returning type U + * @return the world state at the block number + */ + public Optional getAndMapWorldState( + final long blockNumber, final Function> mapper) { + final Hash blockHash = + getBlockHeaderByNumber(blockNumber).map(BlockHeader::getHash).orElse(Hash.EMPTY); + return getAndMapWorldState(blockHash, mapper); + } + + public Wei gasPrice() { + final Block chainHeadBlock = blockchain.getChainHeadBlock(); + final var chainHeadHeader = chainHeadBlock.getHeader(); + final long blockHeight = chainHeadHeader.getNumber(); + +diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AereStateUnavailableIsAnErrorTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AereStateUnavailableIsAnErrorTest.java +new file mode 100755 +index 0000000000..d2caccd124 +--- /dev/null ++++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AereStateUnavailableIsAnErrorTest.java +@@ -0,0 +1,138 @@ ++/* ++ * Copyright contributors to Hyperledger Besu. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++import static org.mockito.ArgumentMatchers.any; ++import static org.mockito.Mockito.mock; ++import static org.mockito.Mockito.when; ++ ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.datatypes.Hash; ++import org.hyperledger.besu.datatypes.Wei; ++import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; ++import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; ++import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; ++import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; ++import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; ++import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; ++import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; ++import org.hyperledger.besu.ethereum.core.BlockHeader; ++import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; ++ ++import java.util.Optional; ++ ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.units.bigints.UInt256; ++import org.junit.jupiter.api.BeforeEach; ++import org.junit.jupiter.api.Test; ++ ++/** ++ * AERE D-FAZA2-04: when the world state for the requested block is not available, the four state ++ * methods answer with the WORLD_STATE_UNAVAILABLE error, never with a bare null (or a nonce of 0). ++ * When the state IS available they answer as before. ++ */ ++public class AereStateUnavailableIsAnErrorTest { ++ ++ private static final Address ADDR = Address.fromHexString("0x1111111111111111111111111111111111111111"); ++ private static final Hash BLOCK_HASH = Hash.fromHexStringLenient("0xabcd"); ++ private static final long HEAD = 1000L; ++ ++ private BlockchainQueries queries; ++ ++ @BeforeEach ++ public void setUp() { ++ queries = mock(BlockchainQueries.class); ++ // the numeric block parameter path: number -> hash ++ when(queries.headBlockNumber()).thenReturn(HEAD); ++ when(queries.getBlockHashByNumber(HEAD)).thenReturn(Optional.of(BLOCK_HASH)); ++ final BlockHeader header = mock(BlockHeader.class); ++ when(header.getBlockHash()).thenReturn(BLOCK_HASH); ++ when(queries.getBlockHeaderByNumber(HEAD)).thenReturn(Optional.of(header)); ++ when(queries.getBlockHeaderByHash(BLOCK_HASH)).thenReturn(Optional.of(header)); ++ } ++ ++ private static JsonRpcRequestContext request(final String method, final Object... params) { ++ return new JsonRpcRequestContext(new JsonRpcRequest("2.0", method, params)); ++ } ++ ++ private static void assertWorldStateUnavailable(final JsonRpcResponse response) { ++ assertThat(response).isInstanceOf(JsonRpcErrorResponse.class); ++ assertThat(((JsonRpcErrorResponse) response).getErrorType()) ++ .isEqualTo(RpcErrorType.WORLD_STATE_UNAVAILABLE); ++ } ++ ++ private static Object result(final JsonRpcResponse response) { ++ assertThat(response).isInstanceOf(JsonRpcSuccessResponse.class); ++ return ((JsonRpcSuccessResponse) response).getResult(); ++ } ++ ++ @Test ++ public void getCodeWithoutStateIsAnError() { ++ when(queries.getCode(any(Address.class), any(Hash.class))).thenReturn(Optional.empty()); ++ final EthGetCode method = new EthGetCode(queries); ++ assertWorldStateUnavailable(method.response(request("eth_getCode", ADDR.toHexString(), "0x3e8"))); ++ } ++ ++ @Test ++ public void getCodeWithStateAnswersAsBefore() { ++ when(queries.getCode(any(Address.class), any(Hash.class))).thenReturn(Optional.of(Bytes.fromHexString("0x6001"))); ++ final EthGetCode method = new EthGetCode(queries); ++ assertThat(result(method.response(request("eth_getCode", ADDR.toHexString(), "0x3e8")))).isEqualTo("0x6001"); ++ } ++ ++ @Test ++ public void getBalanceWithoutStateIsAnError() { ++ when(queries.accountBalance(any(Address.class), any(Hash.class))).thenReturn(Optional.empty()); ++ final EthGetBalance method = new EthGetBalance(queries); ++ assertWorldStateUnavailable(method.response(request("eth_getBalance", ADDR.toHexString(), "0x3e8"))); ++ } ++ ++ @Test ++ public void getBalanceWithStateAnswersAsBefore() { ++ when(queries.accountBalance(any(Address.class), any(Hash.class))).thenReturn(Optional.of(Wei.of(7))); ++ final EthGetBalance method = new EthGetBalance(queries); ++ assertThat(result(method.response(request("eth_getBalance", ADDR.toHexString(), "0x3e8")))).isEqualTo("0x7"); ++ } ++ ++ @Test ++ public void getStorageAtWithoutStateIsAnError() { ++ when(queries.storageAt(any(Address.class), any(UInt256.class), any(Hash.class))).thenReturn(Optional.empty()); ++ final EthGetStorageAt method = new EthGetStorageAt(queries); ++ assertWorldStateUnavailable(method.response(request("eth_getStorageAt", ADDR.toHexString(), "0x0", "0x3e8"))); ++ } ++ ++ @Test ++ public void getStorageAtWithStateAnswersAsBefore() { ++ when(queries.storageAt(any(Address.class), any(UInt256.class), any(Hash.class))).thenReturn(Optional.of(UInt256.valueOf(5))); ++ final EthGetStorageAt method = new EthGetStorageAt(queries); ++ assertThat(result(method.response(request("eth_getStorageAt", ADDR.toHexString(), "0x0", "0x3e8")))) ++ .isEqualTo(UInt256.valueOf(5).toHexString()); ++ } ++ ++ @Test ++ public void getTransactionCountWithoutStateIsAnErrorNotZero() { ++ when(queries.getTransactionCountIfStateAvailable(any(Address.class), any(Hash.class))).thenReturn(Optional.empty()); ++ final EthGetTransactionCount method = new EthGetTransactionCount(queries, mock(TransactionPool.class)); ++ assertWorldStateUnavailable(method.response(request("eth_getTransactionCount", ADDR.toHexString(), "0x3e8"))); ++ } ++ ++ @Test ++ public void getTransactionCountWithStateAnswersAsBefore() { ++ when(queries.getTransactionCountIfStateAvailable(any(Address.class), any(Hash.class))).thenReturn(Optional.of(3L)); ++ final EthGetTransactionCount method = new EthGetTransactionCount(queries, mock(TransactionPool.class)); ++ assertThat(result(method.response(request("eth_getTransactionCount", ADDR.toHexString(), "0x3e8")))).isEqualTo("0x3"); ++ } ++} +diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/AereHeadStateRetryTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/AereHeadStateRetryTest.java +new file mode 100755 +index 0000000000..33be192f65 +--- /dev/null ++++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/AereHeadStateRetryTest.java +@@ -0,0 +1,140 @@ ++/* ++ * Copyright contributors to Hyperledger Besu. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.ethereum.api.query; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++import static org.mockito.ArgumentMatchers.any; ++import static org.mockito.Mockito.mock; ++import static org.mockito.Mockito.times; ++import static org.mockito.Mockito.verify; ++import static org.mockito.Mockito.when; ++ ++import org.hyperledger.besu.datatypes.Hash; ++import org.hyperledger.besu.ethereum.chain.Blockchain; ++import org.hyperledger.besu.ethereum.core.BlockHeader; ++import org.hyperledger.besu.ethereum.core.MiningConfiguration; ++import org.hyperledger.besu.ethereum.core.MutableWorldState; ++import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; ++import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; ++import org.hyperledger.besu.ethereum.trie.pathbased.common.provider.WorldStateQueryParams; ++ ++import java.util.Optional; ++ ++import org.junit.jupiter.api.Test; ++ ++/** ++ * AERE D-109: a query against a block that has just become the chain head can find no world state ++ * for a few milliseconds. {@link BlockchainQueries#getAndMapWorldState(Hash, java.util.function.Function)} ++ * must look again (a bounded number of times) near the head, and must NOT retry for old blocks, ++ * where an empty result is the state window closing. ++ */ ++public class AereHeadStateRetryTest { ++ ++ private static final Hash HASH = Hash.fromHexStringLenient("0x1234"); ++ ++ private static BlockHeader headerAt(final long number) { ++ final BlockHeader header = mock(BlockHeader.class); ++ when(header.getNumber()).thenReturn(number); ++ when(header.getHash()).thenReturn(HASH); ++ when(header.getBlockHash()).thenReturn(HASH); ++ when(header.getStateRoot()).thenReturn(Hash.EMPTY_TRIE_HASH); ++ when(header.getParentHash()).thenReturn(Hash.ZERO); ++ when(header.toLogString()).thenReturn("#" + number); ++ return header; ++ } ++ ++ private static BlockchainQueries queries( ++ final Blockchain blockchain, final WorldStateArchive archive) { ++ return new BlockchainQueries( ++ mock(ProtocolSchedule.class), blockchain, archive, MiningConfiguration.newDefault()); ++ } ++ ++ @Test ++ public void headBlockStateThatAppearsOnSecondLookIsReturned() { ++ final Blockchain blockchain = mock(Blockchain.class); ++ final WorldStateArchive archive = mock(WorldStateArchive.class); ++ final BlockHeader head = headerAt(1000); ++ when(blockchain.getBlockHeader(HASH)).thenReturn(Optional.of(head)); ++ when(blockchain.getChainHeadBlockNumber()).thenReturn(1000L); ++ final MutableWorldState ws = mock(MutableWorldState.class); ++ when(archive.getWorldState(any(WorldStateQueryParams.class))) ++ .thenReturn(Optional.empty()) ++ .thenReturn(Optional.of(ws)); ++ ++ final Optional result = ++ queries(blockchain, archive).getAndMapWorldState(HASH, w -> Optional.of("ok")); ++ ++ assertThat(result).contains("ok"); ++ verify(archive, times(2)).getWorldState(any(WorldStateQueryParams.class)); ++ } ++ ++ @Test ++ public void oldBlockWithoutStateIsNotRetried() { ++ // negative control: an old block gets exactly ONE look, and an empty answer stays empty ++ final Blockchain blockchain = mock(Blockchain.class); ++ final WorldStateArchive archive = mock(WorldStateArchive.class); ++ final BlockHeader old = headerAt(1000); ++ when(blockchain.getBlockHeader(HASH)).thenReturn(Optional.of(old)); ++ when(blockchain.getChainHeadBlockNumber()).thenReturn(5000L); ++ when(archive.getWorldState(any(WorldStateQueryParams.class))).thenReturn(Optional.empty()); ++ ++ final Optional result = ++ queries(blockchain, archive).getAndMapWorldState(HASH, w -> Optional.of("ok")); ++ ++ assertThat(result).isEmpty(); ++ verify(archive, times(1)).getWorldState(any(WorldStateQueryParams.class)); ++ } ++ ++ @Test ++ public void headBlockThatNeverGetsStateStopsAfterBoundedRetries() { ++ // the retry is bounded: a head block that never gets its state is asked 1 + 4 times, then empty ++ final Blockchain blockchain = mock(Blockchain.class); ++ final WorldStateArchive archive = mock(WorldStateArchive.class); ++ final BlockHeader head = headerAt(1000); ++ when(blockchain.getBlockHeader(HASH)).thenReturn(Optional.of(head)); ++ when(blockchain.getChainHeadBlockNumber()).thenReturn(1001L); ++ when(archive.getWorldState(any(WorldStateQueryParams.class))).thenReturn(Optional.empty()); ++ ++ final long t0 = System.nanoTime(); ++ final Optional result = ++ queries(blockchain, archive).getAndMapWorldState(HASH, w -> Optional.of("ok")); ++ final long elapsedMs = (System.nanoTime() - t0) / 1_000_000; ++ ++ assertThat(result).isEmpty(); ++ verify(archive, times(5)).getWorldState(any(WorldStateQueryParams.class)); ++ // 50 + 100 + 150 + 300 ms of pauses, and nothing unbounded ++ assertThat(elapsedMs).isBetween(550L, 5000L); ++ } ++ ++ @Test ++ public void stateFoundOnFirstLookIsReturnedWithoutWaiting() { ++ final Blockchain blockchain = mock(Blockchain.class); ++ final WorldStateArchive archive = mock(WorldStateArchive.class); ++ final BlockHeader head = headerAt(1000); ++ when(blockchain.getBlockHeader(HASH)).thenReturn(Optional.of(head)); ++ when(blockchain.getChainHeadBlockNumber()).thenReturn(1000L); ++ when(archive.getWorldState(any(WorldStateQueryParams.class))) ++ .thenReturn(Optional.of(mock(MutableWorldState.class))); ++ ++ final long t0 = System.nanoTime(); ++ final Optional result = ++ queries(blockchain, archive).getAndMapWorldState(HASH, w -> Optional.of("ok")); ++ final long elapsedMs = (System.nanoTime() - t0) / 1_000_000; ++ ++ assertThat(result).contains("ok"); ++ verify(archive, times(1)).getWorldState(any(WorldStateQueryParams.class)); ++ assertThat(elapsedMs).isLessThan(50L); ++ } ++} +diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java +index e765d882f2..3acaea6ba6 100644 +--- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java ++++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java +@@ -1,47 +1,39 @@ + /* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 +- */ +- +-/* +- * Modifications Copyright 2026 Aere Network. + * +- * This file was changed by Aere Network: the futureEips milestone is based on +- * osakaDefinition instead of amsterdamDefinition, so that the AERE activation at +- * block 9,189,161 keeps the Osaka block format, and EIP-2935 (historical block +- * hashes in the system contract) is enabled in that same milestone. Nothing +- * upstream was removed; the unmodified original is Hyperledger Besu commit +- * d2032017bb3b8cb215a97303980a1e4a643f7180, and the upstream copyright header +- * above is left exactly as it was found. ++ * Modifications Copyright contributors to the Aere Network. + * +- * This notice is required by Apache License 2.0 section 4(b). ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/0005-aere-eip2935-futureeips.patch. + */ + package org.hyperledger.besu.ethereum.mainnet; + + import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.AMSTERDAM; + import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.ARROW_GLACIER; + import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.BERLIN; + import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.BPO1; + import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.BPO2; + import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.BPO3; + import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.BPO4; + import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.BPO5; + import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.BYZANTIUM; + import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.CANCUN; + import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.CONSTANTINOPLE; + import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.DAO_RECOVERY_INIT; + import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.DAO_RECOVERY_TRANSITION; + import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.EXPERIMENTAL_EIPS; + import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.FRONTIER; + import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.FUTURE_EIPS; + import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.GRAY_GLACIER; +@@ -1347,40 +1339,52 @@ public abstract class MainnetProtocolSpecs { + // the post-activation block format IDENTICAL to Osaka and adds ONLY the two + // AERE features below: (a) the 5 PQC precompiles and (b) EIP-2935. + return osakaDefinition( + chainId, + enableRevertReason, + genesisConfigOptions, + evmConfiguration, + miningConfiguration, + isParallelTxProcessingEnabled, + balConfiguration, + metricsSystem) + // AERE EIP-2935: historical block hashes (ring buffer in the system + // contract at 0x0000f9...2935), wired into the SAME futureEips (AerePQC) + // hard fork as the PQC precompiles so a single futureEipsTime activation + // delivers both. Forced on unconditionally here: the inherited Prague + // definition falls back to FrontierPreExecutionProcessor for QBFT/PoA + // chains without system-contract addresses, which would silently skip + // EIP-2935 history storage. This override restores it, protocol-native. + .preExecutionProcessor(new PraguePreExecutionProcessor()) + .precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::futureEips) ++ // AERE AerePQC fork also activates Block-STM optimistic parallel execution when ++ // AERE_BLOCKSTM=1, so one hard fork delivers PQC + EIP-2935 + parallel exec together. ++ // When unset this reproduces the inherited default builder exactly (live-safe). ++ .blockProcessorBuilder( ++ "1".equals(System.getenv("AERE_BLOCKSTM")) ++ ? new org.hyperledger.besu.ethereum.mainnet.blockstm.AereBlockStmProcessor ++ .AereBlockStmProcessorBuilder(metricsSystem) ++ : (isParallelTxProcessingEnabled ++ ? new org.hyperledger.besu.ethereum.mainnet.parallelization ++ .MainnetParallelBlockProcessor.ParallelBlockProcessorBuilder(metricsSystem) ++ : new org.hyperledger.besu.ethereum.mainnet.MainnetBlockProcessor ++ .MainnetBlockProcessorBuilder(metricsSystem))) + .hardforkId(FUTURE_EIPS); + } + + static ProtocolSpecBuilder experimentalEipsDefinition( + final Optional chainId, + final boolean enableRevertReason, + final GenesisConfigOptions genesisConfigOptions, + final EvmConfiguration evmConfiguration, + final MiningConfiguration miningConfiguration, + final boolean isParallelTxProcessingEnabled, + final BalConfiguration balConfiguration, + final MetricsSystem metricsSystem) { + + return futureEipsDefinition( + chainId, + enableRevertReason, + genesisConfigOptions, + evmConfiguration, + miningConfiguration, + isParallelTxProcessingEnabled, +diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java +old mode 100644 +new mode 100755 +index 4c1d265a80..804f4bed0a +--- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java ++++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java +@@ -1,39 +1,39 @@ + /* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was +- * found, as section 4(c) requires. The change itself is in patches/0006-aere-pq-transactions.patch. ++ * found, as section 4(c) requires. The change itself is in patches/aere-tx-gas-cap-unsigned.patch. + */ + package org.hyperledger.besu.ethereum.mainnet; + + import static org.hyperledger.besu.evm.account.Account.MAX_NONCE; + import static org.hyperledger.besu.evm.internal.Words.clampedAdd; + import static org.hyperledger.besu.evm.worldstate.CodeDelegationHelper.hasCodeDelegation; + + import org.hyperledger.besu.crypto.SECPSignature; + import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; + import org.hyperledger.besu.datatypes.BlobType; + import org.hyperledger.besu.datatypes.CodeDelegation; + import org.hyperledger.besu.datatypes.Hash; + import org.hyperledger.besu.datatypes.TransactionType; + import org.hyperledger.besu.datatypes.Wei; + import org.hyperledger.besu.ethereum.GasLimitCalculator; + import org.hyperledger.besu.ethereum.core.Transaction; + import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; + import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; + import org.hyperledger.besu.evm.account.Account; + import org.hyperledger.besu.evm.gascalculator.GasCalculator; +@@ -99,41 +99,43 @@ public class MainnetTransactionValidator implements TransactionValidator { + validateTransactionSignature(transaction); + if (!signatureResult.isValid()) { + return signatureResult; + } + + final TransactionType transactionType = transaction.getType(); + if (!acceptedTransactionTypes.contains(transactionType)) { + return ValidationResult.invalid( + TransactionInvalidReason.INVALID_TRANSACTION_FORMAT, + String.format( + "Transaction type %s is invalid, accepted transaction types are %s", + transactionType, acceptedTransactionTypes)); + } + + if (!transactionValidationParams.isAllowFutureNonce() && transaction.getNonce() == MAX_NONCE) { + return ValidationResult.invalid( + TransactionInvalidReason.NONCE_OVERFLOW, "Nonce must be less than 2^64-1"); + } + + if (!transactionValidationParams.isAllowExceedingGasLimit() +- && transaction.getGasLimit() > gasLimitCalculator.transactionGasLimitCap()) { ++ // AERE D-432: unsigned, like the intrinsic-gas check below. The decoder reads gasLimit with readLongScalar, so a limit of 2^63 ++ // or more arrives as a negative long, and a signed compare let it through the EIP-7825 cap. ++ && Long.compareUnsigned(transaction.getGasLimit(), gasLimitCalculator.transactionGasLimitCap()) > 0) { + return ValidationResult.invalid( + TransactionInvalidReason.EXCEEDS_TRANSACTION_GAS_LIMIT, + "Transaction gas limit must be at most " + gasLimitCalculator.transactionGasLimitCap()); + } + + if (transactionType.supportsBlob()) { + final ValidationResult blobTransactionResult = + blobsValidator.validate(transaction); + if (!blobTransactionResult.isValid()) { + LOG.debug( + "Blob transaction {} validation failed: {}", + transaction.getHash().getBytes().toHexString(), + blobTransactionResult.getErrorMessage()); + return blobTransactionResult; + } + } + + if (transaction.isContractCreation() && transaction.getPayload().size() > maxInitcodeSize) { + return ValidationResult.invalid( + TransactionInvalidReason.INITCODE_TOO_LARGE, +diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/WithdrawalsValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/WithdrawalsValidator.java +old mode 100644 +new mode 100755 +index 2adda62054..fc04a7c55b +--- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/WithdrawalsValidator.java ++++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/WithdrawalsValidator.java +@@ -1,33 +1,39 @@ + /* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/aere-bft-withdrawals-not-applicable.patch. + */ + package org.hyperledger.besu.ethereum.mainnet; + + import static com.google.common.base.Preconditions.checkArgument; + + import org.hyperledger.besu.datatypes.Hash; + import org.hyperledger.besu.ethereum.core.Block; + import org.hyperledger.besu.ethereum.core.Withdrawal; + + import java.util.List; + import java.util.Optional; + + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + + public interface WithdrawalsValidator { + + boolean validateWithdrawals(Optional> withdrawals); + + boolean validateWithdrawalsRoot(Block block); +@@ -82,31 +88,62 @@ public interface WithdrawalsValidator { + LOG.warn("withdrawalsRoot must not be null when Withdrawals are activated"); + return false; + } + + final List withdrawals = block.getBody().getWithdrawals().get(); + final Hash expectedWithdrawalsRoot = BodyValidation.withdrawalsRoot(withdrawals); + if (!expectedWithdrawalsRoot.equals(withdrawalsRoot.get())) { + LOG.info( + "Invalid block: transaction root mismatch (expected={}, actual={})", + expectedWithdrawalsRoot, + withdrawalsRoot.get()); + return false; + } + + return true; + } + } + + class NotApplicableWithdrawals implements WithdrawalsValidator { + ++ private static final Logger LOG = LoggerFactory.getLogger(NotApplicableWithdrawals.class); ++ ++ // AERE D-433: ported from upstream hyperledger/besu ffe8104ee2 (GHSA-p4h2-gvh4-pv6j) and b7f1387cb4. On a BFT chain a non-empty list is a ++ // Byzantine proposer's injection that WithdrawalsProcessor would credit as native balance on every honest node. + @Override + public boolean validateWithdrawals(final Optional> withdrawals) { ++ // Pre-Shanghai blocks have no withdrawals field (Optional.empty()) - valid. ++ // Shanghai+ blocks must carry an empty list; a non-empty list means a Byzantine ++ // proposer injected unauthorized withdrawals that would be executed as balance credits. ++ if (withdrawals.isPresent() && !withdrawals.get().isEmpty()) { ++ LOG.warn( ++ "Withdrawals not applicable but block contained {} withdrawal(s)", ++ withdrawals.get().size()); ++ return false; ++ } + return true; + } + + @Override + public boolean validateWithdrawalsRoot(final Block block) { ++ final Optional withdrawalsRoot = block.getHeader().getWithdrawalsRoot(); ++ if (withdrawalsRoot.isEmpty()) { ++ return true; // pre-Shanghai block, no withdrawals root field ++ } ++ // A block with a withdrawalsRoot in the header but no withdrawals field in the body is ++ // malformed. ++ if (block.getBody().getWithdrawals().isEmpty()) { ++ LOG.warn( ++ "Invalid block: withdrawalsRoot present in header but withdrawals absent from body"); ++ return false; ++ } ++ if (!Hash.EMPTY_TRIE_HASH.equals(withdrawalsRoot.get())) { ++ LOG.warn( ++ "Invalid block: withdrawals root mismatch (expected={}, actual={})", ++ Hash.EMPTY_TRIE_HASH, ++ withdrawalsRoot.get()); ++ return false; ++ } + return true; + } + } + } +diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/AereBlockStmEngine.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/AereBlockStmEngine.java +new file mode 100644 +index 0000000000..1ef6489405 +--- /dev/null ++++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/AereBlockStmEngine.java +@@ -0,0 +1,528 @@ ++/* ++ * Copyright contributors to AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.ethereum.mainnet.blockstm; ++ ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.datatypes.Hash; ++import org.hyperledger.besu.datatypes.Wei; ++import org.hyperledger.besu.ethereum.ProtocolContext; ++import org.hyperledger.besu.ethereum.core.BlockHeader; ++import org.hyperledger.besu.ethereum.core.MutableWorldState; ++import org.hyperledger.besu.ethereum.core.Transaction; ++import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor; ++import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; ++import org.hyperledger.besu.ethereum.mainnet.block.access.list.BlockAccessList.BlockAccessListBuilder; ++import org.hyperledger.besu.ethereum.mainnet.parallelization.ParallelBlockTransactionProcessor; ++import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; ++import org.hyperledger.besu.ethereum.trie.pathbased.bonsai.worldview.BonsaiWorldState; ++import org.hyperledger.besu.evm.account.Account; ++import org.hyperledger.besu.evm.account.MutableAccount; ++import org.hyperledger.besu.evm.blockhash.BlockHashLookup; ++import org.hyperledger.besu.evm.tracing.OperationTracer; ++import org.hyperledger.besu.evm.worldstate.WorldUpdater; ++import org.hyperledger.besu.plugin.services.metrics.Counter; ++ ++import java.util.ArrayList; ++import java.util.HashMap; ++import java.util.HashSet; ++import java.util.List; ++import java.util.Map; ++import java.util.Optional; ++import java.util.Set; ++import java.util.concurrent.ExecutorService; ++import java.util.concurrent.Executors; ++import java.util.concurrent.TimeUnit; ++import java.util.concurrent.atomic.AtomicBoolean; ++import java.util.concurrent.atomic.AtomicInteger; ++ ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.units.bigints.UInt256; ++import org.slf4j.Logger; ++import org.slf4j.LoggerFactory; ++ ++/** ++ * AERE Block-STM optimistic parallel execution engine, wired into Besu's block-processing ++ * preprocessing hook. Faithful realisation of the AERE Rust Block-STM (Gelashvili et al. 2022): ++ * {@link Scheduler} + {@link MvMemory} drive a worker pool that runs the block's transactions ++ * concurrently against a multi-version world view ({@link MvBaseLayer}/{@link MvAccount}), captures ++ * read/write sets, re-executes conflicting transactions, and yields per-transaction outcomes that ++ * the block processor commits IN BLOCK ORDER — producing a state root bit-identical to sequential ++ * execution. ++ * ++ *

    Safety: any transaction whose parallel outcome is missing, unsuccessful, or produced by a run ++ * that did not reach {@code scheduler.done()} falls back to Besu's sequential execution in the block ++ * loop (see {@link #getProcessingResult}). The engine can never commit an unverified result. ++ */ ++@SuppressWarnings("MissingSummary") ++public class AereBlockStmEngine extends ParallelBlockTransactionProcessor { ++ ++ private static final Logger LOG = LoggerFactory.getLogger(AereBlockStmEngine.class); ++ private static final long PARALLEL_TIMEOUT_SECONDS = 60; ++ ++ private final MainnetTransactionProcessor transactionProcessor; ++ private final int numThreads; ++ ++ // Populated by runAsyncBlock, consumed in block order by getProcessingResult. ++ private volatile MvOutcome[] outcomes; ++ private volatile boolean success = false; ++ private final AtomicInteger totalExecutions = new AtomicInteger(); ++ private final AtomicInteger totalValidations = new AtomicInteger(); ++ private final AtomicInteger totalAborts = new AtomicInteger(); ++ private final AtomicInteger committedParallel = new AtomicInteger(); ++ ++ // Execution-phase instrumentation (see BlockStmStats): snapshotNanos = time to mint the single ++ // parent Bonsai view + flat pre-snapshot wrapper; execPhaseNanos = the PARALLEL EXECUTION PHASE ++ // (worker pool start -> termination) in isolation. Neither includes the downstream serial Bonsai ++ // trie commit, which happens in the block processor after this preprocessing returns. ++ private volatile long snapshotNanos = 0L; ++ private volatile long execPhaseNanos = 0L; ++ ++ /** ++ * @param transactionProcessor the mainnet transaction processor (EVM) ++ * @param numThreads worker-pool size (typically NCPU) ++ */ ++ public AereBlockStmEngine( ++ final MainnetTransactionProcessor transactionProcessor, final int numThreads) { ++ this.transactionProcessor = transactionProcessor; ++ this.numThreads = Math.max(1, numThreads); ++ } ++ ++ /** Per-transaction net outcome captured by the parallel phase. */ ++ private static final class MvOutcome { ++ final Map writes; ++ final Set writeKeys; ++ final List>> storageByAddr; ++ final Map nonceByAddr; // addr -> [nonce] if written ++ final Map balanceByAddr; // addr -> balance if written ++ final Map codeByAddr; // addr -> code if written ++ final Set

    deleted; ++ Wei beneficiaryDelta = Wei.ZERO; ++ TransactionProcessingResult result; ++ ++ MvOutcome() { ++ this.writes = new HashMap<>(); ++ this.writeKeys = new HashSet<>(); ++ this.storageByAddr = new ArrayList<>(); ++ this.nonceByAddr = new HashMap<>(); ++ this.balanceByAddr = new HashMap<>(); ++ this.codeByAddr = new HashMap<>(); ++ this.deleted = new HashSet<>(); ++ } ++ } ++ ++ // ---- shared per-block execution state ---- ++ private MvMemory mv; ++ private Scheduler scheduler; ++ private List txns; ++ private BlockHeader blockHeader; ++ private Address beneficiary; ++ private BlockHashLookup blockHashLookup; ++ private Wei blobGasPrice; ++ private Object[] slotLocks; ++ private Map[] lastReads; ++ private Set[] lastWriteKeys; ++ private final AtomicBoolean hardFail = new AtomicBoolean(false); ++ ++ @Override ++ @SuppressWarnings({"unchecked", "rawtypes"}) ++ public void runAsyncBlock( ++ final ProtocolContext protocolContext, ++ final BlockHeader header, ++ final List transactions, ++ final Address miningBeneficiary, ++ final BlockHashLookup blockHashLookupParam, ++ final Wei blobGasPriceParam, ++ final java.util.concurrent.Executor executorUnused, ++ final Optional blockAccessListBuilder, ++ final Optional maybeParentHeader) { ++ ++ final int n = transactions.size(); ++ outcomes = new MvOutcome[n]; ++ success = false; ++ if (n == 0 || maybeParentHeader.isEmpty()) { ++ return; ++ } ++ ++ // AERE Block-STM Track B: FLAT immutable base pre-snapshot shared lock-free by all workers. ++ // Iteration 1 gave each worker its OWN frozen BonsaiWorldState and re-walked the parent trie on ++ // every base read (task bottleneck #2: per-worker Bonsai-view minting + layered-trie traversal ++ // per read). Here we mint the parent Bonsai view exactly ONCE, wrap it in a FlatBaseSnapshot ++ // that materialises each base value ONCE into an in-memory ConcurrentHashMap, and hand the SAME ++ // snapshot to every worker. Hot-path base reads become lock-free O(1) hashmap lookups with no ++ // trie traversal and no per-worker view. The base state is immutable for the round, so all ++ // workers observe identical parent values and serial equivalence holds (parallelRoot == ++ // sequentialRoot). snapshotNanos captures this one-time mint separately from execPhaseNanos. ++ final long snapT0 = System.nanoTime(); ++ final List openStates = new ArrayList<>(1); ++ try { ++ final BonsaiWorldState ws = ++ getWorldState(protocolContext, maybeParentHeader.get()).orElse(null); ++ if (ws == null) { ++ return; // success stays false -> sequential fallback ++ } ++ ws.disableCacheMerkleTrieLoader(); ++ openStates.add(ws); ++ final BaseReader sharedBase = new FlatBaseSnapshot(ws); ++ this.snapshotNanos = System.nanoTime() - snapT0; ++ ++ this.mv = new MvMemory(); ++ this.scheduler = new Scheduler(n); ++ this.txns = transactions; ++ this.blockHeader = header; ++ this.beneficiary = miningBeneficiary; ++ this.blockHashLookup = blockHashLookupParam; ++ this.blobGasPrice = blobGasPriceParam; ++ this.slotLocks = new Object[n]; ++ this.lastReads = new Map[n]; ++ this.lastWriteKeys = new Set[n]; ++ for (int i = 0; i < n; i++) { ++ slotLocks[i] = new Object(); ++ lastWriteKeys[i] = new HashSet<>(); ++ } ++ hardFail.set(false); ++ ++ // EXECUTION PHASE (timed in isolation from the snapshot mint above and from the downstream ++ // serial Bonsai trie commit that runs after this method returns). All workers share the one ++ // FlatBaseSnapshot; its hot-path reads are lock-free, so distinct-key base reads never contend. ++ final long execT0 = System.nanoTime(); ++ final ExecutorService pool = Executors.newFixedThreadPool(numThreads); ++ try { ++ for (int t = 0; t < numThreads; t++) { ++ pool.execute(() -> worker(sharedBase)); ++ } ++ pool.shutdown(); ++ final boolean finished = pool.awaitTermination(PARALLEL_TIMEOUT_SECONDS, TimeUnit.SECONDS); ++ if (!finished) { ++ pool.shutdownNow(); ++ } ++ this.execPhaseNanos = System.nanoTime() - execT0; ++ success = finished && scheduler.done() && !hardFail.get(); ++ } catch (final InterruptedException ie) { ++ Thread.currentThread().interrupt(); ++ pool.shutdownNow(); ++ this.execPhaseNanos = System.nanoTime() - execT0; ++ success = false; ++ } ++ if (!success) { ++ LOG.info( ++ "AERE Block-STM: parallel phase did not verify (done={}, hardFail={}); block falls back" ++ + " to sequential per-transaction execution", ++ scheduler.done(), ++ hardFail.get()); ++ } ++ } catch (final RuntimeException ex) { ++ LOG.info("AERE Block-STM: parallel preprocessing error; sequential fallback", ex); ++ success = false; ++ } finally { ++ for (final BonsaiWorldState ws : openStates) { ++ try { ++ ws.close(); ++ } catch (final Exception ignored) { ++ // best-effort close ++ } ++ } ++ } ++ } ++ ++ private void worker(final BaseReader base) { ++ try { ++ Scheduler.Task task = scheduler.nextTask(); ++ while (!hardFail.get()) { ++ switch (task.kind()) { ++ case DONE: ++ return; ++ case NO_TASK: ++ task = scheduler.nextTask(); ++ break; ++ case EXECUTION: ++ task = tryExecute(base, task.idx(), task.inc()); ++ break; ++ case VALIDATION: ++ task = tryValidate(task.idx(), task.inc()); ++ break; ++ default: ++ return; ++ } ++ } ++ } catch (final Throwable th) { ++ hardFail.set(true); ++ LOG.debug("AERE Block-STM worker aborted", th); ++ } ++ } ++ ++ private Scheduler.Task tryExecute(final BaseReader base, final int idx, final int inc) { ++ while (true) { ++ if (hardFail.get()) { ++ return Scheduler.Task.NO_TASK; ++ } ++ final MvContext ctx = new MvContext(idx, mv, base, beneficiary); ++ final MvBaseLayer baseLayer = new MvBaseLayer(ctx); ++ final WorldUpdater txUpdater = baseLayer.updater(); ++ totalExecutions.incrementAndGet(); ++ ++ TransactionProcessingResult res = null; ++ try { ++ res = ++ transactionProcessor.processTransaction( ++ txUpdater, ++ blockHeader, ++ txns.get(idx).detachedCopy(), ++ beneficiary, ++ OperationTracer.NO_TRACING, ++ blockHashLookup, ++ TransactionValidationParams.processingBlock(), ++ blobGasPrice, ++ Optional.empty()); ++ } catch (final RuntimeException ex) { ++ if (ctx.blockedOn < 0) { ++ throw ex; // genuine failure -> worker aborts -> sequential fallback ++ } ++ // else: a routed read parked; fall through to dependency handling ++ } ++ ++ if (ctx.blockedOn >= 0) { ++ final int blocking = ctx.blockedOn; ++ if (scheduler.addDependency(idx, blocking)) { ++ return Scheduler.Task.NO_TASK; // parked ++ } ++ continue; // dependency already resolved; re-run same incarnation ++ } ++ ++ final MvOutcome outcome = harvest(ctx, baseLayer, txUpdater, res); ++ final Set prevKeys; ++ synchronized (slotLocks[idx]) { ++ prevKeys = lastWriteKeys[idx]; ++ } ++ final boolean wroteNewPath = mv.applyWriteSet(idx, inc, outcome.writes, prevKeys); ++ synchronized (slotLocks[idx]) { ++ lastReads[idx] = ctx.reads; ++ lastWriteKeys[idx] = outcome.writeKeys; ++ outcomes[idx] = outcome; ++ } ++ return scheduler.finishExecution(idx, inc, wroteNewPath); ++ } ++ } ++ ++ private Scheduler.Task tryValidate(final int idx, final int inc) { ++ totalValidations.incrementAndGet(); ++ final Map reads; ++ synchronized (slotLocks[idx]) { ++ reads = lastReads[idx]; ++ } ++ boolean valid = true; ++ if (reads != null) { ++ for (final Map.Entry e : reads.entrySet()) { ++ final MvMemory.ReadResult now = mv.read(e.getKey(), idx); ++ final boolean matches = !now.isBlocked() && e.getValue().sameProvenance(now.descriptor()); ++ if (!matches) { ++ valid = false; ++ break; ++ } ++ } ++ } ++ final boolean aborted = !valid && scheduler.tryValidationAbort(idx, inc); ++ if (aborted) { ++ totalAborts.incrementAndGet(); ++ final Set keys; ++ synchronized (slotLocks[idx]) { ++ keys = lastWriteKeys[idx]; ++ } ++ if (keys != null) { ++ mv.markEstimates(idx, keys); ++ } ++ } ++ return scheduler.finishValidation(idx, aborted); ++ } ++ ++ private MvOutcome harvest( ++ final MvContext ctx, ++ final MvBaseLayer baseLayer, ++ final WorldUpdater txUpdater, ++ final TransactionProcessingResult res) { ++ final MvOutcome o = new MvOutcome(); ++ o.result = res; ++ ++ for (final Account acct : txUpdater.getTouchedAccounts()) { ++ final Address a = acct.getAddress(); ++ final MvAccount seed = baseLayer.materializedAccount(a); ++ final long seedNonce = seed == null ? 0L : seed.seededNonce(); ++ final Wei seedBalance = seed == null ? Wei.ZERO : seed.seededBalance(); ++ final Hash seedCodeHash = seed == null ? Hash.EMPTY : seed.seededCodeHash(); ++ ++ final long nonce = acct.getNonce(); ++ if (nonce != seedNonce) { ++ o.nonceByAddr.put(a, new long[] {nonce}); ++ final MvKey k = MvKey.nonce(a); ++ o.writes.put(k, Long.valueOf(nonce)); ++ o.writeKeys.add(k); ++ } ++ ++ if (ctx.isBeneficiary(a)) { ++ final Wei bal = acct.getBalance(); ++ o.beneficiaryDelta = bal.subtract(seedBalance); ++ } else { ++ final Wei bal = acct.getBalance(); ++ if (!bal.equals(seedBalance)) { ++ o.balanceByAddr.put(a, bal); ++ final MvKey k = MvKey.balance(a); ++ o.writes.put(k, bal); ++ o.writeKeys.add(k); ++ } ++ } ++ ++ final Hash codeHash = acct.getCodeHash(); ++ if (!codeHash.equals(seedCodeHash)) { ++ final Bytes code = acct.getCode(); ++ o.codeByAddr.put(a, code); ++ final MvKey k = MvKey.code(a); ++ o.writes.put(k, code); ++ o.writeKeys.add(k); ++ } ++ ++ final Map updated = ++ (acct instanceof MutableAccount) ? ((MutableAccount) acct).getUpdatedStorage() : null; ++ if (updated != null && !updated.isEmpty()) { ++ final Map copy = new HashMap<>(updated); ++ o.storageByAddr.add(Map.entry(a, copy)); ++ for (final Map.Entry se : copy.entrySet()) { ++ final MvKey k = MvKey.storage(a, se.getKey()); ++ o.writes.put(k, se.getValue()); ++ o.writeKeys.add(k); ++ } ++ } ++ } ++ ++ for (final Address d : txUpdater.getDeletedAccountAddresses()) { ++ o.deleted.add(d); ++ // reflect clearing in MVMemory so higher transactions read cleared state ++ final MvKey bk = MvKey.balance(d); ++ final MvKey nk = MvKey.nonce(d); ++ final MvKey ck = MvKey.code(d); ++ o.writes.put(bk, Wei.ZERO); ++ o.writes.put(nk, Long.valueOf(0L)); ++ o.writes.put(ck, Bytes.EMPTY); ++ o.writeKeys.add(bk); ++ o.writeKeys.add(nk); ++ o.writeKeys.add(ck); ++ } ++ return o; ++ } ++ ++ /** ++ * Commit phase: called by the block processor in strict block order (location 0..n-1) on the real ++ * world state. Applies transaction {@code location}'s parallel outcome and returns its result, or ++ * empty to request sequential re-execution for this transaction. ++ */ ++ @Override ++ public Optional getProcessingResult( ++ final MutableWorldState worldState, ++ final Address miningBeneficiary, ++ final Transaction transaction, ++ final int location, ++ final Optional confirmedParallelizedTransactionCounter, ++ final Optional conflictingButCachedTransactionCounter) { ++ ++ if (!success || outcomes == null || location >= outcomes.length) { ++ return Optional.empty(); ++ } ++ final MvOutcome o = outcomes[location]; ++ if (o == null || o.result == null || !o.result.isSuccessful()) { ++ return Optional.empty(); ++ } ++ try { ++ final WorldUpdater updater = worldState.updater(); ++ // deletions win over writes for the same address ++ for (final Map.Entry e : o.balanceByAddr.entrySet()) { ++ if (!o.deleted.contains(e.getKey())) { ++ updater.getOrCreate(e.getKey()).setBalance(e.getValue()); ++ } ++ } ++ for (final Map.Entry e : o.nonceByAddr.entrySet()) { ++ if (!o.deleted.contains(e.getKey())) { ++ updater.getOrCreate(e.getKey()).setNonce(e.getValue()[0]); ++ } ++ } ++ for (final Map.Entry e : o.codeByAddr.entrySet()) { ++ if (!o.deleted.contains(e.getKey())) { ++ updater.getOrCreate(e.getKey()).setCode(e.getValue()); ++ } ++ } ++ for (final Map.Entry> e : o.storageByAddr) { ++ if (o.deleted.contains(e.getKey())) { ++ continue; ++ } ++ final MutableAccount ra = updater.getOrCreate(e.getKey()); ++ for (final Map.Entry se : e.getValue().entrySet()) { ++ ra.setStorageValue(se.getKey(), se.getValue()); ++ } ++ } ++ if (!o.beneficiaryDelta.isZero()) { ++ updater.getOrCreate(miningBeneficiary).incrementBalance(o.beneficiaryDelta); ++ } ++ for (final Address d : o.deleted) { ++ updater.deleteAccount(d); ++ } ++ updater.commit(); ++ committedParallel.incrementAndGet(); ++ confirmedParallelizedTransactionCounter.ifPresent(Counter::inc); ++ o.result.setIsProcessedInParallel(Optional.of(Boolean.TRUE)); ++ return Optional.of(o.result); ++ } catch (final RuntimeException ex) { ++ LOG.info("AERE Block-STM: commit of tx {} failed; sequential fallback", location, ex); ++ return Optional.empty(); ++ } ++ } ++ ++ @Override ++ protected org.hyperledger.besu.ethereum.mainnet.parallelization.ParallelizedTransactionContext ++ runTransaction( ++ final ProtocolContext protocolContext, ++ final BlockHeader header, ++ final int transactionLocation, ++ final Transaction transaction, ++ final Address miningBeneficiary, ++ final BlockHashLookup blockHashLookupParam, ++ final Wei blobGasPriceParam, ++ final Optional blockAccessListBuilder, ++ final Optional maybeParentHeader) { ++ // Unused: AERE Block-STM overrides runAsyncBlock wholesale. ++ return null; ++ } ++ ++ /** @return whether the last parallel run verified (reached done with no hard failure). */ ++ public boolean lastRunSucceeded() { ++ return success; ++ } ++ ++ /** @return Block-STM statistics for the last run. */ ++ public BlockStmStats stats() { ++ return new BlockStmStats( ++ outcomes == null ? 0 : outcomes.length, ++ numThreads, ++ totalExecutions.get(), ++ totalValidations.get(), ++ totalAborts.get(), ++ committedParallel.get(), ++ success, ++ snapshotNanos, ++ execPhaseNanos); ++ } ++ ++ /** @return wall-clock nanos of the last parallel EXECUTION PHASE (worker pool only). */ ++ public long execPhaseNanos() { ++ return execPhaseNanos; ++ } ++ ++ /** @return wall-clock nanos spent building the last flat base pre-snapshot. */ ++ public long snapshotNanos() { ++ return snapshotNanos; ++ } ++} +diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/AereBlockStmPreprocessing.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/AereBlockStmPreprocessing.java +new file mode 100644 +index 0000000000..db6562e254 +--- /dev/null ++++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/AereBlockStmPreprocessing.java +@@ -0,0 +1,119 @@ ++/* ++ * Copyright contributors to AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.ethereum.mainnet.blockstm; ++ ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.datatypes.Wei; ++import org.hyperledger.besu.ethereum.ProtocolContext; ++import org.hyperledger.besu.ethereum.core.BlockHeader; ++import org.hyperledger.besu.ethereum.core.Transaction; ++import org.hyperledger.besu.ethereum.mainnet.AbstractBlockProcessor.PreprocessingFunction; ++import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor; ++import org.hyperledger.besu.ethereum.mainnet.block.access.list.BlockAccessList; ++import org.hyperledger.besu.ethereum.mainnet.block.access.list.BlockAccessList.BlockAccessListBuilder; ++import org.hyperledger.besu.ethereum.mainnet.parallelization.PreprocessingContext; ++import org.hyperledger.besu.ethereum.trie.pathbased.common.provider.PathBasedWorldStateProvider; ++import org.hyperledger.besu.evm.blockhash.BlockHashLookup; ++ ++import java.util.List; ++import java.util.Optional; ++ ++import org.slf4j.Logger; ++import org.slf4j.LoggerFactory; ++ ++/** ++ * Preprocessing hook that runs AERE Block-STM optimistic parallel execution over the block's ++ * transactions before the sequential commit loop. Occupies the same {@code PreprocessingFunction} ++ * slot Besu uses for its built-in single-round parallelizer, but drives the AERE multi-version ++ * Block-STM engine instead. A fresh {@link AereBlockStmEngine} is created per block, so no state ++ * leaks between blocks. ++ */ ++@SuppressWarnings("MissingSummary") ++public class AereBlockStmPreprocessing implements PreprocessingFunction { ++ ++ private static final Logger LOG = LoggerFactory.getLogger(AereBlockStmPreprocessing.class); ++ ++ private final MainnetTransactionProcessor transactionProcessor; ++ private final int numThreads; ++ ++ /** ++ * @param transactionProcessor the EVM transaction processor ++ * @param numThreads worker-pool size (typically NCPU) ++ */ ++ public AereBlockStmPreprocessing( ++ final MainnetTransactionProcessor transactionProcessor, final int numThreads) { ++ this.transactionProcessor = transactionProcessor; ++ this.numThreads = numThreads; ++ } ++ ++ @Override ++ public Optional run( ++ final ProtocolContext protocolContext, ++ final BlockHeader blockHeader, ++ final List transactions, ++ final Address miningBeneficiary, ++ final BlockHashLookup blockHashLookup, ++ final Wei blobGasPrice, ++ final Optional blockAccessListBuilder, ++ final Optional maybeBlockBal, ++ final Optional maybeParentHeader) { ++ ++ if (!(protocolContext.getWorldStateArchive() instanceof PathBasedWorldStateProvider)) { ++ // Block-STM multi-version view requires a Bonsai/path-based world state. ++ return Optional.empty(); ++ } ++ ++ final AereBlockStmEngine engine = new AereBlockStmEngine(transactionProcessor, numThreads); ++ engine.runAsyncBlock( ++ protocolContext, ++ blockHeader, ++ transactions, ++ miningBeneficiary, ++ blockHashLookup, ++ blobGasPrice, ++ Runnable::run, ++ blockAccessListBuilder, ++ maybeParentHeader); ++ ++ final BlockStmStats stats = engine.stats(); ++ LOG.debug( ++ "AERE Block-STM block #{}: txns={} threads={} exec={} valid={} aborts={} committedParallel={}" ++ + " verified={}", ++ blockHeader.getNumber(), ++ stats.numTxns(), ++ stats.numThreads(), ++ stats.totalExecutions(), ++ stats.totalValidations(), ++ stats.totalAborts(), ++ stats.committedParallel(), ++ stats.verified()); ++ // Parseable single-line marker for the benchmark harness: the isolated EXECUTION-PHASE nanos ++ // (worker pool only, excludes the flat-snapshot mint AND the downstream serial Bonsai trie ++ // commit) plus the snapshot-mint nanos, per block. Gated on AERE_BLOCKSTM_STATS=1 so it is ++ // silent in normal operation and only emitted during benchmarking. ++ if ("1".equals(System.getenv("AERE_BLOCKSTM_STATS")) && stats.numTxns() > 0) { ++ LOG.info( ++ "AERE-BLOCKSTM-STATS blk={} n={} thr={} execNs={} snapNs={} exec={} aborts={}" ++ + " committedParallel={} verified={}", ++ blockHeader.getNumber(), ++ stats.numTxns(), ++ stats.numThreads(), ++ stats.execPhaseNanos(), ++ stats.snapshotNanos(), ++ stats.totalExecutions(), ++ stats.totalAborts(), ++ stats.committedParallel(), ++ stats.verified()); ++ } ++ ++ return Optional.of(new PreprocessingContext(engine)); ++ } ++} +diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/AereBlockStmProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/AereBlockStmProcessor.java +new file mode 100644 +index 0000000000..db2065a4a6 +--- /dev/null ++++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/AereBlockStmProcessor.java +@@ -0,0 +1,160 @@ ++/* ++ * Copyright contributors to AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.ethereum.mainnet.blockstm; ++ ++import org.hyperledger.besu.datatypes.Wei; ++import org.hyperledger.besu.ethereum.BlockProcessingResult; ++import org.hyperledger.besu.ethereum.ProtocolContext; ++import org.hyperledger.besu.ethereum.chain.Blockchain; ++import org.hyperledger.besu.ethereum.core.Block; ++import org.hyperledger.besu.ethereum.core.MutableWorldState; ++import org.hyperledger.besu.ethereum.mainnet.AbstractBlockProcessor.PreprocessingFunction.NoPreprocessing; ++import org.hyperledger.besu.ethereum.mainnet.AbstractBlockProcessor.TransactionReceiptFactory; ++import org.hyperledger.besu.ethereum.mainnet.BalConfiguration; ++import org.hyperledger.besu.ethereum.mainnet.BlockProcessor; ++import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor; ++import org.hyperledger.besu.ethereum.mainnet.MiningBeneficiaryCalculator; ++import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; ++import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecBuilder; ++import org.hyperledger.besu.ethereum.mainnet.block.access.list.BlockAccessList; ++import org.hyperledger.besu.ethereum.mainnet.parallelization.MainnetParallelBlockProcessor; ++import org.hyperledger.besu.ethereum.trie.pathbased.bonsai.worldview.BonsaiWorldState; ++import org.hyperledger.besu.ethereum.trie.pathbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator; ++import org.hyperledger.besu.plugin.services.MetricsSystem; ++ ++import java.util.Optional; ++ ++import org.slf4j.Logger; ++import org.slf4j.LoggerFactory; ++ ++/** ++ * L1 block processor that executes a block's transactions with AERE Block-STM optimistic parallel ++ * execution, committing in block order to produce a state root bit-identical to sequential ++ * execution. It reuses Besu's parallel consume path ({@link MainnetParallelBlockProcessor}: the ++ * overridden {@code getTransactionProcessingResult} pulls per-transaction results from the ++ * preprocessing context) but swaps Besu's single-round parallelizer for the AERE multi-version ++ * Block-STM engine via {@link AereBlockStmPreprocessing}. ++ * ++ *

    Fork gate: this processor is selected only for the AERE {@code AerePQC} (FUTURE_EIPS) hard fork ++ * and only when {@code AERE_BLOCKSTM=1}, so a single activation delivers PQC precompiles + EIP-2935 ++ * + parallel execution together. On any parallel-phase failure the whole block falls back to ++ * sequential execution, so the processor can never persist an unverified state root. ++ */ ++@SuppressWarnings("MissingSummary") ++public class AereBlockStmProcessor extends MainnetParallelBlockProcessor { ++ ++ private static final Logger LOG = LoggerFactory.getLogger(AereBlockStmProcessor.class); ++ private static final int NCPU = Runtime.getRuntime().availableProcessors(); ++ ++ /** ++ * @param transactionProcessor the EVM transaction processor ++ * @param transactionReceiptFactory receipt factory ++ * @param blockReward block reward ++ * @param miningBeneficiaryCalculator beneficiary calculator ++ * @param skipZeroBlockRewards whether to skip zero rewards ++ * @param protocolSchedule the protocol schedule ++ * @param balConfiguration BAL configuration ++ * @param metricsSystem metrics ++ */ ++ public AereBlockStmProcessor( ++ final MainnetTransactionProcessor transactionProcessor, ++ final TransactionReceiptFactory transactionReceiptFactory, ++ final Wei blockReward, ++ final MiningBeneficiaryCalculator miningBeneficiaryCalculator, ++ final boolean skipZeroBlockRewards, ++ final ProtocolSchedule protocolSchedule, ++ final BalConfiguration balConfiguration, ++ final MetricsSystem metricsSystem) { ++ super( ++ transactionProcessor, ++ transactionReceiptFactory, ++ blockReward, ++ miningBeneficiaryCalculator, ++ skipZeroBlockRewards, ++ protocolSchedule, ++ balConfiguration, ++ metricsSystem); ++ } ++ ++ @Override ++ public BlockProcessingResult processBlock( ++ final ProtocolContext protocolContext, ++ final Blockchain blockchain, ++ final MutableWorldState worldState, ++ final Block block) { ++ return processBlock(protocolContext, blockchain, worldState, block, Optional.empty()); ++ } ++ ++ @Override ++ public BlockProcessingResult processBlock( ++ final ProtocolContext protocolContext, ++ final Blockchain blockchain, ++ final MutableWorldState worldState, ++ final Block block, ++ final Optional blockAccessList) { ++ ++ final BlockProcessingResult result = ++ super.processBlock( ++ protocolContext, ++ blockchain, ++ worldState, ++ block, ++ blockAccessList, ++ new AereBlockStmPreprocessing(transactionProcessor, NCPU)); ++ ++ if (result.isFailed()) { ++ LOG.info( ++ "AERE Block-STM processing failure for block #{} ({}); falling back to sequential", ++ block.getHeader().getNumber(), ++ block.getHash()); ++ if (worldState instanceof BonsaiWorldState) { ++ ((BonsaiWorldStateUpdateAccumulator) worldState.updater()).reset(); ++ } ++ return super.processBlock( ++ protocolContext, blockchain, worldState, block, blockAccessList, new NoPreprocessing()); ++ } ++ return result; ++ } ++ ++ /** Builds {@link AereBlockStmProcessor}, mirroring Besu's parallel builder. */ ++ public static class AereBlockStmProcessorBuilder ++ implements ProtocolSpecBuilder.BlockProcessorBuilder { ++ ++ private final MetricsSystem metricsSystem; ++ ++ /** ++ * @param metricsSystem metrics ++ */ ++ public AereBlockStmProcessorBuilder(final MetricsSystem metricsSystem) { ++ this.metricsSystem = metricsSystem; ++ } ++ ++ @Override ++ public BlockProcessor apply( ++ final MainnetTransactionProcessor transactionProcessor, ++ final TransactionReceiptFactory transactionReceiptFactory, ++ final Wei blockReward, ++ final MiningBeneficiaryCalculator miningBeneficiaryCalculator, ++ final boolean skipZeroBlockRewards, ++ final ProtocolSchedule protocolSchedule, ++ final BalConfiguration balConfiguration) { ++ return new AereBlockStmProcessor( ++ transactionProcessor, ++ transactionReceiptFactory, ++ blockReward, ++ miningBeneficiaryCalculator, ++ skipZeroBlockRewards, ++ protocolSchedule, ++ balConfiguration, ++ metricsSystem); ++ } ++ } ++} +diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/BaseReader.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/BaseReader.java +new file mode 100644 +index 0000000000..2020655ef9 +--- /dev/null ++++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/BaseReader.java +@@ -0,0 +1,67 @@ ++/* ++ * Copyright contributors to AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.ethereum.mainnet.blockstm; ++ ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.datatypes.Wei; ++ ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.units.bigints.UInt256; ++ ++/** ++ * Read-only access to the immutable base (parent-block) world state. A {@code Base} read in ++ * MVMemory falls through to here. Implementations must be safe for concurrent reads (the base state ++ * does not change during block execution). ++ */ ++@SuppressWarnings("MissingSummary") ++public interface BaseReader { ++ ++ /** ++ * Whether the account exists in base state. ++ * ++ * @param address the account ++ * @return true if present ++ */ ++ boolean accountExists(Address address); ++ ++ /** ++ * Base nonce (0 if absent). ++ * ++ * @param address the account ++ * @return nonce ++ */ ++ long getNonce(Address address); ++ ++ /** ++ * Base balance (ZERO if absent). ++ * ++ * @param address the account ++ * @return balance ++ */ ++ Wei getBalance(Address address); ++ ++ /** ++ * Base code (EMPTY if absent). ++ * ++ * @param address the account ++ * @return code ++ */ ++ Bytes getCode(Address address); ++ ++ /** ++ * Base storage slot value (ZERO if absent). ++ * ++ * @param address the account ++ * @param slot the slot ++ * @return value ++ */ ++ UInt256 getStorageValue(Address address, UInt256 slot); ++} +diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/BlockStmStats.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/BlockStmStats.java +new file mode 100644 +index 0000000000..a6a05f00ca +--- /dev/null ++++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/BlockStmStats.java +@@ -0,0 +1,38 @@ ++/* ++ * Copyright contributors to AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.ethereum.mainnet.blockstm; ++ ++/** ++ * Aggregate statistics for one Block-STM run. ++ * ++ * @param numTxns transactions in the block ++ * @param numThreads worker-pool size ++ * @param totalExecutions total incarnations executed (excess over numTxns = re-executions) ++ * @param totalValidations total validation tasks run ++ * @param totalAborts validation failures that triggered re-execution ++ * @param committedParallel transactions committed from a parallel outcome (not sequential fallback) ++ * @param verified whether the run reached scheduler.done() with no hard failure ++ * @param snapshotNanos wall-clock nanos spent building the flat base pre-snapshot (single Bonsai ++ * view mint + wrapper), excluded from the parallel execution phase ++ * @param execPhaseNanos wall-clock nanos of the PARALLEL EXECUTION PHASE only (worker pool start to ++ * termination); excludes both the snapshot build and the downstream serial Bonsai trie commit ++ */ ++@SuppressWarnings("MissingSummary") ++public record BlockStmStats( ++ int numTxns, ++ int numThreads, ++ int totalExecutions, ++ int totalValidations, ++ int totalAborts, ++ int committedParallel, ++ boolean verified, ++ long snapshotNanos, ++ long execPhaseNanos) {} +diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/FlatBaseSnapshot.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/FlatBaseSnapshot.java +new file mode 100644 +index 0000000000..20c3441fca +--- /dev/null ++++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/FlatBaseSnapshot.java +@@ -0,0 +1,165 @@ ++/* ++ * Copyright contributors to AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.ethereum.mainnet.blockstm; ++ ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.datatypes.Wei; ++import org.hyperledger.besu.ethereum.trie.pathbased.bonsai.worldview.BonsaiWorldState; ++import org.hyperledger.besu.evm.account.Account; ++ ++import java.util.Objects; ++import java.util.concurrent.ConcurrentHashMap; ++ ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.units.bigints.UInt256; ++ ++/** ++ * A FLAT, immutable, in-memory pre-snapshot of the parent-block base world state, shared lock-free ++ * by every Block-STM worker. ++ * ++ *

    Iteration-1 gave each worker its OWN frozen {@link BonsaiWorldState} view and routed every base ++ * read through a layered-trie traversal. Two costs dominated cheap-tx blocks and capped scaling on ++ * execution-bound blocks (task bottleneck #2): (1) minting {@code numThreads} BonsaiWorldState ++ * snapshots per block, and (2) re-walking the parent trie on every read, on every worker, on every ++ * re-execution incarnation, even for keys already seen. ++ * ++ *

    This snapshot mints the parent Bonsai view exactly ONCE. Each distinct base value (account ++ * facet triple, or one storage slot) is materialised the first time any worker touches it and cached ++ * in a {@link ConcurrentHashMap}; every subsequent read by any worker/incarnation is a lock-free ++ * O(1) hashmap lookup with no trie traversal. Cold loads (cache misses) route through the single ++ * shared BonsaiWorldState and are serialised on {@link #loadLock} because a BonsaiWorldState is not ++ * safe for concurrent {@code get}; this cold path is one-time-per-key and negligible for ++ * execution-bound workloads, and the hot path is fully lock-free. ++ * ++ *

    Serial-equivalence is preserved: the base state is immutable for the whole parallel round, so ++ * every worker observes identical parent values regardless of load order (parallelRoot == ++ * sequentialRoot). An account is materialised as a whole {@link Shell} (existence + nonce + balance ++ * + code) in one trie hit, so the common pattern of reading several facets of the same account costs ++ * a single traversal. ++ */ ++@SuppressWarnings("MissingSummary") ++final class FlatBaseSnapshot implements BaseReader { ++ ++ /** Immutable materialised account facet triple. */ ++ private static final class Shell { ++ final boolean exists; ++ final long nonce; ++ final Wei balance; ++ final Bytes code; ++ ++ Shell(final boolean exists, final long nonce, final Wei balance, final Bytes code) { ++ this.exists = exists; ++ this.nonce = nonce; ++ this.balance = balance; ++ this.code = code; ++ } ++ } ++ ++ private static final Shell ABSENT = new Shell(false, 0L, Wei.ZERO, Bytes.EMPTY); ++ ++ /** Composite key for a materialised storage slot. */ ++ private static final class SlotKey { ++ private final Address address; ++ private final UInt256 slot; ++ private final int hash; ++ ++ SlotKey(final Address address, final UInt256 slot) { ++ this.address = address; ++ this.slot = slot; ++ this.hash = Objects.hash(address, slot); ++ } ++ ++ @Override ++ public boolean equals(final Object o) { ++ if (this == o) { ++ return true; ++ } ++ if (!(o instanceof SlotKey)) { ++ return false; ++ } ++ final SlotKey k = (SlotKey) o; ++ return address.equals(k.address) && slot.equals(k.slot); ++ } ++ ++ @Override ++ public int hashCode() { ++ return hash; ++ } ++ } ++ ++ private final BonsaiWorldState bws; ++ private final Object loadLock = new Object(); ++ private final ConcurrentHashMap accounts = new ConcurrentHashMap<>(); ++ private final ConcurrentHashMap storage = new ConcurrentHashMap<>(); ++ ++ FlatBaseSnapshot(final BonsaiWorldState bws) { ++ this.bws = bws; ++ } ++ ++ private Shell shell(final Address a) { ++ final Shell hit = accounts.get(a); // lock-free hot path ++ if (hit != null) { ++ return hit; ++ } ++ synchronized (loadLock) { ++ final Shell again = accounts.get(a); ++ if (again != null) { ++ return again; ++ } ++ final Account acct = bws.get(a); ++ final Shell shell = ++ acct == null ++ ? ABSENT ++ : new Shell(true, acct.getNonce(), acct.getBalance(), acct.getCode()); ++ accounts.put(a, shell); ++ return shell; ++ } ++ } ++ ++ @Override ++ public boolean accountExists(final Address address) { ++ return shell(address).exists; ++ } ++ ++ @Override ++ public long getNonce(final Address address) { ++ return shell(address).nonce; ++ } ++ ++ @Override ++ public Wei getBalance(final Address address) { ++ return shell(address).balance; ++ } ++ ++ @Override ++ public Bytes getCode(final Address address) { ++ return shell(address).code; ++ } ++ ++ @Override ++ public UInt256 getStorageValue(final Address address, final UInt256 slot) { ++ final SlotKey key = new SlotKey(address, slot); ++ final UInt256 hit = storage.get(key); // lock-free hot path ++ if (hit != null) { ++ return hit; ++ } ++ synchronized (loadLock) { ++ final UInt256 again = storage.get(key); ++ if (again != null) { ++ return again; ++ } ++ final Account acct = bws.get(address); ++ final UInt256 value = acct == null ? UInt256.ZERO : acct.getStorageValue(slot); ++ storage.put(key, value); ++ return value; ++ } ++ } ++} +diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/MvAccount.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/MvAccount.java +new file mode 100644 +index 0000000000..97feae1227 +--- /dev/null ++++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/MvAccount.java +@@ -0,0 +1,82 @@ ++/* ++ * Copyright contributors to AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.ethereum.mainnet.blockstm; ++ ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.datatypes.Hash; ++import org.hyperledger.besu.datatypes.Wei; ++import org.hyperledger.besu.evm.fluent.SimpleAccount; ++ ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.units.bigints.UInt256; ++ ++/** ++ * An account facade over multi-version memory for a single Block-STM incarnation. Reads of a storage ++ * slot are routed through MVMemory (highest lower-index write, else base), recording the observed ++ * provenance into the execution's read set. Writes buffer in the inherited {@link SimpleAccount} ++ * overlay and are extracted as the write set after execution. ++ */ ++@SuppressWarnings("MissingSummary") ++public class MvAccount extends SimpleAccount { ++ ++ private final MvContext ctx; ++ private final Address addr; ++ ++ // Values this incarnation started from (for write-set diffing). ++ private final long seededNonce; ++ private final Wei seededBalance; ++ private final Hash seededCodeHash; ++ ++ MvAccount( ++ final MvContext ctx, ++ final Address address, ++ final long nonce, ++ final Wei balance, ++ final Bytes code) { ++ super(null, address, nonce, balance, code); ++ this.ctx = ctx; ++ this.addr = address; ++ this.seededNonce = nonce; ++ this.seededBalance = balance; ++ this.seededCodeHash = code == null || code.isEmpty() ? Hash.EMPTY : Hash.hash(code); ++ } ++ ++ @Override ++ public UInt256 getOriginalStorageValue(final UInt256 key) { ++ final MvKey k = MvKey.storage(addr, key); ++ final MvMemory.ReadResult rr = ctx.mv.read(k, ctx.txnIdx); ++ if (rr.isBlocked()) { ++ if (ctx.blockedOn < 0) { ++ ctx.blockedOn = rr.blockingTxn(); ++ } ++ return UInt256.ZERO; ++ } ++ if (!rr.descriptor().isBase()) { ++ ctx.record(k, rr.descriptor()); ++ final Object v = rr.value(); ++ return v == null ? UInt256.ZERO : (UInt256) v; ++ } ++ ctx.record(k, MvMemory.ReadDescriptor.BASE); ++ return ctx.base.getStorageValue(addr, key); ++ } ++ ++ long seededNonce() { ++ return seededNonce; ++ } ++ ++ Wei seededBalance() { ++ return seededBalance; ++ } ++ ++ Hash seededCodeHash() { ++ return seededCodeHash; ++ } ++} +diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/MvBaseLayer.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/MvBaseLayer.java +new file mode 100644 +index 0000000000..bbb54d60c2 +--- /dev/null ++++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/MvBaseLayer.java +@@ -0,0 +1,149 @@ ++/* ++ * Copyright contributors to AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.ethereum.mainnet.blockstm; ++ ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.datatypes.Wei; ++import org.hyperledger.besu.evm.account.Account; ++import org.hyperledger.besu.evm.account.MutableAccount; ++import org.hyperledger.besu.evm.fluent.SimpleWorld; ++ ++import java.util.HashMap; ++import java.util.HashSet; ++import java.util.Map; ++import java.util.Set; ++ ++import org.apache.tuweni.bytes.Bytes; ++ ++/** ++ * The base (bottom) world layer for one Block-STM incarnation. It never holds writes: every EVM ++ * write lands in a child {@link SimpleWorld} layer obtained via {@link #updater()}. On a miss, this ++ * layer materialises an {@link MvAccount} by routing balance/nonce/code reads through MVMemory ++ * (highest lower-index write, else the immutable base state), recording provenance into the read ++ * set. Storage reads route lazily inside {@link MvAccount}. ++ */ ++@SuppressWarnings("MissingSummary") ++public class MvBaseLayer extends SimpleWorld { ++ ++ private final MvContext ctx; ++ private final Map materialized = new HashMap<>(); ++ private final Set

    absent = new HashSet<>(); ++ ++ MvBaseLayer(final MvContext ctx) { ++ super(); ++ this.ctx = ctx; ++ } ++ ++ @Override ++ public Account get(final Address address) { ++ return getAccount(address); ++ } ++ ++ @Override ++ public MutableAccount getAccount(final Address address) { ++ final MvAccount m = materialized.get(address); ++ if (m != null) { ++ return m; ++ } ++ if (absent.contains(address)) { ++ return null; ++ } ++ final MvAccount created = materialize(address); ++ if (created == null) { ++ absent.add(address); ++ return null; ++ } ++ materialized.put(address, created); ++ return created; ++ } ++ ++ /** ++ * The seeded (pre-execution) account, for write-set diffing. ++ * ++ * @param address the account ++ * @return the materialised account, or null if it was absent / freshly created in a child layer ++ */ ++ MvAccount materializedAccount(final Address address) { ++ return materialized.get(address); ++ } ++ ++ private MvAccount materialize(final Address a) { ++ boolean exists = ctx.base.accountExists(a); ++ ++ // balance (beneficiary balance is excluded from conflict tracking) ++ final Wei balance; ++ if (ctx.isBeneficiary(a)) { ++ balance = ctx.base.getBalance(a); ++ } else { ++ final MvKey k = MvKey.balance(a); ++ final MvMemory.ReadResult rr = ctx.mv.read(k, ctx.txnIdx); ++ if (rr.isBlocked()) { ++ block(rr); ++ balance = Wei.ZERO; ++ } else if (!rr.descriptor().isBase()) { ++ ctx.record(k, rr.descriptor()); ++ balance = (Wei) rr.value(); ++ exists = true; ++ } else { ++ ctx.record(k, MvMemory.ReadDescriptor.BASE); ++ balance = ctx.base.getBalance(a); ++ } ++ } ++ ++ // nonce ++ final long nonce; ++ { ++ final MvKey k = MvKey.nonce(a); ++ final MvMemory.ReadResult rr = ctx.mv.read(k, ctx.txnIdx); ++ if (rr.isBlocked()) { ++ block(rr); ++ nonce = 0L; ++ } else if (!rr.descriptor().isBase()) { ++ ctx.record(k, rr.descriptor()); ++ nonce = (Long) rr.value(); ++ exists = true; ++ } else { ++ ctx.record(k, MvMemory.ReadDescriptor.BASE); ++ nonce = ctx.base.getNonce(a); ++ } ++ } ++ ++ // code ++ final Bytes code; ++ { ++ final MvKey k = MvKey.code(a); ++ final MvMemory.ReadResult rr = ctx.mv.read(k, ctx.txnIdx); ++ if (rr.isBlocked()) { ++ block(rr); ++ code = Bytes.EMPTY; ++ } else if (!rr.descriptor().isBase()) { ++ ctx.record(k, rr.descriptor()); ++ code = (Bytes) rr.value(); ++ exists = true; ++ } else { ++ ctx.record(k, MvMemory.ReadDescriptor.BASE); ++ code = ctx.base.getCode(a); ++ } ++ } ++ ++ if (!exists) { ++ // Absent account: reads recorded so a later creating write is caught by validation. ++ return null; ++ } ++ return new MvAccount(ctx, a, nonce, balance, code); ++ } ++ ++ private void block(final MvMemory.ReadResult rr) { ++ if (ctx.blockedOn < 0) { ++ ctx.blockedOn = rr.blockingTxn(); ++ } ++ } ++} +diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/MvContext.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/MvContext.java +new file mode 100644 +index 0000000000..6f1902b421 +--- /dev/null ++++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/MvContext.java +@@ -0,0 +1,55 @@ ++/* ++ * Copyright contributors to AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.ethereum.mainnet.blockstm; ++ ++import org.hyperledger.besu.datatypes.Address; ++ ++import java.util.LinkedHashMap; ++import java.util.Map; ++ ++/** ++ * Per-execution capture state for one incarnation of one transaction. Confined to the single worker ++ * thread executing that incarnation, so it needs no synchronization internally. ++ * ++ *

    Records the read set (key -> observed provenance) for later validation, and the address of the ++ * mining beneficiary, whose balance is excluded from conflict detection (its reward is applied ++ * additively during in-order commit, mirroring Besu's {@code traceBeforeRewardTransaction} trick). ++ */ ++@SuppressWarnings("MissingSummary") ++public final class MvContext { ++ ++ final int txnIdx; ++ final MvMemory mv; ++ final BaseReader base; ++ final Address beneficiary; ++ ++ /** key -> first observed provenance (dedup on key, preserve encounter order). */ ++ final Map reads = new LinkedHashMap<>(); ++ ++ /** set to the blocking txn index (>=0) the first time a read hit an ESTIMATE. */ ++ int blockedOn = -1; ++ ++ MvContext( ++ final int txnIdx, final MvMemory mv, final BaseReader base, final Address beneficiary) { ++ this.txnIdx = txnIdx; ++ this.mv = mv; ++ this.base = base; ++ this.beneficiary = beneficiary; ++ } ++ ++ void record(final MvKey key, final MvMemory.ReadDescriptor desc) { ++ reads.putIfAbsent(key, desc); ++ } ++ ++ boolean isBeneficiary(final Address a) { ++ return beneficiary != null && beneficiary.equals(a); ++ } ++} +diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/MvKey.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/MvKey.java +new file mode 100644 +index 0000000000..b06eecf35c +--- /dev/null ++++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/MvKey.java +@@ -0,0 +1,156 @@ ++/* ++ * Copyright contributors to AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.ethereum.mainnet.blockstm; ++ ++import org.hyperledger.besu.datatypes.Address; ++ ++import java.util.Objects; ++ ++import org.apache.tuweni.units.bigints.UInt256; ++ ++/** ++ * A location in world state that Block-STM tracks for read/write-set conflict detection. Mirrors the ++ * Rust {@code Key} enum (Balance / Storage) generalised to the four EVM account facets that a ++ * transaction can read or write: BALANCE, NONCE, CODE and a STORAGE slot. ++ * ++ *

    This is the unit over which MVMemory shards and over which read-set validation compares ++ * provenance. Two {@code MvKey}s are equal iff they refer to the same facet of the same account (and ++ * same slot for STORAGE). ++ */ ++@SuppressWarnings("MissingSummary") ++public final class MvKey { ++ ++ /** The account facet this key addresses. */ ++ public enum Kind { ++ /** Account balance. */ ++ BALANCE, ++ /** Account nonce. */ ++ NONCE, ++ /** Account code. */ ++ CODE, ++ /** A single storage slot. */ ++ STORAGE ++ } ++ ++ private final Kind kind; ++ private final Address address; ++ private final UInt256 slot; // null unless STORAGE ++ private final int hash; ++ ++ private MvKey(final Kind kind, final Address address, final UInt256 slot) { ++ this.kind = kind; ++ this.address = address; ++ this.slot = slot; ++ this.hash = Objects.hash(kind, address, slot); ++ } ++ ++ /** ++ * Balance key. ++ * ++ * @param address the account ++ * @return the key ++ */ ++ public static MvKey balance(final Address address) { ++ return new MvKey(Kind.BALANCE, address, null); ++ } ++ ++ /** ++ * Nonce key. ++ * ++ * @param address the account ++ * @return the key ++ */ ++ public static MvKey nonce(final Address address) { ++ return new MvKey(Kind.NONCE, address, null); ++ } ++ ++ /** ++ * Code key. ++ * ++ * @param address the account ++ * @return the key ++ */ ++ public static MvKey code(final Address address) { ++ return new MvKey(Kind.CODE, address, null); ++ } ++ ++ /** ++ * Storage-slot key. ++ * ++ * @param address the account ++ * @param slot the slot ++ * @return the key ++ */ ++ public static MvKey storage(final Address address, final UInt256 slot) { ++ return new MvKey(Kind.STORAGE, address, slot); ++ } ++ ++ /** ++ * The facet kind. ++ * ++ * @return kind ++ */ ++ public Kind kind() { ++ return kind; ++ } ++ ++ /** ++ * The account address. ++ * ++ * @return address ++ */ ++ public Address address() { ++ return address; ++ } ++ ++ /** ++ * Deterministic shard index, mirroring the Rust FNV-1a spread. ++ * ++ * @param shards number of shards ++ * @return shard index in [0, shards) ++ */ ++ public int shard(final int shards) { ++ long h = 0xcbf29ce484222325L; ++ h = fnv(h, kind.ordinal() + 1L); ++ h = fnv(h, address.hashCode() & 0xffffffffL); ++ h = fnv(h, slot == null ? 0L : slot.hashCode() & 0xffffffffL); ++ int s = (int) Long.remainderUnsigned(h, shards); ++ return s; ++ } ++ ++ private static long fnv(final long acc, final long b) { ++ long h = acc ^ b; ++ h *= 0x100000001b3L; ++ return h; ++ } ++ ++ @Override ++ public boolean equals(final Object o) { ++ if (this == o) { ++ return true; ++ } ++ if (!(o instanceof MvKey)) { ++ return false; ++ } ++ final MvKey k = (MvKey) o; ++ return kind == k.kind && address.equals(k.address) && Objects.equals(slot, k.slot); ++ } ++ ++ @Override ++ public int hashCode() { ++ return hash; ++ } ++ ++ @Override ++ public String toString() { ++ return kind + "(" + address + (slot == null ? "" : "," + slot.toShortHexString()) + ")"; ++ } ++} +diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/MvMemory.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/MvMemory.java +new file mode 100644 +index 0000000000..914df3a3ad +--- /dev/null ++++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/MvMemory.java +@@ -0,0 +1,266 @@ ++/* ++ * Copyright contributors to AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.ethereum.mainnet.blockstm; ++ ++import java.util.HashMap; ++import java.util.Map; ++import java.util.Set; ++import java.util.TreeMap; ++import java.util.concurrent.locks.ReentrantLock; ++ ++/** ++ * Multi-version shared memory (MVMemory). Faithful Java port of the AERE Rust {@code mvmemory.rs} ++ * (Gelashvili et al. 2022). ++ * ++ *

    For every {@link MvKey}, MVMemory keeps an ordered map {@code txnIndex -> Cell}, where a cell ++ * is either a concrete value written by that transaction's latest incarnation, or an ESTIMATE ++ * placeholder (a marker that a lower transaction previously wrote here but is currently being ++ * re-executed, so its value is not trustworthy). ++ * ++ *

    A read by transaction {@code i} for key {@code k} returns the entry of the HIGHEST transaction ++ * {@code j < i} that wrote {@code k}. That is what makes speculative parallel execution ++ * serial-equivalent: transaction {@code i} always observes the writes of all lower-indexed ++ * transactions that have run, and nothing from higher ones. ++ * ++ *

    Storage is sharded across many independent locks keyed by a hash of the key, so ++ * non-conflicting transactions touch disjoint locks and run without contention. ++ */ ++@SuppressWarnings("MissingSummary") ++public class MvMemory { ++ ++ private static final int SHARDS = 256; ++ ++ /** What a read observed, recorded into the reader's read set for later validation. */ ++ public enum DescKind { ++ /** Nothing below the reader wrote this key: it came from base state. */ ++ BASE, ++ /** It was written by some (txnIndex, incarnation). */ ++ VERSION ++ } ++ ++ /** A read-set descriptor: BASE, or VERSION(txnIndex, incarnation). */ ++ public static final class ReadDescriptor { ++ /** Shared BASE singleton. */ ++ public static final ReadDescriptor BASE = new ReadDescriptor(DescKind.BASE, -1, -1); ++ ++ private final DescKind kind; ++ private final int txnIndex; ++ private final int incarnation; ++ ++ private ReadDescriptor(final DescKind kind, final int txnIndex, final int incarnation) { ++ this.kind = kind; ++ this.txnIndex = txnIndex; ++ this.incarnation = incarnation; ++ } ++ ++ static ReadDescriptor version(final int txnIndex, final int incarnation) { ++ return new ReadDescriptor(DescKind.VERSION, txnIndex, incarnation); ++ } ++ ++ /** @return true if this descriptor is a BASE read. */ ++ public boolean isBase() { ++ return kind == DescKind.BASE; ++ } ++ ++ boolean sameProvenance(final ReadDescriptor other) { ++ if (kind != other.kind) { ++ return false; ++ } ++ if (kind == DescKind.BASE) { ++ return true; ++ } ++ return txnIndex == other.txnIndex && incarnation == other.incarnation; ++ } ++ } ++ ++ /** Live read outcome: OK(descriptor,value) or BLOCKED(blockingTxn). */ ++ public static final class ReadResult { ++ final boolean blocked; ++ final int blockingTxn; ++ final ReadDescriptor descriptor; ++ final Object value; ++ ++ private ReadResult( ++ final boolean blocked, ++ final int blockingTxn, ++ final ReadDescriptor descriptor, ++ final Object value) { ++ this.blocked = blocked; ++ this.blockingTxn = blockingTxn; ++ this.descriptor = descriptor; ++ this.value = value; ++ } ++ ++ static ReadResult ok(final ReadDescriptor d, final Object v) { ++ return new ReadResult(false, -1, d, v); ++ } ++ ++ static ReadResult blocked(final int blockingTxn) { ++ return new ReadResult(true, blockingTxn, null, null); ++ } ++ ++ /** @return true if this read hit an ESTIMATE and the reader must park. */ ++ public boolean isBlocked() { ++ return blocked; ++ } ++ ++ /** @return the blocking txn index (valid iff {@link #isBlocked()}). */ ++ public int blockingTxn() { ++ return blockingTxn; ++ } ++ ++ /** @return the observed provenance descriptor (valid iff not blocked). */ ++ public ReadDescriptor descriptor() { ++ return descriptor; ++ } ++ ++ /** @return the observed value, or null for a BASE read (caller falls back to base state). */ ++ public Object value() { ++ return value; ++ } ++ } ++ ++ private static final class Cell { ++ final boolean estimate; ++ final int incarnation; ++ final Object value; ++ ++ private Cell(final boolean estimate, final int incarnation, final Object value) { ++ this.estimate = estimate; ++ this.incarnation = incarnation; ++ this.value = value; ++ } ++ ++ static Cell value(final int inc, final Object v) { ++ return new Cell(false, inc, v); ++ } ++ ++ static final Cell ESTIMATE = new Cell(true, -1, null); ++ } ++ ++ private final ReentrantLock[] locks = new ReentrantLock[SHARDS]; ++ // shard -> (key -> (txnIndex -> Cell)) ++ private final Map>[] shards; ++ ++ /** New empty MVMemory. */ ++ @SuppressWarnings({"unchecked", "rawtypes"}) ++ public MvMemory() { ++ shards = new Map[SHARDS]; ++ for (int i = 0; i < SHARDS; i++) { ++ locks[i] = new ReentrantLock(); ++ shards[i] = new HashMap<>(); ++ } ++ } ++ ++ /** ++ * Read the value visible to {@code txnIdx}: the highest entry strictly below it. ++ * ++ * @param key the key ++ * @param txnIdx the reading transaction index ++ * @return the read result ++ */ ++ public ReadResult read(final MvKey key, final int txnIdx) { ++ final int s = key.shard(SHARDS); ++ locks[s].lock(); ++ try { ++ final TreeMap versions = shards[s].get(key); ++ if (versions != null) { ++ final Map.Entry e = versions.lowerEntry(txnIdx); ++ if (e != null) { ++ final Cell cell = e.getValue(); ++ if (cell.estimate) { ++ return ReadResult.blocked(e.getKey()); ++ } ++ return ReadResult.ok(ReadDescriptor.version(e.getKey(), cell.incarnation), cell.value); ++ } ++ } ++ return ReadResult.ok(ReadDescriptor.BASE, null); ++ } finally { ++ locks[s].unlock(); ++ } ++ } ++ ++ /** ++ * Install {@code txnIdx}'s new write set (incarnation {@code inc}); remove stale entries the ++ * previous incarnation wrote but this one no longer does. Returns true if the written key-SET ++ * changed (a key added or removed) — Block-STM's "wrote a new path", which triggers revalidation ++ * of the suffix. ++ * ++ * @param txnIdx the writing transaction ++ * @param inc the incarnation ++ * @param writes the new write set ++ * @param prevKeys the keys written by the previous incarnation ++ * @return whether the written key-set changed ++ */ ++ public boolean applyWriteSet( ++ final int txnIdx, ++ final int inc, ++ final Map writes, ++ final Set prevKeys) { ++ for (final Map.Entry w : writes.entrySet()) { ++ final MvKey k = w.getKey(); ++ final int s = k.shard(SHARDS); ++ locks[s].lock(); ++ try { ++ shards[s].computeIfAbsent(k, kk -> new TreeMap<>()).put(txnIdx, Cell.value(inc, w.getValue())); ++ } finally { ++ locks[s].unlock(); ++ } ++ } ++ boolean removedAny = false; ++ for (final MvKey k : prevKeys) { ++ if (!writes.containsKey(k)) { ++ final int s = k.shard(SHARDS); ++ locks[s].lock(); ++ try { ++ final TreeMap versions = shards[s].get(k); ++ if (versions != null) { ++ versions.remove(txnIdx); ++ } ++ } finally { ++ locks[s].unlock(); ++ } ++ removedAny = true; ++ } ++ } ++ boolean addedAny = false; ++ for (final MvKey k : writes.keySet()) { ++ if (!prevKeys.contains(k)) { ++ addedAny = true; ++ break; ++ } ++ } ++ return addedAny || removedAny; ++ } ++ ++ /** ++ * Convert all of {@code txnIdx}'s current writes (over {@code keys}) into ESTIMATE placeholders, ++ * so any concurrent higher transaction that reads one of these keys blocks on {@code txnIdx} ++ * instead of consuming a soon-to-be-wrong value. ++ * ++ * @param txnIdx the aborted transaction ++ * @param keys its written keys ++ */ ++ public void markEstimates(final int txnIdx, final Set keys) { ++ for (final MvKey k : keys) { ++ final int s = k.shard(SHARDS); ++ locks[s].lock(); ++ try { ++ final TreeMap versions = shards[s].get(k); ++ if (versions != null && versions.containsKey(txnIdx)) { ++ versions.put(txnIdx, Cell.ESTIMATE); ++ } ++ } finally { ++ locks[s].unlock(); ++ } ++ } ++ } ++} +diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/Scheduler.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/Scheduler.java +new file mode 100644 +index 0000000000..a967bbd6f3 +--- /dev/null ++++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockstm/Scheduler.java +@@ -0,0 +1,390 @@ ++/* ++ * Copyright contributors to AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.ethereum.mainnet.blockstm; ++ ++import java.util.ArrayList; ++import java.util.Collections; ++import java.util.List; ++import java.util.concurrent.atomic.AtomicBoolean; ++import java.util.concurrent.atomic.AtomicInteger; ++import java.util.concurrent.locks.ReentrantLock; ++ ++/** ++ * The Block-STM collaborative scheduler (Gelashvili et al. 2022, Algorithm 3). Faithful Java port of ++ * the AERE Rust {@code scheduler.rs}. ++ * ++ *

    Hands out EXECUTION and VALIDATION tasks to a worker pool. Two cursors ({@code executionIdx}, ++ * {@code validationIdx}) drive it; validation of a lower index always takes priority over execution ++ * of a higher one. When a transaction aborts or writes a new path, the relevant cursor is decreased ++ * so the affected range is revisited. The block is done when both cursors have passed the end AND no ++ * task is in flight AND no decrease happened during the check. Dependencies are handled without ++ * condvars via parking on the blocker's dependency list. ++ */ ++@SuppressWarnings("MissingSummary") ++public class Scheduler { ++ ++ /** Task type handed to a worker. */ ++ public enum TaskKind { ++ /** Run incarnation {@code inc} of transaction {@code idx}. */ ++ EXECUTION, ++ /** Re-check {@code idx}'s read set. */ ++ VALIDATION, ++ /** No task available right now; retry. */ ++ NO_TASK, ++ /** Block fully executed & validated. */ ++ DONE ++ } ++ ++ /** A unit of work, or a control signal. */ ++ public static final class Task { ++ /** Shared NO_TASK singleton. */ ++ public static final Task NO_TASK = new Task(TaskKind.NO_TASK, -1, -1); ++ /** Shared DONE singleton. */ ++ public static final Task DONE = new Task(TaskKind.DONE, -1, -1); ++ ++ final TaskKind kind; ++ final int idx; ++ final int inc; ++ ++ Task(final TaskKind kind, final int idx, final int inc) { ++ this.kind = kind; ++ this.idx = idx; ++ this.inc = inc; ++ } ++ ++ /** @return the task kind */ ++ public TaskKind kind() { ++ return kind; ++ } ++ ++ /** @return the transaction index */ ++ public int idx() { ++ return idx; ++ } ++ ++ /** @return the incarnation */ ++ public int inc() { ++ return inc; ++ } ++ } ++ ++ private enum StatusKind { ++ READY_TO_EXECUTE, ++ EXECUTING, ++ SUSPENDED, ++ EXECUTED, ++ ABORTING ++ } ++ ++ private static final class Status { ++ StatusKind kind; ++ int inc; ++ ++ Status(final StatusKind kind, final int inc) { ++ this.kind = kind; ++ this.inc = inc; ++ } ++ } ++ ++ private final int numTxns; ++ private final AtomicInteger executionIdx = new AtomicInteger(0); ++ private final AtomicInteger validationIdx = new AtomicInteger(0); ++ private final AtomicInteger decreaseCnt = new AtomicInteger(0); ++ private final AtomicInteger numActiveTasks = new AtomicInteger(0); ++ private final AtomicBoolean done = new AtomicBoolean(false); ++ private final Status[] status; ++ private final ReentrantLock[] statusLocks; ++ private final List[] dependencies; ++ private final ReentrantLock[] depLocks; ++ ++ /** ++ * New scheduler over {@code numTxns} transactions. ++ * ++ * @param numTxns transaction count ++ */ ++ @SuppressWarnings({"unchecked", "rawtypes"}) ++ public Scheduler(final int numTxns) { ++ this.numTxns = numTxns; ++ this.status = new Status[numTxns]; ++ this.statusLocks = new ReentrantLock[numTxns]; ++ this.dependencies = new List[numTxns]; ++ this.depLocks = new ReentrantLock[numTxns]; ++ for (int i = 0; i < numTxns; i++) { ++ status[i] = new Status(StatusKind.READY_TO_EXECUTE, 0); ++ statusLocks[i] = new ReentrantLock(); ++ dependencies[i] = new ArrayList<>(); ++ depLocks[i] = new ReentrantLock(); ++ } ++ } ++ ++ /** @return true once the block is fully executed & validated. */ ++ public boolean done() { ++ return done.get(); ++ } ++ ++ private void decreaseExecutionIdx(final int target) { ++ executionIdx.getAndUpdate(cur -> Math.min(cur, target)); ++ decreaseCnt.incrementAndGet(); ++ } ++ ++ private void decreaseValidationIdx(final int target) { ++ validationIdx.getAndUpdate(cur -> Math.min(cur, target)); ++ decreaseCnt.incrementAndGet(); ++ } ++ ++ private void checkDone() { ++ final int observed = decreaseCnt.get(); ++ if (executionIdx.get() >= numTxns ++ && validationIdx.get() >= numTxns ++ && numActiveTasks.get() == 0 ++ && decreaseCnt.get() == observed) { ++ done.set(true); ++ } ++ } ++ ++ private Task tryIncarnate(final int idx) { ++ if (idx < numTxns) { ++ statusLocks[idx].lock(); ++ try { ++ if (status[idx].kind == StatusKind.READY_TO_EXECUTE) { ++ final int inc = status[idx].inc; ++ status[idx].kind = StatusKind.EXECUTING; ++ return new Task(TaskKind.EXECUTION, idx, inc); ++ } ++ } finally { ++ statusLocks[idx].unlock(); ++ } ++ } ++ numActiveTasks.decrementAndGet(); ++ return null; ++ } ++ ++ private Task nextVersionToExecute() { ++ if (executionIdx.get() >= numTxns) { ++ checkDone(); ++ return null; ++ } ++ numActiveTasks.incrementAndGet(); ++ final int idx = executionIdx.getAndIncrement(); ++ return tryIncarnate(idx); ++ } ++ ++ private Task nextVersionToValidate() { ++ if (validationIdx.get() >= numTxns) { ++ checkDone(); ++ return null; ++ } ++ numActiveTasks.incrementAndGet(); ++ final int idx = validationIdx.getAndIncrement(); ++ if (idx < numTxns) { ++ statusLocks[idx].lock(); ++ try { ++ if (status[idx].kind == StatusKind.EXECUTED) { ++ return new Task(TaskKind.VALIDATION, idx, status[idx].inc); ++ } ++ } finally { ++ statusLocks[idx].unlock(); ++ } ++ } ++ numActiveTasks.decrementAndGet(); ++ return null; ++ } ++ ++ /** ++ * Main entry point workers spin on. ++ * ++ * @return a task, NO_TASK (retry), or DONE ++ */ ++ public Task nextTask() { ++ int idle = 0; ++ while (true) { ++ if (done.get()) { ++ return Task.DONE; ++ } ++ final int v = validationIdx.get(); ++ final int e = executionIdx.get(); ++ Task task = (v < e) ? nextVersionToValidate() : nextVersionToExecute(); ++ if (task == null && v < e) { ++ // The preferred lower-index validation had nothing runnable (its target is still ++ // EXECUTING on another worker). Rather than busy-draining validationIdx while pending ++ // independent EXECUTION tasks sit ungrabbed (which starved real parallel work and made ++ // the execution phase anti-scale with worker count), try to grab a pending execution. ++ // This is scheduling-order only: executing any READY incarnation in any order is already ++ // permitted by Block-STM, and read-set validation still re-checks and re-executes on any ++ // conflict, so the committed result stays bit-identical to sequential. ++ task = nextVersionToExecute(); ++ } ++ if (task != null) { ++ return task; ++ } ++ if (done.get()) { ++ return Task.DONE; ++ } ++ // Nothing runnable right now: back off so idle workers stop ping-ponging the shared ++ // cursors/locks across cores (that cache-line contention slows the workers doing real ++ // execution). Pure CPU hint / brief park; does not alter task selection or ordering. ++ if (++idle < 128) { ++ Thread.onSpinWait(); ++ } else { ++ java.util.concurrent.locks.LockSupport.parkNanos(Math.min((idle - 127) * 512L, 50_000L)); ++ } ++ } ++ } ++ ++ /** ++ * Register that {@code idx} depends on {@code blocking} (it read {@code blocking}'s ESTIMATE). ++ * ++ * @param idx the reader ++ * @param blocking the blocker ++ * @return true if {@code idx} was parked (caller drops the task); false if {@code blocking} ++ * already finished (caller re-executes {@code idx}) ++ */ ++ public boolean addDependency(final int idx, final int blocking) { ++ statusLocks[blocking].lock(); ++ try { ++ if (status[blocking].kind == StatusKind.EXECUTED) { ++ return false; ++ } ++ depLocks[blocking].lock(); ++ try { ++ dependencies[blocking].add(idx); ++ } finally { ++ depLocks[blocking].unlock(); ++ } ++ statusLocks[idx].lock(); ++ try { ++ if (status[idx].kind == StatusKind.EXECUTING) { ++ status[idx].kind = StatusKind.SUSPENDED; ++ } ++ } finally { ++ statusLocks[idx].unlock(); ++ } ++ } finally { ++ statusLocks[blocking].unlock(); ++ } ++ numActiveTasks.decrementAndGet(); ++ return true; ++ } ++ ++ private void resume(final int idx) { ++ statusLocks[idx].lock(); ++ try { ++ if (status[idx].kind == StatusKind.SUSPENDED) { ++ status[idx].kind = StatusKind.READY_TO_EXECUTE; ++ } ++ } finally { ++ statusLocks[idx].unlock(); ++ } ++ } ++ ++ private void setReadyAfterAbort(final int idx) { ++ statusLocks[idx].lock(); ++ try { ++ if (status[idx].kind == StatusKind.ABORTING) { ++ status[idx].kind = StatusKind.READY_TO_EXECUTE; ++ status[idx].inc = status[idx].inc + 1; ++ } ++ } finally { ++ statusLocks[idx].unlock(); ++ } ++ } ++ ++ private void setExecuted(final int idx, final int inc) { ++ statusLocks[idx].lock(); ++ try { ++ status[idx].kind = StatusKind.EXECUTED; ++ status[idx].inc = inc; ++ } finally { ++ statusLocks[idx].unlock(); ++ } ++ } ++ ++ /** ++ * Called after an execution task completes. ++ * ++ * @param idx transaction ++ * @param inc incarnation ++ * @param wroteNewPath whether the written key-set changed vs the previous incarnation ++ * @return a follow-up task (inheriting the active-task unit) or NO_TASK (releasing it) ++ */ ++ public Task finishExecution(final int idx, final int inc, final boolean wroteNewPath) { ++ setExecuted(idx, inc); ++ ++ final List deps; ++ depLocks[idx].lock(); ++ try { ++ deps = new ArrayList<>(dependencies[idx]); ++ dependencies[idx].clear(); ++ } finally { ++ depLocks[idx].unlock(); ++ } ++ if (!deps.isEmpty()) { ++ final int minDep = Collections.min(deps); ++ for (final int d : deps) { ++ resume(d); ++ } ++ decreaseExecutionIdx(minDep); ++ } ++ ++ if (validationIdx.get() > idx) { ++ if (wroteNewPath) { ++ decreaseValidationIdx(idx); ++ numActiveTasks.decrementAndGet(); ++ return Task.NO_TASK; ++ } else { ++ return new Task(TaskKind.VALIDATION, idx, inc); ++ } ++ } else { ++ numActiveTasks.decrementAndGet(); ++ return Task.NO_TASK; ++ } ++ } ++ ++ /** ++ * Attempt to win the right to abort {@code idx} at {@code inc}. ++ * ++ * @param idx transaction ++ * @param inc incarnation ++ * @return true iff this caller flipped EXECUTED(inc) -> ABORTING(inc) ++ */ ++ public boolean tryValidationAbort(final int idx, final int inc) { ++ statusLocks[idx].lock(); ++ try { ++ if (status[idx].kind == StatusKind.EXECUTED && status[idx].inc == inc) { ++ status[idx].kind = StatusKind.ABORTING; ++ return true; ++ } ++ return false; ++ } finally { ++ statusLocks[idx].unlock(); ++ } ++ } ++ ++ /** ++ * Called after a validation task. ++ * ++ * @param idx transaction ++ * @param aborted whether validation failed AND this caller won {@link #tryValidationAbort} ++ * @return a follow-up execution task (inheriting the active-task unit) or NO_TASK (releasing it) ++ */ ++ public Task finishValidation(final int idx, final boolean aborted) { ++ if (aborted) { ++ setReadyAfterAbort(idx); ++ decreaseValidationIdx(idx + 1); ++ if (executionIdx.get() > idx) { ++ final Task t = tryIncarnate(idx); ++ return t == null ? Task.NO_TASK : t; ++ } ++ } ++ numActiveTasks.decrementAndGet(); ++ return Task.NO_TASK; ++ } ++} +diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AereD432GasCapUnsignedTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AereD432GasCapUnsignedTest.java +new file mode 100644 +index 0000000000..7dcf917525 +--- /dev/null ++++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AereD432GasCapUnsignedTest.java +@@ -0,0 +1,103 @@ ++/* ++ * Copyright contributors to Besu. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Aere Network notice (Apache-2.0 section 4(b)): this file was added by Aere Network, 2026-09-28 (D-432). ++ */ ++package org.hyperledger.besu.ethereum.mainnet; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++ ++import org.hyperledger.besu.crypto.KeyPair; ++import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.datatypes.BlobType; ++import org.hyperledger.besu.datatypes.TransactionType; ++import org.hyperledger.besu.datatypes.Wei; ++import org.hyperledger.besu.ethereum.GasLimitCalculator; ++import org.hyperledger.besu.ethereum.core.Transaction; ++import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; ++import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; ++import org.hyperledger.besu.evm.gascalculator.OsakaGasCalculator; ++ ++import java.math.BigInteger; ++import java.util.Optional; ++import java.util.Set; ++ ++import org.apache.tuweni.bytes.Bytes; ++import org.junit.jupiter.api.Test; ++ ++/** ++ * AERE D-432: the EIP-7825 transaction gas cap is compared UNSIGNED. The decoder reads gasLimit with readLongScalar, so a limit ++ * of 2^63 or more is a negative long here; a signed compare let it through the cap, while the second client refuses it at ++ * decoding. Found by the AIP-20 differential fuzzer (aips/aip20-conformitate/fuzz-pqtx). ++ */ ++class AereD432GasCapUnsignedTest { ++ ++ private static final long CAP = 1L << 24; ++ private static final BigInteger CHAIN = BigInteger.valueOf(28001); ++ private static final KeyPair KEYS = SignatureAlgorithmFactory.getInstance().generateKeyPair(); ++ ++ private static MainnetTransactionValidator validator() { ++ final GasLimitCalculator glc = ++ new GasLimitCalculator() { ++ @Override ++ public long nextGasLimit(final long currentGasLimit, final long targetGasLimit, final long newBlockNumber) { ++ return currentGasLimit; ++ } ++ ++ @Override ++ public long transactionGasLimitCap() { ++ return CAP; ++ } ++ }; ++ return new MainnetTransactionValidator( ++ new OsakaGasCalculator(), glc, FeeMarket.london(0L), true, Optional.of(CHAIN), Set.of(TransactionType.EIP1559), ++ Set.of(BlobType.KZG_CELL_PROOFS), 2 * 24576); ++ } ++ ++ private static ValidationResult judge(final long gasLimit) { ++ final Transaction tx = ++ Transaction.builder() ++ .type(TransactionType.EIP1559) ++ .chainId(CHAIN) ++ .nonce(0) ++ .maxPriorityFeePerGas(Wei.ONE) ++ .maxFeePerGas(Wei.of(2_000_000_000L)) ++ .gasLimit(gasLimit) ++ .to(Address.ZERO) ++ .value(Wei.ZERO) ++ .payload(Bytes.EMPTY) ++ .signAndBuild(KEYS); ++ return validator().validate(tx, Optional.of(Wei.of(1_000_000_000L)), Optional.empty(), TransactionValidationParams.processingBlock()); ++ } ++ ++ @Test ++ void aGasLimitOf2To63OrMoreIsRefusedByTheCapNotLetThroughAsANegativeLong() { ++ // 2^63, 2^63 + 5 and 2^64 - 1, as readLongScalar hands them over ++ for (final long g : new long[] {Long.MIN_VALUE, Long.MIN_VALUE + 5, -1L}) { ++ final ValidationResult r = judge(g); ++ assertThat(r.isValid()).withFailMessage("gasLimit %s admitted", Long.toUnsignedString(g)).isFalse(); ++ assertThat(r.getInvalidReason()) ++ .withFailMessage("gasLimit %s refused for %s, not the cap", Long.toUnsignedString(g), r.getInvalidReason()) ++ .isEqualTo(TransactionInvalidReason.EXCEEDS_TRANSACTION_GAS_LIMIT); ++ } ++ } ++ ++ @Test ++ void theCapItselfIsAdmittedAndOneAboveIsRefused() { ++ // positive control: the rule is armed at exactly 2^24 and the fixture is otherwise valid ++ assertThat(judge(CAP).isValid()).withFailMessage(() -> "gasLimit = cap refused: " + judge(CAP).getErrorMessage()).isTrue(); ++ assertThat(judge(CAP + 1).getInvalidReason()).isEqualTo(TransactionInvalidReason.EXCEEDS_TRANSACTION_GAS_LIMIT); ++ } ++} +diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AereD433BftWithdrawalsTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AereD433BftWithdrawalsTest.java +new file mode 100644 +index 0000000000..6c935b7394 +--- /dev/null ++++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AereD433BftWithdrawalsTest.java +@@ -0,0 +1,75 @@ ++/* ++ * Copyright contributors to Besu. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Aere Network notice (Apache-2.0 section 4(b)): this file was added by Aere Network, 2026-09-28 (D-433), as the regression ++ * test of the ported upstream fixes hyperledger/besu ffe8104ee2 (GHSA-p4h2-gvh4-pv6j) and b7f1387cb4. ++ */ ++package org.hyperledger.besu.ethereum.mainnet; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++ ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.datatypes.GWei; ++import org.hyperledger.besu.datatypes.Hash; ++import org.hyperledger.besu.ethereum.core.Block; ++import org.hyperledger.besu.ethereum.core.BlockDataGenerator; ++import org.hyperledger.besu.ethereum.core.Withdrawal; ++ ++import java.util.Collections; ++import java.util.List; ++import java.util.Optional; ++ ++import org.apache.tuweni.units.bigints.UInt64; ++import org.junit.jupiter.api.Test; ++ ++/** ++ * AERE D-433: on a BFT chain (QBFT on 2800 and 28001, Shanghai active from genesis) withdrawals are not applicable, and the ++ * BFT schedule installs NotApplicableWithdrawals while keeping Shanghai's WithdrawalsProcessor. Before the port the validator ++ * returned true for anything, so a single Byzantine proposer could put withdrawals in a block and every honest Besu node would ++ * credit them as native balance. The port (upstream ffe8104ee2) refuses a non-empty list and a withdrawals root other than the ++ * empty trie root. ++ */ ++class AereD433BftWithdrawalsTest { ++ ++ private static final WithdrawalsValidator V = new WithdrawalsValidator.NotApplicableWithdrawals(); ++ ++ @Test ++ void aByzantineWithdrawalListAndItsRootAreRefused() { ++ final List injected = ++ List.of(new Withdrawal(UInt64.valueOf(1), UInt64.valueOf(2), Address.fromHexString("0x000000000000000000000000000000000000c0de"), GWei.of(11))); ++ assertThat(V.validateWithdrawals(Optional.of(injected))).withFailMessage("a non-empty withdrawal list was accepted").isFalse(); ++ final BlockDataGenerator gen = new BlockDataGenerator(); ++ final Block withRoot = ++ gen.block(BlockDataGenerator.BlockOptions.create().setWithdrawals(Optional.of(injected)).setWithdrawalsRoot(Hash.ZERO)); ++ assertThat(V.validateWithdrawalsRoot(withRoot)).withFailMessage("a withdrawals root other than the empty trie was accepted").isFalse(); ++ // upstream b7f1387cb4: a root in the header with NO withdrawals field in the body is malformed, even when the root is the empty one ++ final Block noBody = gen.block(BlockDataGenerator.BlockOptions.create().setWithdrawals(Optional.empty()).setWithdrawalsRoot(Hash.EMPTY_TRIE_HASH)); ++ assertThat(V.validateWithdrawalsRoot(noBody)).withFailMessage("a header root without body withdrawals was accepted").isFalse(); ++ } ++ ++ @Test ++ void theEmptyFormsAreStillAccepted() { ++ // positive control: the blocks the chain actually carries (empty list, empty-trie root) and pre-Shanghai (absent) ++ assertThat(V.validateWithdrawals(Optional.of(Collections.emptyList()))).isTrue(); ++ assertThat(V.validateWithdrawals(Optional.empty())).isTrue(); ++ final BlockDataGenerator gen = new BlockDataGenerator(); ++ assertThat( ++ V.validateWithdrawalsRoot( ++ gen.block( ++ BlockDataGenerator.BlockOptions.create() ++ .setWithdrawals(Optional.of(Collections.emptyList())) ++ .setWithdrawalsRoot(Hash.EMPTY_TRIE_HASH)))) ++ .isTrue(); ++ } ++} +diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/feemarket/LondonFeeMarketAereFloorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/feemarket/LondonFeeMarketAereFloorTest.java +new file mode 100644 +index 0000000000..b36bfd7811 +--- /dev/null ++++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/feemarket/LondonFeeMarketAereFloorTest.java +@@ -0,0 +1,129 @@ ++/* ++ * Copyright contributors to Hyperledger Besu. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.ethereum.mainnet.feemarket; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++ ++import org.hyperledger.besu.datatypes.Wei; ++import org.hyperledger.besu.ethereum.core.feemarket.TransactionPriceCalculator; ++ ++import java.util.Optional; ++ ++import org.junit.jupiter.api.Test; ++ ++/** ++ * Tests for the AERE fork-gated base-fee floor in {@link LondonFeeMarket}. ++ * ++ *

    Proves: (a) fork UNSET is byte-behaviour-identical to upstream London (empty blocks decay to / ++ * stay at the legacy 7-wei floor, no 1-Gwei clamp); (b) once the fork block N is set with a 1-Gwei ++ * floor, empty blocks at/after N floor at EXACTLY 1 Gwei and never below; (c) the jump to >= 1 Gwei ++ * happens exactly at block N (block N-1 is still legacy); (d) an over-target block still rises above ++ * 1 Gwei via the normal EIP-1559 formula. ++ */ ++public class LondonFeeMarketAereFloorTest { ++ ++ private static final long ONE_GWEI = 1_000_000_000L; ++ private static final long GAS_TARGET = 15_000_000L; ++ private static final long FORK_BLOCK = 100L; ++ ++ /** London fee market with an explicit AERE floor-fork configuration (bypasses global JVM config). */ ++ private static LondonFeeMarket market(final long aereForkBlock, final long aereFloorValueWei) { ++ return new LondonFeeMarket( ++ TransactionPriceCalculator.eip1559(), ++ 0L, // londonForkBlockNumber (kept off the tested block range) ++ Optional.empty(), ++ aereForkBlock, ++ aereFloorValueWei); ++ } ++ ++ // (a) UNSET fork => byte-identical to upstream: empty blocks decay to and stay at 7 wei, and no ++ // value is ever clamped up to 1 Gwei. ++ @Test ++ public void forkUnset_emptyBlocksDecayToSevenWei_noClampToOneGwei() { ++ final LondonFeeMarket unset = market(Long.MAX_VALUE, ONE_GWEI); ++ ++ // Decay many empty blocks from well above the floor: must settle at EXACTLY 7 wei. ++ Wei baseFee = Wei.of(10_000L); ++ for (int i = 0; i < 400; i++) { ++ baseFee = unset.computeBaseFee(500L + i, baseFee, 0L, GAS_TARGET); ++ } ++ assertThat(baseFee).isEqualTo(Wei.of(7L)); ++ ++ // Once at 7 wei it stays at 7 wei (never below), never jumps to 1 Gwei. ++ assertThat(unset.computeBaseFee(9_000L, Wei.of(7L), 0L, GAS_TARGET)).isEqualTo(Wei.of(7L)); ++ ++ // A mid-range empty-block value is NOT clamped up (proves the fork is a genuine no-op): ++ // 1000 - 1000/8 = 1000 - 125 = 875 wei. ++ assertThat(unset.computeBaseFee(9_000L, Wei.of(1_000L), 0L, GAS_TARGET)) ++ .isEqualTo(Wei.of(875L)); ++ } ++ ++ // (b) Fork ACTIVE => empty blocks at/after N floor at EXACTLY 1 Gwei and never drop below. ++ @Test ++ public void forkActive_emptyBlocksFloorAtExactlyOneGwei_neverBelow() { ++ final LondonFeeMarket forked = market(FORK_BLOCK, ONE_GWEI); ++ ++ // Sanity: raw EIP-1559 decrease from 1 Gwei on an empty block would be 875M; clamp pins it. ++ assertThat(forked.computeBaseFee(FORK_BLOCK + 1, Wei.of(ONE_GWEI), 0L, GAS_TARGET)) ++ .isEqualTo(Wei.of(ONE_GWEI)); ++ ++ // Many consecutive empty blocks after the fork: stays EXACTLY at 1 Gwei each block. ++ Wei baseFee = Wei.of(ONE_GWEI); ++ for (int i = 0; i < 50; i++) { ++ baseFee = forked.computeBaseFee(FORK_BLOCK + 1 + i, baseFee, 0L, GAS_TARGET); ++ assertThat(baseFee).isEqualTo(Wei.of(ONE_GWEI)); ++ } ++ ++ // Even a pathologically low parent baseFee (7 wei) is clamped up to exactly 1 Gwei post-fork. ++ assertThat(forked.computeBaseFee(FORK_BLOCK + 500, Wei.of(7L), 0L, GAS_TARGET)) ++ .isEqualTo(Wei.of(ONE_GWEI)); ++ } ++ ++ // (c) The jump to >= 1 Gwei happens exactly at the fork block N (N-1 is still legacy). ++ @Test ++ public void forkActivation_jumpHappensExactlyAtForkBlock() { ++ final LondonFeeMarket forked = market(FORK_BLOCK, ONE_GWEI); ++ ++ // Block N-1 is pre-fork: legacy behaviour, a 7-wei empty-block parent stays at 7 wei. ++ assertThat(forked.computeBaseFee(FORK_BLOCK - 1, Wei.of(7L), 0L, GAS_TARGET)) ++ .isEqualTo(Wei.of(7L)); ++ ++ // Block N itself jumps to >= 1 Gwei even though the parent baseFee was only 7 wei. ++ final Wei atForkBlock = forked.computeBaseFee(FORK_BLOCK, Wei.of(7L), 0L, GAS_TARGET); ++ assertThat(atForkBlock).isEqualTo(Wei.of(ONE_GWEI)); ++ assertThat(atForkBlock.greaterOrEqualThan(Wei.of(ONE_GWEI))).isTrue(); ++ } ++ ++ // (d) An over-target (active) block still rises above 1 Gwei via the normal EIP-1559 formula, ++ // and the clamp does not distort above-floor values (identical to the unset market's raw result). ++ @Test ++ public void forkActive_overTargetBlockRisesAboveOneGweiNormally() { ++ final LondonFeeMarket forked = market(FORK_BLOCK, ONE_GWEI); ++ final LondonFeeMarket unset = market(Long.MAX_VALUE, ONE_GWEI); ++ ++ final long parentGasUsed = 2 * GAS_TARGET; // over target => baseFee increases ++ final Wei parent = Wei.of(ONE_GWEI); ++ ++ // EIP-1559 rise: 1Gwei + 1Gwei * (2T - T)/T / 8 = 1Gwei + 1Gwei/8 = 1_125_000_000 wei. ++ final Wei rose = forked.computeBaseFee(FORK_BLOCK + 5, parent, parentGasUsed, GAS_TARGET); ++ assertThat(rose).isEqualTo(Wei.of(1_125_000_000L)); ++ assertThat(rose.greaterOrEqualThan(Wei.of(ONE_GWEI))).isTrue(); ++ assertThat(rose).isNotEqualTo(Wei.of(ONE_GWEI)); // strictly above the floor ++ ++ // Above-floor values are unaffected by the clamp: identical to the unset (no-op) market. ++ assertThat(rose) ++ .isEqualTo(unset.computeBaseFee(FORK_BLOCK + 5, parent, parentGasUsed, GAS_TARGET)); ++ } ++} +diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/parallelization/AereBlockStmBenchmarkTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/parallelization/AereBlockStmBenchmarkTest.java +new file mode 100644 +index 0000000000..aac192aeba +--- /dev/null ++++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/parallelization/AereBlockStmBenchmarkTest.java +@@ -0,0 +1,620 @@ ++/* ++ * Copyright contributors to AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.ethereum.mainnet.parallelization; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++import static org.hyperledger.besu.ethereum.mainnet.parallelization.ParallelBlockProcessorTestSupport.MINING_BENEFICIARY; ++import static org.junit.jupiter.api.Assertions.assertTrue; ++ ++import org.hyperledger.besu.config.GenesisConfig; ++import org.hyperledger.besu.config.JsonUtil; ++import org.hyperledger.besu.crypto.KeyPair; ++import org.hyperledger.besu.datatypes.Address; ++import org.hyperledger.besu.datatypes.Hash; ++import org.hyperledger.besu.datatypes.TransactionType; ++import org.hyperledger.besu.datatypes.Wei; ++import org.hyperledger.besu.ethereum.BlockProcessingResult; ++import org.hyperledger.besu.ethereum.core.Block; ++import org.hyperledger.besu.ethereum.core.BlockBody; ++import org.hyperledger.besu.ethereum.core.BlockHeader; ++import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; ++import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture; ++import org.hyperledger.besu.ethereum.core.MutableWorldState; ++import org.hyperledger.besu.ethereum.core.Transaction; ++import org.hyperledger.besu.ethereum.core.Util; ++import org.hyperledger.besu.ethereum.mainnet.BlockProcessor; ++import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor; ++import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; ++import org.hyperledger.besu.ethereum.mainnet.blockstm.AereBlockStmEngine; ++import org.hyperledger.besu.ethereum.mainnet.blockstm.AereBlockStmPreprocessing; ++import org.hyperledger.besu.ethereum.mainnet.blockstm.BlockStmStats; ++import org.hyperledger.besu.ethereum.trie.pathbased.common.provider.WorldStateQueryParams; ++import org.hyperledger.besu.evm.blockhash.BlockHashLookup; ++import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; ++import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; ++ ++import java.io.InputStream; ++import java.lang.management.ManagementFactory; ++import java.math.BigInteger; ++import java.nio.charset.StandardCharsets; ++import java.nio.file.Files; ++import java.nio.file.Path; ++import java.nio.file.StandardOpenOption; ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.Collections; ++import java.util.List; ++import java.util.Optional; ++ ++import com.fasterxml.jackson.databind.node.ObjectNode; ++import org.apache.tuweni.bytes.Bytes; ++import org.apache.tuweni.units.bigints.UInt256; ++import org.junit.jupiter.api.BeforeAll; ++import org.junit.jupiter.api.Test; ++ ++/** ++ * AERE Block-STM benchmark + verification harness (chain-independent, block-processor grain). ++ * ++ *

    Proves serial-equivalence (parallel state root == sequential state root) for an independent ++ * workload AND a genuine read/write-conflict workload (all transfers to one shared recipient, which ++ * forces the multi-version scheduler to abort and re-execute), and measures parallel-vs-sequential ++ * block execution time / TPS across worker counts. All numbers are written to {@code REPORT}. ++ */ ++public class AereBlockStmBenchmarkTest extends AbstractParallelBlockProcessorIntegrationTest { ++ ++ private static final String BASE_GENESIS = ++ "/org/hyperledger/besu/ethereum/mainnet/parallelization/genesis-it.json"; ++ private static final Path REPORT = ++ Path.of(System.getProperty("java.io.tmpdir"), "blockstm_bench_results.txt"); ++ ++ // Compute-heavy runtime: PUSH1 0 CALLDATALOAD (iters); loop { KECCAK256 32 bytes of mem; MSTORE }; ++ // then SSTORE slot0=1; STOP. Iteration count is supplied per-tx via 32-byte calldata. ++ private static final String COMPUTE_CODE = ++ "0x6000355b60206000206000526001900380600357600160005500"; ++ ++ private static final int MAX_SENDERS = 1024; ++ private static final Wei BASE_FEE = Wei.of(5); ++ ++ private static GenesisConfig customGenesis; ++ private static KeyPair[] senders; ++ private static Address[] senderAddr; ++ private final List lines = new ArrayList<>(); ++ ++ private static Address recipient(final int i) { ++ return Address.fromHexString(String.format("0x%040x", 0x10000000L + i)); ++ } ++ ++ private static final Address SHARED_RECIPIENT = ++ Address.fromHexString(String.format("0x%040x", 0x0DEAD001L)); ++ ++ private static Address computeContract(final int i) { ++ return Address.fromHexString(String.format("0x%040x", 0x20000000L + i)); ++ } ++ ++ @BeforeAll ++ static void buildGenesis() throws Exception { ++ final String baseText; ++ try (InputStream is = AereBlockStmBenchmarkTest.class.getResourceAsStream(BASE_GENESIS)) { ++ baseText = new String(is.readAllBytes(), StandardCharsets.UTF_8); ++ } ++ final ObjectNode root = JsonUtil.objectNodeFromString(baseText); ++ final ObjectNode alloc = (ObjectNode) root.get("alloc"); ++ ++ senders = new KeyPair[MAX_SENDERS]; ++ senderAddr = new Address[MAX_SENDERS]; ++ final String richBalance = "0x" + new BigInteger("1000000000000000000000000").toString(16); ++ for (int i = 0; i < MAX_SENDERS; i++) { ++ final String pkHex = String.format("%064x", i + 1); ++ final KeyPair kp = ParallelBlockProcessorTestSupport.generateKeyPair(pkHex); ++ senders[i] = kp; ++ senderAddr[i] = Util.publicKeyToAddress(kp.getPublicKey()); ++ final ObjectNode acct = JsonUtil.createEmptyObjectNode(); ++ acct.put("balance", richBalance); ++ alloc.set(senderAddr[i].getBytes().toUnprefixedHexString(), acct); ++ ++ final ObjectNode contract = JsonUtil.createEmptyObjectNode(); ++ contract.put("balance", "0"); ++ contract.put("code", COMPUTE_CODE); ++ alloc.set(computeContract(i).getBytes().toUnprefixedHexString(), contract); ++ } ++ customGenesis = GenesisConfig.fromConfig(root); ++ Files.write( ++ REPORT, ++ ("AERE BLOCK-STM BENCHMARK / VERIFICATION REPORT\n" ++ + "generated on a scratch host (chain-independent block-processor grain)\n" ++ + "cpus(reported)=" + Runtime.getRuntime().availableProcessors() ++ + " loadAvg(start)=" ++ + String.format("%.2f", ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage()) ++ + "\n===============================================================\n") ++ .getBytes(StandardCharsets.UTF_8), ++ StandardOpenOption.CREATE, ++ StandardOpenOption.TRUNCATE_EXISTING); ++ } ++ ++ private void log(final String s) { ++ lines.add(s); ++ System.out.println("[BLOCKSTM-BENCH] " + s); ++ } ++ ++ private void flush() throws Exception { ++ Files.write( ++ REPORT, ++ (String.join("\n", lines) + "\n").getBytes(StandardCharsets.UTF_8), ++ StandardOpenOption.APPEND); ++ lines.clear(); ++ } ++ ++ @Override ++ protected ExecutionContextTestFixture createFreshContext() { ++ return ExecutionContextTestFixture.builder(customGenesis) ++ .dataStorageFormat(DataStorageFormat.BONSAI) ++ .build(); ++ } ++ ++ @Override ++ protected String getVariantName() { ++ return "AERE Block-STM Benchmark"; ++ } ++ ++ @Override ++ protected ParallelTransactionPreprocessing createParallelPreprocessing( ++ final MainnetTransactionProcessor transactionProcessor) { ++ return new ParallelTransactionPreprocessing( ++ transactionProcessor, Runnable::run, getBalConfiguration()); ++ } ++ ++ // ---- workloads ---------------------------------------------------------- ++ ++ private Transaction[] independentTransfers(final int n) { ++ final Transaction[] txs = new Transaction[n]; ++ for (int i = 0; i < n; i++) { ++ txs[i] = ++ createTransferTransaction( ++ 0, 1L, 100_000L, 0L, 5L, recipient(i).toHexString(), senders[i]); ++ } ++ return txs; ++ } ++ ++ private Transaction[] lowConflictTransfers(final int n, final int pool) { ++ // Distinct senders credit recipients drawn from a small pool -> occasional write-conflict on a ++ // shared recipient balance (ERC20-style low contention). pool read/write conflict on that balance. ++ final Transaction[] txs = new Transaction[n]; ++ for (int i = 0; i < n; i++) { ++ txs[i] = ++ createTransferTransaction( ++ 0, 1L, 100_000L, 0L, 5L, SHARED_RECIPIENT.toHexString(), senders[i]); ++ } ++ return txs; ++ } ++ ++ private Transaction[] independentCompute(final int n, final long iters) { ++ final Bytes payload = UInt256.valueOf(iters).toBytes(); ++ final Transaction[] txs = new Transaction[n]; ++ for (int i = 0; i < n; i++) { ++ txs[i] = ++ Transaction.builder() ++ .type(TransactionType.EIP1559) ++ .nonce(0) ++ .maxPriorityFeePerGas(Wei.ZERO) ++ .maxFeePerGas(Wei.of(5)) ++ .gasLimit(30_000_000L) ++ .to(computeContract(i)) ++ .value(Wei.ZERO) ++ .payload(payload) ++ .chainId(BigInteger.valueOf(42)) ++ .signAndBuild(senders[i]); ++ } ++ return txs; ++ } ++ ++ // ---- block plumbing (configurable gas limit) ---------------------------- ++ ++ private Block buildBlock( ++ final BlockHeader parent, ++ final Hash stateRoot, ++ final long gasLimit, ++ final Transaction[] txs) { ++ final BlockHeader header = ++ new BlockHeaderTestFixture() ++ .number(parent.getNumber() + 1L) ++ .parentHash(parent.getHash()) ++ .coinbase(MINING_BENEFICIARY) ++ .stateRoot(stateRoot) ++ .gasLimit(gasLimit) ++ .baseFeePerGas(BASE_FEE) ++ .buildHeader(); ++ final BlockBody body = ++ new BlockBody(Arrays.asList(txs), Collections.emptyList(), Optional.empty()); ++ return new Block(header, body); ++ } ++ ++ private Hash discover(final long gasLimit, final Transaction[] txs) { ++ final ExecutionContextTestFixture ctx = createFreshContext(); ++ final BlockHeader parent = ctx.getBlockchain().getChainHeadHeader(); ++ final MutableWorldState ws = ++ ctx.getStateArchive() ++ .getWorldState(WorldStateQueryParams.withBlockHeaderAndUpdateNodeHead(parent)) ++ .orElseThrow(); ++ final Block block = buildBlock(parent, Hash.ZERO, gasLimit, txs); ++ final BlockProcessor seq = createSequentialProcessor(ctx); ++ final BlockProcessingResult r = ++ seq.processBlock(ctx.getProtocolContext(), ctx.getBlockchain(), ws, block); ++ if (r.isSuccessful()) { ++ return ws.rootHash(); ++ } ++ // Header stateRoot was ZERO, so processing "failed" on the root-mismatch check; recover the ++ // real (calculated) root from the error message: the first non-zero 32-byte hex it contains. ++ final String msg = r.errorMessage.orElseThrow(); ++ final java.util.regex.Matcher m = ++ java.util.regex.Pattern.compile("0x[0-9a-fA-F]{64}").matcher(msg); ++ while (m.find()) { ++ final Hash h = Hash.fromHexString(m.group()); ++ if (!h.equals(Hash.ZERO)) { ++ return h; ++ } ++ } ++ throw new AssertionError("could not recover state root from: " + msg); ++ } ++ ++ private BlockProcessor stockParallel(final ExecutionContextTestFixture ctx) { ++ final ProtocolSpec spec = ++ ctx.getProtocolSchedule() ++ .getByBlockHeader(new BlockHeaderTestFixture().number(0L).buildHeader()); ++ return new MainnetParallelBlockProcessor( ++ spec.getTransactionProcessor(), ++ spec.getTransactionReceiptFactory(), ++ Wei.ZERO, ++ BlockHeader::getCoinbase, ++ true, ++ ctx.getProtocolSchedule(), ++ getBalConfiguration(), ++ new NoOpMetricsSystem()); ++ } ++ ++ /** One timed sequential run. Returns [rootHex, nanos]. */ ++ private Object[] runSeq(final long gasLimit, final Hash stateRoot, final Transaction[] txs) { ++ final ExecutionContextTestFixture ctx = createFreshContext(); ++ final BlockHeader parent = ctx.getBlockchain().getChainHeadHeader(); ++ final MutableWorldState ws = ++ ctx.getStateArchive() ++ .getWorldState(WorldStateQueryParams.withBlockHeaderAndUpdateNodeHead(parent)) ++ .orElseThrow(); ++ final Block block = buildBlock(parent, stateRoot, gasLimit, txs); ++ final BlockProcessor seq = createSequentialProcessor(ctx); ++ final long t0 = System.nanoTime(); ++ final BlockProcessingResult r = ++ seq.processBlock(ctx.getProtocolContext(), ctx.getBlockchain(), ws, block); ++ final long dt = System.nanoTime() - t0; ++ assertTrue(r.isSuccessful(), "seq failed: " + r.errorMessage.orElse("?")); ++ return new Object[] {ws.rootHash(), dt, r}; ++ } ++ ++ /** One timed AERE Block-STM parallel run at {@code workers}. Returns [rootHex, nanos, nbParallel]. */ ++ private Object[] runPar( ++ final long gasLimit, final Hash stateRoot, final int workers, final Transaction[] txs) { ++ final ExecutionContextTestFixture ctx = createFreshContext(); ++ final BlockHeader parent = ctx.getBlockchain().getChainHeadHeader(); ++ final MutableWorldState ws = ++ ctx.getStateArchive() ++ .getWorldState(WorldStateQueryParams.withBlockHeaderAndUpdateNodeHead(parent)) ++ .orElseThrow(); ++ final Block block = buildBlock(parent, stateRoot, gasLimit, txs); ++ final ProtocolSpec spec = ++ ctx.getProtocolSchedule() ++ .getByBlockHeader(new BlockHeaderTestFixture().number(0L).buildHeader()); ++ final BlockProcessor par = stockParallel(ctx); ++ final AereBlockStmPreprocessing pf = ++ new AereBlockStmPreprocessing(spec.getTransactionProcessor(), workers); ++ final long t0 = System.nanoTime(); ++ final BlockProcessingResult r = ++ par.processBlock(ctx.getProtocolContext(), ctx.getBlockchain(), ws, block, pf); ++ final long dt = System.nanoTime() - t0; ++ assertTrue(r.isSuccessful(), "par failed: " + r.errorMessage.orElse("?")); ++ return new Object[] {ws.rootHash(), dt, r.getNbParallelizedTransactions().orElse(0)}; ++ } ++ ++ /** Drive the engine directly to read scheduler statistics (executions / aborts / verified). */ ++ private BlockStmStats engineStats(final long gasLimit, final int workers, final Transaction[] txs) { ++ final ExecutionContextTestFixture ctx = createFreshContext(); ++ final BlockHeader parent = ctx.getBlockchain().getChainHeadHeader(); ++ final Block block = buildBlock(parent, Hash.ZERO, gasLimit, txs); ++ final AereBlockStmEngine engine = ++ new AereBlockStmEngine( ++ ctx.getProtocolSchedule() ++ .getByBlockHeader(new BlockHeaderTestFixture().number(0L).buildHeader()) ++ .getTransactionProcessor(), ++ workers); ++ final BlockHashLookup zero = (frame, number) -> Hash.ZERO; ++ engine.runAsyncBlock( ++ ctx.getProtocolContext(), ++ block.getHeader(), ++ Arrays.asList(txs), ++ MINING_BENEFICIARY, ++ zero, ++ Wei.ZERO, ++ Runnable::run, ++ Optional.empty(), ++ Optional.of(parent)); ++ return engine.stats(); ++ } ++ ++ private static long median(final long[] a) { ++ final long[] c = a.clone(); ++ Arrays.sort(c); ++ return c[c.length / 2]; ++ } ++ ++ // ---- the suite ---------------------------------------------------------- ++ ++ @Test ++ void blockStmVerifyAndBenchmark() throws Exception { ++ final int cpus = Runtime.getRuntime().availableProcessors(); ++ final int[] workerCounts = {1, 2, 4, 8, 16}; ++ ++ // ===================== CORRECTNESS ===================== ++ log(""); ++ log("## PART 1 - CORRECTNESS (parallel root == sequential root)"); ++ ++ // 1a. Independent transfers: expect zero aborts, executions == n. ++ { ++ final int n = 300; ++ final Transaction[] txs = independentTransfers(n); ++ final Hash root = discover(30_000_000L, txs); ++ final Object[] seq = runSeq(30_000_000L, root, txs); ++ final Object[] par = runPar(30_000_000L, root, cpus, txs); ++ final Hash seqRoot = (Hash) seq[0]; ++ final Hash parRoot = (Hash) par[0]; ++ final int nbPar = (Integer) par[2]; ++ final BlockStmStats st = engineStats(30_000_000L, cpus, txs); ++ assertThat(parRoot).as("independent parallel root == sequential").isEqualTo(seqRoot); ++ log(String.format( ++ " [independent n=%d w=%d] parRoot==seqRoot: %s root=%s", n, cpus, ++ parRoot.equals(seqRoot), seqRoot.toHexString())); ++ log(String.format( ++ " nbParallelized=%d verified=%s execs=%d (n=%d) aborts=%d committedParallel=%d", ++ nbPar, st.verified(), st.totalExecutions(), st.numTxns(), st.totalAborts(), ++ st.committedParallel())); ++ assertThat(st.verified()).as("independent must verify").isTrue(); ++ assertThat(st.totalAborts()).as("independent must have zero aborts").isZero(); ++ assertThat(st.totalExecutions()).as("independent: one execution per tx").isEqualTo(n); ++ assertThat(nbPar).as("parallel path exercised").isGreaterThan(0); ++ } ++ ++ // 1b. Conflicting transfers (shared recipient): expect aborts>0, executions>n, root still equal. ++ { ++ final int n = 300; ++ final Transaction[] txs = conflictingTransfers(n); ++ final Hash root = discover(30_000_000L, txs); ++ final Object[] seq = runSeq(30_000_000L, root, txs); ++ final Object[] par = runPar(30_000_000L, root, cpus, txs); ++ final Hash seqRoot = (Hash) seq[0]; ++ final Hash parRoot = (Hash) par[0]; ++ final int nbPar = (Integer) par[2]; ++ final BlockStmStats st = engineStats(30_000_000L, cpus, txs); ++ assertThat(parRoot).as("CONFLICT parallel root == sequential").isEqualTo(seqRoot); ++ log(String.format( ++ " [conflict n=%d w=%d] parRoot==seqRoot: %s root=%s", n, cpus, ++ parRoot.equals(seqRoot), seqRoot.toHexString())); ++ log(String.format( ++ " nbParallelized=%d verified=%s execs=%d (n=%d, re-exec=%d) aborts=%d committedParallel=%d", ++ nbPar, st.verified(), st.totalExecutions(), st.numTxns(), ++ st.totalExecutions() - st.numTxns(), st.totalAborts(), st.committedParallel())); ++ assertThat(st.verified()).as("conflict must verify").isTrue(); ++ assertThat(st.totalAborts()).as("conflict must trigger re-execution (aborts>0)").isGreaterThan(0); ++ assertThat(st.totalExecutions()).as("conflict re-executes (execs>n)").isGreaterThan(n); ++ } ++ ++ // 1c. Independent compute contract calls: root equal, zero aborts. ++ { ++ final int n = 128; ++ final long iters = 400; ++ final Transaction[] txs = independentCompute(n, iters); ++ final Hash root = discover(3_000_000_000L, txs); ++ final Object[] seq = runSeq(3_000_000_000L, root, txs); ++ final Object[] par = runPar(3_000_000_000L, root, cpus, txs); ++ final Hash seqRoot = (Hash) seq[0]; ++ final Hash parRoot = (Hash) par[0]; ++ final BlockStmStats st = engineStats(3_000_000_000L, cpus, txs); ++ assertThat(parRoot).as("compute parallel root == sequential").isEqualTo(seqRoot); ++ log(String.format( ++ " [compute n=%d w=%d iters=%d] parRoot==seqRoot: %s root=%s", n, cpus, iters, ++ parRoot.equals(seqRoot), seqRoot.toHexString())); ++ log(String.format( ++ " verified=%s execs=%d (n=%d) aborts=%d committedParallel=%d", ++ st.verified(), st.totalExecutions(), st.numTxns(), st.totalAborts(), ++ st.committedParallel())); ++ assertThat(st.verified()).isTrue(); ++ assertThat(st.totalAborts()).isZero(); ++ } ++ ++ // 1d. Low-conflict transfers (recipient pool): root equal, verified (aborts allowed but rare). ++ { ++ final int n = 300; ++ final Transaction[] txs = lowConflictTransfers(n, 270); ++ final Hash root = discover(30_000_000L, txs); ++ final Object[] seq = runSeq(30_000_000L, root, txs); ++ final Object[] par = runPar(30_000_000L, root, cpus, txs); ++ final Hash seqRoot = (Hash) seq[0]; ++ final Hash parRoot = (Hash) par[0]; ++ final int nbPar = (Integer) par[2]; ++ final BlockStmStats st = engineStats(30_000_000L, cpus, txs); ++ assertThat(parRoot).as("low-conflict parallel root == sequential").isEqualTo(seqRoot); ++ log(String.format( ++ " [low-conflict n=%d w=%d pool=270] parRoot==seqRoot: %s root=%s", n, cpus, ++ parRoot.equals(seqRoot), seqRoot.toHexString())); ++ log(String.format( ++ " nbParallelized=%d verified=%s execs=%d (n=%d, re-exec=%d) aborts=%d committedParallel=%d", ++ nbPar, st.verified(), st.totalExecutions(), st.numTxns(), ++ st.totalExecutions() - st.numTxns(), st.totalAborts(), st.committedParallel())); ++ assertThat(st.verified()).as("low-conflict must verify").isTrue(); ++ } ++ flush(); ++ ++ // ===================== THROUGHPUT ===================== ++ final int warmup = 3; ++ final int measure = 5; ++ ++ // Workload A: independent transfers. ++ runThroughput( ++ "PART 2A - THROUGHPUT: independent transfers", 1000, 30_000_000L, ++ independentTransfers(1000), workerCounts, warmup, measure); ++ ++ // Workload A': independent compute-heavy calls (execution-bound; best case for parallelism). ++ runThroughput( ++ "PART 2B - THROUGHPUT: independent compute calls (iters=800)", 256, 3_000_000_000L, ++ independentCompute(256, 800), workerCounts, warmup, measure); ++ ++ // Workload C: high-conflict transfers (all to one recipient) - expect no speedup. ++ runThroughput( ++ "PART 2C - THROUGHPUT: high-conflict transfers (shared recipient)", 500, 30_000_000L, ++ conflictingTransfers(500), workerCounts, warmup, measure); ++ ++ // Workload D: low-conflict transfers (recipient pool=900 of 1000) - ERC20-style ~10% contention. ++ runThroughput( ++ "PART 2D - THROUGHPUT: low-conflict transfers (recipient pool=900)", 1000, 30_000_000L, ++ lowConflictTransfers(1000, 900), workerCounts, warmup, measure); ++ ++ // ===================== ISOLATED EXECUTION PHASE ===================== ++ // The real Block-STM test: time ONLY the parallel execution phase (engine.runAsyncBlock, i.e. ++ // the flat-snapshot base reads + concurrent EVM execution + MV bookkeeping), measured INSIDE the ++ // engine (execPhaseNanos), with the serial Bonsai trie commit excluded entirely. Execution-bound ++ // independent compute calls so there is real work to parallelize; scaling vs w=1 is the proof. ++ runExecPhase( ++ "PART 3A - EXECUTION PHASE (isolated): independent compute calls (iters=800)", ++ 256, 3_000_000_000L, independentCompute(256, 800), workerCounts, warmup, measure); ++ runExecPhase( ++ "PART 3B - EXECUTION PHASE (isolated): independent compute calls (iters=3000, heavy)", ++ 256, 3_000_000_000L, independentCompute(256, 3000), workerCounts, warmup, measure); ++ ++ log(""); ++ log("loadAvg(end)=" ++ + String.format("%.2f", ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage())); ++ log("=============================== END ==============================="); ++ flush(); ++ } ++ ++ private void runThroughput( ++ final String title, ++ final int n, ++ final long gasLimit, ++ final Transaction[] txs, ++ final int[] workerCounts, ++ final int warmup, ++ final int measure) ++ throws Exception { ++ log(""); ++ log("## " + title + " (n=" + n + " txs)"); ++ final Hash root = discover(gasLimit, txs); ++ ++ // Sequential baseline. ++ for (int i = 0; i < warmup; i++) { ++ runSeq(gasLimit, root, txs); ++ } ++ final long[] seqT = new long[measure]; ++ for (int i = 0; i < measure; i++) { ++ seqT[i] = (Long) runSeq(gasLimit, root, txs)[1]; ++ } ++ final long seqMed = median(seqT); ++ final double seqMs = seqMed / 1e6; ++ final double seqTps = n / (seqMed / 1e9); ++ log(String.format( ++ " SEQUENTIAL (MainnetBlockProcessor): %8.3f ms %10.0f tx/s", seqMs, seqTps)); ++ log(" worker | median ms | tx/s | speedup vs seq | scaling vs w=1"); ++ log(" -------+------------+----------+----------------+---------------"); ++ ++ double par1Ms = Double.NaN; ++ for (final int w : workerCounts) { ++ for (int i = 0; i < warmup; i++) { ++ runPar(gasLimit, root, w, txs); ++ } ++ final long[] pt = new long[measure]; ++ int nbPar = 0; ++ for (int i = 0; i < measure; i++) { ++ final Object[] r = runPar(gasLimit, root, w, txs); ++ pt[i] = (Long) r[1]; ++ nbPar = (Integer) r[2]; ++ } ++ final long med = median(pt); ++ final double ms = med / 1e6; ++ final double tps = n / (med / 1e9); ++ if (w == 1) { ++ par1Ms = ms; ++ } ++ log(String.format( ++ " %6d | %10.3f | %8.0f | %13.2fx | %12.2fx (nbParallel=%d)", ++ w, ms, tps, seqMs / ms, par1Ms / ms, nbPar)); ++ } ++ flush(); ++ } ++ ++ /** ++ * Measures the ISOLATED parallel execution phase across worker counts. Drives the engine directly ++ * (runAsyncBlock) and reads {@code execPhaseNanos} recorded INSIDE the engine (worker pool start -> ++ * termination), so the flat-snapshot mint and the downstream serial Bonsai trie commit are both ++ * excluded. Scaling vs w=1 of this number is the direct test of whether Block-STM execution ++ * parallelism works once the per-worker snapshot overhead is removed. ++ */ ++ private void runExecPhase( ++ final String title, ++ final int n, ++ final long gasLimit, ++ final Transaction[] txs, ++ final int[] workerCounts, ++ final int warmup, ++ final int measure) ++ throws Exception { ++ log(""); ++ log("## " + title + " (n=" + n + " txs)"); ++ log(" worker | exec-phase ms | snapshot ms | exec tx/s | scaling vs w=1 | verified"); ++ log(" -------+----------------+-------------+--------------+----------------+---------"); ++ ++ double w1Ms = Double.NaN; ++ for (final int w : workerCounts) { ++ for (int i = 0; i < warmup; i++) { ++ engineStats(gasLimit, w, txs); ++ } ++ final long[] execT = new long[measure]; ++ final long[] snapT = new long[measure]; ++ boolean verified = true; ++ for (int i = 0; i < measure; i++) { ++ final BlockStmStats st = engineStats(gasLimit, w, txs); ++ execT[i] = st.execPhaseNanos(); ++ snapT[i] = st.snapshotNanos(); ++ verified = verified && st.verified(); ++ } ++ final long execMed = median(execT); ++ final long snapMed = median(snapT); ++ final double execMs = execMed / 1e6; ++ final double snapMs = snapMed / 1e6; ++ final double tps = n / (execMed / 1e9); ++ if (w == 1) { ++ w1Ms = execMs; ++ } ++ assertThat(verified).as("exec-phase run must verify at w=" + w).isTrue(); ++ log(String.format( ++ " %6d | %14.3f | %11.3f | %12.0f | %13.2fx | %s", ++ w, execMs, snapMs, tps, w1Ms / execMs, verified)); ++ } ++ flush(); ++ } ++} +diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/parallelization/AereBlockStmSmokeTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/parallelization/AereBlockStmSmokeTest.java +new file mode 100644 +index 0000000000..a8e3db99de +--- /dev/null ++++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/parallelization/AereBlockStmSmokeTest.java +@@ -0,0 +1,130 @@ ++/* ++ * Copyright contributors to AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.ethereum.mainnet.parallelization; ++ ++import static org.assertj.core.api.Assertions.assertThat; ++import static org.hyperledger.besu.ethereum.mainnet.parallelization.ParallelBlockProcessorTestSupport.ACCOUNT_2; ++import static org.hyperledger.besu.ethereum.mainnet.parallelization.ParallelBlockProcessorTestSupport.ACCOUNT_3; ++import static org.hyperledger.besu.ethereum.mainnet.parallelization.ParallelBlockProcessorTestSupport.ACCOUNT_4; ++import static org.hyperledger.besu.ethereum.mainnet.parallelization.ParallelBlockProcessorTestSupport.ACCOUNT_GENESIS_1_KEYPAIR; ++import static org.hyperledger.besu.ethereum.mainnet.parallelization.ParallelBlockProcessorTestSupport.ACCOUNT_GENESIS_2_KEYPAIR; ++import static org.junit.jupiter.api.Assertions.assertTrue; ++ ++import org.hyperledger.besu.datatypes.Hash; ++import org.hyperledger.besu.datatypes.Wei; ++import org.hyperledger.besu.ethereum.BlockProcessingResult; ++import org.hyperledger.besu.ethereum.core.Block; ++import org.hyperledger.besu.ethereum.core.BlockHeader; ++import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; ++import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture; ++import org.hyperledger.besu.ethereum.core.MutableWorldState; ++import org.hyperledger.besu.ethereum.core.Transaction; ++import org.hyperledger.besu.ethereum.mainnet.AbstractBlockProcessor.PreprocessingFunction; ++import org.hyperledger.besu.ethereum.mainnet.BlockProcessor; ++import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor; ++import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; ++import org.hyperledger.besu.ethereum.mainnet.blockstm.AereBlockStmPreprocessing; ++import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; ++ ++import org.junit.jupiter.api.DisplayName; ++import org.junit.jupiter.api.Test; ++ ++/** ++ * Smoke test proving AERE Block-STM parallel execution is serial-equivalent: a block processed ++ * through the AERE Block-STM engine (a stock {@link MainnetParallelBlockProcessor} driven by {@link ++ * AereBlockStmPreprocessing}) yields a state root bit-identical to sequential {@code ++ * MainnetBlockProcessor} execution of the same block, and the parallel path is actually exercised. ++ */ ++public class AereBlockStmSmokeTest extends AbstractParallelBlockProcessorIntegrationTest { ++ ++ @Override ++ protected String getVariantName() { ++ return "AERE Block-STM"; ++ } ++ ++ @Override ++ protected ParallelTransactionPreprocessing createParallelPreprocessing( ++ final MainnetTransactionProcessor transactionProcessor) { ++ // Not used by this test; provided to satisfy the abstract base. ++ return new ParallelTransactionPreprocessing( ++ transactionProcessor, Runnable::run, getBalConfiguration()); ++ } ++ ++ private BlockProcessor stockParallelProcessor(final ExecutionContextTestFixture ctx) { ++ final ProtocolSpec spec = ++ ctx.getProtocolSchedule() ++ .getByBlockHeader(new BlockHeaderTestFixture().number(0L).buildHeader()); ++ return new MainnetParallelBlockProcessor( ++ spec.getTransactionProcessor(), ++ spec.getTransactionReceiptFactory(), ++ Wei.ZERO, ++ BlockHeader::getCoinbase, ++ true, ++ ctx.getProtocolSchedule(), ++ getBalConfiguration(), ++ new NoOpMetricsSystem()); ++ } ++ ++ @Test ++ @DisplayName("AERE Block-STM parallel root equals sequential root for independent transfers") ++ void blockStmRootMatchesSequential() { ++ final Transaction tx1 = ++ createTransferTransaction( ++ 0, 1_000_000_000_000_000_000L, 300_000L, 0L, 5L, ACCOUNT_2, ACCOUNT_GENESIS_1_KEYPAIR); ++ final Transaction tx2 = ++ createTransferTransaction( ++ 0, 2_000_000_000_000_000_000L, 300_000L, 0L, 5L, ACCOUNT_3, ACCOUNT_GENESIS_2_KEYPAIR); ++ final Transaction tx3 = ++ createTransferTransaction( ++ 1, 3_000_000_000_000_000_000L, 300_000L, 0L, 5L, ACCOUNT_4, ACCOUNT_GENESIS_1_KEYPAIR); ++ ++ final Wei baseFee = Wei.of(5); ++ final Transaction[] txs = {tx1, tx2, tx3}; ++ final Hash stateRoot = discoverStateRoot(baseFee, txs); ++ ++ // Sequential ++ final ExecutionContextTestFixture seqCtx = createFreshContext(); ++ final MutableWorldState seqWs = seqCtx.getStateArchive().getWorldState(); ++ final Block seqBlock = createBlock(seqCtx, stateRoot, baseFee, txs); ++ final BlockProcessor seqProcessor = createSequentialProcessor(seqCtx); ++ final BlockProcessingResult seqResult = ++ seqProcessor.processBlock( ++ seqCtx.getProtocolContext(), seqCtx.getBlockchain(), seqWs, seqBlock); ++ assertTrue(seqResult.isSuccessful(), "sequential processing failed"); ++ ++ // Parallel via AERE Block-STM ++ final ExecutionContextTestFixture parCtx = createFreshContext(); ++ final MutableWorldState parWs = parCtx.getStateArchive().getWorldState(); ++ final Block parBlock = createBlock(parCtx, stateRoot, baseFee, txs); ++ final ProtocolSpec spec = ++ parCtx ++ .getProtocolSchedule() ++ .getByBlockHeader(new BlockHeaderTestFixture().number(0L).buildHeader()); ++ final BlockProcessor parProcessor = stockParallelProcessor(parCtx); ++ final PreprocessingFunction blockStm = ++ new AereBlockStmPreprocessing( ++ spec.getTransactionProcessor(), Runtime.getRuntime().availableProcessors()); ++ final BlockProcessingResult parResult = ++ parProcessor.processBlock( ++ parCtx.getProtocolContext(), parCtx.getBlockchain(), parWs, parBlock, blockStm); ++ assertTrue( ++ parResult.isSuccessful(), ++ "AERE Block-STM processing failed: " + parResult.errorMessage.orElse("(no message)")); ++ ++ // Serial-equivalence: bit-identical 32-byte state root. ++ assertThat(parWs.rootHash()) ++ .as("AERE Block-STM parallel state root must equal sequential") ++ .isEqualTo(seqWs.rootHash()); ++ ++ // The parallel path was actually exercised (outcomes consumed, not per-tx sequential fallback). ++ assertParallelizationRecordedInResults(seqResult, parResult, txs.length); ++ } ++} +diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthPeers.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthPeers.java +index ee4e941111..92ec415271 100644 +--- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthPeers.java ++++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthPeers.java +@@ -1,33 +1,39 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/aere-cap-prestatus-rlpx-connections.patch. + */ + package org.hyperledger.besu.ethereum.eth.manager; + + import org.hyperledger.besu.ethereum.core.BlockHeader; + import org.hyperledger.besu.ethereum.eth.EthProtocol; + import org.hyperledger.besu.ethereum.eth.SnapProtocol; + import org.hyperledger.besu.ethereum.eth.manager.EthPeer.DisconnectCallback; + import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerSelector; + import org.hyperledger.besu.ethereum.eth.peervalidation.PeerValidator; + import org.hyperledger.besu.ethereum.eth.sync.ChainHeadTracker; + import org.hyperledger.besu.ethereum.eth.sync.SnapServerChecker; + import org.hyperledger.besu.ethereum.eth.sync.SyncMode; + import org.hyperledger.besu.ethereum.eth.sync.TrailingPeerRequirements; + import org.hyperledger.besu.ethereum.forkid.ForkId; + import org.hyperledger.besu.ethereum.forkid.ForkIdManager; + import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; + import org.hyperledger.besu.ethereum.p2p.peers.Peer; + import org.hyperledger.besu.ethereum.p2p.peers.PeerId; + import org.hyperledger.besu.ethereum.p2p.rlpx.RlpxAgent; + import org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection; +@@ -74,46 +80,55 @@ public class EthPeers implements PeerSelector { + Comparator.comparing((final EthPeerImmutableAttributes p) -> p.estimatedTotalDifficulty()); + + public static final Comparator CHAIN_HEIGHT = + Comparator.comparing((final EthPeerImmutableAttributes p) -> p.estimatedChainHeight()); + + public static final Comparator MOST_USEFUL_PEER = + Comparator.comparing((final EthPeerImmutableAttributes p) -> p.reputationScore()) + .thenComparing(CHAIN_HEIGHT); + + public static final Comparator TOTAL_DIFFICULTY_THEN_HEIGHT = + TOTAL_DIFFICULTY.thenComparing(CHAIN_HEIGHT); + + public static final Comparator LEAST_TO_MOST_BUSY = + Comparator.comparing(EthPeerImmutableAttributes::outstandingRequests) + .thenComparing(EthPeerImmutableAttributes::lastRequestTimestamp); + public static final int NODE_ID_LENGTH = 64; + public static final int USEFULL_PEER_SCORE_THRESHOLD = 102; + + private final Map activeConnections = new ConcurrentHashMap<>(); + +- private final Cache incompleteConnections = +- CacheBuilder.newBuilder() +- .expireAfterWrite(Duration.ofSeconds(20L)) +- .concurrencyLevel(1) +- .removalListener(this::onCacheRemoval) +- .build(); ++ /** ++ * Lower bound for the pre-STATUS (incomplete) connection cap, so that even very small {@code ++ * --max-peers} values still tolerate a reasonable number of concurrent inbound handshakes. AERE ++ * D-434: ported from upstream hyperledger/besu e540ae2394 (GHSA-6r9q-wjp4-34gh). ++ */ ++ private static final int INCOMPLETE_CONNECTIONS_CAP_FLOOR = 10; ++ ++ /** ++ * Maximum number of connections that have completed the devp2p HELLO but not yet the eth STATUS ++ * handshake that we retain. Bounds file-descriptor and heap growth from peers that connect and ++ * never send STATUS, which are otherwise invisible to {@code --max-peers} accounting. ++ */ ++ private final int maxIncompleteConnections; ++ ++ private final Cache incompleteConnections; + private final Clock clock; + private final List permissioningProviders; + private final int maxMessageSize; + private final Subscribers connectCallbacks = Subscribers.create(); + private final Subscribers disconnectCallbacks = Subscribers.create(); + private final Collection pendingRequests = new CopyOnWriteArrayList<>(); + private final int peerUpperBound; + private final int maxRemotelyInitiatedConnections; + private final Boolean randomPeerPriority; + private final Bytes nodeIdMask = Bytes.random(NODE_ID_LENGTH); + private final Supplier currentProtocolSpecSupplier; + private final SyncMode syncMode; + private final ForkIdManager forkIdManager; + private final int snapServerTargetNumber; + private final boolean shouldLimitRemoteConnections; + + private Comparator bestPeerComparator; + private final Bytes localNodeId; + private RlpxAgent rlpxAgent; + +@@ -134,62 +149,75 @@ public class EthPeers implements PeerSelector { + final int peerUpperBound, + final int maxRemotelyInitiatedConnections, + final Boolean randomPeerPriority, + final SyncMode syncMode, + final ForkIdManager forkIdManager) { + this.currentProtocolSpecSupplier = currentProtocolSpecSupplier; + this.clock = clock; + this.permissioningProviders = permissioningProviders; + this.maxMessageSize = maxMessageSize; + this.bestPeerComparator = TOTAL_DIFFICULTY_THEN_HEIGHT; + this.localNodeId = localNodeId; + this.peerUpperBound = peerUpperBound; + this.maxRemotelyInitiatedConnections = maxRemotelyInitiatedConnections; + this.randomPeerPriority = randomPeerPriority; + LOG.trace("MaxPeers: {}, Max Remote: {}", peerUpperBound, maxRemotelyInitiatedConnections); + this.syncMode = syncMode; + this.forkIdManager = forkIdManager; + this.snapServerTargetNumber = + peerUpperBound / 2; // 50% of peers should be snap servers while snap syncing + this.shouldLimitRemoteConnections = maxRemotelyInitiatedConnections < peerUpperBound; ++ this.maxIncompleteConnections = Math.max(peerUpperBound * 2, INCOMPLETE_CONNECTIONS_CAP_FLOOR); ++ this.incompleteConnections = ++ CacheBuilder.newBuilder() ++ .maximumSize(maxIncompleteConnections) ++ .expireAfterWrite(Duration.ofSeconds(20L)) ++ .concurrencyLevel(1) ++ .removalListener(this::onCacheRemoval) ++ .build(); + + metricsSystem.createIntegerGauge( + BesuMetricCategory.ETHEREUM, + "peer_count", + "The current number of peers connected", + activeConnections::size); + metricsSystem.createIntegerGauge( + BesuMetricCategory.ETHEREUM, + "peer_count_snap_server", + "The current number of peers connected that serve snap data", + () -> + (int) streamAvailablePeers().filter(EthPeerImmutableAttributes::isServingSnap).count()); + metricsSystem.createIntegerGauge( + BesuMetricCategory.PEERS, + "pending_peer_requests_current", + "Number of peer requests currently pending because peers are busy", + pendingRequests::size); + metricsSystem.createIntegerGauge( + BesuMetricCategory.ETHEREUM, + "peer_limit", + "The maximum number of peers this node allows to connect", + () -> peerUpperBound); ++ metricsSystem.createIntegerGauge( ++ BesuMetricCategory.ETHEREUM, ++ "peer_count_incomplete", ++ "The current number of connections that have not yet completed the eth STATUS handshake", ++ () -> (int) incompleteConnections.size()); + + connectedPeersCounter = + metricsSystem.createCounter( + BesuMetricCategory.PEERS, "connected_total", "Total number of peers connected"); + + final LabelledSuppliedMetric peerClientLabelledGauge = + metricsSystem.createLabelledSuppliedGauge( + BesuMetricCategory.PEERS, + "peer_count_by_client", + "The number of clients connected by client", + "client"); + + for (final var clientName : PeerClientName.values()) { + peerClientLabelledGauge.labels( + () -> countConnectedPeersByClientName(clientName), clientName.getDisplayName()); + } + } + + private double countConnectedPeersByClientName(final PeerClientName clientName) { + return streamAllActiveConnections() +@@ -737,56 +765,86 @@ public class EthPeers implements PeerSelector { + conn, + peerUpperBound); + conn.disconnect(DisconnectMessage.DisconnectReason.TOO_MANY_PEERS); + }); + } + + private boolean inboundInitiatedConnectionLimitExceeded() { + return shouldLimitRemoteConnections + && countUntrustedRemotelyInitiatedConnections() > maxRemotelyInitiatedConnections; + } + + private long countUntrustedRemotelyInitiatedConnections() { + return activeConnections.values().stream() + .map(EthPeer::getConnection) + .filter(PeerConnection::inboundInitiated) + .filter(c -> !c.isDisconnected()) + .filter(conn -> !canExceedPeerLimits(conn.getPeer().getId())) + .count(); + } + +- private void onCacheRemoval( +- final RemovalNotification removalNotification) { +- if (removalNotification.wasEvicted()) { +- final PeerConnection peerConnectionRemoved = removalNotification.getKey(); +- final EthPeer peer = removalNotification.getValue(); +- if (peer == null) { +- return; +- } +- final PeerConnection peerConnectionOfEthPeer = peer.getConnection(); +- if (peerConnectionRemoved != null) { +- if (!peerConnectionRemoved.equals(peerConnectionOfEthPeer)) { +- // If this connection is not the connection of the EthPeer by now we can disconnect +- peerConnectionRemoved.disconnect(DisconnectMessage.DisconnectReason.ALREADY_CONNECTED); +- } +- } ++ // AERE D-434 (e540ae2394, GHSA-6r9q-wjp4-34gh): close pre-STATUS connections evicted from the ++ // bounded incomplete-connection cache so they cannot leak file descriptors or heap. ++ @VisibleForTesting ++ void onCacheRemoval(final RemovalNotification removalNotification) { ++ // Only react to evictions (size cap or expiry). Explicit invalidations (e.g. on a normal ++ // disconnect) already close the connection through their own path. ++ if (!removalNotification.wasEvicted()) { ++ return; ++ } ++ final PeerConnection evictedConnection = removalNotification.getKey(); ++ final EthPeer peer = removalNotification.getValue(); ++ if (evictedConnection == null || evictedConnection.isDisconnected()) { ++ return; + } ++ ++ final boolean isCurrentConnectionOfPeer = ++ peer != null && evictedConnection.equals(peer.getConnection()); ++ if (isCurrentConnectionOfPeer && peer.statusHasBeenReceived()) { ++ // The peer completed (or is completing) the eth STATUS handshake and is being promoted to an ++ // active connection; its incomplete-cache entry is expiring naturally. Leave the live ++ // connection alone - it is (or will be) tracked in activeConnections. ++ return; ++ } ++ ++ // Either a superseded connection (the peer reconnected with a different connection), or a ++ // connection that completed the devp2p HELLO but never sent eth STATUS and has now been evicted ++ // (20s expiry, or pushed out of the bounded cache). Close the socket so evicted pre-STATUS ++ // connections cannot leak file descriptors or heap while remaining invisible to --max-peers. ++ DisconnectReason reason = ++ isCurrentConnectionOfPeer ++ ? DisconnectMessage.DisconnectReason.TIMEOUT ++ : DisconnectMessage.DisconnectReason.ALREADY_CONNECTED; ++ ++ LOG.atTrace() ++ .setMessage( ++ "Closing pre-STATUS connection {} evicted from incomplete-connection cache, reason {}") ++ .addArgument(evictedConnection::getPeerInfo) ++ .addArgument(reason) ++ .log(); ++ ++ evictedConnection.disconnect(reason); ++ } ++ ++ @VisibleForTesting ++ int incompleteConnectionCount() { ++ return (int) incompleteConnections.size(); + } + + boolean addPeerToEthPeers(final EthPeer peer) { + // We have a connection to a peer that is on the right chain and is willing to connect to us. + // Figure out whether we want to add it to the active connections. + final PeerConnection connection = peer.getConnection(); + if (activeConnections.containsValue(peer)) { + return false; + } + + final Bytes id = peer.getId(); + if (!randomPeerPriority) { + + if (peerCount() >= peerUpperBound) { + final long numSnapServers = numberOfSnapServers(); + final boolean inboundLimitExceeded = inboundInitiatedConnectionLimitExceeded(); + // three reasons why we would disconnect an existing peer to accommodate the new peer + if (canExceedPeerLimits(id) + || (snapServerPeersNeeded + && numSnapServers < snapServerTargetNumber +diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/BlockPropagationManager.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/BlockPropagationManager.java +index 7fde3a17c7..dbcc8fbacc 100644 +--- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/BlockPropagationManager.java ++++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/BlockPropagationManager.java +@@ -1,33 +1,39 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/0008-aere-pq-aip22.patch. + */ + package org.hyperledger.besu.ethereum.eth.sync; + + import static org.hyperledger.besu.util.FutureUtils.exceptionallyCompose; + + import org.hyperledger.besu.consensus.merge.ForkchoiceEvent; + import org.hyperledger.besu.consensus.merge.UnverifiedForkchoiceListener; + import org.hyperledger.besu.datatypes.Hash; + import org.hyperledger.besu.ethereum.ProtocolContext; + import org.hyperledger.besu.ethereum.chain.BadBlockCause; + import org.hyperledger.besu.ethereum.chain.BadBlockManager; + import org.hyperledger.besu.ethereum.chain.BlockAddedEvent; + import org.hyperledger.besu.ethereum.chain.Blockchain; + import org.hyperledger.besu.ethereum.chain.MutableBlockchain; + import org.hyperledger.besu.ethereum.core.Block; + import org.hyperledger.besu.ethereum.core.BlockHeader; + import org.hyperledger.besu.ethereum.core.Difficulty; + import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; + import org.hyperledger.besu.ethereum.eth.manager.EthContext; + import org.hyperledger.besu.ethereum.eth.manager.EthMessage; +@@ -704,40 +710,53 @@ public class BlockPropagationManager implements UnverifiedForkchoiceListener { + if (!protocolContext + .getBlockchain() + .contains(lowestPendingBlock.getHeader().getParentHash())) { + requestParentBlock(lowestPendingBlock); + } else { + LOG.trace("Parent block is already in the chain"); + // if the parent is already imported, process its children + maybeProcessPendingChildrenBlocks(lowestPendingBlock.getHeader()); + } + } + } + + private CompletableFuture validateAndProcessPendingBlock( + final BlockHeaderValidator blockHeaderValidator, + final Block block, + final BlockHeader parent, + final BadBlockManager badBlockManager) { + final HeaderValidationMode validationMode = HeaderValidationMode.FULL; + if (blockHeaderValidator.validateHeader( + block.getHeader(), parent, protocolContext, validationMode)) { ++ // AERE D-412 (2026-09-26), Rule C: a valid header is not, from AIP-22 stage 5, a proof that a ++ // quorum agreed the block (it carries only the proposer's single Falcon seal). A validator does ++ // not ADOPT a propagated block at the tip of its own consensus height without a post-quantum ++ // commit quorum for it; the gate is inert below H_hdr and for non-validators, and the sync ++ // downloader (a different path) is untouched, so this is fork choice, not validation. ++ if (!PropagatedBlockAdoptionGate.mayAdopt(block.getHeader(), parent)) { ++ processingBlocksManager.registerBlockImportDone(block.getHash()); ++ LOG.info( ++ "AERE D-412: not adopting propagated block {} at the tip without a post-quantum commit " ++ + "quorum; this node's own consensus decides this height", ++ block.toLogString()); ++ return CompletableFuture.completedFuture(block); ++ } + ethContext.getScheduler().scheduleSyncWorkerTask(() -> broadcastBlock(block, parent)); + return runImportTask(block); + } else { + processingBlocksManager.registerBlockImportDone(block.getHash()); + final String description = String.format("Failed header validation (%s)", validationMode); + badBlockManager.addBadBlock(block, BadBlockCause.fromValidationFailure(description)); + LOG.warn( + "Added to bad block manager for invalid header, failed to import announced block {}", + block.toLogString()); + return CompletableFuture.completedFuture(block); + } + } + + private CompletableFuture runImportTask(final Block block) { + final PersistBlockTask importTask = + PersistBlockTask.create( + protocolSchedule, + protocolContext, + ethContext, + block, +diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/PropagatedBlockAdoptionGate.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/PropagatedBlockAdoptionGate.java +new file mode 100644 +index 0000000000..7e11ed3686 +--- /dev/null ++++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/PropagatedBlockAdoptionGate.java +@@ -0,0 +1,103 @@ ++/* ++ * Copyright contributors to Besu / AERE Network. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on ++ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the ++ * specific language governing permissions and limitations under the License. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ */ ++package org.hyperledger.besu.ethereum.eth.sync; ++ ++import org.hyperledger.besu.ethereum.core.BlockHeader; ++ ++import org.slf4j.Logger; ++import org.slf4j.LoggerFactory; ++ ++/** ++ * AERE D-412 (2026-09-26), Rule C. A process-wide gate the block PROPAGATION path asks before it adopts ++ * a block arriving from the network as the new canonical head. ++ * ++ *

    WHY IT EXISTS. From AIP-22 stage 5 (H_hdr) a header carries only the proposer's single Falcon-512 ++ * seal, so a valid header no longer proves a quorum agreed the block: an honest committed block and a ++ * block a single key forged are indistinguishable to header validation. The quorum agreement lives OFF ++ * the header, in the commit seals a validator heard (AIP-21, {@code PqSealCache}). Measured on rep28098, ++ * a single validator forged its own between-anchor block, gossiped it, and honest validators imported it ++ * as head and built on top. This gate lets a validator refuse to ADOPT such a propagated block at the tip ++ * of its own consensus height unless it holds a post-quantum commit quorum for it. Block VALIDITY is ++ * unchanged (this is fork choice, not validation), so the sync downloader - a different code path that ++ * does not consult this gate - still imports the same chain and catch-up is unaffected. ++ * ++ *

    WHY A STATIC REGISTRY. This module ({@code ethereum/eth}) sits below the consensus modules and ++ * cannot depend on them, so the smart part of the decision (the seal cache, the registry, the validator ++ * set) lives in a consensus-aware implementation that registers itself here at startup, exactly as ++ * {@code PqSealCache.instance()} and the other AERE consensus singletons are process-wide. The interface ++ * takes only {@code ethereum/core} types, so there is no backward dependency. Unset, the gate is ++ * {@link #ALLOW_ALL} and behaviour is byte-for-byte as before. ++ * ++ *

    FAIL OPEN. {@link #mayAdopt} never throws: a bug in the installed gate reverts to the current ++ * behaviour (adopt), never to refusing every block, because a repair that could stop the chain is worse ++ * than the exposure it closes. ++ */ ++public final class PropagatedBlockAdoptionGate { ++ ++ private static final Logger LOG = LoggerFactory.getLogger(PropagatedBlockAdoptionGate.class); ++ ++ /** The decision a consensus-aware implementation supplies. */ ++ @FunctionalInterface ++ public interface Gate { ++ /** ++ * Whether this node may adopt a block that arrived by propagation as the new canonical head. ++ * ++ * @param header the propagated block's header, already header-validated ++ * @param parent the parent header, already on this node's chain ++ * @return true to adopt (import as head), false to leave this height to this node's own consensus ++ */ ++ boolean mayAdopt(BlockHeader header, BlockHeader parent); ++ } ++ ++ /** The default: adopt everything, i.e. exactly the behaviour before this gate existed. */ ++ public static final Gate ALLOW_ALL = (header, parent) -> true; ++ ++ private static volatile Gate gate = ALLOW_ALL; ++ ++ private PropagatedBlockAdoptionGate() {} ++ ++ /** ++ * Install the gate for this process. A consensus builder calls this at startup. ++ * ++ * @param g the gate, or null to reset to {@link #ALLOW_ALL} ++ */ ++ public static void install(final Gate g) { ++ gate = (g == null) ? ALLOW_ALL : g; ++ } ++ ++ /** Reset to {@link #ALLOW_ALL}. For tests and a deliberate operator reset. */ ++ public static void reset() { ++ gate = ALLOW_ALL; ++ } ++ ++ /** ++ * Whether the installed gate allows adopting this propagated block. Never throws: on any error it ++ * allows (fail open), so a gate bug can never stop the chain. ++ * ++ * @param header the propagated block's header ++ * @param parent the parent header ++ * @return true to adopt ++ */ ++ public static boolean mayAdopt(final BlockHeader header, final BlockHeader parent) { ++ try { ++ return gate.mayAdopt(header, parent); ++ } catch (final RuntimeException e) { ++ LOG.warn( ++ "AERE D-412: propagation adoption gate threw ({}); allowing the block, as before the gate.", ++ e.toString()); ++ return true; ++ } ++ } ++} +diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/state/SyncState.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/state/SyncState.java +old mode 100644 +new mode 100755 +index ab09fafaa0..9d5cdadf39 +--- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/state/SyncState.java ++++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/state/SyncState.java +@@ -1,65 +1,77 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/aere-syncstate-in-sync-lock.patch. + */ + package org.hyperledger.besu.ethereum.eth.sync.state; + + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.ethereum.chain.Blockchain; + import org.hyperledger.besu.ethereum.chain.ChainHead; + import org.hyperledger.besu.ethereum.core.BlockHeader; + import org.hyperledger.besu.ethereum.core.DefaultSyncStatus; + import org.hyperledger.besu.ethereum.core.Synchronizer; + import org.hyperledger.besu.ethereum.core.Synchronizer.InSyncListener; + import org.hyperledger.besu.ethereum.eth.manager.ChainHeadEstimate; + import org.hyperledger.besu.ethereum.eth.manager.EthPeer; + import org.hyperledger.besu.ethereum.eth.manager.EthPeers; + import org.hyperledger.besu.ethereum.eth.sync.common.checkpoint.Checkpoint; + import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldStateDownloadStatus; + import org.hyperledger.besu.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.DisconnectReason; + import org.hyperledger.besu.plugin.data.SyncStatus; + import org.hyperledger.besu.plugin.services.BesuEvents.InitialSyncCompletionListener; + import org.hyperledger.besu.plugin.services.BesuEvents.SyncStatusListener; + import org.hyperledger.besu.plugin.services.BesuEvents.TTDReachedListener; + import org.hyperledger.besu.util.Subscribers; + + import java.util.Map; + import java.util.Optional; + import java.util.concurrent.ConcurrentHashMap; + import java.util.concurrent.atomic.AtomicLong; + + public class SyncState { + + private final Blockchain blockchain; + private final EthPeers ethPeers; + ++ // Ensures checkInSync() re-evaluation gives a consistent view of sync status. A ++ // standalone lock is used instead of the object monitor to prevent checkInSync() ++ // causing a deadlock while synchronized on the object monitor. ++ // (AERE D-426: upstream hyperledger/besu#11041, ported) ++ private final Object inSyncLock = new Object(); ++ + private final AtomicLong inSyncSubscriberId = new AtomicLong(); + private final Map inSyncTrackers = new ConcurrentHashMap<>(); + private final Subscribers syncStatusListeners = Subscribers.create(); + private final Subscribers ttdReachedListeners = Subscribers.create(); + + private final Subscribers completionListenerSubscribers = + Subscribers.create(); + + private volatile long chainHeightListenerId; + private volatile Optional syncTarget = Optional.empty(); + private Optional worldStateDownloadStatus = Optional.empty(); + private Optional newPeerListenerId; + private Optional reachedTerminalDifficulty = Optional.empty(); + private final Optional checkpoint; + private volatile boolean isInitialSyncPhaseDone; + + private volatile boolean isResyncNeeded; + + private Optional

    maybeAccountToRepair = Optional.empty(); + +@@ -285,56 +297,59 @@ public class SyncState { + } + + public long getLocalChainHeight() { + return blockchain.getChainHeadBlockNumber(); + } + + public long bestChainHeight() { + final long localChainHeight = blockchain.getChainHeadBlockNumber(); + return bestChainHeight(localChainHeight); + } + + public long bestChainHeight(final long localChainHeight) { + return Math.max( + localChainHeight, + ethPeers + .bestPeerWithHeightEstimate() + .map(p -> p.chainState().getEstimatedHeight()) + .orElse(localChainHeight)); + } + +- private synchronized void checkInSync() { +- final ChainHead localChain = getLocalChainHead(); +- final Optional syncTargetChain = getSyncTargetChainHead(); +- final Optional bestPeerChain = getBestPeerChainHead(); +- +- // Remove listener when we've found a peer. +- newPeerListenerId.ifPresent( +- listenerId -> { +- ethPeers.unsubscribeConnect(listenerId); +- newPeerListenerId = Optional.empty(); +- }); +- +- inSyncTrackers +- .values() +- .forEach( +- (syncTracker) -> syncTracker.checkState(localChain, syncTargetChain, bestPeerChain)); ++ /** Evaluates whether this node is in sync and notifies any tracker whose verdict changed. */ ++ private void checkInSync() { ++ synchronized (inSyncLock) { ++ final ChainHead localChain = getLocalChainHead(); ++ final Optional syncTargetChain = getSyncTargetChainHead(); ++ final Optional bestPeerChain = getBestPeerChainHead(); ++ ++ // Remove listener when we've found a peer. ++ newPeerListenerId.ifPresent( ++ listenerId -> { ++ ethPeers.unsubscribeConnect(listenerId); ++ newPeerListenerId = Optional.empty(); ++ }); ++ ++ inSyncTrackers ++ .values() ++ .forEach( ++ (syncTracker) -> syncTracker.checkState(localChain, syncTargetChain, bestPeerChain)); ++ } + } + + public Optional getCheckpoint() { + return checkpoint; + } + + public boolean isInitialSyncPhaseDone() { + return isInitialSyncPhaseDone; + } + + public void markInitialSyncPhaseAsDone() { + isInitialSyncPhaseDone = true; + isResyncNeeded = false; + completionListenerSubscribers.forEach(InitialSyncCompletionListener::onInitialSyncCompleted); + } + + public boolean isResyncNeeded() { + return isResyncNeeded; + } + +diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/state/SyncStateTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/state/SyncStateTest.java +index ba6fd7b3dd..5b58648df1 100644 +--- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/state/SyncStateTest.java ++++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/state/SyncStateTest.java +@@ -1,33 +1,39 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/aere-syncstate-in-sync-lock.patch. + */ + package org.hyperledger.besu.ethereum.eth.sync.state; + + import static org.assertj.core.api.Assertions.assertThat; + import static org.mockito.ArgumentMatchers.any; + import static org.mockito.ArgumentMatchers.anyBoolean; + import static org.mockito.Mockito.doReturn; + import static org.mockito.Mockito.lenient; + import static org.mockito.Mockito.mock; + import static org.mockito.Mockito.never; + import static org.mockito.Mockito.spy; + import static org.mockito.Mockito.times; + import static org.mockito.Mockito.verify; + import static org.mockito.Mockito.verifyNoMoreInteractions; + + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.datatypes.Hash; + import org.hyperledger.besu.ethereum.chain.MutableBlockchain; + import org.hyperledger.besu.ethereum.core.Block; + import org.hyperledger.besu.ethereum.core.BlockDataGenerator; +@@ -39,42 +45,47 @@ import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider; + import org.hyperledger.besu.ethereum.core.Synchronizer; + import org.hyperledger.besu.ethereum.core.Synchronizer.InSyncListener; + import org.hyperledger.besu.ethereum.core.TransactionReceipt; + import org.hyperledger.besu.ethereum.eth.manager.ChainHeadEstimate; + import org.hyperledger.besu.ethereum.eth.manager.ChainState; + import org.hyperledger.besu.ethereum.eth.manager.EthPeer; + import org.hyperledger.besu.ethereum.eth.manager.EthPeers; + import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; + import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; + import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; + import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; + import org.hyperledger.besu.ethereum.eth.sync.common.checkpoint.Checkpoint; + import org.hyperledger.besu.ethereum.eth.sync.common.checkpoint.ImmutableCheckpoint; + import org.hyperledger.besu.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.DisconnectReason; + import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; + import org.hyperledger.besu.plugin.data.SyncStatus; + import org.hyperledger.besu.plugin.services.BesuEvents.InitialSyncCompletionListener; + import org.hyperledger.besu.plugin.services.BesuEvents.SyncStatusListener; + import org.hyperledger.besu.plugin.services.BesuEvents.TTDReachedListener; + ++import java.util.ArrayList; + import java.util.List; + import java.util.Optional; ++import java.util.concurrent.CountDownLatch; ++import java.util.concurrent.TimeUnit; ++import java.util.concurrent.atomic.AtomicBoolean; ++import java.util.concurrent.atomic.AtomicReference; + + import org.junit.jupiter.api.BeforeEach; + import org.junit.jupiter.api.Test; + import org.junit.jupiter.api.extension.ExtendWith; + import org.mockito.ArgumentCaptor; + import org.mockito.Captor; + import org.mockito.junit.jupiter.MockitoExtension; + + @ExtendWith(MockitoExtension.class) + public class SyncStateTest { + + private static final Difficulty standardDifficultyPerBlock = Difficulty.ONE; + private static final long OUR_CHAIN_HEAD_NUMBER = 3; + private static final Difficulty OUR_CHAIN_DIFFICULTY = + standardDifficultyPerBlock.multiply(OUR_CHAIN_HEAD_NUMBER); + private static final long TARGET_CHAIN_DELTA = 20; + private static final long TARGET_CHAIN_HEIGHT = OUR_CHAIN_HEAD_NUMBER + TARGET_CHAIN_DELTA; + private static final Difficulty TARGET_DIFFICULTY = + standardDifficultyPerBlock.multiply(TARGET_CHAIN_HEIGHT); + +@@ -527,40 +538,117 @@ public class SyncStateTest { + } + + private EthPeer mockChainIsBetterThan(final EthPeer peer, final boolean isBetter) { + final ChainState chainState = spy(peer.chainState()); + final ChainHeadEstimate chainStateSnapshot = spy(peer.chainStateSnapshot()); + lenient().doReturn(isBetter).when(chainState).chainIsBetterThan(any()); + lenient().doReturn(isBetter).when(chainStateSnapshot).chainIsBetterThan(any()); + final EthPeer mockedPeer = spy(peer); + lenient().doReturn(chainStateSnapshot).when(chainState).getSnapshot(); + lenient().doReturn(chainStateSnapshot).when(mockedPeer).chainStateSnapshot(); + lenient().doReturn(chainState).when(mockedPeer).chainState(); + return mockedPeer; + } + + private void setupOutOfSyncState() { + syncState.setSyncTarget(syncTargetPeer.getEthPeer(), blockchain.getGenesisBlock().getHeader()); + verify(inSyncListener).onInSyncStatusChange(false); + verify(inSyncListenerExact).onInSyncStatusChange(false); + } + ++ @Test ++ public void inSyncCheckDrivenByABlockImportDoesNotTakeTheSyncStateMonitor() { ++ // AERE D-426: upstream hyperledger/besu#11041, ported (unnamed lambda parameter spelled out for Java 21) ++ final List heldMonitorDuringCallback = new ArrayList<>(); ++ syncState.subscribeInSync( ++ ignored -> heldMonitorDuringCallback.add(Thread.holdsLock(syncState)), ++ Synchronizer.DEFAULT_IN_SYNC_TOLERANCE); ++ ++ // Fires the block-added observer and therefore calls checkInSync() on this thread. ++ advanceLocalChain(blockchain.getChainHeadBlockNumber() + 1); ++ ++ assertThat(heldMonitorDuringCallback) ++ .withFailMessage("a block import called checkInSync() while holding the sync state monitor") ++ .isNotEmpty() ++ .containsOnly(false); ++ } ++ ++ /** ++ * AERE D-426: the chain that froze validator 2 of testnet 28001 for 3 h 18 min on 2026-09-28. The chain downloader ++ * sets a sync target (replaceSyncTarget holds this monitor) and publishes the sync status; the BFT mining ++ * coordinator's listener stops the coordinator and waits for the BFT thread, which is importing a block, and the ++ * block-added observer calls checkInSync(). With checkInSync() on the monitor the import cannot finish while the ++ * listener waits, so each side waits for the other. ++ */ ++ @Test ++ public void syncStatusListenerWaitingOnABlockImportDoesNotDeadlockTheImport() throws Exception { ++ final CountDownLatch inCallback = new CountDownLatch(1); ++ final CountDownLatch blockAppended = new CountDownLatch(1); ++ final AtomicBoolean importFinishedWhileListenerWaited = new AtomicBoolean(); ++ final AtomicReference importFailure = new AtomicReference<>(); ++ syncState.subscribeSyncStatus( ++ ignored -> { ++ if (inCallback.getCount() == 0) { ++ return; ++ } ++ inCallback.countDown(); ++ try { ++ // stands for BftMiningCoordinator.stop() -> BftProcessor.awaitStop() ++ importFinishedWhileListenerWaited.set(blockAppended.await(5, TimeUnit.SECONDS)); ++ } catch (final InterruptedException e) { ++ Thread.currentThread().interrupt(); ++ } ++ }); ++ ++ final long headBefore = blockchain.getChainHeadBlockNumber(); ++ final Thread importer = ++ new Thread( ++ () -> { ++ try { ++ if (!inCallback.await(5, TimeUnit.SECONDS)) { ++ return; ++ } ++ // stands for QbftRound.importSealedBlock on the BFT thread ++ advanceLocalChain(headBefore + 1); ++ blockAppended.countDown(); ++ } catch (final Throwable t) { ++ importFailure.set(t); ++ } ++ }, ++ "aere-d426-importer"); ++ importer.start(); ++ ++ // publishes on this thread, as PipelineChainDownloader.startDownloadForSyncTarget does ++ syncState.setSyncTarget(syncTargetPeer.getEthPeer(), blockchain.getGenesisBlock().getHeader()); ++ importer.join(TimeUnit.SECONDS.toMillis(30)); ++ ++ assertThat(importer.isAlive()).withFailMessage("the importer thread never finished").isFalse(); ++ assertThat(importFailure.get()).withFailMessage("the import itself failed: %s", importFailure.get()).isNull(); ++ assertThat(inCallback.getCount()).withFailMessage("the sync status was never published").isZero(); ++ assertThat(blockchain.getChainHeadBlockNumber()).isEqualTo(headBefore + 1); ++ assertThat(importFinishedWhileListenerWaited) ++ .withFailMessage( ++ "a block import could not finish while a sync-status listener waited for it: " ++ + "checkInSync() is taking the monitor that replaceSyncTarget() holds (D-426)") ++ .isTrue(); ++ } ++ + private void advanceLocalChain(final long newChainHeight) { + while (blockchain.getChainHeadBlockNumber() < newChainHeight) { + final BlockHeader parent = blockchain.getChainHeadHeader(); + final Block block = + gen.block( + BlockOptions.create() + .setDifficulty(standardDifficultyPerBlock) + .setParentHash(parent.getHash()) + .setBlockNumber(parent.getNumber() + 1L) + .transactionCount(0)); + final List receipts = gen.receipts(block); + blockchain.appendBlock(block, receipts); + } + } + + /** + * Updates the chain state, such that the peer will end up with an estimated height of {@code + * blockHeight} and an estimated total difficulty of {@code totalDifficulty} + * + * @param peer The peer whose chain should be updated +diff --git a/ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/RLPInput.java b/ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/RLPInput.java +old mode 100644 +new mode 100755 +index 15fc61698b..695f088181 +--- a/ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/RLPInput.java ++++ b/ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/RLPInput.java +@@ -1,33 +1,39 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/aere-bft-bounded-message-lists.patch. + */ + package org.hyperledger.besu.ethereum.rlp; + + import java.math.BigInteger; + import java.net.InetAddress; + import java.util.ArrayList; + import java.util.List; + import java.util.function.Function; + + import org.apache.tuweni.bytes.Bytes; + import org.apache.tuweni.bytes.Bytes32; + import org.apache.tuweni.bytes.Bytes48; + import org.apache.tuweni.units.bigints.UInt256; + import org.apache.tuweni.units.bigints.UInt64; + + /** + * An input used to decode data in RLP encoding. + * + *

    An RLP "value" is fundamentally an {@code Item} defined the following way: + * +@@ -369,41 +375,61 @@ public interface RLPInput { + /** Resets this RLP input to the start. */ + void reset(); + + /** + * Returns a raw {@link Bytes} representation of this RLP list. + * + * @return The raw RLP list. + */ + Bytes currentListAsBytes(); + + /** + * Reads a full list from the input given a method that knows how to read its elements. + * + * @param valueReader A method that can decode a single list element. + * @param The type of the elements of the decoded list. + * @return The next list of this input, where elements are decoded using {@code valueReader}. + * @throws RLPException is the next item to read is not a list, of if any error happens when + * applying {@code valueReader} to read elements of the list. + */ + default List readList(final Function valueReader) { ++ return readList(valueReader, Integer.MAX_VALUE); ++ } ++ ++ /** ++ * Reads a full list from the input, rejecting inputs whose element count exceeds {@code ++ * maxElements}. AERE D-434: ported from upstream hyperledger/besu dd4101c9ec. ++ * ++ * @param valueReader A method that can decode a single list element. ++ * @param maxElements The maximum number of elements the list may contain. ++ * @param The type of the elements of the decoded list. ++ * @return The next list of this input, where elements are decoded using {@code valueReader}. ++ * @throws RLPException if the next item is not a list, if it holds more than {@code maxElements} ++ * elements, or if any error happens when applying {@code valueReader} to read elements. ++ */ ++ default List readList(final Function valueReader, final int maxElements) { + final int size = enterList(); ++ if (size > maxElements) { ++ throw new RLPException( ++ String.format( ++ "List of %d elements exceeds the maximum permitted size of %d", size, maxElements)); ++ } + final List res = size == 0 ? List.of() : new ArrayList<>(size); + for (int i = 0; i < size; i++) { + try { + res.add(valueReader.apply(this)); + } catch (final RLPException e) { + throw e; + } catch (final Exception e) { + throw new RLPException( + String.format("Error applying element decoding function on element %d of the list", i), + e); + } + } + leaveList(); + return res; + } + + default Bytes currentListAsBytesNoCopy(final boolean moveToNextItem) { + throw new UnsupportedOperationException("Not supported by this input"); + } + } +diff --git a/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java b/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java +index 954f4e1e95..eadf4b3c49 100644 +--- a/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java ++++ b/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java +@@ -1,57 +1,63 @@ + /* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/aere-warm-access-hashdos-treeset.patch. + */ + package org.hyperledger.besu.evm.frame; + + import static com.google.common.base.Preconditions.checkState; + import static java.util.Collections.emptySet; + + import org.hyperledger.besu.collections.undo.UndoSet; + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.datatypes.Log; + import org.hyperledger.besu.datatypes.VersionedHash; + import org.hyperledger.besu.datatypes.Wei; + import org.hyperledger.besu.evm.Code; + import org.hyperledger.besu.evm.blockhash.BlockHashLookup; + import org.hyperledger.besu.evm.internal.MemoryEntry; + import org.hyperledger.besu.evm.internal.OperandStack; + import org.hyperledger.besu.evm.internal.StorageEntry; + import org.hyperledger.besu.evm.internal.UnderflowException; + import org.hyperledger.besu.evm.operation.Operation; + import org.hyperledger.besu.evm.worldstate.WorldUpdater; + + import java.util.ArrayList; + import java.util.Deque; + import java.util.HashMap; +-import java.util.HashSet; ++import java.util.TreeSet; + import java.util.List; + import java.util.Map; + import java.util.Optional; + import java.util.Set; + import java.util.function.Consumer; + + import com.google.common.collect.HashMultimap; + import com.google.common.collect.Multimap; + import com.google.common.collect.Table; + import org.apache.tuweni.bytes.Bytes; + import org.apache.tuweni.bytes.Bytes32; + import org.apache.tuweni.bytes.MutableBytes; + import org.apache.tuweni.units.bigints.UInt256; + + /** + * A container object for all the states associated with a message. + * + *

    A message corresponds to an interaction between two accounts. A Transaction spawns at least + * one message when it's processed. Messages can also spawn messages depending on the code executed + * within a message. +@@ -1842,41 +1848,41 @@ public class MessageFrame { + checkState(sender != null, "Missing message frame sender"); + checkState(value != null, "Missing message frame value"); + checkState(apparentValue != null, "Missing message frame apparent value"); + checkState(code != null, "Missing message frame code"); + checkState(completer != null, "Missing message frame completer"); + } + + /** + * Build MessageFrame. + * + * @return instance of MessageFrame + */ + public MessageFrame build() { + validate(); + + WorldUpdater updater; + boolean newStatic; + TxValues newTxValues; + + if (parentMessageFrame == null) { +- HashSet

    warmedUpAddresses = new HashSet<>(); ++ TreeSet
    warmedUpAddresses = new TreeSet<>(); // AERE D-434 (adfa98d013): TreeSet defeats the grindable base-31 HashDoS + warmedUpAddresses.add(contract); + newTxValues = + TxValues.forTransaction( + blockHashLookup, + maxStackSize, + UndoSet.of(warmedUpAddresses), + originator, + gasPrice, + blobGasPrice, + blockValues, + miningBeneficiary, + versionedHashes); + updater = worldUpdater; + newStatic = isStatic; + } else { + newTxValues = parentMessageFrame.txValues; + updater = parentMessageFrame.getWorldUpdater().updater(); + newStatic = isStatic || parentMessageFrame.isStatic; + parentMessageFrame.warmUpAddress(contract); + } +diff --git a/evm/src/main/java/org/hyperledger/besu/evm/frame/TxValues.java b/evm/src/main/java/org/hyperledger/besu/evm/frame/TxValues.java +index d4c9edad39..b13a96f5bb 100644 +--- a/evm/src/main/java/org/hyperledger/besu/evm/frame/TxValues.java ++++ b/evm/src/main/java/org/hyperledger/besu/evm/frame/TxValues.java +@@ -1,51 +1,57 @@ + /* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/aere-warm-access-hashdos-treeset.patch. + */ + package org.hyperledger.besu.evm.frame; + + import org.hyperledger.besu.collections.undo.UndoScalar; + import org.hyperledger.besu.collections.undo.UndoSet; + import org.hyperledger.besu.collections.undo.UndoTable; + import org.hyperledger.besu.datatypes.Address; + import org.hyperledger.besu.datatypes.VersionedHash; + import org.hyperledger.besu.datatypes.Wei; + import org.hyperledger.besu.evm.blockhash.BlockHashLookup; + + import java.util.ArrayDeque; + import java.util.Deque; +-import java.util.HashSet; ++import java.util.TreeSet; + import java.util.List; + import java.util.Optional; + +-import com.google.common.collect.HashBasedTable; ++import com.google.common.collect.TreeBasedTable; + import org.apache.tuweni.bytes.Bytes32; + + /** + * Transaction Values used by various EVM Opcodes. These are the values that either do not change or + * the backing stores whose changes transcend message frames and are not part of state, such as + * transient storage and address warming. + * + * @param blockHashLookup The block hash lookup function + * @param maxStackSize The maximum stack size + * @param warmedUpAddresses The warmed-up addresses + * @param warmedUpStorage The warmed-up storage + * @param originator The originator address + * @param gasPrice The gas price + * @param blobGasPrice The blob gas price + * @param blockValues The block values + * @param messageFrameStack The message frame stack + * @param miningBeneficiary The mining beneficiary address + * @param versionedHashes The optional list of versioned hashes + * @param transientStorage The transient storage + * @param creates The set of addresses that creates +@@ -93,51 +99,51 @@ public record TxValues( + * @param blobGasPrice the blob gas price + * @param blockValues the block values + * @param miningBeneficiary the mining beneficiary + * @param versionedHashes optional versioned hashes + * @return a new TxValues instance + */ + public static TxValues forTransaction( + final BlockHashLookup blockHashLookup, + final int maxStackSize, + final UndoSet
    warmedUpAddresses, + final Address originator, + final Wei gasPrice, + final Wei blobGasPrice, + final BlockValues blockValues, + final Address miningBeneficiary, + final Optional> versionedHashes) { + return new TxValues( + blockHashLookup, + maxStackSize, + warmedUpAddresses, +- UndoTable.of(HashBasedTable.create()), ++ UndoTable.of(TreeBasedTable.create()), + originator, + gasPrice, + blobGasPrice, + blockValues, + new ArrayDeque<>(), + miningBeneficiary, + versionedHashes, +- UndoTable.of(HashBasedTable.create()), +- UndoSet.of(new HashSet<>()), +- UndoSet.of(new HashSet<>()), ++ UndoTable.of(TreeBasedTable.create()), ++ UndoSet.of(new TreeSet<>()), ++ UndoSet.of(new TreeSet<>()), + new UndoScalar<>(0L), + new UndoScalar<>(0L), + new UndoScalar<>(0L), + new long[] {0L}, + new long[] {0L}); + } + + /** + * For all data stored in this record, undo the changes since the mark. + * + * @param mark the mark to which it should be rolled back to + */ + public void undoChanges(final long mark) { + warmedUpAddresses.undo(mark); + warmedUpStorage.undo(mark); + transientStorage.undo(mark); + creates.undo(mark); + selfDestructs.undo(mark); + gasRefunds.undo(mark); + stateGasUsed.undo(mark); +diff --git a/evm/src/main/java/org/hyperledger/besu/evm/precompile/P256VerifyPrecompiledContract.java b/evm/src/main/java/org/hyperledger/besu/evm/precompile/P256VerifyPrecompiledContract.java +index 47b7145d17..220194b6ab 100644 +--- a/evm/src/main/java/org/hyperledger/besu/evm/precompile/P256VerifyPrecompiledContract.java ++++ b/evm/src/main/java/org/hyperledger/besu/evm/precompile/P256VerifyPrecompiledContract.java +@@ -1,33 +1,39 @@ + /* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Modifications Copyright contributors to the Aere Network. ++ * ++ * This file was modified by contributors to the Aere Network, as required by section 4(b) of the ++ * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was ++ * found, as section 4(c) requires. The change itself is in patches/aere-drop-per-request-console-writes.patch. + */ + package org.hyperledger.besu.evm.precompile; + + import org.hyperledger.besu.crypto.SECP256R1; + import org.hyperledger.besu.crypto.SECPPublicKey; + import org.hyperledger.besu.crypto.SECPSignature; + import org.hyperledger.besu.crypto.SignatureAlgorithm; + import org.hyperledger.besu.evm.frame.MessageFrame; + import org.hyperledger.besu.evm.gascalculator.GasCalculator; + import org.hyperledger.besu.nativelib.boringssl.BoringSSLPrecompiles; + + import java.math.BigInteger; + + import com.github.benmanes.caffeine.cache.Cache; + import com.github.benmanes.caffeine.cache.Caffeine; + import jakarta.validation.constraints.NotNull; + import org.apache.tuweni.bytes.Bytes; + import org.apache.tuweni.bytes.Bytes32; + import org.bouncycastle.asn1.sec.SECNamedCurves; + import org.bouncycastle.asn1.x9.X9ECParameters; +@@ -152,41 +158,41 @@ public class P256VerifyPrecompiledContract extends AbstractPrecompiledContract { + } + } else { + cacheEventConsumer.accept(new CacheEvent(PRECOMPILE_NAME, CacheMetric.MISS)); + } + } + + try { + if (useNativeBoringSSL) { + res = computeNative(input); + } else { + res = computeDefault(input); + } + + if (enableResultCaching) { + p256VerifyCache.put(cacheKey, res); + } + return res.cachedResult(); + + } catch (Exception e) { + LOG.warn("P256VERIFY verification failed: {}", e.getMessage()); +- System.err.println("P256VERIFY verification failed: " + e.getMessage()); ++ // AERE D-434 (fbfb5f9ecd): removed System.err print on the P256VERIFY failure path; a cheap invalid signature could otherwise spam the process console, bypassing log4j. LOG.warn above records it. + return PrecompileContractResult.success(INVALID); + } + } + + @NotNull + private static PrecompileInputResultTuple computeNative(final Bytes input) { + PrecompileInputResultTuple res; + BoringSSLPrecompiles.P256VerifyResult result = + BoringSSLPrecompiles.p256Verify(input.toArrayUnsafe(), input.size()); + + if (result.status != 0) { + LOG.atTrace().setMessage("Verify failed: {}").addArgument(result.error).log(); + } + res = + new PrecompileInputResultTuple( + enableResultCaching ? input.copy() : input, + PrecompileContractResult.success(result.status == 0 ? VALID : INVALID)); + return res; + } + diff --git a/registries/SHA256SUMS b/registries/SHA256SUMS index 06b8696..59da814 100644 --- a/registries/SHA256SUMS +++ b/registries/SHA256SUMS @@ -4,3 +4,4 @@ c9a215d294e106f69fb2f16e3af21f9787523969e4b7260a3098f4b2cf458059 *registru-2800- f155bd46958cd533e710f79aac4fd96549d7b6ca54df17df71a4e5d876012c59 *hibrid-1.properties c6601ae5159875a090066946991517c9a38e5d6206da76b018c0917e1ca6f12f *manifest-18082816.json 35d69f60e357d405aff39fd33858de901dfb21327b0c4aeb18be17ffdaa115d6 *hibrid-10.properties +0212d8ff9e857f1c756b0004929e9ad4c7988341af4837d947e7b5263fb8c581 *epoca-v3-2800-20836228.json diff --git a/registries/epoca-v3-2800-20836228.json b/registries/epoca-v3-2800-20836228.json new file mode 100644 index 0000000..ebf5143 --- /dev/null +++ b/registries/epoca-v3-2800-20836228.json @@ -0,0 +1,187 @@ +{ + "0": { + "id": "0xf58a3907d9b97b62dc227272997d4abba02e4fba", + "keys": { + "falcon-512": "0x093b946f7ac3adbb6b49eb1426d60f07725a1b9409d472c9e8ea47a8e4ba38bfc773de905f06c51860d4e83eecf5f5621329634c3d9061816305c1fc89d55ba937f97b6482cd055895c8b4864b549ca4bb197244771d0635828882718142fb6800cbac04bd6005e3ae582f7e3ab704471877faec7aa6e1e96d1912a6e763f74dae69c2ccee323c06e5515fcc6880a2d96935220f50ac5bb02343fd2985a1b3b78f0a8548abd6702adc2e298bc113dd37411454286c29ec5592b963fae4bd7042fa6877e2363fd03c9a95e97da50144f02690d0b97ca332d14f9332edc0b0c5e5b27279569526523034d65b618147d267fdc5a35220091cca00b7456ed9bb1def448f4105bded1e79e1e34a6de8bed08a24383b954d47b3df5d1d8ae8b5e8592a92bc80b4220a7c0bb123cba55ae14371ca1716282276416c82772795ab0191c2562f189700469714ca5500b94beb23ad45a41ddef1184eda4d06f4286da21c0fdcb450e760d84401968a4e0fd19dc49bb1fa0bd79be005d781a4f19d5c40e71a4e6ab3ccf4413bd7f922799d28554f19609d7e4746e6519c8d029a1a1a548d369498feef77438051dbc2e024ac08220934dd42264acc038beebb5314f198589b211a81d8f1ef97e41af8d9b0de9fcc7b645cd80fc72c8c255e34495c51a060628205d48a11f9992b3865d59e692879a9ea9c6af9b831986e852c2583f35b1ef9aa55d41b1d18dd7162aab0ff4931476092f9d7e2f078f44ea2d0da699d362b8a0de3f140640826788faf7c7d4c0aee4b88a14cde9300a7253ac6c9b8de188515720f130a94673465e0f1e84a501b6c390b2ae84ba44a449320de37b26520e12988a11911465afdd2fc9b161965d3ccc15a0559930810104a6e40d17f629cacb8fb3973af0967c679a7d8c93b8aa833a28d6ae975913d0096a1416d79779c00052b2f19f479251a76264084552e99a76d42cc8572dd2573de7497472bc096e29cd7b81a2c1e8c20688e84245a46e159080bc976d98581b7a1023f94a5947cd244ad487b0193a62cb799afd30a8bfebb6a23ead4da7d2c7993919913583deef2311da82a924594d11f1e337b1ebd4364405c0cc88f57254261441d7a0b416492af894a9920e2c34cddcae506e16581b977e978150402663246b709bf9a4a0264050c4c972d86258d40eb8a046755ab187663109ad0aeab371f798b503c2ae73da67c5b8069dbaf06c0b6af28e0007dc22a766fdc3e1a87439258e65a701d8098d474", + "slh-dsa-sha2-128s": "0x5a223b6ccd6991221265ed715c0d0656a5f14aa3820624d21f044a9fe480f427" + }, + "pop": { + "falcon-512": "0x396e2d4ecdb3d71dde4dd83bb7cc3a5e269ca889b91a1015995a66ef8b0297101822abbbae913419e10088c969716d1356821ffcd24ec4b3e2dfc4fbb59c2e3a77e8cc32ae7a5e8454a28e4639bf98916fcb7e6c88b4b84af198cba4672d8f541854293a223166f2db83b3e3e4ccca0022c8167c8f5b2226653cc4613059b388a7ed705f8d24847a2286ce19a6687131da6d550a30337aa2d54c1dfc5984a01884ef1a68e87939d464db73b5989ad30fb2a0c6773219bc4d0c4278991fb58517207a1b1ac7b2d1b343f3a067c685e19c2dffb933868a190c43e637f11308667993fe9ab9cb71ea4cc7d1baca5af5b1235289e2d2646e90824ce04db792a5929d335ae852dce75d545a2de636fa6526c5327e8d35679b42a57d71900306e8f6a2ed7cd9bda59b87b39b2e88a3781c91814a4b8b66875564627cf95d1829bf4a2b724f5aa3692f50e7bd2f4e77d9bcc7384b913c4edf94563660b6ad3b7d9843d00e4c8a30d315c4aae51782337a8608fde45b73df92d5b63802a5b4c521a40674a97be009b9c6ff4fca925c789d1cca8b59f4e12456f81c05c97e1e18edbea582427bc4772265ae0d524d00794bf38d0d340cd97de2dd35d05efa1705e89b74e63c580813a9ba415a682367c29fe82d5afbcd38dbb6765661b4765f9832014e495add96f63349ccde4c4cba14a8a40ddebede74ff71a66073bbfb7c30c931319338d122cdccb33f0b7b1078bda377a1fbffb3a7db8fd2d1438ddb650713a8edc6379150a29aedca7315551b8a5deb087e616eb6908c8a1d02fd988ffe8a82c59fa522d0799d7712e953ab10736c8013fcfb6b2841c92523511a91cef18c96990e757ef0a33a3408543ed1b38b47cc37a55d9fa856420fd1c5ab1bdd8e81ac42042899b73cbabf3a8ed12353c6cd228a0c22", + "slh-dsa-sha2-128s": "0x29ddcac29e2b0d9fc60de3a6951cf1feff29747d2086114b029599b5c8992349b7f78942168a96d01c3a4d537fe07525d147f3462a3ebad27523eaac01a00299d709a1e11c232d2a4ecbc82984fffa54c4b05ffac50f4a9f5caa21ae9a541f2f7e048f0bd1079e47a3968d9c9d1eb2a2ead870c6eebe9648e89c6447f6ff0a2795069d2f3aee68249409fdc2834b19159119e498991bbe97134b2ee2a334325009e21ffc5cca4bfb458b1fc8ba66487a8021a694be123869bddfec9a7ddaaa8cc23984a2e280228e9a9fef9d836271ec26a3ce534df0c70bf8a3dd1f2a2c546b2d7ed84444ffb85923d594f621269505267923b88a6fc52b9a0c4971f18022f5e008ab8d46611e683e88f17d3670fe1984c3c7e90fe1a09ba9271f4037ddd7e63eeb6544a139c2901cde0f9ef544adb64b78f5d4dbf5ca6371ed5c666a0166780b26dd465c11677242deeecc88eebf2c358dc3543f7514f86efbe45df7593225eb51fb1dc79c6ccec229160bcbeaac2c8a5baea148572c957773dee7ccb2823e07b9ea0955698f5ad28176a50e12b3179fd23e7e9b43113e0d90a40fa11f66bba66d88c1b56af0d97b065cd8c63fbcacc70686577684448be4e553929bb7c8906eaf7054cf8dbca2f0f6103034277dc8bf058c89a5369dc5e944df748e9d7910f6922b9c83f00ffaf3c05aa0226252a0fb4e14d5a2053ce0ae6871b124cc5633da00ef016838ae871d72346e456cbcd1ffe00ca1170c02b9ac1e85a62d90e981a3e901889eeaf2a8943ba5d161c1669644d8283c40ac97da753e1b51cd12012c7d2a19787b9b1a093780239b78bf93f18fa4d9905496dc4558d43f133e312f85deff905fedde09cca158b31f9efddb3f86e653196d2699849255c80d3050cf3d7fa5d54ce82bd442f1ab36788a91bfd8c3d964443d2cd888a1a4cae77d428992fba164eae5b00430b6c07f7d0654e32b0e91cf3eba7a3a5eafa00af26576f545c30c5ada2ae317833ab02a62778df9ddf19dae2d095e2cd618bc1c697e34478de541ef06a4cd315562e5d3b0f98dd6b2334e111646339c872027964a12ca12bf8921771ad149b49e6ddf5866de52e3e0dc0d7ec6522638591c655477a64ac2a0dd1a015c5403ebd58bbc3878cf6fbb10f642eaaef1370579d2b2223cdbf39b5a3c43ec27e6cb5e1c38208c5d65fd8c4008a8a4188f9b7611396c9d967ccf4e03e3209c69840e3a68c2850bb2216137c9458cd77a0ff5355265e1ed44ea62369346b0c4b3b415069656d3103ece26da2f3547b0beb6d9f30f08ae4c931b72861c6de4073d4c6fcd5b510ce27a711b501a72b44b7b3ae6655447fee49750c52181e45282720238fe7cc80da37723f65c9dd337fd59f904419f12a777c0a94f1803ac3b5ec2acb8a4e5dd6f465972d66fe4663ac13ac6509f4fb02058994b96ad088f623f3cad8da2d7f1d5eb16afd00a07492de430f05a4b7b80742c1d489cfda0c74fd14ffea6284d20ca70d05de84279cee420d684a5f10b16fb0544fa82f6c4cf48f0ac36973c33cc6d2eff185353c3814f7d6f15d73ad1e96a49a4de73023bc82181b463f8ea133f9e10d640dfeb7df13a7993d1efe40a3629a10aad19080d67862dd390c46252a5e4abc62289f4e570e89eb0b411d0d68369eb29ffc18b5c31746601a4a5bb7366b0ef07471e78b081ab985d080118b4b76351e41ef09eae0e13766362f4f0a87320509fc9bbe9abf02db6a958ff8b6ce5925933e65d39c1035ea3dc1e90d345ad050abc595c722270511c06f4a5a0d37702043a81422f1da3c4f17de63e987c7e85123eb03e78b00ed2912f7b31be685f3c8fdabb4fe07c0ebc41de2dfc8cda74a4641cea4b7a21f0f77ea4c5c45e3c3117d254c368f0a6eb7bc1a7d869836329e1438b2ba90b7b77f3de4d02fe6eee54023d486c351611ed08945f6b71b788702a93a03af266b1dc2e28eb716d4cefd33ee2cd50953431aac6e15bedbb837449bfa3f1db447e8f0865a7e6b8839e624b8a24ef93bc0017842a83a4ff3c2524bbebc974a2016ae5d1577c665d414b85cd094c628851640356f27ef763a9f49221fca5f8eebd5496a36d032f2895b785268c2f42931d0a66f1b16b8f508e0a9edb939771ffa61600e07f299d5fda6f490430ab1a6294d8e0cfdac77f703d4d6bf7e303f6df7319974b7e78004f07a2d7e6cda5d8b99a0e8d41b19c33e4aa37b8331fa99b68c8b2282799b0f72733ddacd31a938fc0dabc4d722f0913afe78fe417a56e1a71d62334094ae5fb65209bed8c757dc1e173e4059d966432449040336809d18fbec5ccce2842ea3c2262fc36dbff24e3da6703975de3546e4b294e2fbf760a808a2aee896c485d40fc80e34981eac9bc16a0dabb6273d4463a0b3f55f9f3d2dbc0c7b72cc6101d07804e028178475474836b1964aeaaf306df7778539d1459c7f3eb27d6162c14c3d32802c9721dee10fc234ca52462afff3c791fabb578d676fedb0ee00afa33345984fa42068a4f9ad88c68dbe25f5cfed4d650ffbd2e4d6cd88eb9a944913bad10c37c2b3000a6d9550b9074a81651cc5442e228a5f3df130e36723be1e9864c295316cdb7abb4c255e83ea43bd92b920bb2590c04ec8cb1a901a521efb9409ce698d7ed9de43a79f276162648e713cd8a2aaf7a416851dd85cb009c27ab97e42890e67dd4d39bd9045d125e3263532c382070ea2fb0075095d13dac47337411cf41700341ca50b55b262c711cdaaa4a798214fcd179932a0003115c7a93e2e0b97ded255e405cf7a7dea4bf3e52351f15d33a17d744a3520b0ca7c314e0fca41c888511aaf2c1c2e21b957b5854d45da19ef08d93d41995e63e136abf5c88130152dd0424b3d5aab4bed7674fe649693671d5ce6a8e0ae93b98598aea81b3abbe1b32bbde9051305894179a8fb9bd5f79c59454a0370fb8addc859393b8c153728ccdaa0de2b58aaf9d4cebce4637ff93093f23d75656f84a335d4ca0fe7041a0b1824f96b375842aece0c98aa477f17af048d9fdc4a48f071d51f2b836763074cfb1a0ca7f788416244f80df03b6b30de61ab8b3889f96a8c678951303dd308aae1d1dbd200c04f35b7d0d6b49b1d0e5b3d278340994439fbe3a9a877135e79088bef2e2e131fc92929b286739010a69bcbafe0ed7d2c682da2b108f03333d0f8f8e58b3b5fa5f2c5f6d300c0e032fab28e2403f01307d751997f728aac7a3317bf767efb08c6740e4d87007a4181a9f4fb3fcd535d9d7a67d0440b24c32b2ed8a0063d5343957ad41d9af5aaeb0993c110cd4597924f034440fc81c1e4d0a943ce21631a2c47471fec8078844d0a2f62beb71abb398da551ca8ca9f266e6cc5cc5f7d90a5721c16cb28b5a04ed3f32a97d488bddcb82f6cd22fe0b43e9accd47c7d817ff3920bcd9d09ec1dc7ff251d7a90f12c351268f9eb2da7194a4b5c4ece0d51e7f44e9fa4078662c60453acc8003ca90235174201628014b7c7c8e3b8918a8bc470c89ff4fd8ef98f196bae5443e012b44ef2af56745ff703771db1697e0c70afa5fc0591a388f4e177ea9a6c62eb35ed35d1c08a73d57c2102dd8b43c7cb5906a6d66bd2a636cb4e7b3fe886c478941b0b7b29b24fa637412a98778c66f743dbf78beef219d0429caa84b4a903c6e2820d53fc8b34dd69d1fb8e5b93ca0ac6c9112167caa1de363cd95d98d9ddc92904d11d9f5db1db400c239210651474ecfc18d0918a8bb7ee615661d053cab59e91b5385f3d0b92af62688187acb8b347bbd047f6afa568782cc1f268fb453a1d3fd6157e809f88f25f3c87fe5af62dd5493ff35ac736108689d0fbd26757fe2794437ea732999783beb3422a7067f6ef13f15a9ba19076db8485794ba741d009a778b2ffb19021a44564c657d54a3bae9903e703a52f0dd93197b586ec744be2c3d57dea6996bdfbdd790cfdf9119bba3788a8f5d49c6b32725dc5fc86346607fd7675ae6d782cd18a9ee008095cdd2af037f772367c67dbc1368aca14efb9174efacdccfa05806a0668d399595627d13ad4b7c9c6a688d7174600d4a9012bd4ba857ebcd8969d6a266b49ed910333e012f45e4d81bf9933faaef34f79eabd32de7afcb5ca169b054312f49ed419e3f8855e53a3c146d08499f90b6126ca885e60e2ceb2f31c76afa4e1a520009d55dbc3ba9f04e5c65ec8b9c4e4bbe357aeaa83d8fcc7e72a5cbf0155b305d114f134b0809197ecb0b8abb823fe294b9348d215c578badcaa64150b2bb286a0e013717602b9a940b64397eb6ddae53b980ad51dba0c5d996255277f31e028c2fd46d84e89f3836c8094a18e1e2bca7763acbee1ca2a915a4b07f3c6afaf257caf187993b5607d02369d395503a7d4a1a5c59eddaf589151a9d3da4cd8484f5a19f37874e063786c1a72df389c77e92f4031f0547904eb04df03a2b2a40f70d75312283067c87a8bbcb9743c5d76c63a04c2b8c00221d6c32a4980debc183bbf39f8fcd74346ed254848515e187b52ce4d2403f009706fca9dfd6ace2665a8ddfa94dcec8d5416be33d51f52f50b14ce72f0dd19509b87a1a2835eb10595bedd9828bdae26f0dab24b6a2dc735ff9c1a555d92880a78d9a790979c7ddeea6f43c1f3fed7e982567e0143224b5ae90079252f5b50366b88a9af01f905559baba363d3a9d1b9d3821462202cf1ca579a9dfa362df14fd5456ee5742dca251daf3ee34b15f161b9a8441453488ef04a199ed79d9bb9c5ad289c55a6eff41e0844812b4d792ee124e05d54d526a829384ccd9002d5934460299ed1ce2ddf0b15c37f58d28e805b535d866dc4549090a6ddf4fce357455cd49dfb821d6f9ad0606b6ede08f71734974470d8faabc1d7367edbacf27c25c7bf7e1d19764a9876037acb2a9a90ee0766337d798ae1e9d1c69c4457bb569ac3b313399d51919c1939d06616045a9523e4644d5c413c47087c653a535a35ac9350e12302cd8c493c49063dbf1b7e7da79f6bd2ac433bd131ddf99bcfd27fa1a543ff36aed2b70b6af045cb2b532011c8c1e6f54e5647522de56153c8d07d72586e80ea2d03360543c0cd99343be60c5e0857f26c14000a493ef668aafadb286a42bdbc864ae7da15e5b890a688d85e510206de7ad0486a18bd329a68a12d5f6b1899d05c9657b3d15bf0221d210c8d9dfd2b752b2c69ddadd340766071a21fee8ec3a445c33492e18540e0cc090a7a0d11930e02c89de3795b5d39556084c3a5477dc17f464f581ba7dbd2726df2bb09e8410d5414f2069543cb2145b677020173ee6bcdf3fd3072c1d198f14c7fbf9bd01061dd7939f2352a1b5b938a3aaa316936c1283b0f30ba2ab55a06dc5f4f1873ec3f906c28783d3faf542e4b3a9032cdbec7e3a8f18b195fd3f72c2c3105f8ed1690aed86976db35af07ebbee295f7f0fd2b12722727ce9b74d87c8d371ad90e857f1054df92b5a1a74fe1c7592c98e74f23ca23c76ea3ad172cf93a45f3e4199265cf6d940d102685975c5c224acdc065b58c7b2117185cceaad7bce1d1d43b24c270aed5a29a74723a2f1f6274cb16319e79bb4f82a94cd7fba312bfc677fe4ddf6200f5129ec6b104346feecbffa27cb000d35bd12068cca21f6d0e33daa760a40e2477fd9809b47902051c04bc2343a5f54755a826bdaa73143fe52e9a7388a9bf927310ef256555b9fda699b9ebf94ba9771ea667c18102054c580d7d2d56a37473f86bb79ef9bb427d4ad0defbcd6ebca030175164bcfe4672ef5a2ae8aa378d1b496c34d42ee7a19693d74fd5d7497d0b5985eb2145e36770f43e13ee49d5139271a6c59739727bebfbee21ffb23adbe9fb3de88628b2122a0ea6059af4e81b3a05436154d3d5cfc1032c8868c73ab44524d20924e17e4f9f2f13024fc9195f2087c39df39f7d0848a9d93701b399cf45ffa99bee62b04e2f25d8c871d4f317cc03d669ab89849c970651704c6b347b1ece5b75eadfae4ac7b5d9cb1e5a5c1606f80cb1df3fe15455d3e1f0f88aac7c667896c1f6fd5cc424800ffda10b03be3bd08c20e2e5cc0a6104853e22467aa4ec0a6623388b911efd163538d6caa832a7c13832d66d1e7dce0a061c937c6fb4e97cfef3d3e65f2576d6a6143485f15054f64012767199d5d34c517a25c9a6aa0bb90c5559e26d74082f586125e3eabb95448c226f0a0f077b10917dae1fa087c35cec956988874b395c5224b18a98916188e8ef42f9975b3a484179ddea337a3de6c9bf33ae1a9419202f29bc38a313b120f71f9c4c77c02e07dd90219793f56743c0c4828a3605aa779eafdcf40fb334d7b4ad56e875214fe1a0b62ade7007d6feddca0a88e57d33d022e62b6f924fa938343371c174dd1c9fe79ad63cdf290ed8cdc17beff928ee4c108bf7e6af6c0471ee291ec5dbd0059ecd6c59c222fcf411c352f67d29acfe29c2e14bda4de2cf7d582e3be744d7710ca494f871cdf63f4420dae4e96283804c72b421f4237b35066fd4cc5eb1ef700f69043578b3e5272a66474a4d910cc3a82c3684e2f48a946c521b56a9174e31ba8a199e0c9dce4770005761f6061e18f35fac3e09d8130543f1f7432ec96df22a472fb2929a20ea125c2fa1769ad7e7d1350572a40a8f6a38bb80820d0d7124914d374b811153f72f22b850b61c039e4f5d35ca859d4df35c3551c9dbddb02ee0c4c3edd8101c4f20b1634ca990ccfc46d14a47b3165f2a193ca71ce765748cad87ddf393d3f9e27b513d044bb7d7b577dc2b7f48a370967da0b98a29d05c62f8a1fa6143ed3ee1a529c5fde921374d8930fa39b4dcfafa9ea5795ebe1e88e78837d18434878961f4ffd35641fe2c78844f347d2c77b25fa66801eed49fd999def7bd24f3ff2ebabe482a645dc500c7f63534203049fcd40f048616dbb4d192314729d140a0c54bfb9f769b36ceff584c9d9082d6ae924a502d9af237d8bcc13f44a3fb6efe3dad193fed42a484c1c8984999af8fbb8cc016a705bfdf187d722f6c5cc9c6bf3e1f47f525d263583e0f7d4246bc12b9754aed6fb55794c759d807ec1d807f6d359fe6ccd890f9c14fdcfeb32cff4bf9b39cf451d64e2efe9360034c709a7f0ebe896db8d93894847c385b38025db563f845d402ec959a22a2a8751515cda02937cd53113174f3caf3780989f05dcebeb0a5fa13221bea09031d77292f790c6bc892cb31dcfc25fcfba80d6f70358197194a11ee1c1164fdd9df24353bc7dd6ed2b2669f813291344a6f77c72a197c8c3b9996d1d58bddd66d266f02e2de6d3db855b44b24c82df7ef63e25e506fc4224fd5f5afc2607ca9a2cb882175ce52a3d464aeafd1b7e3304ef50f98940e79843e5771e28a16a2a5ddf909e89b3029cf6a49a373811691a269bd540e4b17a40b992173219a6050dcf945ebdaf70684387a21b91aea9387576aaece815c0b08a738c2badf23e1acc554daa181aee4be102201f06e91edf4890811218526fae6a04392504ba1d54d170ef5ccd6baaf5221aff57169a3fae612469069bc432b232047e6fc4f821c51780668855f62ff2fe3cf1f8e5dcea5f7a6a3deed47dfa7762987224c902997c29ce15a2b9fc3f1911e3fdcf5d2961a37f7925aeaa5f6873a6e994d378a76f8e56dc55528f0669724bac42303887aeee6838d42901441abcd14eb597a45ea7c40df82f07c9cef68a2e6f7cfb83a1565fa312ffa0d8e33f4f17c9b1bf914200441bad975bd489b1377067c3fa69e9208100fe1389306a1d522646a0441589aea100126e21ff2cc59c9080b98a9a7e26814ecf93c7ca1170e709c88cf28524f886087d4f3c551597718fadf8d118d0a27377c4e40d0881a08598e5732d41227fb6dfa8a4aa08fee2317b32bb7ecfb08e22a0019815a1a0ffcba32043ece6f7a7021320c6eae5a79bae7a1da7df46d94de252a5b686330d2a3e8e07b38917e31fca3a8010b5d9cd523bc6a104272db6e4e9ef08577f40a175a001119d73306dd76a3674129d56d0b6caa56025db32696959d2f11e1c6e71c3bd0f2abfe1502b2601cd20c4dd4eb250115c8c066a3532db1ef4b4c0f258931d1a56aa4260db064671e17665486eafdec47d94ac45b64cb86458ad7a70e31f34c31914f47f37f6828b57e770055372b46a34b832c3332577df3150c443a090138961b7bed4f58f2a1bdc3ef9530c75979f6b09f116cc441416bf53c4941a99a3771adb2246f2b60172806abf975b726125b296af280580190525275c54c430df249b718202ee902cbae1d2fb9dcdad75e2c2319a20df7d15f4aea5c25906d68c461339c44ddcfb2371759633ab081acc1af1b76caf99c04eb5b1ac2ecec82e34813d36003497e8e348d3be5c8093365f3e97d4ed8f34ed3da556c07371b18fd47e1142752776d966f010e991ff6a5b62ebf6b6464bdd1d7328ed59396864b22f52b91407056b9f3fea234ccfa370bf2283f6f5b31aa6c8af725daab02e2b1b5f496d27396f1de6402bf044803beb508ec8f8d46ecc87c2d454c02f938c77993186214ebb3be2b5d2a7c342d61e0e8df09159c0d5366bf404d4b40e69cebf8c5b9b4eeb65bcc517c9c33d90425e4b1e87bc90839cbe350ef66f908ad3cf14b7b08df3fed75346a66bebfeccdbdcd6c1d81ad2928efb64ca4a99cf476acfe207e727c17b40857abb56d628aa3fdd159fd8a391b63b64f3613d3c337fd9916c2149ffb91d495a1d8acb5958e5782485721009594ba56d7b581e1608f11de3444a2b7109186f1e4159150a2c482991352e21a8d2a42e64fdf1f855c62a29cc3b0db48be013bc556c03c0b242ae23e6f08c0baca0746067697766c1833c1a1d04388c6d5ce263419cb67da8ef3349cc6e11fbacfe5a0641b5bcc2079b6b8c854e261ec9483bd0dad0042005a8b906447b26eba675a4581d5322310cd22fcf5e0e19944c5cdcd1f6fc5b1febeddfc2b9cd81b4391e287e3e954a7b9b7d6230d6d9e70f8b8c645639a9fb64b4fc8a71bf085a95b9994b5244cea0dcac437fc0a27599eb2f98ebac09aa405232645a305ac8ce7006470a583e9bffda79c0fc09407936e3597d9c0bea022b8348455e03e50bd6ad4e5eb6cb9df3065e1eb64e0a46f7310a513d7d0105d103dc048e2a3b0a3c941fc3ad12755ab18c84299ef4fb9f12d44fa5407251602dbc26486fcc87217fe4b1dc8c750067f1af5ee0fb52e19bb628bd8f8882e9cf91b24aac1edff9436d8c15344b720809f085a3f1ef4acb6d56712717ccd37120f772f9c332176b54c81deb762dd24e206e81216e2796fe911087c36a2b8bea4481691217c357c6f0f7ee4c602337c13b70106c9ddfb34eb8d3820a11585ea53398171a0d7b074f34b0ea4271ee28d0d196497993f586ba5b10b9e3851a25520dc810ef1a4c4ff2809d94c72458f42cd680aba7400f5112a08fc8980ea7b89c46684fd6551195468a0a7bed6bb3f8ea3056a158ab7353199ac150aff4b7938eac7e0b6669e5464f94bc6700e51575f59ea46f7eeed1fdac53d5dd0d7192d57fc66150af79aed677a75a7cca6c767fb8883322e597d69aa36fb54d0a55d75ac75ba5fbaa67a255325f70afd6e06eec24b7f6c76d6fe96f24b482ef894466c487bddc749fb3d5fbeae751fd401b04b0f0e0950dc914d8450d31422dc3308b448e7ab0ae076f97eef48dda41e3566608b2cefd06d67a012003b0bd5e6d9e4db2541b37caa96523b00d5558c4308b1cb3df31974b3b9bdc58f63dc001edb04a4e0f0a5e2de6530b0cbe68f76d755abc8d5572fd77f70acb4f30c2f4a9689f319a676cae8e99eefcf75ba8425f8828f1935867b47b11c640d7199ec300630f9240d02b888ae2c86782804023031f0ce14d3aa30ef08b252a630cc77b5d2e1666096738b623c209b56c38d8176bcd9ea8e3ed3398d9ac6c848436ee73ee15623a6febfa7ef1be57704057447a287dcd4cf7503a948bc6431e9a0c8e12c75ad8c8abec7b21b2c2fc1dc1155e31dd6facec818a4fe7a6ebe93c6c9a8ad57158099a8db8e686fdb4b4976b9632d3f2033fa0db97d3a90160c490d86141a4e1f122af407c242b60aee2632eec367632f157f099b244766d2ab6e087b2d493bedcf510d795e62d7496677e0ef713be959a245e181590b49ad20263fb3624c69c22e12c266b5680b9c53dc1a67a4d3104f48bbdd872c9ca9a82e9b153d2d6ec21df5750e3b4daa455a73630ed304ecf1c003731a073148db62736ac24e6bcec381c9ea26c70ab57c2ddb2c6e8a0e4f80582bf1ca36df9c46529ebde48eed6efcb65e6cce305b9e33e3f753cf086ef72693455f204f045a946fe51c548694f2f222292d8c4ed412662005452512c141193697cc8e2e0af365fe76bb9955d5fe70f7a4866485f2f8120a0306c1bc1b867ffac36eeb02863568525195250669b133556f326ddd0609810e32b4975b741981485e3c5d0dd265fcfa31fa3d30056fbf30c834a1ce5808ba2a176934ff103671b38fd1c66b07f1240fa0342976a8cc34999d0f780a782a7bf05ce5c9b447901193353eda3eba40736e9a840129a7a241eb50bd03be8316209db9fd5c611148de864cc135b3ab90fef0ec8b1fbf8756529cf1c825bee603d115655effe5127ef9d2d164254866199ed18b1c35bbb011b531777135621ac09d142c00a668d70ea9cb91287c87253b17598bea9440944a719a03e735fda6fee18d4e77c80ad3a54377be662d5ec91208effc2cbaf784f274a6f53f1dddba6ca5dd23449bc9e226cceb05b116497e454ac9bf15c98c478693443874b91a3787ddd0fc954a52d0d4fc802a107dfead81b572e18d5ce5f3a54d69ec162858f4f07172453b398af9dd0cc74d148c5bf07e8a624bb7a8ae4cb197d6d409474d9f773cdbd299d1954dd01614d8ad03b8be92ff0875b05439cfc4130aac227afd9e3abae9f7742fbe1654f407e9be883c430689ddeace0cb8962aad28c554c9ebdeaf5b4da6d170f5cf5a59383f8ca889c913be0cd967b54b0d294a2d034a47365dc885d85604b66f310283d9c4a9372fea7b8a89d567216d534ce34e919b4e1e2263974bb299836f18107dfd4dac4809d14d" + }, + "transport": { + "secp256k1Address": "0x4bf6f91d84b37454544279cba152581ed6820044" + }, + "ecdsa": { + "addr": "0x4bf6f91d84b37454544279cba152581ed6820044", + "claim": "0x36b8e2d3fd77831f9c5dbd75cf69a7136e68ee4df7e5e829b5a709e42fcef8b37974e54434107e667b5f81bec4d60a8a28c0290a188c12252dde5ff59c736d5700" + } + }, + "1": { + "id": "0x6aebb6786ee10756b5e4c7b9910e800be286314c", + "keys": { + "falcon-512": "0x091125a8c8ceab68078dadd35101e64ac8fff297aec01181732a50ed24098c5106cc1acebc7ab349380a595c7207f93e8cc96aec66e74a5ad73c0d9658e450776448d8b7f6901e8799525b6bafdc0401bda562c5a42e7e66f67ba1645c70f9473769ec01d01239f9d26b6134abe28fd2cc361852138c657455657bba806c37a1eca1b5ef42f4a498a987b7614f41a99752be9e640804d4fb74db16be5e9b3b101f20b37264a31b5efe4b5d2388cc92dab1c82218e24de139ea69e51b9d7f5e190691e6d20626806686939b7d2e593409532d4c465af2b5c8848f298ea7601fdddf2f5c2420b7e02f8bac6273da2b2c91b24e4329dc1c42640b00455ddd4c040b9accd0a90d993062de6e1f82618d523ac0d5b80d407689cdf05c100a758702f60e395df0525a7d0421b1e2bc60c612b89b945765f0b251adc824d9a6a7c4ff48761f36350de36bc7de94900ce4e91486424d1a1901c45abaa1188acb4e45f4bf61753b41287e73ea33213c153b661032e1e158db1d12d5532a0387870ec896e5267e6d290d53850cbe3e4d12ab5f0ef223b6e307c34c9285c122f75090439d152d466f49012bf9135860468886c954a574212d438c99013a878e9295b44686187b92783ef22c53aa95e2ac84d143a1b20e1ef74fc5ac39f2e03566871a42e67b340455da2922ebd9e4400b17a4f1965764039bd864e278d7b5a5a1ab600ea6edb0512a932acc47186db7f0cc5d429e984ec1b4af06747e1e09374d372d65b9c9c9540731d6e5e9f54005011570d3525eabb3c0c6056aa3522b9d3246f818834fa18cdb069807270ee3e6b30e945d0d9009444b303a50f7313d800f11020d49b80d27696a3519e1145b62f678d0206dc6be78cd321459dba0f444e96ea529be49b0d864d56ea2368b60661bc259184154722c1332de5593a5e29235569936210ca761cd9518de96855c328a517c8f4a6a3cbb75ac1f0a6834e9e6ff4d426d22b547ecc88e1ab45d3678481585e1ecba71a54421c0fd83dccc39ad0e4764366e740a482ae8ee05f22f541ac79c48c57eda102288836b3b6242334e96ed85ca3790d3e40ebc859778b844503c5c8a97980ee347294bd9606f226831db0aa40250bdb073312baaa92a86a31770469b7fe041e33f85a40a34f1071aa3ad4af426619fda690e6e60a3b8534c63e080438a123f97fab6f0b66c677de4ed35b65db81fca0521dc99b20e5474466412ca5151f6497893988970d3684f90d95b8283e8d040a5", + "slh-dsa-sha2-128s": "0x73e76257c40876cd9fa2d08060b1be9a8ed216cee06daa351f35ff6d985c34db" + }, + "pop": { + "falcon-512": "0x3971ae0f1afab56d8336480caa248039cacb8ac9f25410a9532595f158161c899199f8503049f944704bb625046bf15031dc36671091ffe592ba2fb5d14791ef9c065902fda8a8ecca6473e2ca360a06352edc7a81d95891eefce3b70ee211268e0a49d1daaffb9d3df9d4f85853dc53e0c26d9dfe49205852e57565de5304861dd826992b224f8aa52b7fa9d689043ccba4543ec3e9b6c031ec92e3728356182c745d2b462b160ea42646cc7ab9f2b6cef2cccea7dd251a465f69cdca6ddddb124b5f71ab88a8af348e9bd971334c7c68e8dcab7d4f173adb99198cdc0f867536bc7dd33095681e077a35915eef68ef9b937785923c4184953792982cfb0d7730c96b8f5e47b65db354ac3ab7ca6fc224994c5f04726790699b4e9518f3a63d5ad48fd17fba612db42d2a0b115e8654f15910b6f13bdbc3916b12ef93cc14735d2becfebbb27bb6f5f2dfe2a5b733f592ab66a6d93d08a4356c6697256355ea3735f2bf0efed6ce9f4356c2acea959b09af924cdf083c2615ee7f7118561087462b6ab108b1aaf8a7fd299c1a0c49ad334405058894867ee64826d5ae1607099a9eeb3cdd45ededb7d3fa3be40dc3a76e3e841c8278b24be291534951e6ed5ccbaa9bb95b474065a04b5f2e44fc44dfeab48f1f16a7c7fa12797a4a40374919c8d03239ee424263188cab9f2d322872ea8426721de12094260f16f2dab3e8a5249f43d72864173249da64220aa93024515880623576069cd0198bce47c33027b68883fc43736f6eb25785dd920ae4d659a46d97bc67bb07db6292aa9a46cc34704dbe97e92d30af1370f7d3e95d8d0e5b0bfdb658aa90f4e238ec4a29c49bbab33a45562718be377cf3599a8e4e3a586ccbeb6ee1ce1e98f120454bebf2a8311d8fd93268121432a533bba0", + "slh-dsa-sha2-128s": "0x57dd06b908bcec35eaf266674ea58db9423d419f2b73ac4027e24f7cc65f61bf007b7c72290605668a58eeea5ae999da7c35600d9d4c2f1effdbe99514ec1d9221f997590e7e43e3a7a2e91876c8921fbc90f85e1456c25431e1130e617bf5732583d7e7fde46f59ee89c8813f4b1a7a9db1f0431749bc5cdcbac9c47c2c5bae4d325a4d10a873cc998e9cc61a41fa1eaa84553c7c8cc7e8bddf5d3fd19959eb063eca067abafb05644fdb45dac0c2ff9a16f1f2e3efc78495d8ecd203f054ad913c6ebbf17068138f23886cb5195f74c55ae859aefc843c7cc5e23ff4a8fe944f1ecb4cf573ddd8f68b265fc8686ae69022749ae77be41f959c2d651acdd1c55b5abf8f73426ab0f8d0497925018a2ef2f726ac66dfc1a405b16fa07b2197b62ac5afcc4451ea0db49c34a329c1320ef76d87a7d7aab9af667aedee8feb8ffdf990ebf09c491023ae5c8594ed49323ff626940356651fba9267f3876e0001d6800a0f961975384fc79ab66c68eadf61fb6b5e12cbdcf2261fb6ffbf832378afe3d0054e964ba8d8b9b6b6ca00af38f28cbb9de22acf6ab32a4a5983c2ac78d9b17a64f8313ddc226e2af9d11d03d5ec8c0567715dd701b2d5b294347cd3386420b551ff4e1d73dd2783823e3298cf7fb1f9ba43c2f3d6920227113308473709faf5d2a69515921ab7b4391512fb8c56c310ed58e8d942bf1f574bb35cc203340e662b1cdb0367a12d5144dd39cdbdf5412fc9750c4cf270233b0fbcaafb1a3b31d07ca9872094fa2e540765dea9b2f7916290af2e4ae10d82e678e7d6efd708f3316628ab7535c3b94bb2288ad0edd1baff3c01ffa243ffffd0dbac63ed0f090fbf20d3fde86247276871a216f4fa597474bfd65ae9f6f7f129fe212d7d152b438ee100100eb661e53a7426cd5ac2efc9b1247617d58ba1dddce85ed6df07b5c04cfd0e26ddbf1bc87ac3ad42d3b69573ed9e42477f83740517c484bc784c18360162d5f6b4af58840dd8c4af3de010a6fa0e8da36f6f0ad3f21a2121dd1267c068df719a81be64806914d9bff31dc27c84a7a9dc739a3b9e3356f160a0e3df57e5c1b7fd3059bad848dce768b441bdb61b1b552774429af6e3604898e83682ca1f1f786f6b6e1a8896e41078ce6663c3a5b3271d3b86f95000c282749048074a4949b8dfff52ab06f444b0f6dab98fe9787255f31164801cd84f45218500dc501cb248825f263a1c1f878c5c6f4aa81549c55069068b2fb72cc19442d9d3ee18eb3430ec73aec24b668a36a2b8031d87b81ae6453bc5193796f044342cdbf05131c40bf785b598c69f292916aaa111a8db49d64a3724777b76e4374a31b91732274a9742ef4126518bdfb094a54d9a137cca10ea215e855dceecc00bf4d889f76244551bc96b45fcd5d81bc8e9f70d74374a6674e0c1072bbd64adce2d861c3300f10663a8c37fff6f60fe545253c3abd91780d826ea264f37734d477ef69a0221aa9ec4a4f5c08229c76457270707888e15eb1386d7b26ff6e7da8ba35cc71a533611150e33a53ba65901e653895c45b0034c062bbdf93955df2e0aac9a335f7a0bae3f71f7dba4b96a11a369ccc9487881239be28c98666c7634a9672bd6ee951e8ec7dfeb8ae41dfd996c7b6a12030387ead698f21108c27313775e987aa6ab7e861a9057d7f0bc015924647671cfbc83a98466b43b13bad287d83bcedd91caedae73dcb2e37b2bd09b1206a557a8cc822b3ed8a6aa31ce22edf060c8987007c48792429b80064b14f9251e16a747c31c9b95c149ca857a4675ed98e28a31429d879077358d772f218bad32370047047a3d8d8bc2426430f8a3bab6a4644fbf107ac666672e85c7fe3cc887e458b86a9aed2e61b78241150038ecc78efb694d827990992fffc00c414b2e8afec48c2d70147cbb1cc71333b89143d583ba2110304c856eb038e61491f7c4ac76026e4be8d0f206db6e4c62527f30640197df1d2d27ed044135180ca71e66d74bcfd4d6161deb60c16add735036ec6e6de7e04a73c1466894d3bda3bbd8f4cf09f1420e3b9831cc14f2b3f419d98da4ba1e8ccc98eafbf1425c2c6ae3cb7f61ddbcabbc6025d9919d41ece9b15495888eb206aabe3b3a3a9b2e5a0b0533bc81b82dedcd2bfe6e7622a8c1cc3b46b41fa9300a972dcde5b2fe9e94d9237da199fad8e7c166cf419d1e156000ed7aec1baac5c63594a110822ba14e5b3bc8de97aea1872a62f61a048ed95fe5e0d6a6a563f19ab604dbf37eeea560468d961f7fead69293583ed723f844902e6ec1edb89f546c023b8d5977d34e8f06f179040926350b09fe63585357f00f7ee847c9b0a090ff1d0087fd29f8c439360dec9b15a78f25fbb73777522004646f30b02a8be058b1170c475d7983e439317771ec64fedc6c300f89a4931760821e44e2932a0ffe6e839488b5dab2c7021de37585631945f1919b27e5b412bc3a1a5ae602c43c5a32399499a55b396476640edc874115b1dddadc2fdeb6f4cfb94a6fe78cef14226e635816f6ac816b5b3f6902f83eb422132cb7406291b27efa55106d66ac9f8b06699dbeed8473d29526529d685028f8bcf17750015db31bcd523d798599494d9ece5e2c770b0841f5fdb0aae42527de920dfda93491e3396336cec1d429d406367dbfaef57f2c2a677ec4d81ddf4b5370acaa37d5e433b6867066438bcf5c1fb4d6c59e9af858ee85c8d5949f9d5a24e3a39e0e690aaaa64ea9c4a4f431103c726b322a777c77435384a4fcdbf34c55de0388e67277babaaa1418efd90f1bda2f14f1e73c38ec398d73f6235a303a126865f942e2fdc8f1c692fb0696f13ac8384f27677d07f7e7b15ceabbd7f973f9407417b09c0ac11dfdc57ffbd21d3d3083f63efdb97c9230928223464ffeae0bf92ff62a78cd0a6e4035d0c276514a1cddfa83c873abf56192107fb08b9333373d089d51a28209880ee1ec48deb5f0f449542f7965af21aa158fbfd80422c3aa461c6d90a91a9ea6d52e649f252f5457137ba9affdecfea76f94da3a91f4a984b70204cf5e24873c9f75187d17936b3d5f53267086faa5d3f0bf636626b97de507b791234f2f3559ea168f17deb0fa30153e23507eaab807e6422ea1cc526b7d9671e83a230bf08711d6798e6827e1294c570924aef098eb10ea60d38333e3b7d17766351853a59e3f04908051c4be1ab51dfd586cfd738e3fb264d84db941c7193a65c54c42b728ada36e87c123c5f9ce467d796f0ad4a24c7bc81c0a82c8952b518257edb985bbb44795cf038280611310d9d5d3b6a3fee9f1f78e79eb5c2ca1c55f4c916ceb470d05b9d037a357ce99fc7643abf78a5f8473fb59054866b9bffb3cdaf560b91ba05b0a38d456e90400d300e7742b469957ae75e2971446453996378b9a2daa22a0b08c9d382900baaf902e372e8bb9f43782103208c55e676514c2aa4a83fa0356cdb410e8cfe2521d097d70d59409069db704730e86871e46b45fe091ba4822cdfe47d760f5507353041fe0deb1df401b2dcc239cdc9c4369839eb259c544dce4913b4c6b6e6ce1a113160f3f38340cb6fae690ba2d9392a3771398a66630c1a4288772c95ba5083928db38a740f1293b82949e1fef094b0c39920d4633f1d174e25b22561adcad9fe6284d2f979e85e26d3e7a23af1feef0b6d266edb829160bd967100daa34e9199a2a0d7758de344fcee578fef86e34400aad4ef96a773a2726114e9141b204c93636d9422e227d34605f0307809b5a9fea8dfff6e2bf015670870daff379720bf8944ea2c662ecf1b42c894f671cd6259e43f36126aca48cb99630119fa6005bf5cfb95aae825a670044b5b9db06e9cf5733695e6ca15513696bbd5fbe7eace27440e037c7a4a5b7b58d082907954066070fa1fb24ae59428d86f9529cff03dbfc2178cde6d4fbb1f8e00669b452a0e7b740c2dc0fc11125f8f308dd78e928d99776dc513429e7c71d29919dcec9b960af64b13a205c4489a7d52110abc034d7e6c1c601eebe90659ec4f56df38a7558c6040aac509006d90af6751dfd1c42b874600bd401368643562aa5af582112838ead2135d0226f6a27a9aa5d8081b97f8103a8b1060169f22b90e084c01884eeb7104b309eddf9440c1f2b8cb7ed8eb531940c1968acabd95ca1f2290d64d9b1eed501a715a056ebcee5778103850dc6ad0a0472c9426f2bd961bdabdfb44dc6c91c861a8dbf2bcb475dcf78b7021f1f51a989e138b6cd160b3fae1bae82ed4df444ae8a70563283cbbd6c8070a0409b0608f1dcc7e89ba708cede106deecbf7ae3dd376a998879bf46c67d54d1482b26443ff54422981cfc37641e86b832552fa6531d982cead6a2f978e0fd7aca7dde93049da6a93e5d040479f30719f339a566d6cbfe05a0e15391eed934bcc19e2e4dbb7e66ec1b6c7cb47f40cd5ec1f882dd1d7cdc7409a09ba625a2838b17b97a7808c5a634d5f36ce0791d59057850d1bdf9cb351aca6e5ab99477893faef381dc4fa08e9cfa01087e8942b7807b9c684619f09595a26adacd6ed33709bcbe05bf3d519b0ab6d086c1ae7ab1c8308e2d184ee15783f9b402b7cb94d82655d564e2933f75e7c3b4a1db4d1f482b7a2c8da3c95b3706311d414ff4559529e797149da29149f0cfb252cf4a9ae26e4db14e33b23492adb7ee559b2cae40fde649e7c8a0bda9c2d3c036d1ac833a7b0c766876d10793b4cdc98cc1ad8e1733e53754383259039ecec5ef4bf3192249317d59d692302e8468eb203f2311b7b7af58411ff80ae285700a05a656196b5765624774e5439ced0b71a6e6ff3b6c8d42ef0e949ae95e32523e36d69e6a1fb806133e698a802c8e2326b91cf0946bfb92fc24448942fa9aae1ba6e27ce7384b1d1da35cb2ad8963939c5eaa7d49f0054aa8be589843367395efacd00a07215b369eb6b2f867830872adc90dd0aed3b433ba24a930be10d2f5a5393fdf1ea30ba5d03886897714099eb0fec13f50c1d76b048b07b388edcd2725ca2d581ae91d7d5b3f14e0cb4d308599e51014212bbc0bd180141bd7c97938515b0e8c9f08dd252f7c7a50b35363461f73b8d35b6659829fbea1883dfc366968d8b80b29868e8a67148b48cf58a7dc5ce2619a3c3819dff0edd3e2261feeb483a6461adf5187bcce376fb04aa8673435cae727cb5358799f7c400a661b5de077be63cbb5ef4b3c167c104f343b7b372850e9ebc1674d4f38572126f56ec3a8151179d1aaab85874644c06c68f500ca53a1737eade6f7cc01938b85e67cfa23d6edb9b2fefb82196e36d1313c0650766eb62a2bfc855f5eac736e11a84a77063b42bdd09af537aef198e2c556239ff30cceab3c3b8182aba6daa434cd37ff0625a8906599c7b328cd24c610d4e3526a1e565e5df560d843a8d204a21d6081d089063dc2ad05a9a440ca47286540f10dfdfbfa20454856a74707a90380d84824d32351462b899d133aaa2cf59891e359e17ef3ef15fa8189e755ab5bec74ff8e4d2c123f2c1bf6b5674f84f2d0bba936fc0499be436af3c75be48e4eaf2a1fb2d0665989eda96c83c89450dfd852dbea4b8a97a4eaa26f5f0dd014c0f7efcf58a0f5f588956231812d9d3c0c0cb411082847fe53ea668ffa44790b570881509b9b379d7c853fad7a874375a43217230c821f519fb033e983547f11328b95c5df199203aaeb6eddf7c0c6fe71cefa9192411a8c437ccbde380ce8749d544acda7415223341deb26ca9ad78c5b8d482b29db7c115c42a475868a39c9a24c8c9fb8256da61dfce863fb2b17d4992d21f899fbed66fb44ee9ae6d87ff492b11965b74b5093d2d732edf4f5ac288093ff1220528db775574a3db85090a32b68a1f6623cb31e883a12c5c7080ae80c96ede3566f16d62f488a8014ad78b85df94b2afb400f1b0babc20a79bb34b9fb4aa92a73bf1a5895c30fdd19690fbb81983b81a9ec9e569c29026f5b22a537f34c5a377ca115a317152a91e5e5010ff58cc714eec78ee77144d7ea70b056aa8efe08f379c447fa8c45777ce9528d8f40deb67b35df3a2318784f1c2fde55477ffcd2bed859b3120c548128235f7fb5f638763e50f5a4566906b098181d8f0e059a64bc07d15a3d38bebd0e7bf03d2a786b9d3d459183496ac35bd95c2ab0e657aa5f57aaf1e8a9b9ac494a5a619c52bce719155617c360e6de1d1bf7d1ccc62a1a1228cec96c8264ec1877ed52120e39c054f267195cec03f24290f19f5a22d658bc9be45755e4a1f7b6faf5ffd14d88913685bbfe7bae4e5a4edb31e386964db60116c65e5f55be204efa5747972217688a2dd4451221c7f2d7cda0e3393538f3aadf4abddae56ce3ab3a40e9355f1de2afb41fa233878e07a914baf59af189b4fa496cee1cbd2e691955e00ae40d27271d40154171ce47120e0ab2a8648ed18971e38e76e0cbcfc069edb5f4c638e89cc2fa4599699748eed99d265111af864d71ccb2a66273932bef1fe9aed4e3c3de7e3fb64e14336b481f60e3ee6c61adee1d8f197fc08d2840d48b39f490dc7abf146f03283e4caca09c43c1d82d79ed3b89c8f8ef6586d39f1089529c72fb422d572a49aeee70745ad37c2208acae46d1e9ac5c7a57dd8690631f6f5fd05d25b15cee1bc6045afa4aad485eb558d8b3b2a987e7580da108069d62aac139ab2a0fd2df96493cf45be1cb5193e2101533442eefff0241a9934e82abb3beb29e9b81e09c44430d391003ca18cc4eab3f5cd52d621ec7a82c5bbaa87fa663f90eb1cf2cc8616bf15b5542af290c5ec5fe6ba31989a4010bffaf9229dba3d2063326a8c16b26ddcd9c3e17de7e07ebba11be083eb0c8c38a4320fa442880da5cef35de94e8d5e663b20a3a654a95ea92635871116edaf3dd72ecf16d1c214a098c06986b02a02db61260374b528c3640de7307a51a077b7255e7fdcd811ca45caf4b1b8629d071554b322dc0f2b90f07bbeda48b9bbd164be8e3173697fb4fb39c0ea841abfeac76a180b31b1f86a31fb2a5be1d6c710d57567495f734c1226f1035f99b756f37b0f9839ea4078c2cc297c9cee96a958b564626e96658d79e664029a2910811d16aa6ad9ea003a867fc6b906669e2199f4a787949e092ee4de1eae60cfd77fc5f305630722404097ff3c5ed84486343905e4c97577516508d5043e960678e3fb8fb81179ada990e929a022bfd2644a7c480a106148d35b3e32b493dc965ecd9a2adc700d8803c28eec52f58abb18f0848dfa04c28601354d37ef06ddfd3445c466a3b46eb862fcfa7e3bfbe274aa0148aadbb5cba17eb76a020e1cb318186137397c26ca6c4479ef0ae8fbf1a2d0ce7c4d72a356fd12fcb4b30a849705445f83ddf65a390927ef775ef4494ece281d766e12b98194e40d35e22a92ace1eec78758dc2c0d6e31a90d8a6ca4571959a72010c9acc0f87f826ebe2dfafa1ed6a7d97336b5a5932c172fb0934d10bf534d04de3b7d9438d6ac867bc0882b80600551b0b11e7349088bc981290693a67c4a52affbb94f72f78faff4b1b1f755e56cdcb343fc4d63593090e8bb452fcc556dfb098efade44d61a851a91e0427754e12ded3a76ec2e5e82614a48e62e224084288972e837340de4042e9b0ce1606b48e12d95697cdbd8481d260d476a00e2f6396bbf9e192862cefa7e3e7e7d246237292521e774c3612697e0ff1cc6b3e25aadf222f8b7ce3b781d5828dee322c7d315810d2dc179e8d5a64ee8bb9bb04427a3536b4f710858af738f349dc6ce8b3ec70aeb79005d49988fb6d8a02c7d262fde008605a1cda61f9f8ade02589e8f636b08e04cc370cda7e695512857a64cbe6dfc5906a728efffe3557c6465fdcc7930731e47681cd7a1a33956dd8a3d02b92b4cc20c299994b201dd479fcbf4163ae1afeaa6bc3e51045cd0aec13519df42efaa396f7b0803663c76de7b2a7107fac3275061bd91c32bdf00c788334a5cdafc3d35a29016661bb2d8ce28b2f79e348c10828ef1b2b20e5d034f5fe8310f7a03a1643c61004e66bdd4815de6ecfbdbc0c6ced47c68db6af44306d811728c4dea68f7720b9c501c5bd6f98225f531026def54b44a2471ec8c5323333ea343461f58b06eaf80a24e861a95018b1e0d950d5328c412ab9bf72bd9bc4573621059c3f1dae7fd0d8cb20e1e6ed4fc8cc6e7bf03c5c99fd6a919f4c50ae012dee5f55db7dae3ffe5fdab37409b31dff4856ffedb20766d7058f1cd90e671870f22a62ccdc1c0cd91a65e67892f5d2c5d37f4e3b767bbcc1c00fa848c68b005db79ecf52582e5bc847a5410008ca4856fcc9eefdd4a84784e5f2a3e6ed0c103be24bad031e54f2f2f55f570eda38901192ee95869570398a6ce285f22b3b7789eaeed7f401b43b843abbf6bbb43722af7f1258cf740621213095368972f4b9d0bfea404d0e44a294d56868b889df298522f931cb746ebaa6c612db1d2a2053803be35b2ea0132e41b0c82f59d0c4ca3428452f4af2f52bf9f24be759f707276ce246b81f640994b74166ae4815e95a0965d377968a126f55b5d41230174be08a0140297a786d5f49372e10af673ca2d32b103e55be64c4c32dc152aab1d0b7f3ce11f4c8804261310e820f51d005df1a54e4afa4a0fa009f59c8f3f8de92c4885b15047d29ef45d0fbc25d2d3116fd1f30c927e81ca0a53ff8ab44c878ee853619980b04ecf0cbd4f015b8dd6c3ba904a9fa22256c0395eb26bf3b12173e42f4ef4174f2b5dd3d0d10f5516f073817dd17cf670649007b0aff790f823037ff2a66c11bc26c48e14cc30c5072cf1a6bf8fcbdf80446e6d2f51f83e5f4ee99e40d2ab4e656842f6ad13d8c03144c0cbdcd2bf89742d77be25482feb2e59a13a9d538146bed9b94d51f2e5fa4d9f0e7dfcdbc0857259df125c0a391caa255160d2250e352589dcd2da574e56744e99a3f6cc98ae87baf1655700d00ce33cc2a27cc8f3f5b0b0ee8001013c4f0d5d5780dd8e4397fb6bdccf9a9044747addfe3ba75a0a6224ead1569ceece4b16d970878a2dfa863a1d4b2576f06ed4e29278aba5450d24196614b96af5b1b62b9fe92dfea608d3084a34538802d89404e901211ec7872750b3ffdcab049a7d07d9df11c753cad51a9e6e3fb6f6b31ea067b8140d60a02325c53e98223d896882b36e105a17ac8e64d6950de4d9441858724d3f2000e39b430795ae40254824339f659fd11c33e814e459b18221202d443d58a4fa5559232332e59e75e820ed86c3f079ec87af4bb21157157c7acb30577c39389dec833d432059f26a0e1dd4dbd244bf2e08458d784345629d2061b32ed172c2c3fdc128f97f66b0c29600fa3fac414d134ba7f6d3f2b638ba8b2f31c5dc07be658feaf8db50e6a9e360a8b5a5fd0919aed37f41f971366ccef0a8a9f5f3fddd2ee687d395ae86f95a4142c65414fb4bfaf288042cf79f9ec264cf9434b5bc4e65fa61dd70bcc708eda76e6cc06c00293b07c0c324d5f8a2052e870fa962c971c0f87c9bfa61f0aaa2f219c4b7ddc0ffccf4c15199ddf3fda5419e90d3c97a868b647d2de04834f1114e6f84d35bce0f48d100633213a23781fa7ecde607526427ddcd93a56ea3780b90c105df19e725a4d0706a4d4808d0a5bf8746d1c89dc957ba8859091f157e8f3b078e69d643f8bda68328f5b3ef970ce9f9ccbb5c3926997ea1cbc87b9a7a53305f3c8a4ad5df7ab46898ec4dee2759c6c6085d41599380a6925ad2b94cbac31e2d98bb35afbc646081f64982429aeeef8be0c3af7c12a9d27b7b1a4fa95fac8b0696e1b63471c539c1b07b51022502f0443543e0131ef1fc2f59a160d7f03c57aa26d0185afc7effbec7635ecb075e2888879274164857900dd8eab69cf5d9f3847eefedb9cdd3d0a987f65b2b01fbd3d90120a1ffe273e11ee70f3a1cabe128f2d91d01bfffe0fa4f476ebea28ab33f83c3fbdd150e4ef0f9baa936b3959918d564c9c5615cf614dbf38adee077d3678283d2c3e3b1df595ad235f3df8d9f2d84e1d42b7d1db2fcdc840ccc7315a1beddf88602cee830ed6ed78325e871e07876c93b2d46fef442a6a3b464c70d293f1a7f0950a6687465f6a004b33bd0709b9252df1b7c7b002a53587b0d8ddf4d49094a68c00bb015b404112d1422188927a4f871c126a8a6b4106c5dccc2edd4f21285aec55f41e5736e47b1380102e3566c35001a1ac4190d5da0a1d3c5e9639c368bbd7823063e0e0b43e38f4bc618d0d56b82ad3136b896dea1fff2dcaebc4c35344c614bc418791e325be1e229566c7ef9ff6199d9dcdc051a491be6a4f1e568a91e9a9da753d2de2c650f63629608d52e44b3b603f05d36fe4f4f666946b9112c9eb4b91fb94406af700cfc6e74d0e9fdfe4654d0bd1ac070363dc86ea3e961c6908908be2f518f5e158f74a6e3df2115536819faea378d5568dcd2748401226ed92929c79a83b1e80978ffa56b513d4cd5412309b63ec2f3c3f6fe6064424d649543c219819c076dd6bde797fce8b85c757f86eb336d1ca88b6aa09b5888f205fe2474594c093258e23983615432e1bb9eb7247cf3b21ef4b9881ae1ed1faaf64544da1fce0c3b41fbeee82cfa47160cc1cf1ca8074266314f4f05bfaf2d13b64a6ca3de8052869cf318d53905c91507686f87837b8fb6e36d0b3d912565e5dfaeea5836615176f5b6e537eec22d8d71da315a298d5357709f65d9a634f82d52db85cb65bf6307af8e046274f96206c8402bd8adcc5205233702f3a86efa62e8e22f78c92e8a11043738456b852fb90ebdc4b220d27873c8bd98ec3b01a95471a3184e9606bbcf5b182a3a8a622404f44ed5bb34cf9afd6a3bc2539a1e120e91f96212792b10dcbc3ed9a5c5b71f03b3906b65810da882c51cb7616a50d7ccdc0efeaafb679b9ce3a7a5a627d108ef674f744d12886f7e95fbd2963694dbb6690fc2c14c397bb660700cb864ca012507c0ec8da8888a2fb3dcdc7e67971bdbbf38bb3995d1e2ba4d59fe84538ff24d1484b43d421e3e760841402c63271c6534a4de8462f33a4150c01afb12b596d266d7d4968af93baaee277e7e60ed1e9ea95a" + }, + "transport": { + "secp256k1Address": "0x5f50fc4e1b129bbd5e6e9f80c57680b0b4a86eb0" + }, + "ecdsa": { + "addr": "0x5f50fc4e1b129bbd5e6e9f80c57680b0b4a86eb0", + "claim": "0xfce8f68a68be37fb514ee9839e1a63975162f2603e548408ab7bd1a938b2f5e55729ee790b688a13f38a6e1492b5803c321fa7374aa82111216862f2ef1275dc00" + } + }, + "2": { + "id": "0x38fb1510d4d11624564a74e6ebfd752e666849c3", + "keys": { + "falcon-512": "0x098cf6831a6196601d69c0db2725e6b0c2ddf4179d8c2eed5bc1e46528a7f9cd046199a53e8e6c127d6dbc35d1a0d0450f6f660dd0a22debe45654788a5b8ec849aafcb2a0ed8345bae07a262769b1a8ee57ac92f496b8ad4082ea0d8f7cdbb9a52040b59dd0f69a9206bd9e48aa41d1852c217cb885a4238e6234b5bd2ee5771a3eb2e70010056438744fd85b4a74d5f080256d65789967c0e0c835a12a36f7e12c32f42107514374220d3a19fd9bf6570c6a53596cfc035024bb9fd1aa67182060f2e8c115a66376d445d840b92b44105d376af967528561cdb18d9492d15c6d7dc2562b310fca6cd1d7da395fb6684467b5451afd1a485aab16af8540247df46be18a78d9840526e7b84bb48c45fe8bbe2f8a43149c04403326ae48b99e684d1d30201fe904226cc3c453dbf407ca84344e882f47c1d32b93597f958c1642d39b23402d8ec498a529534eabf50365f4845e68b34d89d8910c5024dac2208e8610e5aa536a0048d0c62b5364233e96b690124dbdca104adfe8217e3472127c15a8a0ee55a99a29af316ee18460e9440f6192664fe0a36b191d5048eded163ef0e0b32a1b81767672bf13d6b881ad6833500c2418d2f65c530b100689b5f368956a92175425cdb0b2fdcd0346c73f148545d463c99128a859e64f0028447286e7965b58374023b94804bf26a56b88b55feb0b0de8243cd3c1aad0b12affd69a9661829bbbc823264edb8084ea4a71212cc34209af973efb92d0d591838695b91b44da5a88a71a1b0b2c583951584a13c872b007167edaac130aa9fb2386a66f7c83a887af6a7100e9c80e2770bd4d9a535ac7c40b78ffbb148bdead7a6631824bff5da6d781a50310bd827cf0345d8c2d15060995824f98ca752154da4441f17e0739999854eaa6474067ceb026fe705aacfe0c1cb23a192f4d38404b7651a9d416b139a4ba0e7191289999fb41127e2937997fe39f83a090a1d15fb27e689ab7fa9254b79d0321966cd4253c50c197886a7f35209421038d81bc8b66d124066f78ac80936dad17c0cd653244e80771abe442d2f0905da80ad50a3a994cfd282cd7b727097fa444aa384e090668ff174b86e8b072b0c938bbbd9f416b0d9f1a742421a7443eab4a0d66298764016168f5630f2f840a3744d4dce2af0c41f094a3ff6bb57c6af71c03a255939be159379c66fb0bda9a5bb47ee375aa6f9943447ee2cb1b916c0458bbdbc4dca2497c166e586c70b9d47a53ca74a5793537430dc7", + "slh-dsa-sha2-128s": "0x30faf2e4626a0fffd74369c1c1f1c9ef795526677dc9b1a53807f7d2d255a44a" + }, + "pop": { + "falcon-512": "0x3901f5ed3a9564039d778429e79d7f8071a958e037c8c95fce336ace6835b94be9448c27a404a7e470453208f11998b637fd8e3179f26a2f93e4930757b279229e7be945d0caeb18a78d9cf82d7b29d6b1dd436032549380899994e6f269912418cbdf2fb0884dcce67c5719511415cce636c94db8394d7c97628eb058a861a0fe276a0564a034d0c25e249d26557c50efd214910f625b25a4857672784b95f383ca2619999ee165ce09a21f66444d72a5524e9694890b81a35a4bcf2a4951a553e3fb546de295775779a60675634b7d3f33d08da956284e7f265a18790043bd6769bc1c92a7d546143d469b2385572a5a3285e5a539748872aba5659f3e4939cf3cb344899ca075d1e801f8df49d22b8e5d1339de8c85d9b3a6c3b034ebc64385d2137db4456e4658a61351559765ee51a6f4c6e15e658284c7eaaa16b8e428c273b8c4971bf241b56dae00cba6fa86abcc88c68ea278ec7361cc87c3bda2ffc42650a8b49488467fd003335fa67978d85c7fe59edf2d2ba3c252eb36be0dbfc7cbde5b040d21a44f51d9d0fdd45092312770a63585616e3931f36970b54cd4470f4d6fabe3a4333f259a46dc7298be0638b1a3dcac610110713e4529fb1e2c768deded9f4f6da63447d7088fced0a9ba73ba1f83a4b5e7927d350f2bd466d3c8029e8ed6cdd8ac594f63036528adb22628e693ab27510fc28936f96508fa3f2ee344fc0d61ae7dd649a08133af3a0666a2494662a2801959018da3ef99b74d747cce4ef91d2f08de5ff88fa8155b16fb2abe2ccc0b80749d3c456d5504104ae63bfbad891b50d114461e4560a73bfc8b6c957e40cd450f1b2032cbf2538e6f357ac7f77111a26ecc6984cc2977aa8f4aa3eb4f39ecef37150d1e7b9709cf85daf450161491f89d88cb3f842b451904a140", + "slh-dsa-sha2-128s": "0xdea47bc65a5c246f273ff5d97a8e7700405a602c38d77b255522e6072ccd6a93f97850a4d4779a5ca8a4276c5bdcc41d1cb38c5ef8d8e811887f6a45ee3fdf1a32ca4a127d2a7af1bfa2c067f51a303eaeb724f4df320fc4a67261be5786182b98e57795b018b2c8b101544b6350927171f91d8ff45126b045bf2c7fdc542334cbdfe900392376029f9cd2c67d095fa373acfebe31e62f198d2368278d33c8e00b0b6f8e39cfe0163269f69bad622d79ee0ceeb16006bfae4e61f2422b7b4c7c431f65edacce4efd22eb7168561091f7175ee1323fc6d09aca64b22c8748d03efbb19e27827be472f74ec206f3a5fa243f9683c18f8a55f42fd464084824f20b732c2b0ba05be84465f2c44df87d18292d63c4cd30cde4b2356d038d9400522b3080b9b6d6bc14f1cc5200203cf0b2f5f02851c2084b10bb58c6cc96fd043925ef7c36467c0067c589f90afbf60e9a250e8654d8eceaf9e31b6b09d1afae284c0130870db573aa7408e5df6f57b099b1579c280778933ae8471866136d7dae8a2ce40f677bd47466a1290fc9e56ad19e35221d553358f2c950ac5dea44114fe2cbd4b116e1d732eafab37246521882baf6124305d75a619efdd229fc69b097eb8d94689dd7ab1705ed32f799ff9dcb29c6865c7e91641a10843ec88e33e6541a537f6864b09bd07293acf7c443786a73e55e7fd5ec2eaa84fdeb9859e6d62fbe4f3e88d7a08ef5f420bd996c31fdc5eeb9b98a8abba833988319253c73bcad5367eef62d90b28d0f7a6f61a19b0ec564e5c8b2aa568b44e8267423cda156ca60fb9ee74adf9efa1322111fe10d7e2b3df819b9fad380c5600002b7db3ddd7a6f99a55f41f3aaed1dbfcc0d19c915ec22448a022662821248f7c421ea85a2f5180e16de0ffc6db1fce31a760112fe5e353697b86610634124b79d62bffbe7e8132b95ace6ebe72705d15749017da3e2e2ea24514fe252c53a05be275f46eb7c8f9769813dcd2129a84934889c71190464c5dbf7911762b227a229cab57f9bcf236d63dc9b29f917255c04d81af91fedf211b22cd50bae25da184b95412cf0f59b59615f09b8fe622a4a6eef75a322d2ad18bded924806dfdeac11b06b79fbf5727c2e3b14c25676ca913d71ae011a748b433d138bf407a282939c570ef8aab442d397a78e25384425fbaa8eae8bf8e917b43598e161973f5d6a4f0c5cd402b96de42910c1979117c7faa8e543c959a0cb35e3a44d5a94a181e63df9326c77fcd46609c432a73a29dc2420b0ba0e187a18d8e114d3a872b59258a8ba54d2131e3f5cb3568d4d8c46a38406dd19f62be1e618817170379cf725d2fd0740a96f07478901582f9a097e375f7e449b4e605917b7afe4756338da77d05d25ec8f10f2e3802937dcc56f7703a83dcfc0c1a4208c04f951e68d224a20ced543b342d2056a0af8a9325f9941f1bd7df105758bb8f202c063d955d237aad4b078e4922743faa9c01c4d3cdde46d8ea3d6f816ca9a3a04492c04bef7b5d158a1c264910b2c1016c798c5414558003e4ebae0ac451a7dbaf2869bb57a7ad10f334f211e740a45038c7c417557e22a01aa00183dabe35de75728ebb16d58e3bb1cbe1ab3aeec6f1ca81aedf5e8f947a42264ff3daa4737750a05c651a59d44cf01084adefe5044d0144117e0e60dbc5be5dd258acd39560151e18d0a165b6c3fb9556e2f44fb99a12fa1ca1f7028e8e7f685b40990c594f2228915deac00c88af31ffa01eff3405894042f6957395c332c999a0aa634e54642a07c97731335093f9f83b4d18e638e85add1f6d88a652444fa270ced8b1b426bb936eccb547673f2169f4ee7e3285393f8d6459d9f78c18191a76cfbb124a56eb97771376359a2691375234828ca1bc23bbdbc81f8aa7576bca4a77bab312a7cf8618668a749526053e83fab346ff12f164b2334d519a8225d75ec28ccde2c051fff5176d658fd765a895b340b02f5b4426868d07464f1f4f7081176796431e79de12b92601cf5a6d60ca7d4198c8de3499774b031a74ed5b3c5632772fb161cc9c17861be7e632392ca954a631fca268fe5e8516b80221218742917d5cea3aebf30fb61e2711cbc6d13394d628af864e4270362c997ec4fc01967e1a703656bb4ef53c5469cbd907b1ee0ae4a072fedfdbabb61e1ef50b5faa76786da18a6040aa93a583fe0b63ecc3a7fcbe28c3ff69e6981891681227e48500c420d0773513cb8a2f8b89dd20409e1baaf921f8ddab7b732c2d44990caddf13d46c291f2b8574335e816339cba8e92ee535634493995edaf167f62b7233d01323221424af6818801c048b740183df466da92ead7359e7f216d7d5d66eca684faed42f2e8897ee3c7369684050f168477a6283bb226acf44389f3b1308817cc84b1284bea2bb97b4f86a0064e5ef8d3f1deafc6c4e7e09b8d97e75ecd7f013172eb9a98001f80b263d987941fe72f882aeb44d95c591d0a1f2a80617cafc4a7ce668de4d2d56b740ba48bba5b521a374553163e38acb88d8192ab39dc7c70dd929f24ac177fd5bab8787452b295a6df26885fb323d022c3419a1c02c9386000378922071858e8d3f64c3ff351589969cb6d864f4a30f4b9955282ccd15228e20b9ac73306c3ede412138db334218628bb20f1fee83a0b80f2639ffced1b731700bc6372e6e095855cf923eacc51e9354acf12c5c93a6f3d427191a628ce075d864b4599ba0fed7e077483d8b23ee0aa52e83f44699aa8bd8fdaaeb97fb9fef928aa51f12f7fed6c1e2b8725d6a2ab18474c5064aed0c6706c8032eea1009933c265625c3b843398678c6c9d9b84a5f46457031924e5fa1e1dcaca9905719c3c13a7ee9386aae4905721313e2a7fe7a601fcfe51c20c987e9180114aea1b4eb6e768d4955f506965ff747498fb3dea3a45a774ee8b4d180971ffda421daddfc5228d0dc7268bd7008594c77e9444f3fc7feefc831f51e5daef093bb4d2a799990ba3b414c0f5a79f9a41c5014f23a5f9578f4b1b861691e2a049725e4a4ebb66f7f893b88c7665a0831432e92605034e3ee21b7090626142359a46a2be691ab9e4bf3dcef544930d1f057bb0ea7ef7d4df63bb6884a586a2613ad7353e7c32b4a804280e60f980032adf9a1614acb1e8d160cc709fd979fd4fdb1c5e58b289ffc8523300cd3152608d0088c7706f584eea7672276d83c6713de718d6b7a9a3fd003affa82efbb97a81aac8c3962d54378ec3f8c6bfb4c343163d90bb76ef484905a675fe8a1368f53b24ec1bfe3411aa4cbe423e678bd091367c5317ced441e6b31e2f8251543d2ebee5fd633a754ab2945d6e25e696d74de936a0f01d890f7106503ae79741fa1fd6c89f050e65cbc517b109f380cfa1d2966f9f7690ac2edd3c414f5ca0edb74bcda3d8d6df76ffa8237863059fac7307ed6857be58f539fbd25ad1ea7b781768a6494a08a2123e4af4e13d178a9def16085e72b1407ae88f469bc886c3972c40aed301287aa41b1a209a7b1559dc1fde384075f987ef6962f9ce548ed45a4c1e7bf0cf37fd2257f5799978a78045307f2a082dd848fbfd84de1b5ca8fd919768aba91799a393116d97bf05c7c9d990c2c6e65e8ee02773a5e033d6f029bb99e6540766969f5019669a99ddcbaf4c3fb2f565c38b67a7a2c36b5863fe3d88bb4ad5aa3551b00b2665c2d11967ed551d90d756fa0543483aaa8d034362fbd3d9093cdc7ad7dd7b120a11a60f84f173e7c4e4abbb470d9e685b9896c823d2a2fd586cb09d59c491cc14eb640de5d5a28e028f10c65abde514db4e1d4489354adb1e0ae84b32927a7efd55165e110db7f868ee9bc5389774bdc53b1dce2843be8267d99a3f20042b48b233ad4891ad0837b017080e3f5e7afa59a248ba0a41caf6859b1252506c5ca7e59ba95399dfd584c1420ac6f8f2aee58b8eda3b8bd9336f8e9b840852d7c52f3fba06ee549d66ad20e3274cafe4ac0ac3d0978aa483eac11dc3e9778b2b0ddaa7018c081e48dd7599dd4c257fbbc230f30e5895b0cb09945a2e855907be98db08c41cbede9610a132042bba832c0f861b15f455a221f95bd276693e68ea0ae4fa3f12451273e1bc93c30c4d08f8ad943a0decc7df2fd9b70828266dceafb34a5de6100fae3226f24776be83ed4af93141d7c029ab1c672f5e2f9524df820bb8afa91392222698c0825c291a12bed5d38f9970bec3935f269aabeb840fb225665ea3553724e4ff8c88b9cc363c510231bfbabe2868a153b10ffecf69c1c21cefaa41d1b7e45b658a2028b5c47717953476f143fc3ae00d2339fd5084c17c41abbf961a29d26ef8abff0a306e3a77e602ef7e68914335b9d447031827546fda78a2b0e746a40d17fead70a51069ada6408e1a5efa4499a34c58325aa58330ba0743e49253da59b2deff4da32533b236ff4e64572da69011d7969d3cbea17519070bbb7e88ffd47469f48aae23f6aae8ff02c58642cd32ec61569dd87794770638b3c07d2ba4a4de3330882fdf1088f8092d7dab4f059a2ae7a44b4931e5c2f77573d0a02c512e3fdd6d33c58a73abc92febbd1d81d86a0c0a02244402f9a90e6ea06bff5e885325bca43ccd14cb5e394b2bf2fb5f7fa281f75bf9d9673bf964a8217b6f1065bd9e744bedf11e08a2025f61ceb6a6fce32029222bd7593eeec6a68cb930cdb9a9a169fa47804e8f138bf8f3a322b37273d8530fa697121350b99b371eac75345777cb6f036ea1c72ea1c2180bab835bc74a7bc7143a82989972f2605f1886aa64298dba96049ae61d952bd2a194b1e8d3d2dd23f1dd6759a8f9f981275c130da819ea285ec77a8fcf90509ee59c9cc296b013529440e2587e965f4e9311f58268892502378a6f5af8d534ab253ace2c48af2d8cd327e25a75af7c5b438131f23c4f3711b437cdb84099ace353f680586ca386a7d6665d5315b5ab3a4786fd16048c1214bf107fb716b09c4287876ca151239b59dae49a4f0a29046517299a22622001a8f861d510351cf58f6ccd9bf3a17202f3d09fc732dcbf7e77af021b05a18784b4f06395aa38839bed654a479f72919fa9bb04a33faf7c40cb73d999b30b1f0e89bdb51fd010df4f933c57d9b1264fe50b561e9ae5f7596043cdac783715af1c64b2daf3892291221b36b285b7e308f45e809b8c0a2face250b978246ae287f6e980e9c2a5353ac1ec0f43e65ea22b875ee39f0729e2cc24036cec81c840d68f1170f8e62397308d3e27f84dd3c0677264fb499442b929f8f406395c65670802d353f428160e0c98ea459946ac2b2bcf5802a7380c531b55e2c4a940f7ddd0b1f6ed16e029bc99f44efe9e25ba3bce2517753c1a2d7b81ff1f86f18fa772c12cd7cfe8624acd966b51ae983bea2a57927f762148a634278b8531e1727705f454a1383a7144d33543a3492f871f0565053eb07b819a6d5211c7a6a266318e3ac2b1ae3d55a4b7314cf10bd5505a107188c299067bd2afcd04fb3e7fb5ba4271c97770a1226bb0a6715e3a1107ddcb45af0da8ef468622b7bfc8242409e4791721ca00b30b4b6bd8635f9484b0053a2d8f033c123c9280a203fea5473601ff5aed53d66fa1c33b9b14b1c1887d7c9fbd6fb85fa6760f7d0738aefa19fa3a519f62c9fa6f6c17363474ba7b2560e7f8e9aef55beb969f4580bb5ed61ec1ee92788d9a507f63661ae44571ca470a2286ad752f45a6334ef2a08fc8e6098388cd506383548fc9072f271506408fe59d75032dac9b530b735cde7427279bd4c992e9f16cb6f90c6ec718ed929cfee8db407bdef6ce7e499e66135827a038ff2f6707d309c7153e27084ab40c10d77854b134af24913713528b7749809600bd156b561ee557b72a0af95572adfc41eb98ffa2d7bc8500bf343b01629a016dca33cd396f05b9783db62d4a6149c00c34fa9c33a34c3e40af1874beaa07071c25f71b8bbc77b5d0e5f3a56e153857ffe6f54b15425f518e2bb52fe1e0e8ea6407f35942dacdc7b3fffcde50919a3e3f5cbc4beeb744e1b7a392e7782d6c6e44943b3928d14b60399847e651593c1e6aa9f97a92dbffc11f64de2298984f1762082c05373614b6fc0662854c1197c98ee591948e3bf161ccf0517816afa1981fd36bcb42c6ff767368dccb6d583c1624c64fe80a81882ad493863647d658de1940181769e7bc11f5b3295db78b27596dd7c81dfb2c3a3c293321ac4134985f0dbfc8d231036165208b5ae2ff8e4df0d131b4c62953333e684384c05f0dc6b11d0e72107357f153822599148c5f956f0452af5913e4ab64b9b0124a6ea70011a680405d4258a250b6195738e8bf47c1303f48cad561da683cbbc612e146f6e7929ef992c5c3676b71558074265e50123776994e247945de9e50336d42363cf581db68812199ca872b906231794f92f6fbf6306cae12c40f5f0b304ad152dda5e68b0b59f1718f34924d88dce35f8f224c08ac3345645243f7ce95225cae6b76629cff0b9e6d5e6810017744c9629018085526cd5919a2696fe14387c89ffb0c27aa08e2222a79db7a47de2baff971cc724a53b7b32015493b0c62c6c697041b9a81253b65c0f2b71f791de64b71c81a82410fcb47b53b08554f5280aae37777ee5f33b08b0f87b4e36e0299009063ab4778116c0ec1efa668a58c1d70778560c8a5f0a9dbc5b6398e18d83cfaed25e0b8487590096eb89dfdef8ab52b3e757854937456a88c89cadb05bef3c97f32379a8c4614138e52779fa5d2e66ca0013393865bb006ef4fc401f396eca1e61d223f115914b25a77436c2d4f3c75d7ddcde67996fac033a6fe231b2d9d5ea3e83db1addcc6a1ae4b47c934d3dfcb699252848f4db4c5727fb799436ea4580e4475834ff591b033a821738f3494571fbffc5f4dcee0dbed79dba076abe60ee84b51bcf92d165bb52f81abb7be865e55f59e55858190d38fc1389f56f42c1e96f8c90d772910d05ed8fe397a523b94f6503f99df4ae07279899fded0e74af6bf372c5c7145e35abc786b0d28acaa97917e3d64844d56f1a6b77284a3b4f5418277b9fcfbdaea4cb50c5c22806db53407eb98602d8b6cf48928b0db184b81835cfeee5ce6465efbd92fd0b6d0f5ac641ce598c1385db9c363a3d228ee67d9b2739e3a728d48b368c0c8f1722a15a96688d406058830fca122adc9d3e19c27a329b8c15846b62d572ede92badab76bcad1a7161e1340e615fdc758cc4fe476eec9dfc3306fac7cc39c0b9f986ed5bab4993974bb8f1faa0d9c8a5afe641d70b915480bd7025dcec8c24cb95d1df2d65829299699320b11b09513158221ac8da7d260c8daec199b92349ace96d78b014a83062e90d5f757fbaf58000e0c3caade5a37c5ab0d3394699ba0fa1696d47b2b0e76459782f651e7db825c58b9909f47d08295ef57ac58357946ce2200b206be6a3c872fe359f922b49132dc86f198fed8102f813e8c0833e8dc9aaf24c4c9bf5ce3599dd9ac0fd3ed9d2fcf884f4c6874fa04f2a51718f4a1a46c30bd765d76b4dbb41d62fbc5e49f8a935c62006b1442395f6693dede87b95255ae0684a9b9f387525a7bde6318ba984fc83d16a4bd9615c8e0f9690164a303d3084e1f563a9d3f5dd6bf35320e0d5871b5c2ab22cab563994fd534ae0f07ff81c1a276c818e39b4040826ba2e7db0cbe4fa1030e6e77e9f3f5836bf5914937b59bf0c16845fa365d83a5bf67f4fcb195215bd3468a186f051e14f305377c12176a6bbde74681a3bd45cd04243226b875f8c65c12355c644d6331aed9a63af35941ea3aaf7f7dc2b6966b64cb828d4d6cb412793930817f8d6346aed91cc633093ab877987aaf5e2327b12c767737a9009e32b92d7deff072ab20310f4757051884b0239c27475625d14cf0eb16acc4e4076bbe051ef1943f230dce28e43a5d5de1ded4ac5c6e4dfcd59c0cf3a4c58524e353b14145721b176395f4ddddfe77cf1616daccd414397ae510ba4f3444c246f093d7ae48148a5d662d39917fa12764be96c68705d10212e48917b91bbfabac5c88ddfb85c4b73cb5c8868d7431884c1e0653207bd49dfecc815cb6ef0581dfd871867e65fc15913e53a5ae1a14d0a5b0a48944ae9daac3aacb6af5adbf3c6496df1d83c7d61b298baf568a0762663c21f698074a7e70c1cc680914a76c04540bb239887eae1cb45acbbfe8d391624d95c7fa55ebf305fb7d05d9d8335a198b8cf454594615d9e6294047dd0c300d2868412fcd3e704b9d1ca69e40ddf2465bfb35b378bbd0067b84c9cd4bbf5f84e12d535e9f19bc37eea24d65853649476641d4e6fbb47cac285baf2359f0b47c7737b7a8a60d3153c0b73296abab5daef24a8845f9f110d67a6e0a6b27fb246bf7961df13c69d1f76b578e3c5b061774b06af6f7e313d4deb83bceceb1dc9e69715b9b19b8c25c8756596c8730cf4437b920630bd0dd6fbc60c9c42e32331ff25b3f51e815a053b37c411303669fadd3c77b0d4a9e4aae7efb48557fe891ec2be15afe02f193d7b44049baac43c32a791f03c74366baed4da202ee611d0ea63e591766f4b2ab579fdebaa0a44018031a219d1aa5129133c919d9051a9ff9e6c8bec978a013eb0178df64cf8b3a2adddb7dce2c9a3084468f624ccb54b9bb1c6899a8186dc119a588f5ca01c3eb2b4d98dd518471c7683787c8730e60e36f23c9adc6adcdcd5cd6fec9c0820a50e74df045e7b952d08ae9e24347fa815de641edc5e876aa792fcf269a38b741da2b06193df64472970acf0da4215814c987561341e73559d657143dc392deeedf8b91d420462f50cfa9b586c285364c823358f1a86b4850c7c5b4dcaf361351938e7c29948f827a9949409e64cdb2eb22989a41a05c95f70b0a8feda576b039ad6e327f50b214efe24f0ac333c25acd657c0d0d2b7eb02f2b5e0a5a3390e15722926d5e21b09facd6e2fe0293c1d72a567a2ef90d451740ba086ad430d5564191f65f1ebe94a6e280005c505a14b10d31d89e253bdd5618f134a0717d2b57cf2195ddf3269e6362f3c2416535afee91d3d741fd763abadd8a1ea8ac29735b3047954b5f8d46d72b738f3f66d5dd7eb2eb5073e009eedd19a06b06c9e1dc87d40bfe9e369166c7a0f597a09be97d55147c4055f74a1b200eb7b84fede112f0d4b55c7a2bf3171805702ac95867a1bf2daa25c03416249ac20d48f73f164b9d3c177bad62a5ca9af1f432b62bf87b924161663aa1a3d88b4d026de54b5d4050188227e1bd172e8148218725351e176b2aafad7849200fdc872780f9fbe60d1ae144f5f6ce73ddad5851a2b0497399a912903894b4051017ec6dde5b0f0d638a8f4cb5676bcc8c14214ea1c2fdda34c7f832c93b960e2b284d1ace677acbdc36e7c4025e59585f87b164c4de0aeb6ed8798b9597b64489415b2a54ba059dea57ca01efcc7eb86423498e3cfcd31beb0f1fc546d37d2c150e8bfe35d62698eefcf87a2aca1e0a1162b5ca6ca355bcf621514365c60fd582820e478d8b2bbd089866c383f46aa95509c1b192b7cc76f5ed06072c202c2fb63747fe48845f5874c21ca6e2b07bc7b489ea60d5dad4464c41fa4d4d743e580b2804a0d306330dd4d96a6926a3466143f3026048ff2b8743c82580843e9a94522bffec6d8fa88cfd81036772fa02a3be7688dcf45fb97de4a5aad2df4cebce2aa494f3c7515a7812fecf1c8458e8e1cb4fca9ab91bf89167d17df992f95d8c8c8554dce1404142babcb7eccc87764d8dff2a80ee0f17b5582378cd86c2c5810d0cafa7b804c1c5ed8702bad204ed3db7a2b834ba8b36e90ade250efacd1a64a5d3a5d7ba478328b45f0aa668c33a32af897e161e44b8fe63f3489961eae40ef4c3eea3baa40d7ddf6dd4d4e29d316db3195ff275eb280a1e5fd9b32b5c1cd91930cafcc140fa8e9a01b8a723d200997da2394dd5c48a1fa16e36081b3915c6e7c58680eebebab7f2933cf99958649f7475f918e7c8fbffadf21ef141b092b15ba69470163471fac66b4f2d937a26e9a72a83ed8e2f37170483534f51f3ae5ba0c15d25fd6d4f88c881304b902cd5180d4694324d0e92f77144d9b933471ced674a9c3eec594d3212ffe758f18f46f80de4f4c2d7fbee0d17a00c7b0b9e78583dee39a8f9ec1c84eeda5ae208c4a2d9634d7479a47d66c794620f1807f73dc44fd0c911959c93a85c29cae319988a3a17df7d41a61e0f334b92ab494bcdfd64330a31baee5223d9fbcd06f15409c2b7045b697aebbd22b359d147abb2f0eff4f8a1e9ef2575b928ca6b21e0089083bd80a7b525322850425f1b5ace8ea95423f900aa9825a4209b661788c7886c0e37e9ba5e3231287e494a5426ecfbd6b742dcc83e911e3bff7fa5454fdd91252b0b541c3430030f43b18f76d4116a8e8bcd2c09ec633b9138a029633adbb7969bc14e5d13182b145ef6ee35997e4c48917b231ec0702bfbbe59e28264cffa0a8a0169e3d2fd8362b42ae8516204417d9b70e58be303d654a6879eb27b42515011115499e10bc09904fe57586f065fd870f4255e33727178639932bedfbf836784ea0b87e94e948f6fa278607a713497f0bd9166be6465367435c28c8d7e3a20648ad33ef374860d4b8ba643dc1dd2c8d6383a3bf50951709ba19993bf848379d567322169ddbd88562d90ac7e3a29525d7251631250af99362719588cb53fbfa8464424d65fcdd3317b45c5e88a605b8293f962f7630780ce63d0a915184e53b526459228d19960b170a889b8171be20e1b5ea6235f2db21dc498f39ecb0b6114771ff1ca47b1289e219e6a3899e0a9cfc5f7cdb90da598bee611e109844d2239b5665b04dafc88368b08e62eb2362d80f03221d8f917929187eb18b9c41b4f313ee20b0316c52b66c1053a0f1ca4a6ccf0a102fea79452c9a4045747e22d1ac05caa3f3cbae192c3ef001df791c886732f6e3b87364e903ab354f78a77062fa278cebecfd8c3cb0bbc0dbeeae7ec11bbc9a2fe85072a88a9866e855fdf7106e3438436a52349e0114e32af2abc72334b648d57df7e0a71f9409190573ed2b018ca24c8b61c7eb8f1a58ab8f5" + }, + "transport": { + "secp256k1Address": "0x97473985d04723299559f49b856effb47d7abfad" + }, + "ecdsa": { + "addr": "0x97473985d04723299559f49b856effb47d7abfad", + "claim": "0x091773219ce4246e9577d5c703d9662fc322bf0b5029788fa14edc1e85b1df0009bbc64121487e414d317fcc68958b59bc93a2f9cc0b216df2c6338daf71501e01" + } + }, + "3": { + "id": "0xcad2ca4b26d3096f0fc3ffb221033e6d7b424a6a", + "keys": { + "falcon-512": "0x09b991d68a909506b5ec27a59c86a2b0b815f1fc8d60a9224f75f40b8b4fd0a73885821d9982e7f829dbf24a824b1a85292145807041d10005944d107b70cf9636a15765096ed8a5320797415fc709456a85bb47037279d692bcefee14ca4284b9495e0eb80353461c10304d8ac592d665aea90f30b2ca0331e84b0139a4c98e3e47bb48d616198ea14b8b2dfd77453b4065c33a2d4daa44976ecc4d440b772f43700e341c22e146026e75de104be7fdbe4d95a52cd40997eda2a0092a299b44d4274ceff272c05abb0bc59607249be4a58a0093f2fa34c14957250d5bc4ed23339d3a2d0750a77e14e8d107324ed12938c592071335bcc165ea62009145885bca6e2a6937ec815af86c670d2abb119488e2056689090623578b9ec28108654c93806ee0d664e2b7c53146fd981b65b177e8de61fd8f3a47987e6ae66221241a68e64534ca22351c8990641210851fe997b669f848a891337bfeb0faa42e88bc406741cd943685512ef7bfc65440e86340dd96b57408cec4d1648550129fe838e201a86164b081055926b6fae0b6e5f65a65eef5061d6d40681c648c9aad426927134bcb2e38ac7b63e2120a97b21007d553db0dc64be0b2ca1a2c6449c6f9873496b49973af9ca1514e3217fb0608aa3d82246f55dd6504a8c8ae0ad1a634d54bc1c1f0bdd008332817f25ddd700244d68c0b6a8f480cdf90ae1ef1a3a619961bf67c7208697151c2af54fad43471de38739cd6c4067a056587542782a422325a174db998c552d5c48095a0ad555d8b784d32c3645ac4d099165071d662ec365587d954e7128db6cedbc3172621d58c1b242d4a202841374c126c2e80a8830d570301717936b2c328ac7ec61379a7bf1b06be385162ae0c8139d25b010bbe166f1899299862acc316ba59a6313a6bc6a10f590248b2575e243f66be6d62b851bd685413535894e2ab09f2519290bc3f701d52e2518276621df409172f3695e628580432ba096327ce4efb170ead3701c899a7e84f00ac926e21564cf0a78eb662f5df31c2c57540423039b12f402ea20135a62d3c4d90fac5ad8096bf7ec667e919a006ba518a49187744122f783d12ce69a1bcdbbcc486b4e9d2f81c6bd09839a5902e575aba9ec4c81629e6b3e480d74f81aa245c546185542d8a2c1c39942a6e1c6a32f94a8d201eb85b6230e9dd16cd03827eedda829e8f35e6049e9725fce18066a77dae2456c62c82790629494b699a8d648a853eea8d322dd869005025", + "slh-dsa-sha2-128s": "0xf04aca3422194bae6cf9cecf8214215f4c72b5728479f4789fc0bf9a47bcefa7" + }, + "pop": { + "falcon-512": "0x390da0dae92962974e43c606d91298ee883ec1b88f1a3f8a5dc430a04f10d31850c7bc64b18dcdc21675b4b8b44d53d260d1b84538efd6b6ca8d47c35545458338856ea2cd5b31999e22d32a01e77658fa6d130f4c6edef8a62bea946a124c6994bbc58bce7137189c976ac2cd15612d2ebd7cdceea3a2419b2943268c743cb2413cc48d733369ae76b6500438d0deb2b3cb34d96de4bb4646556040de0de2199c4473cb8f05ae60d9f29ef7d571ad2165f1cc202d3e122add6427fecd66151a51b98d6f5190d96d7a95e673d99f8478eb3b97a9e7bfef258678a8d41144e91bf13450e92b7cc0e9afa542c0d94c759768ce8e2d4fc267761e6e71be8d15e415084573c74fb32e6b20a9ef35d4fb55fb9ea671aa68706479029a2c0ea338965731887b532f46a366b530a1cbe9a84563402e4f5fae9b402cbf3bdf49fa6d9aa6bf1bbdc15c3b9b55411762261ce6f59e832c2a5d2959387aadbc992e5aceca708a645ab42dbeffb9cee6bad254bad91411ae813cfe25cfb496b84991aca1895dfd0896a8e9f67a7f18c8ea17f4a304be49a61798a0d4252ae418c9938e8a0e451b564f1fcc63cac1cbf0f0bd245a5f3a7d95c4f9cd75f3b937792d3f576b9cfdd5aebd5dfa46e185f019a721b3b112f4cdedca70d6a23f3ccb2ed97c60f0d56a3d8f3b144f289185be0ffcb379230403ad2bc8c3cda54b2d31c6646f0ea6d186ad59fd7954e9c0783c91481b54b7f53e32c3ad45c961930a7481b4439b5d67fe03b75e2d68b1fa40f34f86bcc375ea3018ce1a9695940cc45cb74d35d9474df077939210e92fb9ffcaf3bc28ff1fa5459e53878df4d79c742095f290372b336c22ef93344e9c8e4aafaea8749d62b1ae5fce9527c539a5cb10b10fd64191fc9dc738a11b3e932c684a15472fb5545278", + "slh-dsa-sha2-128s": "0xcfed5929428e4a18a3254a62c3e779929849cc1524330454d3f08c03a0fddbc7e6959624120a64ed3a916f954d37613a5d8085b058a0811fffaf2a33dcf0586ff5a109c707d1508d3a6fd9dc269a7bf30d694b65d188a30cec35650b9244dabc3b0d8bbf8990ed34fd71c4a42e6f4da84489d18a6f40e3583d010d2c53ad4455990d1f3f4d8c05e2beb42e127c7fd87747bb53cedb431c88586a7bf044251da255c885e27c58d00bebc8232546d42fb04369c0c8a8c410461a89e22e5961d6ccd3aef8a6eafae1923b371b70c6a3cdece436f8adc4a25e0963fdd40c83f333e8b251d792a245f758a7951b2b042d3072c4fca7ca1ba7bf95031c9025c49a0a6a46094955671dc1c18987832b7eab0632d6a82e7a810189c31b942e2928502b7f1770636f3bc2e4520dc5fd4a5f695e7fa7aea3fed5b64fd18582da0b3ed6b3f8f9b2a71f49e5632cf7c71b9eff78424f036f2f8991cac2356d000be9ee5ab771f8adf314df7ba29562a4655eac39daa2fe9d09957b7e7a7299d27589ecfe82351205049fe5fe114da525de2400e0a55f0dd3d55e2a4166a2878a4a0b778eea4062074ddd2505f2cefff79f50b2bba387c25d249b4ac284124f20e71323789f769a3e880b2b48ec14415f446e0554afd3c3a281e5ec5e5a123993c1efcfeec86ebdd56cbab290579043b18b9b0cdcbe215c2aa390b3145d4fc953e94694ef5380ce4d76b40b1734c5f3b62d016afd7ea7e9bcfe746da34c576223ca96f45f3ef5c371ed592d4c96645b6c6c050eac85aaffe760315d3094c6baccf9add7dfffb550c928cae4427133b1f790f7cac30f0ac25cde2d729b615939e3e10ec292a56c66b8c2cb7169e87697b0b3d12cb543c7ead6fab051ea0e399183acb1bb42f999ca2ba40779f3853c3d90aa5e9da408c84214a0f20b94f88c6a4f756417fdb7ead4297bf1524c45008a90818b4fbaafd10df041c36cdead39efc3bc3d86bfebf0a1b08744e574a5076eb1f349a92bf90f5397b5481eba45e526acf0f8f8b08aa2aa8153aff7049861cd31a96534455b121955eda9e92a6cd25380edf004fa035623cfeb681540c5cade3ec587e94fdc94c019dd22bdfb61d58900c5f78ca2eae2afad8d82c89c225aea8668388b048c2d7e9a3e4becccf5dc7439c8f758f18b2aeb2fee6e03d022dd5532a9aa6614f2a207ab5a1b7aff7b0a907437f07f39d6cba22357c3335188540dd9b0e992fae045e8c8035ae1e57b1bf773f0cb8e72df1445f4d35e7e6cc966461d84e871c0515dc0249e18ffe8e70e1fb7e17d1b12c2bb2d07e6fe86d5508a456a693c49b24d25ef07fe6f99a252d367d6615001cb4d38fc6f6dcdd6aad4fdf881a4c53675542ef23102142418b38c6d108958b0f75f80bb2b7f3be3a4b40006ea0bbe6314b4a078431a55d1135fefa1eca9319337c3ffeffd66fe57812a8df643da0ab40c57b27f62803ba6d4239e8e0ee2accd7ace8249647645dd57b67c31b02d01f258ece910e48252cc10df76ff372e49c65b25237eeb86eda87bd8fdcf186e8ec5ab3dd0d53dd670475bbd700c2d9f1a57b64177f69ee48a71912447df53645e8c3462e82f1657483c1b6f4ddc7cdc953f78e204da753b66d853bbdd25723d77345ebc2614e862c2be28765f82b4da9807e9cf3ec2162a2664f267e1f8afe44494b9b3db63ad5b4f29275d8a25070a900ce2b46726b33886b86671611ae75b1a3dd9317798f7084b61c4e98f1c1835d13e75fe5662fe8789bc56a4d8a29878e7551e5eeb314502319dd3c23f78df409465db8cd76ebc1afb4b5172463169ee7675a50d2bedf040e9b0e064f5513ce203fa8e3743e4fc5432715d398e9b0c3d3508cc9015d973de9d5dc42eecd4f508fd6b46cb93c6dbdfc8213a05af177d546916f08053287ae38a8052fb095d037ed1d11d5c83668a3b5c72a4c1ff1180a2333af8a58b701f3e5f153d27b3fd8eafde1706c6df1ab4c5d4835f6c5c5aab78c6a5be1b2689674831421dc14cc8b411bb5f2443c3d9ff5939b09ab5361318cb1a822637ce9159e19550a123cc3a68d7651558139dacda53f5edec6cd5a0125244e72433d063c9142204a720edab42e0d78a497d479fcd55e6de96fac77f3d49ca12d0fcedeb16d2736fe7e294ea2fa0b38180bbb5c14046bdf9e7ce3555f169d645a62fdee9308502cef240e3f292b5e62126a0638beeca94a12c01002925576baf037aaece8e4d96000b585adc24650f1b15dfcefc4ea2895b08b6e3f4a2fe4e9aa4279e0f72abe52637b9cfd9d6c477f2c701b1f46cb82e1d3017a55e6038f6d698ca370e5dd86d82599192994cb5925be803ffcb6f7e5fbe80b8f36ccae48dd235e790e96f5deee95929935c62e70ef387a9e147504a08a21cdab92fcc5b5646822d03c0173960379f313a4fb1bb9232249e087a7f6ecf2902e1f1be952544367981589b27f6481c5552923cbb721df20e6c52893582d7ba305a804b44abf58ad4b929c5a2428ef8c4656dbf888a607d6c5e9ae34155a2490474c4ad62296a90135b7dbdc143acd0b9068912d36fe6796323bb1ba9e4e7192b5f8b15953d8ad9e643c5361c39597b9b7ea5db4227c1debe17674674a67f81d9016492e212022e9e88c5ef33937ad5cb0b56101a5b798820d05fa73ccaa7b6903a4f9af03920b76a763cba25278559907dee88641bb286632327d1162f4cbc9ba5ea54715e6c1a4a1abacec2f44dc5afcdfa469e5384a08766bb7370fa420500560f6dfe90e52ae942426887694683cb8fbe8a955fa46b02816707560212e55a5c765b72d565f263f60ef619335cdbdd32a80ffb4610db54fbaf3881591164b22ae4d56e02b30fc26efe7b18cb1df2325adf76c38665716f4d2e6192d1f892b3d9421c6f276874358fdda34e2f1690bcc3d84bc7eaa70ed2f2bb2b635748d0327ff1a9cdc61f339fc3a3e4eb43b05d186172156e0c1d748fa5a3a2d1b6c2ce0ea884eb7151d2efadb9a22a3946872aa6a8a1b4ab082f6a602f8d525cb8e359270044110ea25ee922d00d3271dea56f117c273811a8bfae869e49b2a643f99cbeaea7e047af3b02f565085fe9749dc808195f4890cc1c233bfc0f156481d55967b21683f38f41378ab7e1a620b946e0464b9b0818a1eef6f3979573139b186949faf4cc6a2289d1d91930d4f353903278edc8ed9d8191de47cc4c1be11f5bf963ba369c797c954bf111d6ebec67acf97ad144f1bbc8b3964e70f3f0e22262b792114e683be8638db544dc0f2975b25c4027bbb9b1ebdcfe1d4834c8d3f2dfa9de0d78240421e1865d8fa29819ff34fb80a28fcb8c33a9a75127f765d30f46a8b363189922932b36650589f93a48d67b4dbc727d0e02e6e5561f97c472672718c39bb6bf2b6472063bed3b59d62f9fd1ce4c7fed1b482cc0e85e939d49a05d45cbda143767c998da2f910d6f4fc68a429b01962df4b203eb99ff32f641c7f6a65fc1ebc645baa19e73f44f9f11747375cf1af9134490aebf4d0d8cfdf4d293deaacfc304b36a554c2bbc2bfebd874373ed4eb9821ee5c2aebfecc582bf4a2f4b508e66e06e77f7e598229b0d4ee6d8d23df5de37e5ec3ac9e39638b8e4274faef687eb652b21475fcb58ffce53dd0b18002f998df21c170f7a3e073940c05487a350aac959a1b62720acb57a0c56d4f288d7543fd76ed1fa2315b74a153c4fc3b421671e2b973a8b733503b73153039b0af4e139eee3439be0425ab41ec60bb8ee3d68a5f1bf97031b83e08f62fb5e287998ada7e790559a7f03039030810321bf614230ce5221a26509f5313e11795fe00e78794ca2eac07d5b57108e4e2c98e692fbaf667511dccaf4db0d99fe14c0d1016167943f855352d52119dba0d9db8526b65afc22220abf379bb5ba481b18661f0292bb239d4afc15c1ff1a8ab210f2fe9af1548cf35d294068bf8de82b3b76edff630b42a91419e3f0e3adbbc261dc45cc198e90b9100c5db380f8ccfcdbe35e6671b984e764fdbce262712cb3aa2076a34556de1a19c0e7dadb84cad656f4ff93174d42b7a84315861b07e092ce67d72b5105e3a2b57540afd6a9650ac4c63cbe93860cd79a21a8dc85cc08128ef60ab5a118e84458236948113cf6e88bd825895781e40b9d79b7222fbe0b8a25ef9c743992d774673a160973a6ab752aea826130196f5da13af3e32b3e55d33aaf0e4db1fc72ba56982609e7ada528050b7a8443af09d675283950dc827316749e7a63422a111173b5ee2e3cfe6af0d8e6bbae627095d4892c1d7ef35ed431b10bdace83c4982ae96fe118f8e7520fb9c896b5c14ca1ee90acaf0846e6e6e3fb737da0b6ae1ef814feb5cf3b6cd62c4f2e4d46288fb757717c995f4ba3aebf20d560dfdda9e6e9529b631d24dd6ba8ae548eeb8753232d0ec7c71d255511130d28bdb310e8c7a17cb744870810a82f60795293c0ed17b1b093caa6504245ffead4a1daf98079aa159ee3913f9dd63ad566271318786923ff8e737f2edf75978d73015ff21e89a255ca66c8509addb1cf6feaa7ed032d4f7b944fa6fadb5c61bfb39f9b2b951f0044dc8d25e50afbd6f94a3b2eb2def735fac533da9c03f9ad3d6c595d4d3ff2e2fa1f5bf8245e715c82a7ef78fbd7370a814c2ccadd0fb0161b864d32622c2577d1ca05f80981a5e548315a1444c57a3a853b2837f2ea9e867b86f51d1f6206650fa6d764f1d9ff6bba87c784c90b39727cc4416b269eca000156218dd561794d8495b3e39d31b14533e611502b6978bc8face439eb35071fcae68ee15c65eb48962fc92ec8cb95fffa48329d2f3ec92a8a9497cfb38c73f75201b0e9884ce094ff002ed31578b35ad5e511d658e9a178f46ea32bb0962721df026ed20e025e82e60587408794547b7213465e823ec96da0a1f5590275282bd183084f194e089e9c621dd278f2f6d6024789a3cc9a7b05cc5cdd644093bd8cbdc74f5feb832e01801c1267fd9d81cb93992ab4e0cec5947fdcdb2e1c5aa65473168fee23f92d244d7cad52de41c74c5098b3519064c9e27aadbdce4431296d65cfc3b4d93ec32ff05db2d7f90af7fa5568ca8351fdfebbbfdab9ec50100fbecb682ecef58211dee4965dbf99cae16bd56cd69ab7a4ce09ce93604ad2d5a3c5c1321c35c3dba78362f805d5ea175ce091de4690a29a8caab97774c39c7459bdad34c0e870f0624905360f9359f1d60f554dfd5a0b086ed44467214a7f252f0fa7c6d3ec38f99bbcd02945277fb54de173e66ed51b6edfb0d9c935142513259ca80549624a676b40e3519f8cd2f1fe8e423f09c362a4553b424424cfc9aa5996c1c85e773a92e3fb7c058fc4b5facff859ffe851fc9470e153ca80fedd002a9304baed63ca19a65e32a715f1cf5dd6f6131588da4cf3e2fa7580dd93759ad557e20eaf2e514988399cc8510d99fde224da79ad1855a83b5f8c0c83713dccb8e834cb501f0ba4edca119d359e8ca3f418dbc44b04b71b7f339dfd5f7c6e5260115558667fb39897ae89e89fffe7089b5f22a3c8f9e4d7ca0cba0be7ed94f180195977e2f70430607edcf43a964ed0bbf7dfa241e8a394c28d5cc60845b21fa758dcea3ac78408df5763b7878c959f191f6364891f83c749b283935154c09a345b78b4133fab066dde8d0f947ee35de078369c17f556195e489e74207feac829108f73339b3eb95bc050e3c1943a59bee3f1bb6b6d596f227c221b03849472b53761e5c10182b53e5c4acb641070019c08a318e5f22e7e7bc7464cc48ebe25b66016fd5c5b642ad092dbd56cc540ee98289344214bf4272d7e914fe3979d4a8397bfa5cea600caf068b3ee16eed7fa8d70f97b436dbb31a094922a87e8297fdfdb35b0d95155736cbcc5ad2484950967cf0eedef642d458abace3f71a51cb0d9e349e21fff8b7d22153ee122e3db1c727e1f53274a49949b0f785aa9785b915272b45a85940333043ea207894e36e7a095f44fa8c4981f9fcc2e57afba17e03a9f2a006dfdf364395ea2178ac07531da77f0a3846681aabaa4ec59f13ae6bf0b409a959616497e83663cdc1afb35254053a2ebb014617246c6bf3203506de394a91e7899234573e8c421d783e45c33a54eac5092fd87327ce1b7bd5d98644dce2abb9b23299bb7161260e7af8acf47473fdab439076267e1b116f88beb49c7eaaa067a329e4da0f3087f257082b8bf60948af25f528c777fc4708c8ad1cb9ef7a0b0fc8494464031b9ab98f643be49d6dd94b76710ecc594930b104147e2c8839812e3b763cc762d649730ebbb162e51cc76ef6ec59ff1485d853e0e2fd3450f7b71668ebe84368e19a02ee38a0a73c369ba253777c183bc2493f736e54b25467881fac9da5ac9203ab226c6e8c22ff6a1bc0498c9af1207d5b6ff938530d74766a3fde9aa765b40e1befd607150601ba4f981b5de4f058785fd20b4e29a11e210bcebe31d47039f3547f05ca9f30555365696f0250455b8c51ad8c0126f1becb87b415fcdab9ab0adf87a2f5d9bfe5c19e527acb6641bf6501086fc5bbca1d938d97e96fd9886e1dad2a1346318e79995756ed946bc4eac7b91e7f904900201ae35f08e2428f33d5c4fb6a82069680f5e42c6292a74841e671540057e561889e8e15aed4a4f2e929458b988f4cfcfadf601f7c36d315d293252dc934c7d8a997c0b0f82e396571d0cecdddd31aa0eb5e7468509f3d20a26e4ba14e0c7bfc028731e240a1a3f87358857f9f527be19795754022e8d711e33a20c4d3dc7408866e3e35c1bed6277b6f20cf6626e78110f7f0a8bf20e89b0483d5e0a2bab8ff0b3763f8c24225395c7907db44f2e0565bb1b3a88410d29bff79a5a487fb01381c7d3ccbc7669400b038604276bba24be33a35a904f57613388af90709f5195800c2ee1a0113879ae604545b1bf3f712981995951e04cb73214f2989d97ee813e099edcea41399341d5f2b89c538e6ac0b5c5030a49d6ebff73a26eaf7d0d058fcb3269398bf6c4035ac66cce165e42fddd1ae3a657d936a64a39648f9c7c7519cb5ce79014afcb6c31f93b4f634e7e594d3f898972cf8f675abc4bc1d3fa2a5352453b4d877709354bc21a887ca49c96ade15c0b988e1f7ffe6c868e46bee7f23f2f0ec7610efb4b7a95f5d775b7e0a5b28ac51183ac577ffe4c2bdcaca6d1c8f172ece9a540b5fedcb85ca50084edd018b5bc90decf1a3ed8e27a35ab98b964acd927c765f7bb33f6506aac756ad8e331b341a5ddcf9e681a9614304f7d7a2d813f83fef97c497ef3862154fe26e3e8ec2d72e3e11e654280942c9925f1a700ced7a0a89fd9d1649926aae5cbbedf695972e199ca5299f011b27f369b96aad2209df885598045924a6dce622e7e808f93574a03dcc384f52ee547e099df4220a47dd5828136dee74220f75a89a47b1b9f7ed6942d1983fc14c37ad672deea6e5d1744b57f2ec34aacda2fe4bd3bf7648151d09a778f66fee003d5339c868f160dd3554af836ddf5b5e2c3c83b71dad84629a4e02ee79564cc189b854926d7ef2185bb65f56ff518002f0ca4c92750ec391c265bf0a54c618edac01b7856d05f7d6210154576c68faa53e8c4313289c75577c69d3b767e0ae9fa913cddb7c84770b565e2a7b8bccbfe5e2908abeb63f5b11a4d1dffeb99a14344a6151237b3cd3939c857bac0b733ff3fa6fe973fff5750fb4808383afbcb6fe937b98325e8d9adc922b1363519c00626c1925cd0deb814482b575b49d4855da093b6c65557636f01879c3a6b1c179166b076ef081d8683e388fd9902e531e3a250a356ea27748c8a16b934a4478bbd4e2fc6da03394b986322eb45ececad85a9a9835f75038f98951c088166e265a5e7678daa806ff3b59720f980bf82672bf19bf2db65756c4588150e0d9db87cbbde8600409f3f94f88cf8939af68b7dfedc5f07bed5dbe668da0c54a85f972ee224ed87e192f716ae8154ee6d2f2d867950e9c52b662c776505723ff9c24fb06cf334a145b0008c4533e40665aa228cb043869c005b7982df041bc8072812c458c985d969d7bd8a2050e9efece5ef9b126313fc43a3d1a4a158a21a51f91cc091161af99bd927e1457c4b024b7d6e803b240d6b2038005f2bb4ea6dac1296990b1d996a2c2069588083c4d548f5aa88b978f9ce541075c5d48d6d98dc97f46a9f9cb92bcd9be219af21cc5a4cc4af560f0349084e795c9c4c5f468acf8a6866e5174c78fa4c41cf2d4d667b747082a6ce97fb19d9bc5f1b335f84810412d20e3e12cb375c162c68ed1b33a935a4e98af229c0beedb04d7a5ee1fec84d679e2b6e46ae9f0afe2d93b9ca91d90e9c606d409a8250d2e35b8e6179aa29b439a1b2fd7400114c195b55373c038f2cb2ddc9a9a761a2ff9a920c9a6baa798ed10fda4f7fcd2ade3966d26bd99004c8efb5ca05facc46f9b86651576e5abcace7ec2542238d1af4ebc65d6fc9981f31b3a4d8a445f03433aa1c71b9586a691a436921da857aafaffa37a8d86fa4f59edd4c4379192fbffa62448f7aaa4b8effde629110211bf5dec5d72730fd0f62c2f7fb2afb9d7853dfc79d7c41e7c3ed0cb6a7975a636fff0fa5cbdfcba74ef72b9dd08896cd793ee95c7972cf1a945e6a9e00e8ed64f836e5b728b8666c65cbf32ed439d17cca4eb931b26484310ccf1608268a418d022b133a57aeae19cab8f845e8dc53b8394bd41f5452c6e5eb894ce7634d49e5bda1bc369a1528493d26d3e869f801b64dcb13e68aece8640849518b7ea7bd4e61b36e61c7ff66fdd91cd35e4f74652ec880498c9c1f612fdff50fe3bd92fa33ca772fc2ced4b0d2130fc30b3a392200b03127878762fe9ab331280e524cc579526c15c21cb0db364868ca507f1040afc2a9550392c084a7446a7fbab0fa885ba04ff889ffa124ed32ac8fdcacf927c4095f6a94b262f0e4f5c5c937268d38c712ee1f1587e522729d7b7d67a1acdd345bfaf1e75e4800bec66c5f991275a326c8e3b56fd463868c7a5819891939979520ae4e63a3c6a877f29ee3c37893fd963ea2cbebaa2a2230a970da7d84ffaffb777c5263f8f359cd3978179e0c57156a475b99f5005db36458afc40a710a5730cb613deb67818064abdcacf607345047ef27292d7535a4cd8c3dd4b94f58cb8754b8f40abc83d1b48429256a9fe6618ca58dbd718cee2723d8550f31f20a0de79929ac399046f2018aacdf657147eb773a05b6aefbef6ec275812c44419811f0f2767e8de5a4f13bff30c386c32d2b64c97f209ea3f7c6ab4cababa251a982b49369c1230f08dc200e52f8f0fa856a78f8aaaa9e09868c493154c8ca2ce4e88751e766213a5e53d4031b01f70d5a6575343e470972a4c4539553dbd742676137f5d5aada486a4d13529e7ac5c6962d6923857ab28b01eeaa74f40c501b116a463c05b796c0adccfe662ea2fd7dd9741bccb88cd85306b581b5d0bd38710a5de938556311e7a2867973f18c20494654b60110bd13b61499f512548884a91a742c27203357faf1783119615b796bbe768517db4ebf160967ac813f10e64fcc933c56e71d9a81e4566c9fb63de12bc35210fb2d5450c11762620a358e8ecf78e12c1bb1deef10eb8ef81b139d4cc11982c7493403ab89dad97c48a671ce4301e71c89923bf3912416a0b40b1b5baa19f58ce074e396fd543ac56be4d84dbac3dfb05120dc89a4986876d972db2e771b8484bfc5e3c238f30ec621dbf91cf7ee1c04395f5360ab812b7ffae2a72f44d581f03f4e2f90db2889d613cc44aa9fb39668dc062ed4e489e7cf7c97a26aba21ac76e78c61e4fc5717edfe815d9ced441eeb3469731536e0e1773a2681c4d3dbe45339c1ca3dedd7f521dc87ac810cf5765558aeca4721dd8dc302c5592fe0f1ee73f5e5ece0ab695e2494bdc51e0acb2d5db661d9bb85bf4bef5ca2dcf91c7dd739d24ba4f46d8698e3abc1aca5d13ed714bd28d0d8ba32331eb09bb9185b3c027f690d4822e77f7e9de730ff9421f48553bbead60a9e96f046fda5c4bb7a338f61e2ab267f4c33cf0cc7f9d814822e9f4c97dbd7ffbfd8ff59403d3a8352c3bfb5a495933fc5e767835eb237c33ac1a13d309f00001b81f84abea68241e9c13b9544c5baf0348899173c28b5814cfae82056b85651483e8c81d4eb6a15cf5873731f4a0ea66756607d267c7907fd88e073f0d3229b1951906442b945a6d740bd9bf883e83062054787365d12db4d2227f1d9e7c89fa880a8ab011a391a84e804949f19e2f31bd294b312900e26f60f4fd082d26705996c9f31523a10de36f34971ff1277ed3d701946c1b5d792011151852f1291bac7390c3647cb90c5263d845b06af0b0e443f6e81a918724f87830f33cef84db60a5fc02876b442557603de8f0f88da85bf048653249f47e47284e393cd4dfefecd57d9e36e0408c04b8c5943db194fd1c644adb36d84d83b4498df862bcfbea101af7cdf8a6ccf8a2bc8411a42bc993d221feff1005c3f0b8b7bc072ca9f79af93cb21b7c35ac2dfb88871cfbfc2c252d02e3ddc90808be24cd11607f0be971e7b6f6a667ecc5e624f76dac5c426694b74ee3bc0ee0987546541c71e56b94a5a8b1fd0277b3f910b17feef371aa5b2ddc908d16bdddc2eaeceb72e1c1846e21b09d414ed08e9114f329bd632cac8db76e42fcd82fe8e63a49dd76f308ff1fadde8fbd75e2666fede86a4398e9b8e85dd2d2c9b8b26e41260857d043e229745821802998a42cc0f35a6811b531a773249e5b55ebcc9f9f13f354d07b722f0fcdc41f44a520bde6dad63540aa12a7e91ae73fa4fecd9972cf65ca760212cf1426070394b61bd003940beaf4f6fea3d433aa15deb1835d56eec30ad1e8dee09097ffb3073cb6874424b3b2a03f3b5596010bbad0378598d482e78a3eafa9d0f1d7236a5461a418272b4de64753f0b578f4872a21c088b2a6aa23184be92fe1ae7e6f216361feaf69d91ce9c6a55889e339fea0702ffb1541b0c2034bba60d6d31b2d8531c1f75051e9c16075be4c031ec3fbe97138f1d27b12d02f2dffca369e647450e57cef09bfcaacefad667c98623fd" + }, + "transport": { + "secp256k1Address": "0xb5e768cb3117ea25175f51aa956b48691025c2a8" + }, + "ecdsa": { + "addr": "0xb5e768cb3117ea25175f51aa956b48691025c2a8", + "claim": "0xf9683bc33acc9722369083cf77f7645c02c20846514a5fee74cb6fbd0ae4c5f75a8fedeb1182c8ba0e959a49afb7672a59ad3718ac2f000fdbb151b4d61b48a101" + } + }, + "4": { + "id": "0xbbeecc251b373fecd3462527fc589879b1c1f49f", + "keys": { + "falcon-512": "0x096e9ada38d7da61bb7062c6812dba3954f433ad08157ce4e9d340c3bb80d6b9b1d1027cbfe1514b2a9e5266da4757f9536a3efccfe15255baa4f48fd442d9c2731d8c63a29f936c1a6908f96fdd393dcda5ad19b81b1ca5c4472cfca358bf1566eecd9e3082dac612c158cc3788681f5f0868ec68a06cb04621465a4fca948f7e118352813e5d2138366c97296dc15649c99394b1bdd0e7969f913c255d694a989d75b6499a7c19bb1ce46f313e6a2fb6f4faa7ba63e4814e3348f7ee68bef4b823486dd6baf6f5b847a48b78bc1003bb125d3b26aaa9694a026c75da351064ff868061a78543677db940eb33a4636baa3e756948d61845dc43c04595427a6e9568a216b50eeea2428d82887931632a5a1d33803b392ed142bbd5cea9f619ce563a3c7b35d2f0a7709ed1e20edf0754f3f60aec60b329c0f51b2ecea714d079d2d4ed5f58a737feabee9c26a0320157147a3295a0eb00399eec3bb82d0a33a9e18789496f4e4d6dd6f29f106eab227336b49f688f95b33398c5489f5c32033cab2176749445c208500778e3955bafb2521628740896a9525d85d61aa2220379f8bbe8a16c44b45652d9ae7b2bfd3664a2a64133edae4b4edc930c64e6d99f97d707fcca1242467c9d0c71c441e59073e0d879e3af0529fdaf99eecc7c5219ec66d2c61c8294bd90dd53a21ffc0b230c6f6a89142336478c1179d6ecd91881d85e1e6535c1692979f217883feafc45b9a539834f0b9d74554901a8b83835c983fc43fe41141281c5234f02d50ea5f7a774a5d4dd9b8aabe902d2d0659bd1773bb62a5b1750a75f24ae7ae492cf2a5469563ad5062b4592037401ac334d8f6b2beb46a8aee678c11e98503e0be846dc5992e43b2019085e2872baa217547855e2d5b9984073b020b5224b577352c1a4bb900d8f5fd974c2c027cd633ec0c08ccae82134453b720a67b78e5d01f617343d81fa0864d6b0b1be09d35f1d707b688d134c4b82af9eaeb8908f40b259a8334c04a5223074638a82046cfaeba392c21f58f0be565492958f6282baf64d98a0d6af810490705136d1d1fc16e43b4668c9cb4fbfbf58d943ce5de56fbc5e44a684990b7df050981e559dd9d34a3fc4962b1282a15e63ac0e85d8d5794cf15a94c9409be98e9652e59176689d153214f2c6d011aa41f5709e536e267a9c897a10dc61081e012c51a2467464023c1dd870091db16b54665070a4db581cca14bd3843c3d42e907ef1f7c053d0a535a4d4f92752", + "slh-dsa-sha2-128s": "0xffc690bb8feb463cc359c0dd64f017f6af77e3fdca17864d562010a1bd058687" + }, + "pop": { + "falcon-512": "0x394f2dcb2bef4939d9b6742ff7100d14dbad6176c22dae5ba784dc70730658d8384a025ebfc85f662e9decf97bf083be8de24df70797a9896f9f195e52679041b9467f5506eac3279788f8edb9489606bb8d90d3e4283d3248ee64138e6ce26dd8b23d3a6d2b06fe23369434e20f96091283617b688c47a701d6b97a370ff5433587b99172cbe1087873b1a2ed1d41a48a5206b74075f68685a8834bb54506ac83effc9b9d2fd7f5a551349284fd19f40ec25ec9cb13f85e9a1532741cd57ba0dc9c145cc0d325c8ea7ffd324cc7d9e9877f4b0c65e06d1173cef4dda169774b40c996d9fa21f27c7c3e930cdee24d0b3cf6330c2c2e17b04b18a55dbb39f25312ec72728c66f4eb33d18c0dc6042c8883bd87a123ea38d03a8f1fba4b1a27d35d1929a477f79da1ad699aa2bed1306e17510e5af8b0d4bf32c0139ee21b3855610b5fd1bacc6ed3ccca2e364ae45752d77df70de519f85637289b3b0f671fea71a07aa2cc299fed615b2eff0628a97ef6a90d1d3ec9376ebdb3ceb421c42d8ed924ed032a25f4a621827e3edd4fea2b3595291ceba6a1458210db95c3f5a13d9c8514973f4926a91fb8b2bafc1d098292971f42118addb791897c0188daa754935f24658ab7dbced7c3ccdbb35447ea2bb71e5f386c58255dde9f6eaadcee9e0a45a0912c685e3e7fb5cdb7789a877eff9fee13e3bb072794b4293fc5a1f21333205118bddb16b2efbbcb16a90dd965e198dc3ba2f81f55529aaee1b44425289930999afef79fb56defd95d0c7b8b6ecb30a8177922253adec2f695441bbc4b22fc5659520ed652d1cd83a88e534a830b10666f97aab4d396a6fff77becaeabc786698ee609d9e1d70ca419b820ee5cf75320264bea40fbbcb076269d828d14d4111323ae3d851f9aa78f035c936784", + "slh-dsa-sha2-128s": "0x081ec68af736d2898dea6ea2999956d8e4e1f2ef6c2d3725ff4095141105da053c770ba1f858c0745b63b745958be6f5d78c91910e683656db4e455f8669944347f58366ec5bc960eda3ad1d973ed7841eead6516c8c0d22eccccf7a80b3f58b3d884c7f85aa3eef40b678905173f7c9cdd44abd4406182c51753677a5a93d26157f3847e33bffc29237fd9d66072973bbb6faaa6246bf5b0b740d08d8faa9a38ab3d94c49df1fa726ff98c29901e941e66532af3956b253309b3b635aca4f952f1d0338e0868d373100d796b9cd0296643d307f6be5f760e879cd5bdc764098e510d51be648e7cf3a7528a3b89753650ec13a08e6fc6956325e1d9834cf0dc7f4c88ed8c503f52dd89ae421961fbf20d387ab96d9a4e6f869b1914c3f0512c41105fdf3aacdc5782e27e9080b1b3c0f7bb30bade0bd398cf82515adc8e92a166850964e660f7e83bbfde0d8603a8bf0ec06105994c0f1d0a2325a494c450d990d480047bdfd97c325c82c8ab5e73a52b9225e80bd37c1b002de9faf627987b970adc9b50c4cf5300ecffc430171dec4a466d91e6e54284239d24d71c6d272bbb7281e7dae2a83d64c89ef95ebb2c36a5d1d3d82a9017a253e58478383847dba9ecf981d8ba09434be1255311a2238439c5a942406d343a302b16ab99ab5de8fa68b33b420a5085444929c377f5545fac9f67ba0175945e94cff5a1f2cbe03abe2b2adffc0dd245c9af6e7a1dc417dc6579792f16ca12f35ae0491ece23fc46d49601713a22a59357121137c58a962f2d3ea8106df6371e14f8ec00b4365781456fc9b164beb447b1be58caead21f19e933d4d31934587fb9b1c4d026e9560bd57044cd3d68903a2f8dfab73284c639dc14a672ff3656907a8ea67b30893c19840aeb520d4b9a1a0a2fc624349765c7f14140e20b13fabc329a5a3c75ab3e2f233d57114b9352be93ba077f287c7356fc3ee665c4b2bc524873c2b3037f72274af515476b7e33a0c205f86e3a47d064217b87a9def7b7c207dac108220d6c0379d708e767690df991f28cb3f1b4ced36daf8e30ecbac7fcf85cd5b02a85d0b64bf6636c388eba65020950205132edcb3102af3fc045a3d733554141026b73809358fb1a41edea5690e1c0930bea8fcae3073ac1c6e828de2e8d87cf78b7d87972d44c1fa0b87d0d89089acbc578490d19a8252e4379df53e3ae51b9fef8801499f493b0016f66c7e58651f07e430da1eea246d9846937c8bedd1f9ed2818c914ab96915c5889fa59b5fa174a9e15069b69a0f444c0aea979f7f55e09267fc63509318f8046853d5dfffb52b66614043729315d13aa9339b5ea645249218e6860a0e7160380d26bcfec724d491a565016dc56bd55d3be3b5cca1690ee9f73a90e64b49dcbce5b389366b6095e5044d8d2e848540ef37fa22a2e3c39ce044351a6559b49d91cef513743cb7f39ac092544ef5ffb92adb293de7ef9f505107ba9ff8fc928ec73c7e3933b1faf909c535d0aa6ab846928c8b317f2c0594f87aaf2d770a3ffbc7a967f50fdc2175d89bfe11a52091f4aa3e3d54cb8acdcb327d1286af76328b3a238ab90eb729ce3a1982f823deba2bf9f5b4f9db596ff0af851724cbb5c94cb175d8a413160bc51a73996bef9b8fec863e2602acf24e959d3b6623524ba042ab7d9b164f02743a62e15f121403bbd2ff54bb7cc6e6101b42da04df0d8bb40ad9e201607299e6758c71914df0b5b5bc1546186b87d1e118053fe314c1b6a7a2abe1eff9d02d9867c1e7ef2b52d6e726fb9fffc3f1a472d621b49ecf9ec712eae5af01970a77736c5ebb642f67e1ca52b48e45ca28f0e2910fd668d58c0b45774f6253af8ace12ef7cba8ad6964778d1ef37bb965f6501cbd01828a5c06b9916783ff2c55dc74a3f0649d1d5a2755b85bd87ef09115228f0627a29787ecf4342f1450b7faccf1e0037120dfb27f984379999d778bce2c60f1789d5cdbc8fbf55e3fccec704d5e2d290436de991ef6123d9ed7920ec6effb725d1af8afe4b99c8d8635ec1d5d470d413203a16f884b65203602314abaa902fe12b649c53f3b4a6f8645878deac2168beea0170ffa5fdb70e6df6b0f2f5e4fce2d296ab24e425e9cd5fbb46215054a4fbbee4782fdd3f005d50ff57385f7d4ffaf2b44c9c143f670b029ac8d4117739445a8484d1ff46055f573eee0de5eb32f27f6fc2735fb666d6fc6424023f9c553b62ee51defb4686f2ccfa9ea74f27a37a5052d64f35c6ebc5d8b0aa03211ba8408fa5d6a12a7ce99ce6a45e50dd1200a95bdffbe2ac46a9190ccd724ab9d320d5d96ed457e01adfcc66a5c8f025f5026095d8465974a69c6a7fdfff895216cefd264e2f6ea44f5a0a946482925dfb28acafaf058b0731f58806602a94b5d7c84d6fc1d60083365f3711a8240c197d37982f6976531fbcca7fce1d3df1c7b6716e09b9c2c1f68051884286f034f5a34ec124ee8e0d24332921c584feb1eff5a09cf11ef43d4091f35fa0be884b2e9474732a541bdf792b7afce8b4caa7f23ca7b513b66a9af68d2f2445cb8d1997582998ff18ce3d5f8e2e5855be73aa479a220cb4aca3ab98cbac0f1ab5e7e1a4f4f0d6f78770c2452146299a9df3e20697f9ed5cd8185b1685b603808b1a59f312c2692fda5dc213ea8d945d76d2289f69728d44d8bfbd90d0d4b804f6089e1fe93e5cd67ac69e4b78a395cc1a38c182a94e2037b683d1a05cee6edb4c51beddfe11222229fa63c0eed44ec5618326cdb17cf98aba3c0208d853335508f08580168ae00b467dd348a1ab60f83ead0a50feb212e969cb6c4a2eed413168cbdd28aac6ec46708907f3b9bbb2314eab283d25f07a13ad9780c116dc0ac57120c6523bae2ed753fcfc6cef0497234f8db72b8db5e21e05528f0e19035fa3a1bcf3ef7c7c09078d2d9f800689afe21298b2b8384c0e3a8b7dbbe9d0e1fda086fa9ee0ebae2e6eb93591f54d169fae933b9c7678d206ac994eb30392bcc43dabfa7c2ae24794cedaa379e5019e1176363a4c00e127ff4053c31f4f0b407fd0acbb08ff0e11d126c53c11a79b9bc6c6df1699bc9a9c4c8efc44b43c9b782cdd5efcde2cf0056c10ddee92a34cf5c7a67a7df2d86a7a63bf9eb0efe130a35176de95db5e0dcc553a049010f93ce3ff0ba666a7d0f0422e2235fc0d3c60d487e3541d51d84c430593297af499f79450e5024159f0b8e7e71038bfcee931ff8fd6d20d2ae607933f032f76832bbfcf42ab12aef196e61225f4b3be4a3f2887bba0608f88db35dd471c716472519a7096cae279e1abdcd2f395b702aff6c7c7485a3111593bef4e0eb819ce697bdbe65d26e88838b516e2e8842b95b7e78f81d2ed87a9f2d49e8dc9a47c9975c669d2d9d6a69242393d134d44ea315b7d48093406b9a64523dcbbefd65951a1602fc73be96bdbe46948f4fd1cf0f4fb4428a4e1e539bf3baf4a079106a3e579b8f131b76a53d03bd2440d5ba790132643955756f0a844fae152c8f671041cfeb88b097f97fc6e3d10f501dd6fb15af459a9a53c82ec2fc5b8a0c52e65d5e7db8dbfdfd8ad8d0ff9eccbc3390722e0ad9c2ad5cdbbe58582937fe26f210094b2b1a57d6be81fe540f293ef351a7ddfcf238c22ba7fb10a75a32f60996ce8929d277e6b0f5b332c992f84af088f4970a72b34b50e66e7808ed8272660be5f28bd351bd280e7c7a539e566a2e4afdfef5c075c61399cad773998c2fd842ca1dfd165aee42fafd0ff243b1fdfadd44f148a22d001fb1f95736834aee75827ae1c03cff766543284bc97e42ede7191b1f2d70ea0ea2e39a663e9f1520f83ecadb7b3cac9da74d181b46c8489e5fc2050fec35f0a1613a703c5b35bb68a1acc6a66e9b0b616ecca4da3b4e5826ac0f2b5ecf2bba1d5f815c81bd80fd7ddfac03065665354049e6547b92aac5acb6e2cc1671d75f89b11c87f744542ffbb53ab12f62a5a75087b32ece4cdfdaaaab4144765d4554a2cd04dfea2fc71e0e2c9691fadb34b1772f38c6187f7083b994d9c729230f8248389afc0af2bbb5e41a86ec202357cd18b54a72124f98ed5b04735b30a40dc6738e4b906c09309efe7e4a8daa67f647a1e9c0ac0b454993fc4c182d27584b413db0c8457533bacd8b5f559644a4b8f5844e15f3cecedc3a96577bfde51a148b7b41b8f1003957116fc585cd65079dd9c6e94a7284e1ce0059f9bfe7f6a8ed144b2f02e517e95b69fbcf5ac5f04f007382af68d308b2954913c8dd16fabe717ac1ed3c2327a19466dba25c8cbfc58b144fb421e9b96636d2447329f456884baac3c9ad26ce7b47e0c8bede024cd2b6e7cf3808b298dd81cce120a3dd096efd97942b8c53f45329d88820bdfd2aea409877de600863b5ca7b717c64515597e13cfa879c29f3102c570e310fc5d50e2d19e4826cdf761de00c202624a8964efcd0cdcb940b52983e08c06dc4453cb1ae3c7e25e976fcb0ae5bc71641999ee05e68fa6edf2363e9f2007e19ba1d17c8512576be5c0f0d738eb9389907d8fa064ea7094ef1791d557a6a33c27dc6c9845b2d53b0726be642bfca8c144d14c660cba3f2cf6d6fed76f87300936b1fa6c9d27ef0afdb000fe0db33805ec554223439e4843419b0ee621549db52927356883dce27e199ffa510aa6300a8ec089640e89e8fc95e538a93e749cc1c509487f7670ebc6fa01ceaa56a774abe4c84307a2aba8ca63a2fd1a784f824091ad1142aacb550c274978d1e2caf08fcb8cd1d29beedadc9971f41c63a3ac50b5f2a6045ae9a0b5804a80e8050e00119b7dda341f5a387823f3093ff2e6f59307430bfbd657a777f8558adbd4cf13569e4cb2690cb5ac034e5c84b280596ce889304e51fed6acdd4312603ce58a19e9bfad6ac78ad28dd5e3f05c07c84be8fd35ac0703f31689fa05f41aa953ccc0646f10f2fcf288993151427810c04179eabd483bccbaca185d549061d33f16f9524e990b05a42b8b6b05bdcb0ee1ad86b8010dadba72d3858cba24fb985ce0f29e943da37ca19ebbedee6a30444593f33e2a80a76fed50753e38a0845e9b8c9a0221cfde19fa12e62212805f68fc875386ec8f4b36453dd36dd995945238977c9cf5fce9db853ceee74bbbd9278f9fdd66cbf8dfaaba3aa17be2c62796ace7ac01b624b9bff6a4deeb47e83138df81380d3ecb44e67b4553fa04e2baec000081b636adcfa74ba3b48e176445646c0692adb0737f54cae07fb1b2093db66e8117eccc18465853e7b9343f2959dda78b52b60886c24e5a850a4b888577be72dce44187ce851d8530c70c2a254cd4066e40a320c30934930599096a35e6adf45083c8d05d1964c714a4e0a70f74b37bffff3523ec248624075c9f0f497f2202a5f1203d9e510082b4ae5644cecd9b5b0f7b2328c528f7f9c9c6ecd3ee4a4d33251646d9334ceca672f4b0aab5ed3b8b5545f4d573e78672fdbbdcd7b9687a79b831566816dac926d4850ca6c46370a996556220bbf8c593b54d5e700fb12d0e5e948caf77729638f4bbc01430e2cbfd913e6f3c81109cc57b5ff873bff9ec8efde49f741c3a28fe50235cf70f3ff7532dd914b42ce47d6f2edd0fa087db4cb9cb6bdabc6076fc7edd6dfc82bc1c93a1af347dd0b862ab9f496c439a52bc709a9ed7d5f2020e4f893104db874695d12363b0fbf15b8479c404b6082c8b9a847e487fdd7c2489a8e7e2de3d8ff8901f415be0cdc778037040b54b4dbea87e602ca37597017903e9635cd05d8c73aa6e8e4639429f4eaf7e4a3488484e6923ed7f7bf0c2a0d22f367375369533f7b682d949c5eebffb3671f8943909a4972c5d277b41df50e4bcbe2eb4b9d120c3d9d97c0709447128bdcde27d466ebad2c223cbb573bc7c379bb8cfe5e63d2fac9fa66a79e0e4ff39309b5eacf3ee00468166dac214d42a270cd6ee0aec2ef0d2e02d727ef6f6f09b9181c32d137c336f2f3e02e4a93042593700447f3d12198f557d14830b1135b7bb1c1defc93b2e52a9598f4400e4ccfcaaae29b1d4089057e0816b017a644782f5995a73521671826ddf88bbbfce2e560515fe680a0a0137406916374d3dfe790b4b038cd78785b3137093fe2bef6b85e1f7ed59bc961ae3d522785840cb006ba2f621e93a5d2b0a555b2418ddb18715a9215dc934c63339d4fce03e29ce34b5bf127e77d670edf82820cdf11b8b8eb6494e9119bd14ea54f30475acdc05e1c333a9c9f102addcf0719aa3826fa29b2b42165a8525e8461f0fcf8b2dbece62a8277d12ad35aaf9f61b4b2c62b29aac2c1571890c3fe51ee2c6ba07e45a35494c7482c139ad39c33978ef0a3aad5c1c29aa21af2b51d800022e1faa6a3a23ab9bea8d7214c7e11a56600359145c543ff67860cf4fe2afcc4fddd00b22e953922ee7aca31bcfb14b2dbb40112e6e4f48333f688281724d5f7a81b95267235af01baf585c8ff47a1c1cb584b0552d9bdce678f5d0daa21d96f0c58632471478f9201a192fd6c8115adff0aeb0bf580ffe441845219fb17d4e74e0975531436042b197c39951accfe41f53bf886facc11835ad0fee805a4f2c0beecab3959f8f009b578921b259f2641db667fe9cae3d2534c8d7b4d6aa809dbb528a369d399b33581dd132589ce8820b88d757b84345f1462e28920fe5e121ad256264bd7cf7c0d21867bfa06183c699c052a6b33200de6aee9d4aa658b438396b223e72b36642bab0a81a27c1cfd6c21f906fa1e8e2bcd8fca19ad22321e16d9bc50a36813a034da97e11aa234729b0f0b3a56973f8de3cafebad798989df7340bb43ca80bf3dfaeb1f804103164cae3cda5424f0e7ed3bc90048168e6e9fa598ac7136ba9a0d796df09d0948701e38349c37cd6ad013b7a9115e7dbd258cdf16e466e43a5358382258ce05827feb3782cd6d7cc8185036e58b6572374f82ee4b45a3eb6aed7f9639076814db127d0987ea88bfb1cb6726ffc29bfcdcc1c8a6040286853cfd3bea981400d9e3f1171a8fa42b88268e69d221fbebb38a509530bfdc9e8b2756e77f67175e7d2714ecb1271909b53b9e3bbf9275508edafc7174a8e1949f787c22e95edf71ea57fb82b00084acd1c3c17cd453d6daddb0eddcd6d074e6e5351f9684d8221938719a1f6dfb56d39fc8bafa0e65342b1d53267efa804c163ecff663165304a8bfbaef6f98cf1b612c05c8a5f6061c8654e4d7775b20409f16a85e612a526e390353a4a648e1efa7b9ecbcebf9b3b4766333810697178294f9dbbba42a0d5da9b62f749f5f7b89510fa6bc0aaf19e8331af71555dc1540870b932fa933e489bf44a9a8950f222c43ce72b2ca3924d33b7b4d16c7392e0518dd1a415d1ff5007d0bf9ba721518c4127e75b853f557313ffb6e6945f8a151d308f770c93b435edddcc11d7026f8bb34330f3ad315c2cca147212b75f3087feee917771da624107c7f257a2810a1aff953776d9315a7aa810ae24bed864ade7e21948335b1249e1e04cbfcab73020cf0e44acbb700937c3a326538e85e8128f4acd58934f540824c7a1dac62d8504e9ce895bb5f0a0aa5b5bfc7e865e2ed9bfe36ebf3cd795936793a062c6bbc33b7fbee112d354d07c6b310a4a34b8c9344ae4efc543be6ae0c76bc17f94203dcb0bef321532ec6d588179e22e8349fd5747640c4332965dd3b630282493e1508c34bab6e091b261f8ff4e7f33f5e27ae5582cc2791a638fecfae71b2b6729f2b8d17e994d4a3790b9ff8bf5752efa78fdfc7ed90c914fd1721c75e758e2bfa13b126d6c14540565cd6ac2ca8a6866cefc62c08afd90d4d5ad39696aeca14041726aa96486ccbfa73370e80d7e7cf10ad69f534cf086b7044b99c630de6808407e02d14a6a2348d8f1bd8ea842722d9ddf818d12fdd7b6cd1aba7908d6ecfad492d326ce108ab719e31cad1c534419074b3e1159bb898ce93f536f895c627a4f9723909adbc9342b4f9b2de1ef710039872fe63c03cb8ae2be021a3d1a07ac5ac9ec376b979699aa6599af2b28b8306c03ad374d9a3033503eb9c7632bc77160f480922e48a1456447c35c002346c23ee61a2f0ea889f4b3ef8367617dfd8c01f801f0123b4e077104010edd4b4870962ad4b6bd8bed658c97e117fea20ce9d677388598b2c6002e163169611307e3ff196f922fdab7d711db00da2ce57eb857015ccd0e1a750e9acd582f82d2c651f11962f5b3144941d21317514b8506bd5cfc5112c51372d7c360abfb3373b0ed8a6ea5fa2e7df18ba62faf195adfd0f442f2bb83c76fae021728e4bf641d21c7704b5cf6df0d6201d579f17af43b7fadab34f7a8cfe79a9505000d78b5445c65614c12e32eb93238ad8d81335470ff185e40e2c9d3a2b19c00f9eb37be9a1b73502438a07ed8361c1a8063ae19f814a1956b5235fc209407645fecd4ba75437ddb7f1bd8b62ca395763a9d020775c361c19fc25330baeb88e9ae556944b9631b1573eece9f5205bf202173fdf836b17d446b84a3e6e0eab4d8959a7b994c052a2a75fc1d85828d9a8d6d610e257ce26d9d25382af99219a5db5d8110dcb5fd8d2fa84800e6aecda79617be575c6d7784a87f611aa0b67079367872c93a4c0cb1790fc0dd26ef967665c53ff9ae0b534ff762267fb83d14990134375818c895138c2ac93e217f4adf5be1ded817eb5ba4ac910fd51e27b12ccf93aa57307d5b934b9fb27e35123c83d8c85f33b16eaf5fb53cb65ab517db06ceb0ab142df47a268a19f9393a1fb882dfc0b4c959f22d4b0d2ebc884c21db684d401e02ba65fbb624815d5d43ffb4d0a33e80f2f46a6778cfb4228d87c8937e166b3a4231a99fdd0940bdd3fe8f89129b75a8b08bc6b786c972332ef06b9ea179da58d80a551fff109d5b5c119d811fceedf05f4fff939b0b0b9a6044925db829563e1b3c160986343098361d85196dfcf76b3b5ae61c990c3949f538298ebf8b3f0b750aaf39752a75e53c04f6925054f1f0555d61a59e6946248becd7ef13dc32f17316f3b3e721056c2ec67e135958c5374b2d82284eaa5083e4b753c9a6e72e61eedb664328277273e7d4e7f7eeec92b738ce65229f2ba3c5e1030ddf7a56295edac4bccfcb3173a4580db52575c5f2f17f52862522a8b9f0531c35272bb96ce2c2f0e814819f3a290a4749080eb85b1c6128f13778f72ca9616396c49ae95a1e6f003e6ab093dbd260474f0f2c75aeeaadfcd289868c27bafa18d82c289d512ed9ae813ada2008036cb590bbfe025aa180fc920e765fa0278115053852615dbf5f18c334a39404d1c05cc9ed709ea2160b30ad9c02f48091615817258b72140b493c1f5896709422a074e808a93c9d2eee1df41c78a84832bd53c97d790c97fa8dfe1ffcb7d9f259c88e9dd381ca2f9cbb629bd989a084b65edb988b892f7882a143420007d05b48233c052b8361e023ba416e2c60d2cf0c0ee2faa8f0a9b443a6ebbf3eaa554ea5d8ee7d1cd104cdb484ded704dda1bc8305d5e8a8678443a03bbf7aca87c5008726e253f4c3722cce1526bfb6fe6cffe25fac7dbf019b80675bee5d24c29d44c42214a4e0bccadaf5151f1293d7b631600da47c71c14017d2dbbaab0eed87512a0351abe277902fa844d2942c92e77f8d2f35b0515efa20e26cdb8b382c623cc8f6a2478739ecc71aba50a1dc815b321bf7a0344853399d087072dce364936f8954123bcbd8801098b60d011a14cc1c8992f29872fd2ad39b5f2a2792d345d7972a171d8c7e443a9e4fbb8e65f0fba822998439365f9c36ef75a6b354453ccf3c4e5f8fd29f916548f873248540cadb458f7532f6f33de88fbc842e8ae6f455c020ce81ec26549080b24564d2cd49c8a3250241448e4724860805b2f960abed4693645f33ab41eb84e690fd7a8dbf1a736acee9a6a0b36e90fd842bd726fc275f70d415f795dd9361ab83b0742593cc90133162d19b90c0da5810c5a71c1fad4272dd8f523a5ae65193d3046289d40ae3b2fa29165bc37bdd68fd1d31d563dad2795e10be39362e00368ee45bef2901869fdd2cb2ffe903f3c88526e41c276bc957db5715d74eeb6b052e963ff0802d8e013c9fa2adb71a09a4ddf6de2eb931de8081b68be5742e913ba81e4673c20a0e57e1529909e068b5a07f2da18a076c8e6f3d2cecc9dc255d58892cabeacbb3c251c942e6c5dab167b9cb8b2abace67a3542327508bb279cb0692e4d8d4e36712c97e6a9b69875b90b8fa3c1afe91b37794111fbba5811fa0e8f75559f907cbf27f8199d4f3cc8ece1f2f43342e452937c28dc6d59ee80b5a35b18210f193b1ecd8690a58c0a1e23dfda404e02e05825c8cbf711ecb2ae100f17f676098d71b1db5ca361b22331c5f94f6fe0db700090ead3ccd06f0a87576ca4c5721faeec41fc050b876630f00482d2ba6cf386f8d85f34e003265b7b96edf7bc82b914e9d7d3758d49d671609e2165d4c543d26eb4429e4216d4ae68242d106ca1a6e363db63826b0f2f3be8f68d2cbb35d33d6adcdf7486b21fcbd800256eb385adeabca021bb3bb9aee811a7754f538b6ba21a5e781671781c5cc3b24654069b6c2759aedea848e07caedf988e05987483fe2c5ac7b937d172ba7c78fc70a7e48b45e467d5d770f86eb3ccfe579349e53968655689d85431ea8d173ed5c85bd4f5c6f45d58c430ed0f33902d9a24afc670e38a6a58f3dd231018e20f9b1471863930f7251396a02f8d5d06e78826b7746c4dd206aa98466494189a48920e62166eb156490d9a0265b3104284a8e42b53f0988a2bc73af09bc3241cff9cd5489d3762d68c9847330d30593a2f19989c2af7d74b0fdc028b6f0a3470f1f388f840671a246911b9ab3cbc760a199c33b2d629c09320add6c32ddb44ad3d04010d3dd0699f234b95ec2368b19463c6ac6cf8ff7791f08ce667d53d100232f1cf24bb0cd21ab9c17b7e269ea709ecb851a577a529af36182602fa275393f7a31071a0320d94e01878a4cac28799a5acdfc45bbabdec54be21df64c18ac42d93d02fc9b397a87ba18110d557a6c9ed9f8f99ba67dc6c71dbac7169c93233573bc20304a0161b9ccbf919b73dbaf036e" + }, + "transport": { + "secp256k1Address": "0xc3314fd768bb68b986e80c0a14175f6f72630d7a" + }, + "ecdsa": { + "addr": "0xc3314fd768bb68b986e80c0a14175f6f72630d7a", + "claim": "0xebe2e0e952bef72ebfdf804cd6f780cb7529abf13d8fd7245246235c4cfb586e596ce84467c25d46aff89a17842a3d2fb9c9a8b246e2bc984c364bbd10e2044200" + } + }, + "5": { + "id": "0xd22e71400eee01f4f70eccd3e20f838a4649d11c", + "keys": { + "falcon-512": "0x09a2b859c229911277f188666a63981fc25ea2b38df500cc8851ccee2f467d0fb1f8aaf84f9e757b7b5db61479c1a6a196677ff6d46779ef8d910a78604f04d8591c5de80ad1c32422ccbb3bc71914cd159001a2c78a9a00480fda69321a6ef54104bd0d1a1b8764d537b5909c107dde111786d5c6b943f52a06bebae81ed7168066aa0723ed5de103d0880994341828d3bbc78546b5e602cd842baeb162c8c099bf1112bff3f3ccaea4cec0ab5b4cc276a81351cc692d463cb6e1c4573036f1d07adad56f0210ee755c474614cd7ac618afa673197716ce24cb041225e4c72062873c8da49d13d11b70e05a71a35b384a90e95290735d9cf1ba9d0eb0abc5aabb728ad13d6cfa3ac2819411684629ff07db9306d6f5c52ac680ba31a2e1e41b1cf0f1b6d190ed3ad00470cbaeff956e7da446016360b515d2da9dad49f26a274957e45a6948843b0ea49c7995403667885a86f6f116e52eb7701615b75dc75801f5a5855c5e1b262746ed991aaeca6f3b9b59ab0406baa1e74a33617dfb6b54afb796c1d2299be9aa68b9bbd71c212f23909466471f8b04a5801408929474ce5304cd87801d01e1e8ff1d2b0842f727bfc3611138a3431e12867bcc000147238d659c7e241703444c26eaa6a161883a91e4e0afdaf39cc57d38615fccb1edf56a2adf1e401df1d5100467ac261772d695f29be1b3113a2a6f8e48f1b47380b97651a852b2c5da942a3ce92d17db15a669a4eaad2f116a25c4beaf1f9d72bfe1d665411c28041761d0960f5d3995e86fa15906195b2a1d163dae8e750b1a5c06b5fb32092b0ea47501da5e6d9a5941d82b5704299ff56e49299ec82c62fee9828ae56bdd2a90eadcdb94fcf2963d02349909dcf27e02224120d6b66747dbafec302bbc6b166e5eb3692b55a35495b15af063bb746d8c99c5c81719d42efb8d851537f875f6deab96b5860f26d6d0b036aa62d8f744692f256093f61f9e2e669f87feda1b60ded5d0574c521860665472ea9d44b1ba317d12e7b5480aa449c6d55f70d7a4341c22560a037b30df071f36573793efd2b098a6138cd74265e0493b71a228463c00a0260e0cbddc7905795261980edafbd3d30a0102ed9bd9e99630116341ef583f387e9ec5f9a6ba035e33d6b6c96faa9e27f6420a952496b540badfed26ceead61d590a5eba9f329ca9a5a0d562f4d0137f643128e6ee270e175c0ee0f5e68c03cc05338f2dc481723857fdc42d9134b908ae43367fb2601355a326", + "slh-dsa-sha2-128s": "0xe4e78e33faf1538665753136783ce1cfcd7ac20d29473b7079905d2859bccf4e" + }, + "pop": { + "falcon-512": "0x392e924c4422da36f1d9e1e21bdc6522db64d85a6c182ac623e5e3dde35b28cb3f631834850137b1521ca84d5887aa99c3e743395fbc899e4ef2f606ae5ce4f4e5a832f742c414e8b335bbadc5e138062fb10345f32cf55e1f88b00c3e8a97815c686dab2445993b1e7c8a5a19da9ec5df378b633b2e441c1477ccf1ecdfd8752d5d9a432c49fcd368f2509738ac1e148330c8b528e7a53adf745ccb8abc3eec49c86bed6b3adbdc6714e2d2b5bf371bc8231f73bcf8685014fa158a42253b480115c9a35af975be389f12043681b4813831073af5b5c739b8546255e54b11eac34fc1d1def879d398c65f23ddc99456e92e72677d7621bad74f8b6a994d8edd608a9e38f74260ce63d8cb349b9d9e8bad5ef8e9608c5b7c5bf2bc3c29dde1b37abe4e9db8d83ea4cef1059f36ac7993e4d1162be21171597e2d3e0e7f4284e0494a6b18bd24bfff5b6bd9a5e3760492bfb8cfe16918f9d376be4690d7bd82b6bb7ac218dd67909ff58b689d682c8450f3dfe715d6123e5eb49b98639bc2642fc9f2b7012112866dfbb015c330c9c27210852ba5339b63e8f3437455d8f5cd669e6d93d9770d90e83790e7db91c785585c3abdf203faeb08a3c68c3c5f0f0441f690aeec211da35e6c79853c9270d1e3531592e3eab4d482473a9de7e52a2422295a16795c7693949566335528b414a7cd5346b080a4a9bb2e67eced630eb5ed58599d215394117fa629e8c83a493ee56b8049266be0ffbdbd341753369379e5ede35fb77b52a60dcdc14d58322ed6922e9520ed6569692529d921746aeee5885e0d29e8f4c60df19e877ccd09f2cab4c97cc916e430ec719af270cab33113ed515dd343ae924eb2c44563d4e77e5f7d0cce531c4de60897f52259ed131961a4a05e6f5d143fcc8729d4c8a4", + "slh-dsa-sha2-128s": "0x73fe0043951e6d6e0212acaad1417c695048becc40d26ad122ef8459a736f43712b8aaf8191b08d473ba97560c9a31b48dcefe71796547d315a260508d97ee6e61cb3aaf8a6bdec576eeae3d7bfa58d68920bdb692fdcada379f512e05c250a5c5933619488cd2776a9b9c74690f442163637012b6f755da1893304fc5a90bca4afe4b525da381065a019e34b510b12348c498c2d5c50a04a269611159c6ce935f5f5adf3030b591e889a9cb51a05b58e225905a7e3d56b0ebf251a0c72d6a1cab744a667d4792f9065933953aaa6b68425b76fe78826d71cc4b37b7546e6e8fa31ec3fb4ee843ecb1df8e25b09a12fecec966fd28f6ee796d3b02aebb0714ab919eee22301cfa159abf246cbd154a35e70684f775c67c87fab5501904067acf6f19013db92bdcff82248c42e20c265b8b000ef74abb6b3d43563f182b7b8d7d7c1796074255d9b52c554fa6beae184501fdcb3cc92e633fedf567314482ab4425dd572812e12c4f7ef5883a055fb286bb8c71fca4c8e953e712e12e3ecfef5d5c78f12fa65c28843434870f64263a37f6083cfa6b8aeee3aff9e798dc0120343a22e772536e031cd85a5bdd82f43498a42fd023c89b5294a57c6901d98612df91ded7bbe26b4dcbed40577df045941629f9b9ebaef307f7efd76e676d4eaa8c6375b31a156fc2dd3d6039ca450f8ee67a51ea2fef44c4341c5069a205d770785a0533895eb8a35184e41ee994296de545b426cb978ba4e3c281d4a2dab868bca1a33ad26e4e659b65835b92bd3a384ca97f7d47e81d81511c5c02db3c25d4c0369690797cebb2f5e511b8253a7f3dbd819d2c3364f7782332f9e79f0737d1f29d3a653d71fb32e54eb58af9bb5b83f4073640eacbef51e8818163f74a243a36e4bc2e4d65a7fccd37e7defea299de9467b0527d870424730a99bc7a5a1c8d2638f31000ad4d38ed45619c1a76b093f594d0025cb088b7f9822d0ca8bb74a65cfc126860f74b43aae952fec6a6ac9f4acc42af4e86d7926b8cf6b3f8215b19ea93365f5c81ffae1e415d055362368d283f64c67bb922ded029cf33baa9fc7dd1e9e59409c80548de5ea3eb091737ac980be71cde3fb03079ecefe2a5f63d2f67394c40d3ee37fc835ea0c509fc33ef5b8912625070ffe4ff8de4b9e29a7a4a4001336632b3c3a155c6a91e2ba0fe37a0155d61fb708df7cdf98b5ce8b73f8e480eef030c0db714fe6b600a3cf96a6f7030afbeaf0aa7bbc623a7bfc70e8f8b5d030ab0fdf714362f427fab37bd8b767645a33324d5a6520787609e0b5407551768369f3564404b76fe1aa4f4d81276014d81e9d1215a798d08d48ac1035ed9cfb5f5efacfc790fdf52ec5144cf17960284f833d6a36f112833b0eeb8efd8a93620386450e54acf7eff2ce795aca078c47b0230163b2cb4afed87e142ab192852baf3d8abac4d1b2c1c02840c60b746d22a0e4e54bb498a4283097b3ae34b49ec0cdbe09b8d38b9cdad25621e9124b8ba2a9d40908e026c05599df4f6bb4ce219c2b5f8e6e444029884c219a3cc53f183e599ba1ae8ce2cb000475757aa277bb2231812cd9bfea05bb76a6e8e84f47f1c535c37c93d3907e18f5a7516fe519ec65f9561a2e476be97b8848d66a767a710c2554e942bffd30f955b850b1c6dbb192a37966d96d113b6022022414fe3fc60fd8200ddc936e24b5a20d857c445b10c9307bb1e24eb5fe214c7954f3f957529c7e7608ed38e53193bee107b290daabb1866d1bb1f8c6658d3370ba3246d4d6ca3187bd1e9f4fec4ebfbf8a6af87cf93bb706331e3698f94728bda497f34dd80f33cc1775aef901e055db873e2ee69c26ba909bd3e80edae7d4771e27fdb8320e21fd09c21f618e421a65d414f542a1f6305e6749109237f585a3fcbde3942d62b3dc143dd11721aa0d2b2cf5585e566e36d3de69caadb8bbc271b7da2a17073ef1fa7fc0abc8e24b7ae4643cf4b3dd35886db362ac674c405549f2462b9835607f441783c911441b5421997f66deffb5e1fee2fb27f38d852531d6fcca1f64f62e3d87f4c352440f76c197ede99a5fe8d6b6d5a75b21ea6c6a3de7df17b58e937c38bd727a0ff3f8245173be5db6744d6cee201424adc528a9b1e2f65527d5db16481586f6a9144557c4290f1246ec65a92da7da2fc49813df417cddf30cafdeaf2bcc447bb661903b81991e9f74d86fc95a9f64205d398c3b7abba6805c8236ae65e4e35b1cbfa6e0ca0191c77b47fb5d95da5301b7cbc9260d3d0b297d7878dbb1fd7dab4a8556b75cff9e2f4375cf8e41607d3022bdc0d89c952c2f31ede13d55f97b2720bd0302c4b313f7d1afce4ed4e0f330f64c6ccf75d84aa9e34e8c1e419b73d3c321794bb96a79799a6808bd1dfeca1bb58d3dd8f57f6ec3cf82aa97699d95289fbdaba9b0e51407b61c361156519d1866ed730c01faa3cc4a74f1e903afa1ec39709a98c5c38974f82b677816be214a49f540fbe87ab6928633b55a30c93f76860206513fddd5abc46ed4e58e0a024cb68bdd185b85d763890b2d851338788c735bca3ecff3b3ff4d0650165b81de79eae2fe3ab1ef658aa213adeccc4900f4c4f091a45b60ac30029fe079bdeaad418d6b6b27372d0d3f34403209b3f60af0f0915299081b937376d4beaf704f8f7540ccf79d794c67ae4bced5ecb0bb8884499fce3d6317b9532c01960264cb7008974113fec1c76d1e030da5e8286ef7946e7228e3f081b3be1a7531eeefe89a6edf152ea570b95e2205a11b845da10e5013dfff9578720178afb61f26e4e2ec329b131ac89a5c97c8ca40f1534b4b8c7e1fd0c3094b370bc3a006a13ff6a2db643beff592b2d4f8d9c7893c858641193c62a30b9695a576b9c179d4b68e2c73e5838db7f002e80dd06fc20a633f42658687bf53c68c0ef4dd79113584701612360bc6f48841992e3ff8a2c8d04d9c30fd232854cdeac685bd836ee5061b5d273fe4f317ec459fc81a572071603c5026285604bd0a06be6b241baead525db39148cee18fd01a1bc43ec6f8fa15dec90cdef8f9ba54a9f886889ed2a1a4f2d186888ca9ae0c069611f8205bca837ab70262866dd26d61adc6741aa420ed131662e262ac8eee77bd8f31428efdccefcfd73e66c216cb9ebef23dcc5affb9ab753a0284acdd98bee824ddf7a458487f30c1784be887f29feb3d3424ba7ab368c68fab8eadeac7d783cae9d1ce79e00cfbbc687db0881b151190eb05aa6e8e7fc7b079d942c99d2f38f9603ba7ea25e7147f4626203f8bec474bd1231f5f78f8568c0a371dc29bb6ab3aacebc6fc665cad763404fa501ab26d143a230582b4daba63ac5fc7e365953d31354ed8717d09371be465bff0571954258a204e522c043167e42e1436948116fff0beddfa79d56aba0fb9c43c0ec1a69f31a71c0221b18924d903eed56983b8f3fd17ee1162868952037fb3efdc1ddcfae82c1f9f67bdcdb7bd95a3aba50744fec21cfa0f03627f48890eb1dd93c60fec19d57155f90a33cf07cf56ed2f6ffbb3c04d24bdbb3c064615c4d70685a6be67a4e77328e943aab4b3fcf7b88c1da69f16cf089ce4d15b40345a8b652800d3ab020bcf4f4fc14e6fdccdcadcd9f4049ff31e9315f62b194c9ef4d97052da542be7dfd1e6e5dd847e367eb328c15d2683232a23cf8ac19695ba03c77fb35066fc43b100972cf1ce924c0c169a78a96b309bd6cbd869310949ebf66f1192df10efbeed7e39da938f857a9d63a8a6e5a623992059056f8459f5a2012f96fb1ee0b07ab7cda49a900b999af28d863ad0a01962dc211573ea4f8c799693b5a79fd346f01fc56411c9c750925c06fc82ebe98266f8b70cc5cc74cdb46fd95137ce8f343ac870ec3e903852cebef3565f2b6fe2d5b6b8cd0b155b6337d5d34646ba99ccb0455597a7c42e98ed4d2728af2925f755af2b7d3647680a398d8f07c6a6bce3c6221d6cc2eef63657f6ff50283c5bcd2aabf9c6ddb08fb2f9789e076a352d5d0b07168b594160de98583430c85b04f8ca5b351f2ce88d2c6187cafee6d6f34c166633df3e66862c9cfb9679de95e4ef3cd792e8a856e869fc56f3395babcd82da617a5fb93fd69b62c4d3f1b1e3767d12c9c812038e3a2e5ae2b7d16bb6026f145856ceb25f54d0263f2d489bb6a66f43b58c0aa02dd02a3d27c1aa9dd5270f3f43bc2579e7b90e3ced107d58b63fd7f94cd53dbffff1815937bb96dc579ae474f0333e14f44941257bf732d79d2f403c5ec8041f18f4ef9501e33aef34356c8bd79eab0eb0548f569608ef284a5d4c743a93b99d14e2b4d8706848cc42b104f4d80ab12dd19c31905ac683cff9ee43a0d9697466f20342a8dd5333645796b1c1e79a6a79e59889fce73f5f36d0f0739f6939e7f59c6e323028132938670f7c4bbe959ae0666a998ab4dda530b5f10e9f2df82b8f47b9040048cc7a49e38043048c71e300f8bbd96ee960dede725ce2b8cc76e26d5b01c6a1ffc564c3df7beb5461d58ccbf91e63d41e0be515bd017410bb2e2434c5ae93aa1235df3e9ac147165c0bfa1b488169a645aaa0352be88eaf93aa284b3abe9236943b306f9c8ec77c3f7e7187eab1b83ecaa59b2fba56dbb76a3bf983d8f62ba354d4fe9e95ff1865264fc2dba8558e40871eab4eaec904259628ff69840c0772bb606e58ef13db9a2298fa569994deac7ba72ede9d7f712c695cfa1dd1938ee0c69f62d4f6c0205de7b09fdc49441f65e7424c588ab4281d01eded16a1373f0da57c1c969166ed8c94e1b1d37df03451d96b6e313a9796d92fface0d3ad1c6c06395712d7a6959936f2f26d3df44a150f7fb0c293a008a635c1a93fea128af87f794dc12e3e3620a6cc3ada09408be2820d005ccbe3911bf35db6920de599a443b018fd36f0071354dd55a4983079d502f31840762f89e8005051669f49edfa12440484c77fdcdae314dfe7985ac9b38956d30de37f094c8601d947ec14eb5c096a248696622d3b6b854757a95e2d3321cfc35f48e62e8cf7af55a2f5de28b2b12041f5a977216a0cdd4fcfd9fc97a3396ab1f6fe87d52ca7835cf05c5d1214776d1f798d62b35f14df4580356e4079f2b160be36aa0ae7d2aa7d30a18a3787f91f4331a5ee1fc4adacf1954104283e8e3cbdc80f183c5d5d877e872970791cb41d8091c0b123244f7caa36529355d8b89463c582ef8c3c11fbd66fffc3a63f5e0e160bcc17c012d8b9404446d8ba041b8dbc14084ad4cdb89d34638d658c3d61d2bf4f8a6da87a53ffbe978c9ce9a83b3673e3fc057b2716a8fb1c24db34c641fbcc744428a4c1dfa8915e5fdf362e8aec396aa09b8b8a6657387ad19967035cc52677dc1f97dc227f183d9e943171eb326695691976f5aa12a9b6eb5d458d1f2720a05aef68cea2ca53ce8a1f4dab8bb4a0993c3ce6acd69ac97752d06457747bb6852b2bbcb8582aec9d3cc41e1e5406a6f7f5c535f1b75f1747be621c110d1df943693aff1f379b1a55623973fa8729de3f19b3cdc4d238c173b362e4a7def83efe3ec8e8c2169ff2e87d06da9fb7ae953aa826718cf7ad49f857679078ac23e1f19918b3f2a548350ad1b3f1d6c107dc5a2ed0dc707d8d592f50d497eacabbca6d23d5420b3a316007bc64277b8aeeea3c7b425d6bac94dd5fa7d529c8a8ee172180c2788a7d71c06e31cae56a61460622b935c3a8c0061fb20cc276c6e3a54ecb26d8a92b2daa453dc7f7115efefd0089221ec5f29f5eade622abe38dc633e95e26a9cb973b9fab8cc235ad8760e5e4913c09b46f50b93d88da56ac08abcd2f7ad82570682921738be531c8e1628ce1d263fb717ba92092630c0f4b76339300e5316b8244633cc44edaa5cece3fddef8e387331d404e4a366e4b0b4005ad6fa586ea64945db9cc566849feaa1e76a2f0262c19e38710b416531af44ab69af04f83ceff76865186e722ef331dd05d1c015e0161e15548ae31af28b9c5fdce3ffea1bd94f32475189f19b249ce0bd500bb49d0d367bd427e86fc414ca1d857b96812f55b1a837005a2f755f1ea283b7cd51e1aa608b39bbeaf15dfaf306e83a04e25b31f80eef1026dca1928c17680dffebcb8af1dd347edab1dd07bb495812ecd96a86f95dcec1aba9ad3432f93ad1cab7aabab90ffa3e88ebe712a1241f5b5b8538f179e03ad652f83f0f6a20630cf1c09e27160b87e0ecee99463d51728c9a29e30ef2475f5dce143624ba338f68cce3d382f38a13ec4091ad86615fd0fdd0f1e44b00f1d08de9357ec68f852a22aa07bd7f72786a8010aefc9441437d583a7dfc302c90a22126d57ddbb2766d90db42c83560400f5f2af16906792cefbc819110f6526b5c88101abe5027afead4802c09fb06406101f7c1a4b219b68d5c168d64bed501dbfb65e05caecddc7e06c683716721ef540b39b82ce108cabcb152156e51d4700ff3955fb12c34ff323e2527bf1579d091d6073e4403a94fab38ac0369c70ad183351b1847fa4f827e9282545ffdabb42fff134a99b50f1173392b6e4fcc26c4bf81e228e38855b5bda1480310f567071fc2c1f5d27ed278bb702bc9f674856522ff58a1261eb11e78ff5b1c002b6bee40aa408fe688a72bf3bb91d2d3a8739341f20457d42d2974a3ae4bab0fb5c7f52d953e286b8f3dca4c5551f0862b969ffb105d50d3e11521f4d4591429b25fe2db9eab3669ac5957f7846ae386c6f2bab58eb89cde672bd30ceabf4a8986bc99acc35d5f47fde1ffc816d3efa84607612c10495ce16cfa24bb94acb15a01b44985e1f3a99b17280d74fcfbcb0a2ffcb1a1506ee487f72ade2cb7d8d72695aa26c511d9e5d0354b2491012e35b22b426385d7926a21ba6ddd10d3aa3e63b330156b14f563107912145fd8489a8b7f30ab8903b9f1b30524647173ca97bcf7ec59637ed2627da3232c1401b33f85e3fb2d30175e245529a4299eda08b181ea3a3ed87a5c56a16e2bfdf6929808269cea021fac4f09104809a9c2c3a82b1204dd5ed2492506f3d71509d540c76f0693db27e821791f5670f2623e7436307c0c9399fcb06201540c27987ca62eb93eebe8722ffb9cba39cff5364c7165d4b4c59a094a3e6063c6eec73a32dc1a73da897476bbb808b4af63aafe01a2d2b14f4ff21bb81f8a5fee62454fd0c35142a50a4a602b3aa8e2de2ba49953bfc519eeefb9212a8cc354fd3c3768a52b452b26956ba1a1a0ec6fce8e08679472765bc075cdb234080b9be7abe47d3675b2174e131b405e70c26d147ef351734ced10b92a597c41622536708abf6eb1b98a6bab09c51b9fc04de45985149d8a2fe7d19e457ec421ccd0d80c54272b1205c2b7cef288e0d8e91886694bd49a48144b18868b2ef2a285f7d79dc17e0fa9995342507459d7c60297d9862cfe52a8e9d7fdcb99efc09b2775fc2f58aa5114480eae1576526757f96747c80f6d6a842df4003ea12a56e3debeb3d66746e834466dedd21c0679594ad338804ab317740f997923fcf0ba45b0924c72c6580712599868261169528204e0fba6c9b19abd9623ace1e1f5dbeae2d0e08ae4cd654960406560a6321cf190244affb6695206e022f91006c9608566c8df885682a5a97789278914a3a24036d40541eb4d2abdd45ebf1c7d652e44a05715a225c7b4d001c23cd605ab32d89e3f4e0586a4042af9a80f48576f0d98afed8247bff6201d44f4f6a6a341f97049c17949341de1a1dffc4401545b0ba478d820ebd084c90e77739597c8689835fe814b17f5fe26962d666ff1a8e940abcc2058f74a43eae511c0128646ba3d6184b743fbec5b9fa3f44898900900e943f980a3898d7ec03bd139fb508786707b757a0dcac640dd17777f6fcce9ac1aec4ad49eb2ed3380f4b79a36a777ac1c9a0af7dc93a65fda17f0309aa278503d7cd08a66f8aac0d829921285af0508dcf6651d0f3e41c1fcd6ec40c25935b7c654c09fd89d9ac7fa892b3e0910c858d77f933defc153344e01673bd5d15a802500702cc6e3de8ded484d17b1f1263a0644ff2833dc743831366c4ea1e876f39067514f459e0d2deb7258d809205496f53b9df968488aa5009aec984fff13afa1306e7adfd5ccb81cf94631ff61126be2855b3dc37712183035be5bb442343fb3e48b711a58973da8acfde5aa191532b9ecd7f6d543a05861e414bef07b8816c9d0d3861b1bf0c884d47c2f165f8eeedb781d32c178745bc6956a6e76f79e30c38eb18e91d94d304d5a29a4948971bdbb0c4f63e02d42214994b9837b53305218e5b2bd48daa402360f3bb8ae228975ad29f012a8b52492c4fd26344670410d332ab1d492bf3c2585caddecbd11a4666a3c7266c1596a0935b6eb666f97c0ea4ee536edbe03212a2bf669aeed2d7516c52c8f2533143663ad8eae302ae4be85ff05c090d1ca345150e5403a2305034b4b16e2312dc3f9ed7572b65359e45eebc31eb3dd4ee5cb0554d3607cd4f4bad3b8b30bd4b1ff8d01d7b7427ad80afa2a2fca4992fd8e1a99e218b271d3311bf0a51fb865e375fe1f235efcce51fe03ecc2525196429655421c723e06252d257b51b3a4fe91a222b0e2a9942658bc6804e86d24641a8c82bec52bd53a9ef384fdda37321be18bb018c29a70bbae11765911f1d7dc41d3063dc2c7b3873ff753d44cc6fc91b90a4eb649e50ee3f5a301c95ce41db9a52a7d51dc2a4099adba57704c50e3f7ab266ed3e1c5909b62a276d0e8d5399a8bca72dab6c6f99867938e3941f2ae8d1d8b761383cc720155b8d53ca77c2edd5aea3a05a371f445a283862ff58208c624df379331e607350ab5c15478b7460b4a1adcaf5a963e7c7a8e41c9829fd79f6b9f30793f8f89f75b937a70c4caf427b9a7ed65eb198ee44e9ff30e43844627f12f5070031b79b4d27a50e57c2d09a7c82417a67b36a547384d4d84dc9f3d88713dca12fb9eb3bf5ae8b66a5bfad684bbf458cead9b9ee810b0c4e095f7a8b489c2c2a7b2c40feb947b8d66affc280d528cf5e0258371b6ced9736834bd89c5dbb3e99d70af68f6977ef69cf5dfc5176e70e6cf5b9de5f23fe3d204edd161d37832bb5afd5503edf2ee69694075419f855681f2dd8683c8cbffc47206e5546a573b034f356db919e71c3a55aa61819104193864defa725fe52560a2d1c99b61156e84862e282d347c88d737173736e8a294be990f70323fa7bba05bbbd8e74f95cb3c049916de8293bc8be4fbc9d04dee08f5dffd2f172f88350252b0c4427c9f9a413dfb4d062c83452517f4946d734a72cf8bee8718c7b18919de035045b14be9486bf0f215c3cb6efb7387f57baaa122852b3deb2213842221bcffe773a384c551a13a6afe0cf6e4e71da08c36ee49046b4d89075a60e16ff7823c588e342f7159e301df149be11487669685905aaa58a0665998f271255ed8f2c5b9380e268b6f44c30a7d85eb9698f3e240dc384edc993ae1b9b951d0b20a3b56d4091cec3ebdb8eb1304c501c9e5203871f4643ae1f5709fefb054f76e7eba0dbc7a98a8c0daa5f7b2f9f65f03ea8bb52509faa42a5b1b287085812b12fa6ee895eac31e9806b4507ba36f96d93429b39ea0779c6ec5d07572622a8005268bf3af183432663be3969bf21022956cbe2c2a705cb5c10fb18ca5142302dd33a9971304a4bea108d3e77aac6740f44466ef3e161a944b9faf083b8605bf55a64d5d291e3598d227e4b9f4d5e6cd16c62e1953335f03fb01f765da00143371503c86abc92e20f55cd6c76d09bab9611c431c5b99f7788b107e1c48070f179403d43670b9d9c2c716097aed89ba36b6b05ca5a6ef4f52f9986cbd415be0ae4ebb625542f3f6b5c57dedb3a9ff0ed30052c559ad2631b66d92eb63a13915d9ae6d365796bc4c9aaac2c049a06d21c77b8ec9e531b0458ce7aff500fa48c7c966f93ca0587e65b7888a52af6c8e60d20d0444e089264643ee9b4c0f40ef41afd3812c111a1ab329a5ce27596a0ee15f480b7af82dfba2d8cd624128132c511704bcb62553de7ca6921cb979dc67e5043710775be3e18675b811615a47171d517a1039d231164c8eb2086568cacb73536753a837a0d833509631b5455b3e15b1af48246242e05a4a37e79d8ead717f12beb6e7efd2d842578c92685070a018aef9d526fdce8d556c24e429ffa4fee06361eb8437708e7c7867ac725cbbd96413c1a14555aaed0e7ccd4e2bf31724d4b49d4857342a18a695d2e8de8ba18d6e29f0e1f40b39fddc7363e729303a74b9dcee275ba19585192f81702c34923d354664ab216fe0b00f25440d1ca84ec6bafeaecb9cd5cd0bdd0e1446dd72b4028ac1764a8a6279ee77a645cd1aaf1ca516f721dc00989f7991266601a47cbfb80277e42d5a5259c5aec7a2f8fdde5209f7a9ddaefc541ab608b96237fa3382d32c13101f94a2cf4450f37edcfa2c1eed87b277bb37244ae5b4882e088d201a85ee1b171a0c93c51d8312da37f0b7d4424196c89f8a20d16e64d53f18aa52bc7803f319dc645f88de3947e80d614ca17e510666e14cfb619030e3559c710b3301203e8fbd649273f83b8039d65c859e0240021d6a8b56e6d950274ed733b138b5030d9f0c9173c7bd54c564f1622e4c475d1e9a2bdd3abcd2b17daf4d13f2b7611431b0c4f894b8451170964aa12aa59985f96ebec7298b51685ea563587f44bd910da6e6e6a1265c576e08f3d072c64586bb5da10e0da2d9bc735ecde44734def00442a976f04e2307f03e2cf704527fcf4c972398ba53b968ef395c07dbb99bb10411ebb5cbba03b131b9d2df037c51d79a4e832bd23ea4566f8c64236b7ac705c6007fa1b086736e4583bb257fe22983b0d71edef26cc883393066a6d8c346489b3f8cabb1a150e1b373ed10a342517aaf11c580f077efdf96f4fa5e3fd31a5d59fb74ea720714ba5f905c86000e25be17ac8bbd5e67265d111d4f1de46bcdaf15e12d9ca9fa1bcc2961f54aecef9117bd6bbfda62eef37294f3d8e121be51925370b06406c194e8e5e4f8ab80b516f143d6fa266609b84ea4d18c02f7db6317d0467ad7b841c679c80ffe6cadcedc9fb975d58e86e1ca29" + }, + "transport": { + "secp256k1Address": "0xe13aa491abbc1252dd714e7ca0e55717a2143eaf" + }, + "ecdsa": { + "addr": "0xe13aa491abbc1252dd714e7ca0e55717a2143eaf", + "claim": "0x199295bdf6268b50c86f581f585c60153ebf7266a666b5db7da2dc79b03a82393f983efecd6809208e1cd7b05cefaeb2b2979f1328caa86b136333c40f214c1b00" + } + }, + "6": { + "id": "0xd55ec6319fb9ccb57900799f771106752c425001", + "keys": { + "falcon-512": "0x09ae79ca93fae11c333ca673090a4b548553614bc1ce7f6aa2773e17b972caf48a07efb416581422605f12400494db84accd432c148168db7794ecff419e83d4738d98f6b0de8f0d742902359aed104a1582cb8ef976965502c28bf4466efdd9ae0350021542a563c9ad2c22b7b0da1f5cb832c5a54d58284ed0f172091dee7be8f94bbae38a4ec0a7c1dca67ca50de962ca09ecae9a66d227841b2c66cb8600a1f01fe2d48be3c64999d1f8236762983a80c3a58fedaa0bd09e3912223b4415cde3fe63d70a62acb564cae57b3ab760780ff26c422d6675920eac389b91659aa3738a5055a76a9046f443ca1c101da8fcca37fe0be18fc9c6851706367cb65f035615d3150acbb738c66eb6eacd7b9a1b03b06e4f046f8615754d85e69d262d8674e8e82052bdbf753591474488488c714a066592718dbfe08d0b91bf387d2b9ee6a86bd0bdf96082fa523e5b6851c27723b99af0aa0722b185d52440c9c82a2a61d6729ec27999f9019f071e9852e813c0ab9318e2cc791a6e7203c27ad48a68ed1385319985aace0112e17999c80662b12a135b5e1a2c9067d5e06d0b33f5a691b65e2181b8b7f389a364543a058268a97c20928b490ceffe1520fa52d143a495941996b527712beecb17786f982425a8ea6cea000f191226855eca65f069782bd777baf11ac781a5b77492e2b69c039903c991259b92a93d18fe6ac74e064370f3dbbbc5ad82b478648ccff8ab45d133b1853a1d21d2e7d525027b2d9740bc82fa16201fb16318da37ec6494c9ddd1af864ef8b50b266f1227134a99c40d8571879b8a660964f6217ca41c6c0435056e5aafb494f4763984a55b196ba4e6691c57a66ec82b886e3e9da601acd9a2ac3584975255ae13c2781abb2a089e423c36cea35126fca8728a82a9bb8dfbf1ed0795a46a83c22945b08f6c7048e3d5f3bc7874164ca39b05ea81d9f75e778cea8b01b1c19a8a5e89991419cea779aa49ae6d562d38be70784def475ca78a3ee40e86de917557d716b008a0819410625ba6d3603b53ce821d1cbc0009dc4d518e025c246e5b6904196e22667a9df22192d22195ccb2694e0cba7fd011553081520d24f53344d5da90299c150b968f7412d51a638bb853d52065e49ae471b5cd979b11953eed2ea89c2d1366a48a664502a96dbad1d8e527d2064d5885cd510898880110cfc7ec002de2029e02516682b953a88fa72b00c55632415e9b52eae8640d866d4074880443ac6f791270a208d2", + "slh-dsa-sha2-128s": "0x4d64e902943d4a78d5dec0ab0f9ab7271ca34b1bb94d84b6e867698b33e03c0f" + }, + "pop": { + "falcon-512": "0x3975d92a1db02f13be5e496af83a5ee3246e47e606bd60431200fd39a93f7ce4ac4d47c2210467aa2c879da085b51f50f21d9becf351a4852564dda0f03c2de1a84434960cd67279d342603ec88364f4340929026785a905c1bd9f570fa700beb52466a71f7671eb43418b32faaddf463d0567a1293de112e3b8e86b26e6a22827f8efc19548179b7a1994111bb2a1218bdbf0afea2b08cc2ff35c7b62f0c076f08cf6cf4c329faacebbc044c82b473427690f2b3383a3c290728f45b540889b65d75562a58109cfc1a35e4963a4f42c3126c564d1b63b7fdb3391f956e4684c435d2ccc10bf727d303249a92e7cea12367b99e19ecad8a98327928b92d37791b5d2295ef926b5fae98ceb9990867b678529abfd24d2851ff51f7a35fa85a7c18f66a7860185329e9c9e43d7ce48e694a89127814b62a66ba8e85d74b6b269015f34d3595973c13b7fb915fd9dd3567a122722b58bcc9b0b862a7d362b887c75b7569b85e202713f1ac23cdef3ea3a74ca2ca711cd1d124282e131f476b3fc869553cfa47f57a9ec4890ec8decdcb2905df7029911e3bcc98c734958c2549d1f0c96f7ac85cb112d060927472ecf8473d684bf9844b5ae1a9e8e544e19cc92739dccd710435e7aa9d3c9ef8265e8c5cf0bbd8d696bb0468d6f8facbae85d6a4f815dd14d2d878898c0df1bc3eb3753bcb275c228b7cae67f7eda0b61e92b333516188a259cf5753525e8075f48836cac2d0c2b1488b1d2ab0df928cfa11b7ea6e90ac8f92e108455a75aefdd67c7d146cf0630ee42bd8686ef6bae685e3d3b58cfd25937b3b7323b74e6b5c7dc2e081324c33ca7450d7015a4ce7af7c269b19cf9676d245289ab6c456cff2e7f5722ad7add62e4d4e6343c77e7664acaaa39bd7e95f5934981a208f353c6faad68", + "slh-dsa-sha2-128s": "0xfc5c40faa2c350656d0246a0eb77be69e63444596e7d84ee70d0e2920bc0e59c78a18b52dc006eb9e5d33ba2586cc46426be7fbfd08f832b91d18007679fe4a4fd802b84eb2d208d5227a7fa206cee037eb7465892c0946764a80f1774362bcacbb78387c50e9f14228cbc0f9af95db6aeab7a1006b122da1b13cb76429e50fd9e047795ef81144996e7e9612cb7f73f53df8181105823aee0034a71909fa5c30d506e082bbd3be3cd1f4b1b29287dff2cfd3190bed0066e6bb0f11059f6bbb9e1fc16c12103206f083297de20cb5f1e2d15a85518ab3784f1a31ca2adb7e488af276dcaee101769858b984e6c567fbcccc57d30a3aa1ee6c0c9f32abb9b12ce6c9191d49c9d8f7f1615da9e32aa925969e773de5c8ad91cc934d409b633d9e2060abc00b528d746e14f3f2e96d1c1930589c15781cfbc8344d1866123b40f6078690b90408aa09c98361b12ca2f6733a082a39a2004acf326a578bc874b6814c8aa2eababd194749cc1645006f6262c462218f6c51dc390b01d71bb2d919a53c0203b6153e17aa64029bd6a1735e1c698e5e2df63a79d718c81d8f6b21b5a448266157be920f1964276f10b341e5d0a5320a532f02a7063397e7a38783b34faf8f2ff6bde20ece64289fcaf896f2f005c57f7c47fa22b9640ddc686ea86a6d5a4b88eb120fc7b3ee4798c5cb56e2654c0c33942b2fe1f0dace5294cb6b58f3bf1131755ae5cb4bcbb939b4d694235d28bf04d2c43a3c3ce965c017e301b7b75b52e974764171f81fc96e8408a6f8758910aa28c55511241be398f0d798dbceaf713cd73929e6552c6f5ef043a61ba27d5ca7e50a3c6f421d794520cab4bb10d7bf959345e96eed438f29d94b0ca9464d163274751b12e09fa408c2bf85804e515f081acbe50348206f93adf464e8c6653f9bd64c16e9b6deb38f9f7cb4eb4458aba68c264937d601dae96e724228feb7d1f0d803e01cd55f249c72584002a8730031167e874108b4d52a057d646074d23c33ba5cd4c47e8c4975870858a770c041c5240f0d4be888b55dd677e24678fefc6f9bfade9e6ae11fd9962ab7d8b18e30bfc3b699fcce1e7f801fac2b4e53d58d1484343a5a502595743704c6e19084e7a967a34baf4a9c2e9d1fbf4098d24ba2b6ce49272c34d0ab8706fc681e0acaabdc0e30e6ca05bc2ca3e1de0b0df5d38514116f0660f067c3910192962034239a4a671bd93bbff03bd82bdb9090bf63d9176120947bbded937afbd498ba426bf8e91cda97f68c9a325c0f26dc281688649fb11ee075a8ac386dbb2037d65c283cf2bc320cd9d6d6328af545c3bc25dc9561379069ec205f2ffb4e7111b06e45bd919209c4aee490edab184c5fcb65b8d28cbacfe8ea35a643d4e50923fa4de43b2345a7a67fb346b7723efee065ae820c96a77ca9727f326f8a05bcdef841bebd91d64b7370c94fef441faf34d145012cc15c23357d0b1e3bd2dccc9be3e7dcce3089c7c3e3e42ef46d14a4dd55607749e88aae7ebbe290fd5f24b29a303cac567ddf9849e3ed27b34a783c0478d44765797207f690830eb9ac4fc1b7699d03b31dd5d5ab043ee7bb0e3539481b0c846a4a205f11e67e01d43a1f0941462cd4302942de812108530e8f65a3a839f9db370cd1aeff683ce3493fa0a3499fbf463dbe154ea234660745e6f773592c59515412ff2eae97641b6e38e04b66b50a8dd852e05c7fd762fa0142f0e93c7357dc43217fa32e29569be731ec25d13c139aa50c9898125b691c46f878853080e730035ead46717c74589a277f2472602dffac23b6db28450524f2fba8af8d9fd1d19183043a67bb994cd35fd3034c385946c62f8b8905b97cdc88fd38984b5de33338b44d0bddde6d37efe7c17cdb4ef5b503a4386d44a95e896d9ffa7248edd9a8176f5122829ea6aea8ed71aac7ce9f6f931531bc163e7fb8e31dc35e52ec01846f723fee89888f4eeff04252eb078f6391ea5db06a2d9d65b8465d075d65c3464e60c362aa7cedfb8768ed1422bb3ad138004398157e56b29b7a591d1b2ca827056d3540aeedf12caadcf4157ac2085bbe8b009708a815fe30f6bceee40ba8b79089c1fcb9b9f350b9bed4f330f7eabc3e1074eb3066007ea5912c4d6924aba6baba2c4f220a8b03b3be404e933aee10530c1da54aa9cdc8443cd1ad2b6aaea5491b4fd70a2d969a4234a92e371b087407fb2b2ac9426573e7df1b1932a501f6fb9fec9f6665b9f87eed4bfa5b4e95048e306fb6d6c287120f73f7a9cc426f3714ed791df1a8d58d5f7761ede9b9408e2c813657731facd7f994e9307a4eb34d98a35ee116caad59f758523f655cc80138fa5a81f90da2f588ec25da3efc7dd35ec6662b4e0241ce16bccadde1be618a3e78f4c65e056aa3920a92546b8204709ab2722f93c68af3d8880401898ece992c26ef605d1757072510dec0585334127fd1dcdb32d10641b0686e0d827033bf98040b1288c9b8a6b15cda0866f0c998e0be91ee2fe84bd7ecdcbc47e1919928416a104d0a53d5f49362aad07895c0debec08f39a1e83b82c720ef546f29cd146d6ed9015837c266602732d865cb65408d48d735f68445d40651e67388da5e48b9a6f0e5e3087a0df696818a6a2eebc7e74f348b011b39177b62b88ad30f325cffbd924e2eff8471aa287b6e05c11a00ec10e39849d755cf6b15edcd35f5ac70f7726d97872c7d34f3f22365b7227f75cd3b67defe9b29df8098b7c869937e6d9e7f207a4209609aaf3f3a1d866e2888a20d16c5dafb62340060f749b07d3f68e6bdeb2acce4d8fd2ff9f9ebbfe11fd32e5ec775d2ae7721fbe6ac1f43b662c082d630170b5bca1e9ab2a99c3d507aff304aa875505617a5b39cc5e615544792ea541fcbfd0ac24191a60d229c69e8315e8024eedb66968d9ced287db4b3e67c0ff08805832b12f8318aabc488a131fa1d804267ad6edf6b7714dd675b5997a823dfe9b3d74cfd90c05316702ad881bf0660025c2f7da655c9a37bf20dcf067afece18ab779e130b5b9692cd026ea6500262b02093c3e2ff8b53cd3dfeaa2ef8d0f54b3c85d186025c9d81b535c45bc5c2d91fce41f57042c29a88a12ea10d5b3d2230c828a1fdcc15f661059d72daa0638285a2c6e84ccd58a1397b0fa121d54dbc7913881412d668bd640b6e2fec44528890eaef4f654ffa453637f505dc35e1926c51a9e5dd62038b13ad2f9853f46253967e2591a9849d3be53e880b43c55cb5f23b9f3c201071b87a620625c4a9f3807fa2926c0f008fd804ab54e68be90e3ce718bad5b8270b469d31bf450cc3ad3df22c1b431ce4e50975ba437182870b6f45b06cc1bfae67e933417e7d0c64a0dc37261780106d4d403b9d1a0503f3cbeaa288123afed705fa5ebbe3132b786713cc0607106b62fe4a4d9393f461e23a622675bf49b6cf5ba3533a3474af9f37cd2d401f494707391ebe694966cf4b6a3c3cfd05219ef5f93b214803bc67754bfc190069268fc1540e7ffafbc16fc724080a0b9bff3eb8509acaecf0c76123a324dd1d9831c6b9f84a612cee4bd4a3ddb29e2af72e0db821b7aac57c7ff31aabb3b2e415b1551295324b8ca05bbf3ce21124ef6da487627e965601da987a40833cf1f9420419a64be3850637d1a1af3ee9e974b17ce95010f4d2339597ca6762cae647f4d03a47d6a51a0ff7d47fc6ec27f49f39b5dab763052544a5db86cd4e565d8b9ba8dd44854a0945305716468aa369df743bf9cf54c86f67727b87b814d13ab8a66d1099f89e1ed40bdc4f77635c0fea61d602eab1833e3b9b15c4f875856d6f7af3accb8931406e1289fbf406d530146851f98553a06183448afc36b3d1cc5a3dcc6eb435e4f33ee7514686f417549486b11c485b5a72831e2368da9323a26efd4a3cffa3b034553a9796954a298c31fb1db447b357260e78c34e9b79801b3171eb9ae79d38a2e49e7684c8fd12b12d0d781d6313c1cb3b1973a42c89c2f17e496b48e0f55e49fcba261ae63c2762f083d47e29c974910642068f1a2d13f5b43dd0db9269a34836b4ef2a4bc05b6f9e4cb8d178e1ff932f860fd782bebb30b127601bcd14a38206b9eb657e38fefd8ba0820a5c7ac9d446cffef4c8f2692212cb552b2d7d9a473834e08140a41c160d20a138cd6884f56137c659bb46c64fcbd512af1ee9f2edb175276e0adeda9eb69bf9d6a979c20062b9ee9db4433ca24b0dcdd551dd716d39e07f56383b354308eff80e93016471d4a1fb0b1a3cf6043ed6efc8a020583496f11793e82d915f7ff808c04afd2ce5c7f5d4558c9ef73eecea9ec021ec6d0f4516a72e39ace787193bcc4e051f431eae816c3ff2652f8be60c12edd134a8b5fad29dc5bd05d31e1ccc0d923da4e63539b0a73b4e6cb733c62f0480740b378b579b309de778fe3ae9a6edd4bf7fbc88baff19b17d21e9e6e14f8319c0099c4f73ead3f660ea24f6ecc6951c3bb6fc9e8f433aa2628a6199587487dcf96293fbd1d0623ed8698566329814049dc34af0fac662ade0d97f32e5c74ebe85c5ac2d1f1e28c10bf3d158f1e4f8eab3b27b4a66e08a88cb276d617d9ce7d4714bba1070fa6df40c9d9cd6aba72975622a84f6136753f295d7e6de034ed0fefef3f303ea692778598747591b565e47b9f03503fdb6889b09671dc9a5ccf4221dd5b0a9eb277f67de0143b57596ec7ebc2898d776c59595407f6ec84b088761006667610bf4d731d251b9e3ec78b15c225c3c9a22e5df6c1ba4bc7e87862790ce2dce1537f0ae4a31f7a5ed60d88d5d14c262363b42626d033791d9696e46770d976f5e4c992d82fba8d26cbbf5a0c3a2a02c72b9ba3561f34e5bae6fe8c8b1d294034ec75d291c15a734feea66bd422ee02054d3b780a222fe290287207d4ca251c8d8e0d9f920ef3828e6a681dff5275ed818ac60854a425dfc20d87727dc40ef321ecf17871860821550bb6e32974d2c1a5345170533785d0b80c521acc55a0c6d867b8452da774126b8d4bce7f96b9aa4d3d18043f61f434d310f3866bfeea73ffede3147d94566a8b15adad266aba7beaf923a53a2198f550a1150d72fbcdfcecc16aec40d98e3b5dccb9e7f96b30fdea18b7a6ad91f54b397801ab6ff53122428d3cf9bb1265b50c9a8d052156995245f98d14d6079d657a6a61cf61b1cb907e5a92d5632ee2d682201379bec4d28e1eb7f85d6617916e0f8b6be5acd6dfc7b002b77016e91819b8ddf1cf810bc7af921074005eda1cdc292e6d08f4fea3d54505aa5ac24196c64805ca9fc67d999ea9f16679e19062adef640abd011d969a21fe61a910b1c24c41639a9b7a2972a936d7f3e9a8da836e8fdd4bf96c858053992bfe30ea33365929ecc39de11c026a008eaacdc600737c58166d50e930d430a203217ba7688c18dd11f73ad3ad34ed8132228c12a20d5a700b0b20d6061ad80f3e8ca4ca9de173c1a62f9b040814253dbcab34b44ee72d8cdbbfefd7e7c05cb48104dbbc73893375793bddf9a470fcd5052275974723f6ef250abfe7a79f03d7353f3d659a37644b2d20bea65865ad0d13e272ca4dcbe4c71f6705f393fa45c2881706f388efb51a2d88fc5006f5f03513604f3bfd57cab71abcf93994486a0be057804345f6e4839e00e6dcd050afad919595437b39a6bbe4f4014a4d5735917335fa12cc65ed168cdf1e683a99a5174a65b50b7fd0b69ead94c1f709718c2c1ad42a9842b561ee95a20bee1133c4ecb3ddcb5a6f57048cdf3ecc1fe40830e1ad91f0c9d12eaa1831e47b3e2cb355d1bea9fdfcebc9de4e8a2d00c6d217e657abcaa50f62a463b70d5536a6fc96a5b61897174ac02e4675dc4b392ef0dcff165e7b771ef5bd5d8fb43746f8b797bbd4451eb07e376aa1b5d48a4611a75e5de73e4f831d1d738c2c8ce2b6e3913575d1967cb5684a80f7d4e3f1020c937deb6662148a928ce88790f72bae2b4b62a13a902327bdbd0266bfd70df44666fbd9388d1196abab5c6eec423dc0cabca33c4746624c358f9bcf3afd6e18a47e3227b8636e553fac56dd8403f54781746e3d09d098ecf5ce1be5228ab428b3c05b194283646be5bf4f7e5a111abde4a007cbfb2223bc2b70a569b62a01d38c43d5f1756459b6a1dc863ec16f38e8093128ae200e66defbe6cde4259c43af5688720e68910db574099f973351a22b5ced7fd2273e28e7bf2c7cd85c1e2492f90078bf4f04e675cb875911df7ffe83b0b43fdfcc6eb9bf8aaf608caae876b292fe2b7a69d9b473ad74085a5533c762fff92e3091c93e01ec247c82bcfd7d697c85fac314aebde9806f18453d3e6a4991aa4104a4e002fae41559fc4ab330705f03a7ff2e86c968dfa1df60d2b2d8dfc445bed7e2b52c73f713da875f229a323fa9255262aefe09776cbec579756d5378ee47ef375543e95f76bd2c31662c74d1f6bea75d94114584f6634de6820e012652a8fcfffa0eef153a753666852af21eff533326e96ee4a9b09bf7b934449dbac74b2a0f349238ec809b539792a28d21483d6a26bf0010dda0fc819c01c5fc0b81d70ecf91062416d6c6169c5ee2f41d6bfaab27d6fb4500caa823b6ef3f3ca2a71314801d56b73c94070bd1e44ac2d6e8f9adaa1c3b1d34fdb8d3b9c36c1e967c1829c740062c8d43e2f2f47eb87dd9c4b2402481e2cbe5b3f3af7a5181881addda9fac282f44a5cfb89d24b34a3b53f014574b234795b9eb2205dbe2a4a18610b5af55c0e1dddb9c1ef884d8fd714df2f6817245ec1f34e11771b59ce3775cf039d720edcfd97d585511e71bb94085ad3957494dfe8cf5120faf4e9a191e614cf7b250be4a9c682811bc25327df59c6e484caa98f7e5d2f4c58fcec9df93c292a2b766bdcc6dd071e9f2cd038d6f8a0f40ec36f1bccf623def1a86dd310abd94ef9a35ae4395fdc87b5ef562d6210e122660a6d892f9159e460d4a44f1bcf4cbf4cedf8b25e43e89a91b76c2040dfa7d54d83a32dd18c49a3bc30f2006e65485467f19b83736cdee29c925844deea4d08ec87f4678d2caa078153764116258fe33e392074d74c22a6f750284fc31342a7d116ebf17edc8b0867b6af35b85092fa9b633ed6c587f8e813c47a3a90c022d1cddc290faec1be2552d6574e2dc8038fb954dec9e80c801df41e3e1cabac10f4164800a25a7845dc2a592eb490140b1eba1981682c12ad3f0664ad7657944412a0810da66988d167f63ebe52cc18a4b35c4203a49f7b51ff324c629f916c60069b0157d9964e6e9422e5ffd1a2fa5b4e1edbba5558ba0682af446553bb6b743ff2c03d3a6af78372e40415d175b6b2a3f8abb8f90e19245260947efb0a079bb547909fa435cd2b10f8a4496769487d928bec7834378e3576ea04614867c7a4335700fd49efa7974ace9d14a4b8669a023fe6713bb6f053b40df9dff3be5889642309d2e9acedfb3bed530a2d4c8c6d8ae17c8bce82db04a816c44e3615542b73903e64f7f06cb8618201b8ea2f1db7b0ccd906427a2159278ecaad81a847fc2276ad43a011675cc3919fb0fcd413db231356f6974efdcead93ee5910b566e8153f315cc80295c56c970dbb05e59e8447e55d85c8b39143b5ca42561546c51e48f14a1ac109b4f91117d60cb07fd65b3b19e75c69602153edef3b1ea0e88130c1324ecff49c10acaa550734ade306b14b7028f34214f51ecfbdeb5b688c600c85d6ad74ca404dc61ebff907c112401c9e489252a7e47c2d369548ae21b797f9869deca8a48bc11f6e961ffb49783195e59c3ce734a611763c5e70fbf97074356e976f4b6c34330a4beb2ef7261c9cf8b62d54c4a40dc120fc17df58fb64e802759a393d666cdb0413be1628e0e3a59ff80537f9c49bde081b0be2219a7d4ac685e925ead23a60d4c6562d1239efba01fa60f1c20faf7b6f7d68da46425886deeb68a03f2457605b25d0ae44361815a8fdfb06820f09ab2a846f2d5f1512c03213b1058c7bf5aa4d2e8c007049888b10e9efe8e904d310b9085c8cd2ea58a60ad4777f3f8141d9ebf266e08267712e5a6627183aeae5f9873a75cae6c8598c6baabce1387c99edd22272eee3c5900f05fb613497c0f15c8cf385117e25e7b2c9c17604727219f6a17ffbaa125e3df4871d82a35f217948387f209043b58fb6bfdbf18f7e71bbdc8da2720ce52d6ab8266fcfeb22448ae037b1ca49df82fe335852c235b7334d98e25a97d6da2dff5ae2aaef60afd978407af09d24f8e3bf8285d70bb162ab186058530f91663802f7de50523bc7815eaba06238886bf330918362e903fceec3131a56c4b53e9ab6b893499bafb3554363bd93ac1ba0d1360f138b4335faa8d4426a0d34cc7c2d94be953bfd4b5bad93f4975cf38f3be4a1ea5dd7fbc6fa32957eb46ae44cc025c9bccfc57d87ee521f53fe160a75fd15af15291bf500cf25a66bd9906b1f1a46e30562ec1b0f22bd23a39f1b2b115cd5bfed413bffba57c32fea570a8926c4d48b3b74b79aab68f92898f7f1c529e7158a2e994d4c2acf79b6fd0d8a7db7201d3cf1819181387deca07befaee2c8d2ed882c4136fd157486a3c2046da0d92396097b28c5962344f85eed003010f1cf0cd86907f4fde69c0f2f1437ca8a61f078513edb5998bbc48b58bc1feb12ef99a2926c9695f6f8ed788aab2d57b62ba325706f1139b3448c87372e959d3bd7e7e74903c7a87bc07f0ddb62b1034099d0924d3c85f8705a623b0ee324af130cd1251a5779d0ebca3f2b94e69103e190af73b664f5bc9496701986b70461bafe450f6c0affd63156e04b15ba668f30ac74fb8f11ff9c6e0ccd58d1cbcbc2fd22db6c9a4a7bd9f7a6a5c3f0f7d83d394de221bfd89dfa5e58970118f00fc8638c06d8d48da5ba8acb5acee7de9b8903255d609c992ef360ccb23361cd87ef526454d00810b2b0fd2915a9458b287a0997485bf8bfef55942641fefb780a207915379afd12f6a74f107dc187e56b1c7160476828594e09d8bd9cb265d27fd99ead9082385b24c07f4b100d73de0f789b9048b774c131d183a23d6e6c94c22ac9d3788adac064d279c698ceefff29fcf764df966009bdc41552d062bcb8129a895345c9f995a852c66d587fde47b9e80676a870f3f67cc277f94a11ae46045528320299c5979ce6d8e7ed68ddf8a733f70d403db5b12570fe501aa1f17a91fe02ae403ade174987c67cbf740fd7c750bcd474aedfcd9db21b1568ca9ba576654f884cbcbd84f1f727a98db6579220ab151415ba1cbbb64ae96565056145400bab7524126a20dca2b50f2a82a1e585c3d17f113e1d1a273d4ee3ca739639f6dc24855be12595aa31ecff985ccb92aa14b73d1f94adba19530591b9aa946caafbf8cef4c38724094dab2323271468b60b134047d59b3ac9cb22fd50ba3722ca18b7072aa1da0b5346ef446736b83c16a56d56504f3f59523025c3e8a1a5ccfcff4b9765cf4238bf49206330fd2304eed9fa6b380be0fc5c2a750367bf4412f6de7556699529ff6eb85abf72251302680a9b358735933059c4e43234c5c7de13847e83b799547f0d151b340eb79bf10e1ed3de9fc1c1d0d25f8333f6d7403d476e04f610a96cf314811f507b24adb6cae0f0bb6112d2d4363ab8f1c71e95d06c48d249bcf427d187245abc224e00d1d2bb4d074d787908eca2b3c54c79f1ab55127c73a73f8c754497fcc89ac7f0d5f9abeb418e9eccd6a47741596c63f47483038f6862b9636d20d6e7e4c4782973e5228b8aa974aaac643738ceaea9cd2602b999e08b116c95e9b5384a3c8036eafd829699d9feac47a07b2b538e17c978826a251599874667516a94b69f9f66eae841b871a35d4755d3a67ffc993bdbd1e647f003dd4e82d8eda43545d8ac393bc491d2be358f0c3e64b331069ba2edae03031a5c41f4b5e279241053ae7ccdb2a169b0bdc34dbe91cf8df5d4f2879afdacb0f9bce78be60b83c39487417d7443f8b7fd944f7aeaec3a7da539704a92ceeccbcf766c594fdbf818b131e1a4e65de4e0c858fa1f42b6b2125c1ae126eef9e611882a6d5ad7fedea480fc1151220515269e3a096bb2d44ba758ae2b8950cea54cb917f38cb3a5ffc28152f9d98f472abd7b11d465cd3edd0eb11100954a153fbfb818d4776be07618f53116a5a62458e0e9e2ba03f18b12d60763ef23138d755320300f758376d89ef778a42f421ed20789a558b292bd8d20f8244cab1eb13df2f57ffe13829d744de0d9d59f8b74dad4fec468f963ff6baa7eacc1ce0155204d2bb4ddfee094ab1af0c9251fbb09dd619f72154b4128ac032557c48b49e5fa5df943905f3e93f14829f884c515bab8137b5772c679125ae561b197023c2f011ea95072da4eb4688c12a9d4460d2c9520d463788a1a831c31e032635f60bc9861675d2fb183734e3f6cbba407cea3f7f680010d6b5c92cf192925125638d5e3bfa258854a6609b473128f56510e3688c3cccc4dbef30a2fa1f40dd97ebb56b32f2056cdade382a2390bca547561582e4f43aed46fd1c714590101d06559670d21f286c6cf51418b853dc934d4f68fce1b1424213050093ebddcc377423d625b8988d21cd62235715c60929876f59f46fbc87afebc71ecb25a5c6d21c088028ff8ccc0c5c131587016782765a5d979570008d7c31c18a7383f619063bbb9e9b29c3528fbaac034607d15cc040a26ea1e7499b68197fa7fe32f0375ddd8604a81b665b3743bd1e0f0bc344da73642f22f6cfedf626d9674e80390d1cb8f3222f7750c8824adb4cff431c5878e9ddc522f307813985b7b52d366b1bb52de283cdabae5a90ba09c64ae5bade136e67004eb4f69d59e9f1c5ffcb0e3c170269e57c491ded8f07caafc02bec99a0a6bde42878b7ec07a2acc94741ab4d1c3d48f296b164b0315a2b2da263e99b89c1231c7380eaa49a511fcb26a16bbea5ff30581799c40234c5ce4468ac35f123c2f4c9bb3e1d812fbcf0d64ce85c933c016201d1f902aabc141713c33520667b519a2bd98f727627450346590e4858ee0f98806a2419b2c2d33c6ef5192954969a173fabdf6e742230a64ae124024e49d96533af95" + }, + "transport": { + "secp256k1Address": "0xf73bbbd26a82dbc769066550d8d4585eab2fc00d" + }, + "ecdsa": { + "addr": "0xf73bbbd26a82dbc769066550d8d4585eab2fc00d", + "claim": "0xc629dc813cf0d36b9b962b3ca67b5ccf05624381260338540ce7f017b8679e09592c5aeae7a5440cb94ba9968909d525ea0ecc34c01d017985cee6e0312ad83401" + } + }, + "7": { + "id": "0xc4ecae0e104fd8ab19bcc4708abd0cdb1180692d", + "keys": { + "falcon-512": "0x09b3e68f6854452ead92a798ea4db7116c6fb4f249d222909490f1837648185d207752134d8830bb9949597b70e7fa8297be87eafd8b7d116d1fece81701e0924d6a745bb64e884a54e1e949238e497868d2bd2960918a07a3cb1100364043d3218d2e76ceae07859de4182c85f7080a6baec87cd2235e908b2ca1a5c2e903bb387c067f2c514aec16c42f1ecf45b2eba63dad3b08a2da6bb6ae485156735261194cb8426fb8d10686527c4567a64195891acd62ba2c368152d2d36c5c24bbfea36412a74830c00135dc21941cea0010dc6d5c14ea61d1181f2db9ece691f151f1976e9a4a375d75964dc3363699f030ca842572c8e322854209f796268bd831e2975bb26f0c43332c2e7c5f5a959a50e7697e218f968e0039664e585a8fd5204261d6d29c287f13dc874122a3c3649169b0e6a2aa3dc93d70dfeefba3aa2970a788112f1c8085802174759594f33fadea69a413e5dee35f8dd13841f29234393a59052787cd8bf4b5f51b8ec26185ef65b788306f317121386a23456a1a64b1abc415d4b4f6281a8074526a19e8dd51b8317342e1de9f4c86a4c7fc90f64d628a909f5b0a2c146fd0b6861165487a75f606536a7abb9aec8571984a90b9b254447df27945cfec9f01ad1e82e54ab3617d22d38d912a4fc93c8bd4154648129bd17818892004605a7a6980b2a54842c5c6be2ca0071527a5b279156983ceea138ed86d93808b732fb492a036088c8864b7e1daa6b589982aca418d73358adb00aad06da91845f80723b4b3903f79f18fca2e3a49e31a21253bb6fae64f08a3350951a454d0fc84cece51f9ca3504d8665933088ca47c2345a744410ada4b41c29639299127c5a38ec701aeccb82a1caa59c0abf4be05bf4d10b119cadb9382f5e785900b70578a3de5659d2c1dee6a5338df1d0b90c293084620b9bacd2602839f75e83aa4258e03be9e541437d0481af11535d4e049b2568190f6cfaf2ed6b2e4d48e8979168299bf96fb192112e99a4589855ad9470a5a8f451e8a61f3eb4a51885865080c8dbc98e71bae8f0c4ab1e15247c79d207a5ad11796c85e6e62733a483e0f022cb05097243e1e61143805cd3ede3cb2640aea3300829821276803d1ab1898401e0196e070b89cfcbbc194e86f49108a45e01bb4a3dc4bbc73a05b5d1a674a9d28b16958812d4ca7bcd475b5e99957e9ee4236506d33f5179e6f804b59db5bb81f0a94500a668302599121fb67a62a4dc56048029c907d226bfcdbf3", + "slh-dsa-sha2-128s": "0x4680b2ae637453f4d28a4092489884f89488fa0df7a95a9f68aa3aaa22112f86" + }, + "pop": { + "falcon-512": "0x3931a312bc9e3e91ee6272838d6446e72385f6b81934590767808a3a199f70640de57bbf8bf86cbbbb9c3335f850efd39d0a2fdd8343501efb9521a3b5fe94ba5f89e5357a88b396e5b22553092a3fcf3b1536b44525d72b8d3aa5b7a1b57c6dea5913e8e413e731e34326ea557619a3ba1c73a3264725b914c25076581508fd48e6b186c3c1fff611a495a4863d15268261b1355e279e82b1b3b3dc8eb5387b35e41dd28126f8958d3841b3bee6ab9bc96209f08a30e6f5bf8699b7a5ba4b31e833552566536fde96d5bde8691a3e760f4d0e7cd556cf0f0f3a1d6e662dd4dfb4491e1546b24efde8ec79f8ee452bd9b6378f64cfcecd4a9591e85f1b6d1eb586533db154193b5c600d46722d1f4c21d5de52eb3fcd2fc9fab19e404c9fc871995601fb72db6f3a67f687b3025efc29cf74a5d0fc9883172a8669771b68067cf4f6a20d472747ec88a649021f3f7d621af1aae1e9f656d7cb80b2c67b2dd57b1cf310fa7497549e64b02e7d8f0672b1c725ce4a94455d178d447bcc44d98d1963afb93d6ccf5d1bf3601405de9bbab1a08b1a23a630d9a4d280d458a0a21782fd45e15873fd736deecf1b988bfc98748310ee3a7df657d28d0e2c8d456c574355f2a7a503d9d0641b6f7a2330449d0a8cd335085f66a97ce12e51addd12c5030dde6a528c5a3a2a6a5472a5daeb7f0acfce9dbcc3434c53b85427672e96bb959fb90e6de989fecb0399e5e9f3ec29658854f4892abe80ce56171947eeaab34dc75a1472e07fbb8b7536915eb8e596d4c1c71ef33d0653cdc9e513b6b67ef4454f14188d19a3dfb79eca987c4fb73dcecdc3598cf3207174b45f9c7746c66f26b9fc758dc4e938726b1ce7cdd19533e5fbbaa9b0cd0c96cef759f46c62f7a6dd1a8c3d6e549cfe328ecd7685ac9c88", + "slh-dsa-sha2-128s": "0xbe037e8a335f9de39f3b730de7a7f3dc7d33be6f495e57f513575c01d7a02f6a4fe96aa347fc6a62e502173eee97fc38cb7d2b174b4e50e349ef500e7c96bb4ea1b81b4d2650bafbae91e90ddbea4ef89cd45c81dd61b5e6334d7076f273e0ebc0db0225499a0597d4148b0da8bfb929797d7beb8be8f5de7c3ff4eb1dc67cef5e9f85aaca08a8bf2578bf9fb22d2babc42bb3ad1522fee5a935c524fa8543d92fa427aede762b17c84b71a90fa17c39c9608b4b0652aa782fb3802477bf91893ba9ac570b4ab485535e7e475c8e229d493994a602f78102cae68d2e510eee9d9048cd88514f7a105222a07f0c15eba2f00956fcab9e8c673f2897f954f70012cdb7431acb66e1f772ea9038802bc8fadc3dd4b08708f723318719863ef4ecdbd63b2a4672b849a4a9178e733c2d659e1bb6bebb28993233b585c06dbaf6112854c31211b8c41b079d7ef3ad003740fcabb1d161bc3f6a3d1f97eb297863492540023b360b4514fba473af5c4f86f9b28ce2ddd81150a1f317b44b83d1cbbff8f45e92f8a54c8b1163eaf8103272418a735f2b52b0bb07ddb59225d69bdcebf1a90245531e890e6c120bdb79e4b2d52092ae07f8f22ed23e25630b64b53a7cbde2701141789fd8654606b795cd5a50c5c33e3102caff8a7c4421beb87ed1f59eee92b3e2b5bcc94f45583c3354243743121643b7edd4988dd3baea119c964572c7f7a57e6209b8016b5f9bb9fa6d8193f789e41415e9565caf24523e74fe54ba1ccedc3f0f304f9655223dd2345cefb2f3e60d133898ffa01e007d63d763530b34d3a46ef83a6940d0729640e8c1d5bf72b452ab0a4c4b11d1958cb845c37126fa32223037970c6c0c5827fe0cf1e1105f5cd9c24eb34658cd1b922c36d48824d1f56fd6a3488574652755b2b6369dc8f4271a76ef114456fecc98e849bd682df672adff5e5c8e025f1b95b5aa7788444bc5e67299942dbe8d8f0dbfc834529d33746d47b43efb9a08ab1d12b66ef7dc4401bc5fe5a2a893767b061166ea2d7831f88be14f965f2b00bed6d6f31ccddcaa580cbd09b431ab46e9015644c15316ab56445692d9abb1955f2de44427cbf26c817b94fc752c1deb21dfb0d0b113dad3d5d29072e1b86db449826985fe747f81ce58a0a32594e79b6978a8b25565a6236a1053a80ab8494bd29d5bfaa8345b4fb77f452651f4361b5e2c4e52b18c05b5db69133ea7de3347e01348fefd7c9dadafa155877b6f44ec42bd1cd5b7f767ef69181f17d92c8c94d24ff56c760bf233d5bd0ddf2b2e6ca75cefbc3cb9391cfca596539ba59ebfe3f429e7ce6892b2fdf5a9766c499e3b840c0587b423f8c4c231defe51bf1d146367b1d59c32b8212b225605e1d3d7b7ca54d722b5d1bd991547ab4232cf92bb87cc85041230e312a42906373cb1480db6cc69308be783e4a74b62cf0753c926eefa622603c44e32a061413ca89fdc7da5b737081696794dd4c358ce3c4e9f577d5dcd44a0173d6f610a9d148e506e175aab8b6d202450bfa956c414dc1358a1f73cfab621df0601082fe6dde6fd9542eb42efec32268d65a08d9231d631560d00e1bcd3d9083f210ceb73e8f5dd95b1ad1f448ed3a054510e013f33500ec8e7379cf7c039f47eaa692b0d9c173d1f0bb60c356f62e3416a6009c8249d06b6a4cf87d5ebcc355aeeead170f9564bdaeb9b6c5f79b9ddb497a5a4d4e77b603f9ac7f93b87a92bb4f1319cf28f6cdc973d9f9e5ff737bdf6cf49a37d5f61c6d748e1e946c2681f5648fb53942e9bf46fe9908ee5ec4eb5a5af3702a44412e78212815de18a85f60f423d7987d20b585794a5bbee87f6c2c3c867a1b466a73ebbc59357fd14d319efd4e834fa76bc14fff2944855b69f5b17da50c56ceab5fccf3cfb24d6d4343a77ae82a6c5755f33699104b0a06b44d90e88c6456558f0e924d728ad8fca707a3aa969f95851fbb40142264ce72e3358cff6bf467b1fdfe5432afbaae4d925966a5ebabc32078cde1cb7a7d8cd8315df2a9e3a4a2017c4696afb5671914ea68183a8679c9174e852036e64f45366cf2d0eca3303a128d07948a1579cedc5dfc90a73574a5ddd94f13f0890ca2afc1c295928363a4275f8b32ced30a366c2ca1d5f230367c84e5712d5035578cd864b890683fcf19018730934486421627746a675a33a0d84eaedb5797ac7a2b82f91766e0e478fd0777a9b4a652c8d6ef348c7a54f0ea767baed8c791fb81a4c26d4d88912ab20e2585f653576b097897ec1bcebcc1aa37cb8574481ca180f82867477246dfbe95f06e71e3b5f71f973d70d65ba1d30ae2155ffd43aaf114994d03c53bb321d9d9d824756504809d965b597b5bbb821b193e3498c482264795c8e3219996f9b137316117aea657623031262520d90f49b1035dfea9a16e94b284737652e156c6a8abf1dae2d97da9d759f176963180cd3a7ba0138dbea73d4dc14b23e3f8c356b2681b9e5eca35fc4cc70d31a483478f121af599661d85b5e7404bb019bdc2edc3259ecf64b3529f3790f15d0bfd306fb4881b478390c4bf9b931b72e80f4d11a1a241a11556c2fa24d8195b00b9a39cdc2ce318648b5bd74349e98f9cb9667b689f2f7b65064455a1acc038797861cec03248bcaed9a4cc296bb001fe0529d84415fcc0a4a3b5c77318fd8763634e93034875728e1f3e4352a872929442d9cbdf75cde3ea70df5f1cf6da71a775710a4ac6bcde2cef5ae2df333e83fea9008ee0b4ac5592dbad1f55c0313d53cb07ef9754cd7c6161630cbb695e0a6832f92370b03ea7ae206edeac5cc68c60c49a3b6f5c36ccab7efc441c2275a7fedae1962d4bdb5cfd0be2ea1b35e76097ede777e314729f45024f9d93ed44059a1d447d78a579d01b76091c8560c87a8880651316e2b597209a0dfcd6d12dbd876db36f8aaf49d49f27b814b81792010644c723b661811dfd292a4248a543ec94c402e7231a80e36387cba3dd363f35db61340527f07b28759e0e34c5ed787190800814dd24a59c4a869db5439fbfd7a2e4eecc914bdce3bf57c5e2e9072d82ada0bad2b2b5f6feb96d77f75729b82b6b7c13ef967128bdc9c17ebcefd07f24694c428f13be48bc2a77e0201f030589633d5f41b5322c0051ceb86bc9f117719129756357eb5abd3fd9362f20a2877d54d46f13e6343f438841c5a4fe7ea17adb8ca005d5c2e91e36b3662a5987fe41094b7babb775dee4efbab5d0bf074184d501425c1506acb068f8a30dd996629b0ca5724956f49773f535535f8e9c4e4cd24f7ab312b3a3994159e6dd509abfae1e3942b19768b7b8506c1d64fa71a665c82e7f33eb12f8481b770c8e547b3f4ef073b826c0977efd5e0fe1a93223df0ce9737b56ef40b262797767136793a0626f32751150f988813e897ec9d4c1e044580f16d3e083d80a5daf1ac39840a7623916a4c7093e116adecfe938f3af2c0b456709a84d40853a9c2235d774a25b0803a089881548cb5a1f8d9801c5adcae8a5136f6aad9b1c30d867ba724ac44f5095ee394b7cee23388da2b543ff0df1c8cc20132179cfc43e05a8f3cb0355decb81b8a24d25184e080c6fd0afc198d1aa93b52af0e537b765f69f909a829a8b54f7e11f4ea24fd6cfc601851f78fc45dedfc4257f0475cfb03932814425edd6ab53cda54f99324c872de8133ec6a27f9e5d0888ac518e671801cb27183364431d670eab707cdbf0a130f2b6a9785d2be022c858ce69936134dc09bc26e650cec4474253f6b56fbdd0b7a9579ffb9e209a33c107a4d563778071fea414de02762cdd337a4acda7c70a4ea416e8697f267b4601f18c48eb4a9a39b7c8fc711913a35b2cd0a71322cadd8062d9a7b3be9a14da61bebcb8d153a32b795713bf0eb3ea2f55a85c3a9b8816ec8f8572161b4ba2ed3781bbdbbaf2fe1d9f24cdc9ac6d892c64097afafb0e9af483736e24c33b00705f0a6e26a1bb2fa5339ba61fce44ba7fc6b8e43bdeb1eaca8c6f9caecb9968995ea59eb7c0071a0a859713de4906c760d5ae86907e66db74373f63a91535d5b00aa60b701887b057dc927123ab3839f6ebfe8303ea9f6ff939af8306ff543946a74809d1596d4e77edf9dad9314ceb6699f270b467318ee3fce70e3a22cd0183997d8243679d306430d3b8eca9f951c6d013cde1eccdcb45e13f7cdd4533fe3fef5399f43d00e2c1ec1e3678e46b89a5fe62cbe8f1d599e6f75465c5a42c78dcddbd9c2eae45edb6f44a25f29ac0dc10eebb311f8924146af8ca268342770e1aabda3fda1a9141c9d855ad26e16fa826bb23b60d7649012c09a6fe36dc07271b0f3e3dd834959a8ea5dda673575e79e4fc775debe5de7df6493a6e8604b6e626db4c21f3e33b4db806c7a51f6d15f5d68c70d6903e4f58b402335504154e957c8219ed7630e2c251dc8e1cf267afbd1fe87001fb98ae95b78dcf8040d6b5d7a38b9c9e2a371d7824eaa43c145a62665784dd202aae213427edc4daa1cf5ea3799bf3d8069be9243ffe9215dff22c15662587370ed3ee863006104cd35488354dc24db73e65fb9ac00e3b2f12b4a67b7f49eff509edc1c5703d0a57908260bebce40987b3d8ea34d1ae018d9dcf109d74293290b37e40612eb454e083b76f808a33fafa4330a235b3902f70828c657f5035f9f54e5a3687df529084cd309c2b703668196b617edee7019b5e1b86d344175b2dc0060da9b891d36a6f723282dd4093c163fddee9108d66c8edc5503d2af713a7ae9e7a988bdc1eec0669b318ed7e2078b336220113cf31d930ecdacc6873197e4fc711cdd1646b497653cea1bb752393c54fd7f81e376c95ec4d62c5eadde314f691d88036dd19a53b66edf5043210b70137db4a65238f81a008d20120c5127a9d31a65df5bc433c474322c47d0f64c79479efc370f347fc0b73640fd0eda7bfd0d3f6fb18de301cbf0af40f99bcf337488b7f9ecf89bc21ef07919f1d4311eb5347b2032d7d8adae12e17b51fc02aaa3702b2a8aa405f4b508acc1e09bc62c074aff3d7c52a406c7ee8b0aee530f509f5690ceb4b843b482972254b27424d466f9f54291003771eadd2fe5dc6ae9d02bc61346b506f7720b9058e5262f716f62b26b2071f81b8d8be70016886df34085c5726c2f1cf10f602f2d89f17405788fa966db64d88d9ca201dc235f41f2214a29c43b0818df3eebba659f709a2c130816bbc95e2c31889f3bce8cd6fc7b1794d3a1dd3bb2547ad7624630c19134028610d7415714566a36166f39de70cdaa9b399ea34fcf821861f12fe32fe9eea27d75ad5b211b6f7ba168ec7aa60f242b6638978c8c3618342f9b07a6da3c96cc405feaed07c80ee65da2fd6ad7a221dcfc42df5da7ba2ab7bfb24fcdde1754d7116f82e6240fc8f1f94ff95ac1c90df953acecae2db82c8f3cabbc65566dbe62ccc4b2b4172886cf7dded77c0e99a79aed7dbc8c508c9650d1f522c7f8efb684a8265f47b4c13104b0f78df9728b045c5c2364399d6194e97804114d588990dbd04756ee1fbabb20a9ab1377c4f78d2f4c9f0ef6bdfe0a9a87b948e17526e7e2bb113e2271ba8f41ca1565ee35e475ba89005dc26739aef6892e03556bb115cc7af7d2c5e550997824019a58e30d5bf079ef510b1f07f102adece245fa2cab29c3f0f30e37a8bb89da6d1953282e5876c39414d458519530a285bd3e294a2a83cddf0c4205e93c09dc40d71cc88ac8d893423a61672965ecf0be00b5cb0e3de10f679cb9160d32be70c355887d16fd1506a93bf42d8cc8007df3aebd531af3cfcbbb5210f0a3c0d9631e469554349c3b8419aa508ae0b3730f7d54771af6e55d5fcacf5de16efdab2626eca373662ebbf61ec9c947d0f015f77a503fe3e3a392219776341e6c4aff684225f13ce9ef0ec0d9f5578d0859a9382e537ee484ad110e314e14ba74e5e8f89a37dd1c86d11179b8f89951faa1781f70df3be62ebaf56093115e09f4a58c44c4e74b0cc07210f78617fdf4bdd487a60d8833332ebfa176bf49e7b71c315400a518e1de681e4fff50a7ed6b0004c3c0f8fe26db2975b9e3ee70e55cd91e4922d2d8977f69b7c2c7490474c97333ebe6e32818773d1a68c7553052be0ed6d320b215308ec869e8ff58bba2a613b2273db8207fca27aa4c8a935222e97dc11f0816af1fc594ed39091e5f72b13b9f5cd4c630ca5e03e92e799e3f6bb9c834d2869ca21ec758317edd96c1a64a32c88f1acc464f0abab95078c9ded723771888edbd4cf3b4ebd1fb6b51b025e901e638f97848c967709ea6990df7b6848b329b04cb4e9a9be2bfcfd5de63f0d7cf00168932b120bca7721cdd208d8395849067bb2342cec3623de4994cc622bd9e8ddbcddadb1fd406a7bd4c48d0af1fcf8a6ddfc4328bac0978917d56ff2f0d2e9cf66769d186fc19552ca5b1c759c7c50d54d298b3a53e3fedd43e9ac1389aae07cc7c426262320e831c618ecdf123ce206cb6c259080276735f073a98e2e11a1ab71feb223f6517d2476e1a64287cf10009c95a1e2b23c03e4692221cb81d210314e5a1e812ff70a5e57c87f4b1d6b17bec33733fd6f51f57349c33a6a9d7596174a894a66b11f54fa0bffb072946184235e7e1460b9f5439680e730d389fa2b693816c1f19ecce91fedfabee806a5bf9b6c96751c74d66c7bdc8a67998c76eb8843d63219956211928023e9a2c45f8b1933141dac88342b9c61514855b68879efc7037fcc26a6f99561743290126c742f49eb9761a5a6eb532c29f470b724e149ec724876a98b3a402db6ed121d9f2f8c56d71f20a7b93dd3750486fb0fffc38c8b00c6af809d7419fc29a6ec3417c81c52e095ff2d63c45f3e77e539679e9b0fe55964119db9b3b305dd3040fa8a3707a871fd315e86c3f694852efbf3851e2caaa33b910f75b559dafcf63530b79e68fa7710c9e8ae9b97739d02ed7d7c4654310f3f2143844fa4d98de49a5717b7cdaeafcf3e44881729de1596d0378ff587808e6f43c4089b0630c124d0e9046f145b9d505cb8c1dbec8b6ae497a53603ccd20a7e31bf5ad50c6ed30bac9b994c4fdd9205d2713301c524b0b8a3d92c5cc27aa35e29d932f8ca194c61113d1ca7e5d9cda87f978011d3343fddfbdd613f7bdac78d5ba2465c99e3b3155995440aaeed663faab18ecb96c1c9ed9a0930c2aea65702173faa127ee31f874d1b85b362d2af5b0c9e54810445df5a376dd267f14ec6952dffc63e3de205022d8b7b477ba1248b79983e0fe53553f92a3ab82e693f500d951cf98d79ab6166ca889e807a47539cfc94930a06630682b14bfd9d557072aa77f38e27147b445aca4b685795f834f6bf0982bdbb1f2292049f7fd7e19b214f9acb0ed2d3242693e7313933f5bfe9d2f937105a7d247123861bb0ac6ebec065d5155f05ff2ad89bc72b7f3109c048f1a2621489b80c21284d85222b127c7828182df7a6e7e535de78f6d8c06538482fb17a4c150894113cab8df26162fb02c6db3901594cf748d7161eb029b5fd682d5e64ce747033d4bb8daad4cb7775406e356e464bc91147cd9b72583b639cdba343eeb308996f97f0b91b8bcdda34bd23fc68d64a28ad2c2ecc1daad832a90406652978385600d02d9c80b73fc72f5a8d8d6608bb142fa51ec77fb07cd281daedad57688f2e2d8ec972b13875f9d9d38f0ca917e7f1acf64d5888f24b722ccb7eb5883d470d0ff26a429cd71ef36326d98acf7b59471f17d85f33447d004c76d2391cbb6260662011e3a6692bb0e9672428c6901e8af31c509cea849dadb414b8e2d6028cf0cdcc973f3fa634ffcc51f4f3dfa868c9684cb1d1639087989f26329aa639fe6a803a250253f34118d18095a47530619208de5f17f30648879f5a8c1edec0d5983c31a7034095d8a6bdcfd619cd7c75f9579226ef7f08596a76f8a16c74dd27547f4b68831f92488fac2a2787e8ca90f870a4e43bbd187e10a6f1c42fb850303ff67cb08fe76da663df4fd31675035a40e32ab1288fc05c5118a43aa7c4b9bff998fc58ec0b1ba208f52c2c34eab819d513052aaa64bb6cd16f4a34f037dfcbd33b19feb244bbdc4ee0a7c086dd965a6bbd2d248c2023d39856f4b70695550078250eb229ff0bf2111f867c526b5819d1a281a328d22c55dee887a17b5104de63275599c65fdd561b66df36720b8cf7950a8190c075a2fd5904973af7af34011e8a9eb7636644c3e2a78dc2949fe9557882e2a87494b78f485e5a7923082d469427557de35da5d45dd163316d2a08c42229b0457cc60641631a5915d2e6215cf076ac657b304bf059fd9701c193f92546da894660200f1176bf58026f4fc75fbc7d477ca946b6a341bd1a0846782b253c9f8b44a7f2f22c23fb8f201bfafafcb77debbd71e0091512b3a59b17a08fd3db7fc30596b45149bfc3e24e82d2071f6562b2106f8ddd2209a646fabdf4f351bccf1579ad802b30d2eccf1e383a4e5b262cb38b91f91ee7399f306955ddf7ae4c738cd57ce39bf2e67ad477cfc19cac30fe1263368a4a091b002e94d3fc17fc048acf18e265bb65dd05b3d44c58f037a49bd7db879bef27c85b5ce952736ee866c48958eca2f15b2ff8ca793b63668f0a9b1374cafebf1f31951d7b1cdc35a5e660e6051ea56b15f39f725ec24e4e9749d469dc15ec135ea890ab2729f7947fcb4d9e6c4c347b440b0c16d13ac16a8ff963f75202a7e1fdb346a7554c2ea59a7473c6c336c331cb7f262830bcd07dd591832e5f1fa109720df5d6e5fc191481dde1bed341d5024dc4f2116e38aa69c04a62a05dd4fd898da04d67323661bd424a61215f6ddd9ae671cedf5b640582b649ca00060ec352eadf2861373e5214954afa85d91dc812fd0687854297a7bace891a978db8909de2e7136bad50b220ffa4d6a333180c13800386ff81157eaa36a99c523fead9c5b8e9aa0d840d380b98296528cdcc44c78de5c60c3f4bc07e8512057fb82a4f0e1ab006b9d03bc20630b3d6f05d5c35ecb6cb786bd0e6175368886c9d368c342c99588647a388becb82222fbfc7bd3e768579e0079059666dfef6e32b85fe3c15aab5cb7664f090caf3dd60ef222c1b1a22ca0cb4838975f2c958c1eec04177dcbd12467c4ee7b2f719a762274726f8d4869e44a9da0bdbb28a5a1e756cb71ffb1d8fe63ddba70797a9d11ae2e9eeed0968f48de4d9bc6a7d8dbd67fafd2dd280f876d1bf3c6a0d236db425bcb4220abcc2632edb5cafaa4a5ec062ec6bf4f714bf5e0718a64ea73eab900e4f60b4e82f6cbbf2fdecd6e5dc73366fee096bb928275d57b97f2e6fcf49c690e1363e65ab7bb003272c60f142b3191aa777e62fce9de94fc36f481ce1b2f98f75edf564713a651b77449472067b6aee1ec00fc6f5f94d2dcea9a410c3a5ef228ba0a860ce6b5b4744748f328cb9cab78f5cf28b8f26b5d82eb75888bf722f5d81496b9808367a510fb6172ee4e9e7c12a679561b79e71908e5bfcfee69f30aa660c8fc0a6627bb507329721ebf97108e0c96ad4e674fa72cac0581c729cce97e7da17048f2699a739e45f9babc81866126685023ce373372ab02e35e2ad76b318691b89b0b4ba32182bfcd32467e4b2de4bfc7c549be779cb8cfca9a565e7db8867b56baa18af8f797dd35b4738c4e78f68156152b8a2e8b502dd639b7fd6040ceee6d8083911e66fab1bf0166fa8b4bf898468e090d1c46f8e971896f8b02159d96ec53c67767643a7f5e41e439eb6d29c5d8515b0ec5d68c0e1c46dca67ae136c5ee1c783556662e68458f389f7d17af4685406ffbef3d222da7e99a18986804133e137e022f9fbd5e033bbcf9c628c2a7bfa73929843b1080c2a862e880297e0e795c120edc893e16c316d331ae2888aee10629f07f9e6e1a07db61ac63e2f66c366c5f70b04e1ecc84198553606a572733e4e702bf90f6e86c819a7cda3ff71d4472fca4b7927e1b4d6c0ca8973ad605c1fd6ff9a9db5ca4dfadd5725c3d900e9172f72b6d28cdc7f202f98dc58285c1818cdc074d5f6f1b08a7db1b568d51bc84ff9fbfd52347782e662c63a85f1e61b67bae2600dcaf0b9b14735b331f48652b2a4576c4d57a56a633b1fe90c8a6966ce0b44f5adf1678889bbd7a32698f1d95d5ef644d8b5e82e22ba76461d0a411b7f17c73942b5197b300f16dca4d9b02ffa07ee31460a98b248f58ab629aedf6ec443fd11fb7f43813468fa6f6a053a8b92feed9bc8837b37829ac13372914e2745756a1ef5017c4d67f72768e43f877387eb401dbb9248b7e2ec9bc0521b7aebfd316b36fca9377a1aba2ac5dc7953aa6fe3d8c64a03af3ef9c497b5b3c3b8db4a81388fcac4561f40a9f19029b1e4558f8459f6b093deb934b1b983151e0d567ef8301b9a37953252680e14ceea3f3ee98600273c8d462d3338fe9daf1b9ff5d2b7e6e8087bb55ddb4e48a337ad93fe3be4397d45c99134efa3a440991f377ef212732a35bccc67b5f4c2991e5cc75053e67ee4e3bf26a0386bd9c86ddfa4126adb46d642df5dc69fb169afcc9faa40caa0797135f8b16154c98bca63c8050eb44d30e2f3300e4911e709b4328afc3a565ccebd1a1f790e4d0d8dfabd7773e745b04cb8f012d6232a2a227c5bb2455aad417ff0a06678fe26d12c7cc842825f6372343ea332d75aec2a49053b4265b14a45663d2a0a7159a6034e8c2deee68560de24ca6b00b42f6a364af8ddab77d87130071e570e198e58e9c962ce1dfdb0535f9028c6dbf40a468e98dc1d23f46cd39c3137e02a3602921c6bc2093d99f2c642b7bad9f633966b54dcf2ee25223001463327aaf65c7839b482b361541bf635794d62569dc29e7ac9f3ac39e988c67e949d5576a932505724cfa152ddb4f768f48c42a77efad39c14a379dd54f2354ba5fdb6ed6c6b4fecb797f385bab7b1188921f0053699a25b789697426f92703ccf1ce1f576d15ef4c1b9b63a0b5f976cf58d97fc58a4d58a6c7fd89438ac4d568eaf777807d355582de20d0358c57f84d67d039c037f67a568469b5a35462ee5e1968a6bcde0b3cefbc560e0ac4ede97fe78c8f446a4af9d5789078" + }, + "transport": { + "secp256k1Address": "0xdf09b32c761620c5be77da398b97a64f03c3980c" + }, + "ecdsa": { + "addr": "0xdf09b32c761620c5be77da398b97a64f03c3980c", + "claim": "0xa5213ec7e29d1942cfdf515fdc75174989419869680670951a8d1056a325d38e5504438d7a61cacd585067f4420b4e71c7f7278ffa7a7084d8ed44e054dfba1701" + } + }, + "8": { + "id": "0x824635f3e11b5702d32668588878eacbf0a76b3f", + "keys": { + "falcon-512": "0x09820cdb49fa91e522cafe7550a586b94132cae78b762b166f6bd819a1a25409c534a0846a6173d047cfbc67f518518f1fef1c0ed22a006ec77175f78b1ba5240ec600a721e7c8444a770bba44fe186a5edb2a8078bd55b823ab4fd0b6991748d142dc710691d574d4f64768167776ed9559de1dc6a466c5103585602f0bb21f2a85b1a76fe9a27ef5d5e6eef099d255c841ee8a12481d9bac050955e049398e228a8bf63013ee4a504a7c50573e65193872fa271f58cb848205112b29592d9222c6242e581ca10bb10ad04852f276182a1db822d63e66926b9b2229b8551a06520f9c89828d053864dc6717d107b9660ac6f5ccdc5696e013774f28a050ba02b787c4801139f33445231b87d44bb0ae5a8b5b16dd08ff174221f51e00bc4ca26712d6d2bbc03aa918cb95f999b23a4d71c1846ad5ab887f71ac294f42359d33b9aa6421d604b1e81eccaaa9ea7787469a68541103cf0a3b8234efc146cab85f4900f9188eddb6e00d68eb04debe0afe14572b1f924de61b610daebc7e7c20b18c97787448e199a79d5316e9b8c2e695b3b030335dcc60927d8d62d6526a4fba58763992605508ae16e3efd27a861d1796c0a6b746d4479c4fbea6f51597c9aa2062e2b8538dd1e85cd5350095472852e15d09b68ba1572c466555616134c8caa3330974244d3d31d00d256b654f92bb5bad3d75f668e69567263c1ae2e5ce6a2a218468b1c02c89f971e474efb8b59283578443f79e425a06e3ed7c344176db59e899a180eef9e0a5440ff4570b385ac700cd7fa290940b9201c56aad19e584ee08a19b4e38bdca2c38ebee649c404495df9ea22cae49b48767eca88e9e784319598688df4223ef1890450c597b2519044230a209488a56856cd1890045967e12006acdb128e4121614a1fd5996df927b6d3d60a84bc362cf4044b5243569639c19821adad4c4e09839a1789b82e9051cec285e611d0ea0170703e5f317496dd0ba0a330ef00bc7e70911463c534be4c1e8296ad5a05256a72712b9cb31d5adb0b4e8c5f89255211d1d41c121ce7d80f1132ec33b91494cd7c22378b3bce21b689d24a9bd933b68aaa917a8df5bf9513014897fd66d9451b62e30fa7c09d5116a11c5f2a9bd21ba718362a40484fe6b93f76c1008316d552bda724634edf50b184eba5a0c1413c17e5b82b16762629746fa5302b352c525e97bc189593e93adcd4430684d2c0237117611f615edfe21c8a4b531354925e7638570bacbc3868ae7", + "slh-dsa-sha2-128s": "0x9de25aee7a187dc2d82c60792f70b6ad71a90d744f89b0baf70639af4c682a20" + }, + "pop": { + "falcon-512": "0x39f03760c9d314c2411f9cae9532717ee1d2f010d39602dd909572030037ea4146e9d803baebf88466bb5c5997a3749ed6b0b69669c48f20fd995a0d31bd154c0a5c828cfa74455e79ea0bd6f42abf5eb4022c92604872253531a52c9440cad436969c33f79f21ffd05829ca6654cd68606bba7f9c6ea6a87ec7ce9e51b9303c82e3779543a72802f8e5ca341b04ef3f397618a825c8b3e0e1191ab114b55c26f7bea73d19dd261807c3edb2184aa5cf9905a033cbe46736d3bdbe1b17371889b59029afa32f00ebda6934785689bec1221c6916db68f47c981afa2941e0cea1caacad1d9890750666d54ed13e745d0888b65554c1f7c3b3f97505e7f49287c62ea69726ef6833ade4a184755514ab2b6f96bb64751130d5c418e7e569b6fb346cc8a5e60719ba56ababbb48615ed3713c6653096ce0bca210049de7e93d1c95ea0ad2ae1efceb5926eb1a2cad372a975fdcc1cd2599d49acebbbe96ea872f79182cf8d320d135a9e2ff2cbff7a16d19e57a38cff6306df926458da66215448fd3693e2c7d8bcd6517ad694081f2fa274b2fc5e762919484d49e7c635c7411280c49b35ee84d9d5cd021d623eb7fee54a3e67353726bfad747811fdeea18c79d88240569a3494e520683a8c4b3e9d5f95956b9ce72ffbb6db664808b17fdc420aa31580285a7f3a586a902235addfc06164756475d9e87f95834ef5f0d43284f36f6db58cdb70d3cfb8c50c4ecd71dcfa44f5d938d543a15a8d78678eb35d8d6f996745d2a71b8acc19dd6ded78977b2ac5a00b87f3aafc4ed09b096ff4334c75a270d7aa7a4dad2b26bd860924fed7b6dc83e16367281b7354d43a71bd6d4e7e96beba0926c4cc456afef89d2b19fe9f44941635222631dda0d094c749abde75f0f1c7f336fb631e3cc35996803e2a0a0", + "slh-dsa-sha2-128s": "0x9132622cf60c35cd53e6f2dba6313525f05ef505cecd9016931c05b8a3e6eae6e6481ab2b925627425373617ba854bcbe98274d84c4331887f724f492ebed3fc31a3ec68f79fe94bf605b8a7b250d9e755fc0cff1ca80ef010c6c45737391fb142febe79891a3c4b1464847d0ff3bce535be02a86f7ba826725a18fea74dd55a867cbab1a2f637c255d6f79db7fabc337ccbaddbc40e85e68b829889c2dbd8121047c840498c16c7efa2860abf7533ffe888056f7a0ec1977d25addf49ec1b5f831a4d797edda11fcf933774d0236fce9e8347f5952696a51e50addb41ba288f18f61823ba6d1c3c781f2da766ee93b6327345b1468c80153b4861e25559b41eef8325a692d176d042630436efbce3c5383ddbe86e6899806fe0322859ca67e7544037f0947b8b93cd94fbbb38a00a09be98317cc6435bef6daa6f3d9b7614c8006898620c295034cf9e7eff5f4db03c6a7228ffae31fa133ae9bd4507df136b746427dcef831fcd4c51d2a631e376c3802b00400c70d93da2741abb003093005c9f6bae3893159bdeda291ff57c7c366247c3743cb29f7263f543bc864e2bd0341bd4f6d30e26fd2a48ba4063325692cb1e9e43011f4e79ca748d73114eff537f4ec1c8f178e6a4e34223436a0a776a2b610c248482bc886234bd4047b75573d61fa7270912bb6836c0c46090a6983b9b714715a699e0d4ca2061ce7f73305f46411d4f60315fbced634580e5fb2ff92cc42a77369b2d29221314f6a499196cb47f60c87ce01d83a6d7f815c2d1182c8ba3edcfb615cec76a5fd02503b96a9399d4a4d03d7b8c10b483ab4289780aeac28571b1dd0b416668dce6b07589e7e049795bcbd02ee4c1711007f721d07cceaca85a807c8ad2f6c4315023222644540c2730554273065c9e0e445b9611d8ed982755e855cb5e60925b8f191d4f336bb0bb9dd5974950cddfd650f12d388b75f870e774ebd610e574a8e69cd42f04d9f2a111fa587e194c13f2ac79fb46c0e8bb10b4313b575f4d3d9542a975fa2ecc691646eb54b223d5a690a01871d5298c8a83ae3d22230ffec69035956252721eb11997e439ebc7ca0b3f152cc9687111a98b6b4425b4ec35152fb255425a9185604962c3a2c109d26b1393329ea74337c26591bc44320333fb4ea3d4c2a7890b1380b6651017132a317aed27719543afe0302130a0390eaf8a5e3d7db032d6d2e09714e100e4b0e36a349345796fcaa9a3b6e5c244a5b33a7c106d8ea68f27324103d3287e825341bade79f87281c4023500de03c4b6af081d641eef8947c6fbdac849462b7a668b695fa479f1b9ccc1f3c9f82d95269611c598a84aafe4c9d032a37cd996b9a92aaf8c822ac0c4e1fa4d1e05d8f9e557488415dfa08674b1ff6963694a71d532d9a20379f94c09b65962244d5ee8b8eab4908996fe9fd80b15a2b7e51f00cad30ed32265d0dbb840281e0ad2143d49d92b347335a100fab827ff8d8d8276bc67e51a82d323fac99e0e9814dfa52df07c3e528b047a3a4524da4274356f729fa768320acf1eee4e315522e717b07bb1bd1694b1af2b4c6a6c380a09f7ce670eb1b51cd9a142186a39ea2bd5b434a4963b2e740c91f77f127490de881f68a3a380dac5d2974a9451e8c1b347f1ba62d80fc718446abad12a7dee6a9cdc0bfa03cd72cd584a511114de96b7214606b732ba4ae974c8b9c8fab0ed6b2bcea66c6afc7b999ad89539f48c90e14dbc1dc32d0da6205b1bee6c4bb7aaf460e2465b2394bdb1ca7877518bd84a0eda3088bb1e33eee34743d17ca79501055b92b450d8f50e3aad5e57964b0acc2aefb816d489906aae990835ea1cecb9cf943a6ece2396f6170ea965ba5a3c6909c7db2768dd1b20c86cd015d6ff1a1707d41d2a9679c4dbadaf46e2620d0941f94e8d4ec7e91f1c21be9752d737308ef1bd25e4309bcaedbe6e01c2d8708256b915f539829d81bcc525655ba40f377c851d6cf708307ed47a53bf311f6810ac29edd768475bdb604f391e75a5f94947925c6d6b343e664bfc8432166397054e174f7dfb59d836a6c348634c176f26b291efac8e6404a0f69cdd4ddcfcd271b8a59d7077224d1899b849f35b6ce23b3516032c3e9dc7ba012810866f9503350095f23a21012c73b0d4b63b2b82020f62771091bedcd9d9fd62308919ad2150a2e65e5f8c0f8f08231b93332fdd2e7f9dc647e7043fbc9b3627815786b0a3cfb45f6e90678634b6ae89d1644bb9cfbf83c8d5be6a77c652f1dce0a53a213c38b61f72859403d0187b17a71ff2281bba41aaa206093b6ca8dc9e217dd4c8b3b3e73f6ed1473bac1f090ea981fb2d7fe9fbbd5d08b88590b9765d596bdef84d26261b73a3af1b0e8c99cbeaf74fcd9aabb429e4c6ef2a880a76f05ffac3a3ae9e3fd3edc4dd6d0eddab5e030a0f420b2708a2ba34966acaa7d9d3674635b6d4b2b01312b0aae9de0e72008a1c40c205712944da848457baceecf0742fddbca5f5ccaa223b130f3c262ba68be7bce5033e117f62e0e672eae59807bce0826f89691c63d860265a281cf1270f0e01e38f8d86810ea8fadc6dc7287becd9f2de8d2693e6a7c9a82c02a0fc19c2e58972d8f46e52f8d9ab12cd2dcdae6c8a805d7443ae7beb2e24d486e06c44f224f0b80faadd86029c059bb005384623c37b41dbdd185d739764e00b27b5e152d9b430acbbe0e4a27a43dee898a41e5591a64fa48bc7cf0e7c58f474d8e3a9159e417a8e2cce5b9ae4bdb8599a64c22f70d3180e6b8fb6b81454a66bf0dc2379fb51b305b6747d0522c1fd9f3991abca69f66f88a989838b894f0d0f4f17b0635764fc3eca259070dee2ad032aa1cd3556b41727f526dcd09fbf3ab45b89dd2afc0e25a492439cac5e9e79af6265b38fc92cc6d21ddb161cf403a32a141268ab053c922ac86ea7008b2e279ef38fc7fc0e6121fc090c86dc9c9a5a36d17df0228181ef2352a17d031fa41129a630c7ae9b19740f47388fe830925667e958febb95b07644e7b7f7a3517f892438c4ee47750b243d36a4b93dcf07db0f236cd5b8555ab42ed183cd01e2d4c542d9fa777573143ec03a77704b22a80b5371ec83a38706c19df6aa3629f9b21527f6411f773b37b907f1a81385c546bf64f2117aec9f8437e164f7e68a80f3b99e056b5f0ce1effd5e9019ab9d965bd02ecc9482a98efdefbe66ba812e4c2810dd8ee31e4a13edcaa19c820575e4f37511b6c88f0679aaad8dd052ac6f922f5bff094e67d9121f27b17f9ae50870590b8d6ec78abbeac11848426b5496c57c66dc43cbbf2c24dcdff009597a8e7402353a4eff620811654ced7c7a6362a2945ea97b3366027933bb52078b62edc7ecc20b956fb3614fd6c6b3d9ccda774db70ab007386dab348383f3209f91c2eeeae7a127e239e0e12b7be08a156edcd8245a85288c0af96dc1ced4c4905532caf8ac21f06d0faf43ce87dd61bb50179a748e1f2e6c7eeb9c02385765540f18b078f41f2a851fe0b726d6fa1faab467ce991650981b112c2d3578711967f18175fac74744e189eaafab8539f018d5fff1318184a3e36ecaa41469c11ff76ab941149813b40a54ddb2d5c05321865e28a489bcaa14e0c5d2efeef315c5a253dd9cd9ad8e63eacac29b05290d00216a8028ff85587ece0a6e43d51a26e57f9a80c4f62a04e3fefa47af6c1145a5bd083143d028a7a0bce5fd8217b993fd8c53036a0d8aa7d1fc4e3f4465c073d325d1235d6862c9b13b83451ba2a1a8d8eafded2513ec8d1130177f17b92d0541f0e05cdf1b04f5ea5c32738acd6444c65b0313220833a02b3fcdaf5e9a0eb80e55cbf4faa513b24362febc8f7e9e2e1300a3bd0b600a12984a577e071706f2eacfefba7306b4e645f7599065d63f8f3139ba7cf547c103828c237e5a3383d072244a0d759df6da0e4861f5c424ddd3e0d01f44e9b524d7ff641fcc652a192ed0a03b192474233fc05d384870bfaf08cec7968b54512d62625f89665b598a893743381484385e1893a9b97b0c2b641d8903495c0000d50db2c4b0241e7033f5b3598040a86c19ef5276b22372a447367853a5f625089f40a802c0e63be0574d10844b97557c1aa6f0398082c91d3efdc9a6612632b0a938c1dc4fdd06464028f0bcc3c0ea52f1132f15257bbaa088713a1b935945275a326773f09b7f10f1ca97043e90ea0c68c4d46b4ec36f2ed074ab590b33fd2edca93e57fa7b7e794219cb20ccaaf9b8455d97883b6d35af9fd9326c0e325db59167bbad98e9afab9d5ef81c249f064dcc031d2b0edcb80919a4862d468927a38f0ec37bbd6cabd7bb1a930c3ea0edfc9c035c426714faba69681e71b91d41742ef67f272b57e16c65986ea01a4da9113489f67d8a35fb0c91a219785752456977d5fb37b8e4be76b4a5fdc6f4c9ff628885dd6043292fe23722ab91964f2b41e67181c46b3fd4cea19440c132e33e132755ba6ead2ae9e5c666b8678b6c92e24e0b89c6133f9445715ccad8df353827f9126c94d8a10b2cbb0105b3574e2f24a0db7a586644c21d1ad7dc6a3c96bbe94018d9bb10c0cbef94dbd3cfa831e45a74bd7b43f6d94f860bf1b9e90801f27ed99cabf1e0fe392c3736789e25a207912af751ba04e48b70386432ba996d805cd6ad6e88e702ecfbfa85831ae1bfb79aa5354ed2da337f5a41745db18fb849ee3276e6819188139ea65e3db190c41dafd859c961526f5b3d90142e05ce2694f29ee78c43295625ce122013303e232e7c10e5924f7aa17d66476ee5174cb8b6406959b768105d82566ddb4609ebafe10ebcdc33443c51a23f9523b64daef751fa846e240c31fa0b2dc31d3e22d92f9779c657373f164ea688a3967cb000e927e473ad1237fa883d678ebf6e9840097c41036f3f2e3d0a50b148aa91938d593a95526461bb230cef096d3ea2b61f1a6c9eb827480869cd1987f75a1cbdfd9a49fb9bf34f4c1754fd4ccdabcf1ea4d3e983e18d9409233b4abf24cdec20128221c948f0c145ec8f4f5c0a50329dcf9d51e51376c6df1d8bf3b99e36eb13751725177d761cc90ec0fe8311a72e268598c2d0f6ab31bfa59f3d67b9d601836d3b41848395c201b5ad14e6707c0e43f81f2d6651ab7832ff7c761f3962a223fa68bb06a60b45a89e4139e7e4e9379bb8bfb76483c0cf7c24fd669d9679cf1e06431525636fc104872186e739196d8f18294cf26ebaf049fe09136a8e2456b4b8802f42666ad496c17f098d19063925f9bd49d3d688e5edc0763768db201f96dc68c11b27f364a2c2aeae61e41a0196f1149808cb814eedc02bcd514a47e260ff91695a4aaf95736edcc7a86a42e496a49bb3c3d569670cfd5d7f83df440a5f50ec7bb96773f4c41d4959bca919907105702740ecc777f71a05c6c3f55d1bcd1b4448f5eacb9e8c756a53c307146e8682d3db174c995e2582bfa5e4044868b86791e200cf702725dc0e335cb29c638388e11eaabb51a1afc6ad6987cf8dacbc9cc36b47963caa811718a224fc49c9921fec1b5f000ed6d38c7c5608913aa011a9376eb9d64a2211dbcefd44c1b01d35995bc5f89ac44307826062c821d97c20dbddc6ecd0aa890316ee31bb8fef9754b3c3c6078fa2729891e38aee6fe0dc9676e5694a46b6c8a57fcce222e7c2305a8a58099daedd7fe02a238b8214ff4dbb72ec16996cee853a50a56117b81fb998b8fc5fc87dd1b3ae334dfd5d5fa6598b8f48ba6e9fcc48a572e5207fdb32f54d0bf36c1847b1b968d3893b7e8bbc6dab5bdf5aff1bb95fd2f6dd04c77034d38792f9da535e8fce3c6d54b191d73e9323d74b2d0afb68dec0ef71cff26a28712d8f4fbcc0baa08f7fa2cd953ebe116e17a34a3685dd1758350ffd018b19a15ae0e30d5aad781ce32afe7ce5ce9506de1c841c915a806d6757eaa5fb6e01c17e945eb39c5960cd2427ecb15f498fb28194e4a59543fbf0aca17ea9fa89467e397d8fc7160aed6169c7d022eab9e3193fc6bc00c984f22a0f44eed71e929c27fe1c07a3adce0de6c6600a316baa80fe490bf894b952834fadb7a346b11f9b85960c158a0d51af7ee5328829f8b9cb7f05d35129087bb9398b8f13c120a9c13ddb77c920bae7cd89c91e643d3614b6db34266e8d5f502c589aafdea32eecdba4f8519d6f8a1abf40dbf9f637c12e4d75e044ada812df99d3fe6e9e2152e724dd73492d93b0555c4585c47369859b7ccd61871e776fa316681cd4596d6b785f6e5e8379ab429039726f78f386e169b75de8b3f4f162d322401b4d705de98916a067508ec6a5b5ef02fcefd857c3f362aaf62a46f579eef7068dd4d7d248f64ab145abc3f924795199d7ad4283ed912b3c0b815c537a18507781676b09f856076dd4422f53599d245ab7b002ca621c9b9cb133da953400bca63b463e81422fed9918a490e4c94cf85f141be8bf81f784a5ba85c0d07d8a607575247820932b19effe1efaa65e34425789275bedc81be5a50973e9b97a9db5a2ebd41c7a94cb1fa0ac956fab4adf770e6341faedb4b486c48ddfb33deb162af9e36f39f1cf2ab07b917e90e76358566a7d2a4b43fbeacee5af603288a22fceb9a84e4176f63e73ba183991b03fe2aeefb772ef1055b181b77fbf4ad38efe8c9c342278f30639bb50fb700f74333ecc0d5995b1530addbf7db0ff9a86c809f3ffb823e5620cda8ba3c8b6d84499382cf2102f4340315578e7922c7b963d4ef6657dcd9a0b97fad4ea637d74b305f35270d1d69635fcceaca2593e307cf102f4b7b489162b166665b7e42fb25c7d1989aa3652ae20bfd6a80a8ce0e18c28e6fddc334fc04e34dfcdb43db1aab5bd7fae2ff288877744ecdd6a865e20e95df30bde74a2bd7891c30b02e399ad148d5e80d71a0cbbd92d05032f3ce0115bbd7f428ab5722cfe205d9b50adf547db3ee62701c0550f1d5efa25f0a623fe8a53a462c6ea62ac4b4a7bf8138c9fda4f46e7fc40f729a25a644489638a2c400f1fc7d8af2d5b517dcdb186d0b5d17a3ade848602df5804b15be410ef0c48d78566837b243719f103dfe6bfd6667af844eebe4ffc922f01c99c4021b31e667d9a9a1b503e793ca68009bc70e92b70c94b328f760a3d32b4d44187e1d90f2798ebdf12ab3cf6f0666a0e72996d0a0b8836dc59938465c77023c83a94e0b4e5294c0818542687a08910e13269aeafc5fad75458309fdca47d72300704708fb9522449bcaa4f5ccde37216e0cf4d75e58428abeaec5161aa5ea1bef85bd07c78147580d82f0af80c4329cbf2d55f263495ef229e2937e63f7e78b9f1007bd41acca9c7af630d272f125430bb47606b0bafefa7fb4c4e1b207f030326ac30520765d5bd0b61759906975120b3e08336437e96c801e2217d42b43136b8e933db71477c69ae7b9973a99473629e0b11479195c811a65d2ef2c5b9e51adaa77477707c67de66a174956e41d2e8aaf0395f0b2f84867ec886c8738625c33f236670b692418b3e186a2122088d501ec62bd91d478b5f25927cc36ddc3994b192e55193b99018b87661db7ee0702a2d1115f80e90731868ad0bf6509b17e7e4f6cd5c28f0da64d81fba39af090e2368ffb15859909b1597db71e25c5c4782b9839a2e6ac7d19beeda25593a8e0df11908252d38765d56bd1440767a11f3c8a66a9a64db3e541f4abea4c749bba1cb297fddd09a53453f427681676d30437c905376eb84f874424215481060b04bd6954ee320524e9932b35196d6484f4e03114fd6859f7f0ab7e828673ca43813ab81c7ac5fb16a57427a938ff79f03542ba9fea22cbc1a1204bcc4baa926d06d892af898954fcaf5883ef149ad5e70c634018baab784403856bcac36cd23ed14701248c962ac474cf9deaf3f26daa375beb1c3594c94c98b92194cca38e8abbb318dbcb4e830f63d600e4ada35928750f3dbdc8d71227d79e1152f10bfba2e3eabce77342d3fae9652166a91ebaf9862b25a8d915cfc1d6623d66f4bf88f25aeb4e8dcb63ab8fd0e3c3a87313ee008f73e5c4fb65dd9271a52c0f5ca542a4cc45228be3eb713779d5262d757b670c3c57064903d4d6b1d046df178dcf2a73821453dc20fdc6b0f29c4319fc353d1b0b3c3d8ab89051038007beb4d69e6acc861434fe5626c7e5a488def944129926a4d784401fd79a2d049a0cff9309ad6a4d4446d6749255c8698783b0e3196ead588008d5bd24d7b96eb73712942667d3280216186be946aaeaaaf70fc5fb5e806863bd22273e8e9a99ea592041b2ff84269201677c592c8cdff563e53521dc0669dbb0e18389f24bec8634b4ed9c020f9474f147ca61775c5c0da574af6ea19211609ce21fb45c392d9d55c1a6e987310c12f83b57180ec66c812ac93820df76ba7ebd850c0f5b3f4b86d88be6fae33bf561808d8c1c6766967f33e90722cc5db9fa2995e120275a8f47396fb2d25425a86be4a9c3192e30b89e05a1ce608ad98aa85975c77bf82cb8fe98b5f8936bd7257f1c78d3d3f1485f488529d624a22d795ddf5618385bc4caa9be273996974170716b962e04cc24b79f136cb30f42c6e4162575e1188e537b5c5a63fcd5cc643265dac8422f242d2871668e7173ee8e2944c758d71cb012576ecfbf172a8f6ce97b8bb15a0c221e1f55dc9a3b97f598e0bc5b05da28a503be459ed48932023965040ea2946dd3897f940de9b8df21d9d33c897dc51b90fd3e6fcab01ca40970be8ae6a5b14b2f6eaf2a0d474b6c7df53cb266ee61e7f0227e0b0c812d974bb3dfc5017234a65cabb121461e12d5b9f13d5714133e2bd0d51d7c0f9d155b8244a0666d23dccdfc010f6b16f51b5eaad3a0e26f5b47d29fdce7c78200bd4936020501d851940ef836e388c9bb846e37fa83e3cef9316a6d244d8208f06bc4ebf9e929b3cee51726dd07835b775a688f2bc8b34865ed972a84db5788a727c2af7d47c13caa9e11f8632e7d1a7baa3738ba6fd01cf829588ee9cc0a72be71b3aa8fb310471cb6927b261c4344f17508af59fd65f348e5c0af38b925e9e25903bbfe5c282716061cafce3d4a65ba0af3b294b94b7fa66180de73082d6c2d3e8370f51b12ede8ecd5dc33868ae14fefb7c8001da263c157a4d89e84ccd457a91c1ca95a6c1e52854086b48fff1ff97c9106bbaf67cce2645562323d0557709621cb03fdbc2d8eb041ebfc8372764969331fa055044f41a41d1b01e83694aa55386af9e8a1587c6bf4735596a113cc6e614725688cb8ff5649ec3f58eb213c30e39d8fe6c6350c1b2a474fa00b85edaaef6471416af946438c031c613650a38ff72a6c30fba395c257a01503ba92cde6557e980d3d112459649744de6fc080895c891b68e46ffc447214f79046c42f21388cfe73f13b1d5bd84f6fb3461afeef9a4bbf9e1ce775ec13650e5b2cd187b8df6b5df8a85cf7800f528d1f8c55757170f8f260d92f8ae1db0d1b383c26d3af15ce23918ec690f2472f25f89965149547ba28b4fb14674f2f95617eab29ac980ab2f36fcce532562da984885d9aefba723a77573ec638b678becbd80aba85ed4ae77b6af21e146df3c13377480d0eaad399bf61bb1ba08a686305d6824b656aa496a6da643ca71a7a56293aff55b07fbc3791266e80593469ed081e981237133903cd23dbf7d0454cd52da625c95f93d6dfd28122dda3a0a47216757a8c8b0bf045e5ff494deb776b6efbaba413dbd7590618618be6db5b6d048100d389b2aa63b79146bcc0db885eb7d1be8d6cd88392e54bb1e778ac57da9758d9b1a5092fde6c5c686180989b7c52608fd2ac95fe8c441658861200d9c539663029747339e22a7f42a9b94f7e3e8fd0fb322231513feccac513744c345188e465ad5c58b0950e819383e41d35f3b56dfdc93f2581d28dac641a92bae199fa908a71dd42f44ca14f855c8d170f938531403c865ad1310058713dd4a0424e6381e96abc7297de3ff779b8d10ab2e53e696446e7e55ccf1fe70230634b04b815c5b6a9f898a36fe17db89ca28b52d2fc75ee4fa30440eaf79dcbdef2e7212a895a2e9777d244a6b31d359c9224afc61a12d21739caf0d3a411677142ffccba7a964999f6d32607f2db356e334559f3b6c17e14b465ea7c10b95e8bad9029e14b5b11f5f5f4badfff87e5f5fc95e5c73020227e48605d1701c930676265dc8e9e4b158bafbea4bdb84ef68ec02546abe422cfe1e0f26052c1f7ab208f386c6ddc701c81f1c4c7d20bff72d95eea889312cf0110f4687a8fc9f4094d6617267ed530ba79798e9a8a9511faf7be5ecf8b8578e3523519c0a8e1893551a58a09761a0238ab290780989813b6fecc8a08544ea09a5bf2fa6ff30e4bde0edcdc861ac383d8a315c7bcd776cd1b01523f8544bf3b75f63636255016ae15e3e95356aa52793f87ea725ad540f96fc7d1a89676fd61c91aa3aaddfd75aacf15abf6cd68ae4a59a8923f41f0cedd48f597b2235610b5f7801aad5859698a37203c399a85a80bd98183b76d6c897e59f5f613fea3181c6f1d8b8b6b233a3343971ac6cef8a0cc8dd92a221f89a9e30f082f0d3e61da4b43f8c06138185fbab50e2e10a22ac299886af82889688fc9c9d614f1219e4ce428af67f142d7931ac14a5ac9b8d641ce87c0686c5fd28c66d254c538d0a0e2465c2e631ae8c0d61d04dc3a45be30dd3bafa8c96b8e484299a0433e52da7cf2bb1945d60f551546db067de8f17a815322085faf947702008ed51a0d46ae307273aeae2c51d0feed90e2888db2f012bbccae90823eb97ce8b170f4c87cc29625860182fe08127aac4e0e9e58dad911be8d670ba75ffc07b4d062adc3f86914f4fe7b838bfa4788816fdfde1d59e774c0fb4744f6c7b36ef4b4e4c9eed4a36df3a1595b918388553ee7e4c99c815b28b31ebde98374470eb7e0def3fdf14df4466070be3a731dd95a4dd95c0c1292a380e873de031fc3664b4a367f5ceaba69980a3b2f0b87b0431dca359d32bcb8149afd74422b51bb26807cf4b0186cb42034483de875855b6df16493ded317cc418271ed0b7bfaef13272dca1c624df8bc1302a11037cbf4a5ea620e63b618c7a3287" + }, + "transport": { + "secp256k1Address": "0x1bd5514286f5602a6762b0075266379d29af1c9d" + }, + "ecdsa": { + "addr": "0x1bd5514286f5602a6762b0075266379d29af1c9d", + "claim": "0x007b491c0631becf043c6c7ef7378637d95d142f824c35795a185a263ad8a2de58274b9cf029a8b92db5d3dacfbae1843958aa74ac5d8fd96d0f9851a6e4a1ef01" + } + }, + "9": { + "id": "0x542191c95aa291abc9bc78cd4a2336898aafcce5", + "keys": { + "falcon-512": "0x091e74b3ebfee790a83ceb68a02712b5ee6d45b8a32e89580a793b1bb4b2b244b32f19311d307dc8e85ffeb516adf81e989a59c9f8b133e0b1a7203783ee645d214554207c93a37bbdbc46cddbec39f86a8b2e84de31551094cdd8de2c5e688baf695d4c68746b532f7a8726ae68a4ce092698dee27a4d3912292d52288cdc2f1223b6224fcc9b89336935e022be58de01e4aba3b5b53e0b4343a6af054974ae6c1f8cb9c35860442324b18b493d9bce9ac104153012061d141ce6381c154d50cf49f25722228c7f6b90aca65e09c590f6a868715ec10478dc341a41c475b8ef7d69daaa9704252e4b21d3710e0be0144e5fd45c11ec5dc0718bb02fd78eb86df829946f301ca778a91fa91f4a98b2cc1050751109c05fc698b10d9580211f560102082003872d5aea25ca5323664e8a03bb71e22d7aec1e0377546b0b95ae9a1b2dcfa42ea2d2e51fee82a4b2eb95e8a908266ff4cd561d89a53cb0541f434c25ba0a02ac14579eb4964801c07d3d1886fa6dcca95dd7d88c00fd43f20079eb991e0aece37345ea0f70b858650dcfa960c0c4f2205c692ed2edb1fcc5a454fc9c671c47ee06793f05f1e7101c88055603e1657a4d1606bbe8f543985df306cf9d3d446c4188ad8d5e2a67b922d9fa029938b2f5c7a90b3966232682c92b1c0408c5e0e89b51b764d4aad660a4c01698560da631e225db479ba0615e28c54ff474e18e48352b4b4afe1b605d968143729b8ac7a6888858adebfc20b34768730aafceca2d88dbcbf9ca116fc8ed56bc2e768e1afb04c4a2c55fae42987b98c355e6de4378e93c3e7287d581a3d22a6894a1a888ad4815d6d23256808335a4f1f51fdf1ee68b8582c03457c69f5887991030a63f031249aa7784bd07209a3213323af4ebccbf11edb2e73451745e7cc207584dcd0b2837274e40114ad064f8e3cb1dafbd9ea6cf200c212616a9674b4bb436e225d4624c570c284818c9028d7d855112e1dbbf068155924c817a213257fcdd0f310a0c0196a34629de2ca2982e0350b88b844e2c31120ce346321e86a92124b256dce0bb6c2d944be784a835757436a8a09920d8101a864083ba5fc70043442e2e6250a0255d93a9264b3254320b327149c8c61d047eeb136399f86fb6dd78000b063086f0b2efafc16d06feb03beac5bc323d1844633258a1c908bfc9d985a69812ebaed174143f48e2ca2bbb92ce37678b8e3fadd424612a100bf090582588230421f2a98e9ed75e298eca9c8374", + "slh-dsa-sha2-128s": "0xd54598af717e15dd28cda15d7603d9423246c1d97411c0173c3673ecc02f530e" + }, + "pop": { + "falcon-512": "0x39dcbd71333838a1b186f4b834ce5345602666220901ad06ab7c4a057463d7484a5a6ca3545ba094b0e7f08dfbd7028a310b261e634d8c3e5386b6b79a65577d48a2312c1110bbca1a331843a4cf82b263b86a27cf8a9bd2f58f77436081967663844b76f8eeea27ceedc290c2b17b491d58abf0c0b050a7ea3989da295da45507220a0da0851bdfc5a608587ab48d572cecbabe599a091098edfd9164cd23673f5acc3248ca4ff31fd41716d8a5b42ca676497c53602caeabed4c993589fc575af410c64e2d618914784ecf2e94a95c59756a4483ab175b0fbf870c8fbd48da72e2b8739896974c9e3cf32e8ca500cfd0e8f44e21b429ba720070111625c153527b07133b0419953cc29d59b567d6b36edbc6c1037298fee3e6ca6a7b2dd1919db2891b0a90bf6e0cac8995988db38695c3e828532245d54e7328adde53c821b83bd3f4fb7c7e12d1001416d308ddf274249cb139c93f9a78e9287e2f81fe4a24792ce1a825c8d355c36b56181c9eac5d787d8e7fc63c5e1f3fddcdbe7ab0a4c25271f29da62147c8ff22ec3eb0c7b71294128bd497d6645893e38d3f79943d3e87a804c46085d1e2c9def032cebac4963192c13e1ab7feed025de96d0183d8fb7b9df35cc0b339684f7a0fdd6c9097e7ee458911a5849bd6c3408d966f573e7ca1d6a555cd6e299ae07f1ef81d691f44f9f58e88d57ab026d331b3a01bcd7e6169f6d3a726ff42b0c74deacde2ebfb7b3c5e3ba30170741fdd9600bec5aba6ff0d244935cc747bd58f38aa220c43e912646470c5975dead86bcaad8d99c363bae7850462d9571fc700e7e4e9b086a6ad974f527757ac657abd5461121c0319826c70fc9b0a0e8eb693bcb98a5111164fd0c332bd5285abcc419439498f6ae167f54f56b042a2ec3a1badf1398bb04b62169aa0", + "slh-dsa-sha2-128s": "0x521c145259a720b9730b042d3097ee690e5eadf1241eb8eb7e73420c51d655f87fafca91e0b71816da824d7782f16a172be83bdbd4a21863a426a6d3c4060970bb545cc2fa76be56254f0d9a03d324fd7eb41e2ed9acb887aceb529b13d2dae268e03a11aef3ec6e9dd142798cf490ac96bde15b8379c953817052ff728af4704bfe539824fdbedc2057079dcda8121f70d246ac0a402657d77118b2c4db65a17947939b614bbc3268f8c52b684487a364f38144dfbfad8f5d5a2820b54d0d85bd31072670ef55c11750df831ff4b290955ea60022a3f2a7653b29e71ab27846fbdab5bac02841b6d7261315f42a2a4203f0bfdfc33542710268061dd70bc2bc9a843961a543e94a2841ffdd8ad869cc43b725c0518681b567fc08ce58fc2d3df3e41e4fe9ccac715ccb5674e8c505f4814359c19cf11290cd601747d4e41cbb6ed7b55511d14eb6e1543c57e081778fbdb93c9754dd1dd3f6f49994d06fb98deba1f6b6a8fcb3b2c951c83fdc889d94161f001e545a9df625768ad717497fe161a894107ee31b8a87dc847dfb98d37e13a5e11411f0d64e85072b97f9c83792feee61cee7fb38abac36e71b75b12b254d4b8598f8e39b5a8e4af17b3333b414bd18a5c0ffce5f1cfc32356ad88d994eb5e568592e18394cec3a2ea3f84db8159b5124de5a1c2f65e9517632ee7b8fb5fb802f31187cd6c3c88174041706657a94dd399b0f3fc34e0564b35465baca211bd638e02cdac34f57445909594acc0793a346e6bb2cf8cc3b94566db84d58a715008790673860d88c7ce45ecfd8d7cc666485c05dd040f6ed900af03b888630b3949089c064420a60203c97ce6564be74413147877a32508dcd03a863fa18177ee0da41743dac1cfea15283d5b7c00c4c9b3754fbda767b7288cd3f666581b480eec87740d7609c9bbed16a85fce56183d6cd7c887fdb5917eb0696bd1ec44e20ea7fd2ed2673d27704239b44ec2245436c981b161e7c50edaf4c3cbe4f50680b1de3c05b94836224b7f8885dd1704e09de3c912df8ae5b6e62120427084457222de70b7c8b03f184195ff1a3f55c4c02450baaa410129fb5e208f00d406b23b278a451b930ef6da291a71c1ae5f726d51de1f2e33ec9079113a99acbbf45008877dc22853c166e06a5858bdf2e356d9e6f9c6b9e89a40d4d09271b84004a4bf1128f8a26073a560c735800073434c88004aa6cbe9d86cfec2d5e9391c4218e9d0ba9f457ca10987e136f4a982acdbab927587aa031d9815adfd97d0dc368bd9e49bbb8fd2d90562cc7ade95a100f412e3879b1cfa405d85650417d1da81219e34c8183f1c9d1c25eb23edb6b77cb2ab7ca8e91b65bd547a77dc2863e8c1ac283fc2f9f96f3d34d13747d0b94454789588a52ced99449ed0845a2eb200ea74c8c57bebb7343bea81edf29567f9e3d1248bee1b8b15b3874126004ecb20495a4ce4d1d6be0b57506c09659bbb060a8b6c734380a49bf8c7c5bdb7fca8c0f43ab064a5b6b7396e73810c8a09712b9a8bc1b983f4a7313648699b5897fa901edbd49d0ed054810f9ab5b29819fff700021bd97910299364a9dcac74be09d09df1fe2500da062ba9d8f490c10c39f02b35f4ed7abd84b6343f616bc26c65290afd387970b4fee1a5ed5fc5cbfb1110f2771488ff5696cc7c346d3382b016935d1bfe41166f682633867e79d6b841a331084de0051eb48131166d93372b1a93b337b6078a2bc3ddfab7540a065ec19938a48d4436e6591b3cc8735abb5b2b1da2f897529552d1bd48ead4973764970815684adcdab371cc749338c448a10f3656961c9e297c1bfef2698fd0ec7eff9d8bf0a76c8c240666cb2d8e06a3d7cdd52443b2ce9e512268e5e674a7adf07f41452801a8f29dd718cfb3e5378140b6aa5593280e7b42205de7d6f793be9905611bf93114785f5664729f083b196e6252f9cbc16472374a74a7b1cdb28505c19c4d7fac54351ac699f3e523393d4e584f1a769a02891620f4441b1c4903d893a90311bfd6bd92c4969c47997cd5a3ff19bdbb6b4b3d9689557eb140a8647e46cc8efc1f3de0a00c2964956ee692e0452f1f36f35b20e4cfc275b3c05e62c9808d6fede592d3d48d08486e862a592d4f9268fbfe1759e88e0cda8a658aa24f088520c7d8e06469e214aaf8537b1857f703e65f8ce23092d666d19aa2472ed648e7c95d2105167d1611a4300d710a14f1216304b89259f64e2743a631663ffa6fb58f5f2535ae8a50fc3e604cae0a03e68927c875ac2e4ce13e39d3ec1931567998906c32dcb0b08459ddba45c3e9091e94756db6d618e607f0f480ffe882617d20c7c7b92ddcb8a3d5895385ef259262d43be024ac1a8eb46483470595269d5552cda738c2699d6beeb1485010b12875a6781c1435bd92d190edb82220e58af9a0ee0229af2743909823bc2ed4537be46102c57e5a12e07ae6d956950ac31f67dec7091db926c895a18598622f3e999c235e549d3ee515768c216eae349e160a71ad58de353d435178d42933d8da500a5d0edc761013fb242da3046a524ae8ac319b1b66c3a115c51deb5cc50a6c0ee93201defae6100f88f7375b75e3cd258bdbd2427194cf12c80c878ef2ee4fb9cdbe22e3aefca4b23f184ec5e959f313e1863ea9e68e96e6359f87a79e18f57a31353a301b480f2fe7019de7f550fb6c2906f552110572750b1ee59d8cc3dc07fc4c24f577e7aa46d4a2331fd67412200d0222c752a499948f4105317bc030ede13f3b778815601a644b21cc80835f8730bffa15f0758400915d0201986b069979746a35e64b09eeec5ac4a69215e960c4fe44c78fd325b32cfd3d94cbe25ce780b134e613b57e5d95989d048994bf835a32e1e07c46994d9a70d9656f79fe4a1fc8e646810258aa1cd181b2baf5bc5665f1139ea729c6420184f3dd4359861d7004fa1f279fdaacf9d16e679628dbd50fdc0204c0e6cca879dc64d76e61f28ccab050dd0d5743b07f7769842d8d79b343d2a0fb07d49eeaabb7eee776aa1d27de5f087706e0708c0edcba1afb5550c06342c8c6095bc3a5f480e706792b95ac0bd054eb6a2397b4b1a5c090d85c5e41bd9931ac1db34f8d779bc23eac3eae0df82d239a420bfa382f3ec3f85bfc5ab1bc4f8a43dadeac9a804ab19edbb6f01b71401c0c8edf9016d4671d594df8abc89d79f481e7319ade86bf7ac7a150894bdef026c651f8833967442e4864d8e95e769a130add6210f9c1cb75aae97a45ae97a8380141b4ca46e44eabb7545a3c6d7644636be529f4d5912b13e56375e56d9ff99c118c25f397733ee25aed8ca14dfcb0a31cf52fa17194612413252ab6b17efc6e80dd4fd6a1bfcb76da98b0a1258c4ee3a0d27a8db8b76fcdde87f972d0596fce4048dbc69f467a0d605e74f6508d82d9a2c1e4d088e3e5b5feb248d950ce2a42099747c03c5a7d376336d988606aa057310f84ff7f6e34dd7a8b09564b77821467831f3f529e6db0ed523682651a92f373de198226210fa5fec2c6d2c104b1926187c72c65e13116c69d4b733bb9f226d919b1197994ec08e1d8796ec2a1547858c13b21385faf629598cad1acbe1a43f3efdb986924c2a588dad6a59c776fef5848279f641b1c182725ac4083a221b500e0830b203bfe633bde58c11aa8902de2200bfa0604330e80893233e3c5ff8f4a3bc61a281c54987d95997d6ba8eae3781a06badf0096398f466b9ae1e8e2baec328f75e2c2efa950b63e4c699a7fa6c4f523a87c1919126ad29ed3fb53169175a680e0e0a3216af01a3822737c70551e4fc4d36958b98cf40a1212985093c016d3293e8ec6e31019c3da933d8757e32530d4cc835cbe8e7772f75554dd4a89835d1a96b04927e2d906fd34d3b014d94d58909975eeaa72e6199abf69fc9d8d414c57cbb62366b2c8203cc7bca9f02ca1e839460362817189ad5dfe1c9e114bf489c5562c5ec272d734ca1a9911fd168af5420d20e33e6b6684979bfe6cceb455d2d253f43d38c92a04401d972cac21688d043c39823ad288b48aa4839bd62ffa65e09f23a7e426582b2a22bb396333605a8f333a074618f687acbe66a7d5e0f7fde115e65ee1cb6ba5eea6e7622d2230b51b5bf7bc39f9abe1e3cf2ee72cebdaced3ea88fdd39f39e312d5dad1deb7bc6e0893eb462025e37318d030aa7abc4c022c8dc93f55342a682a40331aa4b32110ca1ff9f973704ecca89454778646aac50e8b84ae68c48b064094b670bb63d023b119300f87c41e7162fa997ce390bcde215b7b21449a98502e3e60dcb19a3dd399a9f6a89fa2915e500e245581b93be57b6a9038d2c5fb490878c7a9129c6728bcd5e1118a8897cf78b87d0315c65c0e9ff1af11ef73c6ef0ecafa4c697ecab30d70ac99f6c760a8afac552ac511f8ba960440c0fd05849964802bf06978b3e14e0dfb0fbeca482d076cc7545c9aa5c8c09f933aec24e8206e8b18565cba250d898632b5d8dc96a01d227826ed9ae6e3c6a2447799f663bd5cfc65024457bd2a4b6cb1de875428341788cf75ad173f489403d1bfec763fe4a1279ae3eadea0c6b07e0203b8a858799a7bb9272cd83dcb73684570e1590f555d2daef868913f2b6706aee008da58fc2edf8790f04c6cd46af8260ab2ac601d22accf82f4322e29ed508d743d5db7b88c0ba91606ca521922dbcf324fa2d34b15c5c8a63b28395886cc09ee8db58251aa8c8ec26cf0c1a3c5ddd6c873d05a5a1c21ed4f9d6df19ce156ec9870788d7b043480317cd6409c300bfdd6f97120dfb6f796bb17831bf269554bb115f70954c7d0c4e1ccb1aadc04a55be67652b045fac75d584af7a8474dba6bd9ecb8cd554209ad349d3adf352ee936129febc0017882c353ccfd10d06e49d4602c6c2b41b1a3656bf1dacc4820119ba3e3875282b4b91810199a061ab69730dfa0e304b668e4ce05f8b9c8d05e4f2fbd4cc3fe035ecb195e07aeb6e0124be68b80662b1e5136a86e30217926da3428da82d1e409e6c740d88938ad26e9fda827a9e5d4838d6dd32025b0c0fecaa660b40d77b9ed44c3d396593771058b3ff2a52e16c70639618c87faa9fcaa7617097c0c404e33cb7e5e92c58f11b86eb02cf24d7df30472e3fd66321bb09b8ff85313145f0a899e5991967797dcda0f694f017f18d4c0f87228a244fa115a9901ef268ebdd7ab9a78c70f88d338d1bd8d0da80a025ad239080d4d531a6ddaa2502571e3ff7d87cc882effec1f0e1a908f92e5335f58db1e2e61ac2a227d24136dce2c6f81f8498717ba6a806d8c3ad4b365ad74d6c182b36b1d63f6cb0ed0df4f0d4b4b73acfdf661a5fc8071841df61629f9537435864fddccfcbfd8b0e0cebe69c88122129f73e5951edc298fb079e5532ec47be6b9ae1b7edb330ea7b0657ab751546a871351eba060a11587fa759459f4f40cad1268ddc2868ab01724444b522faebd336c6486eb10c6c1957d5e1f7c66779dd3439da50c117a336d6bf794609f325c2d9b5042b758a3ac474e2a00a458a4893e6f379d309d8f4c60cd7ddd1058173daaa8c52308411fd1c65082421f9baed6bc2ebcec41833d372b58f6279a0d747c3902586130fb9b94ff6501b8e0e1153f6f304bfdb18d27c0024c21d04606dabc14d56d353b43a3c5c871aab7c2d9c5bfb36e32d4aa804c07f115a0f65c2b93bdd77cdfa789295ba7925985447d52768377498e97e7d5775d954aa528f7cbe9735a8e6640264a87cb910977b9c93d3345befcd42db82250643db12a5abbecc821eda82441ffc2eb6e19383698fa8b1ed9204c56d9deeffdc7eff94ab8a10f2aef5e33a84364e2277932ad8bb56deb939d4e76f4e8d718e862f8f7ec79629a3940453b76f7bd761d8d4f014894ae5757688c8667dfacdcaa61e6156677d89c0a7f52f9fc8ae5081812b093f211cf3be321f798a134ca4a0500dca0274fe06f113e427ee5974b03a6a388fd2ce4d59c68b1f408f48d982018a8375f4c8140c5a0a767a740fb5572a6919ff9a54d14e37c2ad05745779269839a3c3f510dd23839d7ecdc2e26e158bd99faf33f0884ce3f6f4b2f8b3fa91cbd93ac24bd3cfa0586096d803c54bdfd9a12d935b6c151e4667081919271572e11a4225af403c2e7c6129df57ecef56293527e5483d29b89febc2a71b40ab6959baff90b731cecdd75c870c8ac2d5a84ee778bf591b82092d44c717b365b6194c2bbcf4223d6fea6dc1a681b50ec43aa934a9f25ab67f8ae8c5a5882b8a06b5f765739fec1f0a2bb5483c5fdbc0dda2627649b9cb9883cf2a4d106b7fcd6b33aa2ece34c36ee89ab9aba225a41e5eee1c5edb96304b026a006dc95098225e6dc33d32e5be94b895f2ee33ca3d90dfa9adfaae740ba7cce54f5eb8166bb1d41a7604c44aad7f5cd22afafa21238b46b8ba390dd2ffef01e390c86ca5b610d0a33dbbbb1166dc0ab3db13d815c24dc31bc73e6a1d0146e6b7a6c0ba3f852ac74c7de4e296fa8a869cb95d9b51d49ffcec7f374512c06070634d0859e4a14621b36ccc2181143e9f55ee25dc46041e24ab3c038395203319796ea4481c708ef17337d5377a95644876c6f607d096d437347dbbce02323163b4f6a595e4a198e27f51acc700cb9ca0e9ab057e9aa74926c7011d9537db6ec099f85eeb6df7c428fc10d16b75222c3f31117a1c34e2687cc3a3a18156ddca9036c0868b2285b079c7c8d0010c4e8cf072616d1c52a5be190f5bf11e08d166d8fc367f39349a2a4f3042a8ea0ac9e576c7807c187b02c3e98d26d2de68af01e02a8d50a676dd8d27cdc04e90d06aeac943e0db363ac3f14bc4274a7e529a657e2d84753eadf748ba382d0a995919918ec54c04adf41cd97b478d0f3835abf132647ad548276178daccfa32b2152c3f657ffb801300a9b333f460a1376229b0b1480f7d111652853f1be7afceb51ead94f580724fd863221985b2fb5cdf75985e30db9c752deef322ce3c17fa781cb2e7dee7a5a06e8672c360c72bbb7b1b7d8cf58f8b9e4ec46a2fb4027707d9c625b679c1b70c76b421bd1174559623ccb80fb51e565a6033327df15729923c09a667e656319220c86248334dacaf8dcd5ce39d349808e755bb83a02efe7a76469dee5cc420f3da2a63cc02e6e0c925463c06b71b37172025554219ecebf1df32b186258f3cd90e2af3efb51ee5e28140512044b82e1a826a8171fe36d5c64ec9e8d85607a2d9e31a41f2ee3a5bcb6415d90e283b91f4f4bd4245c093a20607c46942678f0a601c1e4b76c001509bd447e42ce210b248c1bdee13d75299ef39e38f9295046a4e03e00c13ba456ac66661d8c0e59ccb1297f9a2efc8153ee242acbb5e560096c54a9528b00129bb78a1a025348ff32889eb568ee0d792e2a0123cfdf52ce3effb3e4e13848bdb4f54d672a2a7795bef53cc67d7fb2db3de4f8015eac4720c24280c67e44e8b753488f7d6df4a583f9afaa0a076768e2f51eae65ab98f8e2a87b9dbf666e09b118bb7c98dc0a563e407d4016536e897a484dff0e3bde38ac372f256d435daaf2f081ce3029d9d124c1d81da72802a0c47519d5fa7cb6d8ce8d1ebcf2d8aba7a82849a53b76558171d91b18e9d82247ae450504417a49bb87dde89888d55970a50f177a97412e107bb20111a2a00dc00f263dd7a616b1fbe2a6c7ad3540cfc80092ea2db2a120072ae60086399efbd0bd6f8281a00b94779f4f7eecbcc788bd079d27c761b8a30df84f559badd67f25fa89952e45d81542eb18be3d7bf4a0642d4c7cbdeb4d81c71483d73e10d9c7206a779be0b877d5ce204afd9facf25bdf20aac090c29534f75f1617e03bb02d510e4ac0ba783ff78dbfbce7a2378aa6d413a54ee0a7e69bd13d6b686cc38d41d91c3af9f70c438b7921a5e0b8cf5eef7aca22ecaa869b5f33533eea63ff2fa0d277d671b9f0bc73d61d468ae36df6719884dc41eb78e8a2352a9b4053639436078a5f7063819bd455ddb74249918ae843814d58e2cdd381372cd4903d008b321b2aa387fe3f879e61ee2f036fe9c13ae1c6b053ef33c436a7ebe43dc90142ca7f21e1a7a303e8cb58686b6215d4bfef753681e86cb41620f4741a581d0be7b6983f3f2afe5995680585b818e71507fdbf56e6bc2604bc386abb52052462f5e0372d2b30d895a71b984306401a6171a08f042c98290dcb4bbd6ffc18a96da23460564f8b3ea1a5a1f6f11611e566b38d377713132d06c5fff00b5bdf4b28ee96db180b44eb578160de9a1b21e8da9684f2beb021b2e36cc6081c1aab91b882f3029631da2b579bdbbf1819eec301b7a39c950d28b07bd2809816da3a5cde2b69a1c8079d7839dd82f1542e7b50ef57b400fab85dded7ec3ec8ddab405034ea5beeb81af13c31a9e0f422ef5c398eb1189be48d7585900454b8a86ad1087281548a8fa67cd08f678893dfb54c6a7dbb130ea4306792dc0c35766f1b3607c22fc3814cd3bd13810cf670771e4800ff210811ef525bcf921e68df5f388333e88c17c5b395f66c95561f41ceb0f9b48d537196a13d63c8d35ffc1f04fb7c432a6a93f0fd6d58a0878a70975dfa1e597b7b7f72ac1706124fef812f837623764a1b07556e1c72ce28d1d53a8c128df8fa70803b1817fa6634c83df6997c3781025c7b0a4cecdc8a58de4c175533a4b43bdd23d9e8d6081f78f639343bcc3ef52b3a1891083e4abfc1d1adb30c6827e587a4e50c255357750b77d57b0c6ac33923cafd84afaae2f5a955baae7755ebbfe47e7792363a3090bf7dcbbf5a69e64556e5dee356540c4e21d17e281b2c6f34f993c39066a4d3bf954a0ecbeefa0c5e2d2de420dc28e32f90dfa841fee7adb56ab3e3b45cee81c811997ad51fc5b37e6f69e1e1837ea597b9d36a27bba9c09ff548a79a8a48752141177f327d86aea73815233770e6013677bc292d2d11579ce5b78eccd552d028bafddf917c82f0ecdbf3ab9f9ce35bfa1675d5d9335af32142cab7a39e96a0972f8a913e10cf6daba424350c9be012acbf31ef63ac52c633a52fa93530b6cca10b49d63aee45d37e60bc0cee6dcddb827ba673fc4109d84d48ec95d735f407ac302a2853d28b7f0ed73c006ab469c99447a9d85a6ae2dde5f9ba3c140d6c89b0b06974be9531aad880b593281ee4c214a44f3ba62aa87bf935d9b56c38d17466c94e52888c6da549a59f32279cfc8cc890f6c878a0855fbb989b45c0246a7883d4f29134beb115e28d182d9edb433262f23ac4ac193e8e969e1f335116142469c005a5e648a0bcc6be56d37c4b9fd45ef0add71340d4cf38738399d6610af7f29f5529c1358f99750bc1cf33bd84858eab169f5926984a71a9b24d828939758722f2098060e7f4dd6800d759f9f13816b27f5b5f20df90271c600f6b272e55d271d2ef47a1409ba7f4e7fbfbf03513fb001ea0f683e48c0dd3e90bdfab39b45fcb9ae74ee94351e253533d050ca3c11132405c803d1f748c7812210d44e530799164e46f91c2ac34aab21dca67357e134fcc69893581e9c4bbf76c7a21b78bf8c47d21b157466f534764b80dc318cd150251e394255c37336b60deda55b22ea7b016aa695391f4fbd6626420592f6b2fcebe5809cd2bb51359026c98a2d5f053da177b33880640a76b9c06e4110ee348acf29067b2307a42cc20e456786d4e887967502abba77c8024e22398de6ffdf6dfa063ff24f96dff0d3b9bb7bf2d3a86e7bb9961b16d3b2ac3cce86cf8a10198f74c54334e87a36130867594adfd3e8a4071a06b88852bea2b24e905e8511d3143a8a553aa6b597b5864d4d4818cec8202a779983b1d19acda1e02286cbfb5201d42dbb7bca128e5bfa2a52866c5ab5eaf06ba029e8cc6c1ce4a4b95012d62093fa42796b4667e62ea9b50ae29b51eacec4dd3d38e1168e3ba37511a33767c9e9aed675cf1703f3e7f34a9b9844d7b4bc0c829b1e4b6c0f2556eb17ed6fe6435caa6486cbaec9380e9c192e7ea6de0ced854be9617ecd4e2ecbe968cfdefeb464f79bcd5f887f83b4df3881856ec9cea55151a6d41bbc96a98882ed80eb188bc92ab8ae1dcd362ea000ed9ad00015d0f220106f19e0f2bd85ce60272f94b0dada4460c86ad21daef7d92ec09825a1da9ee2971552f74f906e1e5269652a95ac603dcfdfb87bb58ffd82f6f7321a93e5623fe5ae397d9537f57f4c443708b8c1ea8e5a8e96ae9bcb28a43edc6e2d27a4d15c34740c289f4149812fa76a5ceec66f8e37ac0e2c841cce578576172d168637454c60374f812450d052751ff52ba31a12c7036e1bf52b4ee5f41e9e84e6d0ea07ec47d975ca64a95f73eb1cc0db12a9fd293b542e5b7d462e5818ea4e471ad2d33796f37d6ea9044797f7f3aae37d201a792401d2a6457d7b20e2f53267ed00874cfc2361ff4051d720544ec1471b007f2b8db2afb397eb4d37abee371b5d102c913bd5f701e0e40bffc9259ce2ac481efe7a72be57b0c48aa21c83230e5c63e2322d71c03e53d0d3f8330496480d2b6dfbab567e099a4bebe732ee97915627e3aeec12bc29e1eaf9188876c40e6a7d5daad80330ce5b66c40835ce6a174ed7c020627a907a67f1238eb8ccca73b56f2dc441d77e903e6c8676d19dd61c50da5c103c2324b98e2e61f9ac3974e4102d8f818cc194034bb4106afb9c29f027532f1c90ddd3d46d7d0ccb7e7317fe90e080fca7d765bef7aac8830fb1590aeb38cf87793cae67876e5d5ed609a0f2dfc6d8ea8150c34f2a06db34e4fc1184acbbea91ac693c95e6cfeb20337159ba6b71255cf4480a9f30dc1299b7ec9c42c126e401531cd2608e749595e8869aadb2c65a3f5f7bf2886b054ab163281a7ed853db9e25c55f1a6c402f4fb800964efa8e81c4b1d554b28ab437a5a9c629c5ecb9bf4fcc500ee92a43b88603a5e5678d6025d3b33a81a28f6c403644b719d3e617ce16eb7af14806c78b5308232a640552dcb6bad769dd88316456eb412edb0490abce5251561a8517f30cce097341b104296a4528047875e1e97040720fcd6f355c4f04521a95586ed20dda8381852c45ff79eda13a2d0df69bfa87385ba506fa" + }, + "transport": { + "secp256k1Address": "0xd38cb62a38c1d4a5fccef6bee0f2e177ec3c9aa2" + }, + "ecdsa": { + "addr": "0xd38cb62a38c1d4a5fccef6bee0f2e177ec3c9aa2", + "claim": "0xc438df8d13de59d18aed2695888a4fde8a3c0ca9bb67f36d0f5f44d2cadb0f5d2f586e26ee94e4ddc62490fd00e467915f9a59e97a1602bccef573e4f0c6524200" + } + }, + "formatVersion": 3, + "chainId": 2800, + "bindHeight": 20836228, + "count": 10, + "registryHash": "0x5c6f09a44f1b6cc0e2264c9beaf4496e5fdd5bf8ee0dc6571fb5616c80a2e900" +} diff --git a/run-node.sh b/run-node.sh index 122c718..47bed77 100644 --- a/run-node.sh +++ b/run-node.sh @@ -49,6 +49,7 @@ PATCHES=( "0005-aere-eip2935-futureeips.patch" "0006-aere-pq-transactions.patch" "0007-aere-pq-finality.patch" + "0008-aere-pq-aip22.patch" ) # --- locate self ------------------------------------------------------------------------------- @@ -143,7 +144,7 @@ if [ -f "$REG_DIR/SHA256SUMS" ]; then if command -v sha256sum >/dev/null 2>&1; then sha256sum -c SHA256SUMS >/dev/null else shasum -a 256 -c SHA256SUMS >/dev/null; fi ) \ || die "registries failed their SHA256SUMS check. Refusing to run with tampered registries." - ok "registries verified against SHA256SUMS (7 keys @ 13,014,000; 9 keys @ 13,600,000)" + ok "registries verified against SHA256SUMS ($(grep -c . "$REG_DIR/SHA256SUMS") files, see registries/README.md)" else note "WARNING: registries/SHA256SUMS not found; skipping registry integrity check" fi @@ -191,12 +192,18 @@ for p in "${PATCHES[@]}"; do apply_patch "$p"; done # --- 5. build ---------------------------------------------------------------------------------- say "5/6 Building the node (gradlew installDist)" BESU_BIN="$BUILD_DIR/build/install/besu/bin/besu" -if [ -x "$BESU_BIN" ] && [ "$REBUILD" -eq 0 ]; then - ok "built node already present: $BESU_BIN (use --rebuild to force)" +# A binary built from an older patch set must not be reused: a node built from 0001-0007 stops at block 20,836,227 +# (AIP-22 stage 3). The patch set is fingerprinted and a change forces a rebuild. +PATCHSET="$(for p in "${PATCHES[@]}"; do printf '%s %s\n' "$(sha256_of "$SCRIPT_DIR/patches/$p")" "$p"; done)" +BUILT_FROM="$(cat "$BUILD_DIR/.aere-patchset" 2>/dev/null || true)" +if [ -x "$BESU_BIN" ] && [ "$REBUILD" -eq 0 ] && [ "$BUILT_FROM" = "$PATCHSET" ]; then + ok "built node already present, from this exact patch set: $BESU_BIN (use --rebuild to force)" else + [ -x "$BESU_BIN" ] && [ "$BUILT_FROM" != "$PATCHSET" ] && note "the existing build is from another patch set; rebuilding" note "this compiles Besu from source and can take many minutes on the first run" ( cd "$BUILD_DIR" && ./gradlew --no-daemon installDist -x spotlessJavaCheck -x test ) [ -x "$BESU_BIN" ] || die "build finished but $BESU_BIN is missing" + printf '%s\n' "$PATCHSET" > "$BUILD_DIR/.aere-patchset" ok "built: $BESU_BIN" fi @@ -270,6 +277,10 @@ export BESU_OPTS="\ -Daere.pq.anchorV2Block=17047600 \ -Daere.pq.chainId=2800 \ -Daere.pq.hybridRegistry=$REG/hibrid-10.properties \ +-Daere.pq.identityBlock=20836228 \ +-Daere.pq.registryV3.hashes=20836228:0x5c6f09a44f1b6cc0e2264c9beaf4496e5fdd5bf8ee0dc6571fb5616c80a2e900 \ +-Daere.pq.registryV3.keysFrom=20836228 \ +-Daere.pq.registryV3=$REG/epoca-v3-2800-20836228.json \ -Daere.pq.schemeSchedule=17047568:falcon-512+slh-dsa-sha2-128s,20746736:falcon-512/32+slh-dsa-sha2-128s/128 \ -Daere.pqtx.forkBlock=19900000 \ -Daere.pq.anchor.minSealsCeiling=$ANCHOR_MIN_SEALS_CEILING"