Skip to content

Implement HIP-1137 — Block Node discoverability via on-chain registry #1240

@rwalworth

Description

@rwalworth

Summary

The Hiero Rust SDK does not currently support the registered node registry introduced by HIP-1137. This issue tracks the implementation of full SDK support for creating, updating, deleting, and discovering registered nodes (Block Nodes, mirror nodes, and RPC relays) via on-chain data.

The implementation should follow the SDK design document and align with the patterns established by the existing consensus node transactions (NodeCreateTransaction, NodeUpdateTransaction, NodeDeleteTransaction).

Problem

HIP-1137 adds three new transactions to the AddressBookService and extends several existing types. Without SDK support, developers must resort to raw protobuf construction to interact with the registered node registry.

Key gaps:

  • No RegisteredNodeCreateTransaction, RegisteredNodeUpdateTransaction, or RegisteredNodeDeleteTransaction types
  • No RegisteredServiceEndpoint hierarchy (BlockNodeServiceEndpoint, MirrorNodeServiceEndpoint, RpcRelayServiceEndpoint)
  • No BlockNodeApi enum
  • TransactionReceipt does not expose the registered_node_id field
  • NodeCreateTransaction and NodeUpdateTransaction do not support the new associated_registered_nodes field
  • No RegisteredNode, RegisteredNodeAddressBook, or RegisteredNodeAddressBookQuery types

Scope of Work

New transaction types

  • RegisteredNodeCreateTransaction — creates a registered node with an admin_key, optional description, optional node_account_id, and a list of service endpoints (1–50). On success the receipt contains the network-assigned registered_node_id.
  • RegisteredNodeUpdateTransaction — updates an existing registered node by registered_node_id. Supports changing admin_key (requires both old and new key signatures), description, node_account_id, and replacing the service endpoint list.
  • RegisteredNodeDeleteTransaction — removes a registered node by registered_node_id. Must be signed by the node's admin_key or authorized by network governance.

All three transactions must be schedulable via ScheduleCreateTransaction.

New data types

  • BlockNodeApi enum — Other, Status, Publish, SubscribeStream, StateProof.
  • RegisteredServiceEndpoint — base type with ip_address (bytes) or domain_name (string), port, and requires_tls. Three concrete variants or subtypes:
    • BlockNodeServiceEndpoint — adds endpoint_api: BlockNodeApi
    • MirrorNodeServiceEndpoint — empty variant (future-proofing)
    • RpcRelayServiceEndpoint — empty variant (future-proofing)
      In Rust, this hierarchy could be modeled as an enum with variants, each containing the relevant fields, or as a trait with concrete structs.
  • RegisteredNode — immutable representation of a registered node as stored in network state.
  • RegisteredNodeAddressBook — collection of RegisteredNode objects.

New query type

  • RegisteredNodeAddressBookQuery — queries the mirror node for registered nodes and returns a RegisteredNodeAddressBook. Implementation should be deferred until the mirror node API is available, but the type skeleton should be defined.

Updates to existing types

  • TransactionReceipt — add registered_node_id: Option<u64> field.
  • NodeCreateTransaction — add associated_registered_nodes: Vec<u64> and add_associated_registered_node(registered_node_id: u64).
  • NodeUpdateTransaction — add associated_registered_nodes: Option<Vec<u64>>, add_associated_registered_node(registered_node_id: u64), and clear_associated_registered_nodes(). The protobuf uses a wrapper message for three-state semantics (not set / empty list / non-empty list).

Wiring

  • Add the new transaction types to the AnyTransactionData enum in src/transaction/any.rs.
  • Register in the schedulable transaction body mapping in src/schedule/schedulable_transaction_body.rs.
  • Re-export new public types from src/lib.rs.

Implementation Notes

Patterns to follow

The existing NodeCreateTransaction / NodeUpdateTransaction / NodeDeleteTransaction in src/address_book/ serve as the primary reference. Each new registered node transaction should follow the same pattern:

  • Define a RegisteredNodeCreateTransactionData (or similar) struct
  • Implement TransactionData trait methods (to_transaction_body_protobuf, from_protobuf, etc.)
  • Add to AnyTransactionData enum
  • Support scheduling

