// AIP-22 stage 6, the DRILL for the live run on testnet 28001 (2026-09-23). It builds a registry-v3 epoch of THREE rows whose Falcon-512 // keys are generated here, in memory, for this run only (drill keys: never written to disk, never printed; the epoch names chain 28099, // the rehearsal chain, so no record of the drill can be read as one about a validator of 28001 or 2800), and has ONE row seal two // conflicting PREPARE messages and two conflicting COMMIT messages, with the same code the clients use (PqAnchor.*Message, // FalconSealScheme through BouncyCastle, PqRegistryV3 row pre-image, Merkle tree and registry hash). Everything it prints is public: // row pre-images, Merkle paths, registry hash, the messages and the seals, plus a positive and a negative control of each seal under the // same verifier the clients use. The contract on 28001 then checks the same seals with the live precompile. // javac -cp "/lib/*" ExercitiuEchivoc.java && java -cp ".:/lib/*" ExercitiuEchivoc > exercitiu.json import java.security.SecureRandom; 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.bouncycastle.pqc.crypto.falcon.FalconKeyGenerationParameters; import org.bouncycastle.pqc.crypto.falcon.FalconKeyPairGenerator; import org.bouncycastle.pqc.crypto.falcon.FalconParameters; import org.bouncycastle.pqc.crypto.falcon.FalconPrivateKeyParameters; import org.hyperledger.besu.consensus.common.bft.FalconSealScheme; import org.hyperledger.besu.consensus.common.bft.PqAnchor; import org.hyperledger.besu.consensus.common.bft.PqRegistryV3; import org.hyperledger.besu.consensus.common.bft.SealSchemes; public final class ExercitiuEchivoc { static final long CHAIN = 28099L; static final long BIND = 1000L; static final int COUNT = 3; static final int SIGNER = 1; static final long HEIGHT = 2000L; static final int ROUND = 2; static String hx(byte[] b) { return Bytes.wrap(b).toHexString(); } public static void main(String[] a) { final SecureRandom rng = new SecureRandom(); final FalconSealScheme falcon = (FalconSealScheme) SealSchemes.FALCON_512; final List sks = new ArrayList<>(); final List std = new ArrayList<>(); final List pre = new ArrayList<>(); final List leaves = new ArrayList<>(); for (int i = 0; i < COUNT; i++) { final FalconKeyPairGenerator g = new FalconKeyPairGenerator(); g.init(new FalconKeyGenerationParameters(rng, FalconParameters.falcon_512)); final FalconPrivateKeyParameters sk = (FalconPrivateKeyParameters) g.generateKeyPair().getPrivate(); final byte[] h = sk.getPublicKey(); final byte[] s = new byte[PqRegistryV3.FALCON_512_PK_LENGTH]; s[0] = PqRegistryV3.FALCON_512_PK_HEADER; System.arraycopy(h, 0, s, 1, h.length); final byte[] id = PqRegistryV3.idOf(s); final byte[] pop = falcon.signWithParams(sk, PqRegistryV3.popMessage(CHAIN, BIND, COUNT, i, id, SealSchemes.FALCON_512.wireId(), s).toArrayUnsafe()).orElseThrow(); final TreeMap keys = new TreeMap<>(); keys.put(SealSchemes.FALCON_512.wireId() & 0xff, new PqRegistryV3.Key(SealSchemes.FALCON_512, s, pop)); final PqRegistryV3.Row row = new PqRegistryV3.Row(i, id, keys, null, Map.of(), null, null); final byte[] p = PqRegistryV3.rowPreimage(CHAIN, BIND, COUNT, row); sks.add(sk); std.add(s); pre.add(p); leaves.add(PqRegistryV3.rowHash(CHAIN, BIND, COUNT, row)); } final Bytes32 root = PqRegistryV3.merkleRoot(leaves); final Bytes32 rh = PqRegistryV3.registryHash(CHAIN, BIND, COUNT, root); final Bytes32 dA = Bytes32.random(rng), dB = Bytes32.random(rng), hA = Bytes32.random(rng), hB = Bytes32.random(rng); final Bytes32 pA = PqAnchor.prepareMessage(CHAIN, HEIGHT, ROUND, dA), pB = PqAnchor.prepareMessage(CHAIN, HEIGHT, ROUND, dB); final Bytes32 cA = PqAnchor.commitMessage(CHAIN, HEIGHT, hA), cB = PqAnchor.commitMessage(CHAIN, HEIGHT, hB); final FalconPrivateKeyParameters sk = sks.get(SIGNER); final byte[] spA = falcon.signWithParams(sk, pA.toArrayUnsafe()).orElseThrow(), spB = falcon.signWithParams(sk, pB.toArrayUnsafe()).orElseThrow(); final byte[] scA = falcon.signWithParams(sk, cA.toArrayUnsafe()).orElseThrow(), scB = falcon.signWithParams(sk, cB.toArrayUnsafe()).orElseThrow(); final byte[] reg = sks.get(SIGNER).getPublicKey(); final byte[] other = sks.get((SIGNER + 1) % COUNT).getPublicKey(); // controls under the clients' own verifier: each seal verifies under its row's key and NOT under another row's, nor over the other message final boolean ok = falcon.verifyRaw(reg, pA.toArrayUnsafe(), spA) && falcon.verifyRaw(reg, pB.toArrayUnsafe(), spB) && falcon.verifyRaw(reg, cA.toArrayUnsafe(), scA) && falcon.verifyRaw(reg, cB.toArrayUnsafe(), scB); final boolean neg = !falcon.verifyRaw(other, pA.toArrayUnsafe(), spA) && !falcon.verifyRaw(reg, pB.toArrayUnsafe(), spA); final StringBuilder o = new StringBuilder(); o.append("{\n \"what\": \"AIP-22 stage 6 drill: chain 28099 epoch of drill keys generated in memory for this run\",\n"); o.append(" \"chainId\": ").append(CHAIN).append(", \"bindHeight\": ").append(BIND).append(", \"count\": ").append(COUNT).append(",\n"); o.append(" \"root\": \"").append(root.toHexString()).append("\", \"registryHash\": \"").append(rh.toHexString()).append("\",\n"); o.append(" \"rows\": ["); for (int i = 0; i < COUNT; i++) o.append(i > 0 ? ", " : "").append('"').append(hx(pre.get(i))).append('"'); o.append("],\n \"proofs\": ["); for (int i = 0; i < COUNT; i++) { o.append(i > 0 ? ", " : "").append('['); final List pr = PqRegistryV3.merkleProof(leaves, i); for (int j = 0; j < pr.size(); j++) o.append(j > 0 ? ", " : "").append('"').append(pr.get(j).toHexString()).append('"'); o.append(']'); } o.append("],\n \"signer\": ").append(SIGNER).append(", \"height\": ").append(HEIGHT).append(", \"round\": ").append(ROUND).append(",\n"); o.append(" \"prepare\": {\"digestA\": \"").append(dA.toHexString()).append("\", \"digestB\": \"").append(dB.toHexString()) .append("\", \"messageA\": \"").append(pA.toHexString()).append("\", \"messageB\": \"").append(pB.toHexString()) .append("\", \"sealA\": \"").append(hx(spA)).append("\", \"sealB\": \"").append(hx(spB)).append("\"},\n"); o.append(" \"commit\": {\"hashA\": \"").append(hA.toHexString()).append("\", \"hashB\": \"").append(hB.toHexString()) .append("\", \"messageA\": \"").append(cA.toHexString()).append("\", \"messageB\": \"").append(cB.toHexString()) .append("\", \"sealA\": \"").append(hx(scA)).append("\", \"sealB\": \"").append(hx(scB)).append("\"},\n"); o.append(" \"otherRowSeal\": \"").append(hx(falcon.signWithParams(sks.get((SIGNER + 1) % COUNT), pB.toArrayUnsafe()).orElseThrow())).append("\",\n"); o.append(" \"controlsUnderClientVerifier\": {\"positive\": ").append(ok).append(", \"negative\": ").append(neg).append("}\n}\n"); System.out.print(o); if (!ok || !neg) System.exit(1); } }