From e411755a4af7500eb1832f429acea16124c30940 Mon Sep 17 00:00:00 2001 From: Jannik Date: Wed, 20 May 2026 10:22:54 +0200 Subject: [PATCH 01/25] Add DKGContract scaffold and wire it into deploy scripts Introduces the DKGContract with its four immutables (PHASE_LENGTH, DKG_LEAD_LENGTH, keyperSetManager, keyBroadcastContract) and a matching deploy fixture. Phase arithmetic, bulletin-board functions, and success voting follow in subsequent commits. --- src/common/DKGContract.sol | 26 ++++++++++++++ test/DKGContract.t.sol | 69 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 src/common/DKGContract.sol create mode 100644 test/DKGContract.t.sol diff --git a/src/common/DKGContract.sol b/src/common/DKGContract.sol new file mode 100644 index 0000000..75ddc6e --- /dev/null +++ b/src/common/DKGContract.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.22; + +import "./KeyperSetManager.sol"; +import "./KeyBroadcastContract.sol"; + +contract DKGContract { + uint64 public immutable PHASE_LENGTH; + uint64 public immutable DKG_LEAD_LENGTH; + KeyperSetManager public immutable keyperSetManager; + KeyBroadcastContract public immutable keyBroadcastContract; + + constructor( + uint64 phaseLength, + uint64 dkgLeadLength, + address keyperSetManagerAddress, + address keyBroadcastContractAddress + ) { + PHASE_LENGTH = phaseLength; + DKG_LEAD_LENGTH = dkgLeadLength; + keyperSetManager = KeyperSetManager(keyperSetManagerAddress); + keyBroadcastContract = KeyBroadcastContract( + keyBroadcastContractAddress + ); + } +} diff --git a/test/DKGContract.t.sol b/test/DKGContract.t.sol new file mode 100644 index 0000000..241dd6c --- /dev/null +++ b/test/DKGContract.t.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.22; + +import "forge-std/Test.sol"; +import "../src/common/DKGContract.sol"; +import "../src/common/KeyperSet.sol"; +import "../src/common/KeyperSetManager.sol"; +import "../src/common/KeyBroadcastContract.sol"; + +contract DKGContractTest is Test { + DKGContract public dkgContract; + KeyperSetManager public keyperSetManager; + KeyBroadcastContract public keyBroadcastContract; + KeyperSet public keyperSet0; + + uint64 constant PHASE_LENGTH = 10; + uint64 constant DKG_LEAD_LENGTH = 40; + uint64 constant CYCLE_LENGTH = 4 * PHASE_LENGTH; + uint64 constant ACTIVATION_BLOCK_0 = 1000; + + address dao = address(42); + address keyper0 = address(0xA0); + address keyper1 = address(0xA1); + address keyper2 = address(0xA2); + + function setUp() public { + address initializer = address(69); + address sequencer = address(420); + + keyperSetManager = new KeyperSetManager(initializer); + vm.prank(initializer); + keyperSetManager.initialize(dao, sequencer); + + keyBroadcastContract = new KeyBroadcastContract( + address(keyperSetManager) + ); + + dkgContract = new DKGContract( + PHASE_LENGTH, + DKG_LEAD_LENGTH, + address(keyperSetManager), + address(keyBroadcastContract) + ); + + keyperSet0 = new KeyperSet(); + address[] memory members = new address[](3); + members[0] = keyper0; + members[1] = keyper1; + members[2] = keyper2; + keyperSet0.addMembers(members); + keyperSet0.setThreshold(2); + keyperSet0.setFinalized(); + vm.prank(dao); + keyperSetManager.addKeyperSet(ACTIVATION_BLOCK_0, address(keyperSet0)); + } + + function testDeploysWithImmutables() public view { + assertEq(dkgContract.PHASE_LENGTH(), PHASE_LENGTH); + assertEq(dkgContract.DKG_LEAD_LENGTH(), DKG_LEAD_LENGTH); + assertEq( + address(dkgContract.keyperSetManager()), + address(keyperSetManager) + ); + assertEq( + address(dkgContract.keyBroadcastContract()), + address(keyBroadcastContract) + ); + } +} From f323d62a65569ab3dd3b1f7f6f768a2e7e3b0229 Mon Sep 17 00:00:00 2001 From: Jannik Date: Wed, 20 May 2026 10:23:47 +0200 Subject: [PATCH 02/25] Add DKG phase-arithmetic helpers (issue #002) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds Phase enum (None/Dealing/Accusing/Apologizing/Finalizing), cycleLength(), dkgStart(keyperSetIndex, retryCounter), and currentPhase(keyperSetIndex, retryCounter) to DKGContract. DKG instance (k, r) starts at: activation_block(k) - DKG_LEAD_LENGTH + r * cycleLength() All phase windows are derived arithmetically from that start; no per-instance block is stored. dkgStart returns int256 so it can go negative when lead exceeds the activation block (edge case handled without reverting). Tests cover all phase boundaries for r=0, the r=0→r=1 retry boundary, dkgStart arithmetic, and the negative-start edge case. --- src/common/DKGContract.sol | 41 +++++++++++ test/DKGContract.t.sol | 147 +++++++++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+) diff --git a/src/common/DKGContract.sol b/src/common/DKGContract.sol index 75ddc6e..47ecac8 100644 --- a/src/common/DKGContract.sol +++ b/src/common/DKGContract.sol @@ -5,6 +5,14 @@ import "./KeyperSetManager.sol"; import "./KeyBroadcastContract.sol"; contract DKGContract { + enum Phase { + None, + Dealing, + Accusing, + Apologizing, + Finalizing + } + uint64 public immutable PHASE_LENGTH; uint64 public immutable DKG_LEAD_LENGTH; KeyperSetManager public immutable keyperSetManager; @@ -23,4 +31,37 @@ contract DKGContract { keyBroadcastContractAddress ); } + + function cycleLength() public view returns (uint64) { + return 4 * PHASE_LENGTH; + } + + function dkgStart( + uint64 keyperSetIndex, + uint64 retryCounter + ) public view returns (int256) { + uint64 activationBlock = keyperSetManager.getKeyperSetActivationBlock( + keyperSetIndex + ); + return + int256(uint256(activationBlock)) - + int256(uint256(DKG_LEAD_LENGTH)) + + int256(uint256(retryCounter)) * + int256(uint256(cycleLength())); + } + + function currentPhase( + uint64 keyperSetIndex, + uint64 retryCounter + ) public view returns (Phase) { + int256 start = dkgStart(keyperSetIndex, retryCounter); + int256 offset = int256(block.number) - start; + int256 phaseLen = int256(uint256(PHASE_LENGTH)); + if (offset < 0) return Phase.None; + if (offset < phaseLen) return Phase.Dealing; + if (offset < 2 * phaseLen) return Phase.Accusing; + if (offset < 3 * phaseLen) return Phase.Apologizing; + if (offset < 4 * phaseLen) return Phase.Finalizing; + return Phase.None; + } } diff --git a/test/DKGContract.t.sol b/test/DKGContract.t.sol index 241dd6c..d307f13 100644 --- a/test/DKGContract.t.sol +++ b/test/DKGContract.t.sol @@ -66,4 +66,151 @@ contract DKGContractTest is Test { address(keyBroadcastContract) ); } + + function _assertPhase( + uint64 blockNumber, + uint64 retryCounter, + DKGContract.Phase expected + ) internal { + vm.roll(blockNumber); + assertEq( + uint256(dkgContract.currentPhase(0, retryCounter)), + uint256(expected), + "phase mismatch" + ); + } + + // dkg_start(k=0, r=0) = 1000 - 40 + 0 = 960 + // Dealing: [960, 970) + // Accusing: [970, 980) + // Apologizing: [980, 990) + // Finalizing: [990, 1000) + uint64 constant DKG_START_R0 = ACTIVATION_BLOCK_0 - DKG_LEAD_LENGTH; + + function testCurrentPhaseBeforeDkgStartIsNone() public { + _assertPhase(DKG_START_R0 - 1, 0, DKGContract.Phase.None); + } + + function testCurrentPhaseDealingBoundaries() public { + _assertPhase(DKG_START_R0, 0, DKGContract.Phase.Dealing); + _assertPhase( + DKG_START_R0 + PHASE_LENGTH - 1, + 0, + DKGContract.Phase.Dealing + ); + } + + function testCurrentPhaseAccusingBoundaries() public { + // one block before Accusing + _assertPhase( + DKG_START_R0 + PHASE_LENGTH - 1, + 0, + DKGContract.Phase.Dealing + ); + // first block of Accusing + _assertPhase( + DKG_START_R0 + PHASE_LENGTH, + 0, + DKGContract.Phase.Accusing + ); + // last block of Accusing + _assertPhase( + DKG_START_R0 + 2 * PHASE_LENGTH - 1, + 0, + DKGContract.Phase.Accusing + ); + } + + function testCurrentPhaseApologizingBoundaries() public { + // one block before Apologizing + _assertPhase( + DKG_START_R0 + 2 * PHASE_LENGTH - 1, + 0, + DKGContract.Phase.Accusing + ); + // first block of Apologizing + _assertPhase( + DKG_START_R0 + 2 * PHASE_LENGTH, + 0, + DKGContract.Phase.Apologizing + ); + // last block of Apologizing + _assertPhase( + DKG_START_R0 + 3 * PHASE_LENGTH - 1, + 0, + DKGContract.Phase.Apologizing + ); + } + + function testCurrentPhaseFinalizingBoundaries() public { + // one block before Finalizing + _assertPhase( + DKG_START_R0 + 3 * PHASE_LENGTH - 1, + 0, + DKGContract.Phase.Apologizing + ); + // first block of Finalizing + _assertPhase( + DKG_START_R0 + 3 * PHASE_LENGTH, + 0, + DKGContract.Phase.Finalizing + ); + // last block of Finalizing + _assertPhase( + DKG_START_R0 + 4 * PHASE_LENGTH - 1, + 0, + DKGContract.Phase.Finalizing + ); + } + + function testCurrentPhaseAfterFinalizingIsNoneForSameRetry() public { + // r=0 ends at 1000; one block after is Phase.None for r=0 + _assertPhase( + DKG_START_R0 + 4 * PHASE_LENGTH, + 0, + DKGContract.Phase.None + ); + } + + // (k, r+1) Dealing starts exactly when (k, r) Finalizing ends. + function testRetryDealingStartsWhenPriorFinalizingEnds() public { + // r=0 Finalizing ends at DKG_START_R0 + 4 * PHASE_LENGTH = 1000. + // r=1 Dealing should begin at the same block. + uint64 boundary = DKG_START_R0 + 4 * PHASE_LENGTH; + _assertPhase(boundary, 1, DKGContract.Phase.Dealing); + _assertPhase(boundary, 0, DKGContract.Phase.None); + + // one block before boundary: r=0 still Finalizing, r=1 still None + _assertPhase(boundary - 1, 0, DKGContract.Phase.Finalizing); + _assertPhase(boundary - 1, 1, DKGContract.Phase.None); + } + + function testRetryDealingLastBlockBeforeAccusing() public { + // r=1 Dealing: [1000, 1010) + uint64 r1Start = DKG_START_R0 + CYCLE_LENGTH; + _assertPhase(r1Start + PHASE_LENGTH - 1, 1, DKGContract.Phase.Dealing); + _assertPhase(r1Start + PHASE_LENGTH, 1, DKGContract.Phase.Accusing); + } + + function testDkgStartArithmeticPureView() public view { + // dkg_start(k=0, r=0) = 960 + assertEq(dkgContract.dkgStart(0, 0), int256(960)); + // dkg_start(k=0, r=1) = 960 + 40 = 1000 + assertEq(dkgContract.dkgStart(0, 1), int256(1000)); + // dkg_start(k=0, r=2) = 960 + 80 = 1040 + assertEq(dkgContract.dkgStart(0, 2), int256(1040)); + } + + function testDkgStartCanBeNegativeIfLeadExceedsActivation() public { + // Deploy a second DKG contract with a very large lead length so + // dkg_start(k=0, r=0) goes negative. Verify the view returns + // the negative value rather than reverting on underflow. + DKGContract dkg = new DKGContract( + PHASE_LENGTH, + 2000, // lead length larger than activation block 1000 + address(keyperSetManager), + address(keyBroadcastContract) + ); + assertEq(dkg.dkgStart(0, 0), int256(-1000)); + } } From 6c057ead2049ba9f59eb6a1de7ad0ccdcaeb353b Mon Sep 17 00:00:00 2001 From: Jannik Date: Wed, 20 May 2026 10:24:06 +0200 Subject: [PATCH 03/25] Add ECIESKeyRegistry contract (issue #005) Adds a standalone registry where Keypers register their ECIES encryption public keys. Membership is verified via KeyperSetManager at registration time; keys persist across Keyper Set transitions so a new KeyperSet deployment does not require re-registration. Key design decisions: - Uses OZ EnumerableSet.AddressSet so off-chain services can backfill the full set of registered keys via getKeyperCount()/getKeyperAt(). - Re-registration (key update) is accepted: add() is idempotent so the set size does not grow on re-registration. - KeyperSetNotFinalized is surfaced from KeyperSet when the set is not yet finalized. Also updates Deploy.gnosh.s.sol and Deploy.s.sol to deploy DKGContract and ECIESKeyRegistry alongside the existing contracts, and wires DKGContract as the KeyperSet publisher in Deploy.s.sol. Tests cover basic registration, key lookup, identity/membership checks, arbitrary-bytes acceptance, and the iterable enumeration API. --- foundry.lock | 20 ++-- script/Deploy.gnosh.s.sol | 32 +++++- script/Deploy.s.sol | 42 ++++++- src/common/ECIESKeyRegistry.sol | 54 +++++++++ test/ECIESKeyRegistry.t.sol | 195 ++++++++++++++++++++++++++++++++ 5 files changed, 329 insertions(+), 14 deletions(-) create mode 100644 src/common/ECIESKeyRegistry.sol create mode 100644 test/ECIESKeyRegistry.t.sol diff --git a/foundry.lock b/foundry.lock index 38b729d..1ce06cb 100644 --- a/foundry.lock +++ b/foundry.lock @@ -1,23 +1,23 @@ { - "lib/openzeppelin-foundry-upgrades": { + "lib/forge-std": { "tag": { - "name": "v0.4.0", - "rev": "cbce1e00305e943aa1661d43f41e5ac72c662b07" + "name": "v1.10.0", + "rev": "8bbcf6e3f8f62f419e5429a0bd89331c85c37824" } }, + "lib/openzeppelin": { + "rev": "932fddf69a699a9a80fd2396fd1a2ab91cdda123" + }, "lib/openzeppelin-contracts-upgradeable": { "tag": { "name": "v5.4.0", "rev": "e725abddf1e01cf05ace496e950fc8e243cc7cab" } }, - "lib/openzeppelin": { - "rev": "932fddf69a699a9a80fd2396fd1a2ab91cdda123" - }, - "lib/forge-std": { + "lib/openzeppelin-foundry-upgrades": { "tag": { - "name": "v1.10.0", - "rev": "8bbcf6e3f8f62f419e5429a0bd89331c85c37824" + "name": "v0.4.0", + "rev": "cbce1e00305e943aa1661d43f41e5ac72c662b07" } } -} +} \ No newline at end of file diff --git a/script/Deploy.gnosh.s.sol b/script/Deploy.gnosh.s.sol index 64723bc..485f6c8 100644 --- a/script/Deploy.gnosh.s.sol +++ b/script/Deploy.gnosh.s.sol @@ -2,6 +2,8 @@ pragma solidity ^0.8.20; import "forge-std/Script.sol"; +import "../src/common/DKGContract.sol"; +import "../src/common/ECIESKeyRegistry.sol"; import "../src/common/KeyBroadcastContract.sol"; import "../src/common/KeyperSet.sol"; import "../src/common/KeyperSetManager.sol"; @@ -31,6 +33,32 @@ contract Deploy is Script { return kbc; } + function deployDKGContract( + KeyperSetManager ksm, + KeyBroadcastContract kbc + ) public returns (DKGContract) { + uint64 phaseLength = uint64(vm.envOr("DKG_PHASE_LENGTH", uint256(10))); + uint64 dkgLeadLength = uint64( + vm.envOr("DKG_LEAD_LENGTH", uint256(40)) + ); + DKGContract dkg = new DKGContract( + phaseLength, + dkgLeadLength, + address(ksm), + address(kbc) + ); + console.log("DKGContract:", address(dkg)); + return dkg; + } + + function deployECIESKeyRegistry( + KeyperSetManager ksm + ) public returns (ECIESKeyRegistry) { + ECIESKeyRegistry registry = new ECIESKeyRegistry(address(ksm)); + console.log("ECIESKeyRegistry:", address(registry)); + return registry; + } + function deploySequencer() public returns (Sequencer) { Sequencer s = new Sequencer(); console.log("Sequencer:", address(s)); @@ -50,7 +78,9 @@ contract Deploy is Script { vm.startBroadcast(deployKey); KeyperSetManager ksm = deployKeyperSetManager(deployerAddress); - deployKeyBroadcastContract(ksm); + KeyBroadcastContract kbc = deployKeyBroadcastContract(ksm); + deployDKGContract(ksm, kbc); + deployECIESKeyRegistry(ksm); deploySequencer(); deployValidatorRegistry(); diff --git a/script/Deploy.s.sol b/script/Deploy.s.sol index 076d7f3..fd21b4d 100644 --- a/script/Deploy.s.sol +++ b/script/Deploy.s.sol @@ -3,6 +3,8 @@ pragma solidity ^0.8.22; import "forge-std/Script.sol"; import "../src/shop/Inbox.sol"; +import "../src/common/DKGContract.sol"; +import "../src/common/ECIESKeyRegistry.sol"; import "../src/common/KeyperSet.sol"; import "../src/common/KeyperSetManager.sol"; import "../src/common/KeyBroadcastContract.sol"; @@ -14,6 +16,8 @@ contract DeployScript is Script { KeyperSet keyperSet; KeyperSetManager keyperSetManager; KeyBroadcastContract keyBroadcastContract; + DKGContract dkgContract; + ECIESKeyRegistry eciesKeyRegistry; uint256 deployerPrivateKey; address sequencerAddress; @@ -21,12 +25,16 @@ contract DeployScript is Script { uint64 blockGasLimit; uint256 activationDelta; uint256 threshold; + uint64 dkgPhaseLength; + uint64 dkgLeadLength; // address[] memory keypers; address inboxAddress; address keyperSetManagerAddress; address keyBroadcastContractAddress; address keyperSetAddress; + address dkgContractAddress; + address eciesKeyRegistryAddress; function setUp() public { deployerPrivateKey = vm.envUint("PRIVATE_KEY"); @@ -51,6 +59,14 @@ contract DeployScript is Script { address(0) ); keyperSetAddress = vm.envOr("KEYPERSET_ADDRESS", address(0)); + dkgContractAddress = vm.envOr("DKG_CONTRACT_ADDRESS", address(0)); + eciesKeyRegistryAddress = vm.envOr( + "ECIES_KEY_REGISTRY_ADDRESS", + address(0) + ); + + dkgPhaseLength = uint64(vm.envOr("DKG_PHASE_LENGTH", uint256(10))); + dkgLeadLength = uint64(vm.envOr("DKG_LEAD_LENGTH", uint256(40))); } function deploy() public { @@ -91,6 +107,26 @@ contract DeployScript is Script { } else { keyperSet = KeyperSet(keyperSetAddress); } + if (dkgContractAddress == address(0)) { + dkgContract = new DKGContract( + dkgPhaseLength, + dkgLeadLength, + address(keyperSetManager), + address(keyBroadcastContract) + ); + console.log("DKGContract deployed at:", address(dkgContract)); + } else { + dkgContract = DKGContract(dkgContractAddress); + } + if (eciesKeyRegistryAddress == address(0)) { + eciesKeyRegistry = new ECIESKeyRegistry(address(keyperSetManager)); + console.log( + "ECIESKeyRegistry deployed at:", + address(eciesKeyRegistry) + ); + } else { + eciesKeyRegistry = ECIESKeyRegistry(eciesKeyRegistryAddress); + } vm.stopBroadcast(); } @@ -132,9 +168,9 @@ contract DeployScript is Script { keyperSet.addMembers(keypers); keyperSet.setThreshold(uint64(threshold)); - // Step 2: Call setPublisher with deployer address (the sender) - keyperSet.setPublisher(deployerAddress); - console.log("Eon Key Publisher set to deployer's address"); + // Step 2: Set the DKG Contract as publisher so it can broadcast eon keys + keyperSet.setPublisher(address(dkgContract)); + console.log("Eon Key Publisher set to DKGContract:", address(dkgContract)); keyperSet.setFinalized(); console.log("KeyperSet finalized"); diff --git a/src/common/ECIESKeyRegistry.sol b/src/common/ECIESKeyRegistry.sol new file mode 100644 index 0000000..318d7e0 --- /dev/null +++ b/src/common/ECIESKeyRegistry.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.22; + +import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +import "./KeyperSetManager.sol"; +import "./KeyperSet.sol"; + +contract ECIESKeyRegistry { + using EnumerableSet for EnumerableSet.AddressSet; + + error NotAMember(); + + event KeyRegistered(address indexed keyper, bytes eciesPublicKey); + + KeyperSetManager public immutable keyperSetManager; + + EnumerableSet.AddressSet private registeredKeypers; + mapping(address => bytes) private keys; + + constructor(address keyperSetManagerAddress) { + keyperSetManager = KeyperSetManager(keyperSetManagerAddress); + } + + function registerKey( + uint64 keyperSetIndex, + uint64 keyperIndex, + bytes calldata eciesPublicKey + ) external { + KeyperSet keyperSet = KeyperSet( + keyperSetManager.getKeyperSetAddress(keyperSetIndex) + ); + if (!keyperSet.isFinalized()) { + revert KeyperSetNotFinalized(); + } + if (keyperSet.getMember(keyperIndex) != msg.sender) { + revert NotAMember(); + } + registeredKeypers.add(msg.sender); + keys[msg.sender] = eciesPublicKey; + emit KeyRegistered(msg.sender, eciesPublicKey); + } + + function getKey(address keyper) external view returns (bytes memory) { + return keys[keyper]; + } + + function getKeyperCount() external view returns (uint256) { + return registeredKeypers.length(); + } + + function getKeyperAt(uint256 index) external view returns (address) { + return registeredKeypers.at(index); + } +} diff --git a/test/ECIESKeyRegistry.t.sol b/test/ECIESKeyRegistry.t.sol new file mode 100644 index 0000000..1bd7fe2 --- /dev/null +++ b/test/ECIESKeyRegistry.t.sol @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.22; + +import "forge-std/Test.sol"; +import "../src/common/ECIESKeyRegistry.sol"; +import "../src/common/KeyperSet.sol"; +import "../src/common/KeyperSetManager.sol"; +import "../src/common/intf/IKeyperSetManager.sol"; + +contract ECIESKeyRegistryTest is Test { + ECIESKeyRegistry public registry; + KeyperSetManager public keyperSetManager; + KeyperSet public keyperSet0; + + address dao = address(42); + address keyper0 = address(0xA0); + address keyper1 = address(0xA1); + address keyper2 = address(0xA2); + + uint64 constant ACTIVATION_BLOCK_0 = 1000; + + event KeyRegistered(address indexed keyper, bytes eciesPublicKey); + + function setUp() public { + address initializer = address(69); + address sequencer = address(420); + + keyperSetManager = new KeyperSetManager(initializer); + vm.prank(initializer); + keyperSetManager.initialize(dao, sequencer); + + registry = new ECIESKeyRegistry(address(keyperSetManager)); + + keyperSet0 = new KeyperSet(); + address[] memory members = new address[](3); + members[0] = keyper0; + members[1] = keyper1; + members[2] = keyper2; + keyperSet0.addMembers(members); + keyperSet0.setThreshold(2); + keyperSet0.setFinalized(); + vm.prank(dao); + keyperSetManager.addKeyperSet(ACTIVATION_BLOCK_0, address(keyperSet0)); + } + + function testDeploysWithImmutableManager() public view { + assertEq( + address(registry.keyperSetManager()), + address(keyperSetManager) + ); + } + + function testGetKeyEmptyForUnregisteredAddress() public view { + bytes memory key = registry.getKey(keyper0); + assertEq(key.length, 0); + } + + function testRegisterKeySucceedsForMember() public { + bytes memory pubkey = hex"04aabbccddeeff"; + vm.expectEmit(true, false, false, true, address(registry)); + emit KeyRegistered(keyper0, pubkey); + vm.prank(keyper0); + registry.registerKey(0, 0, pubkey); + assertEq(registry.getKey(keyper0), pubkey); + } + + function testRegisterKeyForEachMember() public { + bytes memory key0 = hex"aa"; + bytes memory key1 = hex"bb"; + bytes memory key2 = hex"cc"; + + vm.prank(keyper0); + registry.registerKey(0, 0, key0); + vm.prank(keyper1); + registry.registerKey(0, 1, key1); + vm.prank(keyper2); + registry.registerKey(0, 2, key2); + + assertEq(registry.getKey(keyper0), key0); + assertEq(registry.getKey(keyper1), key1); + assertEq(registry.getKey(keyper2), key2); + } + + function testRegisterKeyUpdatesExistingEntry() public { + bytes memory first = hex"11"; + bytes memory second = hex"2222"; + + vm.prank(keyper0); + registry.registerKey(0, 0, first); + assertEq(registry.getKey(keyper0), first); + + vm.expectEmit(true, false, false, true, address(registry)); + emit KeyRegistered(keyper0, second); + vm.prank(keyper0); + registry.registerKey(0, 0, second); + + assertEq(registry.getKey(keyper0), second); + } + + function testRegisterKeyRevertsWhenSenderIsNotMember() public { + address outsider = address(0xBEEF); + bytes memory pubkey = hex"42"; + vm.prank(outsider); + vm.expectRevert(ECIESKeyRegistry.NotAMember.selector); + registry.registerKey(0, 0, pubkey); + } + + function testRegisterKeyRevertsWhenKeyperIndexDoesNotMatchSender() + public + { + bytes memory pubkey = hex"42"; + // keyper0 is the member at index 0; using index 1 must fail. + vm.prank(keyper0); + vm.expectRevert(ECIESKeyRegistry.NotAMember.selector); + registry.registerKey(0, 1, pubkey); + } + + function testRegisterKeyRevertsWhenKeyperSetNotFinalized() public { + KeyperSet nonFinalized = new KeyperSet(); + address[] memory members = new address[](1); + members[0] = keyper0; + nonFinalized.addMembers(members); + // Deliberately do NOT finalize. + + // Mock KeyperSetManager to surface this non-finalized set under some index. + vm.mockCall( + address(keyperSetManager), + abi.encodeWithSelector( + KeyperSetManager.getKeyperSetAddress.selector, + uint64(99) + ), + abi.encode(address(nonFinalized)) + ); + + vm.prank(keyper0); + vm.expectRevert(KeyperSetNotFinalized.selector); + registry.registerKey(99, 0, hex"00"); + } + + function testRegisterKeyAcceptsArbitraryBytes() public { + // Registry stores arbitrary bytes — no format validation. + bytes memory tiny = hex"00"; + bytes memory empty = new bytes(0); + + vm.prank(keyper0); + registry.registerKey(0, 0, tiny); + assertEq(registry.getKey(keyper0), tiny); + + vm.prank(keyper0); + registry.registerKey(0, 0, empty); + assertEq(registry.getKey(keyper0).length, 0); + } + + // ------------------------------------------------------------------------- + // Iterable enumeration + // ------------------------------------------------------------------------- + + function testGetKeyperCountZeroInitially() public view { + assertEq(registry.getKeyperCount(), 0); + } + + function testGetKeyperCountIncreasesWithNewRegistrations() public { + vm.prank(keyper0); + registry.registerKey(0, 0, hex"aa"); + assertEq(registry.getKeyperCount(), 1); + + vm.prank(keyper1); + registry.registerKey(0, 1, hex"bb"); + assertEq(registry.getKeyperCount(), 2); + } + + function testGetKeyperCountIsIdempotentOnReRegistration() public { + vm.prank(keyper0); + registry.registerKey(0, 0, hex"aa"); + assertEq(registry.getKeyperCount(), 1); + + vm.prank(keyper0); + registry.registerKey(0, 0, hex"bb"); + assertEq(registry.getKeyperCount(), 1); + } + + function testGetKeyperAtReturnsRegisteredAddress() public { + vm.prank(keyper0); + registry.registerKey(0, 0, hex"aa"); + vm.prank(keyper1); + registry.registerKey(0, 1, hex"bb"); + + // Both keyper0 and keyper1 must appear in the set (order not guaranteed). + address a = registry.getKeyperAt(0); + address b = registry.getKeyperAt(1); + assertTrue( + (a == keyper0 && b == keyper1) || (a == keyper1 && b == keyper0) + ); + } +} From 33ec3a5b36ef3ad201c95a9e6c04f85ce21cc4a4 Mon Sep 17 00:00:00 2001 From: Jannik Date: Wed, 20 May 2026 10:25:42 +0200 Subject: [PATCH 04/25] Add DKG bulletin-board message functions (issue #003) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds submitDealing (Dealing Phase), submitAccusation (Accusing Phase), and submitApology (Apologizing Phase) to DKGContract. Each validates phase, identity, and the succeeded[k] guard, then emits an event with no on-chain cryptographic verification and no deduplication. Key decisions: - submitDealing accepts commitment and polyEval together; callers cannot submit them separately. - Empty accusedIndices reverts with EmptyAccusation. An empty accusation has no protocol meaning; clients should skip the call. - Empty apology arrays (length 0) are accepted as a valid no-op. Mismatched array lengths revert with MismatchedArrays. - succeeded[k] mapping is declared here as a read-only gate for the bulletin-board functions; the write logic is owned by issue #004. - Events use 3 indexed fields (keyperSetIndex, retryCounter, keyperIndex) for efficient off-chain filtering. - A shared _checkMember helper calls KeyperSet(manager.getKeyperSetAddress(k)).getMember(keyperIndex) and requires msg.sender match — reverts NotKeyperAtIndex. Tests cover phase/identity/array-validation for all three functions. --- src/common/DKGContract.sol | 123 +++++++++++++++++++++++ test/DKGContract.t.sol | 193 +++++++++++++++++++++++++++++++++++++ 2 files changed, 316 insertions(+) diff --git a/src/common/DKGContract.sol b/src/common/DKGContract.sol index 47ecac8..ba4cbd0 100644 --- a/src/common/DKGContract.sol +++ b/src/common/DKGContract.sol @@ -13,11 +13,43 @@ contract DKGContract { Finalizing } + error WrongPhase(); + error NotKeyperAtIndex(); + error AlreadySucceeded(); + error EmptyAccusation(); + error MismatchedArrays(); + + event DealingSubmitted( + uint64 indexed keyperSetIndex, + uint64 indexed retryCounter, + uint64 indexed keyperIndex, + bytes commitment, + bytes polyEval + ); + event AccusationSubmitted( + uint64 indexed keyperSetIndex, + uint64 indexed retryCounter, + uint64 indexed keyperIndex, + uint64[] accusedIndices + ); + event ApologySubmitted( + uint64 indexed keyperSetIndex, + uint64 indexed retryCounter, + uint64 indexed keyperIndex, + uint64[] accuserIndices, + bytes[] polyEvalData + ); + uint64 public immutable PHASE_LENGTH; uint64 public immutable DKG_LEAD_LENGTH; KeyperSetManager public immutable keyperSetManager; KeyBroadcastContract public immutable keyBroadcastContract; + // Set to true once a DKG Instance for Keyper Set Index k has reached the + // success-vote threshold. Never reset — gates the success-triggering logic + // in submitSuccessVote. + mapping(uint64 => bool) public succeeded; + constructor( uint64 phaseLength, uint64 dkgLeadLength, @@ -64,4 +96,95 @@ contract DKGContract { if (offset < 4 * phaseLen) return Phase.Finalizing; return Phase.None; } + + function _requireNotSucceeded(uint64 keyperSetIndex) internal view { + if (succeeded[keyperSetIndex]) { + revert AlreadySucceeded(); + } + } + + function _checkMember( + uint64 keyperSetIndex, + uint64 keyperIndex + ) internal view { + address keyperSetAddress = keyperSetManager.getKeyperSetAddress( + keyperSetIndex + ); + if (KeyperSet(keyperSetAddress).getMember(keyperIndex) != msg.sender) { + revert NotKeyperAtIndex(); + } + } + + function _requirePhase( + uint64 keyperSetIndex, + uint64 retryCounter, + Phase expected + ) internal view { + if (currentPhase(keyperSetIndex, retryCounter) != expected) { + revert WrongPhase(); + } + } + + function submitDealing( + uint64 keyperSetIndex, + uint64 retryCounter, + uint64 keyperIndex, + bytes calldata commitment, + bytes calldata polyEval + ) external { + _requireNotSucceeded(keyperSetIndex); + _requirePhase(keyperSetIndex, retryCounter, Phase.Dealing); + _checkMember(keyperSetIndex, keyperIndex); + emit DealingSubmitted( + keyperSetIndex, + retryCounter, + keyperIndex, + commitment, + polyEval + ); + } + + // Empty accusedIndices reverts: an empty accusation has no protocol + // meaning, so clients should skip the call instead of submitting one. + function submitAccusation( + uint64 keyperSetIndex, + uint64 retryCounter, + uint64 keyperIndex, + uint64[] calldata accusedIndices + ) external { + _requireNotSucceeded(keyperSetIndex); + _requirePhase(keyperSetIndex, retryCounter, Phase.Accusing); + _checkMember(keyperSetIndex, keyperIndex); + if (accusedIndices.length == 0) { + revert EmptyAccusation(); + } + emit AccusationSubmitted( + keyperSetIndex, + retryCounter, + keyperIndex, + accusedIndices + ); + } + + function submitApology( + uint64 keyperSetIndex, + uint64 retryCounter, + uint64 keyperIndex, + uint64[] calldata accuserIndices, + bytes[] calldata polyEvalData + ) external { + _requireNotSucceeded(keyperSetIndex); + _requirePhase(keyperSetIndex, retryCounter, Phase.Apologizing); + _checkMember(keyperSetIndex, keyperIndex); + if (accuserIndices.length != polyEvalData.length) { + revert MismatchedArrays(); + } + emit ApologySubmitted( + keyperSetIndex, + retryCounter, + keyperIndex, + accuserIndices, + polyEvalData + ); + } } diff --git a/test/DKGContract.t.sol b/test/DKGContract.t.sol index d307f13..bdadfdf 100644 --- a/test/DKGContract.t.sol +++ b/test/DKGContract.t.sol @@ -23,6 +23,28 @@ contract DKGContractTest is Test { address keyper1 = address(0xA1); address keyper2 = address(0xA2); + // Event signatures mirrored from DKGContract for vm.expectEmit usage. + event DealingSubmitted( + uint64 indexed keyperSetIndex, + uint64 indexed retryCounter, + uint64 indexed keyperIndex, + bytes commitment, + bytes polyEval + ); + event AccusationSubmitted( + uint64 indexed keyperSetIndex, + uint64 indexed retryCounter, + uint64 indexed keyperIndex, + uint64[] accusedIndices + ); + event ApologySubmitted( + uint64 indexed keyperSetIndex, + uint64 indexed retryCounter, + uint64 indexed keyperIndex, + uint64[] accuserIndices, + bytes[] polyEvalData + ); + function setUp() public { address initializer = address(69); address sequencer = address(420); @@ -213,4 +235,175 @@ contract DKGContractTest is Test { ); assertEq(dkg.dkgStart(0, 0), int256(-1000)); } + + // --------------------------------------------------------------------- + // Bulletin-board message tests + // --------------------------------------------------------------------- + + uint64 constant DEALING_BLOCK = ACTIVATION_BLOCK_0 - DKG_LEAD_LENGTH; // 960 + uint64 constant ACCUSING_BLOCK = DEALING_BLOCK + PHASE_LENGTH; // 970 + uint64 constant APOLOGIZING_BLOCK = DEALING_BLOCK + 2 * PHASE_LENGTH; // 980 + uint64 constant FINALIZING_BLOCK = DEALING_BLOCK + 3 * PHASE_LENGTH; // 990 + + // submitDealing + + function testSubmitDealingEmitsEvent() public { + vm.roll(DEALING_BLOCK); + bytes memory commitment = hex"deadbeef"; + bytes memory polyEval = hex"cafe"; + vm.expectEmit(true, true, true, true, address(dkgContract)); + emit DealingSubmitted(0, 0, 0, commitment, polyEval); + vm.prank(keyper0); + dkgContract.submitDealing(0, 0, 0, commitment, polyEval); + } + + function testSubmitDealingRevertsOutsideDealing() public { + bytes memory commitment = hex"01"; + bytes memory polyEval = hex"02"; + // Accusing + vm.roll(ACCUSING_BLOCK); + vm.prank(keyper0); + vm.expectRevert(DKGContract.WrongPhase.selector); + dkgContract.submitDealing(0, 0, 0, commitment, polyEval); + // One block before Dealing starts + vm.roll(DEALING_BLOCK - 1); + vm.prank(keyper0); + vm.expectRevert(DKGContract.WrongPhase.selector); + dkgContract.submitDealing(0, 0, 0, commitment, polyEval); + // One block after Dealing ends + vm.roll(DEALING_BLOCK + PHASE_LENGTH); + vm.prank(keyper0); + vm.expectRevert(DKGContract.WrongPhase.selector); + dkgContract.submitDealing(0, 0, 0, commitment, polyEval); + } + + function testSubmitDealingRevertsWhenSenderIsNotMember() public { + vm.roll(DEALING_BLOCK); + vm.prank(address(0xBEEF)); + vm.expectRevert(DKGContract.NotKeyperAtIndex.selector); + dkgContract.submitDealing(0, 0, 0, hex"01", hex"02"); + } + + function testSubmitDealingRevertsWhenIndexMismatchesSender() public { + vm.roll(DEALING_BLOCK); + // keyper0 is at index 0; passing index 1 should be rejected. + vm.prank(keyper0); + vm.expectRevert(DKGContract.NotKeyperAtIndex.selector); + dkgContract.submitDealing(0, 0, 1, hex"01", hex"02"); + } + + // submitAccusation + + function testSubmitAccusationEmitsEvent() public { + vm.roll(ACCUSING_BLOCK); + uint64[] memory accused = new uint64[](2); + accused[0] = 1; + accused[1] = 2; + vm.expectEmit(true, true, true, true, address(dkgContract)); + emit AccusationSubmitted(0, 0, 0, accused); + vm.prank(keyper0); + dkgContract.submitAccusation(0, 0, 0, accused); + } + + function testSubmitAccusationRevertsOutsideAccusing() public { + uint64[] memory accused = new uint64[](1); + accused[0] = 1; + // Dealing + vm.roll(DEALING_BLOCK); + vm.prank(keyper0); + vm.expectRevert(DKGContract.WrongPhase.selector); + dkgContract.submitAccusation(0, 0, 0, accused); + // Apologizing + vm.roll(APOLOGIZING_BLOCK); + vm.prank(keyper0); + vm.expectRevert(DKGContract.WrongPhase.selector); + dkgContract.submitAccusation(0, 0, 0, accused); + } + + function testSubmitAccusationRevertsWhenIndexMismatchesSender() public { + vm.roll(ACCUSING_BLOCK); + uint64[] memory accused = new uint64[](1); + accused[0] = 2; + vm.prank(keyper0); + vm.expectRevert(DKGContract.NotKeyperAtIndex.selector); + dkgContract.submitAccusation(0, 0, 1, accused); + } + + function testSubmitAccusationRevertsOnEmptyArray() public { + // Decision: empty accusedIndices reverts. An empty accusation has no + // protocol meaning; clients should skip the call instead. + vm.roll(ACCUSING_BLOCK); + uint64[] memory empty = new uint64[](0); + vm.prank(keyper0); + vm.expectRevert(DKGContract.EmptyAccusation.selector); + dkgContract.submitAccusation(0, 0, 0, empty); + } + + // submitApology + + function testSubmitApologyEmitsEvent() public { + vm.roll(APOLOGIZING_BLOCK); + uint64[] memory accusers = new uint64[](2); + accusers[0] = 1; + accusers[1] = 2; + bytes[] memory polyEvals = new bytes[](2); + polyEvals[0] = hex"aa"; + polyEvals[1] = hex"bb"; + vm.expectEmit(true, true, true, true, address(dkgContract)); + emit ApologySubmitted(0, 0, 0, accusers, polyEvals); + vm.prank(keyper0); + dkgContract.submitApology(0, 0, 0, accusers, polyEvals); + } + + function testSubmitApologyRevertsOutsideApologizing() public { + uint64[] memory accusers = new uint64[](1); + accusers[0] = 1; + bytes[] memory polyEvals = new bytes[](1); + polyEvals[0] = hex"aa"; + // Accusing + vm.roll(ACCUSING_BLOCK); + vm.prank(keyper0); + vm.expectRevert(DKGContract.WrongPhase.selector); + dkgContract.submitApology(0, 0, 0, accusers, polyEvals); + // Finalizing + vm.roll(FINALIZING_BLOCK); + vm.prank(keyper0); + vm.expectRevert(DKGContract.WrongPhase.selector); + dkgContract.submitApology(0, 0, 0, accusers, polyEvals); + } + + function testSubmitApologyRevertsOnMismatchedArrays() public { + vm.roll(APOLOGIZING_BLOCK); + uint64[] memory accusers = new uint64[](2); + accusers[0] = 1; + accusers[1] = 2; + bytes[] memory polyEvals = new bytes[](1); + polyEvals[0] = hex"aa"; + vm.prank(keyper0); + vm.expectRevert(DKGContract.MismatchedArrays.selector); + dkgContract.submitApology(0, 0, 0, accusers, polyEvals); + } + + function testSubmitApologyRevertsWhenIndexMismatchesSender() public { + vm.roll(APOLOGIZING_BLOCK); + uint64[] memory accusers = new uint64[](1); + accusers[0] = 0; + bytes[] memory polyEvals = new bytes[](1); + polyEvals[0] = hex"aa"; + vm.prank(keyper0); + vm.expectRevert(DKGContract.NotKeyperAtIndex.selector); + dkgContract.submitApology(0, 0, 2, accusers, polyEvals); + } + + function testSubmitApologyAcceptsEmptyArrays() public { + // An apologizer with no accusers to respond to is a valid no-op for + // batching symmetry; the function still records the call as an event. + vm.roll(APOLOGIZING_BLOCK); + uint64[] memory accusers = new uint64[](0); + bytes[] memory polyEvals = new bytes[](0); + vm.expectEmit(true, true, true, true, address(dkgContract)); + emit ApologySubmitted(0, 0, 0, accusers, polyEvals); + vm.prank(keyper0); + dkgContract.submitApology(0, 0, 0, accusers, polyEvals); + } } From e05fff38833b1f713e9eaa0af16ae80706747993 Mon Sep 17 00:00:00 2001 From: Jannik Date: Wed, 20 May 2026 10:28:19 +0200 Subject: [PATCH 05/25] Add DKG success-voting mechanism (issue #004) Implements submitSuccessVote(keyperSetIndex, retryCounter, keyperIndex, eonPublicKey) on DKGContract. Accepts votes only during the Finalizing phase, verifies caller membership, and prevents double-voting per (keyperSetIndex, retryCounter, voter). When a key hash reaches KeyperSet.getThreshold(): - succeeded[keyperSetIndex] = true (gates all message functions) - KeyBroadcastContract.broadcastEonKey is invoked in try/catch so an already-broadcast key (or unauthorized publisher) does not block recording success. - DKGSucceeded event is emitted regardless of the broadcast outcome. Late-arriving votes within the same Finalizing window are accepted and emit SuccessVoteSubmitted but do not re-trigger success once it has already been recorded. State added: voteCount[k][r][keyHash], hasVoted[k][r][voter]. Events added: SuccessVoteSubmitted, DKGSucceeded. Error: AlreadyVoted. setUp now sets the DKGContract as keyperSet0's publisher before finalization so the threshold-reached broadcast succeeds in the default fixture. The silent-revert case constructs its own keyper set with a different publisher. Tests cover phase rejection, identity, double-vote, threshold counting (per-key-hash isolation, no broadcast below threshold), silent broadcast failure, post-success rejection across all message types, concurrent keyper-set independence, and the r=0/r=1 retry boundary. --- src/common/DKGContract.sol | 64 +++++++++ test/DKGContract.t.sol | 288 +++++++++++++++++++++++++++++++++++++ 2 files changed, 352 insertions(+) diff --git a/src/common/DKGContract.sol b/src/common/DKGContract.sol index ba4cbd0..69e46c6 100644 --- a/src/common/DKGContract.sol +++ b/src/common/DKGContract.sol @@ -18,6 +18,7 @@ contract DKGContract { error AlreadySucceeded(); error EmptyAccusation(); error MismatchedArrays(); + error AlreadyVoted(); event DealingSubmitted( uint64 indexed keyperSetIndex, @@ -39,6 +40,17 @@ contract DKGContract { uint64[] accuserIndices, bytes[] polyEvalData ); + event SuccessVoteSubmitted( + uint64 indexed keyperSetIndex, + uint64 indexed retryCounter, + uint64 indexed keyperIndex, + bytes eonPublicKey + ); + event DKGSucceeded( + uint64 indexed keyperSetIndex, + uint64 indexed retryCounter, + bytes eonPublicKey + ); uint64 public immutable PHASE_LENGTH; uint64 public immutable DKG_LEAD_LENGTH; @@ -49,6 +61,10 @@ contract DKGContract { // success-vote threshold. Never reset — gates the success-triggering logic // in submitSuccessVote. mapping(uint64 => bool) public succeeded; + mapping(uint64 => mapping(uint64 => mapping(bytes32 => uint64))) + public voteCount; + mapping(uint64 => mapping(uint64 => mapping(address => bool))) + public hasVoted; constructor( uint64 phaseLength, @@ -187,4 +203,52 @@ contract DKGContract { polyEvalData ); } + + function submitSuccessVote( + uint64 keyperSetIndex, + uint64 retryCounter, + uint64 keyperIndex, + bytes calldata eonPublicKey + ) external { + _requirePhase(keyperSetIndex, retryCounter, Phase.Finalizing); + _checkMember(keyperSetIndex, keyperIndex); + if (hasVoted[keyperSetIndex][retryCounter][msg.sender]) { + revert AlreadyVoted(); + } + hasVoted[keyperSetIndex][retryCounter][msg.sender] = true; + + bytes32 keyHash = keccak256(eonPublicKey); + uint64 newCount = voteCount[keyperSetIndex][retryCounter][keyHash] + 1; + voteCount[keyperSetIndex][retryCounter][keyHash] = newCount; + + emit SuccessVoteSubmitted( + keyperSetIndex, + retryCounter, + keyperIndex, + eonPublicKey + ); + + // Late-arriving votes within the Finalizing window are accepted and + // emit the event above, but do not re-trigger success once it has + // already been recorded. + if (!succeeded[keyperSetIndex]) { + address keyperSetAddress = keyperSetManager.getKeyperSetAddress( + keyperSetIndex + ); + uint64 threshold = KeyperSet(keyperSetAddress).getThreshold(); + if (newCount >= threshold) { + succeeded[keyperSetIndex] = true; + // Errors are intentionally swallowed: if the key has already + // been broadcast (or the publisher is not authorized), the DKG + // outcome is still considered successful. + try + keyBroadcastContract.broadcastEonKey( + keyperSetIndex, + eonPublicKey + ) + {} catch {} + emit DKGSucceeded(keyperSetIndex, retryCounter, eonPublicKey); + } + } + } } diff --git a/test/DKGContract.t.sol b/test/DKGContract.t.sol index bdadfdf..621c1c9 100644 --- a/test/DKGContract.t.sol +++ b/test/DKGContract.t.sol @@ -44,6 +44,18 @@ contract DKGContractTest is Test { uint64[] accuserIndices, bytes[] polyEvalData ); + event SuccessVoteSubmitted( + uint64 indexed keyperSetIndex, + uint64 indexed retryCounter, + uint64 indexed keyperIndex, + bytes eonPublicKey + ); + event DKGSucceeded( + uint64 indexed keyperSetIndex, + uint64 indexed retryCounter, + bytes eonPublicKey + ); + event EonKeyBroadcast(uint64 eon, bytes key); function setUp() public { address initializer = address(69); @@ -71,6 +83,7 @@ contract DKGContractTest is Test { members[2] = keyper2; keyperSet0.addMembers(members); keyperSet0.setThreshold(2); + keyperSet0.setPublisher(address(dkgContract)); keyperSet0.setFinalized(); vm.prank(dao); keyperSetManager.addKeyperSet(ACTIVATION_BLOCK_0, address(keyperSet0)); @@ -406,4 +419,279 @@ contract DKGContractTest is Test { vm.prank(keyper0); dkgContract.submitApology(0, 0, 0, accusers, polyEvals); } + + // --------------------------------------------------------------------- + // submitSuccessVote + // --------------------------------------------------------------------- + + bytes constant EON_KEY_A = hex"1111"; + bytes constant EON_KEY_B = hex"2222"; + + function testSubmitSuccessVoteEmitsEvent() public { + vm.roll(FINALIZING_BLOCK); + vm.expectEmit(true, true, true, true, address(dkgContract)); + emit SuccessVoteSubmitted(0, 0, 0, EON_KEY_A); + vm.prank(keyper0); + dkgContract.submitSuccessVote(0, 0, 0, EON_KEY_A); + } + + function testSubmitSuccessVoteRevertsOutsideFinalizing() public { + // Dealing + vm.roll(DEALING_BLOCK); + vm.prank(keyper0); + vm.expectRevert(DKGContract.WrongPhase.selector); + dkgContract.submitSuccessVote(0, 0, 0, EON_KEY_A); + // Accusing + vm.roll(ACCUSING_BLOCK); + vm.prank(keyper0); + vm.expectRevert(DKGContract.WrongPhase.selector); + dkgContract.submitSuccessVote(0, 0, 0, EON_KEY_A); + // Apologizing + vm.roll(APOLOGIZING_BLOCK); + vm.prank(keyper0); + vm.expectRevert(DKGContract.WrongPhase.selector); + dkgContract.submitSuccessVote(0, 0, 0, EON_KEY_A); + // One block after Finalizing ends + vm.roll(FINALIZING_BLOCK + PHASE_LENGTH); + vm.prank(keyper0); + vm.expectRevert(DKGContract.WrongPhase.selector); + dkgContract.submitSuccessVote(0, 0, 0, EON_KEY_A); + } + + function testSubmitSuccessVoteRevertsWhenSenderIsNotMember() public { + vm.roll(FINALIZING_BLOCK); + vm.prank(address(0xBEEF)); + vm.expectRevert(DKGContract.NotKeyperAtIndex.selector); + dkgContract.submitSuccessVote(0, 0, 0, EON_KEY_A); + } + + function testSubmitSuccessVoteRevertsWhenIndexMismatchesSender() public { + vm.roll(FINALIZING_BLOCK); + vm.prank(keyper0); + vm.expectRevert(DKGContract.NotKeyperAtIndex.selector); + dkgContract.submitSuccessVote(0, 0, 1, EON_KEY_A); + } + + function testSubmitSuccessVoteRevertsOnDoubleVote() public { + vm.roll(FINALIZING_BLOCK); + vm.prank(keyper0); + dkgContract.submitSuccessVote(0, 0, 0, EON_KEY_A); + vm.prank(keyper0); + vm.expectRevert(DKGContract.AlreadyVoted.selector); + dkgContract.submitSuccessVote(0, 0, 0, EON_KEY_A); + } + + function testSubmitSuccessVoteAllowsDifferentKeyByDoubleVoter() public { + // The double-vote guard is per-address, not per-key — voting a second + // time with a different key from the same address is still rejected. + vm.roll(FINALIZING_BLOCK); + vm.prank(keyper0); + dkgContract.submitSuccessVote(0, 0, 0, EON_KEY_A); + vm.prank(keyper0); + vm.expectRevert(DKGContract.AlreadyVoted.selector); + dkgContract.submitSuccessVote(0, 0, 0, EON_KEY_B); + } + + function testBelowThresholdDoesNotBroadcast() public { + // Threshold is 2; a single vote must not trigger broadcast or succeed. + vm.roll(FINALIZING_BLOCK); + vm.prank(keyper0); + dkgContract.submitSuccessVote(0, 0, 0, EON_KEY_A); + assertFalse(dkgContract.succeeded(0)); + assertEq(keyBroadcastContract.getEonKey(0).length, 0); + } + + function testVotesForDifferentKeysCountedSeparately() public { + // Two votes for different keys — neither key reaches threshold of 2. + vm.roll(FINALIZING_BLOCK); + vm.prank(keyper0); + dkgContract.submitSuccessVote(0, 0, 0, EON_KEY_A); + vm.prank(keyper1); + dkgContract.submitSuccessVote(0, 0, 1, EON_KEY_B); + assertFalse(dkgContract.succeeded(0)); + assertEq(keyBroadcastContract.getEonKey(0).length, 0); + } + + function testThresholdReachedTriggersBroadcastAndSuccessEvent() public { + vm.roll(FINALIZING_BLOCK); + vm.prank(keyper0); + dkgContract.submitSuccessVote(0, 0, 0, EON_KEY_A); + // Second identical vote reaches threshold (2). Both the DKG success + // event and the KeyBroadcastContract broadcast event must fire. + vm.expectEmit(true, true, true, true, address(dkgContract)); + emit SuccessVoteSubmitted(0, 0, 1, EON_KEY_A); + vm.expectEmit(false, false, false, true, address(keyBroadcastContract)); + emit EonKeyBroadcast(0, EON_KEY_A); + vm.expectEmit(true, true, false, true, address(dkgContract)); + emit DKGSucceeded(0, 0, EON_KEY_A); + vm.prank(keyper1); + dkgContract.submitSuccessVote(0, 0, 1, EON_KEY_A); + assertTrue(dkgContract.succeeded(0)); + assertEq(keyBroadcastContract.getEonKey(0), EON_KEY_A); + } + + function testSuccessRecordedWhenBroadcastReverts() public { + // Deploy a separate keyper set whose publisher is NOT the DKG contract. + // Calls to broadcastEonKey will revert with NotAllowed; the DKG + // contract must swallow the error but still set succeeded[k] and emit + // its success event. + KeyperSet keyperSet1 = new KeyperSet(); + address[] memory members = new address[](3); + members[0] = keyper0; + members[1] = keyper1; + members[2] = keyper2; + keyperSet1.addMembers(members); + keyperSet1.setThreshold(2); + keyperSet1.setPublisher(address(0xDEAD)); // not the DKG contract + keyperSet1.setFinalized(); + uint64 activation1 = ACTIVATION_BLOCK_0 * 2; + vm.prank(dao); + keyperSetManager.addKeyperSet(activation1, address(keyperSet1)); + + uint64 finalizingBlock1 = activation1 - + DKG_LEAD_LENGTH + + 3 * + PHASE_LENGTH; + vm.roll(finalizingBlock1); + vm.prank(keyper0); + dkgContract.submitSuccessVote(1, 0, 0, EON_KEY_A); + // Threshold-th vote — broadcast reverts internally but the DKG + // contract still records success. + vm.expectEmit(true, true, false, true, address(dkgContract)); + emit DKGSucceeded(1, 0, EON_KEY_A); + vm.prank(keyper1); + dkgContract.submitSuccessVote(1, 0, 1, EON_KEY_A); + assertTrue(dkgContract.succeeded(1)); + assertEq(keyBroadcastContract.getEonKey(1).length, 0); + } + + // --------------------------------------------------------------------- + // Post-success behavior + // --------------------------------------------------------------------- + + function _drive_to_success_for_set0() internal { + vm.roll(FINALIZING_BLOCK); + vm.prank(keyper0); + dkgContract.submitSuccessVote(0, 0, 0, EON_KEY_A); + vm.prank(keyper1); + dkgContract.submitSuccessVote(0, 0, 1, EON_KEY_A); + assertTrue(dkgContract.succeeded(0)); + } + + function testPostSuccessRejectsDealingForNewRetry() public { + _drive_to_success_for_set0(); + // Even during r=1 Dealing, succeeded[k] blocks further messages. + vm.roll(DKG_START_R0 + CYCLE_LENGTH); // r=1 Dealing start + vm.prank(keyper0); + vm.expectRevert(DKGContract.AlreadySucceeded.selector); + dkgContract.submitDealing(0, 1, 0, hex"01", hex"02"); + } + + function testPostSuccessRejectsAccusationForNewRetry() public { + _drive_to_success_for_set0(); + vm.roll(DKG_START_R0 + CYCLE_LENGTH + PHASE_LENGTH); // r=1 Accusing + uint64[] memory accused = new uint64[](1); + accused[0] = 1; + vm.prank(keyper0); + vm.expectRevert(DKGContract.AlreadySucceeded.selector); + dkgContract.submitAccusation(0, 1, 0, accused); + } + + function testPostSuccessRejectsApologyForNewRetry() public { + _drive_to_success_for_set0(); + vm.roll(DKG_START_R0 + CYCLE_LENGTH + 2 * PHASE_LENGTH); // r=1 Apologizing + uint64[] memory accusers = new uint64[](1); + accusers[0] = 1; + bytes[] memory polyEvals = new bytes[](1); + polyEvals[0] = hex"01"; + vm.prank(keyper0); + vm.expectRevert(DKGContract.AlreadySucceeded.selector); + dkgContract.submitApology(0, 1, 0, accusers, polyEvals); + } + + function testPostSuccessSuccessVoteEmitsEventWithoutNewSuccess() public { + // After success for r=0, a late vote in r=0's Finalizing window (if + // still open) is accepted and emits SuccessVoteSubmitted but must not + // re-emit DKGSucceeded or re-broadcast the key. + vm.roll(FINALIZING_BLOCK); + // Drive to success with keyper0 and keyper1 (threshold = 2). + vm.prank(keyper0); + dkgContract.submitSuccessVote(0, 0, 0, EON_KEY_A); + vm.prank(keyper1); + dkgContract.submitSuccessVote(0, 0, 1, EON_KEY_A); + assertTrue(dkgContract.succeeded(0)); + + // keyper2 arrives late in the same Finalizing window. + vm.expectEmit(true, true, true, true, address(dkgContract)); + emit SuccessVoteSubmitted(0, 0, 2, EON_KEY_A); + vm.prank(keyper2); + dkgContract.submitSuccessVote(0, 0, 2, EON_KEY_A); + } + + // --------------------------------------------------------------------- + // Concurrent DKG instances and retry boundary + // --------------------------------------------------------------------- + + function testConcurrentDKGInstancesAreIndependent() public { + // Deploy a second keyper set with a different activation block so + // (k=0, r=0) and (k=1, r=0) have disjoint phase windows. + KeyperSet keyperSet1 = new KeyperSet(); + address[] memory members = new address[](3); + members[0] = keyper0; + members[1] = keyper1; + members[2] = keyper2; + keyperSet1.addMembers(members); + keyperSet1.setThreshold(2); + keyperSet1.setPublisher(address(dkgContract)); + keyperSet1.setFinalized(); + uint64 activation1 = ACTIVATION_BLOCK_0 * 2; // 2000 + vm.prank(dao); + keyperSetManager.addKeyperSet(activation1, address(keyperSet1)); + + // At (k=0, r=0) Dealing: messages for k=1 must revert (Phase.None), + // messages for k=0 accepted. + vm.roll(DEALING_BLOCK); + vm.prank(keyper0); + dkgContract.submitDealing(0, 0, 0, hex"aa", hex""); + vm.prank(keyper0); + vm.expectRevert(DKGContract.WrongPhase.selector); + dkgContract.submitDealing(1, 0, 0, hex"aa", hex""); + + // At (k=1, r=0) Dealing: messages for k=1 accepted, k=0 in Phase.None. + uint64 k1DealingBlock = activation1 - DKG_LEAD_LENGTH; + vm.roll(k1DealingBlock); + vm.prank(keyper0); + dkgContract.submitDealing(1, 0, 0, hex"bb", hex""); + vm.prank(keyper0); + vm.expectRevert(DKGContract.WrongPhase.selector); + dkgContract.submitDealing(0, 0, 0, hex"bb", hex""); + + // Reaching success on k=1 must not set succeeded[0]. + uint64 k1FinalizingBlock = k1DealingBlock + 3 * PHASE_LENGTH; + vm.roll(k1FinalizingBlock); + vm.prank(keyper0); + dkgContract.submitSuccessVote(1, 0, 0, EON_KEY_A); + vm.prank(keyper1); + dkgContract.submitSuccessVote(1, 0, 1, EON_KEY_A); + assertTrue(dkgContract.succeeded(1)); + assertFalse(dkgContract.succeeded(0)); + } + + function testRetryDealingForR1RejectedDuringR0Dealing() public { + vm.roll(DEALING_BLOCK); + vm.prank(keyper0); + vm.expectRevert(DKGContract.WrongPhase.selector); + dkgContract.submitDealing(0, 1, 0, hex"01", hex""); + } + + function testRetryDealingForR1AcceptedAfterR0CycleElapsed() public { + // r=0 Finalizing ends at DKG_START_R0 + CYCLE_LENGTH; r=1 Dealing + // begins there. A dealing submission for (k=0, r=1) must be accepted. + uint64 r1DealingStart = DKG_START_R0 + CYCLE_LENGTH; + vm.roll(r1DealingStart); + vm.expectEmit(true, true, true, true, address(dkgContract)); + emit DealingSubmitted(0, 1, 0, hex"01", hex""); + vm.prank(keyper0); + dkgContract.submitDealing(0, 1, 0, hex"01", hex""); + } } From c79c6371a64700eceaddd05ab4be47912c8559ef Mon Sep 17 00:00:00 2001 From: Jannik Date: Wed, 20 May 2026 19:32:13 +0200 Subject: [PATCH 06/25] Change submitDealing/DealingSubmitted polyEval to bytes[] Replace the opaque ABI-encoded bytes blob with a native bytes[] so the Go binding handles encoding and decoding without bespoke helpers. Key decisions: - Empty arrays are accepted for backward compatibility with the existing testConcurrentDKGInstancesAreIndependent / retry-dealing tests, which previously passed an empty bytes blob. Files changed: - src/common/DKGContract.sol: submitDealing argument and DealingSubmitted event now use bytes[] for polyEvals - test/DKGContract.t.sol: all submitDealing call sites and the mirrored event signature updated to bytes[] --- src/common/DKGContract.sol | 6 ++--- test/DKGContract.t.sol | 48 ++++++++++++++++++++++++-------------- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/common/DKGContract.sol b/src/common/DKGContract.sol index 69e46c6..0e3bbd4 100644 --- a/src/common/DKGContract.sol +++ b/src/common/DKGContract.sol @@ -25,7 +25,7 @@ contract DKGContract { uint64 indexed retryCounter, uint64 indexed keyperIndex, bytes commitment, - bytes polyEval + bytes[] polyEvals ); event AccusationSubmitted( uint64 indexed keyperSetIndex, @@ -146,7 +146,7 @@ contract DKGContract { uint64 retryCounter, uint64 keyperIndex, bytes calldata commitment, - bytes calldata polyEval + bytes[] calldata polyEvals ) external { _requireNotSucceeded(keyperSetIndex); _requirePhase(keyperSetIndex, retryCounter, Phase.Dealing); @@ -156,7 +156,7 @@ contract DKGContract { retryCounter, keyperIndex, commitment, - polyEval + polyEvals ); } diff --git a/test/DKGContract.t.sol b/test/DKGContract.t.sol index 621c1c9..8d0e080 100644 --- a/test/DKGContract.t.sol +++ b/test/DKGContract.t.sol @@ -29,7 +29,7 @@ contract DKGContractTest is Test { uint64 indexed retryCounter, uint64 indexed keyperIndex, bytes commitment, - bytes polyEval + bytes[] polyEvals ); event AccusationSubmitted( uint64 indexed keyperSetIndex, @@ -263,46 +263,53 @@ contract DKGContractTest is Test { function testSubmitDealingEmitsEvent() public { vm.roll(DEALING_BLOCK); bytes memory commitment = hex"deadbeef"; - bytes memory polyEval = hex"cafe"; + bytes[] memory polyEvals = new bytes[](2); + polyEvals[0] = hex"cafe"; + polyEvals[1] = hex"f00d"; vm.expectEmit(true, true, true, true, address(dkgContract)); - emit DealingSubmitted(0, 0, 0, commitment, polyEval); + emit DealingSubmitted(0, 0, 0, commitment, polyEvals); vm.prank(keyper0); - dkgContract.submitDealing(0, 0, 0, commitment, polyEval); + dkgContract.submitDealing(0, 0, 0, commitment, polyEvals); } function testSubmitDealingRevertsOutsideDealing() public { bytes memory commitment = hex"01"; - bytes memory polyEval = hex"02"; + bytes[] memory polyEvals = new bytes[](1); + polyEvals[0] = hex"02"; // Accusing vm.roll(ACCUSING_BLOCK); vm.prank(keyper0); vm.expectRevert(DKGContract.WrongPhase.selector); - dkgContract.submitDealing(0, 0, 0, commitment, polyEval); + dkgContract.submitDealing(0, 0, 0, commitment, polyEvals); // One block before Dealing starts vm.roll(DEALING_BLOCK - 1); vm.prank(keyper0); vm.expectRevert(DKGContract.WrongPhase.selector); - dkgContract.submitDealing(0, 0, 0, commitment, polyEval); + dkgContract.submitDealing(0, 0, 0, commitment, polyEvals); // One block after Dealing ends vm.roll(DEALING_BLOCK + PHASE_LENGTH); vm.prank(keyper0); vm.expectRevert(DKGContract.WrongPhase.selector); - dkgContract.submitDealing(0, 0, 0, commitment, polyEval); + dkgContract.submitDealing(0, 0, 0, commitment, polyEvals); } function testSubmitDealingRevertsWhenSenderIsNotMember() public { vm.roll(DEALING_BLOCK); + bytes[] memory polyEvals = new bytes[](1); + polyEvals[0] = hex"02"; vm.prank(address(0xBEEF)); vm.expectRevert(DKGContract.NotKeyperAtIndex.selector); - dkgContract.submitDealing(0, 0, 0, hex"01", hex"02"); + dkgContract.submitDealing(0, 0, 0, hex"01", polyEvals); } function testSubmitDealingRevertsWhenIndexMismatchesSender() public { vm.roll(DEALING_BLOCK); + bytes[] memory polyEvals = new bytes[](1); + polyEvals[0] = hex"02"; // keyper0 is at index 0; passing index 1 should be rejected. vm.prank(keyper0); vm.expectRevert(DKGContract.NotKeyperAtIndex.selector); - dkgContract.submitDealing(0, 0, 1, hex"01", hex"02"); + dkgContract.submitDealing(0, 0, 1, hex"01", polyEvals); } // submitAccusation @@ -582,9 +589,11 @@ contract DKGContractTest is Test { _drive_to_success_for_set0(); // Even during r=1 Dealing, succeeded[k] blocks further messages. vm.roll(DKG_START_R0 + CYCLE_LENGTH); // r=1 Dealing start + bytes[] memory polyEvals = new bytes[](1); + polyEvals[0] = hex"02"; vm.prank(keyper0); vm.expectRevert(DKGContract.AlreadySucceeded.selector); - dkgContract.submitDealing(0, 1, 0, hex"01", hex"02"); + dkgContract.submitDealing(0, 1, 0, hex"01", polyEvals); } function testPostSuccessRejectsAccusationForNewRetry() public { @@ -650,21 +659,22 @@ contract DKGContractTest is Test { // At (k=0, r=0) Dealing: messages for k=1 must revert (Phase.None), // messages for k=0 accepted. + bytes[] memory emptyEvals = new bytes[](0); vm.roll(DEALING_BLOCK); vm.prank(keyper0); - dkgContract.submitDealing(0, 0, 0, hex"aa", hex""); + dkgContract.submitDealing(0, 0, 0, hex"aa", emptyEvals); vm.prank(keyper0); vm.expectRevert(DKGContract.WrongPhase.selector); - dkgContract.submitDealing(1, 0, 0, hex"aa", hex""); + dkgContract.submitDealing(1, 0, 0, hex"aa", emptyEvals); // At (k=1, r=0) Dealing: messages for k=1 accepted, k=0 in Phase.None. uint64 k1DealingBlock = activation1 - DKG_LEAD_LENGTH; vm.roll(k1DealingBlock); vm.prank(keyper0); - dkgContract.submitDealing(1, 0, 0, hex"bb", hex""); + dkgContract.submitDealing(1, 0, 0, hex"bb", emptyEvals); vm.prank(keyper0); vm.expectRevert(DKGContract.WrongPhase.selector); - dkgContract.submitDealing(0, 0, 0, hex"bb", hex""); + dkgContract.submitDealing(0, 0, 0, hex"bb", emptyEvals); // Reaching success on k=1 must not set succeeded[0]. uint64 k1FinalizingBlock = k1DealingBlock + 3 * PHASE_LENGTH; @@ -679,19 +689,21 @@ contract DKGContractTest is Test { function testRetryDealingForR1RejectedDuringR0Dealing() public { vm.roll(DEALING_BLOCK); + bytes[] memory emptyEvals = new bytes[](0); vm.prank(keyper0); vm.expectRevert(DKGContract.WrongPhase.selector); - dkgContract.submitDealing(0, 1, 0, hex"01", hex""); + dkgContract.submitDealing(0, 1, 0, hex"01", emptyEvals); } function testRetryDealingForR1AcceptedAfterR0CycleElapsed() public { // r=0 Finalizing ends at DKG_START_R0 + CYCLE_LENGTH; r=1 Dealing // begins there. A dealing submission for (k=0, r=1) must be accepted. uint64 r1DealingStart = DKG_START_R0 + CYCLE_LENGTH; + bytes[] memory emptyEvals = new bytes[](0); vm.roll(r1DealingStart); vm.expectEmit(true, true, true, true, address(dkgContract)); - emit DealingSubmitted(0, 1, 0, hex"01", hex""); + emit DealingSubmitted(0, 1, 0, hex"01", emptyEvals); vm.prank(keyper0); - dkgContract.submitDealing(0, 1, 0, hex"01", hex""); + dkgContract.submitDealing(0, 1, 0, hex"01", emptyEvals); } } From f0d8cac76cc8a8cd5d4beb4ac6c9ddd48bc65b8b Mon Sep 17 00:00:00 2001 From: Jannik Date: Wed, 20 May 2026 19:43:03 +0200 Subject: [PATCH 07/25] Add dkgContract address field to KeyperSet Add `dkgContract` slot, owner-only pre-finalization setter `setDKGContract`, and `getDKGContract` view getter to KeyperSet.sol. Expose `getDKGContract` on the IKeyperSet interface so the Go keyper can read it through the typed binding when handling KeyperSetAdded. Tests: - forge test passes (116 tests, incl. new testDKGContract, testSetDKGContractOnlyOwner, and the after-finalized revert case) - go build ./... passes for the regenerated keyperset binding Files: - src/common/KeyperSet.sol - src/common/intf/IKeyperSet.sol - test/KeyperSet.t.sol - bindings/keyperset/keyperset.go (regenerated) Notes for next iteration: - E2E tests in mise-test-setup were not run: the foundry/anvil docker image is linux/amd64 and the sandbox is arm64, so the ethereum container fails with `exec format error`. Acceptance criteria of this task only require forge test + go build. - Unblocks docs/dkg-module-refactor/contract-updates/003 (eons per- keyperset phase params), which will call GetDKGContract from Go and store phase_length/lead_length on the eons row. Co-Authored-By: Claude Opus 4.7 (1M context) --- bindings/keyperset/keyperset.go | 56 +++++++++++++++++++++++++++++++-- src/common/KeyperSet.sol | 12 +++++++ src/common/intf/IKeyperSet.sol | 2 ++ test/KeyperSet.t.sol | 22 +++++++++++++ 4 files changed, 90 insertions(+), 2 deletions(-) diff --git a/bindings/keyperset/keyperset.go b/bindings/keyperset/keyperset.go index 5c068b7..882ab8b 100644 --- a/bindings/keyperset/keyperset.go +++ b/bindings/keyperset/keyperset.go @@ -31,8 +31,8 @@ var ( // KeypersetMetaData contains all meta data concerning the Keyperset contract. var KeypersetMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addMembers\",\"inputs\":[{\"name\":\"newMembers\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getMember\",\"inputs\":[{\"name\":\"index\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getMembers\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getNumMembers\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getPublisher\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getThreshold\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isAllowedToBroadcastEonKey\",\"inputs\":[{\"name\":\"a\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isFinalized\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setFinalized\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setPublisher\",\"inputs\":[{\"name\":\"_publisher\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setThreshold\",\"inputs\":[{\"name\":\"_threshold\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AlreadyFinalized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnableInvalidOwner\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OwnableUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}]}]", - Bin: "0x608060405234801561000f575f5ffd5b50335f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610081575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016100789190610196565b60405180910390fd5b6100908161009660201b60201c565b506101af565b5f5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61018082610157565b9050919050565b61019081610176565b82525050565b5f6020820190506101a95f830184610187565b92915050565b610bfa806101bc5f395ff3fe608060405234801561000f575f5ffd5b50600436106100e8575f3560e01c80638da5cb5b1161008a578063cde1532d11610064578063cde1532d146101fc578063dbf4ab4e1461022c578063e75235b81461024a578063f2fde38b14610268576100e8565b80638da5cb5b146101a45780639eab5253146101c2578063cab63661146101e0576100e8565b80632e8e6cad116100c65780632e8e6cad146101305780636f4d469b14610160578063715018a61461017c5780638d4e408314610186576100e8565b806317c4de35146100ec57806317d5430a146101085780631de7725314610126575b5f5ffd5b610106600480360381019061010191906108ae565b610284565b005b6101106102fd565b60405161011d91906108e8565b60405180910390f35b61012e610309565b005b61014a600480360381019061014591906108ae565b61032d565b6040516101579190610940565b60405180910390f35b61017a600480360381019061017591906109ba565b61037b565b005b61018461048c565b005b61018e61049f565b60405161019b9190610a1f565b60405180910390f35b6101ac6104b4565b6040516101b99190610940565b60405180910390f35b6101ca6104db565b6040516101d79190610aef565b60405180910390f35b6101fa60048036038101906101f59190610b39565b610566565b005b61021660048036038101906102119190610b39565b6105f8565b6040516102239190610a1f565b60405180910390f35b610234610651565b6040516102419190610940565b60405180910390f35b61025261067a565b60405161025f91906108e8565b60405180910390f35b610282600480360381019061027d9190610b39565b610696565b005b61028c61071a565b5f60149054906101000a900460ff16156102d2576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060025f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b5f600180549050905090565b61031161071a565b60015f60146101000a81548160ff021916908315150217905550565b5f60018267ffffffffffffffff168154811061034c5761034b610b64565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b61038361071a565b5f60149054906101000a900460ff16156103c9576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5f90505b828290508167ffffffffffffffff16101561048757600183838367ffffffffffffffff1681811061040257610401610b64565b5b90506020020160208101906104179190610b39565b908060018154018082558091505060019003905f5260205f20015f9091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808061047f90610bbe565b9150506103ce565b505050565b61049461071a565b61049d5f6107a1565b565b5f5f60149054906101000a900460ff16905090565b5f5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060600180548060200260200160405190810160405280929190818152602001828054801561055c57602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610513575b5050505050905090565b61056e61071a565b5f60149054906101000a900460ff16156105b4576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600260086101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f600260089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050919050565b5f600260089054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b5f60025f9054906101000a900467ffffffffffffffff16905090565b61069e61071a565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361070e575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016107059190610940565b60405180910390fd5b610717816107a1565b50565b610722610862565b73ffffffffffffffffffffffffffffffffffffffff166107406104b4565b73ffffffffffffffffffffffffffffffffffffffff161461079f57610763610862565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016107969190610940565b60405180910390fd5b565b5f5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f33905090565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82169050919050565b61088d81610871565b8114610897575f5ffd5b50565b5f813590506108a881610884565b92915050565b5f602082840312156108c3576108c2610869565b5b5f6108d08482850161089a565b91505092915050565b6108e281610871565b82525050565b5f6020820190506108fb5f8301846108d9565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61092a82610901565b9050919050565b61093a81610920565b82525050565b5f6020820190506109535f830184610931565b92915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f84011261097a57610979610959565b5b8235905067ffffffffffffffff8111156109975761099661095d565b5b6020830191508360208202830111156109b3576109b2610961565b5b9250929050565b5f5f602083850312156109d0576109cf610869565b5b5f83013567ffffffffffffffff8111156109ed576109ec61086d565b5b6109f985828601610965565b92509250509250929050565b5f8115159050919050565b610a1981610a05565b82525050565b5f602082019050610a325f830184610a10565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b610a6a81610920565b82525050565b5f610a7b8383610a61565b60208301905092915050565b5f602082019050919050565b5f610a9d82610a38565b610aa78185610a42565b9350610ab283610a52565b805f5b83811015610ae2578151610ac98882610a70565b9750610ad483610a87565b925050600181019050610ab5565b5085935050505092915050565b5f6020820190508181035f830152610b078184610a93565b905092915050565b610b1881610920565b8114610b22575f5ffd5b50565b5f81359050610b3381610b0f565b92915050565b5f60208284031215610b4e57610b4d610869565b5b5f610b5b84828501610b25565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610bc882610871565b915067ffffffffffffffff8203610be257610be1610b91565b5b60018201905091905056fea164736f6c634300081c000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addMembers\",\"inputs\":[{\"name\":\"newMembers\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getDKGContract\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getMember\",\"inputs\":[{\"name\":\"index\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getMembers\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getNumMembers\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getPublisher\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getThreshold\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isAllowedToBroadcastEonKey\",\"inputs\":[{\"name\":\"a\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isFinalized\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setDKGContract\",\"inputs\":[{\"name\":\"_dkgContract\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setFinalized\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setPublisher\",\"inputs\":[{\"name\":\"_publisher\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setThreshold\",\"inputs\":[{\"name\":\"_threshold\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AlreadyFinalized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnableInvalidOwner\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OwnableUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}]}]", + Bin: "0x608060405234801561000f575f5ffd5b50335f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610081575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016100789190610196565b60405180910390fd5b6100908161009660201b60201c565b506101af565b5f5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61018082610157565b9050919050565b61019081610176565b82525050565b5f6020820190506101a95f830184610187565b92915050565b610d02806101bc5f395ff3fe608060405234801561000f575f5ffd5b50600436106100fd575f3560e01c80638d4e408311610095578063cde1532d11610064578063cde1532d1461024b578063dbf4ab4e1461027b578063e75235b814610299578063f2fde38b146102b7576100fd565b80638d4e4083146101d55780638da5cb5b146101f35780639eab525314610211578063cab636611461022f576100fd565b80632e8e6cad116100d15780632e8e6cad146101635780636ab47aae146101935780636f4d469b146101af578063715018a6146101cb576100fd565b806266f0a81461010157806317c4de351461011f57806317d5430a1461013b5780631de7725314610159575b5f5ffd5b6101096102d3565b60405161011691906109b0565b60405180910390f35b61013960048036038101906101349190610a0e565b6102fb565b005b610143610374565b6040516101509190610a48565b60405180910390f35b610161610380565b005b61017d60048036038101906101789190610a0e565b6103a4565b60405161018a91906109b0565b60405180910390f35b6101ad60048036038101906101a89190610a8b565b6103f2565b005b6101c960048036038101906101c49190610b17565b610483565b005b6101d3610594565b005b6101dd6105a7565b6040516101ea9190610b7c565b60405180910390f35b6101fb6105bc565b60405161020891906109b0565b60405180910390f35b6102196105e3565b6040516102269190610c4c565b60405180910390f35b61024960048036038101906102449190610a8b565b61066e565b005b61026560048036038101906102609190610a8b565b610700565b6040516102729190610b7c565b60405180910390f35b610283610759565b60405161029091906109b0565b60405180910390f35b6102a1610782565b6040516102ae9190610a48565b60405180910390f35b6102d160048036038101906102cc9190610a8b565b61079e565b005b5f60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610303610822565b5f60149054906101000a900460ff1615610349576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060025f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b5f600180549050905090565b610388610822565b60015f60146101000a81548160ff021916908315150217905550565b5f60018267ffffffffffffffff16815481106103c3576103c2610c6c565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6103fa610822565b5f60149054906101000a900460ff1615610440576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060035f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61048b610822565b5f60149054906101000a900460ff16156104d1576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5f90505b828290508167ffffffffffffffff16101561058f57600183838367ffffffffffffffff1681811061050a57610509610c6c565b5b905060200201602081019061051f9190610a8b565b908060018154018082558091505060019003905f5260205f20015f9091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808061058790610cc6565b9150506104d6565b505050565b61059c610822565b6105a55f6108a9565b565b5f5f60149054906101000a900460ff16905090565b5f5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060600180548060200260200160405190810160405280929190818152602001828054801561066457602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161061b575b5050505050905090565b610676610822565b5f60149054906101000a900460ff16156106bc576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600260086101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f600260089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050919050565b5f600260089054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b5f60025f9054906101000a900467ffffffffffffffff16905090565b6107a6610822565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610816575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161080d91906109b0565b60405180910390fd5b61081f816108a9565b50565b61082a61096a565b73ffffffffffffffffffffffffffffffffffffffff166108486105bc565b73ffffffffffffffffffffffffffffffffffffffff16146108a75761086b61096a565b6040517f118cdaa700000000000000000000000000000000000000000000000000000000815260040161089e91906109b0565b60405180910390fd5b565b5f5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f33905090565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61099a82610971565b9050919050565b6109aa81610990565b82525050565b5f6020820190506109c35f8301846109a1565b92915050565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82169050919050565b6109ed816109d1565b81146109f7575f5ffd5b50565b5f81359050610a08816109e4565b92915050565b5f60208284031215610a2357610a226109c9565b5b5f610a30848285016109fa565b91505092915050565b610a42816109d1565b82525050565b5f602082019050610a5b5f830184610a39565b92915050565b610a6a81610990565b8114610a74575f5ffd5b50565b5f81359050610a8581610a61565b92915050565b5f60208284031215610aa057610a9f6109c9565b5b5f610aad84828501610a77565b91505092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f840112610ad757610ad6610ab6565b5b8235905067ffffffffffffffff811115610af457610af3610aba565b5b602083019150836020820283011115610b1057610b0f610abe565b5b9250929050565b5f5f60208385031215610b2d57610b2c6109c9565b5b5f83013567ffffffffffffffff811115610b4a57610b496109cd565b5b610b5685828601610ac2565b92509250509250929050565b5f8115159050919050565b610b7681610b62565b82525050565b5f602082019050610b8f5f830184610b6d565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b610bc781610990565b82525050565b5f610bd88383610bbe565b60208301905092915050565b5f602082019050919050565b5f610bfa82610b95565b610c048185610b9f565b9350610c0f83610baf565b805f5b83811015610c3f578151610c268882610bcd565b9750610c3183610be4565b925050600181019050610c12565b5085935050505092915050565b5f6020820190508181035f830152610c648184610bf0565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610cd0826109d1565b915067ffffffffffffffff8203610cea57610ce9610c99565b5b60018201905091905056fea164736f6c634300081c000a", } // KeypersetABI is the input ABI used to generate the binding from. @@ -202,6 +202,37 @@ func (_Keyperset *KeypersetTransactorRaw) Transact(opts *bind.TransactOpts, meth return _Keyperset.Contract.contract.Transact(opts, method, params...) } +// GetDKGContract is a free data retrieval call binding the contract method 0x0066f0a8. +// +// Solidity: function getDKGContract() view returns(address) +func (_Keyperset *KeypersetCaller) GetDKGContract(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Keyperset.contract.Call(opts, &out, "getDKGContract") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// GetDKGContract is a free data retrieval call binding the contract method 0x0066f0a8. +// +// Solidity: function getDKGContract() view returns(address) +func (_Keyperset *KeypersetSession) GetDKGContract() (common.Address, error) { + return _Keyperset.Contract.GetDKGContract(&_Keyperset.CallOpts) +} + +// GetDKGContract is a free data retrieval call binding the contract method 0x0066f0a8. +// +// Solidity: function getDKGContract() view returns(address) +func (_Keyperset *KeypersetCallerSession) GetDKGContract() (common.Address, error) { + return _Keyperset.Contract.GetDKGContract(&_Keyperset.CallOpts) +} + // GetMember is a free data retrieval call binding the contract method 0x2e8e6cad. // // Solidity: function getMember(uint64 index) view returns(address) @@ -492,6 +523,27 @@ func (_Keyperset *KeypersetTransactorSession) RenounceOwnership() (*types.Transa return _Keyperset.Contract.RenounceOwnership(&_Keyperset.TransactOpts) } +// SetDKGContract is a paid mutator transaction binding the contract method 0x6ab47aae. +// +// Solidity: function setDKGContract(address _dkgContract) returns() +func (_Keyperset *KeypersetTransactor) SetDKGContract(opts *bind.TransactOpts, _dkgContract common.Address) (*types.Transaction, error) { + return _Keyperset.contract.Transact(opts, "setDKGContract", _dkgContract) +} + +// SetDKGContract is a paid mutator transaction binding the contract method 0x6ab47aae. +// +// Solidity: function setDKGContract(address _dkgContract) returns() +func (_Keyperset *KeypersetSession) SetDKGContract(_dkgContract common.Address) (*types.Transaction, error) { + return _Keyperset.Contract.SetDKGContract(&_Keyperset.TransactOpts, _dkgContract) +} + +// SetDKGContract is a paid mutator transaction binding the contract method 0x6ab47aae. +// +// Solidity: function setDKGContract(address _dkgContract) returns() +func (_Keyperset *KeypersetTransactorSession) SetDKGContract(_dkgContract common.Address) (*types.Transaction, error) { + return _Keyperset.Contract.SetDKGContract(&_Keyperset.TransactOpts, _dkgContract) +} + // SetFinalized is a paid mutator transaction binding the contract method 0x1de77253. // // Solidity: function setFinalized() returns() diff --git a/src/common/KeyperSet.sol b/src/common/KeyperSet.sol index 683aa10..6df72ce 100644 --- a/src/common/KeyperSet.sol +++ b/src/common/KeyperSet.sol @@ -12,6 +12,7 @@ contract KeyperSet is Ownable, IKeyperSet { address[] members; uint64 threshold; address publisher; + address dkgContract; constructor() Ownable(msg.sender) {} @@ -39,6 +40,10 @@ contract KeyperSet is Ownable, IKeyperSet { return publisher; } + function getDKGContract() external view returns (address) { + return dkgContract; + } + function addMembers(address[] calldata newMembers) public onlyOwner { if (finalized) { revert AlreadyFinalized(); @@ -62,6 +67,13 @@ contract KeyperSet is Ownable, IKeyperSet { publisher = _publisher; } + function setDKGContract(address _dkgContract) public onlyOwner { + if (finalized) { + revert AlreadyFinalized(); + } + dkgContract = _dkgContract; + } + function setFinalized() public onlyOwner { finalized = true; } diff --git a/src/common/intf/IKeyperSet.sol b/src/common/intf/IKeyperSet.sol index 5c047d9..e7538b7 100644 --- a/src/common/intf/IKeyperSet.sol +++ b/src/common/intf/IKeyperSet.sol @@ -12,5 +12,7 @@ interface IKeyperSet { function getThreshold() external view returns (uint64); + function getDKGContract() external view returns (address); + function isAllowedToBroadcastEonKey(address a) external view returns (bool); } diff --git a/test/KeyperSet.t.sol b/test/KeyperSet.t.sol index 438f621..77f921f 100644 --- a/test/KeyperSet.t.sol +++ b/test/KeyperSet.t.sol @@ -27,6 +27,11 @@ contract KeyperSetRevertAfterFinalizedTest is Test { vm.expectRevert(AlreadyFinalized.selector); keyperSet.setPublisher(address(5)); } + + function testSetDKGContract() public { + vm.expectRevert(AlreadyFinalized.selector); + keyperSet.setDKGContract(address(5)); + } } contract KeyperSetTest is Test { @@ -131,4 +136,21 @@ contract KeyperSetTest is Test { assertEq(keyperSet.isAllowedToBroadcastEonKey(address(1)), false); assertEq(keyperSet.isAllowedToBroadcastEonKey(address(5)), true); } + + function testDKGContract() public { + assertEq(keyperSet.getDKGContract(), address(0)); + keyperSet.setDKGContract(address(42)); + assertEq(keyperSet.getDKGContract(), address(42)); + } + + function testSetDKGContractOnlyOwner() public { + vm.expectRevert( + abi.encodeWithSelector( + Ownable.OwnableUnauthorizedAccount.selector, + address(1) + ) + ); + vm.prank(address(1)); + keyperSet.setDKGContract(address(5)); + } } From 748f5aa6b7835f485ee5455572f9f1aa884c680f Mon Sep 17 00:00:00 2001 From: Jannik Date: Wed, 20 May 2026 20:20:08 +0200 Subject: [PATCH 08/25] Add happy-path DKG gas benchmark MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Forge test contract `DKGBenchmark` that measures total on-chain gas for a clean DKG run (n submitDealing calls + ⌈2n/3⌉ submitSuccessVote calls) at n = 3, 5, 10, 20, 50. Setup gas — contract deployment and keyper set creation — is excluded; only protocol operation cost is accumulated via gasleft() deltas around each contract call. Key decisions: - Realistic, non-zero (0xAB) payload sizes from the PRD: commitment = 4 + threshold × 96 bytes, each PolyEvals entry = 129 bytes (ECIES), EonPublicKey = 96 bytes. Non-zero bytes cost 16 gas/byte in calldata and match real BLS/ECIES data. - Threshold via integer ⌈2n/3⌉ = (2n + 2) / 3. - Fresh KeyperSetManager / KeyBroadcastContract / DKGContract per test so warm-storage artefacts from earlier runs do not contaminate results. - Per-test console.log line emits scenario, n, threshold, and gas total for easy parsing. Measured gas (monotonic by design — quadratic calldata dominates): n=3 → 293,144 n=5 → 457,151 n=10 → 901,165 n=20 → 2,368,268 n=50 → 10,962,537 Files changed: - test/DKGBenchmark.t.sol (new) Notes for next iteration: - 002-worst-case-benchmark extends this with Accusing + Apologizing phases, accumulating into the same totalGas counter and adding five test_worstCase_n* entry points. - Rolling-shutter e2e suite could not be exercised in this sandbox (postgres/sqlc downloads firewall-blocked); the change is purely additive Forge test code so it cannot regress Go paths. Co-Authored-By: Claude Opus 4.7 (1M context) --- test/DKGBenchmark.t.sol | 171 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 test/DKGBenchmark.t.sol diff --git a/test/DKGBenchmark.t.sol b/test/DKGBenchmark.t.sol new file mode 100644 index 0000000..7edad0e --- /dev/null +++ b/test/DKGBenchmark.t.sol @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.22; + +import "forge-std/Test.sol"; +import "forge-std/console.sol"; +import "../src/common/DKGContract.sol"; +import "../src/common/KeyperSet.sol"; +import "../src/common/KeyperSetManager.sol"; +import "../src/common/KeyBroadcastContract.sol"; + +/// @title DKG Contract gas benchmark +/// @notice Measures total on-chain gas for a complete DKG run at multiple +/// keyper counts. Setup gas (contract deployment, keyper set creation) is +/// excluded — only protocol operation cost is reported. +contract DKGBenchmark is Test { + // Phase parameters mirror the existing DKGContract.t.sol conventions so + // the benchmark uses block windows the test runner already understands. + uint64 constant PHASE_LENGTH = 10; + uint64 constant DKG_LEAD_LENGTH = 40; + uint64 constant ACTIVATION_BLOCK = 1000; + + // Non-zero fill byte. Real BLS/ECIES payloads are non-zero, and calldata + // gas is 16 per non-zero byte vs. 4 per zero byte — so using 0xAB makes + // the measurement reflect production cost. + bytes1 constant FILL = 0xAB; + + DKGContract dkg; + KeyperSetManager ksm; + KeyBroadcastContract kbc; + KeyperSet ks; + address[] keypers; + + uint256 totalGas; + + // ------------------------------------------------------------------- + // Setup helpers — deploy fresh contracts and a new keyper set per run + // to keep warm-storage effects from leaking between scenarios. + // ------------------------------------------------------------------- + + function _setup(uint64 n) internal { + address initializer = address(69); + address dao = address(42); + address sequencer = address(420); + + ksm = new KeyperSetManager(initializer); + vm.prank(initializer); + ksm.initialize(dao, sequencer); + + kbc = new KeyBroadcastContract(address(ksm)); + dkg = new DKGContract( + PHASE_LENGTH, + DKG_LEAD_LENGTH, + address(ksm), + address(kbc) + ); + + ks = new KeyperSet(); + address[] memory members = new address[](n); + delete keypers; + for (uint64 i = 0; i < n; i++) { + address k = address(uint160(0x1000 + i)); + members[i] = k; + keypers.push(k); + } + ks.addMembers(members); + ks.setThreshold(_threshold(n)); + ks.setPublisher(address(dkg)); + ks.setFinalized(); + + vm.prank(dao); + ksm.addKeyperSet(ACTIVATION_BLOCK, address(ks)); + } + + // ⌈2n/3⌉ via integer arithmetic. + function _threshold(uint64 n) internal pure returns (uint64) { + return (2 * n + 2) / 3; + } + + // ------------------------------------------------------------------- + // Data builders — produce realistic-sized non-zero payloads. + // ------------------------------------------------------------------- + + function _fill(uint256 size) internal pure returns (bytes memory result) { + result = new bytes(size); + for (uint256 i = 0; i < size; i++) { + result[i] = FILL; + } + } + + // PolyCommitment: one compressed BLS12-381 G2 point per polynomial + // coefficient, plus a 4-byte length prefix → 4 + threshold × 96 bytes. + function _commitment(uint64 threshold) internal pure returns (bytes memory) { + return _fill(4 + uint256(threshold) * 96); + } + + // PolyEvals: one ECIES ciphertext per other keyper, each 129 bytes + // (65 ephemeral pubkey + 32 ciphertext + 32 HMAC-SHA256). + function _polyEvals(uint64 n) internal pure returns (bytes[] memory) { + bytes[] memory evals = new bytes[](n - 1); + for (uint64 i = 0; i < n - 1; i++) { + evals[i] = _fill(129); + } + return evals; + } + + // Eon public key: compressed BLS12-381 G2 point, 96 bytes. + function _eonKey() internal pure returns (bytes memory) { + return _fill(96); + } + + // ------------------------------------------------------------------- + // Scenario runner — happy path: n dealings + ⌈2n/3⌉ success votes. + // ------------------------------------------------------------------- + + function _runHappyPath(uint64 n) internal { + _setup(n); + uint64 threshold = _threshold(n); + totalGas = 0; + + uint64 dealingBlock = ACTIVATION_BLOCK - DKG_LEAD_LENGTH; + bytes memory commitment = _commitment(threshold); + bytes[] memory polyEvals = _polyEvals(n); + + vm.roll(dealingBlock); + for (uint64 i = 0; i < n; i++) { + vm.prank(keypers[i]); + uint256 before = gasleft(); + dkg.submitDealing(0, 0, i, commitment, polyEvals); + totalGas += before - gasleft(); + } + + uint64 finalizingBlock = dealingBlock + 3 * PHASE_LENGTH; + bytes memory eonKey = _eonKey(); + + vm.roll(finalizingBlock); + for (uint64 i = 0; i < threshold; i++) { + vm.prank(keypers[i]); + uint256 before = gasleft(); + dkg.submitSuccessVote(0, 0, i, eonKey); + totalGas += before - gasleft(); + } + + assertTrue(dkg.succeeded(0), "DKG must reach success on happy path"); + console.log( + "DKGBenchmark scenario=happy-path n=%s threshold=%s gas=%s", + uint256(n), + uint256(threshold), + totalGas + ); + } + + function test_happyPath_n3() public { + _runHappyPath(3); + } + + function test_happyPath_n5() public { + _runHappyPath(5); + } + + function test_happyPath_n10() public { + _runHappyPath(10); + } + + function test_happyPath_n20() public { + _runHappyPath(20); + } + + function test_happyPath_n50() public { + _runHappyPath(50); + } +} From b21b3118e7f529dd43734912de1158e788534953 Mon Sep 17 00:00:00 2001 From: Jannik Date: Wed, 20 May 2026 20:45:02 +0200 Subject: [PATCH 09/25] Add worst-case DKG gas benchmark MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor _runHappyPath into a parameterized _run(n, worstCase) and extend it with accusing/apologizing phases for the worst-case scenario. Add test_worstCase_n{3,5,10,20,50} entry points. The worst case has every keyper accuse all n-1 others in one tx, then respond to all n-1 accusers in one apology tx with plaintext 32-byte BLS12-381 scalars (NOT 129-byte ECIES ciphertext — the accused keyper reveals the eval in the clear). Key decisions: - Single _run function (parameterized) over duplicating happy-path code. - Apology polyEvalData entries are 32 bytes per PRD: plaintext scalar. - Accusing block = dealingBlock + PHASE_LENGTH; apologizing block = dealingBlock + 2 * PHASE_LENGTH; finalizing block unchanged. Files: contracts/test/DKGBenchmark.t.sol. Verified all 10 tests pass; worst-case gas strictly exceeds happy-path at each n (n=50: 22M worst-case vs 11M happy-path). Co-Authored-By: Claude Opus 4.7 (1M context) --- test/DKGBenchmark.t.sol | 91 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 82 insertions(+), 9 deletions(-) diff --git a/test/DKGBenchmark.t.sol b/test/DKGBenchmark.t.sol index 7edad0e..cc8f76e 100644 --- a/test/DKGBenchmark.t.sol +++ b/test/DKGBenchmark.t.sol @@ -108,11 +108,39 @@ contract DKGBenchmark is Test { return _fill(96); } + // Accusation: every other keyper's index, n-1 uint64 entries. + function _accusedIndices( + uint64 n, + uint64 selfIdx + ) internal pure returns (uint64[] memory) { + uint64[] memory accused = new uint64[](n - 1); + uint64 j = 0; + for (uint64 i = 0; i < n; i++) { + if (i == selfIdx) continue; + accused[j++] = i; + } + return accused; + } + + // Apology polyEvalData: one plaintext BLS12-381 scalar per accuser, 32 + // bytes each (NOT 129-byte ECIES — the accused keyper reveals the + // evaluation in the clear during apology). + function _apologyEvals(uint64 n) internal pure returns (bytes[] memory) { + bytes[] memory evals = new bytes[](n - 1); + for (uint64 i = 0; i < n - 1; i++) { + evals[i] = _fill(32); + } + return evals; + } + // ------------------------------------------------------------------- - // Scenario runner — happy path: n dealings + ⌈2n/3⌉ success votes. + // Scenario runner — happy path or worst case. + // happy path: n dealings + ⌈2n/3⌉ success votes. + // worst case: same + n accusations (all-vs-all) + n apologies (all + // accusers acknowledged with plaintext scalars). // ------------------------------------------------------------------- - function _runHappyPath(uint64 n) internal { + function _run(uint64 n, bool worstCase) internal { _setup(n); uint64 threshold = _threshold(n); totalGas = 0; @@ -129,6 +157,29 @@ contract DKGBenchmark is Test { totalGas += before - gasleft(); } + if (worstCase) { + uint64 accusingBlock = dealingBlock + PHASE_LENGTH; + vm.roll(accusingBlock); + for (uint64 i = 0; i < n; i++) { + uint64[] memory accused = _accusedIndices(n, i); + vm.prank(keypers[i]); + uint256 before = gasleft(); + dkg.submitAccusation(0, 0, i, accused); + totalGas += before - gasleft(); + } + + uint64 apologizingBlock = dealingBlock + 2 * PHASE_LENGTH; + bytes[] memory apologyEvals = _apologyEvals(n); + vm.roll(apologizingBlock); + for (uint64 i = 0; i < n; i++) { + uint64[] memory accusers = _accusedIndices(n, i); + vm.prank(keypers[i]); + uint256 before = gasleft(); + dkg.submitApology(0, 0, i, accusers, apologyEvals); + totalGas += before - gasleft(); + } + } + uint64 finalizingBlock = dealingBlock + 3 * PHASE_LENGTH; bytes memory eonKey = _eonKey(); @@ -140,9 +191,11 @@ contract DKGBenchmark is Test { totalGas += before - gasleft(); } - assertTrue(dkg.succeeded(0), "DKG must reach success on happy path"); + assertTrue(dkg.succeeded(0), "DKG must reach success"); console.log( - "DKGBenchmark scenario=happy-path n=%s threshold=%s gas=%s", + worstCase + ? "DKGBenchmark scenario=worst-case n=%s threshold=%s gas=%s" + : "DKGBenchmark scenario=happy-path n=%s threshold=%s gas=%s", uint256(n), uint256(threshold), totalGas @@ -150,22 +203,42 @@ contract DKGBenchmark is Test { } function test_happyPath_n3() public { - _runHappyPath(3); + _run(3, false); } function test_happyPath_n5() public { - _runHappyPath(5); + _run(5, false); } function test_happyPath_n10() public { - _runHappyPath(10); + _run(10, false); } function test_happyPath_n20() public { - _runHappyPath(20); + _run(20, false); } function test_happyPath_n50() public { - _runHappyPath(50); + _run(50, false); + } + + function test_worstCase_n3() public { + _run(3, true); + } + + function test_worstCase_n5() public { + _run(5, true); + } + + function test_worstCase_n10() public { + _run(10, true); + } + + function test_worstCase_n20() public { + _run(20, true); + } + + function test_worstCase_n50() public { + _run(50, true); } } From 892cb9232d2d952a28d1bd11688047ecc0856b65 Mon Sep 17 00:00:00 2001 From: Jannik Date: Wed, 20 May 2026 22:35:13 +0200 Subject: [PATCH 10/25] feat(scripts): deploy DKG/ECIES in service deployment; wire DKG into AddKeyperSet Service deployment now also deploys DKGContract and ECIESKeyRegistry, so the e2e tests can exercise the full DKG cycle against the shutterservice keyper. AddKeyperSet (both common and gnosh) accept an optional DKG_CONTRACT_ADDRESS env var and call setDKGContract on the new KeyperSet when provided. Key decisions: - Reuse the existing deployDKGContract / deployECIESKeyRegistry helpers (already shared with Deploy.gnosh.s.sol) instead of forking. Reads the same DKG_PHASE_LENGTH / DKG_LEAD_LENGTH env defaults. - AddKeyperSet treats DKG_CONTRACT_ADDRESS as optional: if unset, no setDKGContract call is made. This keeps backward compatibility with callers that haven't been updated, and lets the keyper's eons-row code fall back to its config-supplied global DKG contract. Files changed: - script/Deploy.service.s.sol: deploys DKGContract + ECIESKeyRegistry. - script/AddKeyperSet.s.sol, script/AddKeyperSet.gnosh.s.sol: accept DKG_CONTRACT_ADDRESS env var. Notes for next iteration: - mise-test-setup's contracts container is built from https://github.com/shutter-network/contracts.git#docker so these script changes will only reach the e2e test runs once that branch is pushed. Co-Authored-By: Claude Opus 4.7 (1M context) --- script/AddKeyperSet.gnosh.s.sol | 5 +++++ script/AddKeyperSet.s.sol | 5 +++++ script/Deploy.service.s.sol | 32 +++++++++++++++++++++++++++++++- 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/script/AddKeyperSet.gnosh.s.sol b/script/AddKeyperSet.gnosh.s.sol index 1f3716c..8532d20 100644 --- a/script/AddKeyperSet.gnosh.s.sol +++ b/script/AddKeyperSet.gnosh.s.sol @@ -41,6 +41,8 @@ contract AddKeyperSet is Script { keyBroadcastContractAddress ); + address dkgContract = vm.envOr("DKG_CONTRACT_ADDRESS", address(0)); + address[] memory keypers = vm.envAddress("KEYPER_ADDRESSES", ","); uint256 threshold = vm.envUint("THRESHOLD"); if (threshold > keypers.length) { @@ -57,6 +59,9 @@ contract AddKeyperSet is Script { keyperSet.addMembers(keypers); keyperSet.setThreshold(uint64(threshold)); keyperSet.setPublisher(address(eonKeyPublish)); + if (dkgContract != address(0)) { + keyperSet.setDKGContract(dkgContract); + } keyperSet.setFinalized(); console.log("keyperSet:", address(keyperSet)); console.log("eonKeyPublish:", address(eonKeyPublish)); diff --git a/script/AddKeyperSet.s.sol b/script/AddKeyperSet.s.sol index 1f3716c..8532d20 100644 --- a/script/AddKeyperSet.s.sol +++ b/script/AddKeyperSet.s.sol @@ -41,6 +41,8 @@ contract AddKeyperSet is Script { keyBroadcastContractAddress ); + address dkgContract = vm.envOr("DKG_CONTRACT_ADDRESS", address(0)); + address[] memory keypers = vm.envAddress("KEYPER_ADDRESSES", ","); uint256 threshold = vm.envUint("THRESHOLD"); if (threshold > keypers.length) { @@ -57,6 +59,9 @@ contract AddKeyperSet is Script { keyperSet.addMembers(keypers); keyperSet.setThreshold(uint64(threshold)); keyperSet.setPublisher(address(eonKeyPublish)); + if (dkgContract != address(0)) { + keyperSet.setDKGContract(dkgContract); + } keyperSet.setFinalized(); console.log("keyperSet:", address(keyperSet)); console.log("eonKeyPublish:", address(eonKeyPublish)); diff --git a/script/Deploy.service.s.sol b/script/Deploy.service.s.sol index e39dce5..bf657d8 100644 --- a/script/Deploy.service.s.sol +++ b/script/Deploy.service.s.sol @@ -2,6 +2,8 @@ pragma solidity ^0.8.20; import "forge-std/Script.sol"; +import "../src/common/DKGContract.sol"; +import "../src/common/ECIESKeyRegistry.sol"; import "../src/common/KeyBroadcastContract.sol"; import "../src/common/KeyperSet.sol"; import "../src/common/KeyperSetManager.sol"; @@ -34,6 +36,32 @@ contract Deploy is Script { return kbc; } + function deployDKGContract( + KeyperSetManager ksm, + KeyBroadcastContract kbc + ) public returns (DKGContract) { + uint64 phaseLength = uint64(vm.envOr("DKG_PHASE_LENGTH", uint256(10))); + uint64 dkgLeadLength = uint64( + vm.envOr("DKG_LEAD_LENGTH", uint256(40)) + ); + DKGContract dkg = new DKGContract( + phaseLength, + dkgLeadLength, + address(ksm), + address(kbc) + ); + console.log("DKGContract:", address(dkg)); + return dkg; + } + + function deployECIESKeyRegistry( + KeyperSetManager ksm + ) public returns (ECIESKeyRegistry) { + ECIESKeyRegistry registry = new ECIESKeyRegistry(address(ksm)); + console.log("ECIESKeyRegistry:", address(registry)); + return registry; + } + function deployRegistry() public returns (ShutterRegistry) { ShutterRegistry s = new ShutterRegistry(); console.log("Registry:", address(s)); @@ -58,7 +86,9 @@ contract Deploy is Script { vm.startBroadcast(deployKey); KeyperSetManager ksm = deployKeyperSetManager(deployerAddress); - deployKeyBroadcastContract(ksm); + KeyBroadcastContract kbc = deployKeyBroadcastContract(ksm); + deployDKGContract(ksm, kbc); + deployECIESKeyRegistry(ksm); deployRegistry(); deployEventTriggerRegistry(); From d7e14c7ccbfcc9f12253ebdee9d2e3d26f5ac795 Mon Sep 17 00:00:00 2001 From: Jannik Date: Thu, 21 May 2026 12:22:00 +0200 Subject: [PATCH 11/25] feat(dkg): add WrongDKGContract guard to all submit functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added `error WrongDKGContract` and `_checkDKGContract(uint64 keyperSetIndex)` helper that reverts if the Keyper Set's `dkgContract` field does not match `address(this)` (address(0) is treated as a mismatch — no special case). Called before `_checkMember` in `submitDealing`, `submitAccusation`, `submitApology`, and `submitSuccessVote`. Files changed: - src/common/DKGContract.sol: error + helper + 4 call sites - test/DKGContract.t.sol: setUp wires setDKGContract; 5 new revert tests Decision: check runs after phase/success guards so misconfigured keypers get a clear WrongDKGContract error rather than a phase error. --- src/common/DKGContract.sol | 14 +++++++ test/DKGContract.t.sol | 86 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/src/common/DKGContract.sol b/src/common/DKGContract.sol index 0e3bbd4..b2307d6 100644 --- a/src/common/DKGContract.sol +++ b/src/common/DKGContract.sol @@ -19,6 +19,7 @@ contract DKGContract { error EmptyAccusation(); error MismatchedArrays(); error AlreadyVoted(); + error WrongDKGContract(); event DealingSubmitted( uint64 indexed keyperSetIndex, @@ -119,6 +120,15 @@ contract DKGContract { } } + function _checkDKGContract(uint64 keyperSetIndex) internal view { + address keyperSetAddress = keyperSetManager.getKeyperSetAddress( + keyperSetIndex + ); + if (KeyperSet(keyperSetAddress).getDKGContract() != address(this)) { + revert WrongDKGContract(); + } + } + function _checkMember( uint64 keyperSetIndex, uint64 keyperIndex @@ -150,6 +160,7 @@ contract DKGContract { ) external { _requireNotSucceeded(keyperSetIndex); _requirePhase(keyperSetIndex, retryCounter, Phase.Dealing); + _checkDKGContract(keyperSetIndex); _checkMember(keyperSetIndex, keyperIndex); emit DealingSubmitted( keyperSetIndex, @@ -170,6 +181,7 @@ contract DKGContract { ) external { _requireNotSucceeded(keyperSetIndex); _requirePhase(keyperSetIndex, retryCounter, Phase.Accusing); + _checkDKGContract(keyperSetIndex); _checkMember(keyperSetIndex, keyperIndex); if (accusedIndices.length == 0) { revert EmptyAccusation(); @@ -191,6 +203,7 @@ contract DKGContract { ) external { _requireNotSucceeded(keyperSetIndex); _requirePhase(keyperSetIndex, retryCounter, Phase.Apologizing); + _checkDKGContract(keyperSetIndex); _checkMember(keyperSetIndex, keyperIndex); if (accuserIndices.length != polyEvalData.length) { revert MismatchedArrays(); @@ -211,6 +224,7 @@ contract DKGContract { bytes calldata eonPublicKey ) external { _requirePhase(keyperSetIndex, retryCounter, Phase.Finalizing); + _checkDKGContract(keyperSetIndex); _checkMember(keyperSetIndex, keyperIndex); if (hasVoted[keyperSetIndex][retryCounter][msg.sender]) { revert AlreadyVoted(); diff --git a/test/DKGContract.t.sol b/test/DKGContract.t.sol index 8d0e080..3e1a945 100644 --- a/test/DKGContract.t.sol +++ b/test/DKGContract.t.sol @@ -84,6 +84,7 @@ contract DKGContractTest is Test { keyperSet0.addMembers(members); keyperSet0.setThreshold(2); keyperSet0.setPublisher(address(dkgContract)); + keyperSet0.setDKGContract(address(dkgContract)); keyperSet0.setFinalized(); vm.prank(dao); keyperSetManager.addKeyperSet(ACTIVATION_BLOCK_0, address(keyperSet0)); @@ -550,6 +551,7 @@ contract DKGContractTest is Test { keyperSet1.addMembers(members); keyperSet1.setThreshold(2); keyperSet1.setPublisher(address(0xDEAD)); // not the DKG contract + keyperSet1.setDKGContract(address(dkgContract)); keyperSet1.setFinalized(); uint64 activation1 = ACTIVATION_BLOCK_0 * 2; vm.prank(dao); @@ -652,6 +654,7 @@ contract DKGContractTest is Test { keyperSet1.addMembers(members); keyperSet1.setThreshold(2); keyperSet1.setPublisher(address(dkgContract)); + keyperSet1.setDKGContract(address(dkgContract)); keyperSet1.setFinalized(); uint64 activation1 = ACTIVATION_BLOCK_0 * 2; // 2000 vm.prank(dao); @@ -706,4 +709,87 @@ contract DKGContractTest is Test { vm.prank(keyper0); dkgContract.submitDealing(0, 1, 0, hex"01", emptyEvals); } + + // --------------------------------------------------------------------- + // WrongDKGContract guard tests + // --------------------------------------------------------------------- + + function _makeKeyperSetWithWrongDKGContract() + internal + returns (KeyperSet ks, uint64 ksi) + { + ks = new KeyperSet(); + address[] memory members = new address[](3); + members[0] = keyper0; + members[1] = keyper1; + members[2] = keyper2; + ks.addMembers(members); + ks.setThreshold(2); + ks.setPublisher(address(dkgContract)); + // dkgContract left as address(0) — intentional mismatch + ks.setFinalized(); + uint64 activation = ACTIVATION_BLOCK_0 * 10; + vm.prank(dao); + keyperSetManager.addKeyperSet(activation, address(ks)); + ksi = 1; // first new set added after keyperSet0 + } + + function testSubmitDealingRevertsOnWrongDKGContract() public { + (, uint64 ksi) = _makeKeyperSetWithWrongDKGContract(); + uint64 activation = ACTIVATION_BLOCK_0 * 10; + uint64 dealingBlock = activation - DKG_LEAD_LENGTH; + vm.roll(dealingBlock); + bytes[] memory evals = new bytes[](0); + vm.prank(keyper0); + vm.expectRevert(DKGContract.WrongDKGContract.selector); + dkgContract.submitDealing(ksi, 0, 0, hex"01", evals); + } + + function testSubmitAccusationRevertsOnWrongDKGContract() public { + (, uint64 ksi) = _makeKeyperSetWithWrongDKGContract(); + uint64 activation = ACTIVATION_BLOCK_0 * 10; + uint64 accusingBlock = activation - DKG_LEAD_LENGTH + PHASE_LENGTH; + vm.roll(accusingBlock); + uint64[] memory accused = new uint64[](1); + accused[0] = 1; + vm.prank(keyper0); + vm.expectRevert(DKGContract.WrongDKGContract.selector); + dkgContract.submitAccusation(ksi, 0, 0, accused); + } + + function testSubmitApologyRevertsOnWrongDKGContract() public { + (, uint64 ksi) = _makeKeyperSetWithWrongDKGContract(); + uint64 activation = ACTIVATION_BLOCK_0 * 10; + uint64 apologizingBlock = activation - DKG_LEAD_LENGTH + 2 * PHASE_LENGTH; + vm.roll(apologizingBlock); + uint64[] memory accusers = new uint64[](1); + accusers[0] = 1; + bytes[] memory evals = new bytes[](1); + evals[0] = hex"aa"; + vm.prank(keyper0); + vm.expectRevert(DKGContract.WrongDKGContract.selector); + dkgContract.submitApology(ksi, 0, 0, accusers, evals); + } + + function testSubmitSuccessVoteRevertsOnWrongDKGContract() public { + (, uint64 ksi) = _makeKeyperSetWithWrongDKGContract(); + uint64 activation = ACTIVATION_BLOCK_0 * 10; + uint64 finalizingBlock = activation - DKG_LEAD_LENGTH + 3 * PHASE_LENGTH; + vm.roll(finalizingBlock); + vm.prank(keyper0); + vm.expectRevert(DKGContract.WrongDKGContract.selector); + dkgContract.submitSuccessVote(ksi, 0, 0, EON_KEY_A); + } + + function testSubmitDealingRevertsWhenDKGContractIsZero() public { + // address(0) is an explicit mismatch — no special case. + (, uint64 ksi) = _makeKeyperSetWithWrongDKGContract(); + uint64 activation = ACTIVATION_BLOCK_0 * 10; + uint64 dealingBlock = activation - DKG_LEAD_LENGTH; + vm.roll(dealingBlock); + bytes[] memory evals = new bytes[](0); + vm.prank(keyper0); + vm.expectRevert(DKGContract.WrongDKGContract.selector); + dkgContract.submitDealing(ksi, 0, 0, hex"01", evals); + } } From a79dc7289b9e97b96cc6266e1066d0750685685c Mon Sep 17 00:00:00 2001 From: Jannik Date: Fri, 22 May 2026 11:44:37 +0200 Subject: [PATCH 12/25] fix(benchmark): add missing setDKGContract call in DKGBenchmark._setup All ten tests were reverting with WrongDKGContract(). _setup() finalized the KeyperSet without calling ks.setDKGContract(address(dkg)), so _checkDKGContract saw address(0) instead of address(this). Added ks.setDKGContract(address(dkg)) between setPublisher and setFinalized, mirroring DKGContractTest.t.sol. Files changed: test/DKGBenchmark.t.sol --- test/DKGBenchmark.t.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/test/DKGBenchmark.t.sol b/test/DKGBenchmark.t.sol index cc8f76e..bcfb18b 100644 --- a/test/DKGBenchmark.t.sol +++ b/test/DKGBenchmark.t.sol @@ -65,6 +65,7 @@ contract DKGBenchmark is Test { ks.addMembers(members); ks.setThreshold(_threshold(n)); ks.setPublisher(address(dkg)); + ks.setDKGContract(address(dkg)); ks.setFinalized(); vm.prank(dao); From c18cb30f0538f05a4e70ed588258913441db9014 Mon Sep 17 00:00:00 2001 From: Jannik Date: Tue, 26 May 2026 18:44:40 +0200 Subject: [PATCH 13/25] fix(benchmark): exclude setup gas from Forge per-test gas reporting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All ten DKGBenchmark tests reported inflated [PASS] (gas: X) figures because _setup() (four contract deployments + keyper set creation) was included in Forge's test-level gas counter. The PRD explicitly excludes setup gas; totalGas accumulated via gasleft() was already correct but the headline number was misleading. Fixed by wrapping _setup(n) in vm.pauseGasMetering() / vm.resumeGasMetering() in _run(). vm.pauseGasMetering() pauses Forge's EVM gas counter without affecting gasleft(), so the per-call gasleft()-difference accumulation into totalGas continues to work correctly. The [PASS] gas numbers now reflect only protocol operations. Key decisions: - vm.pauseGasMetering() / vm.resumeGasMetering() is the canonical Forge approach for excluding scaffolding from per-test gas figures. No restructuring (e.g. splitting into per-N test contracts or moving _setup to Forge's setUp()) was needed. - gasleft() is unaffected by pauseGasMetering, so the console.log totalGas output is unchanged and remains the authoritative measurement. Before → after [PASS] gas (happy path): n=3: 5,007,283 → 427,541 n=5: 5,347,205 → 672,400 n=10: 6,195,906 → 1,283,443 n=20: 8,489,712 → 3,101,929 n=50: 19,548,247 → 12,734,473 Files changed: contracts/test/DKGBenchmark.t.sol Notes: no e2e tests to run for a benchmark-only change; all ten DKGBenchmark tests pass with forge test --match-contract DKGBenchmark. --- test/DKGBenchmark.t.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/DKGBenchmark.t.sol b/test/DKGBenchmark.t.sol index bcfb18b..8ffd4d4 100644 --- a/test/DKGBenchmark.t.sol +++ b/test/DKGBenchmark.t.sol @@ -142,7 +142,9 @@ contract DKGBenchmark is Test { // ------------------------------------------------------------------- function _run(uint64 n, bool worstCase) internal { + vm.pauseGasMetering(); _setup(n); + vm.resumeGasMetering(); uint64 threshold = _threshold(n); totalGas = 0; From 8a3180faaf6469687c155f69619277852067e351 Mon Sep 17 00:00:00 2001 From: Jannik Date: Wed, 27 May 2026 16:26:35 +0200 Subject: [PATCH 14/25] chore: format --- foundry.lock | 2 +- script/Deploy.gnosh.s.sol | 4 +--- script/Deploy.s.sol | 5 ++++- script/Deploy.service.s.sol | 4 +--- test/DKGBenchmark.t.sol | 4 +++- test/DKGContract.t.sol | 10 ++++++++-- test/ECIESKeyRegistry.t.sol | 4 +--- 7 files changed, 19 insertions(+), 14 deletions(-) diff --git a/foundry.lock b/foundry.lock index 1ce06cb..97ba8bb 100644 --- a/foundry.lock +++ b/foundry.lock @@ -20,4 +20,4 @@ "rev": "cbce1e00305e943aa1661d43f41e5ac72c662b07" } } -} \ No newline at end of file +} diff --git a/script/Deploy.gnosh.s.sol b/script/Deploy.gnosh.s.sol index 485f6c8..54176a0 100644 --- a/script/Deploy.gnosh.s.sol +++ b/script/Deploy.gnosh.s.sol @@ -38,9 +38,7 @@ contract Deploy is Script { KeyBroadcastContract kbc ) public returns (DKGContract) { uint64 phaseLength = uint64(vm.envOr("DKG_PHASE_LENGTH", uint256(10))); - uint64 dkgLeadLength = uint64( - vm.envOr("DKG_LEAD_LENGTH", uint256(40)) - ); + uint64 dkgLeadLength = uint64(vm.envOr("DKG_LEAD_LENGTH", uint256(40))); DKGContract dkg = new DKGContract( phaseLength, dkgLeadLength, diff --git a/script/Deploy.s.sol b/script/Deploy.s.sol index fd21b4d..4c8ea2a 100644 --- a/script/Deploy.s.sol +++ b/script/Deploy.s.sol @@ -170,7 +170,10 @@ contract DeployScript is Script { // Step 2: Set the DKG Contract as publisher so it can broadcast eon keys keyperSet.setPublisher(address(dkgContract)); - console.log("Eon Key Publisher set to DKGContract:", address(dkgContract)); + console.log( + "Eon Key Publisher set to DKGContract:", + address(dkgContract) + ); keyperSet.setFinalized(); console.log("KeyperSet finalized"); diff --git a/script/Deploy.service.s.sol b/script/Deploy.service.s.sol index bf657d8..bb3c752 100644 --- a/script/Deploy.service.s.sol +++ b/script/Deploy.service.s.sol @@ -41,9 +41,7 @@ contract Deploy is Script { KeyBroadcastContract kbc ) public returns (DKGContract) { uint64 phaseLength = uint64(vm.envOr("DKG_PHASE_LENGTH", uint256(10))); - uint64 dkgLeadLength = uint64( - vm.envOr("DKG_LEAD_LENGTH", uint256(40)) - ); + uint64 dkgLeadLength = uint64(vm.envOr("DKG_LEAD_LENGTH", uint256(40))); DKGContract dkg = new DKGContract( phaseLength, dkgLeadLength, diff --git a/test/DKGBenchmark.t.sol b/test/DKGBenchmark.t.sol index 8ffd4d4..a963bfe 100644 --- a/test/DKGBenchmark.t.sol +++ b/test/DKGBenchmark.t.sol @@ -90,7 +90,9 @@ contract DKGBenchmark is Test { // PolyCommitment: one compressed BLS12-381 G2 point per polynomial // coefficient, plus a 4-byte length prefix → 4 + threshold × 96 bytes. - function _commitment(uint64 threshold) internal pure returns (bytes memory) { + function _commitment( + uint64 threshold + ) internal pure returns (bytes memory) { return _fill(4 + uint256(threshold) * 96); } diff --git a/test/DKGContract.t.sol b/test/DKGContract.t.sol index 3e1a945..15ff575 100644 --- a/test/DKGContract.t.sol +++ b/test/DKGContract.t.sol @@ -760,7 +760,10 @@ contract DKGContractTest is Test { function testSubmitApologyRevertsOnWrongDKGContract() public { (, uint64 ksi) = _makeKeyperSetWithWrongDKGContract(); uint64 activation = ACTIVATION_BLOCK_0 * 10; - uint64 apologizingBlock = activation - DKG_LEAD_LENGTH + 2 * PHASE_LENGTH; + uint64 apologizingBlock = activation - + DKG_LEAD_LENGTH + + 2 * + PHASE_LENGTH; vm.roll(apologizingBlock); uint64[] memory accusers = new uint64[](1); accusers[0] = 1; @@ -774,7 +777,10 @@ contract DKGContractTest is Test { function testSubmitSuccessVoteRevertsOnWrongDKGContract() public { (, uint64 ksi) = _makeKeyperSetWithWrongDKGContract(); uint64 activation = ACTIVATION_BLOCK_0 * 10; - uint64 finalizingBlock = activation - DKG_LEAD_LENGTH + 3 * PHASE_LENGTH; + uint64 finalizingBlock = activation - + DKG_LEAD_LENGTH + + 3 * + PHASE_LENGTH; vm.roll(finalizingBlock); vm.prank(keyper0); vm.expectRevert(DKGContract.WrongDKGContract.selector); diff --git a/test/ECIESKeyRegistry.t.sol b/test/ECIESKeyRegistry.t.sol index 1bd7fe2..b72e6c6 100644 --- a/test/ECIESKeyRegistry.t.sol +++ b/test/ECIESKeyRegistry.t.sol @@ -105,9 +105,7 @@ contract ECIESKeyRegistryTest is Test { registry.registerKey(0, 0, pubkey); } - function testRegisterKeyRevertsWhenKeyperIndexDoesNotMatchSender() - public - { + function testRegisterKeyRevertsWhenKeyperIndexDoesNotMatchSender() public { bytes memory pubkey = hex"42"; // keyper0 is the member at index 0; using index 1 must fail. vm.prank(keyper0); From 8c43092f2fd08315ec0ee72edd4345763958548e Mon Sep 17 00:00:00 2001 From: Jannik Date: Wed, 27 May 2026 17:14:55 +0200 Subject: [PATCH 15/25] feat(dkg): add IDKGContract interface and implement it on DKGContract Introduce IDKGContract covering DKGContract's full public surface (the Phase enum, the seven external/public functions, and external-view getters for every public state variable) so other contracts -- notably KeyperSetManager in the next slice -- can call into a DKG contract without importing the concrete type and re-creating the KeyperSetManager <-> DKGContract import cycle. Key decisions: - The Phase enum moves from DKGContract to IDKGContract; DKGContract inherits it (references stay unqualified). DKGContract.t.sol now uses IDKGContract.Phase. - keyperSetManager()/keyBroadcastContract() in the interface return address, matching this repo's existing intf/ convention (IKeyperSet, IKeyperSetManager return address, never concrete types) and the comparison the next slice needs (IDKGContract(dkg).keyperSetManager() != address(this)). Returning concrete types would force IDKGContract to import KeyperSetManager, reinstating the very cycle this interface exists to break. To satisfy the address-typed getters while keeping internal calls typed, the two contract-typed immutables are renamed to internal _keyperSetManager/_keyBroadcastContract with explicit address getters. ABI is unchanged (the auto-getters already returned address), so Go bindings are unaffected. Files: src/common/intf/IDKGContract.sol (new), src/common/DKGContract.sol, test/DKGContract.t.sol. Verification: forge build clean (no new warnings vs baseline), forge test 131/131 pass, ABI diff confirms the interface covers exactly DKGContract's 14 public functions with matching return types. Notes for next iteration: unblocks 002-validate-dkg-address-on- registration. e2e suite (test-dkg-happy-path, test-dkg-offline-recovery) not run -- mise absent and its bootstrap is blocked by the sandbox classifier, as in every prior commit in this PRD area; this slice is Solidity-only with no ABI change and is fully covered by the forge suite. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/common/DKGContract.sol | 40 +++++++++-------- src/common/intf/IDKGContract.sol | 76 ++++++++++++++++++++++++++++++++ test/DKGContract.t.sol | 41 ++++++++--------- 3 files changed, 119 insertions(+), 38 deletions(-) create mode 100644 src/common/intf/IDKGContract.sol diff --git a/src/common/DKGContract.sol b/src/common/DKGContract.sol index b2307d6..6e8ebd7 100644 --- a/src/common/DKGContract.sol +++ b/src/common/DKGContract.sol @@ -3,16 +3,9 @@ pragma solidity ^0.8.22; import "./KeyperSetManager.sol"; import "./KeyBroadcastContract.sol"; +import "./intf/IDKGContract.sol"; -contract DKGContract { - enum Phase { - None, - Dealing, - Accusing, - Apologizing, - Finalizing - } - +contract DKGContract is IDKGContract { error WrongPhase(); error NotKeyperAtIndex(); error AlreadySucceeded(); @@ -55,8 +48,11 @@ contract DKGContract { uint64 public immutable PHASE_LENGTH; uint64 public immutable DKG_LEAD_LENGTH; - KeyperSetManager public immutable keyperSetManager; - KeyBroadcastContract public immutable keyBroadcastContract; + // Held as concrete types for internal calls; exposed as address through the + // IDKGContract getters below so the interface stays free of concrete-contract + // imports (which would re-create the KeyperSetManager <-> DKGContract cycle). + KeyperSetManager internal immutable _keyperSetManager; + KeyBroadcastContract internal immutable _keyBroadcastContract; // Set to true once a DKG Instance for Keyper Set Index k has reached the // success-vote threshold. Never reset — gates the success-triggering logic @@ -75,12 +71,20 @@ contract DKGContract { ) { PHASE_LENGTH = phaseLength; DKG_LEAD_LENGTH = dkgLeadLength; - keyperSetManager = KeyperSetManager(keyperSetManagerAddress); - keyBroadcastContract = KeyBroadcastContract( + _keyperSetManager = KeyperSetManager(keyperSetManagerAddress); + _keyBroadcastContract = KeyBroadcastContract( keyBroadcastContractAddress ); } + function keyperSetManager() external view returns (address) { + return address(_keyperSetManager); + } + + function keyBroadcastContract() external view returns (address) { + return address(_keyBroadcastContract); + } + function cycleLength() public view returns (uint64) { return 4 * PHASE_LENGTH; } @@ -89,7 +93,7 @@ contract DKGContract { uint64 keyperSetIndex, uint64 retryCounter ) public view returns (int256) { - uint64 activationBlock = keyperSetManager.getKeyperSetActivationBlock( + uint64 activationBlock = _keyperSetManager.getKeyperSetActivationBlock( keyperSetIndex ); return @@ -121,7 +125,7 @@ contract DKGContract { } function _checkDKGContract(uint64 keyperSetIndex) internal view { - address keyperSetAddress = keyperSetManager.getKeyperSetAddress( + address keyperSetAddress = _keyperSetManager.getKeyperSetAddress( keyperSetIndex ); if (KeyperSet(keyperSetAddress).getDKGContract() != address(this)) { @@ -133,7 +137,7 @@ contract DKGContract { uint64 keyperSetIndex, uint64 keyperIndex ) internal view { - address keyperSetAddress = keyperSetManager.getKeyperSetAddress( + address keyperSetAddress = _keyperSetManager.getKeyperSetAddress( keyperSetIndex ); if (KeyperSet(keyperSetAddress).getMember(keyperIndex) != msg.sender) { @@ -246,7 +250,7 @@ contract DKGContract { // emit the event above, but do not re-trigger success once it has // already been recorded. if (!succeeded[keyperSetIndex]) { - address keyperSetAddress = keyperSetManager.getKeyperSetAddress( + address keyperSetAddress = _keyperSetManager.getKeyperSetAddress( keyperSetIndex ); uint64 threshold = KeyperSet(keyperSetAddress).getThreshold(); @@ -256,7 +260,7 @@ contract DKGContract { // been broadcast (or the publisher is not authorized), the DKG // outcome is still considered successful. try - keyBroadcastContract.broadcastEonKey( + _keyBroadcastContract.broadcastEonKey( keyperSetIndex, eonPublicKey ) diff --git a/src/common/intf/IDKGContract.sol b/src/common/intf/IDKGContract.sol new file mode 100644 index 0000000..488b723 --- /dev/null +++ b/src/common/intf/IDKGContract.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +interface IDKGContract { + enum Phase { + None, + Dealing, + Accusing, + Apologizing, + Finalizing + } + + function PHASE_LENGTH() external view returns (uint64); + + function DKG_LEAD_LENGTH() external view returns (uint64); + + function keyperSetManager() external view returns (address); + + function keyBroadcastContract() external view returns (address); + + function succeeded(uint64 keyperSetIndex) external view returns (bool); + + function voteCount( + uint64 keyperSetIndex, + uint64 retryCounter, + bytes32 keyHash + ) external view returns (uint64); + + function hasVoted( + uint64 keyperSetIndex, + uint64 retryCounter, + address voter + ) external view returns (bool); + + function cycleLength() external view returns (uint64); + + function dkgStart( + uint64 keyperSetIndex, + uint64 retryCounter + ) external view returns (int256); + + function currentPhase( + uint64 keyperSetIndex, + uint64 retryCounter + ) external view returns (Phase); + + function submitDealing( + uint64 keyperSetIndex, + uint64 retryCounter, + uint64 keyperIndex, + bytes calldata commitment, + bytes[] calldata polyEvals + ) external; + + function submitAccusation( + uint64 keyperSetIndex, + uint64 retryCounter, + uint64 keyperIndex, + uint64[] calldata accusedIndices + ) external; + + function submitApology( + uint64 keyperSetIndex, + uint64 retryCounter, + uint64 keyperIndex, + uint64[] calldata accuserIndices, + bytes[] calldata polyEvalData + ) external; + + function submitSuccessVote( + uint64 keyperSetIndex, + uint64 retryCounter, + uint64 keyperIndex, + bytes calldata eonPublicKey + ) external; +} diff --git a/test/DKGContract.t.sol b/test/DKGContract.t.sol index 15ff575..434bad7 100644 --- a/test/DKGContract.t.sol +++ b/test/DKGContract.t.sol @@ -6,6 +6,7 @@ import "../src/common/DKGContract.sol"; import "../src/common/KeyperSet.sol"; import "../src/common/KeyperSetManager.sol"; import "../src/common/KeyBroadcastContract.sol"; +import "../src/common/intf/IDKGContract.sol"; contract DKGContractTest is Test { DKGContract public dkgContract; @@ -106,7 +107,7 @@ contract DKGContractTest is Test { function _assertPhase( uint64 blockNumber, uint64 retryCounter, - DKGContract.Phase expected + IDKGContract.Phase expected ) internal { vm.roll(blockNumber); assertEq( @@ -124,15 +125,15 @@ contract DKGContractTest is Test { uint64 constant DKG_START_R0 = ACTIVATION_BLOCK_0 - DKG_LEAD_LENGTH; function testCurrentPhaseBeforeDkgStartIsNone() public { - _assertPhase(DKG_START_R0 - 1, 0, DKGContract.Phase.None); + _assertPhase(DKG_START_R0 - 1, 0, IDKGContract.Phase.None); } function testCurrentPhaseDealingBoundaries() public { - _assertPhase(DKG_START_R0, 0, DKGContract.Phase.Dealing); + _assertPhase(DKG_START_R0, 0, IDKGContract.Phase.Dealing); _assertPhase( DKG_START_R0 + PHASE_LENGTH - 1, 0, - DKGContract.Phase.Dealing + IDKGContract.Phase.Dealing ); } @@ -141,19 +142,19 @@ contract DKGContractTest is Test { _assertPhase( DKG_START_R0 + PHASE_LENGTH - 1, 0, - DKGContract.Phase.Dealing + IDKGContract.Phase.Dealing ); // first block of Accusing _assertPhase( DKG_START_R0 + PHASE_LENGTH, 0, - DKGContract.Phase.Accusing + IDKGContract.Phase.Accusing ); // last block of Accusing _assertPhase( DKG_START_R0 + 2 * PHASE_LENGTH - 1, 0, - DKGContract.Phase.Accusing + IDKGContract.Phase.Accusing ); } @@ -162,19 +163,19 @@ contract DKGContractTest is Test { _assertPhase( DKG_START_R0 + 2 * PHASE_LENGTH - 1, 0, - DKGContract.Phase.Accusing + IDKGContract.Phase.Accusing ); // first block of Apologizing _assertPhase( DKG_START_R0 + 2 * PHASE_LENGTH, 0, - DKGContract.Phase.Apologizing + IDKGContract.Phase.Apologizing ); // last block of Apologizing _assertPhase( DKG_START_R0 + 3 * PHASE_LENGTH - 1, 0, - DKGContract.Phase.Apologizing + IDKGContract.Phase.Apologizing ); } @@ -183,19 +184,19 @@ contract DKGContractTest is Test { _assertPhase( DKG_START_R0 + 3 * PHASE_LENGTH - 1, 0, - DKGContract.Phase.Apologizing + IDKGContract.Phase.Apologizing ); // first block of Finalizing _assertPhase( DKG_START_R0 + 3 * PHASE_LENGTH, 0, - DKGContract.Phase.Finalizing + IDKGContract.Phase.Finalizing ); // last block of Finalizing _assertPhase( DKG_START_R0 + 4 * PHASE_LENGTH - 1, 0, - DKGContract.Phase.Finalizing + IDKGContract.Phase.Finalizing ); } @@ -204,7 +205,7 @@ contract DKGContractTest is Test { _assertPhase( DKG_START_R0 + 4 * PHASE_LENGTH, 0, - DKGContract.Phase.None + IDKGContract.Phase.None ); } @@ -213,19 +214,19 @@ contract DKGContractTest is Test { // r=0 Finalizing ends at DKG_START_R0 + 4 * PHASE_LENGTH = 1000. // r=1 Dealing should begin at the same block. uint64 boundary = DKG_START_R0 + 4 * PHASE_LENGTH; - _assertPhase(boundary, 1, DKGContract.Phase.Dealing); - _assertPhase(boundary, 0, DKGContract.Phase.None); + _assertPhase(boundary, 1, IDKGContract.Phase.Dealing); + _assertPhase(boundary, 0, IDKGContract.Phase.None); // one block before boundary: r=0 still Finalizing, r=1 still None - _assertPhase(boundary - 1, 0, DKGContract.Phase.Finalizing); - _assertPhase(boundary - 1, 1, DKGContract.Phase.None); + _assertPhase(boundary - 1, 0, IDKGContract.Phase.Finalizing); + _assertPhase(boundary - 1, 1, IDKGContract.Phase.None); } function testRetryDealingLastBlockBeforeAccusing() public { // r=1 Dealing: [1000, 1010) uint64 r1Start = DKG_START_R0 + CYCLE_LENGTH; - _assertPhase(r1Start + PHASE_LENGTH - 1, 1, DKGContract.Phase.Dealing); - _assertPhase(r1Start + PHASE_LENGTH, 1, DKGContract.Phase.Accusing); + _assertPhase(r1Start + PHASE_LENGTH - 1, 1, IDKGContract.Phase.Dealing); + _assertPhase(r1Start + PHASE_LENGTH, 1, IDKGContract.Phase.Accusing); } function testDkgStartArithmeticPureView() public view { From ef231f847fbb23d00c6ce823767aac79b2b71589 Mon Sep 17 00:00:00 2001 From: Jannik Date: Wed, 27 May 2026 17:31:05 +0200 Subject: [PATCH 16/25] feat(keyper-set-manager): validate DKG contract pairing on addKeyperSet Enforce the registration-time complement to DKGContract's runtime _checkDKGContract guard: a KeyperSet may only be registered if it designates a DKG Contract that itself references this KeyperSetManager. Without this, a KeyperSet paired with a zero or wrong DKG Contract registers cleanly but can never run DKG (every submission reverts WrongDKGContract), with no early signal to the DAO. Changes (src): - KeyperSetManager: two new errors DKGContractNotSet (zero DKG address) and DKGContractManagerMismatch (DKG's keyperSetManager != this). Both checks run after the existing isFinalized check, reading the DKG address via IKeyperSet.getDKGContract() and calling IDKGContract.keyperSetManager(). Imports IDKGContract (the interface, not the concrete DKGContract) so the KeyperSetManager <-> DKGContract cycle stays broken. Changes (tests): - KeyperSetManager.t.sol: setUp now pairs members0/members1 with a DKGContract bound to the test's manager; three new cases cover zero DKG, mismatched-manager DKG, and the matching happy path. - DKGContract/ECIESKeyRegistry/EonKeyPublish/KeyBroadcastContract tests: their setUps registered bare KeyperSets, which now revert at registration; each now sets a correctly-paired DKGContract before finalization. Key decisions: - Errors declared at file scope on KeyperSetManager.sol (next to AlreadyDeactivated), matching the issue's "KeyperSetManager declares" wording; selectors are visible to tests via the existing import. - DKGContract.t.sol's WrongDKGContract guard tests previously registered a KeyperSet with a zero DKG address. That state is now unreachable (addKeyperSet rejects it), so the helper points at a *second* valid DKGContract bound to the same manager (registration passes; runtime guard still fires). The now-impossible testSubmitDealingRevertsWhen DKGContractIsZero case is removed; the != comparison it exercised is fully covered by the remaining different-contract cases. Verification: forge build clean (only pre-existing unsafe-typecast lints in scripts/benchmarks; none from this change); forge test 133/133 pass (was 131: +3 KeyperSetManager cases, -1 obsolete zero-address case). Blockers/notes: e2e suite (rolling-shutter/mise-test-setup/e2e-tests) not run -- mise is absent and its mise.run bootstrap is blocked by the sandbox classifier, as in every prior commit in this PRD area. This change is Solidity-only, additive, with no addKeyperSet ABI signature change and no runtime behavior change for correctly-configured keyper sets, so the Go e2e happy-path/offline-recovery suites are unaffected. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/common/KeyperSetManager.sol | 15 +++++++++ test/DKGContract.t.sol | 26 +++++++-------- test/ECIESKeyRegistry.t.sol | 9 ++++++ test/EonKeyPublish.t.sol | 11 +++++++ test/KeyBroadcastContract.t.sol | 9 ++++++ test/KeyperSetManager.t.sol | 56 +++++++++++++++++++++++++++++++++ 6 files changed, 113 insertions(+), 13 deletions(-) diff --git a/src/common/KeyperSetManager.sol b/src/common/KeyperSetManager.sol index 98de4fd..bb5350c 100644 --- a/src/common/KeyperSetManager.sol +++ b/src/common/KeyperSetManager.sol @@ -5,8 +5,11 @@ import "openzeppelin/contracts/utils/math/Math.sol"; import "./KeyperSet.sol"; import "./RestrictedPausable.sol"; import "./intf/IKeyperSetManager.sol"; +import "./intf/IDKGContract.sol"; error AlreadyDeactivated(); +error DKGContractNotSet(); +error DKGContractManagerMismatch(); contract KeyperSetManager is RestrictedPausable, IKeyperSetManager { struct KeyperSetData { @@ -43,6 +46,18 @@ contract KeyperSetManager is RestrictedPausable, IKeyperSetManager { if (!KeyperSet(keyperSetContract).isFinalized()) { revert KeyperSetNotFinalized(); } + // The Keyper Set must designate a DKG Contract that itself references + // this manager. This is the registration-time complement to the + // runtime _checkDKGContract guard in DKGContract: without it, a Keyper + // Set paired with the wrong (or no) DKG Contract registers cleanly but + // can never run DKG, since every submission would revert WrongDKGContract. + address dkgContract = IKeyperSet(keyperSetContract).getDKGContract(); + if (dkgContract == address(0)) { + revert DKGContractNotSet(); + } + if (IDKGContract(dkgContract).keyperSetManager() != address(this)) { + revert DKGContractManagerMismatch(); + } keyperSets.push(KeyperSetData(activationBlock, keyperSetContract)); KeyperSet keyperSet = KeyperSet(keyperSetContract); emit KeyperSetAdded( diff --git a/test/DKGContract.t.sol b/test/DKGContract.t.sol index 434bad7..51fd7ab 100644 --- a/test/DKGContract.t.sol +++ b/test/DKGContract.t.sol @@ -727,7 +727,19 @@ contract DKGContractTest is Test { ks.addMembers(members); ks.setThreshold(2); ks.setPublisher(address(dkgContract)); - // dkgContract left as address(0) — intentional mismatch + // Point the Keyper Set at a *different* DKGContract that is still bound + // to this KeyperSetManager. Registration accepts it (its + // keyperSetManager matches the manager), but it is not the dkgContract + // the keypers submit to, so the runtime _checkDKGContract guard rejects + // every submission with WrongDKGContract. A zero DKGContract can no + // longer reach this guard: addKeyperSet rejects it at registration. + DKGContract otherDKG = new DKGContract( + PHASE_LENGTH, + DKG_LEAD_LENGTH, + address(keyperSetManager), + address(keyBroadcastContract) + ); + ks.setDKGContract(address(otherDKG)); ks.setFinalized(); uint64 activation = ACTIVATION_BLOCK_0 * 10; vm.prank(dao); @@ -787,16 +799,4 @@ contract DKGContractTest is Test { vm.expectRevert(DKGContract.WrongDKGContract.selector); dkgContract.submitSuccessVote(ksi, 0, 0, EON_KEY_A); } - - function testSubmitDealingRevertsWhenDKGContractIsZero() public { - // address(0) is an explicit mismatch — no special case. - (, uint64 ksi) = _makeKeyperSetWithWrongDKGContract(); - uint64 activation = ACTIVATION_BLOCK_0 * 10; - uint64 dealingBlock = activation - DKG_LEAD_LENGTH; - vm.roll(dealingBlock); - bytes[] memory evals = new bytes[](0); - vm.prank(keyper0); - vm.expectRevert(DKGContract.WrongDKGContract.selector); - dkgContract.submitDealing(ksi, 0, 0, hex"01", evals); - } } diff --git a/test/ECIESKeyRegistry.t.sol b/test/ECIESKeyRegistry.t.sol index b72e6c6..2452f04 100644 --- a/test/ECIESKeyRegistry.t.sol +++ b/test/ECIESKeyRegistry.t.sol @@ -5,6 +5,7 @@ import "forge-std/Test.sol"; import "../src/common/ECIESKeyRegistry.sol"; import "../src/common/KeyperSet.sol"; import "../src/common/KeyperSetManager.sol"; +import "../src/common/DKGContract.sol"; import "../src/common/intf/IKeyperSetManager.sol"; contract ECIESKeyRegistryTest is Test { @@ -31,6 +32,13 @@ contract ECIESKeyRegistryTest is Test { registry = new ECIESKeyRegistry(address(keyperSetManager)); + DKGContract dkgContract = new DKGContract( + 1, + 1, + address(keyperSetManager), + address(0) + ); + keyperSet0 = new KeyperSet(); address[] memory members = new address[](3); members[0] = keyper0; @@ -38,6 +46,7 @@ contract ECIESKeyRegistryTest is Test { members[2] = keyper2; keyperSet0.addMembers(members); keyperSet0.setThreshold(2); + keyperSet0.setDKGContract(address(dkgContract)); keyperSet0.setFinalized(); vm.prank(dao); keyperSetManager.addKeyperSet(ACTIVATION_BLOCK_0, address(keyperSet0)); diff --git a/test/EonKeyPublish.t.sol b/test/EonKeyPublish.t.sol index 4f154cc..f8603a8 100644 --- a/test/EonKeyPublish.t.sol +++ b/test/EonKeyPublish.t.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.22; import "forge-std/Test.sol"; import "../src/common/EonKeyPublish.sol"; +import "../src/common/DKGContract.sol"; contract EonKeyPublishTest is Test { KeyperSetManager public manager; @@ -10,6 +11,7 @@ contract EonKeyPublishTest is Test { KeyperSet public keyperSet0; KeyperSet public keyperSet; KeyBroadcastContract public broadcastContract; + DKGContract public dkgContract; address public initializer; address public dao; @@ -23,8 +25,16 @@ contract EonKeyPublishTest is Test { vm.prank(initializer); manager.initialize(dao, address(420)); broadcastContract = new KeyBroadcastContract(address(manager)); + dkgContract = new DKGContract( + 1, + 1, + address(manager), + address(broadcastContract) + ); keyperSet = new KeyperSet(); + keyperSet.setDKGContract(address(dkgContract)); keyperSet0 = new KeyperSet(); + keyperSet0.setDKGContract(address(dkgContract)); keyperSet0.setFinalized(); vm.prank(dao); uint64 eon = 1; @@ -58,6 +68,7 @@ contract EonKeyPublishTest is Test { ); ks.setPublisher(address(publisher)); ks.addMembers(members); + ks.setDKGContract(address(dkgContract)); ks.setFinalized(); vm.prank(dao); manager.addKeyperSet(uint64(10), address(ks)); diff --git a/test/KeyBroadcastContract.t.sol b/test/KeyBroadcastContract.t.sol index 0c116a7..4737536 100644 --- a/test/KeyBroadcastContract.t.sol +++ b/test/KeyBroadcastContract.t.sol @@ -5,6 +5,7 @@ import "forge-std/Test.sol"; import "../src/common/KeyBroadcastContract.sol"; import "../src/common/KeyperSetManager.sol"; import "../src/common/KeyperSet.sol"; +import "../src/common/DKGContract.sol"; contract MockPublisher is EonKeyPublisher { function eonKeyConfirmed(bytes memory) external pure returns (bool) { @@ -41,8 +42,15 @@ contract KeyBroadcastTest is Test { keyBroadcastContract = new KeyBroadcastContract( address(keyperSetManager) ); + DKGContract dkgContract = new DKGContract( + 1, + 1, + address(keyperSetManager), + address(keyBroadcastContract) + ); keyperSet0 = new KeyperSet(); keyperSet0.setPublisher(address(publisher0)); + keyperSet0.setDKGContract(address(dkgContract)); keyperSet0.setFinalized(); vm.prank(dao); @@ -50,6 +58,7 @@ contract KeyBroadcastTest is Test { keyperSet1 = new KeyperSet(); keyperSet1.setPublisher(address(publisher1)); + keyperSet1.setDKGContract(address(dkgContract)); keyperSet1.setFinalized(); vm.prank(dao); diff --git a/test/KeyperSetManager.t.sol b/test/KeyperSetManager.t.sol index 8f7b010..252d51c 100644 --- a/test/KeyperSetManager.t.sol +++ b/test/KeyperSetManager.t.sol @@ -4,15 +4,22 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../src/common/KeyperSetManager.sol"; import "../src/common/KeyperSet.sol"; +import "../src/common/DKGContract.sol"; +import "../src/common/KeyBroadcastContract.sol"; contract KeyperSetManagerTest is Test { KeyperSetManager public keyperSetManager; + KeyBroadcastContract public keyBroadcastContract; + DKGContract public dkgContract; KeyperSet public members0; KeyperSet public members1; address public owner; address public dao; address public sequencer; + uint64 constant PHASE_LENGTH = 10; + uint64 constant DKG_LEAD_LENGTH = 40; + function setUp() public { owner = vm.addr(42); dao = address(420); @@ -21,12 +28,31 @@ contract KeyperSetManagerTest is Test { keyperSetManager = new KeyperSetManager(owner); vm.prank(owner); keyperSetManager.initialize(dao, sequencer); + keyBroadcastContract = new KeyBroadcastContract( + address(keyperSetManager) + ); + dkgContract = deployDKGContract(address(keyperSetManager)); members0 = new KeyperSet(); + members0.setDKGContract(address(dkgContract)); members0.setFinalized(); members1 = new KeyperSet(); + members1.setDKGContract(address(dkgContract)); members1.setFinalized(); } + // Deploys a DKGContract bound to the given KeyperSetManager. The + // KeyBroadcastContract address is irrelevant to addKeyperSet validation, + // which only reads back DKGContract.keyperSetManager(). + function deployDKGContract(address manager) internal returns (DKGContract) { + return + new DKGContract( + PHASE_LENGTH, + DKG_LEAD_LENGTH, + manager, + address(keyBroadcastContract) + ); + } + function testGetNumKeyperSets() public { assertEq(keyperSetManager.getNumKeyperSets(), 0); vm.prank(dao); @@ -56,6 +82,36 @@ contract KeyperSetManagerTest is Test { keyperSetManager.addKeyperSet(0, address(ks)); } + function testAddKeyperSetRevertsOnZeroDKGContract() public { + KeyperSet ks = new KeyperSet(); + ks.setFinalized(); + vm.expectRevert(DKGContractNotSet.selector); + vm.prank(dao); + keyperSetManager.addKeyperSet(1000, address(ks)); + } + + function testAddKeyperSetRevertsOnMismatchedDKGContractManager() public { + // A DKGContract bound to a different KeyperSetManager must be rejected. + KeyperSetManager otherManager = new KeyperSetManager(owner); + DKGContract mismatchedDKG = deployDKGContract(address(otherManager)); + KeyperSet ks = new KeyperSet(); + ks.setDKGContract(address(mismatchedDKG)); + ks.setFinalized(); + vm.expectRevert(DKGContractManagerMismatch.selector); + vm.prank(dao); + keyperSetManager.addKeyperSet(1000, address(ks)); + } + + function testAddKeyperSetAcceptsMatchingDKGContract() public { + KeyperSet ks = new KeyperSet(); + ks.setDKGContract(address(dkgContract)); + ks.setFinalized(); + vm.prank(dao); + keyperSetManager.addKeyperSet(1000, address(ks)); + assertEq(keyperSetManager.getNumKeyperSets(), 1); + assertEq(keyperSetManager.getKeyperSetAddress(0), address(ks)); + } + function testAddKeyperSetRequiresIncreasingActivationBlock() public { vm.prank(dao); keyperSetManager.addKeyperSet(1000, address(members0)); From 4ea147cd6d39d4761b30b4a24e644f3b07826872 Mon Sep 17 00:00:00 2001 From: Jannik Date: Wed, 27 May 2026 17:38:03 +0200 Subject: [PATCH 17/25] feat(scripts): require DKG_CONTRACT_ADDRESS in AddKeyperSet The AddKeyperSet deployment script now reads the DKG contract address with vm.envAddress("DKG_CONTRACT_ADDRESS") instead of the vm.envOr(..., address(0)) fallback, and calls setDKGContract unconditionally. This is the deployment-path complement to the on-chain addKeyperSet validation added in ef231f8: a zero DKG address would now revert DKGContractNotSet at the contract call, so failing earlier at env-resolution time with Foundry's clear "environment variable not found" message is strictly better than a silent zero-address branch that always fails downstream. Key decisions: - Scope limited to AddKeyperSet.s.sol per the PRD/issue. The byte- identical AddKeyperSet.gnosh.s.sol is left untouched; it is not on any automated path (the e2e add-keyper-set mise-task always invokes AddKeyperSet.s.sol regardless of deployment type), so hardening it is a separate, out-of-scope follow-up. - No new forge test: scripts are not unit-tested in this repo, and the new revert-on-missing-env behavior is Foundry framework semantics (vm.envAddress), not our logic. Files changed: - script/AddKeyperSet.s.sol Verification: forge clean && forge build clean (only pre-existing unsafe-typecast lints in scripts/benchmarks); forge test 133/133 pass. The e2e add-keyper-set task already derives DKG_CONTRACT_ADDRESS from the deployed DKGContract (both Deploy.service and Deploy.gnosh create one), so the success path is preserved. Notes: e2e suite (test-dkg-happy-path, test-dkg-offline-recovery) not run -- mise is absent and its mise.run | sh bootstrap is blocked by the sandbox classifier (Code-from-External), as in every prior commit in this PRD area. The change is a one-line deployment-script edit with no ABI/runtime impact on correctly-configured keyper sets, so the Go e2e flows are unaffected. Co-Authored-By: Claude Opus 4.7 (1M context) --- script/AddKeyperSet.s.sol | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/script/AddKeyperSet.s.sol b/script/AddKeyperSet.s.sol index 8532d20..5c5d541 100644 --- a/script/AddKeyperSet.s.sol +++ b/script/AddKeyperSet.s.sol @@ -41,7 +41,7 @@ contract AddKeyperSet is Script { keyBroadcastContractAddress ); - address dkgContract = vm.envOr("DKG_CONTRACT_ADDRESS", address(0)); + address dkgContract = vm.envAddress("DKG_CONTRACT_ADDRESS"); address[] memory keypers = vm.envAddress("KEYPER_ADDRESSES", ","); uint256 threshold = vm.envUint("THRESHOLD"); @@ -59,9 +59,7 @@ contract AddKeyperSet is Script { keyperSet.addMembers(keypers); keyperSet.setThreshold(uint64(threshold)); keyperSet.setPublisher(address(eonKeyPublish)); - if (dkgContract != address(0)) { - keyperSet.setDKGContract(dkgContract); - } + keyperSet.setDKGContract(dkgContract); keyperSet.setFinalized(); console.log("keyperSet:", address(keyperSet)); console.log("eonKeyPublish:", address(eonKeyPublish)); From 0c9a9984b846399c88d6f276df50be6b6e51580e Mon Sep 17 00:00:00 2001 From: Jannik Date: Wed, 3 Jun 2026 22:38:17 +0200 Subject: [PATCH 18/25] fix: set dkg contract for fake keyper set --- script/Deploy.service.s.sol | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/script/Deploy.service.s.sol b/script/Deploy.service.s.sol index bb3c752..967da9e 100644 --- a/script/Deploy.service.s.sol +++ b/script/Deploy.service.s.sol @@ -21,6 +21,17 @@ contract Deploy is Script { // add bootstrap keyper set KeyperSet fakeKeyperset = new KeyperSet(); + // The bootstrap keyper set must designate a DKG Contract bound to this + // manager, otherwise addKeyperSet reverts DKGContractNotSet (registration + // -time validation from the check-dkg-address change). The bootstrap set + // never runs DKG, so a placeholder KeyBroadcastContract address is fine. + DKGContract bootstrapDkg = new DKGContract( + 10, + 40, + address(ksm), + address(0) + ); + fakeKeyperset.setDKGContract(address(bootstrapDkg)); fakeKeyperset.setFinalized(); ksm.addKeyperSet(0, address(fakeKeyperset)); From c768ee984f9fd247ea521650baabf849dc82ea03 Mon Sep 17 00:00:00 2001 From: Jannik Date: Wed, 3 Jun 2026 22:47:30 +0200 Subject: [PATCH 19/25] feat: add zero/empty guards --- src/common/DKGContract.sol | 8 ++++++++ src/common/ECIESKeyRegistry.sol | 4 ++++ test/DKGContract.t.sol | 27 +++++++++++++++++++++++++++ test/ECIESKeyRegistry.t.sol | 11 +++++------ 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/common/DKGContract.sol b/src/common/DKGContract.sol index 6e8ebd7..6762e45 100644 --- a/src/common/DKGContract.sol +++ b/src/common/DKGContract.sol @@ -13,6 +13,8 @@ contract DKGContract is IDKGContract { error MismatchedArrays(); error AlreadyVoted(); error WrongDKGContract(); + error ZeroLengthParameter(); + error EmptyEonPublicKey(); event DealingSubmitted( uint64 indexed keyperSetIndex, @@ -69,6 +71,9 @@ contract DKGContract is IDKGContract { address keyperSetManagerAddress, address keyBroadcastContractAddress ) { + if (phaseLength == 0 || dkgLeadLength == 0) { + revert ZeroLengthParameter(); + } PHASE_LENGTH = phaseLength; DKG_LEAD_LENGTH = dkgLeadLength; _keyperSetManager = KeyperSetManager(keyperSetManagerAddress); @@ -230,6 +235,9 @@ contract DKGContract is IDKGContract { _requirePhase(keyperSetIndex, retryCounter, Phase.Finalizing); _checkDKGContract(keyperSetIndex); _checkMember(keyperSetIndex, keyperIndex); + if (eonPublicKey.length == 0) { + revert EmptyEonPublicKey(); + } if (hasVoted[keyperSetIndex][retryCounter][msg.sender]) { revert AlreadyVoted(); } diff --git a/src/common/ECIESKeyRegistry.sol b/src/common/ECIESKeyRegistry.sol index 318d7e0..e1007d6 100644 --- a/src/common/ECIESKeyRegistry.sol +++ b/src/common/ECIESKeyRegistry.sol @@ -9,6 +9,7 @@ contract ECIESKeyRegistry { using EnumerableSet for EnumerableSet.AddressSet; error NotAMember(); + error EmptyECIESPublicKey(); event KeyRegistered(address indexed keyper, bytes eciesPublicKey); @@ -35,6 +36,9 @@ contract ECIESKeyRegistry { if (keyperSet.getMember(keyperIndex) != msg.sender) { revert NotAMember(); } + if (eciesPublicKey.length == 0) { + revert EmptyECIESPublicKey(); + } registeredKeypers.add(msg.sender); keys[msg.sender] = eciesPublicKey; emit KeyRegistered(msg.sender, eciesPublicKey); diff --git a/test/DKGContract.t.sol b/test/DKGContract.t.sol index 51fd7ab..38abd27 100644 --- a/test/DKGContract.t.sol +++ b/test/DKGContract.t.sol @@ -91,6 +91,26 @@ contract DKGContractTest is Test { keyperSetManager.addKeyperSet(ACTIVATION_BLOCK_0, address(keyperSet0)); } + function testConstructorRevertsOnZeroPhaseLength() public { + vm.expectRevert(DKGContract.ZeroLengthParameter.selector); + new DKGContract( + 0, + DKG_LEAD_LENGTH, + address(keyperSetManager), + address(keyBroadcastContract) + ); + } + + function testConstructorRevertsOnZeroDKGLeadLength() public { + vm.expectRevert(DKGContract.ZeroLengthParameter.selector); + new DKGContract( + PHASE_LENGTH, + 0, + address(keyperSetManager), + address(keyBroadcastContract) + ); + } + function testDeploysWithImmutables() public view { assertEq(dkgContract.PHASE_LENGTH(), PHASE_LENGTH); assertEq(dkgContract.DKG_LEAD_LENGTH(), DKG_LEAD_LENGTH); @@ -481,6 +501,13 @@ contract DKGContractTest is Test { dkgContract.submitSuccessVote(0, 0, 1, EON_KEY_A); } + function testSubmitSuccessVoteRevertsOnEmptyEonPublicKey() public { + vm.roll(FINALIZING_BLOCK); + vm.prank(keyper0); + vm.expectRevert(DKGContract.EmptyEonPublicKey.selector); + dkgContract.submitSuccessVote(0, 0, 0, new bytes(0)); + } + function testSubmitSuccessVoteRevertsOnDoubleVote() public { vm.roll(FINALIZING_BLOCK); vm.prank(keyper0); diff --git a/test/ECIESKeyRegistry.t.sol b/test/ECIESKeyRegistry.t.sol index 2452f04..c812fd6 100644 --- a/test/ECIESKeyRegistry.t.sol +++ b/test/ECIESKeyRegistry.t.sol @@ -144,18 +144,17 @@ contract ECIESKeyRegistryTest is Test { registry.registerKey(99, 0, hex"00"); } - function testRegisterKeyAcceptsArbitraryBytes() public { - // Registry stores arbitrary bytes — no format validation. + function testRegisterKeyAcceptsArbitraryNonEmptyBytes() public { bytes memory tiny = hex"00"; - bytes memory empty = new bytes(0); - vm.prank(keyper0); registry.registerKey(0, 0, tiny); assertEq(registry.getKey(keyper0), tiny); + } + function testRegisterKeyRevertsOnEmptyKey() public { vm.prank(keyper0); - registry.registerKey(0, 0, empty); - assertEq(registry.getKey(keyper0).length, 0); + vm.expectRevert(ECIESKeyRegistry.EmptyECIESPublicKey.selector); + registry.registerKey(0, 0, new bytes(0)); } // ------------------------------------------------------------------------- From f718cc108ce21756fc97dc4c72f3365efcbd03b7 Mon Sep 17 00:00:00 2001 From: Jannik Date: Wed, 8 Jul 2026 20:17:44 +0200 Subject: [PATCH 20/25] feat: add go bindings for new contracts --- bindings/dkgcontract/dkgcontract.go | 1405 +++++++++++++++++ bindings/ecieskeyregistry/ecieskeyregistry.go | 493 ++++++ bindings/keypersetmanager/keypersetmanager.go | 4 +- .../shuttereventtriggerregistryv1.go | 231 ++- gen_bindings.sh | 2 + 5 files changed, 2131 insertions(+), 4 deletions(-) create mode 100644 bindings/dkgcontract/dkgcontract.go create mode 100644 bindings/ecieskeyregistry/ecieskeyregistry.go diff --git a/bindings/dkgcontract/dkgcontract.go b/bindings/dkgcontract/dkgcontract.go new file mode 100644 index 0000000..2572047 --- /dev/null +++ b/bindings/dkgcontract/dkgcontract.go @@ -0,0 +1,1405 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package dkgcontract + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// DkgcontractMetaData contains all meta data concerning the Dkgcontract contract. +var DkgcontractMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"phaseLength\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"dkgLeadLength\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperSetManagerAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"keyBroadcastContractAddress\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"DKG_LEAD_LENGTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"PHASE_LENGTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"currentPhase\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumIDKGContract.Phase\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"cycleLength\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"dkgStart\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"int256\",\"internalType\":\"int256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"hasVoted\",\"inputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"keyBroadcastContract\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"keyperSetManager\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"submitAccusation\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"accusedIndices\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitApology\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"accuserIndices\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"polyEvalData\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitDealing\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"commitment\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"polyEvals\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitSuccessVote\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"eonPublicKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"succeeded\",\"inputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"voteCount\",\"inputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"AccusationSubmitted\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"accusedIndices\",\"type\":\"uint64[]\",\"indexed\":false,\"internalType\":\"uint64[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ApologySubmitted\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"accuserIndices\",\"type\":\"uint64[]\",\"indexed\":false,\"internalType\":\"uint64[]\"},{\"name\":\"polyEvalData\",\"type\":\"bytes[]\",\"indexed\":false,\"internalType\":\"bytes[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DKGSucceeded\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"eonPublicKey\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DealingSubmitted\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"commitment\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"polyEvals\",\"type\":\"bytes[]\",\"indexed\":false,\"internalType\":\"bytes[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SuccessVoteSubmitted\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"eonPublicKey\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AlreadySucceeded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AlreadyVoted\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"EmptyAccusation\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"EmptyEonPublicKey\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MismatchedArrays\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotKeyperAtIndex\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"WrongDKGContract\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"WrongPhase\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ZeroLengthParameter\",\"inputs\":[]}]", + Bin: "0x610100604052348015610010575f5ffd5b506040516120aa3803806120aa833981810160405281019061003291906101ce565b5f8467ffffffffffffffff16148061005357505f8367ffffffffffffffff16145b1561008a576040517f038016d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8367ffffffffffffffff1660808167ffffffffffffffff16815250508267ffffffffffffffff1660a08167ffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff168152505050505050610232565b5f5ffd5b5f67ffffffffffffffff82169050919050565b61015381610137565b811461015d575f5ffd5b50565b5f8151905061016e8161014a565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61019d82610174565b9050919050565b6101ad81610193565b81146101b7575f5ffd5b50565b5f815190506101c8816101a4565b92915050565b5f5f5f5f608085870312156101e6576101e5610133565b5b5f6101f387828801610160565b945050602061020487828801610160565b9350506040610215878288016101ba565b9250506060610226878288016101ba565b91505092959194509250565b60805160a05160c05160e051611e0d61029d5f395f81816109860152610b7901525f818161082501528181610b5201528181610cde01528181610ec9015261103801525f81816103c30152610d9f01525f818161030201528181610b2d0152610ba00152611e0d5ff3fe608060405234801561000f575f5ffd5b50600436106100e8575f3560e01c8063b209e7171161008a578063eac471a011610064578063eac471a014610248578063eb05c28014610266578063f01275b014610296578063f48f3d14146102b2576100e8565b8063b209e717146101ee578063d4b2cedd1461020c578063df6406311461022a576100e8565b80637642d0de116100c65780637642d0de1461015657806378a1b9db1461018657806382b870d3146101b657806394afc12d146101d2576100e8565b80630a3ec4d6146100ec57806316b89c3f1461011c5780633f9800981461013a575b5f5ffd5b610106600480360381019061010191906111f6565b6102e2565b60405161011391906112a7565b60405180910390f35b6101246103c1565b60405161013191906112cf565b60405180910390f35b610154600480360381019061014f919061139e565b6103e5565b005b610170600480360381019061016b91906114af565b610474565b60405161017d9190611519565b60405180910390f35b6101a0600480360381019061019b9190611532565b6104a9565b6040516101ad9190611519565b60405180910390f35b6101d060048036038101906101cb919061155d565b6104c5565b005b6101ec60048036038101906101e79190611636565b610a66565b005b6101f6610b2b565b60405161020391906112cf565b60405180910390f35b610214610b4f565b60405161022191906116c9565b60405180910390f35b610232610b76565b60405161023f91906116c9565b60405180910390f35b610250610b9d565b60405161025d91906112cf565b60405180910390f35b610280600480360381019061027b9190611715565b610bd0565b60405161028d91906112cf565b60405180910390f35b6102b060048036038101906102ab9190611765565b610c0c565b005b6102cc60048036038101906102c791906111f6565b610cda565b6040516102d99190611834565b60405180910390f35b5f5f6102ee8484610cda565b90505f81436102fd919061187a565b90505f7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1690505f821215610340575f93505050506103bb565b8082121561035457600193505050506103bb565b80600261036191906118ba565b82121561037457600293505050506103bb565b80600361038191906118ba565b82121561039457600393505050506103bb565b8060046103a191906118ba565b8212156103b457600493505050506103bb565b5f93505050505b92915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6103ee87610df0565b6103fa87876001610e5b565b61040387610ec6565b61040d8786611035565b8467ffffffffffffffff168667ffffffffffffffff168867ffffffffffffffff167fa5074728b92791250d48ccdc55266aca7b1cca22f89e1ef2ab91ccd7ae0f337d878787876040516104639493929190611ae2565b60405180910390a450505050505050565b6002602052825f5260405f20602052815f5260405f20602052805f5260405f205f92509250509054906101000a900460ff1681565b5f602052805f5260405f205f915054906101000a900460ff1681565b6104d185856004610e5b565b6104da85610ec6565b6104e48584611035565b5f8282905003610520576040517f59acc21d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f8667ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8567ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16156105e7576040517f7c9a1cf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160025f8767ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8667ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055505f8282604051610693929190611b49565b604051809103902090505f6001805f8967ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f9054906101000a900467ffffffffffffffff166107149190611b61565b90508060015f8967ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055508467ffffffffffffffff168667ffffffffffffffff168867ffffffffffffffff167facfc0aa3f6ba36ac0ffda53e00d2cdace2fd4a9e41e2fe3214032794332c37c387876040516107e5929190611b9c565b60405180910390a45f5f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16610a5d575f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f90f3bed896040518263ffffffff1660e01b815260040161087c91906112cf565b602060405180830381865afa158015610897573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108bb9190611bd2565b90505f8173ffffffffffffffffffffffffffffffffffffffff1663e75235b86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610907573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061092b9190611c11565b90508067ffffffffffffffff168367ffffffffffffffff1610610a5a5760015f5f8b67ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663daade8e88a88886040518463ffffffff1660e01b81526004016109e193929190611c3c565b5f604051808303815f87803b1580156109f8575f5ffd5b505af1925050508015610a09575060015b508767ffffffffffffffff168967ffffffffffffffff167fe6c9bd3daa50b9218615605cdf333410d405b7f3b8dbeee5a2373769679aa9f58888604051610a51929190611b9c565b60405180910390a35b50505b50505050505050565b610a6f85610df0565b610a7b85856002610e5b565b610a8485610ec6565b610a8e8584611035565b5f8282905003610aca576040517f2eeffe0b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8267ffffffffffffffff168467ffffffffffffffff168667ffffffffffffffff167fb5cc05e740a503c13e1b7ac3ad2d5abf41b91d2e5fca79455d34e515fb70849a8585604051610b1c929190611d28565b60405180910390a45050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f7f0000000000000000000000000000000000000000000000000000000000000000905090565b5f7f0000000000000000000000000000000000000000000000000000000000000000905090565b5f7f00000000000000000000000000000000000000000000000000000000000000006004610bcb9190611d4a565b905090565b6001602052825f5260405f20602052815f5260405f20602052805f5260405f205f92509250509054906101000a900467ffffffffffffffff1681565b610c1587610df0565b610c2187876003610e5b565b610c2a87610ec6565b610c348786611035565b818190508484905014610c73576040517fa121188700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8467ffffffffffffffff168667ffffffffffffffff168867ffffffffffffffff167f62729f0820cf3ab60fbd63a51cdeae0554d0ab24f843b86bd0d2591594d6913687878787604051610cc99493929190611d86565b60405180910390a450505050505050565b5f5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663636df979856040518263ffffffff1660e01b8152600401610d3591906112cf565b602060405180830381865afa158015610d50573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d749190611c11565b9050610d7e610b9d565b67ffffffffffffffff168367ffffffffffffffff16610d9d91906118ba565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168267ffffffffffffffff16610ddd919061187a565b610de79190611dbf565b91505092915050565b5f5f8267ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1615610e58576040517fe0f5ec9d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b806004811115610e6e57610e6d611234565b5b610e7884846102e2565b6004811115610e8a57610e89611234565b5b14610ec1576040517fe2586bcc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f90f3bed836040518263ffffffff1660e01b8152600401610f2091906112cf565b602060405180830381865afa158015610f3b573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f5f9190611bd2565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff166266f0a86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fc0573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fe49190611bd2565b73ffffffffffffffffffffffffffffffffffffffff1614611031576040517ff62f18e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f90f3bed846040518263ffffffff1660e01b815260040161108f91906112cf565b602060405180830381865afa1580156110aa573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110ce9190611bd2565b90503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16632e8e6cad846040518263ffffffff1660e01b815260040161112091906112cf565b602060405180830381865afa15801561113b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061115f9190611bd2565b73ffffffffffffffffffffffffffffffffffffffff16146111ac576040517f7bf9580300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82169050919050565b6111d5816111b9565b81146111df575f5ffd5b50565b5f813590506111f0816111cc565b92915050565b5f5f6040838503121561120c5761120b6111b1565b5b5f611219858286016111e2565b925050602061122a858286016111e2565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b6005811061127257611271611234565b5b50565b5f81905061128282611261565b919050565b5f61129182611275565b9050919050565b6112a181611287565b82525050565b5f6020820190506112ba5f830184611298565b92915050565b6112c9816111b9565b82525050565b5f6020820190506112e25f8301846112c0565b92915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f840112611309576113086112e8565b5b8235905067ffffffffffffffff811115611326576113256112ec565b5b602083019150836001820283011115611342576113416112f0565b5b9250929050565b5f5f83601f84011261135e5761135d6112e8565b5b8235905067ffffffffffffffff81111561137b5761137a6112ec565b5b602083019150836020820283011115611397576113966112f0565b5b9250929050565b5f5f5f5f5f5f5f60a0888a0312156113b9576113b86111b1565b5b5f6113c68a828b016111e2565b97505060206113d78a828b016111e2565b96505060406113e88a828b016111e2565b955050606088013567ffffffffffffffff811115611409576114086111b5565b5b6114158a828b016112f4565b9450945050608088013567ffffffffffffffff811115611438576114376111b5565b5b6114448a828b01611349565b925092505092959891949750929550565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61147e82611455565b9050919050565b61148e81611474565b8114611498575f5ffd5b50565b5f813590506114a981611485565b92915050565b5f5f5f606084860312156114c6576114c56111b1565b5b5f6114d3868287016111e2565b93505060206114e4868287016111e2565b92505060406114f58682870161149b565b9150509250925092565b5f8115159050919050565b611513816114ff565b82525050565b5f60208201905061152c5f83018461150a565b92915050565b5f60208284031215611547576115466111b1565b5b5f611554848285016111e2565b91505092915050565b5f5f5f5f5f60808688031215611576576115756111b1565b5b5f611583888289016111e2565b9550506020611594888289016111e2565b94505060406115a5888289016111e2565b935050606086013567ffffffffffffffff8111156115c6576115c56111b5565b5b6115d2888289016112f4565b92509250509295509295909350565b5f5f83601f8401126115f6576115f56112e8565b5b8235905067ffffffffffffffff811115611613576116126112ec565b5b60208301915083602082028301111561162f5761162e6112f0565b5b9250929050565b5f5f5f5f5f6080868803121561164f5761164e6111b1565b5b5f61165c888289016111e2565b955050602061166d888289016111e2565b945050604061167e888289016111e2565b935050606086013567ffffffffffffffff81111561169f5761169e6111b5565b5b6116ab888289016115e1565b92509250509295509295909350565b6116c381611474565b82525050565b5f6020820190506116dc5f8301846116ba565b92915050565b5f819050919050565b6116f4816116e2565b81146116fe575f5ffd5b50565b5f8135905061170f816116eb565b92915050565b5f5f5f6060848603121561172c5761172b6111b1565b5b5f611739868287016111e2565b935050602061174a868287016111e2565b925050604061175b86828701611701565b9150509250925092565b5f5f5f5f5f5f5f60a0888a0312156117805761177f6111b1565b5b5f61178d8a828b016111e2565b975050602061179e8a828b016111e2565b96505060406117af8a828b016111e2565b955050606088013567ffffffffffffffff8111156117d0576117cf6111b5565b5b6117dc8a828b016115e1565b9450945050608088013567ffffffffffffffff8111156117ff576117fe6111b5565b5b61180b8a828b01611349565b925092505092959891949750929550565b5f819050919050565b61182e8161181c565b82525050565b5f6020820190506118475f830184611825565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6118848261181c565b915061188f8361181c565b925082820390508181125f8412168282135f8512151617156118b4576118b361184d565b5b92915050565b5f6118c48261181c565b91506118cf8361181c565b92508282026118dd8161181c565b91507f800000000000000000000000000000000000000000000000000000000000000084145f841216156119145761191361184d565b5b82820584148315176119295761192861184d565b5b5092915050565b5f82825260208201905092915050565b828183375f83830152505050565b5f601f19601f8301169050919050565b5f6119698385611930565b9350611976838584611940565b61197f8361194e565b840190509392505050565b5f82825260208201905092915050565b5f819050919050565b5f82825260208201905092915050565b5f6119be83856119a3565b93506119cb838584611940565b6119d48361194e565b840190509392505050565b5f6119eb8484846119b3565b90509392505050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83356001602003843603038112611a1c57611a1b6119fc565b5b83810192508235915060208301925067ffffffffffffffff821115611a4457611a436119f4565b5b600182023603831315611a5a57611a596119f8565b5b509250929050565b5f602082019050919050565b5f611a79838561198a565b935083602084028501611a8b8461199a565b805f5b87811015611ad0578484038952611aa58284611a00565b611ab08682846119df565b9550611abb84611a62565b935060208b019a505050600181019050611a8e565b50829750879450505050509392505050565b5f6040820190508181035f830152611afb81868861195e565b90508181036020830152611b10818486611a6e565b905095945050505050565b5f81905092915050565b5f611b308385611b1b565b9350611b3d838584611940565b82840190509392505050565b5f611b55828486611b25565b91508190509392505050565b5f611b6b826111b9565b9150611b76836111b9565b9250828201905067ffffffffffffffff811115611b9657611b9561184d565b5b92915050565b5f6020820190508181035f830152611bb581848661195e565b90509392505050565b5f81519050611bcc81611485565b92915050565b5f60208284031215611be757611be66111b1565b5b5f611bf484828501611bbe565b91505092915050565b5f81519050611c0b816111cc565b92915050565b5f60208284031215611c2657611c256111b1565b5b5f611c3384828501611bfd565b91505092915050565b5f604082019050611c4f5f8301866112c0565b8181036020830152611c6281848661195e565b9050949350505050565b5f82825260208201905092915050565b5f819050919050565b611c8e816111b9565b82525050565b5f611c9f8383611c85565b60208301905092915050565b5f611cb960208401846111e2565b905092915050565b5f602082019050919050565b5f611cd88385611c6c565b9350611ce382611c7c565b805f5b85811015611d1b57611cf88284611cab565b611d028882611c94565b9750611d0d83611cc1565b925050600181019050611ce6565b5085925050509392505050565b5f6020820190508181035f830152611d41818486611ccd565b90509392505050565b5f611d54826111b9565b9150611d5f836111b9565b9250828202611d6d816111b9565b9150808214611d7f57611d7e61184d565b5b5092915050565b5f6040820190508181035f830152611d9f818688611ccd565b90508181036020830152611db4818486611a6e565b905095945050505050565b5f611dc98261181c565b9150611dd48361181c565b92508282019050828112155f8312168382125f841215161715611dfa57611df961184d565b5b9291505056fea164736f6c634300081c000a", +} + +// DkgcontractABI is the input ABI used to generate the binding from. +// Deprecated: Use DkgcontractMetaData.ABI instead. +var DkgcontractABI = DkgcontractMetaData.ABI + +// DkgcontractBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use DkgcontractMetaData.Bin instead. +var DkgcontractBin = DkgcontractMetaData.Bin + +// DeployDkgcontract deploys a new Ethereum contract, binding an instance of Dkgcontract to it. +func DeployDkgcontract(auth *bind.TransactOpts, backend bind.ContractBackend, phaseLength uint64, dkgLeadLength uint64, keyperSetManagerAddress common.Address, keyBroadcastContractAddress common.Address) (common.Address, *types.Transaction, *Dkgcontract, error) { + parsed, err := DkgcontractMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(DkgcontractBin), backend, phaseLength, dkgLeadLength, keyperSetManagerAddress, keyBroadcastContractAddress) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Dkgcontract{DkgcontractCaller: DkgcontractCaller{contract: contract}, DkgcontractTransactor: DkgcontractTransactor{contract: contract}, DkgcontractFilterer: DkgcontractFilterer{contract: contract}}, nil +} + +// Dkgcontract is an auto generated Go binding around an Ethereum contract. +type Dkgcontract struct { + DkgcontractCaller // Read-only binding to the contract + DkgcontractTransactor // Write-only binding to the contract + DkgcontractFilterer // Log filterer for contract events +} + +// DkgcontractCaller is an auto generated read-only Go binding around an Ethereum contract. +type DkgcontractCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// DkgcontractTransactor is an auto generated write-only Go binding around an Ethereum contract. +type DkgcontractTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// DkgcontractFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type DkgcontractFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// DkgcontractSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type DkgcontractSession struct { + Contract *Dkgcontract // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// DkgcontractCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type DkgcontractCallerSession struct { + Contract *DkgcontractCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// DkgcontractTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type DkgcontractTransactorSession struct { + Contract *DkgcontractTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// DkgcontractRaw is an auto generated low-level Go binding around an Ethereum contract. +type DkgcontractRaw struct { + Contract *Dkgcontract // Generic contract binding to access the raw methods on +} + +// DkgcontractCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type DkgcontractCallerRaw struct { + Contract *DkgcontractCaller // Generic read-only contract binding to access the raw methods on +} + +// DkgcontractTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type DkgcontractTransactorRaw struct { + Contract *DkgcontractTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewDkgcontract creates a new instance of Dkgcontract, bound to a specific deployed contract. +func NewDkgcontract(address common.Address, backend bind.ContractBackend) (*Dkgcontract, error) { + contract, err := bindDkgcontract(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Dkgcontract{DkgcontractCaller: DkgcontractCaller{contract: contract}, DkgcontractTransactor: DkgcontractTransactor{contract: contract}, DkgcontractFilterer: DkgcontractFilterer{contract: contract}}, nil +} + +// NewDkgcontractCaller creates a new read-only instance of Dkgcontract, bound to a specific deployed contract. +func NewDkgcontractCaller(address common.Address, caller bind.ContractCaller) (*DkgcontractCaller, error) { + contract, err := bindDkgcontract(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &DkgcontractCaller{contract: contract}, nil +} + +// NewDkgcontractTransactor creates a new write-only instance of Dkgcontract, bound to a specific deployed contract. +func NewDkgcontractTransactor(address common.Address, transactor bind.ContractTransactor) (*DkgcontractTransactor, error) { + contract, err := bindDkgcontract(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &DkgcontractTransactor{contract: contract}, nil +} + +// NewDkgcontractFilterer creates a new log filterer instance of Dkgcontract, bound to a specific deployed contract. +func NewDkgcontractFilterer(address common.Address, filterer bind.ContractFilterer) (*DkgcontractFilterer, error) { + contract, err := bindDkgcontract(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &DkgcontractFilterer{contract: contract}, nil +} + +// bindDkgcontract binds a generic wrapper to an already deployed contract. +func bindDkgcontract(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := DkgcontractMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Dkgcontract *DkgcontractRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Dkgcontract.Contract.DkgcontractCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Dkgcontract *DkgcontractRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Dkgcontract.Contract.DkgcontractTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Dkgcontract *DkgcontractRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Dkgcontract.Contract.DkgcontractTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Dkgcontract *DkgcontractCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Dkgcontract.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Dkgcontract *DkgcontractTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Dkgcontract.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Dkgcontract *DkgcontractTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Dkgcontract.Contract.contract.Transact(opts, method, params...) +} + +// DKGLEADLENGTH is a free data retrieval call binding the contract method 0x16b89c3f. +// +// Solidity: function DKG_LEAD_LENGTH() view returns(uint64) +func (_Dkgcontract *DkgcontractCaller) DKGLEADLENGTH(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _Dkgcontract.contract.Call(opts, &out, "DKG_LEAD_LENGTH") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// DKGLEADLENGTH is a free data retrieval call binding the contract method 0x16b89c3f. +// +// Solidity: function DKG_LEAD_LENGTH() view returns(uint64) +func (_Dkgcontract *DkgcontractSession) DKGLEADLENGTH() (uint64, error) { + return _Dkgcontract.Contract.DKGLEADLENGTH(&_Dkgcontract.CallOpts) +} + +// DKGLEADLENGTH is a free data retrieval call binding the contract method 0x16b89c3f. +// +// Solidity: function DKG_LEAD_LENGTH() view returns(uint64) +func (_Dkgcontract *DkgcontractCallerSession) DKGLEADLENGTH() (uint64, error) { + return _Dkgcontract.Contract.DKGLEADLENGTH(&_Dkgcontract.CallOpts) +} + +// PHASELENGTH is a free data retrieval call binding the contract method 0xb209e717. +// +// Solidity: function PHASE_LENGTH() view returns(uint64) +func (_Dkgcontract *DkgcontractCaller) PHASELENGTH(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _Dkgcontract.contract.Call(opts, &out, "PHASE_LENGTH") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// PHASELENGTH is a free data retrieval call binding the contract method 0xb209e717. +// +// Solidity: function PHASE_LENGTH() view returns(uint64) +func (_Dkgcontract *DkgcontractSession) PHASELENGTH() (uint64, error) { + return _Dkgcontract.Contract.PHASELENGTH(&_Dkgcontract.CallOpts) +} + +// PHASELENGTH is a free data retrieval call binding the contract method 0xb209e717. +// +// Solidity: function PHASE_LENGTH() view returns(uint64) +func (_Dkgcontract *DkgcontractCallerSession) PHASELENGTH() (uint64, error) { + return _Dkgcontract.Contract.PHASELENGTH(&_Dkgcontract.CallOpts) +} + +// CurrentPhase is a free data retrieval call binding the contract method 0x0a3ec4d6. +// +// Solidity: function currentPhase(uint64 keyperSetIndex, uint64 retryCounter) view returns(uint8) +func (_Dkgcontract *DkgcontractCaller) CurrentPhase(opts *bind.CallOpts, keyperSetIndex uint64, retryCounter uint64) (uint8, error) { + var out []interface{} + err := _Dkgcontract.contract.Call(opts, &out, "currentPhase", keyperSetIndex, retryCounter) + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// CurrentPhase is a free data retrieval call binding the contract method 0x0a3ec4d6. +// +// Solidity: function currentPhase(uint64 keyperSetIndex, uint64 retryCounter) view returns(uint8) +func (_Dkgcontract *DkgcontractSession) CurrentPhase(keyperSetIndex uint64, retryCounter uint64) (uint8, error) { + return _Dkgcontract.Contract.CurrentPhase(&_Dkgcontract.CallOpts, keyperSetIndex, retryCounter) +} + +// CurrentPhase is a free data retrieval call binding the contract method 0x0a3ec4d6. +// +// Solidity: function currentPhase(uint64 keyperSetIndex, uint64 retryCounter) view returns(uint8) +func (_Dkgcontract *DkgcontractCallerSession) CurrentPhase(keyperSetIndex uint64, retryCounter uint64) (uint8, error) { + return _Dkgcontract.Contract.CurrentPhase(&_Dkgcontract.CallOpts, keyperSetIndex, retryCounter) +} + +// CycleLength is a free data retrieval call binding the contract method 0xeac471a0. +// +// Solidity: function cycleLength() view returns(uint64) +func (_Dkgcontract *DkgcontractCaller) CycleLength(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _Dkgcontract.contract.Call(opts, &out, "cycleLength") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// CycleLength is a free data retrieval call binding the contract method 0xeac471a0. +// +// Solidity: function cycleLength() view returns(uint64) +func (_Dkgcontract *DkgcontractSession) CycleLength() (uint64, error) { + return _Dkgcontract.Contract.CycleLength(&_Dkgcontract.CallOpts) +} + +// CycleLength is a free data retrieval call binding the contract method 0xeac471a0. +// +// Solidity: function cycleLength() view returns(uint64) +func (_Dkgcontract *DkgcontractCallerSession) CycleLength() (uint64, error) { + return _Dkgcontract.Contract.CycleLength(&_Dkgcontract.CallOpts) +} + +// DkgStart is a free data retrieval call binding the contract method 0xf48f3d14. +// +// Solidity: function dkgStart(uint64 keyperSetIndex, uint64 retryCounter) view returns(int256) +func (_Dkgcontract *DkgcontractCaller) DkgStart(opts *bind.CallOpts, keyperSetIndex uint64, retryCounter uint64) (*big.Int, error) { + var out []interface{} + err := _Dkgcontract.contract.Call(opts, &out, "dkgStart", keyperSetIndex, retryCounter) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// DkgStart is a free data retrieval call binding the contract method 0xf48f3d14. +// +// Solidity: function dkgStart(uint64 keyperSetIndex, uint64 retryCounter) view returns(int256) +func (_Dkgcontract *DkgcontractSession) DkgStart(keyperSetIndex uint64, retryCounter uint64) (*big.Int, error) { + return _Dkgcontract.Contract.DkgStart(&_Dkgcontract.CallOpts, keyperSetIndex, retryCounter) +} + +// DkgStart is a free data retrieval call binding the contract method 0xf48f3d14. +// +// Solidity: function dkgStart(uint64 keyperSetIndex, uint64 retryCounter) view returns(int256) +func (_Dkgcontract *DkgcontractCallerSession) DkgStart(keyperSetIndex uint64, retryCounter uint64) (*big.Int, error) { + return _Dkgcontract.Contract.DkgStart(&_Dkgcontract.CallOpts, keyperSetIndex, retryCounter) +} + +// HasVoted is a free data retrieval call binding the contract method 0x7642d0de. +// +// Solidity: function hasVoted(uint64 , uint64 , address ) view returns(bool) +func (_Dkgcontract *DkgcontractCaller) HasVoted(opts *bind.CallOpts, arg0 uint64, arg1 uint64, arg2 common.Address) (bool, error) { + var out []interface{} + err := _Dkgcontract.contract.Call(opts, &out, "hasVoted", arg0, arg1, arg2) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// HasVoted is a free data retrieval call binding the contract method 0x7642d0de. +// +// Solidity: function hasVoted(uint64 , uint64 , address ) view returns(bool) +func (_Dkgcontract *DkgcontractSession) HasVoted(arg0 uint64, arg1 uint64, arg2 common.Address) (bool, error) { + return _Dkgcontract.Contract.HasVoted(&_Dkgcontract.CallOpts, arg0, arg1, arg2) +} + +// HasVoted is a free data retrieval call binding the contract method 0x7642d0de. +// +// Solidity: function hasVoted(uint64 , uint64 , address ) view returns(bool) +func (_Dkgcontract *DkgcontractCallerSession) HasVoted(arg0 uint64, arg1 uint64, arg2 common.Address) (bool, error) { + return _Dkgcontract.Contract.HasVoted(&_Dkgcontract.CallOpts, arg0, arg1, arg2) +} + +// KeyBroadcastContract is a free data retrieval call binding the contract method 0xdf640631. +// +// Solidity: function keyBroadcastContract() view returns(address) +func (_Dkgcontract *DkgcontractCaller) KeyBroadcastContract(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Dkgcontract.contract.Call(opts, &out, "keyBroadcastContract") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// KeyBroadcastContract is a free data retrieval call binding the contract method 0xdf640631. +// +// Solidity: function keyBroadcastContract() view returns(address) +func (_Dkgcontract *DkgcontractSession) KeyBroadcastContract() (common.Address, error) { + return _Dkgcontract.Contract.KeyBroadcastContract(&_Dkgcontract.CallOpts) +} + +// KeyBroadcastContract is a free data retrieval call binding the contract method 0xdf640631. +// +// Solidity: function keyBroadcastContract() view returns(address) +func (_Dkgcontract *DkgcontractCallerSession) KeyBroadcastContract() (common.Address, error) { + return _Dkgcontract.Contract.KeyBroadcastContract(&_Dkgcontract.CallOpts) +} + +// KeyperSetManager is a free data retrieval call binding the contract method 0xd4b2cedd. +// +// Solidity: function keyperSetManager() view returns(address) +func (_Dkgcontract *DkgcontractCaller) KeyperSetManager(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Dkgcontract.contract.Call(opts, &out, "keyperSetManager") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// KeyperSetManager is a free data retrieval call binding the contract method 0xd4b2cedd. +// +// Solidity: function keyperSetManager() view returns(address) +func (_Dkgcontract *DkgcontractSession) KeyperSetManager() (common.Address, error) { + return _Dkgcontract.Contract.KeyperSetManager(&_Dkgcontract.CallOpts) +} + +// KeyperSetManager is a free data retrieval call binding the contract method 0xd4b2cedd. +// +// Solidity: function keyperSetManager() view returns(address) +func (_Dkgcontract *DkgcontractCallerSession) KeyperSetManager() (common.Address, error) { + return _Dkgcontract.Contract.KeyperSetManager(&_Dkgcontract.CallOpts) +} + +// Succeeded is a free data retrieval call binding the contract method 0x78a1b9db. +// +// Solidity: function succeeded(uint64 ) view returns(bool) +func (_Dkgcontract *DkgcontractCaller) Succeeded(opts *bind.CallOpts, arg0 uint64) (bool, error) { + var out []interface{} + err := _Dkgcontract.contract.Call(opts, &out, "succeeded", arg0) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// Succeeded is a free data retrieval call binding the contract method 0x78a1b9db. +// +// Solidity: function succeeded(uint64 ) view returns(bool) +func (_Dkgcontract *DkgcontractSession) Succeeded(arg0 uint64) (bool, error) { + return _Dkgcontract.Contract.Succeeded(&_Dkgcontract.CallOpts, arg0) +} + +// Succeeded is a free data retrieval call binding the contract method 0x78a1b9db. +// +// Solidity: function succeeded(uint64 ) view returns(bool) +func (_Dkgcontract *DkgcontractCallerSession) Succeeded(arg0 uint64) (bool, error) { + return _Dkgcontract.Contract.Succeeded(&_Dkgcontract.CallOpts, arg0) +} + +// VoteCount is a free data retrieval call binding the contract method 0xeb05c280. +// +// Solidity: function voteCount(uint64 , uint64 , bytes32 ) view returns(uint64) +func (_Dkgcontract *DkgcontractCaller) VoteCount(opts *bind.CallOpts, arg0 uint64, arg1 uint64, arg2 [32]byte) (uint64, error) { + var out []interface{} + err := _Dkgcontract.contract.Call(opts, &out, "voteCount", arg0, arg1, arg2) + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// VoteCount is a free data retrieval call binding the contract method 0xeb05c280. +// +// Solidity: function voteCount(uint64 , uint64 , bytes32 ) view returns(uint64) +func (_Dkgcontract *DkgcontractSession) VoteCount(arg0 uint64, arg1 uint64, arg2 [32]byte) (uint64, error) { + return _Dkgcontract.Contract.VoteCount(&_Dkgcontract.CallOpts, arg0, arg1, arg2) +} + +// VoteCount is a free data retrieval call binding the contract method 0xeb05c280. +// +// Solidity: function voteCount(uint64 , uint64 , bytes32 ) view returns(uint64) +func (_Dkgcontract *DkgcontractCallerSession) VoteCount(arg0 uint64, arg1 uint64, arg2 [32]byte) (uint64, error) { + return _Dkgcontract.Contract.VoteCount(&_Dkgcontract.CallOpts, arg0, arg1, arg2) +} + +// SubmitAccusation is a paid mutator transaction binding the contract method 0x94afc12d. +// +// Solidity: function submitAccusation(uint64 keyperSetIndex, uint64 retryCounter, uint64 keyperIndex, uint64[] accusedIndices) returns() +func (_Dkgcontract *DkgcontractTransactor) SubmitAccusation(opts *bind.TransactOpts, keyperSetIndex uint64, retryCounter uint64, keyperIndex uint64, accusedIndices []uint64) (*types.Transaction, error) { + return _Dkgcontract.contract.Transact(opts, "submitAccusation", keyperSetIndex, retryCounter, keyperIndex, accusedIndices) +} + +// SubmitAccusation is a paid mutator transaction binding the contract method 0x94afc12d. +// +// Solidity: function submitAccusation(uint64 keyperSetIndex, uint64 retryCounter, uint64 keyperIndex, uint64[] accusedIndices) returns() +func (_Dkgcontract *DkgcontractSession) SubmitAccusation(keyperSetIndex uint64, retryCounter uint64, keyperIndex uint64, accusedIndices []uint64) (*types.Transaction, error) { + return _Dkgcontract.Contract.SubmitAccusation(&_Dkgcontract.TransactOpts, keyperSetIndex, retryCounter, keyperIndex, accusedIndices) +} + +// SubmitAccusation is a paid mutator transaction binding the contract method 0x94afc12d. +// +// Solidity: function submitAccusation(uint64 keyperSetIndex, uint64 retryCounter, uint64 keyperIndex, uint64[] accusedIndices) returns() +func (_Dkgcontract *DkgcontractTransactorSession) SubmitAccusation(keyperSetIndex uint64, retryCounter uint64, keyperIndex uint64, accusedIndices []uint64) (*types.Transaction, error) { + return _Dkgcontract.Contract.SubmitAccusation(&_Dkgcontract.TransactOpts, keyperSetIndex, retryCounter, keyperIndex, accusedIndices) +} + +// SubmitApology is a paid mutator transaction binding the contract method 0xf01275b0. +// +// Solidity: function submitApology(uint64 keyperSetIndex, uint64 retryCounter, uint64 keyperIndex, uint64[] accuserIndices, bytes[] polyEvalData) returns() +func (_Dkgcontract *DkgcontractTransactor) SubmitApology(opts *bind.TransactOpts, keyperSetIndex uint64, retryCounter uint64, keyperIndex uint64, accuserIndices []uint64, polyEvalData [][]byte) (*types.Transaction, error) { + return _Dkgcontract.contract.Transact(opts, "submitApology", keyperSetIndex, retryCounter, keyperIndex, accuserIndices, polyEvalData) +} + +// SubmitApology is a paid mutator transaction binding the contract method 0xf01275b0. +// +// Solidity: function submitApology(uint64 keyperSetIndex, uint64 retryCounter, uint64 keyperIndex, uint64[] accuserIndices, bytes[] polyEvalData) returns() +func (_Dkgcontract *DkgcontractSession) SubmitApology(keyperSetIndex uint64, retryCounter uint64, keyperIndex uint64, accuserIndices []uint64, polyEvalData [][]byte) (*types.Transaction, error) { + return _Dkgcontract.Contract.SubmitApology(&_Dkgcontract.TransactOpts, keyperSetIndex, retryCounter, keyperIndex, accuserIndices, polyEvalData) +} + +// SubmitApology is a paid mutator transaction binding the contract method 0xf01275b0. +// +// Solidity: function submitApology(uint64 keyperSetIndex, uint64 retryCounter, uint64 keyperIndex, uint64[] accuserIndices, bytes[] polyEvalData) returns() +func (_Dkgcontract *DkgcontractTransactorSession) SubmitApology(keyperSetIndex uint64, retryCounter uint64, keyperIndex uint64, accuserIndices []uint64, polyEvalData [][]byte) (*types.Transaction, error) { + return _Dkgcontract.Contract.SubmitApology(&_Dkgcontract.TransactOpts, keyperSetIndex, retryCounter, keyperIndex, accuserIndices, polyEvalData) +} + +// SubmitDealing is a paid mutator transaction binding the contract method 0x3f980098. +// +// Solidity: function submitDealing(uint64 keyperSetIndex, uint64 retryCounter, uint64 keyperIndex, bytes commitment, bytes[] polyEvals) returns() +func (_Dkgcontract *DkgcontractTransactor) SubmitDealing(opts *bind.TransactOpts, keyperSetIndex uint64, retryCounter uint64, keyperIndex uint64, commitment []byte, polyEvals [][]byte) (*types.Transaction, error) { + return _Dkgcontract.contract.Transact(opts, "submitDealing", keyperSetIndex, retryCounter, keyperIndex, commitment, polyEvals) +} + +// SubmitDealing is a paid mutator transaction binding the contract method 0x3f980098. +// +// Solidity: function submitDealing(uint64 keyperSetIndex, uint64 retryCounter, uint64 keyperIndex, bytes commitment, bytes[] polyEvals) returns() +func (_Dkgcontract *DkgcontractSession) SubmitDealing(keyperSetIndex uint64, retryCounter uint64, keyperIndex uint64, commitment []byte, polyEvals [][]byte) (*types.Transaction, error) { + return _Dkgcontract.Contract.SubmitDealing(&_Dkgcontract.TransactOpts, keyperSetIndex, retryCounter, keyperIndex, commitment, polyEvals) +} + +// SubmitDealing is a paid mutator transaction binding the contract method 0x3f980098. +// +// Solidity: function submitDealing(uint64 keyperSetIndex, uint64 retryCounter, uint64 keyperIndex, bytes commitment, bytes[] polyEvals) returns() +func (_Dkgcontract *DkgcontractTransactorSession) SubmitDealing(keyperSetIndex uint64, retryCounter uint64, keyperIndex uint64, commitment []byte, polyEvals [][]byte) (*types.Transaction, error) { + return _Dkgcontract.Contract.SubmitDealing(&_Dkgcontract.TransactOpts, keyperSetIndex, retryCounter, keyperIndex, commitment, polyEvals) +} + +// SubmitSuccessVote is a paid mutator transaction binding the contract method 0x82b870d3. +// +// Solidity: function submitSuccessVote(uint64 keyperSetIndex, uint64 retryCounter, uint64 keyperIndex, bytes eonPublicKey) returns() +func (_Dkgcontract *DkgcontractTransactor) SubmitSuccessVote(opts *bind.TransactOpts, keyperSetIndex uint64, retryCounter uint64, keyperIndex uint64, eonPublicKey []byte) (*types.Transaction, error) { + return _Dkgcontract.contract.Transact(opts, "submitSuccessVote", keyperSetIndex, retryCounter, keyperIndex, eonPublicKey) +} + +// SubmitSuccessVote is a paid mutator transaction binding the contract method 0x82b870d3. +// +// Solidity: function submitSuccessVote(uint64 keyperSetIndex, uint64 retryCounter, uint64 keyperIndex, bytes eonPublicKey) returns() +func (_Dkgcontract *DkgcontractSession) SubmitSuccessVote(keyperSetIndex uint64, retryCounter uint64, keyperIndex uint64, eonPublicKey []byte) (*types.Transaction, error) { + return _Dkgcontract.Contract.SubmitSuccessVote(&_Dkgcontract.TransactOpts, keyperSetIndex, retryCounter, keyperIndex, eonPublicKey) +} + +// SubmitSuccessVote is a paid mutator transaction binding the contract method 0x82b870d3. +// +// Solidity: function submitSuccessVote(uint64 keyperSetIndex, uint64 retryCounter, uint64 keyperIndex, bytes eonPublicKey) returns() +func (_Dkgcontract *DkgcontractTransactorSession) SubmitSuccessVote(keyperSetIndex uint64, retryCounter uint64, keyperIndex uint64, eonPublicKey []byte) (*types.Transaction, error) { + return _Dkgcontract.Contract.SubmitSuccessVote(&_Dkgcontract.TransactOpts, keyperSetIndex, retryCounter, keyperIndex, eonPublicKey) +} + +// DkgcontractAccusationSubmittedIterator is returned from FilterAccusationSubmitted and is used to iterate over the raw logs and unpacked data for AccusationSubmitted events raised by the Dkgcontract contract. +type DkgcontractAccusationSubmittedIterator struct { + Event *DkgcontractAccusationSubmitted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *DkgcontractAccusationSubmittedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(DkgcontractAccusationSubmitted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(DkgcontractAccusationSubmitted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *DkgcontractAccusationSubmittedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DkgcontractAccusationSubmittedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DkgcontractAccusationSubmitted represents a AccusationSubmitted event raised by the Dkgcontract contract. +type DkgcontractAccusationSubmitted struct { + KeyperSetIndex uint64 + RetryCounter uint64 + KeyperIndex uint64 + AccusedIndices []uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAccusationSubmitted is a free log retrieval operation binding the contract event 0xb5cc05e740a503c13e1b7ac3ad2d5abf41b91d2e5fca79455d34e515fb70849a. +// +// Solidity: event AccusationSubmitted(uint64 indexed keyperSetIndex, uint64 indexed retryCounter, uint64 indexed keyperIndex, uint64[] accusedIndices) +func (_Dkgcontract *DkgcontractFilterer) FilterAccusationSubmitted(opts *bind.FilterOpts, keyperSetIndex []uint64, retryCounter []uint64, keyperIndex []uint64) (*DkgcontractAccusationSubmittedIterator, error) { + + var keyperSetIndexRule []interface{} + for _, keyperSetIndexItem := range keyperSetIndex { + keyperSetIndexRule = append(keyperSetIndexRule, keyperSetIndexItem) + } + var retryCounterRule []interface{} + for _, retryCounterItem := range retryCounter { + retryCounterRule = append(retryCounterRule, retryCounterItem) + } + var keyperIndexRule []interface{} + for _, keyperIndexItem := range keyperIndex { + keyperIndexRule = append(keyperIndexRule, keyperIndexItem) + } + + logs, sub, err := _Dkgcontract.contract.FilterLogs(opts, "AccusationSubmitted", keyperSetIndexRule, retryCounterRule, keyperIndexRule) + if err != nil { + return nil, err + } + return &DkgcontractAccusationSubmittedIterator{contract: _Dkgcontract.contract, event: "AccusationSubmitted", logs: logs, sub: sub}, nil +} + +// WatchAccusationSubmitted is a free log subscription operation binding the contract event 0xb5cc05e740a503c13e1b7ac3ad2d5abf41b91d2e5fca79455d34e515fb70849a. +// +// Solidity: event AccusationSubmitted(uint64 indexed keyperSetIndex, uint64 indexed retryCounter, uint64 indexed keyperIndex, uint64[] accusedIndices) +func (_Dkgcontract *DkgcontractFilterer) WatchAccusationSubmitted(opts *bind.WatchOpts, sink chan<- *DkgcontractAccusationSubmitted, keyperSetIndex []uint64, retryCounter []uint64, keyperIndex []uint64) (event.Subscription, error) { + + var keyperSetIndexRule []interface{} + for _, keyperSetIndexItem := range keyperSetIndex { + keyperSetIndexRule = append(keyperSetIndexRule, keyperSetIndexItem) + } + var retryCounterRule []interface{} + for _, retryCounterItem := range retryCounter { + retryCounterRule = append(retryCounterRule, retryCounterItem) + } + var keyperIndexRule []interface{} + for _, keyperIndexItem := range keyperIndex { + keyperIndexRule = append(keyperIndexRule, keyperIndexItem) + } + + logs, sub, err := _Dkgcontract.contract.WatchLogs(opts, "AccusationSubmitted", keyperSetIndexRule, retryCounterRule, keyperIndexRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(DkgcontractAccusationSubmitted) + if err := _Dkgcontract.contract.UnpackLog(event, "AccusationSubmitted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseAccusationSubmitted is a log parse operation binding the contract event 0xb5cc05e740a503c13e1b7ac3ad2d5abf41b91d2e5fca79455d34e515fb70849a. +// +// Solidity: event AccusationSubmitted(uint64 indexed keyperSetIndex, uint64 indexed retryCounter, uint64 indexed keyperIndex, uint64[] accusedIndices) +func (_Dkgcontract *DkgcontractFilterer) ParseAccusationSubmitted(log types.Log) (*DkgcontractAccusationSubmitted, error) { + event := new(DkgcontractAccusationSubmitted) + if err := _Dkgcontract.contract.UnpackLog(event, "AccusationSubmitted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// DkgcontractApologySubmittedIterator is returned from FilterApologySubmitted and is used to iterate over the raw logs and unpacked data for ApologySubmitted events raised by the Dkgcontract contract. +type DkgcontractApologySubmittedIterator struct { + Event *DkgcontractApologySubmitted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *DkgcontractApologySubmittedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(DkgcontractApologySubmitted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(DkgcontractApologySubmitted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *DkgcontractApologySubmittedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DkgcontractApologySubmittedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DkgcontractApologySubmitted represents a ApologySubmitted event raised by the Dkgcontract contract. +type DkgcontractApologySubmitted struct { + KeyperSetIndex uint64 + RetryCounter uint64 + KeyperIndex uint64 + AccuserIndices []uint64 + PolyEvalData [][]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterApologySubmitted is a free log retrieval operation binding the contract event 0x62729f0820cf3ab60fbd63a51cdeae0554d0ab24f843b86bd0d2591594d69136. +// +// Solidity: event ApologySubmitted(uint64 indexed keyperSetIndex, uint64 indexed retryCounter, uint64 indexed keyperIndex, uint64[] accuserIndices, bytes[] polyEvalData) +func (_Dkgcontract *DkgcontractFilterer) FilterApologySubmitted(opts *bind.FilterOpts, keyperSetIndex []uint64, retryCounter []uint64, keyperIndex []uint64) (*DkgcontractApologySubmittedIterator, error) { + + var keyperSetIndexRule []interface{} + for _, keyperSetIndexItem := range keyperSetIndex { + keyperSetIndexRule = append(keyperSetIndexRule, keyperSetIndexItem) + } + var retryCounterRule []interface{} + for _, retryCounterItem := range retryCounter { + retryCounterRule = append(retryCounterRule, retryCounterItem) + } + var keyperIndexRule []interface{} + for _, keyperIndexItem := range keyperIndex { + keyperIndexRule = append(keyperIndexRule, keyperIndexItem) + } + + logs, sub, err := _Dkgcontract.contract.FilterLogs(opts, "ApologySubmitted", keyperSetIndexRule, retryCounterRule, keyperIndexRule) + if err != nil { + return nil, err + } + return &DkgcontractApologySubmittedIterator{contract: _Dkgcontract.contract, event: "ApologySubmitted", logs: logs, sub: sub}, nil +} + +// WatchApologySubmitted is a free log subscription operation binding the contract event 0x62729f0820cf3ab60fbd63a51cdeae0554d0ab24f843b86bd0d2591594d69136. +// +// Solidity: event ApologySubmitted(uint64 indexed keyperSetIndex, uint64 indexed retryCounter, uint64 indexed keyperIndex, uint64[] accuserIndices, bytes[] polyEvalData) +func (_Dkgcontract *DkgcontractFilterer) WatchApologySubmitted(opts *bind.WatchOpts, sink chan<- *DkgcontractApologySubmitted, keyperSetIndex []uint64, retryCounter []uint64, keyperIndex []uint64) (event.Subscription, error) { + + var keyperSetIndexRule []interface{} + for _, keyperSetIndexItem := range keyperSetIndex { + keyperSetIndexRule = append(keyperSetIndexRule, keyperSetIndexItem) + } + var retryCounterRule []interface{} + for _, retryCounterItem := range retryCounter { + retryCounterRule = append(retryCounterRule, retryCounterItem) + } + var keyperIndexRule []interface{} + for _, keyperIndexItem := range keyperIndex { + keyperIndexRule = append(keyperIndexRule, keyperIndexItem) + } + + logs, sub, err := _Dkgcontract.contract.WatchLogs(opts, "ApologySubmitted", keyperSetIndexRule, retryCounterRule, keyperIndexRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(DkgcontractApologySubmitted) + if err := _Dkgcontract.contract.UnpackLog(event, "ApologySubmitted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseApologySubmitted is a log parse operation binding the contract event 0x62729f0820cf3ab60fbd63a51cdeae0554d0ab24f843b86bd0d2591594d69136. +// +// Solidity: event ApologySubmitted(uint64 indexed keyperSetIndex, uint64 indexed retryCounter, uint64 indexed keyperIndex, uint64[] accuserIndices, bytes[] polyEvalData) +func (_Dkgcontract *DkgcontractFilterer) ParseApologySubmitted(log types.Log) (*DkgcontractApologySubmitted, error) { + event := new(DkgcontractApologySubmitted) + if err := _Dkgcontract.contract.UnpackLog(event, "ApologySubmitted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// DkgcontractDKGSucceededIterator is returned from FilterDKGSucceeded and is used to iterate over the raw logs and unpacked data for DKGSucceeded events raised by the Dkgcontract contract. +type DkgcontractDKGSucceededIterator struct { + Event *DkgcontractDKGSucceeded // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *DkgcontractDKGSucceededIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(DkgcontractDKGSucceeded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(DkgcontractDKGSucceeded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *DkgcontractDKGSucceededIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DkgcontractDKGSucceededIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DkgcontractDKGSucceeded represents a DKGSucceeded event raised by the Dkgcontract contract. +type DkgcontractDKGSucceeded struct { + KeyperSetIndex uint64 + RetryCounter uint64 + EonPublicKey []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterDKGSucceeded is a free log retrieval operation binding the contract event 0xe6c9bd3daa50b9218615605cdf333410d405b7f3b8dbeee5a2373769679aa9f5. +// +// Solidity: event DKGSucceeded(uint64 indexed keyperSetIndex, uint64 indexed retryCounter, bytes eonPublicKey) +func (_Dkgcontract *DkgcontractFilterer) FilterDKGSucceeded(opts *bind.FilterOpts, keyperSetIndex []uint64, retryCounter []uint64) (*DkgcontractDKGSucceededIterator, error) { + + var keyperSetIndexRule []interface{} + for _, keyperSetIndexItem := range keyperSetIndex { + keyperSetIndexRule = append(keyperSetIndexRule, keyperSetIndexItem) + } + var retryCounterRule []interface{} + for _, retryCounterItem := range retryCounter { + retryCounterRule = append(retryCounterRule, retryCounterItem) + } + + logs, sub, err := _Dkgcontract.contract.FilterLogs(opts, "DKGSucceeded", keyperSetIndexRule, retryCounterRule) + if err != nil { + return nil, err + } + return &DkgcontractDKGSucceededIterator{contract: _Dkgcontract.contract, event: "DKGSucceeded", logs: logs, sub: sub}, nil +} + +// WatchDKGSucceeded is a free log subscription operation binding the contract event 0xe6c9bd3daa50b9218615605cdf333410d405b7f3b8dbeee5a2373769679aa9f5. +// +// Solidity: event DKGSucceeded(uint64 indexed keyperSetIndex, uint64 indexed retryCounter, bytes eonPublicKey) +func (_Dkgcontract *DkgcontractFilterer) WatchDKGSucceeded(opts *bind.WatchOpts, sink chan<- *DkgcontractDKGSucceeded, keyperSetIndex []uint64, retryCounter []uint64) (event.Subscription, error) { + + var keyperSetIndexRule []interface{} + for _, keyperSetIndexItem := range keyperSetIndex { + keyperSetIndexRule = append(keyperSetIndexRule, keyperSetIndexItem) + } + var retryCounterRule []interface{} + for _, retryCounterItem := range retryCounter { + retryCounterRule = append(retryCounterRule, retryCounterItem) + } + + logs, sub, err := _Dkgcontract.contract.WatchLogs(opts, "DKGSucceeded", keyperSetIndexRule, retryCounterRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(DkgcontractDKGSucceeded) + if err := _Dkgcontract.contract.UnpackLog(event, "DKGSucceeded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseDKGSucceeded is a log parse operation binding the contract event 0xe6c9bd3daa50b9218615605cdf333410d405b7f3b8dbeee5a2373769679aa9f5. +// +// Solidity: event DKGSucceeded(uint64 indexed keyperSetIndex, uint64 indexed retryCounter, bytes eonPublicKey) +func (_Dkgcontract *DkgcontractFilterer) ParseDKGSucceeded(log types.Log) (*DkgcontractDKGSucceeded, error) { + event := new(DkgcontractDKGSucceeded) + if err := _Dkgcontract.contract.UnpackLog(event, "DKGSucceeded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// DkgcontractDealingSubmittedIterator is returned from FilterDealingSubmitted and is used to iterate over the raw logs and unpacked data for DealingSubmitted events raised by the Dkgcontract contract. +type DkgcontractDealingSubmittedIterator struct { + Event *DkgcontractDealingSubmitted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *DkgcontractDealingSubmittedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(DkgcontractDealingSubmitted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(DkgcontractDealingSubmitted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *DkgcontractDealingSubmittedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DkgcontractDealingSubmittedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DkgcontractDealingSubmitted represents a DealingSubmitted event raised by the Dkgcontract contract. +type DkgcontractDealingSubmitted struct { + KeyperSetIndex uint64 + RetryCounter uint64 + KeyperIndex uint64 + Commitment []byte + PolyEvals [][]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterDealingSubmitted is a free log retrieval operation binding the contract event 0xa5074728b92791250d48ccdc55266aca7b1cca22f89e1ef2ab91ccd7ae0f337d. +// +// Solidity: event DealingSubmitted(uint64 indexed keyperSetIndex, uint64 indexed retryCounter, uint64 indexed keyperIndex, bytes commitment, bytes[] polyEvals) +func (_Dkgcontract *DkgcontractFilterer) FilterDealingSubmitted(opts *bind.FilterOpts, keyperSetIndex []uint64, retryCounter []uint64, keyperIndex []uint64) (*DkgcontractDealingSubmittedIterator, error) { + + var keyperSetIndexRule []interface{} + for _, keyperSetIndexItem := range keyperSetIndex { + keyperSetIndexRule = append(keyperSetIndexRule, keyperSetIndexItem) + } + var retryCounterRule []interface{} + for _, retryCounterItem := range retryCounter { + retryCounterRule = append(retryCounterRule, retryCounterItem) + } + var keyperIndexRule []interface{} + for _, keyperIndexItem := range keyperIndex { + keyperIndexRule = append(keyperIndexRule, keyperIndexItem) + } + + logs, sub, err := _Dkgcontract.contract.FilterLogs(opts, "DealingSubmitted", keyperSetIndexRule, retryCounterRule, keyperIndexRule) + if err != nil { + return nil, err + } + return &DkgcontractDealingSubmittedIterator{contract: _Dkgcontract.contract, event: "DealingSubmitted", logs: logs, sub: sub}, nil +} + +// WatchDealingSubmitted is a free log subscription operation binding the contract event 0xa5074728b92791250d48ccdc55266aca7b1cca22f89e1ef2ab91ccd7ae0f337d. +// +// Solidity: event DealingSubmitted(uint64 indexed keyperSetIndex, uint64 indexed retryCounter, uint64 indexed keyperIndex, bytes commitment, bytes[] polyEvals) +func (_Dkgcontract *DkgcontractFilterer) WatchDealingSubmitted(opts *bind.WatchOpts, sink chan<- *DkgcontractDealingSubmitted, keyperSetIndex []uint64, retryCounter []uint64, keyperIndex []uint64) (event.Subscription, error) { + + var keyperSetIndexRule []interface{} + for _, keyperSetIndexItem := range keyperSetIndex { + keyperSetIndexRule = append(keyperSetIndexRule, keyperSetIndexItem) + } + var retryCounterRule []interface{} + for _, retryCounterItem := range retryCounter { + retryCounterRule = append(retryCounterRule, retryCounterItem) + } + var keyperIndexRule []interface{} + for _, keyperIndexItem := range keyperIndex { + keyperIndexRule = append(keyperIndexRule, keyperIndexItem) + } + + logs, sub, err := _Dkgcontract.contract.WatchLogs(opts, "DealingSubmitted", keyperSetIndexRule, retryCounterRule, keyperIndexRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(DkgcontractDealingSubmitted) + if err := _Dkgcontract.contract.UnpackLog(event, "DealingSubmitted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseDealingSubmitted is a log parse operation binding the contract event 0xa5074728b92791250d48ccdc55266aca7b1cca22f89e1ef2ab91ccd7ae0f337d. +// +// Solidity: event DealingSubmitted(uint64 indexed keyperSetIndex, uint64 indexed retryCounter, uint64 indexed keyperIndex, bytes commitment, bytes[] polyEvals) +func (_Dkgcontract *DkgcontractFilterer) ParseDealingSubmitted(log types.Log) (*DkgcontractDealingSubmitted, error) { + event := new(DkgcontractDealingSubmitted) + if err := _Dkgcontract.contract.UnpackLog(event, "DealingSubmitted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// DkgcontractSuccessVoteSubmittedIterator is returned from FilterSuccessVoteSubmitted and is used to iterate over the raw logs and unpacked data for SuccessVoteSubmitted events raised by the Dkgcontract contract. +type DkgcontractSuccessVoteSubmittedIterator struct { + Event *DkgcontractSuccessVoteSubmitted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *DkgcontractSuccessVoteSubmittedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(DkgcontractSuccessVoteSubmitted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(DkgcontractSuccessVoteSubmitted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *DkgcontractSuccessVoteSubmittedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DkgcontractSuccessVoteSubmittedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DkgcontractSuccessVoteSubmitted represents a SuccessVoteSubmitted event raised by the Dkgcontract contract. +type DkgcontractSuccessVoteSubmitted struct { + KeyperSetIndex uint64 + RetryCounter uint64 + KeyperIndex uint64 + EonPublicKey []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterSuccessVoteSubmitted is a free log retrieval operation binding the contract event 0xacfc0aa3f6ba36ac0ffda53e00d2cdace2fd4a9e41e2fe3214032794332c37c3. +// +// Solidity: event SuccessVoteSubmitted(uint64 indexed keyperSetIndex, uint64 indexed retryCounter, uint64 indexed keyperIndex, bytes eonPublicKey) +func (_Dkgcontract *DkgcontractFilterer) FilterSuccessVoteSubmitted(opts *bind.FilterOpts, keyperSetIndex []uint64, retryCounter []uint64, keyperIndex []uint64) (*DkgcontractSuccessVoteSubmittedIterator, error) { + + var keyperSetIndexRule []interface{} + for _, keyperSetIndexItem := range keyperSetIndex { + keyperSetIndexRule = append(keyperSetIndexRule, keyperSetIndexItem) + } + var retryCounterRule []interface{} + for _, retryCounterItem := range retryCounter { + retryCounterRule = append(retryCounterRule, retryCounterItem) + } + var keyperIndexRule []interface{} + for _, keyperIndexItem := range keyperIndex { + keyperIndexRule = append(keyperIndexRule, keyperIndexItem) + } + + logs, sub, err := _Dkgcontract.contract.FilterLogs(opts, "SuccessVoteSubmitted", keyperSetIndexRule, retryCounterRule, keyperIndexRule) + if err != nil { + return nil, err + } + return &DkgcontractSuccessVoteSubmittedIterator{contract: _Dkgcontract.contract, event: "SuccessVoteSubmitted", logs: logs, sub: sub}, nil +} + +// WatchSuccessVoteSubmitted is a free log subscription operation binding the contract event 0xacfc0aa3f6ba36ac0ffda53e00d2cdace2fd4a9e41e2fe3214032794332c37c3. +// +// Solidity: event SuccessVoteSubmitted(uint64 indexed keyperSetIndex, uint64 indexed retryCounter, uint64 indexed keyperIndex, bytes eonPublicKey) +func (_Dkgcontract *DkgcontractFilterer) WatchSuccessVoteSubmitted(opts *bind.WatchOpts, sink chan<- *DkgcontractSuccessVoteSubmitted, keyperSetIndex []uint64, retryCounter []uint64, keyperIndex []uint64) (event.Subscription, error) { + + var keyperSetIndexRule []interface{} + for _, keyperSetIndexItem := range keyperSetIndex { + keyperSetIndexRule = append(keyperSetIndexRule, keyperSetIndexItem) + } + var retryCounterRule []interface{} + for _, retryCounterItem := range retryCounter { + retryCounterRule = append(retryCounterRule, retryCounterItem) + } + var keyperIndexRule []interface{} + for _, keyperIndexItem := range keyperIndex { + keyperIndexRule = append(keyperIndexRule, keyperIndexItem) + } + + logs, sub, err := _Dkgcontract.contract.WatchLogs(opts, "SuccessVoteSubmitted", keyperSetIndexRule, retryCounterRule, keyperIndexRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(DkgcontractSuccessVoteSubmitted) + if err := _Dkgcontract.contract.UnpackLog(event, "SuccessVoteSubmitted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseSuccessVoteSubmitted is a log parse operation binding the contract event 0xacfc0aa3f6ba36ac0ffda53e00d2cdace2fd4a9e41e2fe3214032794332c37c3. +// +// Solidity: event SuccessVoteSubmitted(uint64 indexed keyperSetIndex, uint64 indexed retryCounter, uint64 indexed keyperIndex, bytes eonPublicKey) +func (_Dkgcontract *DkgcontractFilterer) ParseSuccessVoteSubmitted(log types.Log) (*DkgcontractSuccessVoteSubmitted, error) { + event := new(DkgcontractSuccessVoteSubmitted) + if err := _Dkgcontract.contract.UnpackLog(event, "SuccessVoteSubmitted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/bindings/ecieskeyregistry/ecieskeyregistry.go b/bindings/ecieskeyregistry/ecieskeyregistry.go new file mode 100644 index 0000000..4eed603 --- /dev/null +++ b/bindings/ecieskeyregistry/ecieskeyregistry.go @@ -0,0 +1,493 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package ecieskeyregistry + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// EcieskeyregistryMetaData contains all meta data concerning the Ecieskeyregistry contract. +var EcieskeyregistryMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"keyperSetManagerAddress\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getKey\",\"inputs\":[{\"name\":\"keyper\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getKeyperAt\",\"inputs\":[{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getKeyperCount\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"keyperSetManager\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractKeyperSetManager\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"registerKey\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"eciesPublicKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"KeyRegistered\",\"inputs\":[{\"name\":\"keyper\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"eciesPublicKey\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"EmptyECIESPublicKey\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"KeyperSetNotFinalized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotAMember\",\"inputs\":[]}]", + Bin: "0x60a060405234801561000f575f5ffd5b50604051610f04380380610f04833981810160405281019061003191906100c9565b8073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1681525050506100f4565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6100988261006f565b9050919050565b6100a88161008e565b81146100b2575f5ffd5b50565b5f815190506100c38161009f565b92915050565b5f602082840312156100de576100dd61006b565b5b5f6100eb848285016100b5565b91505092915050565b608051610df16101135f395f81816101fb01526102200152610df15ff3fe608060405234801561000f575f5ffd5b5060043610610055575f3560e01c806393790f44146100595780639ce385a214610089578063d4b2cedd146100b9578063df713e19146100d7578063ecad263c146100f3575b5f5ffd5b610073600480360381019061006e91906106b0565b610111565b604051610080919061074b565b60405180910390f35b6100a3600480360381019061009e919061079e565b6101de565b6040516100b091906107d8565b60405180910390f35b6100c16101f9565b6040516100ce919061084c565b60405180910390f35b6100f160048036038101906100ec9190610903565b61021d565b005b6100fb61052b565b6040516101089190610983565b60405180910390f35b606060025f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20805461015b906109c9565b80601f0160208091040260200160405190810160405280929190818152602001828054610187906109c9565b80156101d25780601f106101a9576101008083540402835291602001916101d2565b820191905f5260205f20905b8154815290600101906020018083116101b557829003601f168201915b50505050509050919050565b5f6101f2825f61053a90919063ffffffff16565b9050919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f90f3bed866040518263ffffffff1660e01b81526004016102779190610a08565b602060405180830381865afa158015610292573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102b69190610a35565b90508073ffffffffffffffffffffffffffffffffffffffff16638d4e40836040518163ffffffff1660e01b8152600401602060405180830381865afa158015610301573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103259190610a95565b61035b576040517feac631aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16632e8e6cad866040518263ffffffff1660e01b81526004016103ab9190610a08565b602060405180830381865afa1580156103c6573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103ea9190610a35565b73ffffffffffffffffffffffffffffffffffffffff1614610437576040517f2818e88800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8383905003610473576040517f0f154c2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610486335f61055190919063ffffffff16565b50828260025f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2091826104d3929190610c8e565b503373ffffffffffffffffffffffffffffffffffffffff167f9b368ac41b4759b00feab16152db5d57270846c8d258ce8ab77ea58800b288f2848460405161051c929190610d95565b60405180910390a25050505050565b5f6105355f61057e565b905090565b5f610547835f0183610591565b5f1c905092915050565b5f610576835f018373ffffffffffffffffffffffffffffffffffffffff165f1b6105b8565b905092915050565b5f61058a825f0161061f565b9050919050565b5f825f0182815481106105a7576105a6610db7565b5b905f5260205f200154905092915050565b5f6105c3838361062e565b61061557825f0182908060018154018082558091505060019003905f5260205f20015f9091909190915055825f0180549050836001015f8481526020019081526020015f208190555060019050610619565b5f90505b92915050565b5f815f01805490509050919050565b5f5f836001015f8481526020019081526020015f20541415905092915050565b5f5ffd5b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61067f82610656565b9050919050565b61068f81610675565b8114610699575f5ffd5b50565b5f813590506106aa81610686565b92915050565b5f602082840312156106c5576106c461064e565b5b5f6106d28482850161069c565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61071d826106db565b61072781856106e5565b93506107378185602086016106f5565b61074081610703565b840191505092915050565b5f6020820190508181035f8301526107638184610713565b905092915050565b5f819050919050565b61077d8161076b565b8114610787575f5ffd5b50565b5f8135905061079881610774565b92915050565b5f602082840312156107b3576107b261064e565b5b5f6107c08482850161078a565b91505092915050565b6107d281610675565b82525050565b5f6020820190506107eb5f8301846107c9565b92915050565b5f819050919050565b5f61081461080f61080a84610656565b6107f1565b610656565b9050919050565b5f610825826107fa565b9050919050565b5f6108368261081b565b9050919050565b6108468161082c565b82525050565b5f60208201905061085f5f83018461083d565b92915050565b5f67ffffffffffffffff82169050919050565b61088181610865565b811461088b575f5ffd5b50565b5f8135905061089c81610878565b92915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f8401126108c3576108c26108a2565b5b8235905067ffffffffffffffff8111156108e0576108df6108a6565b5b6020830191508360018202830111156108fc576108fb6108aa565b5b9250929050565b5f5f5f5f6060858703121561091b5761091a61064e565b5b5f6109288782880161088e565b94505060206109398782880161088e565b935050604085013567ffffffffffffffff81111561095a57610959610652565b5b610966878288016108ae565b925092505092959194509250565b61097d8161076b565b82525050565b5f6020820190506109965f830184610974565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806109e057607f821691505b6020821081036109f3576109f261099c565b5b50919050565b610a0281610865565b82525050565b5f602082019050610a1b5f8301846109f9565b92915050565b5f81519050610a2f81610686565b92915050565b5f60208284031215610a4a57610a4961064e565b5b5f610a5784828501610a21565b91505092915050565b5f8115159050919050565b610a7481610a60565b8114610a7e575f5ffd5b50565b5f81519050610a8f81610a6b565b92915050565b5f60208284031215610aaa57610aa961064e565b5b5f610ab784828501610a81565b91505092915050565b5f82905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302610b537fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610b18565b610b5d8683610b18565b95508019841693508086168417925050509392505050565b5f610b8f610b8a610b858461076b565b6107f1565b61076b565b9050919050565b5f819050919050565b610ba883610b75565b610bbc610bb482610b96565b848454610b24565b825550505050565b5f5f905090565b610bd3610bc4565b610bde818484610b9f565b505050565b5b81811015610c0157610bf65f82610bcb565b600181019050610be4565b5050565b601f821115610c4657610c1781610af7565b610c2084610b09565b81016020851015610c2f578190505b610c43610c3b85610b09565b830182610be3565b50505b505050565b5f82821c905092915050565b5f610c665f1984600802610c4b565b1980831691505092915050565b5f610c7e8383610c57565b9150826002028217905092915050565b610c988383610ac0565b67ffffffffffffffff811115610cb157610cb0610aca565b5b610cbb82546109c9565b610cc6828285610c05565b5f601f831160018114610cf3575f8415610ce1578287013590505b610ceb8582610c73565b865550610d52565b601f198416610d0186610af7565b5f5b82811015610d2857848901358255600182019150602085019450602081019050610d03565b86831015610d455784890135610d41601f891682610c57565b8355505b6001600288020188555050505b50505050505050565b828183375f83830152505050565b5f610d7483856106e5565b9350610d81838584610d5b565b610d8a83610703565b840190509392505050565b5f6020820190508181035f830152610dae818486610d69565b90509392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffdfea164736f6c634300081c000a", +} + +// EcieskeyregistryABI is the input ABI used to generate the binding from. +// Deprecated: Use EcieskeyregistryMetaData.ABI instead. +var EcieskeyregistryABI = EcieskeyregistryMetaData.ABI + +// EcieskeyregistryBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use EcieskeyregistryMetaData.Bin instead. +var EcieskeyregistryBin = EcieskeyregistryMetaData.Bin + +// DeployEcieskeyregistry deploys a new Ethereum contract, binding an instance of Ecieskeyregistry to it. +func DeployEcieskeyregistry(auth *bind.TransactOpts, backend bind.ContractBackend, keyperSetManagerAddress common.Address) (common.Address, *types.Transaction, *Ecieskeyregistry, error) { + parsed, err := EcieskeyregistryMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(EcieskeyregistryBin), backend, keyperSetManagerAddress) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Ecieskeyregistry{EcieskeyregistryCaller: EcieskeyregistryCaller{contract: contract}, EcieskeyregistryTransactor: EcieskeyregistryTransactor{contract: contract}, EcieskeyregistryFilterer: EcieskeyregistryFilterer{contract: contract}}, nil +} + +// Ecieskeyregistry is an auto generated Go binding around an Ethereum contract. +type Ecieskeyregistry struct { + EcieskeyregistryCaller // Read-only binding to the contract + EcieskeyregistryTransactor // Write-only binding to the contract + EcieskeyregistryFilterer // Log filterer for contract events +} + +// EcieskeyregistryCaller is an auto generated read-only Go binding around an Ethereum contract. +type EcieskeyregistryCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// EcieskeyregistryTransactor is an auto generated write-only Go binding around an Ethereum contract. +type EcieskeyregistryTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// EcieskeyregistryFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type EcieskeyregistryFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// EcieskeyregistrySession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type EcieskeyregistrySession struct { + Contract *Ecieskeyregistry // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// EcieskeyregistryCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type EcieskeyregistryCallerSession struct { + Contract *EcieskeyregistryCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// EcieskeyregistryTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type EcieskeyregistryTransactorSession struct { + Contract *EcieskeyregistryTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// EcieskeyregistryRaw is an auto generated low-level Go binding around an Ethereum contract. +type EcieskeyregistryRaw struct { + Contract *Ecieskeyregistry // Generic contract binding to access the raw methods on +} + +// EcieskeyregistryCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type EcieskeyregistryCallerRaw struct { + Contract *EcieskeyregistryCaller // Generic read-only contract binding to access the raw methods on +} + +// EcieskeyregistryTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type EcieskeyregistryTransactorRaw struct { + Contract *EcieskeyregistryTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewEcieskeyregistry creates a new instance of Ecieskeyregistry, bound to a specific deployed contract. +func NewEcieskeyregistry(address common.Address, backend bind.ContractBackend) (*Ecieskeyregistry, error) { + contract, err := bindEcieskeyregistry(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Ecieskeyregistry{EcieskeyregistryCaller: EcieskeyregistryCaller{contract: contract}, EcieskeyregistryTransactor: EcieskeyregistryTransactor{contract: contract}, EcieskeyregistryFilterer: EcieskeyregistryFilterer{contract: contract}}, nil +} + +// NewEcieskeyregistryCaller creates a new read-only instance of Ecieskeyregistry, bound to a specific deployed contract. +func NewEcieskeyregistryCaller(address common.Address, caller bind.ContractCaller) (*EcieskeyregistryCaller, error) { + contract, err := bindEcieskeyregistry(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &EcieskeyregistryCaller{contract: contract}, nil +} + +// NewEcieskeyregistryTransactor creates a new write-only instance of Ecieskeyregistry, bound to a specific deployed contract. +func NewEcieskeyregistryTransactor(address common.Address, transactor bind.ContractTransactor) (*EcieskeyregistryTransactor, error) { + contract, err := bindEcieskeyregistry(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &EcieskeyregistryTransactor{contract: contract}, nil +} + +// NewEcieskeyregistryFilterer creates a new log filterer instance of Ecieskeyregistry, bound to a specific deployed contract. +func NewEcieskeyregistryFilterer(address common.Address, filterer bind.ContractFilterer) (*EcieskeyregistryFilterer, error) { + contract, err := bindEcieskeyregistry(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &EcieskeyregistryFilterer{contract: contract}, nil +} + +// bindEcieskeyregistry binds a generic wrapper to an already deployed contract. +func bindEcieskeyregistry(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := EcieskeyregistryMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Ecieskeyregistry *EcieskeyregistryRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Ecieskeyregistry.Contract.EcieskeyregistryCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Ecieskeyregistry *EcieskeyregistryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Ecieskeyregistry.Contract.EcieskeyregistryTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Ecieskeyregistry *EcieskeyregistryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Ecieskeyregistry.Contract.EcieskeyregistryTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Ecieskeyregistry *EcieskeyregistryCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Ecieskeyregistry.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Ecieskeyregistry *EcieskeyregistryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Ecieskeyregistry.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Ecieskeyregistry *EcieskeyregistryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Ecieskeyregistry.Contract.contract.Transact(opts, method, params...) +} + +// GetKey is a free data retrieval call binding the contract method 0x93790f44. +// +// Solidity: function getKey(address keyper) view returns(bytes) +func (_Ecieskeyregistry *EcieskeyregistryCaller) GetKey(opts *bind.CallOpts, keyper common.Address) ([]byte, error) { + var out []interface{} + err := _Ecieskeyregistry.contract.Call(opts, &out, "getKey", keyper) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +// GetKey is a free data retrieval call binding the contract method 0x93790f44. +// +// Solidity: function getKey(address keyper) view returns(bytes) +func (_Ecieskeyregistry *EcieskeyregistrySession) GetKey(keyper common.Address) ([]byte, error) { + return _Ecieskeyregistry.Contract.GetKey(&_Ecieskeyregistry.CallOpts, keyper) +} + +// GetKey is a free data retrieval call binding the contract method 0x93790f44. +// +// Solidity: function getKey(address keyper) view returns(bytes) +func (_Ecieskeyregistry *EcieskeyregistryCallerSession) GetKey(keyper common.Address) ([]byte, error) { + return _Ecieskeyregistry.Contract.GetKey(&_Ecieskeyregistry.CallOpts, keyper) +} + +// GetKeyperAt is a free data retrieval call binding the contract method 0x9ce385a2. +// +// Solidity: function getKeyperAt(uint256 index) view returns(address) +func (_Ecieskeyregistry *EcieskeyregistryCaller) GetKeyperAt(opts *bind.CallOpts, index *big.Int) (common.Address, error) { + var out []interface{} + err := _Ecieskeyregistry.contract.Call(opts, &out, "getKeyperAt", index) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// GetKeyperAt is a free data retrieval call binding the contract method 0x9ce385a2. +// +// Solidity: function getKeyperAt(uint256 index) view returns(address) +func (_Ecieskeyregistry *EcieskeyregistrySession) GetKeyperAt(index *big.Int) (common.Address, error) { + return _Ecieskeyregistry.Contract.GetKeyperAt(&_Ecieskeyregistry.CallOpts, index) +} + +// GetKeyperAt is a free data retrieval call binding the contract method 0x9ce385a2. +// +// Solidity: function getKeyperAt(uint256 index) view returns(address) +func (_Ecieskeyregistry *EcieskeyregistryCallerSession) GetKeyperAt(index *big.Int) (common.Address, error) { + return _Ecieskeyregistry.Contract.GetKeyperAt(&_Ecieskeyregistry.CallOpts, index) +} + +// GetKeyperCount is a free data retrieval call binding the contract method 0xecad263c. +// +// Solidity: function getKeyperCount() view returns(uint256) +func (_Ecieskeyregistry *EcieskeyregistryCaller) GetKeyperCount(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Ecieskeyregistry.contract.Call(opts, &out, "getKeyperCount") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetKeyperCount is a free data retrieval call binding the contract method 0xecad263c. +// +// Solidity: function getKeyperCount() view returns(uint256) +func (_Ecieskeyregistry *EcieskeyregistrySession) GetKeyperCount() (*big.Int, error) { + return _Ecieskeyregistry.Contract.GetKeyperCount(&_Ecieskeyregistry.CallOpts) +} + +// GetKeyperCount is a free data retrieval call binding the contract method 0xecad263c. +// +// Solidity: function getKeyperCount() view returns(uint256) +func (_Ecieskeyregistry *EcieskeyregistryCallerSession) GetKeyperCount() (*big.Int, error) { + return _Ecieskeyregistry.Contract.GetKeyperCount(&_Ecieskeyregistry.CallOpts) +} + +// KeyperSetManager is a free data retrieval call binding the contract method 0xd4b2cedd. +// +// Solidity: function keyperSetManager() view returns(address) +func (_Ecieskeyregistry *EcieskeyregistryCaller) KeyperSetManager(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Ecieskeyregistry.contract.Call(opts, &out, "keyperSetManager") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// KeyperSetManager is a free data retrieval call binding the contract method 0xd4b2cedd. +// +// Solidity: function keyperSetManager() view returns(address) +func (_Ecieskeyregistry *EcieskeyregistrySession) KeyperSetManager() (common.Address, error) { + return _Ecieskeyregistry.Contract.KeyperSetManager(&_Ecieskeyregistry.CallOpts) +} + +// KeyperSetManager is a free data retrieval call binding the contract method 0xd4b2cedd. +// +// Solidity: function keyperSetManager() view returns(address) +func (_Ecieskeyregistry *EcieskeyregistryCallerSession) KeyperSetManager() (common.Address, error) { + return _Ecieskeyregistry.Contract.KeyperSetManager(&_Ecieskeyregistry.CallOpts) +} + +// RegisterKey is a paid mutator transaction binding the contract method 0xdf713e19. +// +// Solidity: function registerKey(uint64 keyperSetIndex, uint64 keyperIndex, bytes eciesPublicKey) returns() +func (_Ecieskeyregistry *EcieskeyregistryTransactor) RegisterKey(opts *bind.TransactOpts, keyperSetIndex uint64, keyperIndex uint64, eciesPublicKey []byte) (*types.Transaction, error) { + return _Ecieskeyregistry.contract.Transact(opts, "registerKey", keyperSetIndex, keyperIndex, eciesPublicKey) +} + +// RegisterKey is a paid mutator transaction binding the contract method 0xdf713e19. +// +// Solidity: function registerKey(uint64 keyperSetIndex, uint64 keyperIndex, bytes eciesPublicKey) returns() +func (_Ecieskeyregistry *EcieskeyregistrySession) RegisterKey(keyperSetIndex uint64, keyperIndex uint64, eciesPublicKey []byte) (*types.Transaction, error) { + return _Ecieskeyregistry.Contract.RegisterKey(&_Ecieskeyregistry.TransactOpts, keyperSetIndex, keyperIndex, eciesPublicKey) +} + +// RegisterKey is a paid mutator transaction binding the contract method 0xdf713e19. +// +// Solidity: function registerKey(uint64 keyperSetIndex, uint64 keyperIndex, bytes eciesPublicKey) returns() +func (_Ecieskeyregistry *EcieskeyregistryTransactorSession) RegisterKey(keyperSetIndex uint64, keyperIndex uint64, eciesPublicKey []byte) (*types.Transaction, error) { + return _Ecieskeyregistry.Contract.RegisterKey(&_Ecieskeyregistry.TransactOpts, keyperSetIndex, keyperIndex, eciesPublicKey) +} + +// EcieskeyregistryKeyRegisteredIterator is returned from FilterKeyRegistered and is used to iterate over the raw logs and unpacked data for KeyRegistered events raised by the Ecieskeyregistry contract. +type EcieskeyregistryKeyRegisteredIterator struct { + Event *EcieskeyregistryKeyRegistered // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *EcieskeyregistryKeyRegisteredIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(EcieskeyregistryKeyRegistered) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(EcieskeyregistryKeyRegistered) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *EcieskeyregistryKeyRegisteredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *EcieskeyregistryKeyRegisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// EcieskeyregistryKeyRegistered represents a KeyRegistered event raised by the Ecieskeyregistry contract. +type EcieskeyregistryKeyRegistered struct { + Keyper common.Address + EciesPublicKey []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterKeyRegistered is a free log retrieval operation binding the contract event 0x9b368ac41b4759b00feab16152db5d57270846c8d258ce8ab77ea58800b288f2. +// +// Solidity: event KeyRegistered(address indexed keyper, bytes eciesPublicKey) +func (_Ecieskeyregistry *EcieskeyregistryFilterer) FilterKeyRegistered(opts *bind.FilterOpts, keyper []common.Address) (*EcieskeyregistryKeyRegisteredIterator, error) { + + var keyperRule []interface{} + for _, keyperItem := range keyper { + keyperRule = append(keyperRule, keyperItem) + } + + logs, sub, err := _Ecieskeyregistry.contract.FilterLogs(opts, "KeyRegistered", keyperRule) + if err != nil { + return nil, err + } + return &EcieskeyregistryKeyRegisteredIterator{contract: _Ecieskeyregistry.contract, event: "KeyRegistered", logs: logs, sub: sub}, nil +} + +// WatchKeyRegistered is a free log subscription operation binding the contract event 0x9b368ac41b4759b00feab16152db5d57270846c8d258ce8ab77ea58800b288f2. +// +// Solidity: event KeyRegistered(address indexed keyper, bytes eciesPublicKey) +func (_Ecieskeyregistry *EcieskeyregistryFilterer) WatchKeyRegistered(opts *bind.WatchOpts, sink chan<- *EcieskeyregistryKeyRegistered, keyper []common.Address) (event.Subscription, error) { + + var keyperRule []interface{} + for _, keyperItem := range keyper { + keyperRule = append(keyperRule, keyperItem) + } + + logs, sub, err := _Ecieskeyregistry.contract.WatchLogs(opts, "KeyRegistered", keyperRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(EcieskeyregistryKeyRegistered) + if err := _Ecieskeyregistry.contract.UnpackLog(event, "KeyRegistered", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseKeyRegistered is a log parse operation binding the contract event 0x9b368ac41b4759b00feab16152db5d57270846c8d258ce8ab77ea58800b288f2. +// +// Solidity: event KeyRegistered(address indexed keyper, bytes eciesPublicKey) +func (_Ecieskeyregistry *EcieskeyregistryFilterer) ParseKeyRegistered(log types.Log) (*EcieskeyregistryKeyRegistered, error) { + event := new(EcieskeyregistryKeyRegistered) + if err := _Ecieskeyregistry.contract.UnpackLog(event, "KeyRegistered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/bindings/keypersetmanager/keypersetmanager.go b/bindings/keypersetmanager/keypersetmanager.go index 5d9615e..dd60af6 100644 --- a/bindings/keypersetmanager/keypersetmanager.go +++ b/bindings/keypersetmanager/keypersetmanager.go @@ -31,8 +31,8 @@ var ( // KeypersetmanagerMetaData contains all meta data concerning the Keypersetmanager contract. var KeypersetmanagerMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"initializer\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"DEFAULT_ADMIN_ROLE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"PAUSER_ROLE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addKeyperSet\",\"inputs\":[{\"name\":\"activationBlock\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperSetContract\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getKeyperSetActivationBlock\",\"inputs\":[{\"name\":\"index\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getKeyperSetAddress\",\"inputs\":[{\"name\":\"index\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getKeyperSetIndexByBlock\",\"inputs\":[{\"name\":\"blockNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getNumKeyperSets\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRoleAdmin\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"grantRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"hasRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"admin\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"pauser\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializer\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"pause\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"paused\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"callerConfirmation\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"revokeRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"unpause\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"KeyperSetAdded\",\"inputs\":[{\"name\":\"activationBlock\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"keyperSetContract\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"members\",\"type\":\"address[]\",\"indexed\":false,\"internalType\":\"address[]\"},{\"name\":\"threshold\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"eon\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"KeyperSetAdded\",\"inputs\":[{\"name\":\"activationSlot\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"keyperSetContract\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Paused\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleAdminChanged\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"previousAdminRole\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"newAdminRole\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleGranted\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleRevoked\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Unpaused\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AccessControlBadConfirmation\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AccessControlUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"neededRole\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"AlreadyHaveKeyperSet\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AlreadyInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"EnforcedPause\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ExpectedPause\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"KeyperSetNotFinalized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NoActiveKeyperSet\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnauthorizedInitializer\",\"inputs\":[]}]", - Bin: "0x608060405234801561000f575f5ffd5b506040516118e73803806118e7833981810160405281019061003191906100d7565b80806001806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050610102565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6100a68261007d565b9050919050565b6100b68161009c565b81146100c0575f5ffd5b50565b5f815190506100d1816100ad565b92915050565b5f602082840312156100ec576100eb610079565b5b5f6100f9848285016100c3565b91505092915050565b6117d88061010f5f395ff3fe608060405234801561000f575f5ffd5b5060043610610114575f3560e01c80638456cb59116100a0578063d3877c431161006f578063d3877c43146102ca578063d547741f146102e6578063e63ab1e914610302578063f2e6100a14610320578063f90f3bed1461033e57610114565b80638456cb591461025457806391d148541461025e5780639ce110d71461028e578063a217fddf146102ac57610114565b806336568abe116100e757806336568abe146101c45780633f4ba83a146101e0578063485cc955146101ea5780635c975abb14610206578063636df9791461022457610114565b806301ffc9a714610118578063035cef1514610148578063248a9ca3146101785780632f2ff15d146101a8575b5f5ffd5b610132600480360381019061012d91906110b6565b61036e565b60405161013f91906110fb565b60405180910390f35b610162600480360381019061015d9190611151565b6103e7565b60405161016f919061118b565b60405180910390f35b610192600480360381019061018d91906111d7565b6104b2565b60405161019f9190611211565b60405180910390f35b6101c260048036038101906101bd9190611284565b6104ce565b005b6101de60048036038101906101d99190611284565b6104f0565b005b6101e861056b565b005b61020460048036038101906101ff91906112c2565b610582565b005b61020e610708565b60405161021b91906110fb565b60405180910390f35b61023e60048036038101906102399190611151565b61071d565b60405161024b919061118b565b60405180910390f35b61025c610761565b005b61027860048036038101906102739190611284565b610796565b60405161028591906110fb565b60405180910390f35b6102966107f9565b6040516102a3919061130f565b60405180910390f35b6102b461081d565b6040516102c19190611211565b60405180910390f35b6102e460048036038101906102df9190611328565b610823565b005b61030060048036038101906102fb9190611284565b610b89565b005b61030a610bab565b6040516103179190611211565b60405180910390f35b610328610bcf565b604051610335919061118b565b60405180910390f35b61035860048036038101906103539190611151565b610bdb565b604051610365919061130f565b60405180910390f35b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806103e057506103df82610c2c565b5b9050919050565b5f5f60028054905090505b5f81111561047a578267ffffffffffffffff166002600183610414919061139c565b81548110610425576104246113cf565b5b905f5260205f20015f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff16116104675760018161045f919061139c565b9150506104ad565b8080610472906113fc565b9150506103f2565b506040517fcf93fa3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b5f5f5f8381526020019081526020015f20600101549050919050565b6104d7826104b2565b6104e081610c95565b6104ea8383610ca9565b50505050565b6104f8610d92565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461055c576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6105668282610d99565b505050565b5f5f1b61057781610c95565b61057f610e82565b50565b5f73ffffffffffffffffffffffffffffffffffffffff1660018054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603610607576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461068c576040517f0d622feb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106985f5f1b83610ca9565b506106c37f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a82610ca9565b505f6001806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b5f60015f9054906101000a900460ff16905090565b5f60028267ffffffffffffffff168154811061073c5761073b6113cf565b5b905f5260205f20015f015f9054906101000a900467ffffffffffffffff169050919050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a61078b81610c95565b610793610ee3565b50565b5f5f5f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b60018054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f5f1b81565b5f5f1b61082f81610c95565b5f6002805490501180156108ad57506108a060026001600280549050610855919061139c565b81548110610866576108656113cf565b5b905f5260205f20015f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff1660014361089b9190611423565b610f44565b8367ffffffffffffffff16105b156108e4576040517fc396e95600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16638d4e40836040518163ffffffff1660e01b8152600401602060405180830381865afa15801561092d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109519190611480565b610987576040517feac631aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260405180604001604052808567ffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003905f5260205f20015f909190919091505f820151815f015f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506020820151815f0160086101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505f8290507fa940387dac06ebd336730f1d14b21629a9d137069a9137e871f95313e101016584848373ffffffffffffffffffffffffffffffffffffffff16639eab52536040518163ffffffff1660e01b81526004015f60405180830381865afa158015610ac3573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610aeb919061160f565b8473ffffffffffffffffffffffffffffffffffffffff1663e75235b86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b34573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b58919061166a565b6001600280549050610b6a919061139c565b604051610b7b95949392919061174c565b60405180910390a150505050565b610b92826104b2565b610b9b81610c95565b610ba58383610d99565b50505050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b5f600280549050905090565b5f60028267ffffffffffffffff1681548110610bfa57610bf96113cf565b5b905f5260205f20015f0160089054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b610ca681610ca1610d92565b610f5a565b50565b5f610cb48383610796565b610d885760015f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550610d25610d92565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050610d8c565b5f90505b92915050565b5f33905090565b5f610da48383610796565b15610e78575f5f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550610e15610d92565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050610e7c565b5f90505b92915050565b610e8a610fab565b5f60015f6101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa610ecc610d92565b604051610ed9919061130f565b60405180910390a1565b610eeb610feb565b6001805f6101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610f2d610d92565b604051610f3a919061130f565b60405180910390a1565b5f610f52828411848461102c565b905092915050565b610f648282610796565b610fa75780826040517fe2517d3f000000000000000000000000000000000000000000000000000000008152600401610f9e9291906117a4565b60405180910390fd5b5050565b610fb3610708565b610fe9576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b610ff3610708565b1561102a576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b5f61103684611045565b82841802821890509392505050565b5f8115159050919050565b5f604051905090565b5f5ffd5b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61109581611061565b811461109f575f5ffd5b50565b5f813590506110b08161108c565b92915050565b5f602082840312156110cb576110ca611059565b5b5f6110d8848285016110a2565b91505092915050565b5f8115159050919050565b6110f5816110e1565b82525050565b5f60208201905061110e5f8301846110ec565b92915050565b5f67ffffffffffffffff82169050919050565b61113081611114565b811461113a575f5ffd5b50565b5f8135905061114b81611127565b92915050565b5f6020828403121561116657611165611059565b5b5f6111738482850161113d565b91505092915050565b61118581611114565b82525050565b5f60208201905061119e5f83018461117c565b92915050565b5f819050919050565b6111b6816111a4565b81146111c0575f5ffd5b50565b5f813590506111d1816111ad565b92915050565b5f602082840312156111ec576111eb611059565b5b5f6111f9848285016111c3565b91505092915050565b61120b816111a4565b82525050565b5f6020820190506112245f830184611202565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6112538261122a565b9050919050565b61126381611249565b811461126d575f5ffd5b50565b5f8135905061127e8161125a565b92915050565b5f5f6040838503121561129a57611299611059565b5b5f6112a7858286016111c3565b92505060206112b885828601611270565b9150509250929050565b5f5f604083850312156112d8576112d7611059565b5b5f6112e585828601611270565b92505060206112f685828601611270565b9150509250929050565b61130981611249565b82525050565b5f6020820190506113225f830184611300565b92915050565b5f5f6040838503121561133e5761133d611059565b5b5f61134b8582860161113d565b925050602061135c85828601611270565b9150509250929050565b5f819050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6113a682611366565b91506113b183611366565b92508282039050818111156113c9576113c861136f565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f61140682611366565b91505f82036114185761141761136f565b5b600182039050919050565b5f61142d82611366565b915061143883611366565b92508282019050808211156114505761144f61136f565b5b92915050565b61145f816110e1565b8114611469575f5ffd5b50565b5f8151905061147a81611456565b92915050565b5f6020828403121561149557611494611059565b5b5f6114a28482850161146c565b91505092915050565b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6114f5826114af565b810181811067ffffffffffffffff82111715611514576115136114bf565b5b80604052505050565b5f611526611050565b905061153282826114ec565b919050565b5f67ffffffffffffffff821115611551576115506114bf565b5b602082029050602081019050919050565b5f5ffd5b5f815190506115748161125a565b92915050565b5f61158c61158784611537565b61151d565b905080838252602082019050602084028301858111156115af576115ae611562565b5b835b818110156115d857806115c48882611566565b8452602084019350506020810190506115b1565b5050509392505050565b5f82601f8301126115f6576115f56114ab565b5b815161160684826020860161157a565b91505092915050565b5f6020828403121561162457611623611059565b5b5f82015167ffffffffffffffff8111156116415761164061105d565b5b61164d848285016115e2565b91505092915050565b5f8151905061166481611127565b92915050565b5f6020828403121561167f5761167e611059565b5b5f61168c84828501611656565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6116c781611249565b82525050565b5f6116d883836116be565b60208301905092915050565b5f602082019050919050565b5f6116fa82611695565b611704818561169f565b935061170f836116af565b805f5b8381101561173f57815161172688826116cd565b9750611731836116e4565b925050600181019050611712565b5085935050505092915050565b5f60a08201905061175f5f83018861117c565b61176c6020830187611300565b818103604083015261177e81866116f0565b905061178d606083018561117c565b61179a608083018461117c565b9695505050505050565b5f6040820190506117b75f830185611300565b6117c46020830184611202565b939250505056fea164736f6c634300081c000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"initializer\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"DEFAULT_ADMIN_ROLE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"PAUSER_ROLE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addKeyperSet\",\"inputs\":[{\"name\":\"activationBlock\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperSetContract\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getKeyperSetActivationBlock\",\"inputs\":[{\"name\":\"index\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getKeyperSetAddress\",\"inputs\":[{\"name\":\"index\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getKeyperSetIndexByBlock\",\"inputs\":[{\"name\":\"blockNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getNumKeyperSets\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRoleAdmin\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"grantRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"hasRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"admin\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"pauser\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializer\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"pause\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"paused\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"callerConfirmation\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"revokeRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"unpause\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"KeyperSetAdded\",\"inputs\":[{\"name\":\"activationBlock\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"keyperSetContract\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"members\",\"type\":\"address[]\",\"indexed\":false,\"internalType\":\"address[]\"},{\"name\":\"threshold\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"eon\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"KeyperSetAdded\",\"inputs\":[{\"name\":\"activationSlot\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"keyperSetContract\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Paused\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleAdminChanged\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"previousAdminRole\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"newAdminRole\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleGranted\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleRevoked\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Unpaused\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AccessControlBadConfirmation\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AccessControlUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"neededRole\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"AlreadyHaveKeyperSet\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AlreadyInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DKGContractManagerMismatch\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DKGContractNotSet\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"EnforcedPause\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ExpectedPause\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"KeyperSetNotFinalized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NoActiveKeyperSet\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnauthorizedInitializer\",\"inputs\":[]}]", + Bin: "0x608060405234801561000f575f5ffd5b50604051611ab8380380611ab8833981810160405281019061003191906100d7565b80806001806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050610102565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6100a68261007d565b9050919050565b6100b68161009c565b81146100c0575f5ffd5b50565b5f815190506100d1816100ad565b92915050565b5f602082840312156100ec576100eb610079565b5b5f6100f9848285016100c3565b91505092915050565b6119a98061010f5f395ff3fe608060405234801561000f575f5ffd5b5060043610610114575f3560e01c80638456cb59116100a0578063d3877c431161006f578063d3877c43146102ca578063d547741f146102e6578063e63ab1e914610302578063f2e6100a14610320578063f90f3bed1461033e57610114565b80638456cb591461025457806391d148541461025e5780639ce110d71461028e578063a217fddf146102ac57610114565b806336568abe116100e757806336568abe146101c45780633f4ba83a146101e0578063485cc955146101ea5780635c975abb14610206578063636df9791461022457610114565b806301ffc9a714610118578063035cef1514610148578063248a9ca3146101785780632f2ff15d146101a8575b5f5ffd5b610132600480360381019061012d919061125c565b61036e565b60405161013f91906112a1565b60405180910390f35b610162600480360381019061015d91906112f7565b6103e7565b60405161016f9190611331565b60405180910390f35b610192600480360381019061018d919061137d565b6104b2565b60405161019f91906113b7565b60405180910390f35b6101c260048036038101906101bd919061142a565b6104ce565b005b6101de60048036038101906101d9919061142a565b6104f0565b005b6101e861056b565b005b61020460048036038101906101ff9190611468565b610582565b005b61020e610708565b60405161021b91906112a1565b60405180910390f35b61023e600480360381019061023991906112f7565b61071d565b60405161024b9190611331565b60405180910390f35b61025c610761565b005b6102786004803603810190610273919061142a565b610796565b60405161028591906112a1565b60405180910390f35b6102966107f9565b6040516102a391906114b5565b60405180910390f35b6102b461081d565b6040516102c191906113b7565b60405180910390f35b6102e460048036038101906102df91906114ce565b610823565b005b61030060048036038101906102fb919061142a565b610d2f565b005b61030a610d51565b60405161031791906113b7565b60405180910390f35b610328610d75565b6040516103359190611331565b60405180910390f35b610358600480360381019061035391906112f7565b610d81565b60405161036591906114b5565b60405180910390f35b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806103e057506103df82610dd2565b5b9050919050565b5f5f60028054905090505b5f81111561047a578267ffffffffffffffff1660026001836104149190611542565b8154811061042557610424611575565b5b905f5260205f20015f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff16116104675760018161045f9190611542565b9150506104ad565b8080610472906115a2565b9150506103f2565b506040517fcf93fa3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b5f5f5f8381526020019081526020015f20600101549050919050565b6104d7826104b2565b6104e081610e3b565b6104ea8383610e4f565b50505050565b6104f8610f38565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461055c576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6105668282610f3f565b505050565b5f5f1b61057781610e3b565b61057f611028565b50565b5f73ffffffffffffffffffffffffffffffffffffffff1660018054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603610607576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461068c576040517f0d622feb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106985f5f1b83610e4f565b506106c37f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a82610e4f565b505f6001806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b5f60015f9054906101000a900460ff16905090565b5f60028267ffffffffffffffff168154811061073c5761073b611575565b5b905f5260205f20015f015f9054906101000a900467ffffffffffffffff169050919050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a61078b81610e3b565b610793611089565b50565b5f5f5f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b60018054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f5f1b81565b5f5f1b61082f81610e3b565b5f6002805490501180156108ad57506108a0600260016002805490506108559190611542565b8154811061086657610865611575565b5b905f5260205f20015f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff1660014361089b91906115c9565b6110ea565b8367ffffffffffffffff16105b156108e4576040517fc396e95600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16638d4e40836040518163ffffffff1660e01b8152600401602060405180830381865afa15801561092d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109519190611626565b610987576040517feac631aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8273ffffffffffffffffffffffffffffffffffffffff166266f0a86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109d0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109f49190611665565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610a5b576040517f73dd647200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1663d4b2cedd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610abb573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610adf9190611665565b73ffffffffffffffffffffffffffffffffffffffff1614610b2c576040517f7cfd996a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260405180604001604052808667ffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003905f5260205f20015f909190919091505f820151815f015f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506020820151815f0160086101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505f8390507fa940387dac06ebd336730f1d14b21629a9d137069a9137e871f95313e101016585858373ffffffffffffffffffffffffffffffffffffffff16639eab52536040518163ffffffff1660e01b81526004015f60405180830381865afa158015610c68573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610c9091906117e0565b8473ffffffffffffffffffffffffffffffffffffffff1663e75235b86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cd9573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cfd919061183b565b6001600280549050610d0f9190611542565b604051610d2095949392919061191d565b60405180910390a15050505050565b610d38826104b2565b610d4181610e3b565b610d4b8383610f3f565b50505050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b5f600280549050905090565b5f60028267ffffffffffffffff1681548110610da057610d9f611575565b5b905f5260205f20015f0160089054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b610e4c81610e47610f38565b611100565b50565b5f610e5a8383610796565b610f2e5760015f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550610ecb610f38565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050610f32565b5f90505b92915050565b5f33905090565b5f610f4a8383610796565b1561101e575f5f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550610fbb610f38565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050611022565b5f90505b92915050565b611030611151565b5f60015f6101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611072610f38565b60405161107f91906114b5565b60405180910390a1565b611091611191565b6001805f6101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586110d3610f38565b6040516110e091906114b5565b60405180910390a1565b5f6110f882841184846111d2565b905092915050565b61110a8282610796565b61114d5780826040517fe2517d3f000000000000000000000000000000000000000000000000000000008152600401611144929190611975565b60405180910390fd5b5050565b611159610708565b61118f576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b611199610708565b156111d0576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b5f6111dc846111eb565b82841802821890509392505050565b5f8115159050919050565b5f604051905090565b5f5ffd5b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61123b81611207565b8114611245575f5ffd5b50565b5f8135905061125681611232565b92915050565b5f60208284031215611271576112706111ff565b5b5f61127e84828501611248565b91505092915050565b5f8115159050919050565b61129b81611287565b82525050565b5f6020820190506112b45f830184611292565b92915050565b5f67ffffffffffffffff82169050919050565b6112d6816112ba565b81146112e0575f5ffd5b50565b5f813590506112f1816112cd565b92915050565b5f6020828403121561130c5761130b6111ff565b5b5f611319848285016112e3565b91505092915050565b61132b816112ba565b82525050565b5f6020820190506113445f830184611322565b92915050565b5f819050919050565b61135c8161134a565b8114611366575f5ffd5b50565b5f8135905061137781611353565b92915050565b5f60208284031215611392576113916111ff565b5b5f61139f84828501611369565b91505092915050565b6113b18161134a565b82525050565b5f6020820190506113ca5f8301846113a8565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6113f9826113d0565b9050919050565b611409816113ef565b8114611413575f5ffd5b50565b5f8135905061142481611400565b92915050565b5f5f604083850312156114405761143f6111ff565b5b5f61144d85828601611369565b925050602061145e85828601611416565b9150509250929050565b5f5f6040838503121561147e5761147d6111ff565b5b5f61148b85828601611416565b925050602061149c85828601611416565b9150509250929050565b6114af816113ef565b82525050565b5f6020820190506114c85f8301846114a6565b92915050565b5f5f604083850312156114e4576114e36111ff565b5b5f6114f1858286016112e3565b925050602061150285828601611416565b9150509250929050565b5f819050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61154c8261150c565b91506115578361150c565b925082820390508181111561156f5761156e611515565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6115ac8261150c565b91505f82036115be576115bd611515565b5b600182039050919050565b5f6115d38261150c565b91506115de8361150c565b92508282019050808211156115f6576115f5611515565b5b92915050565b61160581611287565b811461160f575f5ffd5b50565b5f81519050611620816115fc565b92915050565b5f6020828403121561163b5761163a6111ff565b5b5f61164884828501611612565b91505092915050565b5f8151905061165f81611400565b92915050565b5f6020828403121561167a576116796111ff565b5b5f61168784828501611651565b91505092915050565b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6116da82611694565b810181811067ffffffffffffffff821117156116f9576116f86116a4565b5b80604052505050565b5f61170b6111f6565b905061171782826116d1565b919050565b5f67ffffffffffffffff821115611736576117356116a4565b5b602082029050602081019050919050565b5f5ffd5b5f61175d6117588461171c565b611702565b905080838252602082019050602084028301858111156117805761177f611747565b5b835b818110156117a957806117958882611651565b845260208401935050602081019050611782565b5050509392505050565b5f82601f8301126117c7576117c6611690565b5b81516117d784826020860161174b565b91505092915050565b5f602082840312156117f5576117f46111ff565b5b5f82015167ffffffffffffffff81111561181257611811611203565b5b61181e848285016117b3565b91505092915050565b5f81519050611835816112cd565b92915050565b5f602082840312156118505761184f6111ff565b5b5f61185d84828501611827565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b611898816113ef565b82525050565b5f6118a9838361188f565b60208301905092915050565b5f602082019050919050565b5f6118cb82611866565b6118d58185611870565b93506118e083611880565b805f5b838110156119105781516118f7888261189e565b9750611902836118b5565b9250506001810190506118e3565b5085935050505092915050565b5f60a0820190506119305f830188611322565b61193d60208301876114a6565b818103604083015261194f81866118c1565b905061195e6060830185611322565b61196b6080830184611322565b9695505050505050565b5f6040820190506119885f8301856114a6565b61199560208301846113a8565b939250505056fea164736f6c634300081c000a", } // KeypersetmanagerABI is the input ABI used to generate the binding from. diff --git a/bindings/shuttereventtriggerregistryv1/shuttereventtriggerregistryv1.go b/bindings/shuttereventtriggerregistryv1/shuttereventtriggerregistryv1.go index 57ddd86..be87263 100644 --- a/bindings/shuttereventtriggerregistryv1/shuttereventtriggerregistryv1.go +++ b/bindings/shuttereventtriggerregistryv1/shuttereventtriggerregistryv1.go @@ -31,8 +31,8 @@ var ( // Shuttereventtriggerregistryv1MetaData contains all meta data concerning the Shuttereventtriggerregistryv1 contract. var Shuttereventtriggerregistryv1MetaData = &bind.MetaData{ - ABI: "[{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"register\",\"inputs\":[{\"name\":\"eon\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"identityPrefix\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"triggerDefinition\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"ttl\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"EventTriggerRegistered\",\"inputs\":[{\"name\":\"eon\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"identityPrefix\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"triggerDefinition\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"expirationBlockNumber\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnableInvalidOwner\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OwnableUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}]}]", - Bin: "0x6080604052348015600e575f5ffd5b50610aaa8061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610055575f3560e01c8063715018a6146100595780638129fc1c146100635780638da5cb5b1461006d578063d48b6d1e1461008b578063f2fde38b146100a7575b5f5ffd5b6100616100c3565b005b61006b6100d6565b005b610075610256565b6040516100829190610667565b60405180910390f35b6100a560048036038101906100a0919061083d565b61028b565b005b6100c160048036038101906100bc91906108e7565b6102ec565b005b6100cb610370565b6100d45f6103f7565b565b5f6100df6104c8565b90505f815f0160089054906101000a900460ff161590505f825f015f9054906101000a900467ffffffffffffffff1690505f5f8267ffffffffffffffff161480156101275750825b90505f60018367ffffffffffffffff1614801561015a57505f3073ffffffffffffffffffffffffffffffffffffffff163b145b905081158015610168575080155b1561019f576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001855f015f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555083156101ec576001855f0160086101000a81548160ff0219169083151502179055505b6101f5336104db565b831561024f575f855f0160086101000a81548160ff0219169083151502179055507fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d260016040516102469190610954565b60405180910390a15b5050505050565b5f5f6102606104ef565b9050805f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505090565b610293610370565b8367ffffffffffffffff167f06809c10c5d53027eb51ca4ec6da8fbfd54d79f41cdefaab2cb142d10b039db584338585436102ce919061099a565b6040516102de9493929190610a53565b60405180910390a250505050565b6102f4610370565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610364575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161035b9190610667565b60405180910390fd5b61036d816103f7565b50565b610378610516565b73ffffffffffffffffffffffffffffffffffffffff16610396610256565b73ffffffffffffffffffffffffffffffffffffffff16146103f5576103b9610516565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016103ec9190610667565b60405180910390fd5b565b5f6104006104ef565b90505f815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905082825f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3505050565b5f5f6104d261051d565b90508091505090565b6104e3610546565b6104ec81610586565b50565b5f7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300905090565b5f33905090565b5f7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005f1b905090565b61054e61060a565b610584576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b61058e610546565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036105fe575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016105f59190610667565b60405180910390fd5b610607816103f7565b50565b5f6106136104c8565b5f0160089054906101000a900460ff16905090565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61065182610628565b9050919050565b61066181610647565b82525050565b5f60208201905061067a5f830184610658565b92915050565b5f604051905090565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82169050919050565b6106ad81610691565b81146106b7575f5ffd5b50565b5f813590506106c8816106a4565b92915050565b5f819050919050565b6106e0816106ce565b81146106ea575f5ffd5b50565b5f813590506106fb816106d7565b92915050565b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61074f82610709565b810181811067ffffffffffffffff8211171561076e5761076d610719565b5b80604052505050565b5f610780610680565b905061078c8282610746565b919050565b5f67ffffffffffffffff8211156107ab576107aa610719565b5b6107b482610709565b9050602081019050919050565b828183375f83830152505050565b5f6107e16107dc84610791565b610777565b9050828152602081018484840111156107fd576107fc610705565b5b6108088482856107c1565b509392505050565b5f82601f83011261082457610823610701565b5b81356108348482602086016107cf565b91505092915050565b5f5f5f5f6080858703121561085557610854610689565b5b5f610862878288016106ba565b9450506020610873878288016106ed565b935050604085013567ffffffffffffffff8111156108945761089361068d565b5b6108a087828801610810565b92505060606108b1878288016106ba565b91505092959194509250565b6108c681610647565b81146108d0575f5ffd5b50565b5f813590506108e1816108bd565b92915050565b5f602082840312156108fc576108fb610689565b5b5f610909848285016108d3565b91505092915050565b5f819050919050565b5f819050919050565b5f61093e61093961093484610912565b61091b565b610691565b9050919050565b61094e81610924565b82525050565b5f6020820190506109675f830184610945565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6109a482610691565b91506109af83610691565b9250828201905067ffffffffffffffff8111156109cf576109ce61096d565b5b92915050565b6109de816106ce565b82525050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f610a16826109e4565b610a2081856109ee565b9350610a308185602086016109fe565b610a3981610709565b840191505092915050565b610a4d81610691565b82525050565b5f608082019050610a665f8301876109d5565b610a736020830186610658565b8181036040830152610a858185610a0c565b9050610a946060830184610a44565b9594505050505056fea164736f6c634300081c000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"UPGRADE_INTERFACE_VERSION\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proxiableUUID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"register\",\"inputs\":[{\"name\":\"eon\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"identityPrefix\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"triggerDefinition\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"ttl\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"inputs\":[{\"name\":\"newImplementation\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"event\",\"name\":\"EventTriggerRegistered\",\"inputs\":[{\"name\":\"eon\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"identityPrefix\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"triggerDefinition\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"expirationBlockNumber\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Upgraded\",\"inputs\":[{\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AddressEmptyCode\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC1967InvalidImplementation\",\"inputs\":[{\"name\":\"implementation\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC1967NonPayable\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"FailedCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnableInvalidOwner\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OwnableUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"UUPSUnauthorizedCallContext\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UUPSUnsupportedProxiableUUID\",\"inputs\":[{\"name\":\"slot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]}]", + Bin: "0x60a06040523073ffffffffffffffffffffffffffffffffffffffff1660809073ffffffffffffffffffffffffffffffffffffffff16815250348015610042575f5ffd5b5061005161005660201b60201c565b6101d1565b5f61006561015460201b60201c565b9050805f0160089054906101000a900460ff16156100af576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8016815f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff16146101515767ffffffffffffffff815f015f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d267ffffffffffffffff60405161014891906101b8565b60405180910390a15b50565b5f5f61016461016d60201b60201c565b90508091505090565b5f7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005f1b905090565b5f67ffffffffffffffff82169050919050565b6101b281610196565b82525050565b5f6020820190506101cb5f8301846101a9565b92915050565b6080516113436101f75f395f81816104d40152818161052901526106e301526113435ff3fe60806040526004361061007a575f3560e01c80638da5cb5b1161004d5780638da5cb5b146100f0578063ad3cb1cc1461011a578063d48b6d1e14610144578063f2fde38b1461016c5761007a565b80634f1ef2861461007e57806352d1902d1461009a578063715018a6146100c45780638129fc1c146100da575b5f5ffd5b61009860048036038101906100939190610ef4565b610194565b005b3480156100a5575f5ffd5b506100ae6101b3565b6040516100bb9190610f66565b60405180910390f35b3480156100cf575f5ffd5b506100d86101e4565b005b3480156100e5575f5ffd5b506100ee6101f7565b005b3480156100fb575f5ffd5b5061010461037f565b6040516101119190610f8e565b60405180910390f35b348015610125575f5ffd5b5061012e6103b4565b60405161013b9190611007565b60405180910390f35b34801561014f575f5ffd5b5061016a6004803603810190610165919061108e565b6103ed565b005b348015610177575f5ffd5b50610192600480360381019061018d919061110e565b61044e565b005b61019c6104d2565b6101a5826105b8565b6101af82826105c3565b5050565b5f6101bc6106e1565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5f1b905090565b6101ec610768565b6101f55f6107ef565b565b5f6102006108c0565b90505f815f0160089054906101000a900460ff161590505f825f015f9054906101000a900467ffffffffffffffff1690505f5f8267ffffffffffffffff161480156102485750825b90505f60018367ffffffffffffffff1614801561027b57505f3073ffffffffffffffffffffffffffffffffffffffff163b145b905081158015610289575080155b156102c0576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001855f015f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550831561030d576001855f0160086101000a81548160ff0219169083151502179055505b610316336108d3565b61031e6108e7565b8315610378575f855f0160086101000a81548160ff0219169083151502179055507fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2600160405161036f919061117b565b60405180910390a15b5050505050565b5f5f6103896108f1565b9050805f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505090565b6040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6103f5610768565b8367ffffffffffffffff167f06809c10c5d53027eb51ca4ec6da8fbfd54d79f41cdefaab2cb142d10b039db5843385854361043091906111c1565b604051610440949392919061125d565b60405180910390a250505050565b610456610768565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036104c6575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016104bd9190610f8e565b60405180910390fd5b6104cf816107ef565b50565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148061057f57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16610566610918565b73ffffffffffffffffffffffffffffffffffffffff1614155b156105b6576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6105c0610768565b50565b8173ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561062b57506040513d601f19601f8201168201806040525081019061062891906112bb565b60015b61066c57816040517f4c9c8ce30000000000000000000000000000000000000000000000000000000081526004016106639190610f8e565b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5f1b81146106d257806040517faa1d49a40000000000000000000000000000000000000000000000000000000081526004016106c99190610f66565b60405180910390fd5b6106dc838361096b565b505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1614610766576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6107706109dd565b73ffffffffffffffffffffffffffffffffffffffff1661078e61037f565b73ffffffffffffffffffffffffffffffffffffffff16146107ed576107b16109dd565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016107e49190610f8e565b60405180910390fd5b565b5f6107f86108f1565b90505f815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905082825f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3505050565b5f5f6108ca6109e4565b90508091505090565b6108db610a0d565b6108e481610a4d565b50565b6108ef610a0d565b565b5f7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300905090565b5f6109447f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5f1b610ad1565b5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b61097482610ada565b8173ffffffffffffffffffffffffffffffffffffffff167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b60405160405180910390a25f815111156109d0576109ca8282610ba3565b506109d9565b6109d8610c23565b5b5050565b5f33905090565b5f7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005f1b905090565b610a15610c5f565b610a4b576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b610a55610a0d565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610ac5575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401610abc9190610f8e565b60405180910390fd5b610ace816107ef565b50565b5f819050919050565b5f8173ffffffffffffffffffffffffffffffffffffffff163b03610b3557806040517f4c9c8ce3000000000000000000000000000000000000000000000000000000008152600401610b2c9190610f8e565b60405180910390fd5b80610b617f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5f1b610ad1565b5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60605f5f8473ffffffffffffffffffffffffffffffffffffffff1684604051610bcc9190611320565b5f60405180830381855af49150503d805f8114610c04576040519150601f19603f3d011682016040523d82523d5f602084013e610c09565b606091505b5091509150610c19858383610c7d565b9250505092915050565b5f341115610c5d576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b5f610c686108c0565b5f0160089054906101000a900460ff16905090565b606082610c9257610c8d82610d0a565b610d02565b5f8251148015610cb857505f8473ffffffffffffffffffffffffffffffffffffffff163b145b15610cfa57836040517f9996b315000000000000000000000000000000000000000000000000000000008152600401610cf19190610f8e565b60405180910390fd5b819050610d03565b5b9392505050565b5f81511115610d1b57805160208201fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f604051905090565b5f5ffd5b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610d8782610d5e565b9050919050565b610d9781610d7d565b8114610da1575f5ffd5b50565b5f81359050610db281610d8e565b92915050565b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b610e0682610dc0565b810181811067ffffffffffffffff82111715610e2557610e24610dd0565b5b80604052505050565b5f610e37610d4d565b9050610e438282610dfd565b919050565b5f67ffffffffffffffff821115610e6257610e61610dd0565b5b610e6b82610dc0565b9050602081019050919050565b828183375f83830152505050565b5f610e98610e9384610e48565b610e2e565b905082815260208101848484011115610eb457610eb3610dbc565b5b610ebf848285610e78565b509392505050565b5f82601f830112610edb57610eda610db8565b5b8135610eeb848260208601610e86565b91505092915050565b5f5f60408385031215610f0a57610f09610d56565b5b5f610f1785828601610da4565b925050602083013567ffffffffffffffff811115610f3857610f37610d5a565b5b610f4485828601610ec7565b9150509250929050565b5f819050919050565b610f6081610f4e565b82525050565b5f602082019050610f795f830184610f57565b92915050565b610f8881610d7d565b82525050565b5f602082019050610fa15f830184610f7f565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f610fd982610fa7565b610fe38185610fb1565b9350610ff3818560208601610fc1565b610ffc81610dc0565b840191505092915050565b5f6020820190508181035f83015261101f8184610fcf565b905092915050565b5f67ffffffffffffffff82169050919050565b61104381611027565b811461104d575f5ffd5b50565b5f8135905061105e8161103a565b92915050565b61106d81610f4e565b8114611077575f5ffd5b50565b5f8135905061108881611064565b92915050565b5f5f5f5f608085870312156110a6576110a5610d56565b5b5f6110b387828801611050565b94505060206110c48782880161107a565b935050604085013567ffffffffffffffff8111156110e5576110e4610d5a565b5b6110f187828801610ec7565b925050606061110287828801611050565b91505092959194509250565b5f6020828403121561112357611122610d56565b5b5f61113084828501610da4565b91505092915050565b5f819050919050565b5f819050919050565b5f61116561116061115b84611139565b611142565b611027565b9050919050565b6111758161114b565b82525050565b5f60208201905061118e5f83018461116c565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6111cb82611027565b91506111d683611027565b9250828201905067ffffffffffffffff8111156111f6576111f5611194565b5b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f611220826111fc565b61122a8185611206565b935061123a818560208601610fc1565b61124381610dc0565b840191505092915050565b61125781611027565b82525050565b5f6080820190506112705f830187610f57565b61127d6020830186610f7f565b818103604083015261128f8185611216565b905061129e606083018461124e565b95945050505050565b5f815190506112b581611064565b92915050565b5f602082840312156112d0576112cf610d56565b5b5f6112dd848285016112a7565b91505092915050565b5f81905092915050565b5f6112fa826111fc565b61130481856112e6565b9350611314818560208601610fc1565b80840191505092915050565b5f61132b82846112f0565b91508190509291505056fea164736f6c634300081c000a", } // Shuttereventtriggerregistryv1ABI is the input ABI used to generate the binding from. @@ -202,6 +202,37 @@ func (_Shuttereventtriggerregistryv1 *Shuttereventtriggerregistryv1TransactorRaw return _Shuttereventtriggerregistryv1.Contract.contract.Transact(opts, method, params...) } +// UPGRADEINTERFACEVERSION is a free data retrieval call binding the contract method 0xad3cb1cc. +// +// Solidity: function UPGRADE_INTERFACE_VERSION() view returns(string) +func (_Shuttereventtriggerregistryv1 *Shuttereventtriggerregistryv1Caller) UPGRADEINTERFACEVERSION(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Shuttereventtriggerregistryv1.contract.Call(opts, &out, "UPGRADE_INTERFACE_VERSION") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// UPGRADEINTERFACEVERSION is a free data retrieval call binding the contract method 0xad3cb1cc. +// +// Solidity: function UPGRADE_INTERFACE_VERSION() view returns(string) +func (_Shuttereventtriggerregistryv1 *Shuttereventtriggerregistryv1Session) UPGRADEINTERFACEVERSION() (string, error) { + return _Shuttereventtriggerregistryv1.Contract.UPGRADEINTERFACEVERSION(&_Shuttereventtriggerregistryv1.CallOpts) +} + +// UPGRADEINTERFACEVERSION is a free data retrieval call binding the contract method 0xad3cb1cc. +// +// Solidity: function UPGRADE_INTERFACE_VERSION() view returns(string) +func (_Shuttereventtriggerregistryv1 *Shuttereventtriggerregistryv1CallerSession) UPGRADEINTERFACEVERSION() (string, error) { + return _Shuttereventtriggerregistryv1.Contract.UPGRADEINTERFACEVERSION(&_Shuttereventtriggerregistryv1.CallOpts) +} + // Owner is a free data retrieval call binding the contract method 0x8da5cb5b. // // Solidity: function owner() view returns(address) @@ -233,6 +264,37 @@ func (_Shuttereventtriggerregistryv1 *Shuttereventtriggerregistryv1CallerSession return _Shuttereventtriggerregistryv1.Contract.Owner(&_Shuttereventtriggerregistryv1.CallOpts) } +// ProxiableUUID is a free data retrieval call binding the contract method 0x52d1902d. +// +// Solidity: function proxiableUUID() view returns(bytes32) +func (_Shuttereventtriggerregistryv1 *Shuttereventtriggerregistryv1Caller) ProxiableUUID(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Shuttereventtriggerregistryv1.contract.Call(opts, &out, "proxiableUUID") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// ProxiableUUID is a free data retrieval call binding the contract method 0x52d1902d. +// +// Solidity: function proxiableUUID() view returns(bytes32) +func (_Shuttereventtriggerregistryv1 *Shuttereventtriggerregistryv1Session) ProxiableUUID() ([32]byte, error) { + return _Shuttereventtriggerregistryv1.Contract.ProxiableUUID(&_Shuttereventtriggerregistryv1.CallOpts) +} + +// ProxiableUUID is a free data retrieval call binding the contract method 0x52d1902d. +// +// Solidity: function proxiableUUID() view returns(bytes32) +func (_Shuttereventtriggerregistryv1 *Shuttereventtriggerregistryv1CallerSession) ProxiableUUID() ([32]byte, error) { + return _Shuttereventtriggerregistryv1.Contract.ProxiableUUID(&_Shuttereventtriggerregistryv1.CallOpts) +} + // Initialize is a paid mutator transaction binding the contract method 0x8129fc1c. // // Solidity: function initialize() returns() @@ -317,6 +379,27 @@ func (_Shuttereventtriggerregistryv1 *Shuttereventtriggerregistryv1TransactorSes return _Shuttereventtriggerregistryv1.Contract.TransferOwnership(&_Shuttereventtriggerregistryv1.TransactOpts, newOwner) } +// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286. +// +// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns() +func (_Shuttereventtriggerregistryv1 *Shuttereventtriggerregistryv1Transactor) UpgradeToAndCall(opts *bind.TransactOpts, newImplementation common.Address, data []byte) (*types.Transaction, error) { + return _Shuttereventtriggerregistryv1.contract.Transact(opts, "upgradeToAndCall", newImplementation, data) +} + +// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286. +// +// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns() +func (_Shuttereventtriggerregistryv1 *Shuttereventtriggerregistryv1Session) UpgradeToAndCall(newImplementation common.Address, data []byte) (*types.Transaction, error) { + return _Shuttereventtriggerregistryv1.Contract.UpgradeToAndCall(&_Shuttereventtriggerregistryv1.TransactOpts, newImplementation, data) +} + +// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286. +// +// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns() +func (_Shuttereventtriggerregistryv1 *Shuttereventtriggerregistryv1TransactorSession) UpgradeToAndCall(newImplementation common.Address, data []byte) (*types.Transaction, error) { + return _Shuttereventtriggerregistryv1.Contract.UpgradeToAndCall(&_Shuttereventtriggerregistryv1.TransactOpts, newImplementation, data) +} + // Shuttereventtriggerregistryv1EventTriggerRegisteredIterator is returned from FilterEventTriggerRegistered and is used to iterate over the raw logs and unpacked data for EventTriggerRegistered events raised by the Shuttereventtriggerregistryv1 contract. type Shuttereventtriggerregistryv1EventTriggerRegisteredIterator struct { Event *Shuttereventtriggerregistryv1EventTriggerRegistered // Event containing the contract specifics and raw log @@ -751,3 +834,147 @@ func (_Shuttereventtriggerregistryv1 *Shuttereventtriggerregistryv1Filterer) Par event.Raw = log return event, nil } + +// Shuttereventtriggerregistryv1UpgradedIterator is returned from FilterUpgraded and is used to iterate over the raw logs and unpacked data for Upgraded events raised by the Shuttereventtriggerregistryv1 contract. +type Shuttereventtriggerregistryv1UpgradedIterator struct { + Event *Shuttereventtriggerregistryv1Upgraded // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Shuttereventtriggerregistryv1UpgradedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Shuttereventtriggerregistryv1Upgraded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Shuttereventtriggerregistryv1Upgraded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Shuttereventtriggerregistryv1UpgradedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Shuttereventtriggerregistryv1UpgradedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Shuttereventtriggerregistryv1Upgraded represents a Upgraded event raised by the Shuttereventtriggerregistryv1 contract. +type Shuttereventtriggerregistryv1Upgraded struct { + Implementation common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpgraded is a free log retrieval operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_Shuttereventtriggerregistryv1 *Shuttereventtriggerregistryv1Filterer) FilterUpgraded(opts *bind.FilterOpts, implementation []common.Address) (*Shuttereventtriggerregistryv1UpgradedIterator, error) { + + var implementationRule []interface{} + for _, implementationItem := range implementation { + implementationRule = append(implementationRule, implementationItem) + } + + logs, sub, err := _Shuttereventtriggerregistryv1.contract.FilterLogs(opts, "Upgraded", implementationRule) + if err != nil { + return nil, err + } + return &Shuttereventtriggerregistryv1UpgradedIterator{contract: _Shuttereventtriggerregistryv1.contract, event: "Upgraded", logs: logs, sub: sub}, nil +} + +// WatchUpgraded is a free log subscription operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_Shuttereventtriggerregistryv1 *Shuttereventtriggerregistryv1Filterer) WatchUpgraded(opts *bind.WatchOpts, sink chan<- *Shuttereventtriggerregistryv1Upgraded, implementation []common.Address) (event.Subscription, error) { + + var implementationRule []interface{} + for _, implementationItem := range implementation { + implementationRule = append(implementationRule, implementationItem) + } + + logs, sub, err := _Shuttereventtriggerregistryv1.contract.WatchLogs(opts, "Upgraded", implementationRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Shuttereventtriggerregistryv1Upgraded) + if err := _Shuttereventtriggerregistryv1.contract.UnpackLog(event, "Upgraded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseUpgraded is a log parse operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_Shuttereventtriggerregistryv1 *Shuttereventtriggerregistryv1Filterer) ParseUpgraded(log types.Log) (*Shuttereventtriggerregistryv1Upgraded, error) { + event := new(Shuttereventtriggerregistryv1Upgraded) + if err := _Shuttereventtriggerregistryv1.contract.UnpackLog(event, "Upgraded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/gen_bindings.sh b/gen_bindings.sh index fc6f1b5..a764d35 100755 --- a/gen_bindings.sh +++ b/gen_bindings.sh @@ -9,6 +9,8 @@ CONTRACTS=( "src/common/KeyperSet.sol:KeyperSet" "src/common/EonKeyPublish.sol:EonKeyPublish" "src/common/KeyBroadcastContract.sol:KeyBroadcastContract" + "src/common/DKGContract.sol:DKGContract" + "src/common/ECIESKeyRegistry.sol:ECIESKeyRegistry" "src/shop/Inbox.sol:Inbox" "src/shutter-service/ShutterRegistry.sol:ShutterRegistry" "src/shutter-service/ShutterEventTriggerRegistry.sol:ShutterEventTriggerRegistryV1" From 960de203e923c68eb3ec377c8494eabd4e1fa967 Mon Sep 17 00:00:00 2001 From: Jannik Date: Wed, 8 Jul 2026 20:20:46 +0200 Subject: [PATCH 21/25] chore: drop stale unversioned event-trigger binding --- .../shuttereventtriggerregistry.go | 648 ------------------ 1 file changed, 648 deletions(-) delete mode 100644 bindings/shuttereventtriggerregistry/shuttereventtriggerregistry.go diff --git a/bindings/shuttereventtriggerregistry/shuttereventtriggerregistry.go b/bindings/shuttereventtriggerregistry/shuttereventtriggerregistry.go deleted file mode 100644 index 50e6b4f..0000000 --- a/bindings/shuttereventtriggerregistry/shuttereventtriggerregistry.go +++ /dev/null @@ -1,648 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package shuttereventtriggerregistry - -import ( - "errors" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription - _ = abi.ConvertType -) - -// ShuttereventtriggerregistryMetaData contains all meta data concerning the Shuttereventtriggerregistry contract. -var ShuttereventtriggerregistryMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"register\",\"inputs\":[{\"name\":\"eon\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"identityPrefix\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"triggerDefinition\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"ttl\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"registrations\",\"inputs\":[{\"name\":\"identity\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"eon\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"ttl\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"triggerDefinitionHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"EventTriggerRegistered\",\"inputs\":[{\"name\":\"eon\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"identityPrefix\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"triggerDefinition\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"ttl\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AlreadyRegistered\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidIdentityPrefix\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnableInvalidOwner\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OwnableUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"TTLTooShort\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TimestampInThePast\",\"inputs\":[]}]", - Bin: "0x608060405234801561000f575f5ffd5b50335f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610081575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016100789190610196565b60405180910390fd5b6100908161009660201b60201c565b506101af565b5f5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61018082610157565b9050919050565b61019081610176565b82525050565b5f6020820190506101a95f830184610187565b92915050565b610a94806101bc5f395ff3fe608060405234801561000f575f5ffd5b5060043610610055575f3560e01c8063715018a6146100595780638da5cb5b14610063578063d48b6d1e14610081578063da7c6a421461009d578063f2fde38b146100cf575b5f5ffd5b6100616100eb565b005b61006b6100fe565b6040516100789190610604565b60405180910390f35b61009b600480360381019061009691906107da565b610125565b005b6100b760048036038101906100b2919061085a565b6103a6565b6040516100c6939291906108a3565b60405180910390f35b6100e960048036038101906100e49190610902565b6103f2565b005b6100f3610476565b6100fc5f6104fd565b565b5f5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b438167ffffffffffffffff161015610169576040517f84f8e55900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5f1b83036101a4576040517f63a4021d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f83336040516020016101b8929190610992565b6040516020818303038152906040528051906020012090505f60015f8381526020019081526020015f2090505f815f0160089054906101000a900467ffffffffffffffff1667ffffffffffffffff16146102d4578267ffffffffffffffff16815f0160089054906101000a900467ffffffffffffffff1667ffffffffffffffff1610610270576040517fb5f2184000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060010154846040516020016102869190610a1d565b60405160208183030381529060405280519060200120146102d3576040517f3a81d6fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b82815f0160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555085815f015f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550836040516020016103389190610a1d565b6040516020818303038152906040528051906020012081600101819055508567ffffffffffffffff167f06809c10c5d53027eb51ca4ec6da8fbfd54d79f41cdefaab2cb142d10b039db5863387876040516103969493929190610a3d565b60405180910390a2505050505050565b6001602052805f5260405f205f91509050805f015f9054906101000a900467ffffffffffffffff1690805f0160089054906101000a900467ffffffffffffffff16908060010154905083565b6103fa610476565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361046a575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016104619190610604565b60405180910390fd5b610473816104fd565b50565b61047e6105be565b73ffffffffffffffffffffffffffffffffffffffff1661049c6100fe565b73ffffffffffffffffffffffffffffffffffffffff16146104fb576104bf6105be565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016104f29190610604565b60405180910390fd5b565b5f5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f33905090565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6105ee826105c5565b9050919050565b6105fe816105e4565b82525050565b5f6020820190506106175f8301846105f5565b92915050565b5f604051905090565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82169050919050565b61064a8161062e565b8114610654575f5ffd5b50565b5f8135905061066581610641565b92915050565b5f819050919050565b61067d8161066b565b8114610687575f5ffd5b50565b5f8135905061069881610674565b92915050565b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6106ec826106a6565b810181811067ffffffffffffffff8211171561070b5761070a6106b6565b5b80604052505050565b5f61071d61061d565b905061072982826106e3565b919050565b5f67ffffffffffffffff821115610748576107476106b6565b5b610751826106a6565b9050602081019050919050565b828183375f83830152505050565b5f61077e6107798461072e565b610714565b90508281526020810184848401111561079a576107996106a2565b5b6107a584828561075e565b509392505050565b5f82601f8301126107c1576107c061069e565b5b81356107d184826020860161076c565b91505092915050565b5f5f5f5f608085870312156107f2576107f1610626565b5b5f6107ff87828801610657565b94505060206108108782880161068a565b935050604085013567ffffffffffffffff8111156108315761083061062a565b5b61083d878288016107ad565b925050606061084e87828801610657565b91505092959194509250565b5f6020828403121561086f5761086e610626565b5b5f61087c8482850161068a565b91505092915050565b61088e8161062e565b82525050565b61089d8161066b565b82525050565b5f6060820190506108b65f830186610885565b6108c36020830185610885565b6108d06040830184610894565b949350505050565b6108e1816105e4565b81146108eb575f5ffd5b50565b5f813590506108fc816108d8565b92915050565b5f6020828403121561091757610916610626565b5b5f610924848285016108ee565b91505092915050565b5f819050919050565b6109476109428261066b565b61092d565b82525050565b5f8160601b9050919050565b5f6109638261094d565b9050919050565b5f61097482610959565b9050919050565b61098c610987826105e4565b61096a565b82525050565b5f61099d8285610936565b6020820191506109ad828461097b565b6014820191508190509392505050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f6109ef826109bd565b6109f981856109c7565b9350610a098185602086016109d7565b610a12816106a6565b840191505092915050565b5f6020820190508181035f830152610a3581846109e5565b905092915050565b5f608082019050610a505f830187610894565b610a5d60208301866105f5565b8181036040830152610a6f81856109e5565b9050610a7e6060830184610885565b9594505050505056fea164736f6c634300081c000a", -} - -// ShuttereventtriggerregistryABI is the input ABI used to generate the binding from. -// Deprecated: Use ShuttereventtriggerregistryMetaData.ABI instead. -var ShuttereventtriggerregistryABI = ShuttereventtriggerregistryMetaData.ABI - -// ShuttereventtriggerregistryBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use ShuttereventtriggerregistryMetaData.Bin instead. -var ShuttereventtriggerregistryBin = ShuttereventtriggerregistryMetaData.Bin - -// DeployShuttereventtriggerregistry deploys a new Ethereum contract, binding an instance of Shuttereventtriggerregistry to it. -func DeployShuttereventtriggerregistry(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Shuttereventtriggerregistry, error) { - parsed, err := ShuttereventtriggerregistryMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(ShuttereventtriggerregistryBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &Shuttereventtriggerregistry{ShuttereventtriggerregistryCaller: ShuttereventtriggerregistryCaller{contract: contract}, ShuttereventtriggerregistryTransactor: ShuttereventtriggerregistryTransactor{contract: contract}, ShuttereventtriggerregistryFilterer: ShuttereventtriggerregistryFilterer{contract: contract}}, nil -} - -// Shuttereventtriggerregistry is an auto generated Go binding around an Ethereum contract. -type Shuttereventtriggerregistry struct { - ShuttereventtriggerregistryCaller // Read-only binding to the contract - ShuttereventtriggerregistryTransactor // Write-only binding to the contract - ShuttereventtriggerregistryFilterer // Log filterer for contract events -} - -// ShuttereventtriggerregistryCaller is an auto generated read-only Go binding around an Ethereum contract. -type ShuttereventtriggerregistryCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ShuttereventtriggerregistryTransactor is an auto generated write-only Go binding around an Ethereum contract. -type ShuttereventtriggerregistryTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ShuttereventtriggerregistryFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type ShuttereventtriggerregistryFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ShuttereventtriggerregistrySession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type ShuttereventtriggerregistrySession struct { - Contract *Shuttereventtriggerregistry // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// ShuttereventtriggerregistryCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type ShuttereventtriggerregistryCallerSession struct { - Contract *ShuttereventtriggerregistryCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// ShuttereventtriggerregistryTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type ShuttereventtriggerregistryTransactorSession struct { - Contract *ShuttereventtriggerregistryTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// ShuttereventtriggerregistryRaw is an auto generated low-level Go binding around an Ethereum contract. -type ShuttereventtriggerregistryRaw struct { - Contract *Shuttereventtriggerregistry // Generic contract binding to access the raw methods on -} - -// ShuttereventtriggerregistryCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type ShuttereventtriggerregistryCallerRaw struct { - Contract *ShuttereventtriggerregistryCaller // Generic read-only contract binding to access the raw methods on -} - -// ShuttereventtriggerregistryTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type ShuttereventtriggerregistryTransactorRaw struct { - Contract *ShuttereventtriggerregistryTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewShuttereventtriggerregistry creates a new instance of Shuttereventtriggerregistry, bound to a specific deployed contract. -func NewShuttereventtriggerregistry(address common.Address, backend bind.ContractBackend) (*Shuttereventtriggerregistry, error) { - contract, err := bindShuttereventtriggerregistry(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Shuttereventtriggerregistry{ShuttereventtriggerregistryCaller: ShuttereventtriggerregistryCaller{contract: contract}, ShuttereventtriggerregistryTransactor: ShuttereventtriggerregistryTransactor{contract: contract}, ShuttereventtriggerregistryFilterer: ShuttereventtriggerregistryFilterer{contract: contract}}, nil -} - -// NewShuttereventtriggerregistryCaller creates a new read-only instance of Shuttereventtriggerregistry, bound to a specific deployed contract. -func NewShuttereventtriggerregistryCaller(address common.Address, caller bind.ContractCaller) (*ShuttereventtriggerregistryCaller, error) { - contract, err := bindShuttereventtriggerregistry(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &ShuttereventtriggerregistryCaller{contract: contract}, nil -} - -// NewShuttereventtriggerregistryTransactor creates a new write-only instance of Shuttereventtriggerregistry, bound to a specific deployed contract. -func NewShuttereventtriggerregistryTransactor(address common.Address, transactor bind.ContractTransactor) (*ShuttereventtriggerregistryTransactor, error) { - contract, err := bindShuttereventtriggerregistry(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &ShuttereventtriggerregistryTransactor{contract: contract}, nil -} - -// NewShuttereventtriggerregistryFilterer creates a new log filterer instance of Shuttereventtriggerregistry, bound to a specific deployed contract. -func NewShuttereventtriggerregistryFilterer(address common.Address, filterer bind.ContractFilterer) (*ShuttereventtriggerregistryFilterer, error) { - contract, err := bindShuttereventtriggerregistry(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &ShuttereventtriggerregistryFilterer{contract: contract}, nil -} - -// bindShuttereventtriggerregistry binds a generic wrapper to an already deployed contract. -func bindShuttereventtriggerregistry(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := ShuttereventtriggerregistryMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Shuttereventtriggerregistry.Contract.ShuttereventtriggerregistryCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Shuttereventtriggerregistry.Contract.ShuttereventtriggerregistryTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Shuttereventtriggerregistry.Contract.ShuttereventtriggerregistryTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Shuttereventtriggerregistry.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Shuttereventtriggerregistry.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Shuttereventtriggerregistry.Contract.contract.Transact(opts, method, params...) -} - -// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. -// -// Solidity: function owner() view returns(address) -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _Shuttereventtriggerregistry.contract.Call(opts, &out, "owner") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. -// -// Solidity: function owner() view returns(address) -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistrySession) Owner() (common.Address, error) { - return _Shuttereventtriggerregistry.Contract.Owner(&_Shuttereventtriggerregistry.CallOpts) -} - -// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. -// -// Solidity: function owner() view returns(address) -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryCallerSession) Owner() (common.Address, error) { - return _Shuttereventtriggerregistry.Contract.Owner(&_Shuttereventtriggerregistry.CallOpts) -} - -// Registrations is a free data retrieval call binding the contract method 0xda7c6a42. -// -// Solidity: function registrations(bytes32 identity) view returns(uint64 eon, uint64 ttl, bytes32 triggerDefinitionHash) -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryCaller) Registrations(opts *bind.CallOpts, identity [32]byte) (struct { - Eon uint64 - Ttl uint64 - TriggerDefinitionHash [32]byte -}, error) { - var out []interface{} - err := _Shuttereventtriggerregistry.contract.Call(opts, &out, "registrations", identity) - - outstruct := new(struct { - Eon uint64 - Ttl uint64 - TriggerDefinitionHash [32]byte - }) - if err != nil { - return *outstruct, err - } - - outstruct.Eon = *abi.ConvertType(out[0], new(uint64)).(*uint64) - outstruct.Ttl = *abi.ConvertType(out[1], new(uint64)).(*uint64) - outstruct.TriggerDefinitionHash = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte) - - return *outstruct, err - -} - -// Registrations is a free data retrieval call binding the contract method 0xda7c6a42. -// -// Solidity: function registrations(bytes32 identity) view returns(uint64 eon, uint64 ttl, bytes32 triggerDefinitionHash) -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistrySession) Registrations(identity [32]byte) (struct { - Eon uint64 - Ttl uint64 - TriggerDefinitionHash [32]byte -}, error) { - return _Shuttereventtriggerregistry.Contract.Registrations(&_Shuttereventtriggerregistry.CallOpts, identity) -} - -// Registrations is a free data retrieval call binding the contract method 0xda7c6a42. -// -// Solidity: function registrations(bytes32 identity) view returns(uint64 eon, uint64 ttl, bytes32 triggerDefinitionHash) -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryCallerSession) Registrations(identity [32]byte) (struct { - Eon uint64 - Ttl uint64 - TriggerDefinitionHash [32]byte -}, error) { - return _Shuttereventtriggerregistry.Contract.Registrations(&_Shuttereventtriggerregistry.CallOpts, identity) -} - -// Register is a paid mutator transaction binding the contract method 0xd48b6d1e. -// -// Solidity: function register(uint64 eon, bytes32 identityPrefix, bytes triggerDefinition, uint64 ttl) returns() -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryTransactor) Register(opts *bind.TransactOpts, eon uint64, identityPrefix [32]byte, triggerDefinition []byte, ttl uint64) (*types.Transaction, error) { - return _Shuttereventtriggerregistry.contract.Transact(opts, "register", eon, identityPrefix, triggerDefinition, ttl) -} - -// Register is a paid mutator transaction binding the contract method 0xd48b6d1e. -// -// Solidity: function register(uint64 eon, bytes32 identityPrefix, bytes triggerDefinition, uint64 ttl) returns() -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistrySession) Register(eon uint64, identityPrefix [32]byte, triggerDefinition []byte, ttl uint64) (*types.Transaction, error) { - return _Shuttereventtriggerregistry.Contract.Register(&_Shuttereventtriggerregistry.TransactOpts, eon, identityPrefix, triggerDefinition, ttl) -} - -// Register is a paid mutator transaction binding the contract method 0xd48b6d1e. -// -// Solidity: function register(uint64 eon, bytes32 identityPrefix, bytes triggerDefinition, uint64 ttl) returns() -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryTransactorSession) Register(eon uint64, identityPrefix [32]byte, triggerDefinition []byte, ttl uint64) (*types.Transaction, error) { - return _Shuttereventtriggerregistry.Contract.Register(&_Shuttereventtriggerregistry.TransactOpts, eon, identityPrefix, triggerDefinition, ttl) -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Shuttereventtriggerregistry.contract.Transact(opts, "renounceOwnership") -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistrySession) RenounceOwnership() (*types.Transaction, error) { - return _Shuttereventtriggerregistry.Contract.RenounceOwnership(&_Shuttereventtriggerregistry.TransactOpts) -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryTransactorSession) RenounceOwnership() (*types.Transaction, error) { - return _Shuttereventtriggerregistry.Contract.RenounceOwnership(&_Shuttereventtriggerregistry.TransactOpts) -} - -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { - return _Shuttereventtriggerregistry.contract.Transact(opts, "transferOwnership", newOwner) -} - -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistrySession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { - return _Shuttereventtriggerregistry.Contract.TransferOwnership(&_Shuttereventtriggerregistry.TransactOpts, newOwner) -} - -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { - return _Shuttereventtriggerregistry.Contract.TransferOwnership(&_Shuttereventtriggerregistry.TransactOpts, newOwner) -} - -// ShuttereventtriggerregistryEventTriggerRegisteredIterator is returned from FilterEventTriggerRegistered and is used to iterate over the raw logs and unpacked data for EventTriggerRegistered events raised by the Shuttereventtriggerregistry contract. -type ShuttereventtriggerregistryEventTriggerRegisteredIterator struct { - Event *ShuttereventtriggerregistryEventTriggerRegistered // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *ShuttereventtriggerregistryEventTriggerRegisteredIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(ShuttereventtriggerregistryEventTriggerRegistered) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(ShuttereventtriggerregistryEventTriggerRegistered) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *ShuttereventtriggerregistryEventTriggerRegisteredIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *ShuttereventtriggerregistryEventTriggerRegisteredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// ShuttereventtriggerregistryEventTriggerRegistered represents a EventTriggerRegistered event raised by the Shuttereventtriggerregistry contract. -type ShuttereventtriggerregistryEventTriggerRegistered struct { - Eon uint64 - IdentityPrefix [32]byte - Sender common.Address - TriggerDefinition []byte - Ttl uint64 - Raw types.Log // Blockchain specific contextual infos -} - -// FilterEventTriggerRegistered is a free log retrieval operation binding the contract event 0x06809c10c5d53027eb51ca4ec6da8fbfd54d79f41cdefaab2cb142d10b039db5. -// -// Solidity: event EventTriggerRegistered(uint64 indexed eon, bytes32 identityPrefix, address sender, bytes triggerDefinition, uint64 ttl) -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryFilterer) FilterEventTriggerRegistered(opts *bind.FilterOpts, eon []uint64) (*ShuttereventtriggerregistryEventTriggerRegisteredIterator, error) { - - var eonRule []interface{} - for _, eonItem := range eon { - eonRule = append(eonRule, eonItem) - } - - logs, sub, err := _Shuttereventtriggerregistry.contract.FilterLogs(opts, "EventTriggerRegistered", eonRule) - if err != nil { - return nil, err - } - return &ShuttereventtriggerregistryEventTriggerRegisteredIterator{contract: _Shuttereventtriggerregistry.contract, event: "EventTriggerRegistered", logs: logs, sub: sub}, nil -} - -// WatchEventTriggerRegistered is a free log subscription operation binding the contract event 0x06809c10c5d53027eb51ca4ec6da8fbfd54d79f41cdefaab2cb142d10b039db5. -// -// Solidity: event EventTriggerRegistered(uint64 indexed eon, bytes32 identityPrefix, address sender, bytes triggerDefinition, uint64 ttl) -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryFilterer) WatchEventTriggerRegistered(opts *bind.WatchOpts, sink chan<- *ShuttereventtriggerregistryEventTriggerRegistered, eon []uint64) (event.Subscription, error) { - - var eonRule []interface{} - for _, eonItem := range eon { - eonRule = append(eonRule, eonItem) - } - - logs, sub, err := _Shuttereventtriggerregistry.contract.WatchLogs(opts, "EventTriggerRegistered", eonRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(ShuttereventtriggerregistryEventTriggerRegistered) - if err := _Shuttereventtriggerregistry.contract.UnpackLog(event, "EventTriggerRegistered", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseEventTriggerRegistered is a log parse operation binding the contract event 0x06809c10c5d53027eb51ca4ec6da8fbfd54d79f41cdefaab2cb142d10b039db5. -// -// Solidity: event EventTriggerRegistered(uint64 indexed eon, bytes32 identityPrefix, address sender, bytes triggerDefinition, uint64 ttl) -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryFilterer) ParseEventTriggerRegistered(log types.Log) (*ShuttereventtriggerregistryEventTriggerRegistered, error) { - event := new(ShuttereventtriggerregistryEventTriggerRegistered) - if err := _Shuttereventtriggerregistry.contract.UnpackLog(event, "EventTriggerRegistered", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// ShuttereventtriggerregistryOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the Shuttereventtriggerregistry contract. -type ShuttereventtriggerregistryOwnershipTransferredIterator struct { - Event *ShuttereventtriggerregistryOwnershipTransferred // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *ShuttereventtriggerregistryOwnershipTransferredIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(ShuttereventtriggerregistryOwnershipTransferred) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(ShuttereventtriggerregistryOwnershipTransferred) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *ShuttereventtriggerregistryOwnershipTransferredIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *ShuttereventtriggerregistryOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// ShuttereventtriggerregistryOwnershipTransferred represents a OwnershipTransferred event raised by the Shuttereventtriggerregistry contract. -type ShuttereventtriggerregistryOwnershipTransferred struct { - PreviousOwner common.Address - NewOwner common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. -// -// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*ShuttereventtriggerregistryOwnershipTransferredIterator, error) { - - var previousOwnerRule []interface{} - for _, previousOwnerItem := range previousOwner { - previousOwnerRule = append(previousOwnerRule, previousOwnerItem) - } - var newOwnerRule []interface{} - for _, newOwnerItem := range newOwner { - newOwnerRule = append(newOwnerRule, newOwnerItem) - } - - logs, sub, err := _Shuttereventtriggerregistry.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) - if err != nil { - return nil, err - } - return &ShuttereventtriggerregistryOwnershipTransferredIterator{contract: _Shuttereventtriggerregistry.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. -// -// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *ShuttereventtriggerregistryOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { - - var previousOwnerRule []interface{} - for _, previousOwnerItem := range previousOwner { - previousOwnerRule = append(previousOwnerRule, previousOwnerItem) - } - var newOwnerRule []interface{} - for _, newOwnerItem := range newOwner { - newOwnerRule = append(newOwnerRule, newOwnerItem) - } - - logs, sub, err := _Shuttereventtriggerregistry.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(ShuttereventtriggerregistryOwnershipTransferred) - if err := _Shuttereventtriggerregistry.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. -// -// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -func (_Shuttereventtriggerregistry *ShuttereventtriggerregistryFilterer) ParseOwnershipTransferred(log types.Log) (*ShuttereventtriggerregistryOwnershipTransferred, error) { - event := new(ShuttereventtriggerregistryOwnershipTransferred) - if err := _Shuttereventtriggerregistry.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} From 49bd96d747433154ac9700b487d21ae90f7c0080 Mon Sep 17 00:00:00 2001 From: Jannik Date: Fri, 10 Jul 2026 18:53:27 +0200 Subject: [PATCH 22/25] feat: add dkg deploy and status script --- script/AddKeyperSet.v2.s.sol | 81 ++++ script/DKGState.s.sol | 831 +++++++++++++++++++++++++++++++++++ 2 files changed, 912 insertions(+) create mode 100644 script/AddKeyperSet.v2.s.sol create mode 100644 script/DKGState.s.sol diff --git a/script/AddKeyperSet.v2.s.sol b/script/AddKeyperSet.v2.s.sol new file mode 100644 index 0000000..ec8a221 --- /dev/null +++ b/script/AddKeyperSet.v2.s.sol @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.22; + +import "forge-std/Script.sol"; +import {KeyperSet} from "../src/common/KeyperSet.sol"; +import {KeyperSetManager} from "../src/common/KeyperSetManager.sol"; +import {KeyBroadcastContract} from "../src/common/KeyBroadcastContract.sol"; + +/// Variant of AddKeyperSet that wires the DKG contract itself as the +/// KeyBroadcastContract publisher. The old script deployed a separate +/// EonKeyPublish aggregator; with the current DKGContract this is +/// redundant, because submitSuccessVote already tallies votes and, on +/// crossing threshold, attempts KeyBroadcastContract.broadcastEonKey via +/// try/catch. Setting publisher = address(dkg) lets that broadcast succeed, +/// so the eon key ends up in KBC as a side effect of the last success vote +/// and no extra contract is needed. + +error ActivationDeltaTooLow(); +error ThresholdExceedsKeyperSetSize(uint256 threshold, uint256 keyperSetSize); +error UnexpectedKeyperSet( + uint256 index, + address expectedKeyperSet, + address actualKeyperSet +); + +contract AddKeyperSetV2 is Script { + function run() public { + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + address deployerAddress = vm.addr(deployerPrivateKey); + console.log("deployer:", deployerAddress); + vm.startBroadcast(deployerPrivateKey); + + uint256 activationDelta = vm.envOr("ACTIVATION_DELTA", uint256(1)); + if (activationDelta < 1) { + revert ActivationDeltaTooLow(); + } + + address keyperSetManagerAddress = vm.envAddress( + "KEYPERSETMANAGER_ADDRESS" + ); + KeyperSetManager keyperSetManager = KeyperSetManager( + keyperSetManagerAddress + ); + + address dkgContract = vm.envAddress("DKG_CONTRACT_ADDRESS"); + + address[] memory keypers = vm.envAddress("KEYPER_ADDRESSES", ","); + uint256 threshold = vm.envUint("THRESHOLD"); + if (threshold > keypers.length) { + revert ThresholdExceedsKeyperSetSize(threshold, keypers.length); + } + + uint64 keyperSetIndex = keyperSetManager.getNumKeyperSets(); + KeyperSet keyperSet = new KeyperSet(); + keyperSet.addMembers(keypers); + keyperSet.setThreshold(uint64(threshold)); + keyperSet.setPublisher(dkgContract); + keyperSet.setDKGContract(dkgContract); + keyperSet.setFinalized(); + console.log("keyperSet:", address(keyperSet)); + console.log("publisher (= dkgContract):", dkgContract); + + uint64 activationBlock = uint64(block.number + activationDelta); + keyperSetManager.addKeyperSet(activationBlock, address(keyperSet)); + console.log("activationBlock:", activationBlock); + console.log("keyperSetIndex:", keyperSetIndex); + + address actualKeyperSet = keyperSetManager.getKeyperSetAddress( + keyperSetIndex + ); + if (actualKeyperSet != address(keyperSet)) { + revert UnexpectedKeyperSet( + keyperSetIndex, + address(keyperSet), + actualKeyperSet + ); + } + + vm.stopBroadcast(); + } +} diff --git a/script/DKGState.s.sol b/script/DKGState.s.sol new file mode 100644 index 0000000..a053ddb --- /dev/null +++ b/script/DKGState.s.sol @@ -0,0 +1,831 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.22; + +import "forge-std/Script.sol"; +import {Vm} from "forge-std/Vm.sol"; +import {KeyperSet} from "../src/common/KeyperSet.sol"; +import {KeyperSetManager} from "../src/common/KeyperSetManager.sol"; +import {DKGContract} from "../src/common/DKGContract.sol"; +import {KeyBroadcastContract} from "../src/common/KeyBroadcastContract.sol"; +import {IDKGContract} from "../src/common/intf/IDKGContract.sol"; + +contract DKGState is Script { + bytes32 constant SIG_DEALING = + keccak256("DealingSubmitted(uint64,uint64,uint64,bytes,bytes[])"); + bytes32 constant SIG_ACCUSATION = + keccak256("AccusationSubmitted(uint64,uint64,uint64,uint64[])"); + bytes32 constant SIG_APOLOGY = + keccak256("ApologySubmitted(uint64,uint64,uint64,uint64[],bytes[])"); + bytes32 constant SIG_SUCCESS_VOTE = + keccak256("SuccessVoteSubmitted(uint64,uint64,uint64,bytes)"); + bytes32 constant SIG_DKG_SUCCEEDED = + keccak256("DKGSucceeded(uint64,uint64,bytes)"); + + struct Ctx { + address managerAddr; + uint64 setIndex; + uint64 numKeyperSets; + uint64 activationBlock; + address keyperSetAddr; + address[] members; + uint64 threshold; + address publisher; + bool finalized; + address dkgAddr; + uint64 phaseLength; + uint64 dkgLeadLength; + uint64 cycleLen; + int256 dkgStart0; + bool succeededFlag; + address keyBroadcastAddr; + bytes broadcastedKey; + uint256 currentBlock; + } + + struct Logs { + Vm.EthGetLogs[] dealing; + Vm.EthGetLogs[] accusation; + Vm.EthGetLogs[] apology; + Vm.EthGetLogs[] vote; + Vm.EthGetLogs[] success; + } + + // First-seen order of unique eon-key hashes across fetched vote+success + // events. A key's label is its index in this list. + struct KeyReg { + bytes32[] hashes; + } + + function run() external { + Ctx memory ctx = loadContext(); + printHeader(ctx); + Logs memory logs = fetchLogs(ctx); + KeyReg memory reg = buildKeyReg(logs); + printKeyBroadcastLine(ctx, reg); + printCurrentContext(ctx); + printBody(ctx, logs, reg); + } + + // ---------------- context load ---------------- + + function loadContext() internal returns (Ctx memory ctx) { + ctx.managerAddr = vm.envAddress("KEYPERSETMANAGER_ADDRESS"); + ctx.setIndex = uint64(vm.envUint("KEYPER_SET_INDEX")); + + KeyperSetManager manager = KeyperSetManager(ctx.managerAddr); + ctx.numKeyperSets = manager.getNumKeyperSets(); + if (ctx.setIndex >= ctx.numKeyperSets) { + revert( + string.concat( + "KEYPER_SET_INDEX=", + vm.toString(uint256(ctx.setIndex)), + " out of range (numKeyperSets=", + vm.toString(uint256(ctx.numKeyperSets)), + " on this RPC; valid indices 0..", + ctx.numKeyperSets == 0 + ? "(none)" + : vm.toString(uint256(ctx.numKeyperSets - 1)), + ")" + ) + ); + } + ctx.activationBlock = manager.getKeyperSetActivationBlock(ctx.setIndex); + ctx.keyperSetAddr = manager.getKeyperSetAddress(ctx.setIndex); + + KeyperSet ks = KeyperSet(ctx.keyperSetAddr); + ctx.members = ks.getMembers(); + ctx.threshold = ks.getThreshold(); + ctx.publisher = ks.getPublisher(); + ctx.finalized = ks.isFinalized(); + ctx.dkgAddr = ks.getDKGContract(); + + DKGContract dkg = DKGContract(ctx.dkgAddr); + ctx.phaseLength = dkg.PHASE_LENGTH(); + ctx.dkgLeadLength = dkg.DKG_LEAD_LENGTH(); + ctx.cycleLen = dkg.cycleLength(); + ctx.dkgStart0 = dkg.dkgStart(ctx.setIndex, 0); + ctx.succeededFlag = dkg.succeeded(ctx.setIndex); + ctx.keyBroadcastAddr = dkg.keyBroadcastContract(); + + if (ctx.keyBroadcastAddr != address(0)) { + KeyBroadcastContract kb = KeyBroadcastContract( + ctx.keyBroadcastAddr + ); + ctx.broadcastedKey = kb.getEonKey(ctx.setIndex); + } + ctx.currentBlock = block.number; + } + + // ---------------- header ---------------- + + function printHeader(Ctx memory c) internal view { + console.log("=== DKG State ==="); + console.log(""); + console.log("KeyperSetManager: ", c.managerAddr); + console.log(" numKeyperSets: ", uint256(c.numKeyperSets)); + console.log(""); + console.log( + string.concat( + "Keyper set: index ", + vm.toString(uint256(c.setIndex)) + ) + ); + console.log(" contract: ", c.keyperSetAddr); + console.log(" finalized: ", c.finalized); + console.log(" threshold: ", uint256(c.threshold)); + console.log(" publisher: ", c.publisher); + console.log(" DKG contract: ", c.dkgAddr); + console.log(" activation block: ", uint256(c.activationBlock)); + console.log( + string.concat( + " members (", + vm.toString(c.members.length), + "):" + ) + ); + for (uint256 i = 0; i < c.members.length; i++) { + console.log( + string.concat( + " [", + vm.toString(i), + "] ", + vm.toString(c.members[i]) + ) + ); + } + console.log(""); + console.log("DKG contract config:"); + console.log(" PHASE_LENGTH: ", uint256(c.phaseLength)); + console.log(" DKG_LEAD_LENGTH: ", uint256(c.dkgLeadLength)); + console.log(" cycleLength: ", uint256(c.cycleLen)); + console.log( + string.concat(" dkgStart(index,0): ", _intToString(c.dkgStart0)) + ); + console.log(" succeeded[index]: ", c.succeededFlag); + console.log(""); + console.log("KeyBroadcastContract: ", c.keyBroadcastAddr); + } + + function printKeyBroadcastLine( + Ctx memory c, + KeyReg memory reg + ) internal view { + if (c.keyBroadcastAddr == address(0)) { + console.log(" eon key broadcast: (KeyBroadcastContract unset)"); + return; + } + if (c.broadcastedKey.length == 0) { + console.log(" eon key broadcast: (none)"); + } else { + bytes32 h = keccak256(c.broadcastedKey); + string memory desc = _keyDesc(reg, h); + console.log( + string.concat(" eon key broadcast: ", desc) + ); + } + } + + function printCurrentContext(Ctx memory c) internal view { + console.log(""); + console.log("Chain context:"); + console.log(" current block: ", c.currentBlock); + int256 curR = _currentRetry(c); + if (curR < 0) { + console.log(" current retry: (DKG has not started yet)"); + return; + } + console.log(" current retry: ", uint256(curR)); + if (c.succeededFlag) { + console.log( + " current phase: (DKG already succeeded; no active phase)" + ); + return; + } + uint256 retryStart = _retryStartBlock(c, uint64(uint256(curR))); + uint256 offset = c.currentBlock - retryStart; + uint256 phaseIdx = offset / uint256(c.phaseLength); + uint256 blocksInto = offset % uint256(c.phaseLength); + string memory phaseName; + if (phaseIdx == 0) phaseName = "Dealing"; + else if (phaseIdx == 1) phaseName = "Accusing"; + else if (phaseIdx == 2) phaseName = "Apologizing"; + else phaseName = "Finalizing"; + console.log( + string.concat( + " current phase: ", + phaseName, + " (block ", + vm.toString(blocksInto + 1), + " of ", + vm.toString(uint256(c.phaseLength)), + ")" + ) + ); + } + + // ---------------- fetch logs ---------------- + + function fetchLogs(Ctx memory ctx) internal returns (Logs memory logs) { + uint256 fromBlock = ctx.dkgStart0 < 0 + ? 0 + : uint256(ctx.dkgStart0); + uint256 toBlock = ctx.currentBlock; + if (fromBlock > toBlock) { + logs.dealing = new Vm.EthGetLogs[](0); + logs.accusation = new Vm.EthGetLogs[](0); + logs.apology = new Vm.EthGetLogs[](0); + logs.vote = new Vm.EthGetLogs[](0); + logs.success = new Vm.EthGetLogs[](0); + return logs; + } + bytes32 setIdxTopic = bytes32(uint256(ctx.setIndex)); + logs.dealing = _fetch( + fromBlock, + toBlock, + ctx.dkgAddr, + SIG_DEALING, + setIdxTopic + ); + logs.accusation = _fetch( + fromBlock, + toBlock, + ctx.dkgAddr, + SIG_ACCUSATION, + setIdxTopic + ); + logs.apology = _fetch( + fromBlock, + toBlock, + ctx.dkgAddr, + SIG_APOLOGY, + setIdxTopic + ); + logs.vote = _fetch( + fromBlock, + toBlock, + ctx.dkgAddr, + SIG_SUCCESS_VOTE, + setIdxTopic + ); + logs.success = _fetch( + fromBlock, + toBlock, + ctx.dkgAddr, + SIG_DKG_SUCCEEDED, + setIdxTopic + ); + } + + function _fetch( + uint256 fromB, + uint256 toB, + address emitter, + bytes32 sig, + bytes32 setIdxTopic + ) internal returns (Vm.EthGetLogs[] memory) { + bytes32[] memory topics = new bytes32[](2); + topics[0] = sig; + topics[1] = setIdxTopic; + return vm.eth_getLogs(fromB, toB, emitter, topics); + } + + // ---------------- key registry ---------------- + + function buildKeyReg( + Logs memory logs + ) internal pure returns (KeyReg memory reg) { + uint256 maxCount = logs.vote.length + logs.success.length; + bytes32[] memory buf = new bytes32[](maxCount); + uint256 n = 0; + for (uint256 i = 0; i < logs.vote.length; i++) { + bytes memory k = abi.decode(logs.vote[i].data, (bytes)); + bytes32 h = keccak256(k); + if (!_contains(buf, n, h)) { + buf[n++] = h; + } + } + for (uint256 i = 0; i < logs.success.length; i++) { + bytes memory k = abi.decode(logs.success[i].data, (bytes)); + bytes32 h = keccak256(k); + if (!_contains(buf, n, h)) { + buf[n++] = h; + } + } + bytes32[] memory out = new bytes32[](n); + for (uint256 i = 0; i < n; i++) out[i] = buf[i]; + reg.hashes = out; + } + + function _contains( + bytes32[] memory arr, + uint256 len, + bytes32 v + ) internal pure returns (bool) { + for (uint256 i = 0; i < len; i++) if (arr[i] == v) return true; + return false; + } + + function _labelOf( + KeyReg memory reg, + bytes32 keyHash + ) internal pure returns (int256) { + for (uint256 i = 0; i < reg.hashes.length; i++) { + if (reg.hashes[i] == keyHash) return int256(i); + } + return -1; + } + + function _keyDesc( + KeyReg memory reg, + bytes32 keyHash + ) internal pure returns (string memory) { + int256 idx = _labelOf(reg, keyHash); + if (idx < 0) return "unknown key (not seen in votes)"; + if (reg.hashes.length <= 1) return "the eon key"; + return string.concat("KEY#", vm.toString(uint256(idx))); + } + + // ---------------- body ---------------- + + function printBody( + Ctx memory c, + Logs memory logs, + KeyReg memory reg + ) internal view { + console.log(""); + console.log("--- Retries ---"); + + int256 currentRetry = _currentRetry(c); + if (currentRetry < 0) { + console.log("(no retries have started yet)"); + return; + } + + int256 succeededAtRetry = -1; + for (uint256 i = 0; i < logs.success.length; i++) { + int256 r = int256( + uint256(uint64(uint256(logs.success[i].topics[2]))) + ); + if (succeededAtRetry < 0 || r < succeededAtRetry) { + succeededAtRetry = r; + } + } + if (c.succeededFlag && succeededAtRetry < 0) { + console.log( + "WARNING: succeeded[index] is true but no DKGSucceeded event" + ); + console.log( + " was fetched in the query range. Iterating to current retry." + ); + } + int256 lastRetry = succeededAtRetry >= 0 + ? succeededAtRetry + : currentRetry; + + int256 condStart = -1; + int256 condEnd = -1; + for (int256 r = 0; r <= lastRetry; r++) { + bool inProgress = (r == currentRetry) && !c.succeededFlag; + uint64 ru = uint64(uint256(r)); + bool hasEvents = _retryHasEvents(logs, ru); + if (!hasEvents && !inProgress) { + if (condStart < 0) condStart = r; + condEnd = r; + continue; + } + if (condStart >= 0) { + _printCondensed(condStart, condEnd); + condStart = -1; + } + _printRetry(c, logs, reg, ru, inProgress, ru == uint64(uint256(succeededAtRetry >= 0 ? succeededAtRetry : int256(-1)))); + } + if (condStart >= 0) _printCondensed(condStart, condEnd); + } + + function _printCondensed(int256 startR, int256 endR) internal view { + if (startR == endR) { + console.log( + string.concat( + "Retry ", + vm.toString(uint256(startR)), + ": no messages" + ) + ); + } else { + console.log( + string.concat( + "Retries ", + vm.toString(uint256(startR)), + "-", + vm.toString(uint256(endR)), + ": no messages" + ) + ); + } + } + + function _printRetry( + Ctx memory c, + Logs memory logs, + KeyReg memory reg, + uint64 r, + bool inProgress, + bool succeededHere + ) internal view { + console.log(""); + uint256 startB = _retryStartBlock(c, r); + uint256 endB = startB + uint256(c.cycleLen) - 1; + string memory tag; + if (succeededHere) tag = " [SUCCEEDED]"; + else if (inProgress) tag = " [current]"; + else tag = ""; + console.log( + string.concat( + "Retry ", + vm.toString(uint256(r)), + " (blocks ", + vm.toString(startB), + "-", + vm.toString(endB), + ")", + tag + ) + ); + _printPhaseWindows(c, startB, inProgress); + _printDealings(c, logs, r); + _printAccusations(c, logs, r); + _printApologies(c, logs, r); + _printVotes(c, logs, reg, r, succeededHere); + } + + function _printPhaseWindows( + Ctx memory c, + uint256 startB, + bool inProgress + ) internal view { + uint256 pl = uint256(c.phaseLength); + if (!inProgress) { + console.log( + string.concat( + " Phases: Dealing ", + vm.toString(startB), + "-", + vm.toString(startB + pl - 1), + " | Accusing ", + vm.toString(startB + pl), + "-", + vm.toString(startB + 2 * pl - 1), + " | Apologizing ", + vm.toString(startB + 2 * pl), + "-", + vm.toString(startB + 3 * pl - 1), + " | Finalizing ", + vm.toString(startB + 3 * pl), + "-", + vm.toString(startB + 4 * pl - 1) + ) + ); + } else { + uint256 offset = c.currentBlock - startB; + uint256 phaseIdx = offset / pl; + uint256 blocksInto = offset % pl; + string memory phaseName; + if (phaseIdx == 0) phaseName = "Dealing"; + else if (phaseIdx == 1) phaseName = "Accusing"; + else if (phaseIdx == 2) phaseName = "Apologizing"; + else phaseName = "Finalizing"; + console.log( + string.concat( + " Currently in ", + phaseName, + " phase (block ", + vm.toString(blocksInto + 1), + " of ", + vm.toString(pl), + ")" + ) + ); + } + } + + function _printDealings( + Ctx memory c, + Logs memory logs, + uint64 r + ) internal view { + uint256 total = c.members.length; + bool[] memory submitted = new bool[](total); + uint256 count = 0; + for (uint256 i = 0; i < logs.dealing.length; i++) { + if (uint64(uint256(logs.dealing[i].topics[2])) != r) continue; + uint64 keyperIdx = uint64(uint256(logs.dealing[i].topics[3])); + if (keyperIdx < total && !submitted[keyperIdx]) { + submitted[keyperIdx] = true; + count++; + } + } + if (count == 0) { + console.log( + string.concat( + " Dealings: none (0/", + vm.toString(total), + ")" + ) + ); + return; + } + console.log( + string.concat( + " Dealings (", + vm.toString(count), + "/", + vm.toString(total), + "):" + ) + ); + console.log( + string.concat(" submitted: ", _indexList(submitted, true)) + ); + if (count < total) { + console.log( + string.concat(" SILENT: ", _indexList(submitted, false)) + ); + } + } + + function _printAccusations( + Ctx memory, + Logs memory logs, + uint64 r + ) internal view { + uint256 n = 0; + for (uint256 i = 0; i < logs.accusation.length; i++) { + if (uint64(uint256(logs.accusation[i].topics[2])) == r) n++; + } + if (n == 0) { + console.log(" Accusations: none"); + return; + } + console.log(string.concat(" Accusations (", vm.toString(n), "):")); + for (uint256 i = 0; i < logs.accusation.length; i++) { + if (uint64(uint256(logs.accusation[i].topics[2])) != r) continue; + uint64 accuser = uint64( + uint256(logs.accusation[i].topics[3]) + ); + uint64[] memory accused = abi.decode( + logs.accusation[i].data, + (uint64[]) + ); + console.log( + string.concat( + " keyper[", + vm.toString(uint256(accuser)), + "] accused ", + _uint64ListToString(accused) + ) + ); + } + } + + function _printApologies( + Ctx memory, + Logs memory logs, + uint64 r + ) internal view { + uint256 n = 0; + for (uint256 i = 0; i < logs.apology.length; i++) { + if (uint64(uint256(logs.apology[i].topics[2])) == r) n++; + } + if (n == 0) { + console.log(" Apologies: none"); + return; + } + console.log(string.concat(" Apologies (", vm.toString(n), "):")); + for (uint256 i = 0; i < logs.apology.length; i++) { + if (uint64(uint256(logs.apology[i].topics[2])) != r) continue; + uint64 apologizer = uint64( + uint256(logs.apology[i].topics[3]) + ); + (uint64[] memory accusers, ) = abi.decode( + logs.apology[i].data, + (uint64[], bytes[]) + ); + console.log( + string.concat( + " keyper[", + vm.toString(uint256(apologizer)), + "] apologized to ", + _uint64ListToString(accusers) + ) + ); + } + } + + struct VoteTally { + uint256[] tallies; + bool[][] voterByKey; + bool[] voted; + uint256 votedCount; + } + + function _tallyVotes( + Ctx memory c, + Logs memory logs, + KeyReg memory reg, + uint64 r + ) internal pure returns (VoteTally memory t) { + uint256 total = c.members.length; + uint256 numKeys = reg.hashes.length; + t.tallies = new uint256[](numKeys); + t.voterByKey = new bool[][](numKeys); + for (uint256 k = 0; k < numKeys; k++) { + t.voterByKey[k] = new bool[](total); + } + t.voted = new bool[](total); + for (uint256 i = 0; i < logs.vote.length; i++) { + if (uint64(uint256(logs.vote[i].topics[2])) != r) continue; + uint64 keyperIdx = uint64(uint256(logs.vote[i].topics[3])); + if (keyperIdx >= total) continue; + bytes memory k = abi.decode(logs.vote[i].data, (bytes)); + int256 label = _labelOf(reg, keccak256(k)); + if (label < 0) continue; + uint256 li = uint256(label); + if (!t.voted[keyperIdx]) { + t.voted[keyperIdx] = true; + t.votedCount++; + } + if (!t.voterByKey[li][keyperIdx]) { + t.voterByKey[li][keyperIdx] = true; + t.tallies[li]++; + } + } + } + + function _successKeyHash( + Logs memory logs, + uint64 r + ) internal pure returns (bytes32) { + for (uint256 i = 0; i < logs.success.length; i++) { + if (uint64(uint256(logs.success[i].topics[2])) == r) { + bytes memory k = abi.decode(logs.success[i].data, (bytes)); + return keccak256(k); + } + } + return bytes32(0); + } + + function _printVotes( + Ctx memory c, + Logs memory logs, + KeyReg memory reg, + uint64 r, + bool succeededHere + ) internal view { + VoteTally memory t = _tallyVotes(c, logs, reg, r); + bytes32 successHash = _successKeyHash(logs, r); + uint256 total = c.members.length; + + if (t.votedCount == 0 && !succeededHere) { + console.log( + string.concat( + " Success votes: none (threshold ", + vm.toString(uint256(c.threshold)), + ")" + ) + ); + return; + } + console.log( + string.concat( + " Success votes (", + vm.toString(t.votedCount), + "/", + vm.toString(total), + ", threshold ", + vm.toString(uint256(c.threshold)), + "):" + ) + ); + for (uint256 li = 0; li < reg.hashes.length; li++) { + if (t.tallies[li] == 0) continue; + _printOneKeyTally(reg, t, li, successHash); + } + if (t.votedCount < total) { + console.log( + string.concat(" NON-VOTERS: ", _indexList(t.voted, false)) + ); + } + if (succeededHere) { + console.log( + string.concat( + " Outcome: DKGSucceeded emitted (", + _keyDesc(reg, successHash), + ")" + ) + ); + } + } + + function _printOneKeyTally( + KeyReg memory reg, + VoteTally memory t, + uint256 li, + bytes32 successHash + ) internal view { + string memory winnerMark = (successHash != bytes32(0) && + reg.hashes[li] == successHash) + ? " <- SUCCEEDED" + : ""; + console.log( + string.concat( + " ", + _keyDesc(reg, reg.hashes[li]), + ": ", + vm.toString(t.tallies[li]), + " votes", + winnerMark + ) + ); + console.log( + string.concat( + " voters: ", + _indexList(t.voterByKey[li], true) + ) + ); + } + + // ---------------- helpers ---------------- + + function _currentRetry(Ctx memory c) internal pure returns (int256) { + int256 rel = int256(c.currentBlock) - c.dkgStart0; + if (rel < 0) return -1; + return rel / int256(uint256(c.cycleLen)); + } + + function _retryStartBlock( + Ctx memory c, + uint64 r + ) internal pure returns (uint256) { + int256 s = c.dkgStart0 + int256(uint256(r)) * int256(uint256(c.cycleLen)); + // Caller must not invoke for retries with negative start; guarded by + // _currentRetry returning -1 upstream. + return uint256(s); + } + + function _retryHasEvents( + Logs memory logs, + uint64 r + ) internal pure returns (bool) { + return + _anyAt(logs.dealing, r) || + _anyAt(logs.accusation, r) || + _anyAt(logs.apology, r) || + _anyAt(logs.vote, r) || + _anyAt(logs.success, r); + } + + function _anyAt( + Vm.EthGetLogs[] memory arr, + uint64 r + ) internal pure returns (bool) { + for (uint256 i = 0; i < arr.length; i++) { + if (uint64(uint256(arr[i].topics[2])) == r) return true; + } + return false; + } + + function _indexList( + bool[] memory flags, + bool matchValue + ) internal pure returns (string memory) { + string memory out = ""; + bool first = true; + for (uint256 i = 0; i < flags.length; i++) { + if (flags[i] != matchValue) continue; + if (first) { + out = string.concat("[", vm.toString(i)); + first = false; + } else { + out = string.concat(out, ",", vm.toString(i)); + } + } + if (first) return "[]"; + return string.concat(out, "]"); + } + + function _uint64ListToString( + uint64[] memory xs + ) internal pure returns (string memory) { + if (xs.length == 0) return "[]"; + string memory out = string.concat("[", vm.toString(uint256(xs[0]))); + for (uint256 i = 1; i < xs.length; i++) { + out = string.concat(out, ",", vm.toString(uint256(xs[i]))); + } + return string.concat(out, "]"); + } + + function _intToString(int256 x) internal pure returns (string memory) { + if (x < 0) return string.concat("-", vm.toString(uint256(-x))); + return vm.toString(uint256(x)); + } +} From 029404fa82c4f20eea85b72f36f9deae6dfef844 Mon Sep 17 00:00:00 2001 From: Jannik Date: Tue, 14 Jul 2026 17:37:35 +0200 Subject: [PATCH 23/25] feat(dkg): bound DKG retries with MAX_RETRIES immutable Add `uint64 immutable MAX_RETRIES` as a new constructor arg on DKGContract. Valid retry counters are {0..MAX_RETRIES-1}; every submit fn reverts with MaxRetriesExceeded at or above the ceiling and currentPhase returns Phase.None for the same range. The constructor rejects maxRetries=0 with ZeroMaxRetries. Deploy.s.sol, Deploy.service.s.sol, and Deploy.gnosh.s.sol read a new DKG_MAX_RETRIES env var (default 10) and forward it to the constructor. DKGState.s.sol prints MAX_RETRIES alongside the other phase constants. Go bindings regenerated. Implements docs/dkg-max-retries/01-contract-enforcement-and-glossary.md. Keyper-side wiring lands in ticket 02. --- bindings/dkgcontract/dkgcontract.go | 39 +++++++- script/DKGState.s.sol | 3 + script/Deploy.gnosh.s.sol | 2 + script/Deploy.s.sol | 3 + script/Deploy.service.s.sol | 3 + src/common/DKGContract.sol | 22 +++++ test/DKGBenchmark.t.sol | 2 + test/DKGContract.t.sol | 141 ++++++++++++++++++++++++++++ test/ECIESKeyRegistry.t.sol | 1 + test/EonKeyPublish.t.sol | 1 + test/KeyBroadcastContract.t.sol | 1 + test/KeyperSetManager.t.sol | 2 + 12 files changed, 216 insertions(+), 4 deletions(-) diff --git a/bindings/dkgcontract/dkgcontract.go b/bindings/dkgcontract/dkgcontract.go index 2572047..f3c2f13 100644 --- a/bindings/dkgcontract/dkgcontract.go +++ b/bindings/dkgcontract/dkgcontract.go @@ -31,8 +31,8 @@ var ( // DkgcontractMetaData contains all meta data concerning the Dkgcontract contract. var DkgcontractMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"phaseLength\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"dkgLeadLength\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperSetManagerAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"keyBroadcastContractAddress\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"DKG_LEAD_LENGTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"PHASE_LENGTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"currentPhase\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumIDKGContract.Phase\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"cycleLength\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"dkgStart\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"int256\",\"internalType\":\"int256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"hasVoted\",\"inputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"keyBroadcastContract\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"keyperSetManager\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"submitAccusation\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"accusedIndices\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitApology\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"accuserIndices\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"polyEvalData\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitDealing\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"commitment\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"polyEvals\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitSuccessVote\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"eonPublicKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"succeeded\",\"inputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"voteCount\",\"inputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"AccusationSubmitted\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"accusedIndices\",\"type\":\"uint64[]\",\"indexed\":false,\"internalType\":\"uint64[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ApologySubmitted\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"accuserIndices\",\"type\":\"uint64[]\",\"indexed\":false,\"internalType\":\"uint64[]\"},{\"name\":\"polyEvalData\",\"type\":\"bytes[]\",\"indexed\":false,\"internalType\":\"bytes[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DKGSucceeded\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"eonPublicKey\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DealingSubmitted\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"commitment\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"polyEvals\",\"type\":\"bytes[]\",\"indexed\":false,\"internalType\":\"bytes[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SuccessVoteSubmitted\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"eonPublicKey\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AlreadySucceeded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AlreadyVoted\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"EmptyAccusation\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"EmptyEonPublicKey\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MismatchedArrays\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotKeyperAtIndex\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"WrongDKGContract\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"WrongPhase\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ZeroLengthParameter\",\"inputs\":[]}]", - Bin: "0x610100604052348015610010575f5ffd5b506040516120aa3803806120aa833981810160405281019061003291906101ce565b5f8467ffffffffffffffff16148061005357505f8367ffffffffffffffff16145b1561008a576040517f038016d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8367ffffffffffffffff1660808167ffffffffffffffff16815250508267ffffffffffffffff1660a08167ffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff168152505050505050610232565b5f5ffd5b5f67ffffffffffffffff82169050919050565b61015381610137565b811461015d575f5ffd5b50565b5f8151905061016e8161014a565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61019d82610174565b9050919050565b6101ad81610193565b81146101b7575f5ffd5b50565b5f815190506101c8816101a4565b92915050565b5f5f5f5f608085870312156101e6576101e5610133565b5b5f6101f387828801610160565b945050602061020487828801610160565b9350506040610215878288016101ba565b9250506060610226878288016101ba565b91505092959194509250565b60805160a05160c05160e051611e0d61029d5f395f81816109860152610b7901525f818161082501528181610b5201528181610cde01528181610ec9015261103801525f81816103c30152610d9f01525f818161030201528181610b2d0152610ba00152611e0d5ff3fe608060405234801561000f575f5ffd5b50600436106100e8575f3560e01c8063b209e7171161008a578063eac471a011610064578063eac471a014610248578063eb05c28014610266578063f01275b014610296578063f48f3d14146102b2576100e8565b8063b209e717146101ee578063d4b2cedd1461020c578063df6406311461022a576100e8565b80637642d0de116100c65780637642d0de1461015657806378a1b9db1461018657806382b870d3146101b657806394afc12d146101d2576100e8565b80630a3ec4d6146100ec57806316b89c3f1461011c5780633f9800981461013a575b5f5ffd5b610106600480360381019061010191906111f6565b6102e2565b60405161011391906112a7565b60405180910390f35b6101246103c1565b60405161013191906112cf565b60405180910390f35b610154600480360381019061014f919061139e565b6103e5565b005b610170600480360381019061016b91906114af565b610474565b60405161017d9190611519565b60405180910390f35b6101a0600480360381019061019b9190611532565b6104a9565b6040516101ad9190611519565b60405180910390f35b6101d060048036038101906101cb919061155d565b6104c5565b005b6101ec60048036038101906101e79190611636565b610a66565b005b6101f6610b2b565b60405161020391906112cf565b60405180910390f35b610214610b4f565b60405161022191906116c9565b60405180910390f35b610232610b76565b60405161023f91906116c9565b60405180910390f35b610250610b9d565b60405161025d91906112cf565b60405180910390f35b610280600480360381019061027b9190611715565b610bd0565b60405161028d91906112cf565b60405180910390f35b6102b060048036038101906102ab9190611765565b610c0c565b005b6102cc60048036038101906102c791906111f6565b610cda565b6040516102d99190611834565b60405180910390f35b5f5f6102ee8484610cda565b90505f81436102fd919061187a565b90505f7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1690505f821215610340575f93505050506103bb565b8082121561035457600193505050506103bb565b80600261036191906118ba565b82121561037457600293505050506103bb565b80600361038191906118ba565b82121561039457600393505050506103bb565b8060046103a191906118ba565b8212156103b457600493505050506103bb565b5f93505050505b92915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6103ee87610df0565b6103fa87876001610e5b565b61040387610ec6565b61040d8786611035565b8467ffffffffffffffff168667ffffffffffffffff168867ffffffffffffffff167fa5074728b92791250d48ccdc55266aca7b1cca22f89e1ef2ab91ccd7ae0f337d878787876040516104639493929190611ae2565b60405180910390a450505050505050565b6002602052825f5260405f20602052815f5260405f20602052805f5260405f205f92509250509054906101000a900460ff1681565b5f602052805f5260405f205f915054906101000a900460ff1681565b6104d185856004610e5b565b6104da85610ec6565b6104e48584611035565b5f8282905003610520576040517f59acc21d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f8667ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8567ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16156105e7576040517f7c9a1cf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160025f8767ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8667ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055505f8282604051610693929190611b49565b604051809103902090505f6001805f8967ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f9054906101000a900467ffffffffffffffff166107149190611b61565b90508060015f8967ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055508467ffffffffffffffff168667ffffffffffffffff168867ffffffffffffffff167facfc0aa3f6ba36ac0ffda53e00d2cdace2fd4a9e41e2fe3214032794332c37c387876040516107e5929190611b9c565b60405180910390a45f5f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16610a5d575f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f90f3bed896040518263ffffffff1660e01b815260040161087c91906112cf565b602060405180830381865afa158015610897573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108bb9190611bd2565b90505f8173ffffffffffffffffffffffffffffffffffffffff1663e75235b86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610907573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061092b9190611c11565b90508067ffffffffffffffff168367ffffffffffffffff1610610a5a5760015f5f8b67ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663daade8e88a88886040518463ffffffff1660e01b81526004016109e193929190611c3c565b5f604051808303815f87803b1580156109f8575f5ffd5b505af1925050508015610a09575060015b508767ffffffffffffffff168967ffffffffffffffff167fe6c9bd3daa50b9218615605cdf333410d405b7f3b8dbeee5a2373769679aa9f58888604051610a51929190611b9c565b60405180910390a35b50505b50505050505050565b610a6f85610df0565b610a7b85856002610e5b565b610a8485610ec6565b610a8e8584611035565b5f8282905003610aca576040517f2eeffe0b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8267ffffffffffffffff168467ffffffffffffffff168667ffffffffffffffff167fb5cc05e740a503c13e1b7ac3ad2d5abf41b91d2e5fca79455d34e515fb70849a8585604051610b1c929190611d28565b60405180910390a45050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f7f0000000000000000000000000000000000000000000000000000000000000000905090565b5f7f0000000000000000000000000000000000000000000000000000000000000000905090565b5f7f00000000000000000000000000000000000000000000000000000000000000006004610bcb9190611d4a565b905090565b6001602052825f5260405f20602052815f5260405f20602052805f5260405f205f92509250509054906101000a900467ffffffffffffffff1681565b610c1587610df0565b610c2187876003610e5b565b610c2a87610ec6565b610c348786611035565b818190508484905014610c73576040517fa121188700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8467ffffffffffffffff168667ffffffffffffffff168867ffffffffffffffff167f62729f0820cf3ab60fbd63a51cdeae0554d0ab24f843b86bd0d2591594d6913687878787604051610cc99493929190611d86565b60405180910390a450505050505050565b5f5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663636df979856040518263ffffffff1660e01b8152600401610d3591906112cf565b602060405180830381865afa158015610d50573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d749190611c11565b9050610d7e610b9d565b67ffffffffffffffff168367ffffffffffffffff16610d9d91906118ba565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168267ffffffffffffffff16610ddd919061187a565b610de79190611dbf565b91505092915050565b5f5f8267ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1615610e58576040517fe0f5ec9d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b806004811115610e6e57610e6d611234565b5b610e7884846102e2565b6004811115610e8a57610e89611234565b5b14610ec1576040517fe2586bcc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f90f3bed836040518263ffffffff1660e01b8152600401610f2091906112cf565b602060405180830381865afa158015610f3b573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f5f9190611bd2565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff166266f0a86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fc0573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fe49190611bd2565b73ffffffffffffffffffffffffffffffffffffffff1614611031576040517ff62f18e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f90f3bed846040518263ffffffff1660e01b815260040161108f91906112cf565b602060405180830381865afa1580156110aa573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110ce9190611bd2565b90503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16632e8e6cad846040518263ffffffff1660e01b815260040161112091906112cf565b602060405180830381865afa15801561113b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061115f9190611bd2565b73ffffffffffffffffffffffffffffffffffffffff16146111ac576040517f7bf9580300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82169050919050565b6111d5816111b9565b81146111df575f5ffd5b50565b5f813590506111f0816111cc565b92915050565b5f5f6040838503121561120c5761120b6111b1565b5b5f611219858286016111e2565b925050602061122a858286016111e2565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b6005811061127257611271611234565b5b50565b5f81905061128282611261565b919050565b5f61129182611275565b9050919050565b6112a181611287565b82525050565b5f6020820190506112ba5f830184611298565b92915050565b6112c9816111b9565b82525050565b5f6020820190506112e25f8301846112c0565b92915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f840112611309576113086112e8565b5b8235905067ffffffffffffffff811115611326576113256112ec565b5b602083019150836001820283011115611342576113416112f0565b5b9250929050565b5f5f83601f84011261135e5761135d6112e8565b5b8235905067ffffffffffffffff81111561137b5761137a6112ec565b5b602083019150836020820283011115611397576113966112f0565b5b9250929050565b5f5f5f5f5f5f5f60a0888a0312156113b9576113b86111b1565b5b5f6113c68a828b016111e2565b97505060206113d78a828b016111e2565b96505060406113e88a828b016111e2565b955050606088013567ffffffffffffffff811115611409576114086111b5565b5b6114158a828b016112f4565b9450945050608088013567ffffffffffffffff811115611438576114376111b5565b5b6114448a828b01611349565b925092505092959891949750929550565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61147e82611455565b9050919050565b61148e81611474565b8114611498575f5ffd5b50565b5f813590506114a981611485565b92915050565b5f5f5f606084860312156114c6576114c56111b1565b5b5f6114d3868287016111e2565b93505060206114e4868287016111e2565b92505060406114f58682870161149b565b9150509250925092565b5f8115159050919050565b611513816114ff565b82525050565b5f60208201905061152c5f83018461150a565b92915050565b5f60208284031215611547576115466111b1565b5b5f611554848285016111e2565b91505092915050565b5f5f5f5f5f60808688031215611576576115756111b1565b5b5f611583888289016111e2565b9550506020611594888289016111e2565b94505060406115a5888289016111e2565b935050606086013567ffffffffffffffff8111156115c6576115c56111b5565b5b6115d2888289016112f4565b92509250509295509295909350565b5f5f83601f8401126115f6576115f56112e8565b5b8235905067ffffffffffffffff811115611613576116126112ec565b5b60208301915083602082028301111561162f5761162e6112f0565b5b9250929050565b5f5f5f5f5f6080868803121561164f5761164e6111b1565b5b5f61165c888289016111e2565b955050602061166d888289016111e2565b945050604061167e888289016111e2565b935050606086013567ffffffffffffffff81111561169f5761169e6111b5565b5b6116ab888289016115e1565b92509250509295509295909350565b6116c381611474565b82525050565b5f6020820190506116dc5f8301846116ba565b92915050565b5f819050919050565b6116f4816116e2565b81146116fe575f5ffd5b50565b5f8135905061170f816116eb565b92915050565b5f5f5f6060848603121561172c5761172b6111b1565b5b5f611739868287016111e2565b935050602061174a868287016111e2565b925050604061175b86828701611701565b9150509250925092565b5f5f5f5f5f5f5f60a0888a0312156117805761177f6111b1565b5b5f61178d8a828b016111e2565b975050602061179e8a828b016111e2565b96505060406117af8a828b016111e2565b955050606088013567ffffffffffffffff8111156117d0576117cf6111b5565b5b6117dc8a828b016115e1565b9450945050608088013567ffffffffffffffff8111156117ff576117fe6111b5565b5b61180b8a828b01611349565b925092505092959891949750929550565b5f819050919050565b61182e8161181c565b82525050565b5f6020820190506118475f830184611825565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6118848261181c565b915061188f8361181c565b925082820390508181125f8412168282135f8512151617156118b4576118b361184d565b5b92915050565b5f6118c48261181c565b91506118cf8361181c565b92508282026118dd8161181c565b91507f800000000000000000000000000000000000000000000000000000000000000084145f841216156119145761191361184d565b5b82820584148315176119295761192861184d565b5b5092915050565b5f82825260208201905092915050565b828183375f83830152505050565b5f601f19601f8301169050919050565b5f6119698385611930565b9350611976838584611940565b61197f8361194e565b840190509392505050565b5f82825260208201905092915050565b5f819050919050565b5f82825260208201905092915050565b5f6119be83856119a3565b93506119cb838584611940565b6119d48361194e565b840190509392505050565b5f6119eb8484846119b3565b90509392505050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83356001602003843603038112611a1c57611a1b6119fc565b5b83810192508235915060208301925067ffffffffffffffff821115611a4457611a436119f4565b5b600182023603831315611a5a57611a596119f8565b5b509250929050565b5f602082019050919050565b5f611a79838561198a565b935083602084028501611a8b8461199a565b805f5b87811015611ad0578484038952611aa58284611a00565b611ab08682846119df565b9550611abb84611a62565b935060208b019a505050600181019050611a8e565b50829750879450505050509392505050565b5f6040820190508181035f830152611afb81868861195e565b90508181036020830152611b10818486611a6e565b905095945050505050565b5f81905092915050565b5f611b308385611b1b565b9350611b3d838584611940565b82840190509392505050565b5f611b55828486611b25565b91508190509392505050565b5f611b6b826111b9565b9150611b76836111b9565b9250828201905067ffffffffffffffff811115611b9657611b9561184d565b5b92915050565b5f6020820190508181035f830152611bb581848661195e565b90509392505050565b5f81519050611bcc81611485565b92915050565b5f60208284031215611be757611be66111b1565b5b5f611bf484828501611bbe565b91505092915050565b5f81519050611c0b816111cc565b92915050565b5f60208284031215611c2657611c256111b1565b5b5f611c3384828501611bfd565b91505092915050565b5f604082019050611c4f5f8301866112c0565b8181036020830152611c6281848661195e565b9050949350505050565b5f82825260208201905092915050565b5f819050919050565b611c8e816111b9565b82525050565b5f611c9f8383611c85565b60208301905092915050565b5f611cb960208401846111e2565b905092915050565b5f602082019050919050565b5f611cd88385611c6c565b9350611ce382611c7c565b805f5b85811015611d1b57611cf88284611cab565b611d028882611c94565b9750611d0d83611cc1565b925050600181019050611ce6565b5085925050509392505050565b5f6020820190508181035f830152611d41818486611ccd565b90509392505050565b5f611d54826111b9565b9150611d5f836111b9565b9250828202611d6d816111b9565b9150808214611d7f57611d7e61184d565b5b5092915050565b5f6040820190508181035f830152611d9f818688611ccd565b90508181036020830152611db4818486611a6e565b905095945050505050565b5f611dc98261181c565b9150611dd48361181c565b92508282019050828112155f8312168382125f841215161715611dfa57611df961184d565b5b9291505056fea164736f6c634300081c000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"phaseLength\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"dkgLeadLength\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"maxRetries\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperSetManagerAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"keyBroadcastContractAddress\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"DKG_LEAD_LENGTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MAX_RETRIES\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"PHASE_LENGTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"currentPhase\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumIDKGContract.Phase\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"cycleLength\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"dkgStart\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"int256\",\"internalType\":\"int256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"hasVoted\",\"inputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"keyBroadcastContract\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"keyperSetManager\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"submitAccusation\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"accusedIndices\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitApology\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"accuserIndices\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"polyEvalData\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitDealing\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"commitment\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"polyEvals\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitSuccessVote\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"eonPublicKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"succeeded\",\"inputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"voteCount\",\"inputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"AccusationSubmitted\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"accusedIndices\",\"type\":\"uint64[]\",\"indexed\":false,\"internalType\":\"uint64[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ApologySubmitted\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"accuserIndices\",\"type\":\"uint64[]\",\"indexed\":false,\"internalType\":\"uint64[]\"},{\"name\":\"polyEvalData\",\"type\":\"bytes[]\",\"indexed\":false,\"internalType\":\"bytes[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DKGSucceeded\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"eonPublicKey\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DealingSubmitted\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"commitment\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"polyEvals\",\"type\":\"bytes[]\",\"indexed\":false,\"internalType\":\"bytes[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SuccessVoteSubmitted\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"eonPublicKey\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AlreadySucceeded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AlreadyVoted\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"EmptyAccusation\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"EmptyEonPublicKey\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MaxRetriesExceeded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MismatchedArrays\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotKeyperAtIndex\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"WrongDKGContract\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"WrongPhase\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ZeroLengthParameter\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ZeroMaxRetries\",\"inputs\":[]}]", + Bin: "0x610120604052348015610010575f5ffd5b5060405161225a38038061225a8339818101604052810190610032919061022f565b5f8567ffffffffffffffff16148061005357505f8467ffffffffffffffff16145b1561008a576040517f038016d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8367ffffffffffffffff16036100cd576040517fb8579f9100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8467ffffffffffffffff1660808167ffffffffffffffff16815250508367ffffffffffffffff1660a08167ffffffffffffffff16815250508267ffffffffffffffff1660c08167ffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff166101008173ffffffffffffffffffffffffffffffffffffffff168152505050505050506102a6565b5f5ffd5b5f67ffffffffffffffff82169050919050565b6101b481610198565b81146101be575f5ffd5b50565b5f815190506101cf816101ab565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6101fe826101d5565b9050919050565b61020e816101f4565b8114610218575f5ffd5b50565b5f8151905061022981610205565b92915050565b5f5f5f5f5f60a0868803121561024857610247610194565b5b5f610255888289016101c1565b9550506020610266888289016101c1565b9450506040610277888289016101c1565b93505060606102888882890161021b565b92505060806102998882890161021b565b9150509295509295909350565b60805160a05160c05160e05161010051611f316103295f395f8181610a280152610c2401525f81816108c701528181610bfd01528181610d9201528181610fed015261115c01525f818161030e015281816104eb0152610ea601525f818161042f0152610e5301525f818161036e01528181610bd80152610c4b0152611f315ff3fe608060405234801561000f575f5ffd5b50600436106100f3575f3560e01c806394afc12d11610095578063eac471a011610064578063eac471a014610271578063eb05c2801461028f578063f01275b0146102bf578063f48f3d14146102db576100f3565b806394afc12d146101fb578063b209e71714610217578063d4b2cedd14610235578063df64063114610253576100f3565b806346ebbdb0116100d157806346ebbdb0146101615780637642d0de1461017f57806378a1b9db146101af57806382b870d3146101df576100f3565b80630a3ec4d6146100f757806316b89c3f146101275780633f98009814610145575b5f5ffd5b610111600480360381019061010c919061131a565b61030b565b60405161011e91906113cb565b60405180910390f35b61012f61042d565b60405161013c91906113f3565b60405180910390f35b61015f600480360381019061015a91906114c2565b610451565b005b6101696104e9565b60405161017691906113f3565b60405180910390f35b610199600480360381019061019491906115d3565b61050d565b6040516101a6919061163d565b60405180910390f35b6101c960048036038101906101c49190611656565b610542565b6040516101d6919061163d565b60405180910390f35b6101f960048036038101906101f49190611681565b61055e565b005b6102156004803603810190610210919061175a565b610b08565b005b61021f610bd6565b60405161022c91906113f3565b60405180910390f35b61023d610bfa565b60405161024a91906117ed565b60405180910390f35b61025b610c21565b60405161026891906117ed565b60405180910390f35b610279610c48565b60405161028691906113f3565b60405180910390f35b6102a960048036038101906102a49190611839565b610c7b565b6040516102b691906113f3565b60405180910390f35b6102d960048036038101906102d49190611889565b610cb7565b005b6102f560048036038101906102f0919061131a565b610d8e565b6040516103029190611958565b60405180910390f35b5f7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168267ffffffffffffffff161061034f575f9050610427565b5f61035a8484610d8e565b90505f8143610369919061199e565b90505f7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1690505f8212156103ac575f9350505050610427565b808212156103c05760019350505050610427565b8060026103cd91906119de565b8212156103e05760029350505050610427565b8060036103ed91906119de565b8212156104005760039350505050610427565b80600461040d91906119de565b8212156104205760049350505050610427565b5f93505050505b92915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b61045a86610ea4565b61046387610f14565b61046f87876001610f7f565b61047887610fea565b6104828786611159565b8467ffffffffffffffff168667ffffffffffffffff168867ffffffffffffffff167fa5074728b92791250d48ccdc55266aca7b1cca22f89e1ef2ab91ccd7ae0f337d878787876040516104d89493929190611c06565b60405180910390a450505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6002602052825f5260405f20602052815f5260405f20602052805f5260405f205f92509250509054906101000a900460ff1681565b5f602052805f5260405f205f915054906101000a900460ff1681565b61056784610ea4565b61057385856004610f7f565b61057c85610fea565b6105868584611159565b5f82829050036105c2576040517f59acc21d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f8667ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8567ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1615610689576040517f7c9a1cf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160025f8767ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8667ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055505f8282604051610735929190611c6d565b604051809103902090505f6001805f8967ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f9054906101000a900467ffffffffffffffff166107b69190611c85565b90508060015f8967ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055508467ffffffffffffffff168667ffffffffffffffff168867ffffffffffffffff167facfc0aa3f6ba36ac0ffda53e00d2cdace2fd4a9e41e2fe3214032794332c37c38787604051610887929190611cc0565b60405180910390a45f5f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16610aff575f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f90f3bed896040518263ffffffff1660e01b815260040161091e91906113f3565b602060405180830381865afa158015610939573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061095d9190611cf6565b90505f8173ffffffffffffffffffffffffffffffffffffffff1663e75235b86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109a9573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109cd9190611d35565b90508067ffffffffffffffff168367ffffffffffffffff1610610afc5760015f5f8b67ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663daade8e88a88886040518463ffffffff1660e01b8152600401610a8393929190611d60565b5f604051808303815f87803b158015610a9a575f5ffd5b505af1925050508015610aab575060015b508767ffffffffffffffff168967ffffffffffffffff167fe6c9bd3daa50b9218615605cdf333410d405b7f3b8dbeee5a2373769679aa9f58888604051610af3929190611cc0565b60405180910390a35b50505b50505050505050565b610b1184610ea4565b610b1a85610f14565b610b2685856002610f7f565b610b2f85610fea565b610b398584611159565b5f8282905003610b75576040517f2eeffe0b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8267ffffffffffffffff168467ffffffffffffffff168667ffffffffffffffff167fb5cc05e740a503c13e1b7ac3ad2d5abf41b91d2e5fca79455d34e515fb70849a8585604051610bc7929190611e4c565b60405180910390a45050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f7f0000000000000000000000000000000000000000000000000000000000000000905090565b5f7f0000000000000000000000000000000000000000000000000000000000000000905090565b5f7f00000000000000000000000000000000000000000000000000000000000000006004610c769190611e6e565b905090565b6001602052825f5260405f20602052815f5260405f20602052805f5260405f205f92509250509054906101000a900467ffffffffffffffff1681565b610cc086610ea4565b610cc987610f14565b610cd587876003610f7f565b610cde87610fea565b610ce88786611159565b818190508484905014610d27576040517fa121188700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8467ffffffffffffffff168667ffffffffffffffff168867ffffffffffffffff167f62729f0820cf3ab60fbd63a51cdeae0554d0ab24f843b86bd0d2591594d6913687878787604051610d7d9493929190611eaa565b60405180910390a450505050505050565b5f5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663636df979856040518263ffffffff1660e01b8152600401610de991906113f3565b602060405180830381865afa158015610e04573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e289190611d35565b9050610e32610c48565b67ffffffffffffffff168367ffffffffffffffff16610e5191906119de565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168267ffffffffffffffff16610e91919061199e565b610e9b9190611ee3565b91505092915050565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168167ffffffffffffffff1610610f11576040517f12f6147700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f5f8267ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1615610f7c576040517fe0f5ec9d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b806004811115610f9257610f91611358565b5b610f9c848461030b565b6004811115610fae57610fad611358565b5b14610fe5576040517fe2586bcc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f90f3bed836040518263ffffffff1660e01b815260040161104491906113f3565b602060405180830381865afa15801561105f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110839190611cf6565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff166266f0a86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111089190611cf6565b73ffffffffffffffffffffffffffffffffffffffff1614611155576040517ff62f18e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f90f3bed846040518263ffffffff1660e01b81526004016111b391906113f3565b602060405180830381865afa1580156111ce573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111f29190611cf6565b90503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16632e8e6cad846040518263ffffffff1660e01b815260040161124491906113f3565b602060405180830381865afa15801561125f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112839190611cf6565b73ffffffffffffffffffffffffffffffffffffffff16146112d0576040517f7bf9580300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82169050919050565b6112f9816112dd565b8114611303575f5ffd5b50565b5f81359050611314816112f0565b92915050565b5f5f604083850312156113305761132f6112d5565b5b5f61133d85828601611306565b925050602061134e85828601611306565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b6005811061139657611395611358565b5b50565b5f8190506113a682611385565b919050565b5f6113b582611399565b9050919050565b6113c5816113ab565b82525050565b5f6020820190506113de5f8301846113bc565b92915050565b6113ed816112dd565b82525050565b5f6020820190506114065f8301846113e4565b92915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f84011261142d5761142c61140c565b5b8235905067ffffffffffffffff81111561144a57611449611410565b5b60208301915083600182028301111561146657611465611414565b5b9250929050565b5f5f83601f8401126114825761148161140c565b5b8235905067ffffffffffffffff81111561149f5761149e611410565b5b6020830191508360208202830111156114bb576114ba611414565b5b9250929050565b5f5f5f5f5f5f5f60a0888a0312156114dd576114dc6112d5565b5b5f6114ea8a828b01611306565b97505060206114fb8a828b01611306565b965050604061150c8a828b01611306565b955050606088013567ffffffffffffffff81111561152d5761152c6112d9565b5b6115398a828b01611418565b9450945050608088013567ffffffffffffffff81111561155c5761155b6112d9565b5b6115688a828b0161146d565b925092505092959891949750929550565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6115a282611579565b9050919050565b6115b281611598565b81146115bc575f5ffd5b50565b5f813590506115cd816115a9565b92915050565b5f5f5f606084860312156115ea576115e96112d5565b5b5f6115f786828701611306565b935050602061160886828701611306565b9250506040611619868287016115bf565b9150509250925092565b5f8115159050919050565b61163781611623565b82525050565b5f6020820190506116505f83018461162e565b92915050565b5f6020828403121561166b5761166a6112d5565b5b5f61167884828501611306565b91505092915050565b5f5f5f5f5f6080868803121561169a576116996112d5565b5b5f6116a788828901611306565b95505060206116b888828901611306565b94505060406116c988828901611306565b935050606086013567ffffffffffffffff8111156116ea576116e96112d9565b5b6116f688828901611418565b92509250509295509295909350565b5f5f83601f84011261171a5761171961140c565b5b8235905067ffffffffffffffff81111561173757611736611410565b5b60208301915083602082028301111561175357611752611414565b5b9250929050565b5f5f5f5f5f60808688031215611773576117726112d5565b5b5f61178088828901611306565b955050602061179188828901611306565b94505060406117a288828901611306565b935050606086013567ffffffffffffffff8111156117c3576117c26112d9565b5b6117cf88828901611705565b92509250509295509295909350565b6117e781611598565b82525050565b5f6020820190506118005f8301846117de565b92915050565b5f819050919050565b61181881611806565b8114611822575f5ffd5b50565b5f813590506118338161180f565b92915050565b5f5f5f606084860312156118505761184f6112d5565b5b5f61185d86828701611306565b935050602061186e86828701611306565b925050604061187f86828701611825565b9150509250925092565b5f5f5f5f5f5f5f60a0888a0312156118a4576118a36112d5565b5b5f6118b18a828b01611306565b97505060206118c28a828b01611306565b96505060406118d38a828b01611306565b955050606088013567ffffffffffffffff8111156118f4576118f36112d9565b5b6119008a828b01611705565b9450945050608088013567ffffffffffffffff811115611923576119226112d9565b5b61192f8a828b0161146d565b925092505092959891949750929550565b5f819050919050565b61195281611940565b82525050565b5f60208201905061196b5f830184611949565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6119a882611940565b91506119b383611940565b925082820390508181125f8412168282135f8512151617156119d8576119d7611971565b5b92915050565b5f6119e882611940565b91506119f383611940565b9250828202611a0181611940565b91507f800000000000000000000000000000000000000000000000000000000000000084145f84121615611a3857611a37611971565b5b8282058414831517611a4d57611a4c611971565b5b5092915050565b5f82825260208201905092915050565b828183375f83830152505050565b5f601f19601f8301169050919050565b5f611a8d8385611a54565b9350611a9a838584611a64565b611aa383611a72565b840190509392505050565b5f82825260208201905092915050565b5f819050919050565b5f82825260208201905092915050565b5f611ae28385611ac7565b9350611aef838584611a64565b611af883611a72565b840190509392505050565b5f611b0f848484611ad7565b90509392505050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83356001602003843603038112611b4057611b3f611b20565b5b83810192508235915060208301925067ffffffffffffffff821115611b6857611b67611b18565b5b600182023603831315611b7e57611b7d611b1c565b5b509250929050565b5f602082019050919050565b5f611b9d8385611aae565b935083602084028501611baf84611abe565b805f5b87811015611bf4578484038952611bc98284611b24565b611bd4868284611b03565b9550611bdf84611b86565b935060208b019a505050600181019050611bb2565b50829750879450505050509392505050565b5f6040820190508181035f830152611c1f818688611a82565b90508181036020830152611c34818486611b92565b905095945050505050565b5f81905092915050565b5f611c548385611c3f565b9350611c61838584611a64565b82840190509392505050565b5f611c79828486611c49565b91508190509392505050565b5f611c8f826112dd565b9150611c9a836112dd565b9250828201905067ffffffffffffffff811115611cba57611cb9611971565b5b92915050565b5f6020820190508181035f830152611cd9818486611a82565b90509392505050565b5f81519050611cf0816115a9565b92915050565b5f60208284031215611d0b57611d0a6112d5565b5b5f611d1884828501611ce2565b91505092915050565b5f81519050611d2f816112f0565b92915050565b5f60208284031215611d4a57611d496112d5565b5b5f611d5784828501611d21565b91505092915050565b5f604082019050611d735f8301866113e4565b8181036020830152611d86818486611a82565b9050949350505050565b5f82825260208201905092915050565b5f819050919050565b611db2816112dd565b82525050565b5f611dc38383611da9565b60208301905092915050565b5f611ddd6020840184611306565b905092915050565b5f602082019050919050565b5f611dfc8385611d90565b9350611e0782611da0565b805f5b85811015611e3f57611e1c8284611dcf565b611e268882611db8565b9750611e3183611de5565b925050600181019050611e0a565b5085925050509392505050565b5f6020820190508181035f830152611e65818486611df1565b90509392505050565b5f611e78826112dd565b9150611e83836112dd565b9250828202611e91816112dd565b9150808214611ea357611ea2611971565b5b5092915050565b5f6040820190508181035f830152611ec3818688611df1565b90508181036020830152611ed8818486611b92565b905095945050505050565b5f611eed82611940565b9150611ef883611940565b92508282019050828112155f8312168382125f841215161715611f1e57611f1d611971565b5b9291505056fea164736f6c634300081c000a", } // DkgcontractABI is the input ABI used to generate the binding from. @@ -44,7 +44,7 @@ var DkgcontractABI = DkgcontractMetaData.ABI var DkgcontractBin = DkgcontractMetaData.Bin // DeployDkgcontract deploys a new Ethereum contract, binding an instance of Dkgcontract to it. -func DeployDkgcontract(auth *bind.TransactOpts, backend bind.ContractBackend, phaseLength uint64, dkgLeadLength uint64, keyperSetManagerAddress common.Address, keyBroadcastContractAddress common.Address) (common.Address, *types.Transaction, *Dkgcontract, error) { +func DeployDkgcontract(auth *bind.TransactOpts, backend bind.ContractBackend, phaseLength uint64, dkgLeadLength uint64, maxRetries uint64, keyperSetManagerAddress common.Address, keyBroadcastContractAddress common.Address) (common.Address, *types.Transaction, *Dkgcontract, error) { parsed, err := DkgcontractMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -53,7 +53,7 @@ func DeployDkgcontract(auth *bind.TransactOpts, backend bind.ContractBackend, ph return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(DkgcontractBin), backend, phaseLength, dkgLeadLength, keyperSetManagerAddress, keyBroadcastContractAddress) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(DkgcontractBin), backend, phaseLength, dkgLeadLength, maxRetries, keyperSetManagerAddress, keyBroadcastContractAddress) if err != nil { return common.Address{}, nil, nil, err } @@ -233,6 +233,37 @@ func (_Dkgcontract *DkgcontractCallerSession) DKGLEADLENGTH() (uint64, error) { return _Dkgcontract.Contract.DKGLEADLENGTH(&_Dkgcontract.CallOpts) } +// MAXRETRIES is a free data retrieval call binding the contract method 0x46ebbdb0. +// +// Solidity: function MAX_RETRIES() view returns(uint64) +func (_Dkgcontract *DkgcontractCaller) MAXRETRIES(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _Dkgcontract.contract.Call(opts, &out, "MAX_RETRIES") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// MAXRETRIES is a free data retrieval call binding the contract method 0x46ebbdb0. +// +// Solidity: function MAX_RETRIES() view returns(uint64) +func (_Dkgcontract *DkgcontractSession) MAXRETRIES() (uint64, error) { + return _Dkgcontract.Contract.MAXRETRIES(&_Dkgcontract.CallOpts) +} + +// MAXRETRIES is a free data retrieval call binding the contract method 0x46ebbdb0. +// +// Solidity: function MAX_RETRIES() view returns(uint64) +func (_Dkgcontract *DkgcontractCallerSession) MAXRETRIES() (uint64, error) { + return _Dkgcontract.Contract.MAXRETRIES(&_Dkgcontract.CallOpts) +} + // PHASELENGTH is a free data retrieval call binding the contract method 0xb209e717. // // Solidity: function PHASE_LENGTH() view returns(uint64) diff --git a/script/DKGState.s.sol b/script/DKGState.s.sol index a053ddb..6964686 100644 --- a/script/DKGState.s.sol +++ b/script/DKGState.s.sol @@ -34,6 +34,7 @@ contract DKGState is Script { address dkgAddr; uint64 phaseLength; uint64 dkgLeadLength; + uint64 maxRetries; uint64 cycleLen; int256 dkgStart0; bool succeededFlag; @@ -102,6 +103,7 @@ contract DKGState is Script { DKGContract dkg = DKGContract(ctx.dkgAddr); ctx.phaseLength = dkg.PHASE_LENGTH(); ctx.dkgLeadLength = dkg.DKG_LEAD_LENGTH(); + ctx.maxRetries = dkg.MAX_RETRIES(); ctx.cycleLen = dkg.cycleLength(); ctx.dkgStart0 = dkg.dkgStart(ctx.setIndex, 0); ctx.succeededFlag = dkg.succeeded(ctx.setIndex); @@ -157,6 +159,7 @@ contract DKGState is Script { console.log("DKG contract config:"); console.log(" PHASE_LENGTH: ", uint256(c.phaseLength)); console.log(" DKG_LEAD_LENGTH: ", uint256(c.dkgLeadLength)); + console.log(" MAX_RETRIES: ", uint256(c.maxRetries)); console.log(" cycleLength: ", uint256(c.cycleLen)); console.log( string.concat(" dkgStart(index,0): ", _intToString(c.dkgStart0)) diff --git a/script/Deploy.gnosh.s.sol b/script/Deploy.gnosh.s.sol index 54176a0..01aef59 100644 --- a/script/Deploy.gnosh.s.sol +++ b/script/Deploy.gnosh.s.sol @@ -39,9 +39,11 @@ contract Deploy is Script { ) public returns (DKGContract) { uint64 phaseLength = uint64(vm.envOr("DKG_PHASE_LENGTH", uint256(10))); uint64 dkgLeadLength = uint64(vm.envOr("DKG_LEAD_LENGTH", uint256(40))); + uint64 maxRetries = uint64(vm.envOr("DKG_MAX_RETRIES", uint256(10))); DKGContract dkg = new DKGContract( phaseLength, dkgLeadLength, + maxRetries, address(ksm), address(kbc) ); diff --git a/script/Deploy.s.sol b/script/Deploy.s.sol index 4c8ea2a..44f81a7 100644 --- a/script/Deploy.s.sol +++ b/script/Deploy.s.sol @@ -27,6 +27,7 @@ contract DeployScript is Script { uint256 threshold; uint64 dkgPhaseLength; uint64 dkgLeadLength; + uint64 dkgMaxRetries; // address[] memory keypers; address inboxAddress; @@ -67,6 +68,7 @@ contract DeployScript is Script { dkgPhaseLength = uint64(vm.envOr("DKG_PHASE_LENGTH", uint256(10))); dkgLeadLength = uint64(vm.envOr("DKG_LEAD_LENGTH", uint256(40))); + dkgMaxRetries = uint64(vm.envOr("DKG_MAX_RETRIES", uint256(10))); } function deploy() public { @@ -111,6 +113,7 @@ contract DeployScript is Script { dkgContract = new DKGContract( dkgPhaseLength, dkgLeadLength, + dkgMaxRetries, address(keyperSetManager), address(keyBroadcastContract) ); diff --git a/script/Deploy.service.s.sol b/script/Deploy.service.s.sol index 967da9e..b5340fe 100644 --- a/script/Deploy.service.s.sol +++ b/script/Deploy.service.s.sol @@ -28,6 +28,7 @@ contract Deploy is Script { DKGContract bootstrapDkg = new DKGContract( 10, 40, + 10, address(ksm), address(0) ); @@ -53,9 +54,11 @@ contract Deploy is Script { ) public returns (DKGContract) { uint64 phaseLength = uint64(vm.envOr("DKG_PHASE_LENGTH", uint256(10))); uint64 dkgLeadLength = uint64(vm.envOr("DKG_LEAD_LENGTH", uint256(40))); + uint64 maxRetries = uint64(vm.envOr("DKG_MAX_RETRIES", uint256(10))); DKGContract dkg = new DKGContract( phaseLength, dkgLeadLength, + maxRetries, address(ksm), address(kbc) ); diff --git a/src/common/DKGContract.sol b/src/common/DKGContract.sol index 6762e45..c069eae 100644 --- a/src/common/DKGContract.sol +++ b/src/common/DKGContract.sol @@ -14,6 +14,8 @@ contract DKGContract is IDKGContract { error AlreadyVoted(); error WrongDKGContract(); error ZeroLengthParameter(); + error ZeroMaxRetries(); + error MaxRetriesExceeded(); error EmptyEonPublicKey(); event DealingSubmitted( @@ -50,6 +52,10 @@ contract DKGContract is IDKGContract { uint64 public immutable PHASE_LENGTH; uint64 public immutable DKG_LEAD_LENGTH; + // Ceiling on the number of DKG attempts per keyper set. Valid retry + // counters are {0, ..., MAX_RETRIES - 1}; every submit at or above the + // limit reverts and currentPhase returns Phase.None. + uint64 public immutable MAX_RETRIES; // Held as concrete types for internal calls; exposed as address through the // IDKGContract getters below so the interface stays free of concrete-contract // imports (which would re-create the KeyperSetManager <-> DKGContract cycle). @@ -68,14 +74,19 @@ contract DKGContract is IDKGContract { constructor( uint64 phaseLength, uint64 dkgLeadLength, + uint64 maxRetries, address keyperSetManagerAddress, address keyBroadcastContractAddress ) { if (phaseLength == 0 || dkgLeadLength == 0) { revert ZeroLengthParameter(); } + if (maxRetries == 0) { + revert ZeroMaxRetries(); + } PHASE_LENGTH = phaseLength; DKG_LEAD_LENGTH = dkgLeadLength; + MAX_RETRIES = maxRetries; _keyperSetManager = KeyperSetManager(keyperSetManagerAddress); _keyBroadcastContract = KeyBroadcastContract( keyBroadcastContractAddress @@ -112,6 +123,7 @@ contract DKGContract is IDKGContract { uint64 keyperSetIndex, uint64 retryCounter ) public view returns (Phase) { + if (retryCounter >= MAX_RETRIES) return Phase.None; int256 start = dkgStart(keyperSetIndex, retryCounter); int256 offset = int256(block.number) - start; int256 phaseLen = int256(uint256(PHASE_LENGTH)); @@ -123,6 +135,12 @@ contract DKGContract is IDKGContract { return Phase.None; } + function _requireWithinMaxRetries(uint64 retryCounter) internal view { + if (retryCounter >= MAX_RETRIES) { + revert MaxRetriesExceeded(); + } + } + function _requireNotSucceeded(uint64 keyperSetIndex) internal view { if (succeeded[keyperSetIndex]) { revert AlreadySucceeded(); @@ -167,6 +185,7 @@ contract DKGContract is IDKGContract { bytes calldata commitment, bytes[] calldata polyEvals ) external { + _requireWithinMaxRetries(retryCounter); _requireNotSucceeded(keyperSetIndex); _requirePhase(keyperSetIndex, retryCounter, Phase.Dealing); _checkDKGContract(keyperSetIndex); @@ -188,6 +207,7 @@ contract DKGContract is IDKGContract { uint64 keyperIndex, uint64[] calldata accusedIndices ) external { + _requireWithinMaxRetries(retryCounter); _requireNotSucceeded(keyperSetIndex); _requirePhase(keyperSetIndex, retryCounter, Phase.Accusing); _checkDKGContract(keyperSetIndex); @@ -210,6 +230,7 @@ contract DKGContract is IDKGContract { uint64[] calldata accuserIndices, bytes[] calldata polyEvalData ) external { + _requireWithinMaxRetries(retryCounter); _requireNotSucceeded(keyperSetIndex); _requirePhase(keyperSetIndex, retryCounter, Phase.Apologizing); _checkDKGContract(keyperSetIndex); @@ -232,6 +253,7 @@ contract DKGContract is IDKGContract { uint64 keyperIndex, bytes calldata eonPublicKey ) external { + _requireWithinMaxRetries(retryCounter); _requirePhase(keyperSetIndex, retryCounter, Phase.Finalizing); _checkDKGContract(keyperSetIndex); _checkMember(keyperSetIndex, keyperIndex); diff --git a/test/DKGBenchmark.t.sol b/test/DKGBenchmark.t.sol index a963bfe..c2f2313 100644 --- a/test/DKGBenchmark.t.sol +++ b/test/DKGBenchmark.t.sol @@ -17,6 +17,7 @@ contract DKGBenchmark is Test { // the benchmark uses block windows the test runner already understands. uint64 constant PHASE_LENGTH = 10; uint64 constant DKG_LEAD_LENGTH = 40; + uint64 constant MAX_RETRIES = 10; uint64 constant ACTIVATION_BLOCK = 1000; // Non-zero fill byte. Real BLS/ECIES payloads are non-zero, and calldata @@ -50,6 +51,7 @@ contract DKGBenchmark is Test { dkg = new DKGContract( PHASE_LENGTH, DKG_LEAD_LENGTH, + MAX_RETRIES, address(ksm), address(kbc) ); diff --git a/test/DKGContract.t.sol b/test/DKGContract.t.sol index 38abd27..c9a295f 100644 --- a/test/DKGContract.t.sol +++ b/test/DKGContract.t.sol @@ -16,6 +16,7 @@ contract DKGContractTest is Test { uint64 constant PHASE_LENGTH = 10; uint64 constant DKG_LEAD_LENGTH = 40; + uint64 constant MAX_RETRIES = 10; uint64 constant CYCLE_LENGTH = 4 * PHASE_LENGTH; uint64 constant ACTIVATION_BLOCK_0 = 1000; @@ -73,6 +74,7 @@ contract DKGContractTest is Test { dkgContract = new DKGContract( PHASE_LENGTH, DKG_LEAD_LENGTH, + MAX_RETRIES, address(keyperSetManager), address(keyBroadcastContract) ); @@ -96,6 +98,7 @@ contract DKGContractTest is Test { new DKGContract( 0, DKG_LEAD_LENGTH, + MAX_RETRIES, address(keyperSetManager), address(keyBroadcastContract) ); @@ -106,6 +109,18 @@ contract DKGContractTest is Test { new DKGContract( PHASE_LENGTH, 0, + MAX_RETRIES, + address(keyperSetManager), + address(keyBroadcastContract) + ); + } + + function testConstructorRevertsOnZeroMaxRetries() public { + vm.expectRevert(DKGContract.ZeroMaxRetries.selector); + new DKGContract( + PHASE_LENGTH, + DKG_LEAD_LENGTH, + 0, address(keyperSetManager), address(keyBroadcastContract) ); @@ -114,6 +129,7 @@ contract DKGContractTest is Test { function testDeploysWithImmutables() public view { assertEq(dkgContract.PHASE_LENGTH(), PHASE_LENGTH); assertEq(dkgContract.DKG_LEAD_LENGTH(), DKG_LEAD_LENGTH); + assertEq(dkgContract.MAX_RETRIES(), MAX_RETRIES); assertEq( address(dkgContract.keyperSetManager()), address(keyperSetManager) @@ -265,6 +281,7 @@ contract DKGContractTest is Test { DKGContract dkg = new DKGContract( PHASE_LENGTH, 2000, // lead length larger than activation block 1000 + MAX_RETRIES, address(keyperSetManager), address(keyBroadcastContract) ); @@ -763,6 +780,7 @@ contract DKGContractTest is Test { DKGContract otherDKG = new DKGContract( PHASE_LENGTH, DKG_LEAD_LENGTH, + MAX_RETRIES, address(keyperSetManager), address(keyBroadcastContract) ); @@ -826,4 +844,127 @@ contract DKGContractTest is Test { vm.expectRevert(DKGContract.WrongDKGContract.selector); dkgContract.submitSuccessVote(ksi, 0, 0, EON_KEY_A); } + + // --------------------------------------------------------------------- + // MAX_RETRIES enforcement + // --------------------------------------------------------------------- + + // Retry r's Dealing window starts at DKG_START_R0 + r * CYCLE_LENGTH. + function _dealingBlockForRetry(uint64 r) internal pure returns (uint64) { + return DKG_START_R0 + r * CYCLE_LENGTH; + } + + function testSubmitDealingRevertsAtMaxRetries() public { + // retryCounter == MAX_RETRIES: rejected before phase arithmetic runs, + // regardless of block number. + vm.roll(_dealingBlockForRetry(MAX_RETRIES)); + bytes[] memory evals = new bytes[](0); + vm.prank(keyper0); + vm.expectRevert(DKGContract.MaxRetriesExceeded.selector); + dkgContract.submitDealing(0, MAX_RETRIES, 0, hex"01", evals); + } + + function testSubmitDealingRevertsAboveMaxRetries() public { + vm.roll(_dealingBlockForRetry(MAX_RETRIES + 5)); + bytes[] memory evals = new bytes[](0); + vm.prank(keyper0); + vm.expectRevert(DKGContract.MaxRetriesExceeded.selector); + dkgContract.submitDealing(0, MAX_RETRIES + 5, 0, hex"01", evals); + } + + function testSubmitAccusationRevertsAtMaxRetries() public { + vm.roll(_dealingBlockForRetry(MAX_RETRIES) + PHASE_LENGTH); + uint64[] memory accused = new uint64[](1); + accused[0] = 1; + vm.prank(keyper0); + vm.expectRevert(DKGContract.MaxRetriesExceeded.selector); + dkgContract.submitAccusation(0, MAX_RETRIES, 0, accused); + } + + function testSubmitApologyRevertsAtMaxRetries() public { + vm.roll(_dealingBlockForRetry(MAX_RETRIES) + 2 * PHASE_LENGTH); + uint64[] memory accusers = new uint64[](1); + accusers[0] = 1; + bytes[] memory evals = new bytes[](1); + evals[0] = hex"aa"; + vm.prank(keyper0); + vm.expectRevert(DKGContract.MaxRetriesExceeded.selector); + dkgContract.submitApology(0, MAX_RETRIES, 0, accusers, evals); + } + + function testSubmitSuccessVoteRevertsAtMaxRetries() public { + vm.roll(_dealingBlockForRetry(MAX_RETRIES) + 3 * PHASE_LENGTH); + vm.prank(keyper0); + vm.expectRevert(DKGContract.MaxRetriesExceeded.selector); + dkgContract.submitSuccessVote(0, MAX_RETRIES, 0, EON_KEY_A); + } + + function testSubmitDealingAcceptedAtLastAllowedRetry() public { + // retryCounter == MAX_RETRIES - 1 is the last valid retry and must + // succeed given a legitimate Dealing-phase block number. + uint64 lastRetry = MAX_RETRIES - 1; + vm.roll(_dealingBlockForRetry(lastRetry)); + bytes[] memory evals = new bytes[](0); + vm.expectEmit(true, true, true, true, address(dkgContract)); + emit DealingSubmitted(0, lastRetry, 0, hex"01", evals); + vm.prank(keyper0); + dkgContract.submitDealing(0, lastRetry, 0, hex"01", evals); + } + + function testCurrentPhaseIsNoneAtMaxRetries() public { + // currentPhase must return Phase.None regardless of block number when + // retryCounter >= MAX_RETRIES. + uint64[4] memory samples = [ + uint64(0), + _dealingBlockForRetry(MAX_RETRIES), + _dealingBlockForRetry(MAX_RETRIES) + 5 * PHASE_LENGTH, + _dealingBlockForRetry(MAX_RETRIES) + 100 * CYCLE_LENGTH + ]; + for (uint256 i = 0; i < samples.length; i++) { + _assertPhase(samples[i], MAX_RETRIES, IDKGContract.Phase.None); + _assertPhase(samples[i], MAX_RETRIES + 7, IDKGContract.Phase.None); + } + } + + function testMaxRetriesEnforcementUsesConstructorValue() public { + // A contract deployed with a smaller MAX_RETRIES rejects submits at + // its own ceiling — proving the guard reads the immutable, not a + // hardcoded constant. + uint64 tightMaxRetries = 3; + DKGContract tightDkg = new DKGContract( + PHASE_LENGTH, + DKG_LEAD_LENGTH, + tightMaxRetries, + address(keyperSetManager), + address(keyBroadcastContract) + ); + // Point a fresh keyper set at the tight DKG and register it. + KeyperSet ks = new KeyperSet(); + address[] memory members = new address[](3); + members[0] = keyper0; + members[1] = keyper1; + members[2] = keyper2; + ks.addMembers(members); + ks.setThreshold(2); + ks.setPublisher(address(tightDkg)); + ks.setDKGContract(address(tightDkg)); + ks.setFinalized(); + uint64 activation = ACTIVATION_BLOCK_0 * 3; + vm.prank(dao); + keyperSetManager.addKeyperSet(activation, address(ks)); + uint64 ksi = 1; + + uint64 dkgStart = activation - DKG_LEAD_LENGTH; + // Dealing for r = MAX_RETRIES - 1 is accepted. + vm.roll(dkgStart + (tightMaxRetries - 1) * CYCLE_LENGTH); + bytes[] memory evals = new bytes[](0); + vm.prank(keyper0); + tightDkg.submitDealing(ksi, tightMaxRetries - 1, 0, hex"01", evals); + + // Dealing at retryCounter == MAX_RETRIES reverts with MaxRetriesExceeded. + vm.roll(dkgStart + tightMaxRetries * CYCLE_LENGTH); + vm.prank(keyper0); + vm.expectRevert(DKGContract.MaxRetriesExceeded.selector); + tightDkg.submitDealing(ksi, tightMaxRetries, 0, hex"01", evals); + } } diff --git a/test/ECIESKeyRegistry.t.sol b/test/ECIESKeyRegistry.t.sol index c812fd6..36ced2a 100644 --- a/test/ECIESKeyRegistry.t.sol +++ b/test/ECIESKeyRegistry.t.sol @@ -35,6 +35,7 @@ contract ECIESKeyRegistryTest is Test { DKGContract dkgContract = new DKGContract( 1, 1, + 10, address(keyperSetManager), address(0) ); diff --git a/test/EonKeyPublish.t.sol b/test/EonKeyPublish.t.sol index f8603a8..8f66a42 100644 --- a/test/EonKeyPublish.t.sol +++ b/test/EonKeyPublish.t.sol @@ -28,6 +28,7 @@ contract EonKeyPublishTest is Test { dkgContract = new DKGContract( 1, 1, + 10, address(manager), address(broadcastContract) ); diff --git a/test/KeyBroadcastContract.t.sol b/test/KeyBroadcastContract.t.sol index 4737536..afa5c87 100644 --- a/test/KeyBroadcastContract.t.sol +++ b/test/KeyBroadcastContract.t.sol @@ -45,6 +45,7 @@ contract KeyBroadcastTest is Test { DKGContract dkgContract = new DKGContract( 1, 1, + 10, address(keyperSetManager), address(keyBroadcastContract) ); diff --git a/test/KeyperSetManager.t.sol b/test/KeyperSetManager.t.sol index 252d51c..2bf890d 100644 --- a/test/KeyperSetManager.t.sol +++ b/test/KeyperSetManager.t.sol @@ -19,6 +19,7 @@ contract KeyperSetManagerTest is Test { uint64 constant PHASE_LENGTH = 10; uint64 constant DKG_LEAD_LENGTH = 40; + uint64 constant MAX_RETRIES = 10; function setUp() public { owner = vm.addr(42); @@ -48,6 +49,7 @@ contract KeyperSetManagerTest is Test { new DKGContract( PHASE_LENGTH, DKG_LEAD_LENGTH, + MAX_RETRIES, manager, address(keyBroadcastContract) ); From 929d7e1043cc1f1342172519ba72997a2a7112f1 Mon Sep 17 00:00:00 2001 From: Jannik Date: Tue, 14 Jul 2026 19:49:36 +0200 Subject: [PATCH 24/25] style(dkg-state): apply prettier formatting --- script/DKGState.s.sol | 53 ++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/script/DKGState.s.sol b/script/DKGState.s.sol index 6964686..0e2f064 100644 --- a/script/DKGState.s.sol +++ b/script/DKGState.s.sol @@ -139,11 +139,7 @@ contract DKGState is Script { console.log(" DKG contract: ", c.dkgAddr); console.log(" activation block: ", uint256(c.activationBlock)); console.log( - string.concat( - " members (", - vm.toString(c.members.length), - "):" - ) + string.concat(" members (", vm.toString(c.members.length), "):") ); for (uint256 i = 0; i < c.members.length; i++) { console.log( @@ -182,9 +178,7 @@ contract DKGState is Script { } else { bytes32 h = keccak256(c.broadcastedKey); string memory desc = _keyDesc(reg, h); - console.log( - string.concat(" eon key broadcast: ", desc) - ); + console.log(string.concat(" eon key broadcast: ", desc)); } } @@ -229,9 +223,7 @@ contract DKGState is Script { // ---------------- fetch logs ---------------- function fetchLogs(Ctx memory ctx) internal returns (Logs memory logs) { - uint256 fromBlock = ctx.dkgStart0 < 0 - ? 0 - : uint256(ctx.dkgStart0); + uint256 fromBlock = ctx.dkgStart0 < 0 ? 0 : uint256(ctx.dkgStart0); uint256 toBlock = ctx.currentBlock; if (fromBlock > toBlock) { logs.dealing = new Vm.EthGetLogs[](0); @@ -400,7 +392,21 @@ contract DKGState is Script { _printCondensed(condStart, condEnd); condStart = -1; } - _printRetry(c, logs, reg, ru, inProgress, ru == uint64(uint256(succeededAtRetry >= 0 ? succeededAtRetry : int256(-1)))); + _printRetry( + c, + logs, + reg, + ru, + inProgress, + ru == + uint64( + uint256( + succeededAtRetry >= 0 + ? succeededAtRetry + : int256(-1) + ) + ) + ); } if (condStart >= 0) _printCondensed(condStart, condEnd); } @@ -529,11 +535,7 @@ contract DKGState is Script { } if (count == 0) { console.log( - string.concat( - " Dealings: none (0/", - vm.toString(total), - ")" - ) + string.concat(" Dealings: none (0/", vm.toString(total), ")") ); return; } @@ -572,9 +574,7 @@ contract DKGState is Script { console.log(string.concat(" Accusations (", vm.toString(n), "):")); for (uint256 i = 0; i < logs.accusation.length; i++) { if (uint64(uint256(logs.accusation[i].topics[2])) != r) continue; - uint64 accuser = uint64( - uint256(logs.accusation[i].topics[3]) - ); + uint64 accuser = uint64(uint256(logs.accusation[i].topics[3])); uint64[] memory accused = abi.decode( logs.accusation[i].data, (uint64[]) @@ -606,9 +606,7 @@ contract DKGState is Script { console.log(string.concat(" Apologies (", vm.toString(n), "):")); for (uint256 i = 0; i < logs.apology.length; i++) { if (uint64(uint256(logs.apology[i].topics[2])) != r) continue; - uint64 apologizer = uint64( - uint256(logs.apology[i].topics[3]) - ); + uint64 apologizer = uint64(uint256(logs.apology[i].topics[3])); (uint64[] memory accusers, ) = abi.decode( logs.apology[i].data, (uint64[], bytes[]) @@ -750,10 +748,7 @@ contract DKGState is Script { ) ); console.log( - string.concat( - " voters: ", - _indexList(t.voterByKey[li], true) - ) + string.concat(" voters: ", _indexList(t.voterByKey[li], true)) ); } @@ -769,7 +764,9 @@ contract DKGState is Script { Ctx memory c, uint64 r ) internal pure returns (uint256) { - int256 s = c.dkgStart0 + int256(uint256(r)) * int256(uint256(c.cycleLen)); + int256 s = c.dkgStart0 + + int256(uint256(r)) * + int256(uint256(c.cycleLen)); // Caller must not invoke for retries with negative start; guarded by // _currentRetry returning -1 upstream. return uint256(s); From 80d0dd0f354d91da926f1a4731a056bcbef8c7aa Mon Sep 17 00:00:00 2001 From: Jannik Date: Thu, 16 Jul 2026 00:44:03 +0200 Subject: [PATCH 25/25] feat(dkg): expose winning retry counter for succeeded DKGs Replace `mapping(uint64 => bool) succeeded` with an internal `mapping(uint64 => uint64) _successRetryPlusOne`. Zero means "not yet succeeded"; non-zero stores `retryCounter + 1`, packing the success flag and the winning retry into a single storage slot. New public views: - succeeded(ksi) returns (bool) [ABI unchanged] - succeededAtRetry(ksi) returns (uint64) [new] Motivation: on-chain views previously exposed only the boolean success flag. Off-chain consumers backfilling successful DKGs without event-log access could not learn which retry actually won and had to assume retry 0. See the paired fix on the rolling-shutter side that consumes this new view during DKG catch-up. --- bindings/dkgcontract/dkgcontract.go | 53 +++++++++++++++++++++++------ src/common/DKGContract.sol | 30 ++++++++++++---- src/common/intf/IDKGContract.sol | 4 +++ test/DKGContract.t.sol | 30 ++++++++++++++++ 4 files changed, 99 insertions(+), 18 deletions(-) diff --git a/bindings/dkgcontract/dkgcontract.go b/bindings/dkgcontract/dkgcontract.go index f3c2f13..12ce8cb 100644 --- a/bindings/dkgcontract/dkgcontract.go +++ b/bindings/dkgcontract/dkgcontract.go @@ -31,8 +31,8 @@ var ( // DkgcontractMetaData contains all meta data concerning the Dkgcontract contract. var DkgcontractMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"phaseLength\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"dkgLeadLength\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"maxRetries\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperSetManagerAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"keyBroadcastContractAddress\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"DKG_LEAD_LENGTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MAX_RETRIES\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"PHASE_LENGTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"currentPhase\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumIDKGContract.Phase\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"cycleLength\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"dkgStart\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"int256\",\"internalType\":\"int256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"hasVoted\",\"inputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"keyBroadcastContract\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"keyperSetManager\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"submitAccusation\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"accusedIndices\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitApology\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"accuserIndices\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"polyEvalData\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitDealing\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"commitment\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"polyEvals\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitSuccessVote\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"eonPublicKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"succeeded\",\"inputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"voteCount\",\"inputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"AccusationSubmitted\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"accusedIndices\",\"type\":\"uint64[]\",\"indexed\":false,\"internalType\":\"uint64[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ApologySubmitted\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"accuserIndices\",\"type\":\"uint64[]\",\"indexed\":false,\"internalType\":\"uint64[]\"},{\"name\":\"polyEvalData\",\"type\":\"bytes[]\",\"indexed\":false,\"internalType\":\"bytes[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DKGSucceeded\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"eonPublicKey\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DealingSubmitted\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"commitment\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"polyEvals\",\"type\":\"bytes[]\",\"indexed\":false,\"internalType\":\"bytes[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SuccessVoteSubmitted\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"eonPublicKey\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AlreadySucceeded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AlreadyVoted\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"EmptyAccusation\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"EmptyEonPublicKey\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MaxRetriesExceeded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MismatchedArrays\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotKeyperAtIndex\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"WrongDKGContract\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"WrongPhase\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ZeroLengthParameter\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ZeroMaxRetries\",\"inputs\":[]}]", - Bin: "0x610120604052348015610010575f5ffd5b5060405161225a38038061225a8339818101604052810190610032919061022f565b5f8567ffffffffffffffff16148061005357505f8467ffffffffffffffff16145b1561008a576040517f038016d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8367ffffffffffffffff16036100cd576040517fb8579f9100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8467ffffffffffffffff1660808167ffffffffffffffff16815250508367ffffffffffffffff1660a08167ffffffffffffffff16815250508267ffffffffffffffff1660c08167ffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff166101008173ffffffffffffffffffffffffffffffffffffffff168152505050505050506102a6565b5f5ffd5b5f67ffffffffffffffff82169050919050565b6101b481610198565b81146101be575f5ffd5b50565b5f815190506101cf816101ab565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6101fe826101d5565b9050919050565b61020e816101f4565b8114610218575f5ffd5b50565b5f8151905061022981610205565b92915050565b5f5f5f5f5f60a0868803121561024857610247610194565b5b5f610255888289016101c1565b9550506020610266888289016101c1565b9450506040610277888289016101c1565b93505060606102888882890161021b565b92505060806102998882890161021b565b9150509295509295909350565b60805160a05160c05160e05161010051611f316103295f395f8181610a280152610c2401525f81816108c701528181610bfd01528181610d9201528181610fed015261115c01525f818161030e015281816104eb0152610ea601525f818161042f0152610e5301525f818161036e01528181610bd80152610c4b0152611f315ff3fe608060405234801561000f575f5ffd5b50600436106100f3575f3560e01c806394afc12d11610095578063eac471a011610064578063eac471a014610271578063eb05c2801461028f578063f01275b0146102bf578063f48f3d14146102db576100f3565b806394afc12d146101fb578063b209e71714610217578063d4b2cedd14610235578063df64063114610253576100f3565b806346ebbdb0116100d157806346ebbdb0146101615780637642d0de1461017f57806378a1b9db146101af57806382b870d3146101df576100f3565b80630a3ec4d6146100f757806316b89c3f146101275780633f98009814610145575b5f5ffd5b610111600480360381019061010c919061131a565b61030b565b60405161011e91906113cb565b60405180910390f35b61012f61042d565b60405161013c91906113f3565b60405180910390f35b61015f600480360381019061015a91906114c2565b610451565b005b6101696104e9565b60405161017691906113f3565b60405180910390f35b610199600480360381019061019491906115d3565b61050d565b6040516101a6919061163d565b60405180910390f35b6101c960048036038101906101c49190611656565b610542565b6040516101d6919061163d565b60405180910390f35b6101f960048036038101906101f49190611681565b61055e565b005b6102156004803603810190610210919061175a565b610b08565b005b61021f610bd6565b60405161022c91906113f3565b60405180910390f35b61023d610bfa565b60405161024a91906117ed565b60405180910390f35b61025b610c21565b60405161026891906117ed565b60405180910390f35b610279610c48565b60405161028691906113f3565b60405180910390f35b6102a960048036038101906102a49190611839565b610c7b565b6040516102b691906113f3565b60405180910390f35b6102d960048036038101906102d49190611889565b610cb7565b005b6102f560048036038101906102f0919061131a565b610d8e565b6040516103029190611958565b60405180910390f35b5f7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168267ffffffffffffffff161061034f575f9050610427565b5f61035a8484610d8e565b90505f8143610369919061199e565b90505f7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1690505f8212156103ac575f9350505050610427565b808212156103c05760019350505050610427565b8060026103cd91906119de565b8212156103e05760029350505050610427565b8060036103ed91906119de565b8212156104005760039350505050610427565b80600461040d91906119de565b8212156104205760049350505050610427565b5f93505050505b92915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b61045a86610ea4565b61046387610f14565b61046f87876001610f7f565b61047887610fea565b6104828786611159565b8467ffffffffffffffff168667ffffffffffffffff168867ffffffffffffffff167fa5074728b92791250d48ccdc55266aca7b1cca22f89e1ef2ab91ccd7ae0f337d878787876040516104d89493929190611c06565b60405180910390a450505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6002602052825f5260405f20602052815f5260405f20602052805f5260405f205f92509250509054906101000a900460ff1681565b5f602052805f5260405f205f915054906101000a900460ff1681565b61056784610ea4565b61057385856004610f7f565b61057c85610fea565b6105868584611159565b5f82829050036105c2576040517f59acc21d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f8667ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8567ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1615610689576040517f7c9a1cf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160025f8767ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8667ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055505f8282604051610735929190611c6d565b604051809103902090505f6001805f8967ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f9054906101000a900467ffffffffffffffff166107b69190611c85565b90508060015f8967ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055508467ffffffffffffffff168667ffffffffffffffff168867ffffffffffffffff167facfc0aa3f6ba36ac0ffda53e00d2cdace2fd4a9e41e2fe3214032794332c37c38787604051610887929190611cc0565b60405180910390a45f5f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16610aff575f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f90f3bed896040518263ffffffff1660e01b815260040161091e91906113f3565b602060405180830381865afa158015610939573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061095d9190611cf6565b90505f8173ffffffffffffffffffffffffffffffffffffffff1663e75235b86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109a9573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109cd9190611d35565b90508067ffffffffffffffff168367ffffffffffffffff1610610afc5760015f5f8b67ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663daade8e88a88886040518463ffffffff1660e01b8152600401610a8393929190611d60565b5f604051808303815f87803b158015610a9a575f5ffd5b505af1925050508015610aab575060015b508767ffffffffffffffff168967ffffffffffffffff167fe6c9bd3daa50b9218615605cdf333410d405b7f3b8dbeee5a2373769679aa9f58888604051610af3929190611cc0565b60405180910390a35b50505b50505050505050565b610b1184610ea4565b610b1a85610f14565b610b2685856002610f7f565b610b2f85610fea565b610b398584611159565b5f8282905003610b75576040517f2eeffe0b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8267ffffffffffffffff168467ffffffffffffffff168667ffffffffffffffff167fb5cc05e740a503c13e1b7ac3ad2d5abf41b91d2e5fca79455d34e515fb70849a8585604051610bc7929190611e4c565b60405180910390a45050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f7f0000000000000000000000000000000000000000000000000000000000000000905090565b5f7f0000000000000000000000000000000000000000000000000000000000000000905090565b5f7f00000000000000000000000000000000000000000000000000000000000000006004610c769190611e6e565b905090565b6001602052825f5260405f20602052815f5260405f20602052805f5260405f205f92509250509054906101000a900467ffffffffffffffff1681565b610cc086610ea4565b610cc987610f14565b610cd587876003610f7f565b610cde87610fea565b610ce88786611159565b818190508484905014610d27576040517fa121188700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8467ffffffffffffffff168667ffffffffffffffff168867ffffffffffffffff167f62729f0820cf3ab60fbd63a51cdeae0554d0ab24f843b86bd0d2591594d6913687878787604051610d7d9493929190611eaa565b60405180910390a450505050505050565b5f5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663636df979856040518263ffffffff1660e01b8152600401610de991906113f3565b602060405180830381865afa158015610e04573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e289190611d35565b9050610e32610c48565b67ffffffffffffffff168367ffffffffffffffff16610e5191906119de565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168267ffffffffffffffff16610e91919061199e565b610e9b9190611ee3565b91505092915050565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168167ffffffffffffffff1610610f11576040517f12f6147700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f5f8267ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1615610f7c576040517fe0f5ec9d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b806004811115610f9257610f91611358565b5b610f9c848461030b565b6004811115610fae57610fad611358565b5b14610fe5576040517fe2586bcc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f90f3bed836040518263ffffffff1660e01b815260040161104491906113f3565b602060405180830381865afa15801561105f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110839190611cf6565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff166266f0a86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111089190611cf6565b73ffffffffffffffffffffffffffffffffffffffff1614611155576040517ff62f18e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f90f3bed846040518263ffffffff1660e01b81526004016111b391906113f3565b602060405180830381865afa1580156111ce573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111f29190611cf6565b90503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16632e8e6cad846040518263ffffffff1660e01b815260040161124491906113f3565b602060405180830381865afa15801561125f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112839190611cf6565b73ffffffffffffffffffffffffffffffffffffffff16146112d0576040517f7bf9580300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82169050919050565b6112f9816112dd565b8114611303575f5ffd5b50565b5f81359050611314816112f0565b92915050565b5f5f604083850312156113305761132f6112d5565b5b5f61133d85828601611306565b925050602061134e85828601611306565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b6005811061139657611395611358565b5b50565b5f8190506113a682611385565b919050565b5f6113b582611399565b9050919050565b6113c5816113ab565b82525050565b5f6020820190506113de5f8301846113bc565b92915050565b6113ed816112dd565b82525050565b5f6020820190506114065f8301846113e4565b92915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f84011261142d5761142c61140c565b5b8235905067ffffffffffffffff81111561144a57611449611410565b5b60208301915083600182028301111561146657611465611414565b5b9250929050565b5f5f83601f8401126114825761148161140c565b5b8235905067ffffffffffffffff81111561149f5761149e611410565b5b6020830191508360208202830111156114bb576114ba611414565b5b9250929050565b5f5f5f5f5f5f5f60a0888a0312156114dd576114dc6112d5565b5b5f6114ea8a828b01611306565b97505060206114fb8a828b01611306565b965050604061150c8a828b01611306565b955050606088013567ffffffffffffffff81111561152d5761152c6112d9565b5b6115398a828b01611418565b9450945050608088013567ffffffffffffffff81111561155c5761155b6112d9565b5b6115688a828b0161146d565b925092505092959891949750929550565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6115a282611579565b9050919050565b6115b281611598565b81146115bc575f5ffd5b50565b5f813590506115cd816115a9565b92915050565b5f5f5f606084860312156115ea576115e96112d5565b5b5f6115f786828701611306565b935050602061160886828701611306565b9250506040611619868287016115bf565b9150509250925092565b5f8115159050919050565b61163781611623565b82525050565b5f6020820190506116505f83018461162e565b92915050565b5f6020828403121561166b5761166a6112d5565b5b5f61167884828501611306565b91505092915050565b5f5f5f5f5f6080868803121561169a576116996112d5565b5b5f6116a788828901611306565b95505060206116b888828901611306565b94505060406116c988828901611306565b935050606086013567ffffffffffffffff8111156116ea576116e96112d9565b5b6116f688828901611418565b92509250509295509295909350565b5f5f83601f84011261171a5761171961140c565b5b8235905067ffffffffffffffff81111561173757611736611410565b5b60208301915083602082028301111561175357611752611414565b5b9250929050565b5f5f5f5f5f60808688031215611773576117726112d5565b5b5f61178088828901611306565b955050602061179188828901611306565b94505060406117a288828901611306565b935050606086013567ffffffffffffffff8111156117c3576117c26112d9565b5b6117cf88828901611705565b92509250509295509295909350565b6117e781611598565b82525050565b5f6020820190506118005f8301846117de565b92915050565b5f819050919050565b61181881611806565b8114611822575f5ffd5b50565b5f813590506118338161180f565b92915050565b5f5f5f606084860312156118505761184f6112d5565b5b5f61185d86828701611306565b935050602061186e86828701611306565b925050604061187f86828701611825565b9150509250925092565b5f5f5f5f5f5f5f60a0888a0312156118a4576118a36112d5565b5b5f6118b18a828b01611306565b97505060206118c28a828b01611306565b96505060406118d38a828b01611306565b955050606088013567ffffffffffffffff8111156118f4576118f36112d9565b5b6119008a828b01611705565b9450945050608088013567ffffffffffffffff811115611923576119226112d9565b5b61192f8a828b0161146d565b925092505092959891949750929550565b5f819050919050565b61195281611940565b82525050565b5f60208201905061196b5f830184611949565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6119a882611940565b91506119b383611940565b925082820390508181125f8412168282135f8512151617156119d8576119d7611971565b5b92915050565b5f6119e882611940565b91506119f383611940565b9250828202611a0181611940565b91507f800000000000000000000000000000000000000000000000000000000000000084145f84121615611a3857611a37611971565b5b8282058414831517611a4d57611a4c611971565b5b5092915050565b5f82825260208201905092915050565b828183375f83830152505050565b5f601f19601f8301169050919050565b5f611a8d8385611a54565b9350611a9a838584611a64565b611aa383611a72565b840190509392505050565b5f82825260208201905092915050565b5f819050919050565b5f82825260208201905092915050565b5f611ae28385611ac7565b9350611aef838584611a64565b611af883611a72565b840190509392505050565b5f611b0f848484611ad7565b90509392505050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83356001602003843603038112611b4057611b3f611b20565b5b83810192508235915060208301925067ffffffffffffffff821115611b6857611b67611b18565b5b600182023603831315611b7e57611b7d611b1c565b5b509250929050565b5f602082019050919050565b5f611b9d8385611aae565b935083602084028501611baf84611abe565b805f5b87811015611bf4578484038952611bc98284611b24565b611bd4868284611b03565b9550611bdf84611b86565b935060208b019a505050600181019050611bb2565b50829750879450505050509392505050565b5f6040820190508181035f830152611c1f818688611a82565b90508181036020830152611c34818486611b92565b905095945050505050565b5f81905092915050565b5f611c548385611c3f565b9350611c61838584611a64565b82840190509392505050565b5f611c79828486611c49565b91508190509392505050565b5f611c8f826112dd565b9150611c9a836112dd565b9250828201905067ffffffffffffffff811115611cba57611cb9611971565b5b92915050565b5f6020820190508181035f830152611cd9818486611a82565b90509392505050565b5f81519050611cf0816115a9565b92915050565b5f60208284031215611d0b57611d0a6112d5565b5b5f611d1884828501611ce2565b91505092915050565b5f81519050611d2f816112f0565b92915050565b5f60208284031215611d4a57611d496112d5565b5b5f611d5784828501611d21565b91505092915050565b5f604082019050611d735f8301866113e4565b8181036020830152611d86818486611a82565b9050949350505050565b5f82825260208201905092915050565b5f819050919050565b611db2816112dd565b82525050565b5f611dc38383611da9565b60208301905092915050565b5f611ddd6020840184611306565b905092915050565b5f602082019050919050565b5f611dfc8385611d90565b9350611e0782611da0565b805f5b85811015611e3f57611e1c8284611dcf565b611e268882611db8565b9750611e3183611de5565b925050600181019050611e0a565b5085925050509392505050565b5f6020820190508181035f830152611e65818486611df1565b90509392505050565b5f611e78826112dd565b9150611e83836112dd565b9250828202611e91816112dd565b9150808214611ea357611ea2611971565b5b5092915050565b5f6040820190508181035f830152611ec3818688611df1565b90508181036020830152611ed8818486611b92565b905095945050505050565b5f611eed82611940565b9150611ef883611940565b92508282019050828112155f8312168382125f841215161715611f1e57611f1d611971565b5b9291505056fea164736f6c634300081c000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"phaseLength\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"dkgLeadLength\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"maxRetries\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperSetManagerAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"keyBroadcastContractAddress\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"DKG_LEAD_LENGTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MAX_RETRIES\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"PHASE_LENGTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"currentPhase\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumIDKGContract.Phase\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"cycleLength\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"dkgStart\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"int256\",\"internalType\":\"int256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"hasVoted\",\"inputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"keyBroadcastContract\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"keyperSetManager\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"submitAccusation\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"accusedIndices\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitApology\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"accuserIndices\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"polyEvalData\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitDealing\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"commitment\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"polyEvals\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitSuccessVote\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"eonPublicKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"succeeded\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"succeededAtRetry\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"voteCount\",\"inputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"AccusationSubmitted\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"accusedIndices\",\"type\":\"uint64[]\",\"indexed\":false,\"internalType\":\"uint64[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ApologySubmitted\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"accuserIndices\",\"type\":\"uint64[]\",\"indexed\":false,\"internalType\":\"uint64[]\"},{\"name\":\"polyEvalData\",\"type\":\"bytes[]\",\"indexed\":false,\"internalType\":\"bytes[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DKGSucceeded\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"eonPublicKey\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DealingSubmitted\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"commitment\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"polyEvals\",\"type\":\"bytes[]\",\"indexed\":false,\"internalType\":\"bytes[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SuccessVoteSubmitted\",\"inputs\":[{\"name\":\"keyperSetIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"retryCounter\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"keyperIndex\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"eonPublicKey\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AlreadySucceeded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AlreadyVoted\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"EmptyAccusation\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"EmptyEonPublicKey\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MaxRetriesExceeded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MismatchedArrays\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotKeyperAtIndex\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"WrongDKGContract\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"WrongPhase\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ZeroLengthParameter\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ZeroMaxRetries\",\"inputs\":[]}]", + Bin: "0x610120604052348015610010575f5ffd5b506040516123e03803806123e08339818101604052810190610032919061022f565b5f8567ffffffffffffffff16148061005357505f8467ffffffffffffffff16145b1561008a576040517f038016d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8367ffffffffffffffff16036100cd576040517fb8579f9100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8467ffffffffffffffff1660808167ffffffffffffffff16815250508367ffffffffffffffff1660a08167ffffffffffffffff16815250508267ffffffffffffffff1660c08167ffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff166101008173ffffffffffffffffffffffffffffffffffffffff168152505050505050506102a6565b5f5ffd5b5f67ffffffffffffffff82169050919050565b6101b481610198565b81146101be575f5ffd5b50565b5f815190506101cf816101ab565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6101fe826101d5565b9050919050565b61020e816101f4565b8114610218575f5ffd5b50565b5f8151905061022981610205565b92915050565b5f5f5f5f5f60a0868803121561024857610247610194565b5b5f610255888289016101c1565b9550506020610266888289016101c1565b9450506040610277888289016101c1565b93505060606102888882890161021b565b92505060806102998882890161021b565b9150509295509295909350565b60805160a05160c05160e051610100516120b76103295f395f8181610b230152610d1f01525f81816109a801528181610cf801528181610e8d015281816110c0015261122f01525f8181610349015281816105c30152610fa101525f818161046a0152610f4e01525f81816103a901528181610cd30152610d4601526120b75ff3fe608060405234801561000f575f5ffd5b50600436106100fe575f3560e01c806394afc12d11610095578063eac471a011610064578063eac471a0146102ac578063eb05c280146102ca578063f01275b0146102fa578063f48f3d1414610316576100fe565b806394afc12d14610236578063b209e71714610252578063d4b2cedd14610270578063df6406311461028e576100fe565b806346ebbdb0116100d157806346ebbdb01461019c5780637642d0de146101ba57806378a1b9db146101ea57806382b870d31461021a576100fe565b80630a3ec4d61461010257806316b89c3f1461013257806316e16061146101505780633f98009814610180575b5f5ffd5b61011c600480360381019061011791906113ed565b610346565b604051610129919061149e565b60405180910390f35b61013a610468565b60405161014791906114c6565b60405180910390f35b61016a600480360381019061016591906114df565b61048c565b60405161017791906114c6565b60405180910390f35b61019a600480360381019061019591906115c0565b610529565b005b6101a46105c1565b6040516101b191906114c6565b60405180910390f35b6101d460048036038101906101cf91906116d1565b6105e5565b6040516101e1919061173b565b60405180910390f35b61020460048036038101906101ff91906114df565b61061a565b604051610211919061173b565b60405180910390f35b610234600480360381019061022f9190611754565b610667565b005b610250600480360381019061024b919061182d565b610c03565b005b61025a610cd1565b60405161026791906114c6565b60405180910390f35b610278610cf5565b60405161028591906118c0565b60405180910390f35b610296610d1c565b6040516102a391906118c0565b60405180910390f35b6102b4610d43565b6040516102c191906114c6565b60405180910390f35b6102e460048036038101906102df919061190c565b610d76565b6040516102f191906114c6565b60405180910390f35b610314600480360381019061030f919061195c565b610db2565b005b610330600480360381019061032b91906113ed565b610e89565b60405161033d9190611a2b565b60405180910390f35b5f7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168267ffffffffffffffff161061038a575f9050610462565b5f6103958484610e89565b90505f81436103a49190611a71565b90505f7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1690505f8212156103e7575f9350505050610462565b808212156103fb5760019350505050610462565b8060026104089190611ab1565b82121561041b5760029350505050610462565b8060036104289190611ab1565b82121561043b5760039350505050610462565b8060046104489190611ab1565b82121561045b5760049350505050610462565b5f93505050505b92915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f5f5f5f8467ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f9054906101000a900467ffffffffffffffff1690505f8167ffffffffffffffff1603610514576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161050b90611b81565b60405180910390fd5b6001816105219190611b9f565b915050919050565b61053286610f9f565b61053b8761100f565b61054787876001611052565b610550876110bd565b61055a878661122c565b8467ffffffffffffffff168667ffffffffffffffff168867ffffffffffffffff167fa5074728b92791250d48ccdc55266aca7b1cca22f89e1ef2ab91ccd7ae0f337d878787876040516105b09493929190611d8c565b60405180910390a450505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6002602052825f5260405f20602052815f5260405f20602052805f5260405f205f92509250509054906101000a900460ff1681565b5f5f5f5f8467ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f9054906101000a900467ffffffffffffffff1667ffffffffffffffff1614159050919050565b61067084610f9f565b61067c85856004611052565b610685856110bd565b61068f858461122c565b5f82829050036106cb576040517f59acc21d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f8667ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8567ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1615610792576040517f7c9a1cf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160025f8767ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8667ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055505f828260405161083e929190611df3565b604051809103902090505f6001805f8967ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f9054906101000a900467ffffffffffffffff166108bf9190611e0b565b90508060015f8967ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055508467ffffffffffffffff168667ffffffffffffffff168867ffffffffffffffff167facfc0aa3f6ba36ac0ffda53e00d2cdace2fd4a9e41e2fe3214032794332c37c38787604051610990929190611e46565b60405180910390a46109a18761061a565b610bfa575f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f90f3bed896040518263ffffffff1660e01b81526004016109ff91906114c6565b602060405180830381865afa158015610a1a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a3e9190611e7c565b90505f8173ffffffffffffffffffffffffffffffffffffffff1663e75235b86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a8a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610aae9190611ebb565b90508067ffffffffffffffff168367ffffffffffffffff1610610bf757600188610ad89190611e0b565b5f5f8b67ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663daade8e88a88886040518463ffffffff1660e01b8152600401610b7e93929190611ee6565b5f604051808303815f87803b158015610b95575f5ffd5b505af1925050508015610ba6575060015b508767ffffffffffffffff168967ffffffffffffffff167fe6c9bd3daa50b9218615605cdf333410d405b7f3b8dbeee5a2373769679aa9f58888604051610bee929190611e46565b60405180910390a35b50505b50505050505050565b610c0c84610f9f565b610c158561100f565b610c2185856002611052565b610c2a856110bd565b610c34858461122c565b5f8282905003610c70576040517f2eeffe0b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8267ffffffffffffffff168467ffffffffffffffff168667ffffffffffffffff167fb5cc05e740a503c13e1b7ac3ad2d5abf41b91d2e5fca79455d34e515fb70849a8585604051610cc2929190611fd2565b60405180910390a45050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f7f0000000000000000000000000000000000000000000000000000000000000000905090565b5f7f0000000000000000000000000000000000000000000000000000000000000000905090565b5f7f00000000000000000000000000000000000000000000000000000000000000006004610d719190611ff4565b905090565b6001602052825f5260405f20602052815f5260405f20602052805f5260405f205f92509250509054906101000a900467ffffffffffffffff1681565b610dbb86610f9f565b610dc48761100f565b610dd087876003611052565b610dd9876110bd565b610de3878661122c565b818190508484905014610e22576040517fa121188700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8467ffffffffffffffff168667ffffffffffffffff168867ffffffffffffffff167f62729f0820cf3ab60fbd63a51cdeae0554d0ab24f843b86bd0d2591594d6913687878787604051610e789493929190612030565b60405180910390a450505050505050565b5f5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663636df979856040518263ffffffff1660e01b8152600401610ee491906114c6565b602060405180830381865afa158015610eff573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f239190611ebb565b9050610f2d610d43565b67ffffffffffffffff168367ffffffffffffffff16610f4c9190611ab1565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168267ffffffffffffffff16610f8c9190611a71565b610f969190612069565b91505092915050565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168167ffffffffffffffff161061100c576040517f12f6147700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b6110188161061a565b1561104f576040517fe0f5ec9d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b8060048111156110655761106461142b565b5b61106f8484610346565b60048111156110815761108061142b565b5b146110b8576040517fe2586bcc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f90f3bed836040518263ffffffff1660e01b815260040161111791906114c6565b602060405180830381865afa158015611132573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111569190611e7c565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff166266f0a86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111b7573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111db9190611e7c565b73ffffffffffffffffffffffffffffffffffffffff1614611228576040517ff62f18e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f90f3bed846040518263ffffffff1660e01b815260040161128691906114c6565b602060405180830381865afa1580156112a1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112c59190611e7c565b90503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16632e8e6cad846040518263ffffffff1660e01b815260040161131791906114c6565b602060405180830381865afa158015611332573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113569190611e7c565b73ffffffffffffffffffffffffffffffffffffffff16146113a3576040517f7bf9580300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82169050919050565b6113cc816113b0565b81146113d6575f5ffd5b50565b5f813590506113e7816113c3565b92915050565b5f5f60408385031215611403576114026113a8565b5b5f611410858286016113d9565b9250506020611421858286016113d9565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b600581106114695761146861142b565b5b50565b5f81905061147982611458565b919050565b5f6114888261146c565b9050919050565b6114988161147e565b82525050565b5f6020820190506114b15f83018461148f565b92915050565b6114c0816113b0565b82525050565b5f6020820190506114d95f8301846114b7565b92915050565b5f602082840312156114f4576114f36113a8565b5b5f611501848285016113d9565b91505092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f84011261152b5761152a61150a565b5b8235905067ffffffffffffffff8111156115485761154761150e565b5b60208301915083600182028301111561156457611563611512565b5b9250929050565b5f5f83601f8401126115805761157f61150a565b5b8235905067ffffffffffffffff81111561159d5761159c61150e565b5b6020830191508360208202830111156115b9576115b8611512565b5b9250929050565b5f5f5f5f5f5f5f60a0888a0312156115db576115da6113a8565b5b5f6115e88a828b016113d9565b97505060206115f98a828b016113d9565b965050604061160a8a828b016113d9565b955050606088013567ffffffffffffffff81111561162b5761162a6113ac565b5b6116378a828b01611516565b9450945050608088013567ffffffffffffffff81111561165a576116596113ac565b5b6116668a828b0161156b565b925092505092959891949750929550565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6116a082611677565b9050919050565b6116b081611696565b81146116ba575f5ffd5b50565b5f813590506116cb816116a7565b92915050565b5f5f5f606084860312156116e8576116e76113a8565b5b5f6116f5868287016113d9565b9350506020611706868287016113d9565b9250506040611717868287016116bd565b9150509250925092565b5f8115159050919050565b61173581611721565b82525050565b5f60208201905061174e5f83018461172c565b92915050565b5f5f5f5f5f6080868803121561176d5761176c6113a8565b5b5f61177a888289016113d9565b955050602061178b888289016113d9565b945050604061179c888289016113d9565b935050606086013567ffffffffffffffff8111156117bd576117bc6113ac565b5b6117c988828901611516565b92509250509295509295909350565b5f5f83601f8401126117ed576117ec61150a565b5b8235905067ffffffffffffffff81111561180a5761180961150e565b5b60208301915083602082028301111561182657611825611512565b5b9250929050565b5f5f5f5f5f60808688031215611846576118456113a8565b5b5f611853888289016113d9565b9550506020611864888289016113d9565b9450506040611875888289016113d9565b935050606086013567ffffffffffffffff811115611896576118956113ac565b5b6118a2888289016117d8565b92509250509295509295909350565b6118ba81611696565b82525050565b5f6020820190506118d35f8301846118b1565b92915050565b5f819050919050565b6118eb816118d9565b81146118f5575f5ffd5b50565b5f81359050611906816118e2565b92915050565b5f5f5f60608486031215611923576119226113a8565b5b5f611930868287016113d9565b9350506020611941868287016113d9565b9250506040611952868287016118f8565b9150509250925092565b5f5f5f5f5f5f5f60a0888a031215611977576119766113a8565b5b5f6119848a828b016113d9565b97505060206119958a828b016113d9565b96505060406119a68a828b016113d9565b955050606088013567ffffffffffffffff8111156119c7576119c66113ac565b5b6119d38a828b016117d8565b9450945050608088013567ffffffffffffffff8111156119f6576119f56113ac565b5b611a028a828b0161156b565b925092505092959891949750929550565b5f819050919050565b611a2581611a13565b82525050565b5f602082019050611a3e5f830184611a1c565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f611a7b82611a13565b9150611a8683611a13565b925082820390508181125f8412168282135f851215161715611aab57611aaa611a44565b5b92915050565b5f611abb82611a13565b9150611ac683611a13565b9250828202611ad481611a13565b91507f800000000000000000000000000000000000000000000000000000000000000084145f84121615611b0b57611b0a611a44565b5b8282058414831517611b2057611b1f611a44565b5b5092915050565b5f82825260208201905092915050565b7f6e6f7420737563636565646564000000000000000000000000000000000000005f82015250565b5f611b6b600d83611b27565b9150611b7682611b37565b602082019050919050565b5f6020820190508181035f830152611b9881611b5f565b9050919050565b5f611ba9826113b0565b9150611bb4836113b0565b9250828203905067ffffffffffffffff811115611bd457611bd3611a44565b5b92915050565b5f82825260208201905092915050565b828183375f83830152505050565b5f601f19601f8301169050919050565b5f611c138385611bda565b9350611c20838584611bea565b611c2983611bf8565b840190509392505050565b5f82825260208201905092915050565b5f819050919050565b5f82825260208201905092915050565b5f611c688385611c4d565b9350611c75838584611bea565b611c7e83611bf8565b840190509392505050565b5f611c95848484611c5d565b90509392505050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83356001602003843603038112611cc657611cc5611ca6565b5b83810192508235915060208301925067ffffffffffffffff821115611cee57611ced611c9e565b5b600182023603831315611d0457611d03611ca2565b5b509250929050565b5f602082019050919050565b5f611d238385611c34565b935083602084028501611d3584611c44565b805f5b87811015611d7a578484038952611d4f8284611caa565b611d5a868284611c89565b9550611d6584611d0c565b935060208b019a505050600181019050611d38565b50829750879450505050509392505050565b5f6040820190508181035f830152611da5818688611c08565b90508181036020830152611dba818486611d18565b905095945050505050565b5f81905092915050565b5f611dda8385611dc5565b9350611de7838584611bea565b82840190509392505050565b5f611dff828486611dcf565b91508190509392505050565b5f611e15826113b0565b9150611e20836113b0565b9250828201905067ffffffffffffffff811115611e4057611e3f611a44565b5b92915050565b5f6020820190508181035f830152611e5f818486611c08565b90509392505050565b5f81519050611e76816116a7565b92915050565b5f60208284031215611e9157611e906113a8565b5b5f611e9e84828501611e68565b91505092915050565b5f81519050611eb5816113c3565b92915050565b5f60208284031215611ed057611ecf6113a8565b5b5f611edd84828501611ea7565b91505092915050565b5f604082019050611ef95f8301866114b7565b8181036020830152611f0c818486611c08565b9050949350505050565b5f82825260208201905092915050565b5f819050919050565b611f38816113b0565b82525050565b5f611f498383611f2f565b60208301905092915050565b5f611f6360208401846113d9565b905092915050565b5f602082019050919050565b5f611f828385611f16565b9350611f8d82611f26565b805f5b85811015611fc557611fa28284611f55565b611fac8882611f3e565b9750611fb783611f6b565b925050600181019050611f90565b5085925050509392505050565b5f6020820190508181035f830152611feb818486611f77565b90509392505050565b5f611ffe826113b0565b9150612009836113b0565b9250828202612017816113b0565b915080821461202957612028611a44565b5b5092915050565b5f6040820190508181035f830152612049818688611f77565b9050818103602083015261205e818486611d18565b905095945050505050565b5f61207382611a13565b915061207e83611a13565b92508282019050828112155f8312168382125f8412151617156120a4576120a3611a44565b5b9291505056fea164736f6c634300081c000a", } // DkgcontractABI is the input ABI used to generate the binding from. @@ -483,10 +483,10 @@ func (_Dkgcontract *DkgcontractCallerSession) KeyperSetManager() (common.Address // Succeeded is a free data retrieval call binding the contract method 0x78a1b9db. // -// Solidity: function succeeded(uint64 ) view returns(bool) -func (_Dkgcontract *DkgcontractCaller) Succeeded(opts *bind.CallOpts, arg0 uint64) (bool, error) { +// Solidity: function succeeded(uint64 keyperSetIndex) view returns(bool) +func (_Dkgcontract *DkgcontractCaller) Succeeded(opts *bind.CallOpts, keyperSetIndex uint64) (bool, error) { var out []interface{} - err := _Dkgcontract.contract.Call(opts, &out, "succeeded", arg0) + err := _Dkgcontract.contract.Call(opts, &out, "succeeded", keyperSetIndex) if err != nil { return *new(bool), err @@ -500,16 +500,47 @@ func (_Dkgcontract *DkgcontractCaller) Succeeded(opts *bind.CallOpts, arg0 uint6 // Succeeded is a free data retrieval call binding the contract method 0x78a1b9db. // -// Solidity: function succeeded(uint64 ) view returns(bool) -func (_Dkgcontract *DkgcontractSession) Succeeded(arg0 uint64) (bool, error) { - return _Dkgcontract.Contract.Succeeded(&_Dkgcontract.CallOpts, arg0) +// Solidity: function succeeded(uint64 keyperSetIndex) view returns(bool) +func (_Dkgcontract *DkgcontractSession) Succeeded(keyperSetIndex uint64) (bool, error) { + return _Dkgcontract.Contract.Succeeded(&_Dkgcontract.CallOpts, keyperSetIndex) } // Succeeded is a free data retrieval call binding the contract method 0x78a1b9db. // -// Solidity: function succeeded(uint64 ) view returns(bool) -func (_Dkgcontract *DkgcontractCallerSession) Succeeded(arg0 uint64) (bool, error) { - return _Dkgcontract.Contract.Succeeded(&_Dkgcontract.CallOpts, arg0) +// Solidity: function succeeded(uint64 keyperSetIndex) view returns(bool) +func (_Dkgcontract *DkgcontractCallerSession) Succeeded(keyperSetIndex uint64) (bool, error) { + return _Dkgcontract.Contract.Succeeded(&_Dkgcontract.CallOpts, keyperSetIndex) +} + +// SucceededAtRetry is a free data retrieval call binding the contract method 0x16e16061. +// +// Solidity: function succeededAtRetry(uint64 keyperSetIndex) view returns(uint64) +func (_Dkgcontract *DkgcontractCaller) SucceededAtRetry(opts *bind.CallOpts, keyperSetIndex uint64) (uint64, error) { + var out []interface{} + err := _Dkgcontract.contract.Call(opts, &out, "succeededAtRetry", keyperSetIndex) + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// SucceededAtRetry is a free data retrieval call binding the contract method 0x16e16061. +// +// Solidity: function succeededAtRetry(uint64 keyperSetIndex) view returns(uint64) +func (_Dkgcontract *DkgcontractSession) SucceededAtRetry(keyperSetIndex uint64) (uint64, error) { + return _Dkgcontract.Contract.SucceededAtRetry(&_Dkgcontract.CallOpts, keyperSetIndex) +} + +// SucceededAtRetry is a free data retrieval call binding the contract method 0x16e16061. +// +// Solidity: function succeededAtRetry(uint64 keyperSetIndex) view returns(uint64) +func (_Dkgcontract *DkgcontractCallerSession) SucceededAtRetry(keyperSetIndex uint64) (uint64, error) { + return _Dkgcontract.Contract.SucceededAtRetry(&_Dkgcontract.CallOpts, keyperSetIndex) } // VoteCount is a free data retrieval call binding the contract method 0xeb05c280. diff --git a/src/common/DKGContract.sol b/src/common/DKGContract.sol index c069eae..45b82c6 100644 --- a/src/common/DKGContract.sol +++ b/src/common/DKGContract.sol @@ -62,10 +62,14 @@ contract DKGContract is IDKGContract { KeyperSetManager internal immutable _keyperSetManager; KeyBroadcastContract internal immutable _keyBroadcastContract; - // Set to true once a DKG Instance for Keyper Set Index k has reached the - // success-vote threshold. Never reset — gates the success-triggering logic - // in submitSuccessVote. - mapping(uint64 => bool) public succeeded; + // Set once a DKG Instance for Keyper Set Index k has reached the + // success-vote threshold. Stores the winning retry counter plus one so a + // single slot encodes both "did it succeed" and "which retry won"; zero + // means "not yet succeeded". Never reset once non-zero — gates the + // success-triggering logic in submitSuccessVote. Read via succeeded() and + // succeededAtRetry(); direct mapping access is internal so external + // callers cannot observe the +1 encoding. + mapping(uint64 => uint64) internal _successRetryPlusOne; mapping(uint64 => mapping(uint64 => mapping(bytes32 => uint64))) public voteCount; mapping(uint64 => mapping(uint64 => mapping(address => bool))) @@ -141,8 +145,20 @@ contract DKGContract is IDKGContract { } } + function succeeded(uint64 keyperSetIndex) public view returns (bool) { + return _successRetryPlusOne[keyperSetIndex] != 0; + } + + function succeededAtRetry( + uint64 keyperSetIndex + ) external view returns (uint64) { + uint64 v = _successRetryPlusOne[keyperSetIndex]; + require(v != 0, "not succeeded"); + return v - 1; + } + function _requireNotSucceeded(uint64 keyperSetIndex) internal view { - if (succeeded[keyperSetIndex]) { + if (succeeded(keyperSetIndex)) { revert AlreadySucceeded(); } } @@ -279,13 +295,13 @@ contract DKGContract is IDKGContract { // Late-arriving votes within the Finalizing window are accepted and // emit the event above, but do not re-trigger success once it has // already been recorded. - if (!succeeded[keyperSetIndex]) { + if (!succeeded(keyperSetIndex)) { address keyperSetAddress = _keyperSetManager.getKeyperSetAddress( keyperSetIndex ); uint64 threshold = KeyperSet(keyperSetAddress).getThreshold(); if (newCount >= threshold) { - succeeded[keyperSetIndex] = true; + _successRetryPlusOne[keyperSetIndex] = retryCounter + 1; // Errors are intentionally swallowed: if the key has already // been broadcast (or the publisher is not authorized), the DKG // outcome is still considered successful. diff --git a/src/common/intf/IDKGContract.sol b/src/common/intf/IDKGContract.sol index 488b723..61a6e3f 100644 --- a/src/common/intf/IDKGContract.sol +++ b/src/common/intf/IDKGContract.sol @@ -20,6 +20,10 @@ interface IDKGContract { function succeeded(uint64 keyperSetIndex) external view returns (bool); + function succeededAtRetry( + uint64 keyperSetIndex + ) external view returns (uint64); + function voteCount( uint64 keyperSetIndex, uint64 retryCounter, diff --git a/test/DKGContract.t.sol b/test/DKGContract.t.sol index c9a295f..8912c97 100644 --- a/test/DKGContract.t.sol +++ b/test/DKGContract.t.sol @@ -665,6 +665,36 @@ contract DKGContractTest is Test { dkgContract.submitApology(0, 1, 0, accusers, polyEvals); } + function testSucceededAtRetryReturnsWinningRetry() public { + // Drive retry 0 to Finalizing without reaching threshold, then drive + // retry 1 to success. succeededAtRetry(0) must report 1. + vm.roll(FINALIZING_BLOCK); + vm.prank(keyper0); + dkgContract.submitSuccessVote(0, 0, 0, EON_KEY_A); + // No second vote for retry 0. Roll into retry 1 Finalizing. + uint64 r1FinalizingBlock = DKG_START_R0 + + CYCLE_LENGTH + + 3 * + PHASE_LENGTH; + vm.roll(r1FinalizingBlock); + vm.prank(keyper0); + dkgContract.submitSuccessVote(0, 1, 0, EON_KEY_A); + vm.prank(keyper1); + dkgContract.submitSuccessVote(0, 1, 1, EON_KEY_A); + assertTrue(dkgContract.succeeded(0)); + assertEq(dkgContract.succeededAtRetry(0), 1); + } + + function testSucceededAtRetryRevertsBeforeSuccess() public { + vm.expectRevert("not succeeded"); + dkgContract.succeededAtRetry(0); + } + + function testSucceededAtRetryZeroForFirstRetryWin() public { + _drive_to_success_for_set0(); + assertEq(dkgContract.succeededAtRetry(0), 0); + } + function testPostSuccessSuccessVoteEmitsEventWithoutNewSuccess() public { // After success for r=0, a late vote in r=0's Finalizing window (if // still open) is accepted and emits SuccessVoteSubmitted but must not