Endpoint types

The design document specifies an inheritance-based hierarchy. In Rust this maps naturally to an enum:

pub enum RegisteredServiceEndpoint {
    BlockNode {
        ip_address: Option<Vec<u8>>,
        domain_name: Option<String>,
        port: u32,
        requires_tls: bool,
        endpoint_api: BlockNodeApi,
    },
    MirrorNode {
        ip_address: Option<Vec<u8>>,
        domain_name: Option<String>,
        port: u32,
        requires_tls: bool,
    },
    RpcRelay {
        ip_address: Option<Vec<u8>>,
        domain_name: Option<String>,
        port: u32,
        requires_tls: bool,
    },
}

Alternatively, a base struct with a kind-specific enum field could be used. Follow whichever approach is most consistent with existing Rust SDK patterns.

Each variant needs protobuf round-trip support, following the pattern in src/service_endpoint.rs.

Key files to create or modify

New files (under src/):

  • src/address_book/registered_node_create_transaction.rs
  • src/address_book/registered_node_update_transaction.rs
  • src/address_book/registered_node_delete_transaction.rs
  • src/registered_service_endpoint.rs
  • src/block_node_api.rs
  • src/registered_node.rs
  • src/registered_node_address_book.rs
  • src/registered_node_address_book_query.rs

Existing files to update:

  • src/transaction_receipt.rs — add registered_node_id
  • src/address_book/node_create_transaction.rs — add associated_registered_nodes
  • src/address_book/node_update_transaction.rs — add associated_registered_nodes with three-state wrapper semantics
  • src/transaction/any.rs — add new types to AnyTransactionData
  • src/schedule/schedulable_transaction_body.rs — register schedulable types
  • src/lib.rs — re-export new public types

Protobuf dependencies

The implementation depends on new protobuf definitions from HIP-1137:

  • registered_node_create.proto
  • registered_node_update.proto
  • registered_node_delete.proto
  • registered_service_endpoint.proto (or equivalent)
  • Updated transaction_body.proto (fields 78–80)
  • Updated schedulable_transaction_body.proto (fields 49–51)
  • Updated transaction_receipt.proto (field 16)

Testing strategy

  1. Unit tests — verify serialization round-trips for all new types, field validation, and getter/setter correctness.
  2. Integration tests — execute the full registered node lifecycle against a test network:
    • Create a registered node with various endpoint types and verify the receipt contains a registered_node_id
    • Update the node's description, endpoints, and admin key
    • Associate a registered node with a consensus node
    • Delete the registered node
    • Verify failure cases (missing admin key, empty endpoints, non-existent node ID, already-deleted node)
  3. TCK alignment — corresponding test cases should be defined in the TCK repository per the design document's 18-point test plan.

Acceptance Criteria

  • Implement RegisteredNodeCreateTransaction, RegisteredNodeUpdateTransaction, and RegisteredNodeDeleteTransaction following existing transaction patterns
  • Implement the RegisteredServiceEndpoint types (BlockNodeServiceEndpoint, MirrorNodeServiceEndpoint, RpcRelayServiceEndpoint) and the BlockNodeApi enum
  • Implement RegisteredNode and RegisteredNodeAddressBook data types
  • Define the RegisteredNodeAddressBookQuery type skeleton
  • Update TransactionReceipt to expose registered_node_id
  • Update NodeCreateTransaction and NodeUpdateTransaction with associated_registered_nodes support
  • Add new types to AnyTransactionData and schedulable body mapping
  • Re-export all new public types from lib.rs
  • Ensure all three new transactions are schedulable
  • Include unit tests for serialization, field validation, and getter/setter correctness
  • Include integration tests covering the registered node lifecycle
  • Maintain backwards compatibility with existing APIs
  • Follow existing Rust conventions and architectural patterns
  • Pass all CI checks

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions