diff --git a/HIP/hip-869.md b/HIP/hip-869.md index 68537f192..be0f3956d 100644 --- a/HIP/hip-869.md +++ b/HIP/hip-869.md @@ -11,7 +11,7 @@ status: Accepted last-call-date-time: 2023-02-14T07:00:00Z created: 2024-01-22 discussions-to: https://github.com/hashgraph/hedera-improvement-proposal/pull/869 -updated: 2024-05-21 +updated: 2024-07-31 --- ## Abstract @@ -101,141 +101,273 @@ Adopting a two-phase strategy, this approach facilitated the earlier release of This HIP proposes the introduction of a new NodeService API that enables a node operator to create, delete, and update nodes. All of these transactions must be signed by the Hedera Council. ```protobuf -service NodeService { - /** - * Prepare to add a new node to the network. - * When a valid council member initiates a HAPI transaction to add a new node, - * then the network should acknowledge the transaction and update the network’s Address Book within 24 hours. - * The added node will not be active until the network is upgraded. +service AddressBookService { + /** + * A transaction to create a new consensus node in the network + * address book. + *
+ * This transaction, once complete, SHALL add a new consensus node to the
+ * network state.
+ * The new consensus node SHALL remain in state, but SHALL NOT participate
+ * in network consensus until the network updates the network configuration.
+ *
+ * Hedera governing council authorization is REQUIRED for this transaction. */ - rpc createNode (Transaction) returns (TransactionResponse); + rpc createNode (proto.Transaction) returns (proto.TransactionResponse); /** - * Prepare to delete the node to the network. - * The deleted node will not be deleted until the network is upgraded. - * Such a deleted node can never be reused. + * A transaction to remove a consensus node from the network address + * book. + *
+ * This transaction, once complete, SHALL remove the identified consensus + * node from the network state. + *
+ * Hedera governing council authorization is REQUIRED for this transaction. */ - rpc deleteNode (Transaction) returns (TransactionResponse); + rpc deleteNode (proto.Transaction) returns (proto.TransactionResponse); /** - * Prepare to update the node to the network. - * The node will not be updated until the network is upgraded. + * A transaction to update an existing consensus node from the network + * address book. + *
+ * This transaction, once complete, SHALL modify the identified consensus + * node state as requested. + *
+ * This transaction MUST be authorized by the node operator. */ - rpc updateNode (Transaction) returns (TransactionResponse); + rpc updateNode (proto.Transaction) returns (proto.TransactionResponse); } ``` A new Hedera API will be added called NodeCreate, which falls under the Node Service category. This function is used by the node operator to create a new node. To complete this transaction, both the node operator and a council member must sign it. ```protobuf -/** -* The council has to sign this transaction. This is a privileged transaction. -*/ message NodeCreateTransactionBody { + /** + * A Node account identifier. + *
+ * This account identifier MUST be in the "account number" form.
+ * This account identifier MUST NOT use the alias field.
+ * If the identified account does not exist, this transaction SHALL fail.
+ * Multiple nodes MAY share the same node account.
+ * This field is REQUIRED.
+ */
+ proto.AccountID account_id = 1;
- /**
- * Node account id, mandatory field, ALIAS is not allowed, only ACCOUNT_NUM.
- * If account_id does not exist, it will reject the transaction.
- * Multiple nodes can have the same account_id.
- */
- AccountID account_id = 1;
-
- /**
- * Description of the node with UTF-8 encoding up to 100 bytes, optional field.
- */
- string description = 2;
-
- /**
- * Ip address and port, mandatory field. Fully qualified domain name is
- * not allowed here. Maximum number of these endpoints is 10.
- * The first in the list is used as the Internal IP address in config.txt,
- * the second in the list is used as the External IP address in config.txt,
- * the rest of IP addresses are ignored for DAB phase 2.
- */
- repeated ServiceEndpoint gossip_endpoint = 3;
-
- /**
- * A node's grpc service IP addresses and ports, IP:Port is mandatory,
- * fully qualified domain name is optional. Maximum number of these endpoints is 8.
- */
- repeated ServiceEndpoint service_endpoint = 4;
-
- /**
- * The node's X509 RSA public key used to sign stream files (e.g., record stream
- * files). Precisely, this field is the public key's DER encoding.
- * This is a mandatory field.
- */
- bytes public_key = 5;
-
- /**
- * Hash of the node's TLS certificate. Precisely, this field is a string of
- * hexadecimal characters which translated to binary, are the SHA-384 hash of
- * the UTF-8 NFKD encoding of the node's TLS cert in PEM format.
- * Its value can be used to verify the node's certificate it presents
- * during TLS negotiations.node x509 certificate hash, optional field.
- */
- bytes certificate_hash = 6;
+ /**
+ * A short description of the node.
+ *
+ * This value, if set, MUST NOT exceed 100 bytes when encoded as UTF-8.
+ * This field is OPTIONAL.
+ */
+ string description = 2;
+
+ /**
+ * A list of service endpoints for gossip.
+ *
+ * These endpoints SHALL represent the published endpoints to which other
+ * consensus nodes may _gossip_ transactions.
+ * These endpoints MUST specify a port.
+ * This list MUST NOT be empty.
+ * This list MUST NOT contain more than `10` entries.
+ * The first two entries in this list SHALL be the endpoints published to
+ * all consensus nodes.
+ * All other entries SHALL be reserved for future use.
+ *
+ * Each network may have additional requirements for these endpoints.
+ * A client MUST check network-specific documentation for those
+ * details.
+ * If the network configuration value `gossipFqdnRestricted` is set, then
+ * all endpoints in this list MUST supply only IP address.
+ * If the network configuration value `gossipFqdnRestricted` is _not_ set,
+ * then endpoints in this list MAY supply either IP address or FQDN, but
+ * MUST NOT supply both values for the same endpoint.
+ */
+ repeated proto.ServiceEndpoint gossip_endpoint = 3;
+
+ /**
+ * A list of service endpoints for gRPC calls.
+ *
+ * These endpoints SHALL represent the published gRPC endpoints to which
+ * clients may submit transactions.
+ * These endpoints MUST specify a port.
+ * Endpoints in this list MAY supply either IP address or FQDN, but MUST
+ * NOT supply both values for the same endpoint.
+ * This list MUST NOT be empty.
+ * This list MUST NOT contain more than `8` entries.
+ */
+ repeated proto.ServiceEndpoint service_endpoint = 4;
+
+ /**
+ * A certificate used to sign gossip events.
+ *
+ * This value MUST be a certificate of a type permitted for gossip
+ * signatures.
+ * This value MUST be the DER encoding of the certificate presented.
+ * This field is REQUIRED and MUST NOT be empty.
+ */
+ bytes gossip_ca_certificate = 5;
+
+ /**
+ * A hash of the node gRPC TLS certificate.
+ *
+ * This value MAY be used to verify the certificate presented by the node
+ * during TLS negotiation for gRPC.
+ * This value MUST be a SHA-384 hash.
+ * The TLS certificate to be hashed MUST first be in PEM format and MUST be
+ * encoded with UTF-8 NFKD encoding to a stream of bytes provided to
+ * the hash algorithm.
+ * This field is OPTIONAL.
+ */
+ bytes grpc_certificate_hash = 6;
+
+ /**
+ * An administrative key controlled by the node operator.
+ *
+ * This key MUST sign this transaction.
+ * This key MUST sign each transaction to update this node.
+ * This field MUST contain a valid `Key` value.
+ * This field is REQUIRED and MUST NOT be set to an empty `KeyList`.
+ */
+ proto.Key admin_key = 7;
}
+
```
A new Hedera API called NodeDelete will be added under the Node Service. This API function is used by the node operator to delete a node. To perform this transaction, both the node operator and a council member need to sign it.
```protobuf
-/**
-/**
-* The council has to sign this transaction. This is a privileged transaction.
-*/
message NodeDeleteTransactionBody {
-
- /**
- * The unique id of the node to be deleted.
- */
- int64 node_id = 1;
+ /**
+ * A consensus node identifier in the network state.
+ *
+ * The node identified MUST exist in the network address book.
+ * The node identified MUST NOT be deleted.
+ * This value is REQUIRED.
+ */
+ uint64 node_id = 1;
}
```
A new Hedera API called NodeUpdate will be added under the Node Service. This function is used by the node operator to update a node. For this transaction, both the node operator and council member need to sign it.
```protobuf
-/**
-* Original node account ID has to sign this transaction.
-*/
message NodeUpdateTransactionBody {
+ /**
+ * A consensus node identifier in the network state.
+ *
+ * The node identified MUST exist in the network address book.
+ * The node identified MUST NOT be deleted.
+ * This value is REQUIRED.
+ */
+ uint64 node_id = 1;
+
+ /**
+ * An account identifier.
+ *
+ * If set, this SHALL replace the node account identifier.
+ * If set, this transaction MUST be signed by the active `key` for _both_
+ * the current node account _and_ the identified new node account.
+ */
+ proto.AccountID account_id = 2;
+
+ /**
+ * A short description of the node.
+ *
+ * This value, if set, MUST NOT exceed 100 bytes when encoded as UTF-8.
+ * If set, this value SHALL replace the previous value.
+ */
+ google.protobuf.StringValue description = 3;
+
+ /**
+ * A list of service endpoints for gossip.
+ *
+ * If set, this list MUST meet the following requirements. + *
+ * Each network may have additional requirements for these endpoints.
+ * A client MUST check network-specific documentation for those
+ * details.
+ *
Example+ *+ * Hedera Mainnet _requires_ that address be specified, and does not + * permit DNS name (FQDN) to be specified.+ *
+ * Mainnet also requires that the first entry be an "internal" IP + * address and the second entry be an "external" IP address. + *+ * Solo, however, _requires_ DNS name (FQDN) but also permits + * address. + *
+ * If set, the new list SHALL replace the existing list. + */ + repeated proto.ServiceEndpoint gossip_endpoint = 4; + + /** + * A list of service endpoints for gRPC calls. + *
+ * If set, this list MUST meet the following requirements. + *
+ * Each network may have additional requirements for these endpoints. + * A client MUST check network-specific documentation for those + * details. + *
+ * If set, the new list SHALL replace the existing list. + */ + repeated proto.ServiceEndpoint service_endpoint = 5; + + /** + * A certificate used to sign gossip events. + *
+ * This value MUST be a certificate of a type permitted for gossip
+ * signatures.
+ * This value MUST be the DER encoding of the certificate presented.
+ *
+ * If set, the new value SHALL replace the existing bytes value. + */ + google.protobuf.BytesValue gossip_ca_certificate = 6; + + /** + * A hash of the node gRPC TLS certificate. + *
+ * This value MAY be used to verify the certificate presented by the node
+ * during TLS negotiation for gRPC.
+ * This value MUST be a SHA-384 hash.
+ * The TLS certificate to be hashed MUST first be in PEM format and MUST be
+ * encoded with UTF-8 NFKD encoding to a stream of bytes provided to
+ * the hash algorithm.
+ *
+ * If set, the new value SHALL replace the existing hash value. + */ + google.protobuf.BytesValue grpc_certificate_hash = 7; - /** - * The unique id of the Node to be updated. This must refer to an existing, non-deleted node. - */ - int64 node_id = 1; - - /** - * If set, the new node account_id. - */ - AccountID account_id = 2; - - /** - * If set, the new description to be associated with the node. - */ - google.protobuf.StringValue description = 3; - - /** - * If set, the new ip address or FQDN and port. - */ - repeated ServiceEndpoint gossip_endpoint = 4; - - /** - * If set, replace the current list of service_endpoints. - */ - repeated ServiceEndpoint service_endpoint = 5; - - /** - * If set, the new public_key to be associated with the node. - */ - google.protobuf.BytesValue public_key = 6; - - /** - * If set, the new node x509 certificate hash to be associated with the node. - */ - google.protobuf.BytesValue certificate_hash = 7; + /** + * An administrative key controlled by the node operator. + *
+ * This field is OPTIONAL.
+ * If set, this key MUST sign this transaction.
+ * If set, this key MUST sign each subsequent transaction to
+ * update this node.
+ * If set, this field MUST contain a valid `Key` value.
+ * If set, this field MUST NOT be set to an empty `KeyList`.
+ */
+ proto.Key admin_key = 8;
}
```
@@ -248,20 +380,20 @@ enum HederaFunctionality {
[...]
- /**
+ /**
* Create a node
*/
- NodeCreate = 88;
+ NodeCreate = 89;
/**
* Update a node
*/
- NodeUpdate = 89;
+ NodeUpdate = 90;
/**
* Delete a node
*/
- NodeDelete = 90;
+ NodeDelete = 91;
}
```
@@ -272,10 +404,15 @@ message ServiceEndpoint {
[...]
- /**
- * The fully qualified domain name of the node, the maximum size is 253 characters.
- */
- string domain_name = 3;
+ /**
+ * A node domain name.
+ * This MUST be the fully qualified domain(DNS) name of the node.
+ * This value MUST NOT be more than 253 characters.
+ * domain_name and ipAddressV4 are mutually exclusive.
+ * When the `domain_name` field is set, the `ipAddressV4` field MUST NOT be set.
+ * When the `ipAddressV4` field is set, the `domain_name` field MUST NOT be set.
+ */
+ string domain_name = 3;
}
```
@@ -286,34 +423,134 @@ message TransactionReceipt {
[...]
- /**
- * In the receipt of a NodeCreate, the id of the newly created node.
- */
- int64 node_id = 15;
+ /**
+ * In the receipt of a NodeCreate, NodeUpdate, NodeDelete, the id of the newly created node.
+ * An affected node identifier.
+ * This value SHALL be set following a `createNode` transaction.
+ * This value SHALL be set following a `updateNode` transaction.
+ * This value SHALL be set following a `deleteNode` transaction.
+ * This value SHALL NOT be set following any other transaction.
+ */
+ uint64 node_id = 15;
+
}
```
-Added a couple of response codes.
+Added a few response codes.
```protobuf
enum ResponseCodeEnum {
[...]
- /**
- * A node is already deleted
- */
- NODE_DELETED = 333;
+ /**
+ * A transaction failed because the consensus node identified is
+ * deleted from the address book.
+ */
+ NODE_DELETED = 338;
+
+ /**
+ * A transaction failed because the consensus node identified is not valid or
+ * does not exist in state.
+ */
+ INVALID_NODE_ID = 339;
+
+ /**
+ * A transaction failed because one or more entries in the list of
+ * service endpoints for the `gossip_endpoint` field is invalid.
+ * The most common cause for this response is a service endpoint that has
+ * the domain name (DNS) set rather than address and port.
+ */
+ INVALID_GOSSIP_ENDPOINT = 340;
+
+ /**
+ * A transaction failed because the node account identifier provided
+ * does not exist or is not valid.
+ * One common source of this error is providing a node account identifier
+ * using the "alias" form rather than "numeric" form.
+ */
+ INVALID_NODE_ACCOUNT_ID = 341;
+
+ /**
+ * A transaction failed because the description field cannot be encoded
+ * as UTF-8 or is more than 100 bytes when encoded.
+ */
+ INVALID_NODE_DESCRIPTION = 342;
+
+ /**
+ * A transaction failed because one or more entries in the list of
+ * service endpoints for the `service_endpoint` field is invalid.
+ * The most common cause for this response is a service endpoint that has
+ * the domain name (DNS) set rather than address and port.
+ */
+ INVALID_SERVICE_ENDPOINT = 343;
+
+ /**
+ * A transaction failed because the TLS certificate provided for the
+ * node is missing or invalid.
+ * The certificate MUST be a TLS certificate of a type permitted for gossip
+ * signatures.
+ * The value presented MUST be a UTF-8 NFKD encoding of the TLS
+ * certificate.
+ * The certificate encoded MUST be in PEM format.
+ * The `gossip_ca_certificate` field is REQUIRED and MUST NOT be empty.
+ */
+ INVALID_GOSSIP_CA_CERTIFICATE = 344;
+
+ /**
+ * A transaction failed because the hash provided for the gRPC certificate
+ * is present but invalid.
+ * The `grpc_certificate_hash` MUST be a SHA-384 hash.
+ * The input hashed MUST be a UTF-8 NFKD encoding of the actual TLS
+ * certificate.
+ * The certificate to be encoded MUST be in PEM format.
+ */
+ INVALID_GRPC_CERTIFICATE = 345;
+
+ /**
+ * The maximum number of nodes allowed in the address book have been created.
+ */
+ MAX_NODES_CREATED = 347;
+
+ /**
+ * In ServiceEndpoint, domain_name and ipAddressV4 are mutually exclusive
+ */
+ IP_FQDN_CANNOT_BE_SET_FOR_SAME_ENDPOINT = 348;
+
+ /**
+ * Fully qualified domain name is not allowed in gossip_endpoint
+ */
+ GOSSIP_ENDPOINT_CANNOT_HAVE_FQDN = 349;
+
+ /**
+ * In ServiceEndpoint, domain_name size too large
+ */
+ FQDN_SIZE_TOO_LARGE = 350;
+
+ /**
+ * ServiceEndpoint is invalid
+ */
+ INVALID_ENDPOINT = 351;
+
+ /**
+ * The number of gossip endpoints exceeds the limit
+ */
+ GOSSIP_ENDPOINTS_EXCEEDED_LIMIT = 352;
- /**
- * A node is not found
- */
- INVALID_NODE_ID = 334;
+ /**
+ * The number of service endpoints exceeds the limit
+ */
+ SERVICE_ENDPOINTS_EXCEEDED_LIMIT = 356;
- /**
- * gossip_endpoint has a fully qualified domain name instead or ip
- */
- INVALID_GOSSIP_ENDPOINT = 335;
+ /*
+ * The IPv4 address is invalid
+ */
+ INVALID_IPV4_ADDRESS = 357;
+
+ /*
+ * The node account is not allowed to be updated
+ */
+ UPDATE_NODE_ACCOUNT_NOT_ALLOWED = 359;
}
```