Skip to content

Commit 346f855

Browse files
authored
feat(hip-869): added DAB Node operations
1 parent 3c4de74 commit 346f855

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+3418
-28
lines changed

Package.resolved

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ let package = Package(
8888
.package(url: "https://github.com/objecthub/swift-numberkit.git", from: "2.4.1"),
8989
.package(url: "https://github.com/thebarndog/swift-dotenv.git", from: "1.0.0"),
9090
.package(url: "https://github.com/grpc/grpc-swift.git", from: "1.23.0"),
91-
.package(url: "https://github.com/apple/swift-protobuf.git", from: "1.6.0"),
91+
.package(url: "https://github.com/apple/swift-protobuf.git", from: "1.26.0"),
9292
.package(url: "https://github.com/vsanthanam/AnyAsyncSequence.git", from: "1.0.0"),
9393
.package(url: "https://github.com/apple/swift-atomics.git", from: "1.1.0"),
9494
// swift-asn1 wants swift 5.7+ past 0.4
Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
/*
2+
* ‌
3+
* Hedera Swift SDK
4+
* ​
5+
* Copyright (C) 2022 - 2024 Hedera Hashgraph, LLC
6+
* ​
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
* ‍
19+
*/
20+
21+
import Foundation
22+
import GRPC
23+
import HederaProtobufs
24+
import SwiftProtobuf
25+
26+
/// A transaction body to add a new consensus node to the network address book.
27+
///
28+
/// This transaction body SHALL be considered a "privileged transaction".
29+
///
30+
/// This message supports a transaction to create a new node in the network
31+
/// address book. The transaction, once complete, enables a new consensus node
32+
/// to join the network, and requires governing council authorization.
33+
///
34+
/// - A `NodeCreateTransactionBody` MUST be signed by the governing council.
35+
/// - A `NodeCreateTransactionBody` MUST be signed by the `Key` assigned to the
36+
/// `admin_key` field.
37+
/// - The newly created node information SHALL be added to the network address
38+
/// book information in the network state.
39+
/// - The new entry SHALL be created in "state" but SHALL NOT participate in
40+
/// network consensus and SHALL NOT be present in network "configuration"
41+
/// until the next "upgrade" transaction (as noted below).
42+
/// - All new address book entries SHALL be added to the active network
43+
/// configuration during the next `freeze` transaction with the field
44+
/// `freeze_type` set to `PREPARE_UPGRADE`.
45+
///
46+
public final class NodeCreateTransaction: Transaction {
47+
public init(
48+
accountId: AccountId? = nil,
49+
description: String = "",
50+
gossipEndpoints: [Endpoint] = [],
51+
serviceEndpoints: [Endpoint] = [],
52+
gossipCaCertificate: Data? = nil,
53+
grpcCertificateHash: Data? = nil,
54+
adminKey: Key? = nil
55+
) {
56+
self.accountId = accountId
57+
self.description = description
58+
self.gossipEndpoints = gossipEndpoints
59+
self.serviceEndpoints = serviceEndpoints
60+
self.gossipCaCertificate = gossipCaCertificate
61+
self.grpcCertificateHash = grpcCertificateHash
62+
self.adminKey = adminKey
63+
64+
super.init()
65+
}
66+
67+
internal init(
68+
protobuf proto: Proto_TransactionBody, _ data: Com_Hedera_Hapi_Node_Addressbook_NodeCreateTransactionBody
69+
) throws {
70+
self.accountId = data.hasAccountID ? try .fromProtobuf(data.accountID) : nil
71+
self.description = data.description_p
72+
self.gossipEndpoints = try data.gossipEndpoint.map(Endpoint.init)
73+
self.serviceEndpoints = try data.serviceEndpoint.map(Endpoint.init)
74+
self.gossipCaCertificate = data.gossipCaCertificate
75+
self.grpcCertificateHash = data.grpcCertificateHash
76+
self.adminKey = data.hasAdminKey ? try .fromProtobuf(data.adminKey) : nil
77+
78+
try super.init(protobuf: proto)
79+
}
80+
81+
/// Node account ID.
82+
public var accountId: AccountId? {
83+
willSet {
84+
ensureNotFrozen()
85+
}
86+
}
87+
88+
/// Sets the node account
89+
@discardableResult
90+
public func accountId(_ accountId: AccountId?) -> Self {
91+
self.accountId = accountId
92+
93+
return self
94+
}
95+
96+
/// Returns the nodes description.
97+
public var description: String {
98+
willSet {
99+
ensureNotFrozen()
100+
}
101+
}
102+
103+
/// Sets the node's description.
104+
@discardableResult
105+
public func description(_ description: String) -> Self {
106+
self.description = description
107+
108+
return self
109+
}
110+
111+
/// A list of service endpoints for gossip.
112+
public var gossipEndpoints: [Endpoint] {
113+
willSet {
114+
ensureNotFrozen()
115+
}
116+
}
117+
118+
/// Assign the list of service endpoints for gossip.
119+
@discardableResult
120+
public func gossipEndpoints(_ gossipEndpoints: [Endpoint]) -> Self {
121+
self.gossipEndpoints = gossipEndpoints
122+
123+
return self
124+
}
125+
126+
/// Add an endpoint for gossip to the list of service endpoints for gossip.
127+
@discardableResult
128+
public func addGossipEndpoint(_ gossipEndpoint: Endpoint) -> Self {
129+
self.gossipEndpoints.append(gossipEndpoint)
130+
131+
return self
132+
}
133+
134+
/// Extract the list of service endpoints for gRPC calls.
135+
public var serviceEndpoints: [Endpoint] {
136+
willSet {
137+
ensureNotFrozen()
138+
}
139+
}
140+
141+
/// Assign the list of service endpoints for gRPC calls.
142+
@discardableResult
143+
public func serviceEndpoints(_ serviceEndpoints: [Endpoint]) -> Self {
144+
self.serviceEndpoints = serviceEndpoints
145+
146+
return self
147+
}
148+
149+
/// Add an endpoint for gRPC calls to the list of service endpoints for gRPC calls.
150+
@discardableResult
151+
public func addServiceEndpoint(_ serviceEndpoint: Endpoint) -> Self {
152+
self.serviceEndpoints.append(serviceEndpoint)
153+
154+
return self
155+
}
156+
157+
/// Extract the certificate used to sign gossip events.
158+
public var gossipCaCertificate: Data? {
159+
willSet {
160+
ensureNotFrozen()
161+
}
162+
}
163+
164+
/// Sets the certificate used to sign gossip events.
165+
@discardableResult
166+
public func gossipCaCertificate(_ gossipCaCertificate: Data) -> Self {
167+
self.gossipCaCertificate = gossipCaCertificate
168+
169+
return self
170+
}
171+
172+
/// Extract the hash of the node gRPC TLS certificate.
173+
public var grpcCertificateHash: Data? {
174+
willSet {
175+
ensureNotFrozen()
176+
}
177+
}
178+
179+
/// Sets the hash of the node gRPC TLS certificate.
180+
@discardableResult
181+
public func grpcCertificateHash(_ grpcCertificateHash: Data) -> Self {
182+
self.grpcCertificateHash = grpcCertificateHash
183+
184+
return self
185+
}
186+
187+
/// Get an administrative key controlled by the node operator.
188+
public var adminKey: Key? {
189+
willSet {
190+
ensureNotFrozen()
191+
}
192+
}
193+
194+
/// Sets an administrative key controlled by the node operator.
195+
@discardableResult
196+
public func adminKey(_ adminKey: Key) -> Self {
197+
self.adminKey = adminKey
198+
199+
return self
200+
}
201+
202+
internal override func validateChecksums(on ledgerId: LedgerId) throws {
203+
try accountId?.validateChecksums(on: ledgerId)
204+
try super.validateChecksums(on: ledgerId)
205+
}
206+
207+
internal override func transactionExecute(_ channel: GRPCChannel, _ request: Proto_Transaction) async throws
208+
-> Proto_TransactionResponse
209+
{
210+
try await Proto_AddressBookServiceAsyncClient(channel: channel).createNode(request)
211+
}
212+
213+
internal override func toTransactionDataProtobuf(_ chunkInfo: ChunkInfo) -> Proto_TransactionBody.OneOf_Data {
214+
_ = chunkInfo.assertSingleTransaction()
215+
216+
return .nodeCreate(toProtobuf())
217+
}
218+
}
219+
220+
extension NodeCreateTransaction: ToProtobuf {
221+
internal typealias Protobuf = Com_Hedera_Hapi_Node_Addressbook_NodeCreateTransactionBody
222+
223+
internal func toProtobuf() -> Protobuf {
224+
.with { proto in
225+
accountId?.toProtobufInto(&proto.accountID)
226+
proto.description_p = description
227+
proto.gossipEndpoint = gossipEndpoints.map { $0.toProtobuf() }
228+
proto.serviceEndpoint = serviceEndpoints.map { $0.toProtobuf() }
229+
proto.gossipCaCertificate = gossipCaCertificate ?? Data()
230+
proto.grpcCertificateHash = grpcCertificateHash ?? Data()
231+
if let adminKey = adminKey {
232+
proto.adminKey = adminKey.toProtobuf()
233+
}
234+
}
235+
}
236+
}
237+
238+
extension NodeCreateTransaction {
239+
internal func toSchedulableTransactionData() -> Proto_SchedulableTransactionBody.OneOf_Data {
240+
.nodeCreate(toProtobuf())
241+
}
242+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* ‌
3+
* Hedera Swift SDK
4+
* ​
5+
* Copyright (C) 2022 - 2024 Hedera Hashgraph, LLC
6+
* ​
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
* ‍
19+
*/
20+
21+
import Foundation
22+
import GRPC
23+
import HederaProtobufs
24+
import SwiftProtobuf
25+
26+
/// A transaction body to delete a node from the network address book.
27+
///
28+
/// This transaction body SHALL be considered a "privileged transaction".
29+
///
30+
/// - A `NodeDeleteTransactionBody` MUST be signed by the governing council.
31+
/// - Upon success, the address book entry SHALL enter a "pending delete"
32+
/// state.
33+
/// - All address book entries pending deletion SHALL be removed from the
34+
/// active network configuration during the next `freeze` transaction with
35+
/// the field `freeze_type` set to `PREPARE_UPGRADE`.<br/>
36+
/// - A deleted address book node SHALL be removed entirely from network state.
37+
/// - A deleted address book node identifier SHALL NOT be reused.
38+
public final class NodeDeleteTransaction: Transaction {
39+
public init(
40+
nodeId: UInt64 = 0
41+
) {
42+
self.nodeId = nodeId
43+
super.init()
44+
}
45+
46+
internal init(
47+
protobuf proto: Proto_TransactionBody, _ data: Com_Hedera_Hapi_Node_Addressbook_NodeDeleteTransactionBody
48+
) throws {
49+
self.nodeId = data.nodeID
50+
51+
try super.init(protobuf: proto)
52+
}
53+
54+
/// Node index to delete.
55+
public var nodeId: UInt64 {
56+
willSet {
57+
ensureNotFrozen()
58+
}
59+
}
60+
61+
/// Sets the node index to delete.
62+
@discardableResult
63+
public func nodeId(_ nodeId: UInt64) -> Self {
64+
self.nodeId = nodeId
65+
66+
return self
67+
}
68+
69+
internal override func validateChecksums(on ledgerId: LedgerId) throws {}
70+
71+
internal override func transactionExecute(_ channel: GRPCChannel, _ request: Proto_Transaction) async throws
72+
-> Proto_TransactionResponse
73+
{
74+
try await Proto_AddressBookServiceAsyncClient(channel: channel).deleteNode(request)
75+
}
76+
77+
internal override func toTransactionDataProtobuf(_ chunkInfo: ChunkInfo) -> Proto_TransactionBody.OneOf_Data {
78+
_ = chunkInfo.assertSingleTransaction()
79+
80+
return .nodeDelete(toProtobuf())
81+
}
82+
}
83+
84+
extension NodeDeleteTransaction: ToProtobuf {
85+
internal typealias Protobuf = Com_Hedera_Hapi_Node_Addressbook_NodeDeleteTransactionBody
86+
87+
internal func toProtobuf() -> Protobuf {
88+
.with { proto in
89+
proto.nodeID = nodeId
90+
}
91+
}
92+
}
93+
94+
extension NodeDeleteTransaction {
95+
internal func toSchedulableTransactionData() -> Proto_SchedulableTransactionBody.OneOf_Data {
96+
.nodeDelete(toProtobuf())
97+
}
98+
}

0 commit comments

Comments
 (0)