Skip to content

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

@rwalworth

Description

@rwalworth

Summary

The Hiero Go 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 RegisteredNodeID field
  • NodeCreateTransaction and NodeUpdateTransaction do not support the new AssociatedRegisteredNodes field
  • No RegisteredNode, RegisteredNodeAddressBook, or RegisteredNodeAddressBookQuery types

Scope of Work

New transaction types

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

All three transactions must be schedulable via ScheduleCreateTransaction.

New data types

  • BlockNodeApi enum — BlockNodeApiOther, BlockNodeApiStatus, BlockNodeApiPublish, BlockNodeApiSubscribeStream, BlockNodeApiStateProof.
  • RegisteredServiceEndpoint — base struct with IPAddress (bytes) or DomainName (string), Port, and RequiresTLS. Three concrete subtypes (or a discriminated union):
    • BlockNodeServiceEndpoint — adds EndpointApi: BlockNodeApi
    • MirrorNodeServiceEndpoint — empty subtype (future-proofing)
    • RpcRelayServiceEndpoint — empty subtype (future-proofing)
  • 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 struct skeleton should be defined.

Updates to existing types

  • TransactionReceipt — add RegisteredNodeID *uint64 field.
  • NodeCreateTransaction — add AssociatedRegisteredNodes []uint64 and AddAssociatedRegisteredNode(registeredNodeID uint64).
  • NodeUpdateTransaction — add nullable AssociatedRegisteredNodes, AddAssociatedRegisteredNode(registeredNodeID uint64), and ClearAssociatedRegisteredNodes(). The protobuf uses a wrapper message for three-state semantics (not set / empty list / non-empty list).

Wiring

  • Register the new transaction types in the transaction.go dispatch logic for deserialization from protobuf.
  • Map to protobuf oneof cases and schedulable body fields.

Implementation Notes

Patterns to follow

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

  • build() — construct the protobuf transaction body
  • _fromProtobuf() — construct from a protobuf transaction body
  • Schedule() — support scheduling
  • Setter and getter methods for all fields

Endpoint types

The design document specifies an inheritance-based endpoint hierarchy. In Go this likely maps to either:

  • An interface-based approach with RegisteredServiceEndpoint as an interface and concrete struct implementations, or
  • A single RegisteredServiceEndpoint struct with a type discriminator and optional type-specific fields

Follow whichever approach is most consistent with existing Go SDK patterns. Each type needs _fromProtobuf() / _toProtobuf() round-trip support, following the pattern in sdk/endpoint.go.

Key files to create or modify

New files (under sdk/):

  • registered_node_create_transaction.go
  • registered_node_update_transaction.go
  • registered_node_delete_transaction.go
  • registered_service_endpoint.go
  • block_node_api.go
  • registered_node.go
  • registered_node_address_book.go
  • registered_node_address_book_query.go

Existing files to update:

  • sdk/transaction_receipt.go — add RegisteredNodeID
  • sdk/node_create_transaction.go — add AssociatedRegisteredNodes
  • sdk/node_update_transaction.go — add AssociatedRegisteredNodes with three-state wrapper semantics
  • sdk/transaction.go — register new types in the dispatch logic

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 RegisteredNodeID
    • 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 struct skeleton
  • Update TransactionReceipt to expose RegisteredNodeID
  • Update NodeCreateTransaction and NodeUpdateTransaction with AssociatedRegisteredNodes support
  • Register new transaction types in transaction.go dispatch
  • 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
  • Pass all CI checks

References

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions