From 1160b312f13e3821680c9edff2a68cb380992f86 Mon Sep 17 00:00:00 2001 From: Hyunsoo Shin Date: Fri, 24 Apr 2026 14:13:30 +0900 Subject: [PATCH 1/2] feat(kip-290): sync interface with kaia#871, #872, #876 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add string name field to NodeInfo struct (between blsInfo and metadata) - Remove name from metadata JSON schema; add note that name is a top-level NodeInfo field - Update NodeCreated event: remove gcId param (now assigned via assignGcId) - Update EpochTransitionProcessed: slotFactor → epochVACount - Update processSystemTransition: epochSlotFactor → epochVACount - Add errors: OnlySuspender, OnlyConfigurator, InsufficientNodeBalance, GcIdAlreadyAssigned, GcIdNotAssigned - Add events: ValidatorSuspended, ValidatorUnsuspended, SuspenderUpdated, ConfiguratorUpdated - Add admin functions: updateSuspender, updateConfigurator, assignGcId, revokeGcId - Update createNode signature: add name param before metadata - Update admin section: reflect suspender/configurator roles - Add getters: getSuspender, getConfigurator, getEpochVACount (replaces getSlotFactor) Co-Authored-By: Claude Sonnet 4.6 --- KIPs/kip-290.md | 51 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/KIPs/kip-290.md b/KIPs/kip-290.md index d221085..49028b0 100644 --- a/KIPs/kip-290.md +++ b/KIPs/kip-290.md @@ -84,6 +84,8 @@ struct NodeInfo { uint256 gcId; /// @dev BLS public key and proof-of-possession (immutable) BlsPublicKeyInfo blsInfo; + /// @dev Human-readable node name (mutable) + string name; /// @dev Validator metadata in JSON format (mutable) string metadata; /// @dev Current state of the node @@ -118,9 +120,10 @@ enum State { The `metadata` field in `NodeInfo` is a JSON-encoded string. All fields are optional. Unrecognized fields SHOULD be ignored by readers. +> **Note**: The node operator name is stored as the top-level `name` field in `NodeInfo` (a required parameter of `createNode`), not inside `metadata`. + | Field | Type | Description | | ------------- | -------- | ---------------------------------- | -| `name` | string | Human-readable node operator name | | `thumbnail` | string | URL to operator thumbnail/logo | | `summary` | string | Short description | | `description` | string | Long description | @@ -132,7 +135,6 @@ Example: ```json { - "name": "Kaia Foundation", "thumbnail": "https://cdn.prod.website-files.com/66a8ba5239a3fbe8e678da2a/69866193d03bf54b81aa0283_66ce395e60f880698890073dcc91fa28_kaia-logo.svg", "summary": "The organization behind the Kaia blockchain.", "description": "The Kaia Foundation is the organization behind the Kaia blockchain, an EVM-compatible Layer 1 built for stablecoin settlement and onchain finance across Asia.", @@ -144,7 +146,7 @@ Example: #### Interface -AddressBookV2 replaces the existing AddressBook at `0x0000000000000000000000000000000000000400` starting from `FORK_BLOCK`. The interface is divided into user functions (called by node manager), system functions (called by core client via system transaction following [EIP-4788](https://eips.ethereum.org/EIPS/eip-4788) convention), and admin functions (called by contract owner). +AddressBookV2 replaces the existing AddressBook at `0x0000000000000000000000000000000000000400` starting from `FORK_BLOCK`. The interface is divided into user functions (called by node manager), system functions (called by core client via system transaction following [EIP-4788](https://eips.ethereum.org/EIPS/eip-4788) convention), and admin functions (called by contract owner or designated roles). ```solidity pragma solidity ^0.8.0; @@ -152,19 +154,41 @@ pragma solidity ^0.8.0; import {State, BlsPublicKeyInfo, NodeInfo, Profile} from "./types/Node.sol"; interface IAddressBookV2 { + // ── Errors ── + error OnlySuspender(); + error OnlyConfigurator(); + error InvalidState(); + error SlotsFull(); + error InvalidInput(); + error StakingTooLow(); + error NodeAlreadyExists(); + error NodeNotFound(); + error TimeoutExpired(); + error AlreadySuspended(); + error NotSuspended(); + error PDEnabled(); + error InsufficientNodeBalance(); + error GcIdAlreadyAssigned(); + error GcIdNotAssigned(); + // ── Events ── event StateChanged(address indexed nodeId, State indexed fromState, State indexed toState); - event NodeCreated(address indexed nodeId, uint256 gcId); + event NodeCreated(address indexed nodeId); event NodeDeleted(address indexed nodeId); + event ValidatorSuspended(address indexed nodeId); + event ValidatorUnsuspended(address indexed nodeId); event SystemTransitionProcessed(address[] nodeIds, State[] newStates); event EpochTransitionProcessed(uint256 epochVACount); + event SuspenderUpdated(address oldSuspender, address newSuspender); + event ConfiguratorUpdated(address oldConfigurator, address newConfigurator); // ── User Functions (called by node manager) ── - /// @notice Register a new node in Registered state + /// @notice Register a new node in Registered state; name must be non-empty function createNode( address nodeId, address stakingContract, address rewardAddress, - address voterAddress, BlsPublicKeyInfo memory blsInfo, string memory metadata + address voterAddress, BlsPublicKeyInfo memory blsInfo, + string memory name, string memory metadata ) external; /// @notice Remove a Registered node entirely @@ -207,10 +231,21 @@ interface IAddressBookV2 { uint256 epochVACount ) external; - // ── Admin Functions (called by contract owner) ── + // ── Admin Functions ── + /// @notice Emergency suspension (called by suspender) function suspendValidator(address nodeId) external; + /// @notice Lift suspension (called by suspender) function unsuspendValidator(address nodeId) external; + /// @notice Update suspender address (called by owner) + function updateSuspender(address newSuspender) external; + /// @notice Update configurator address (called by owner) + function updateConfigurator(address newConfigurator) external; + /// @notice Assign auto-incremented gcId to a node (called by configurator) + function assignGcId(address nodeId) external; + /// @notice Revoke gcId from a node, setting it back to 0 (called by configurator) + function revokeGcId(address nodeId) external; + function updatePauseTimeout(uint256 newPauseTimeout) external; function updateIdleTimeout(uint256 newIdleTimeout) external; function updateMaxNodeCount(uint256 newMaxNodeCount) external; @@ -221,6 +256,8 @@ interface IAddressBookV2 { // ── Getters ── + function getSuspender() external view returns (address); + function getConfigurator() external view returns (address); function getNodeInfo(address nodeId) external view returns (NodeInfo memory); function getNodeInfos(address[] calldata nodeIds) external view returns (NodeInfo[] memory); function getAllProfiles() external view returns (Profile[] memory); From ba132377754304526381da91a561ae364684a441 Mon Sep 17 00:00:00 2001 From: Hyunsoo Shin Date: Thu, 30 Apr 2026 17:05:53 +0900 Subject: [PATCH 2/2] feat(kip-290): sync events with system-contracts PR #157 - Replace SuspenderUpdated/ConfiguratorUpdated with unified AddressConfigUpdated - Add UintConfigUpdated for config update events - Add GcIdAssigned, CandidateReadied, CandidateUnreadied, ValidatorsInitialized Co-Authored-By: Claude Sonnet 4.6 --- KIPs/kip-290.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/KIPs/kip-290.md b/KIPs/kip-290.md index 49028b0..e08e12b 100644 --- a/KIPs/kip-290.md +++ b/KIPs/kip-290.md @@ -174,13 +174,17 @@ interface IAddressBookV2 { // ── Events ── event StateChanged(address indexed nodeId, State indexed fromState, State indexed toState); event NodeCreated(address indexed nodeId); + event GcIdAssigned(address indexed nodeId, uint256 gcId); event NodeDeleted(address indexed nodeId); event ValidatorSuspended(address indexed nodeId); event ValidatorUnsuspended(address indexed nodeId); + event CandidateReadied(address indexed nodeId); + event CandidateUnreadied(address indexed nodeId); + event ValidatorsInitialized(address[] nodeIds); event SystemTransitionProcessed(address[] nodeIds, State[] newStates); event EpochTransitionProcessed(uint256 epochVACount); - event SuspenderUpdated(address oldSuspender, address newSuspender); - event ConfiguratorUpdated(address oldConfigurator, address newConfigurator); + event UintConfigUpdated(uint8 indexed configId, uint256 oldValue, uint256 newValue); + event AddressConfigUpdated(uint8 indexed configId, address oldValue, address newValue); // ── User Functions (called by node manager) ──