Skip to content

Commit

Permalink
refactor: use ServiceEndpoint instead SocketAddressV4 for Node
Browse files Browse the repository at this point in the history
Signed-off-by: Ricky Saechao <[email protected]>
  • Loading branch information
RickyLB committed Aug 26, 2024
1 parent 3b1dfb5 commit 5c21298
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 82 deletions.
20 changes: 10 additions & 10 deletions Sources/Hedera/AddressBook/NodeCreateTransaction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ public final class NodeCreateTransaction: Transaction {
public init(
accountId: AccountId? = nil,
description: String = "",
gossipEndpoints: [SocketAddressV4] = [],
serviceEndpoints: [SocketAddressV4] = [],
gossipEndpoints: [Endpoint] = [],
serviceEndpoints: [Endpoint] = [],
gossipCaCertificate: Data? = nil,
grpcCertificateHash: Data? = nil,
adminKey: Key? = nil
Expand All @@ -69,8 +69,8 @@ public final class NodeCreateTransaction: Transaction {
) throws {
self.accountId = data.hasAccountID ? try .fromProtobuf(data.accountID) : nil
self.description = data.description_p
self.gossipEndpoints = try data.gossipEndpoint.map(SocketAddressV4.init)
self.serviceEndpoints = try data.serviceEndpoint.map(SocketAddressV4.init)
self.gossipEndpoints = try data.gossipEndpoint.map(Endpoint.init)
self.serviceEndpoints = try data.serviceEndpoint.map(Endpoint.init)
self.gossipCaCertificate = data.gossipCaCertificate
self.grpcCertificateHash = data.grpcCertificateHash
self.adminKey = data.hasAdminKey ? try .fromProtobuf(data.adminKey) : nil
Expand Down Expand Up @@ -109,46 +109,46 @@ public final class NodeCreateTransaction: Transaction {
}

/// A list of service endpoints for gossip.
public var gossipEndpoints: [SocketAddressV4] {
public var gossipEndpoints: [Endpoint] {
willSet {
ensureNotFrozen()
}
}

/// Assign the list of service endpoints for gossip.
@discardableResult
public func gossipEndpoints(_ gossipEndpoints: [SocketAddressV4]) -> Self {
public func gossipEndpoints(_ gossipEndpoints: [Endpoint]) -> Self {
self.gossipEndpoints = gossipEndpoints

return self
}

/// Add an endpoint for gossip to the list of service endpoints for gossip.
@discardableResult
public func addGossipEndpoint(_ gossipEndpoint: SocketAddressV4) -> Self {
public func addGossipEndpoint(_ gossipEndpoint: Endpoint) -> Self {
self.gossipEndpoints.append(gossipEndpoint)

return self
}

/// Extract the list of service endpoints for gRPC calls.
public var serviceEndpoints: [SocketAddressV4] {
public var serviceEndpoints: [Endpoint] {
willSet {
ensureNotFrozen()
}
}

/// Assign the list of service endpoints for gRPC calls.
@discardableResult
public func serviceEndpoints(_ serviceEndpoints: [SocketAddressV4]) -> Self {
public func serviceEndpoints(_ serviceEndpoints: [Endpoint]) -> Self {
self.serviceEndpoints = serviceEndpoints

return self
}

/// Add an endpoint for gRPC calls to the list of service endpoints for gRPC calls.
@discardableResult
public func addServiceEndpoint(_ serviceEndpoint: SocketAddressV4) -> Self {
public func addServiceEndpoint(_ serviceEndpoint: Endpoint) -> Self {
self.serviceEndpoints.append(serviceEndpoint)

return self
Expand Down
20 changes: 10 additions & 10 deletions Sources/Hedera/AddressBook/NodeUpdateTransaction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ public final class NodeUpdateTransaction: Transaction {
nodeId: UInt64 = 0,
accountId: AccountId? = nil,
description: String? = nil,
gossipEndpoints: [SocketAddressV4] = [],
serviceEndpoints: [SocketAddressV4] = [],
gossipEndpoints: [Endpoint] = [],
serviceEndpoints: [Endpoint] = [],
gossipCaCertificate: Data? = nil,
grpcCertificateHash: Data? = nil,
adminKey: Key? = nil
Expand All @@ -66,8 +66,8 @@ public final class NodeUpdateTransaction: Transaction {
self.nodeId = data.nodeID
self.accountId = data.hasAccountID ? try .fromProtobuf(data.accountID) : nil
self.description = data.hasDescription_p ? data.description_p.value : nil
self.gossipEndpoints = try data.gossipEndpoint.map(SocketAddressV4.init)
self.serviceEndpoints = try data.serviceEndpoint.map(SocketAddressV4.init)
self.gossipEndpoints = try data.gossipEndpoint.map(Endpoint.init)
self.serviceEndpoints = try data.serviceEndpoint.map(Endpoint.init)
self.gossipCaCertificate = data.hasGossipCaCertificate ? data.gossipCaCertificate.value : nil
self.grpcCertificateHash = data.hasGrpcCertificateHash ? data.grpcCertificateHash.value : nil
self.adminKey = data.hasAdminKey ? try .fromProtobuf(data.adminKey) : nil
Expand Down Expand Up @@ -121,46 +121,46 @@ public final class NodeUpdateTransaction: Transaction {
}

/// A list of service endpoints for gossip.
public var gossipEndpoints: [SocketAddressV4] {
public var gossipEndpoints: [Endpoint] {
willSet {
ensureNotFrozen()
}
}

/// Assign the list of service endpoints for gossip.
@discardableResult
public func gossipEndpoints(_ gossipEndpoints: [SocketAddressV4]) -> Self {
public func gossipEndpoints(_ gossipEndpoints: [Endpoint]) -> Self {
self.gossipEndpoints = gossipEndpoints

return self
}

/// Add an endpoint for gossip to the list of service endpoints for gossip.
@discardableResult
public func addGossipEndpoint(_ gossipEndpoint: SocketAddressV4) -> Self {
public func addGossipEndpoint(_ gossipEndpoint: Endpoint) -> Self {
self.gossipEndpoints.append(gossipEndpoint)

return self
}

/// Extract the list of service endpoints for gRPC calls.
public var serviceEndpoints: [SocketAddressV4] {
public var serviceEndpoints: [Endpoint] {
willSet {
ensureNotFrozen()
}
}

/// Assign the list of service endpoints for gRPC calls.
@discardableResult
public func serviceEndpoints(_ serviceEndpoints: [SocketAddressV4]) -> Self {
public func serviceEndpoints(_ serviceEndpoints: [Endpoint]) -> Self {
self.serviceEndpoints = serviceEndpoints

return self
}

/// Add an endpoint for gRPC calls to the list of service endpoints for gRPC calls.
@discardableResult
public func addServiceEndpoint(_ serviceEndpoint: SocketAddressV4) -> Self {
public func addServiceEndpoint(_ serviceEndpoint: Endpoint) -> Self {
self.serviceEndpoints.append(serviceEndpoint)

return self
Expand Down
85 changes: 85 additions & 0 deletions Sources/Hedera/Endpoint.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* ‌
* Hedera Swift SDK
* ​
* Copyright (C) 2022 - 2024 Hedera Hashgraph, LLC
* ​
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ‍
*/

import Foundation
import HederaProtobufs
import Network

public struct Endpoint {
public var ipAddress: IPv4Address? = nil

public var port: Int32 = 0

public var domainName: String = ""

public init(ipAddress: IPv4Address? = nil, port: Int32 = 0, domainName: String = "") {
self.ipAddress = ipAddress
self.port = port
self.domainName = domainName
}

@discardableResult
public mutating func address(_ ipAddress: IPv4Address) -> Self {
self.ipAddress = ipAddress
return self
}

@discardableResult
public mutating func port(_ port: Int32) -> Self {
self.port = port
return self
}

@discardableResult
public mutating func domainName(_ domainName: String) -> Self {
self.domainName = domainName
return self
}

public var description: String {
guard !domainName.isEmpty else {
return "\(ipAddress.debugDescription):\(port)"
}
return "\(domainName):\(port)"
}
}
extension Endpoint: TryProtobufCodable {
internal typealias Protobuf = Proto_ServiceEndpoint

internal init(protobuf proto: Protobuf) throws {
let ipAddress = IPv4Address(proto.ipAddressV4)

var port = proto.port

if proto.port == 0 || proto.port == 50111 {
port = 50211
}

self.init(ipAddress: ipAddress, port: port, domainName: proto.domainName)
}

internal func toProtobuf() -> Protobuf {
.with { proto in
proto.ipAddressV4 = ipAddress?.rawValue ?? Data()
proto.port = port
proto.domainName = domainName
}
}
}
4 changes: 2 additions & 2 deletions Sources/HederaProtobufs/Services/file_service.grpc.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import SwiftProtobuf


///*
/// Transactions and queries for the file service.
/// Transactions and queries for the file service.
///
/// Usage: instantiate `Proto_FileServiceClient`, then call methods of this protocol to make API calls.
public protocol Proto_FileServiceClientProtocol: GRPCClient {
Expand Down Expand Up @@ -276,7 +276,7 @@ public struct Proto_FileServiceNIOClient: Proto_FileServiceClientProtocol {
}

///*
/// Transactions and queries for the file service.
/// Transactions and queries for the file service.
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
public protocol Proto_FileServiceAsyncClientProtocol: GRPCClient {
static var serviceDescriptor: GRPCServiceDescriptor { get }
Expand Down
6 changes: 3 additions & 3 deletions Sources/HederaProtobufs/Services/network_service.grpc.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ extension Proto_NetworkServiceClientProtocol {
}

///*
/// Retrieves the time in nanoseconds spent in <tt>handleTransaction</tt> for one or more
/// TransactionIDs (assuming they have reached consensus "recently", since only a limited
/// number of execution times are kept in-memory, depending on the value of the node-local
/// Retrieves the time in nanoseconds spent in <tt>handleTransaction</tt> for one or more
/// TransactionIDs (assuming they have reached consensus "recently", since only a limited
/// number of execution times are kept in-memory, depending on the value of the node-local
/// property <tt>stats.executionTimesToTrack</tt>).
///
/// - Parameters:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import SwiftProtobuf


///*
/// Transactions and queries for the file service.
/// Transactions and queries for the file service.
///
/// Usage: instantiate `Proto_SmartContractServiceClient`, then call methods of this protocol to make API calls.
public protocol Proto_SmartContractServiceClientProtocol: GRPCClient {
Expand Down Expand Up @@ -373,7 +373,7 @@ public struct Proto_SmartContractServiceNIOClient: Proto_SmartContractServiceCli
}

///*
/// Transactions and queries for the file service.
/// Transactions and queries for the file service.
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
public protocol Proto_SmartContractServiceAsyncClientProtocol: GRPCClient {
static var serviceDescriptor: GRPCServiceDescriptor { get }
Expand Down
43 changes: 24 additions & 19 deletions Tests/HederaTests/NodeCreateTransactionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*/

import HederaProtobufs
import Network
import SnapshotTesting
import XCTest

Expand All @@ -29,8 +30,12 @@ internal final class NodeCreateTransactionTests: XCTestCase {
internal static let testGossipCertificate = Data([0x01, 0x02, 0x03, 0x04])
internal static let testGrpcCertificateHash = Data([0x05, 0x06, 0x07, 0x08])

private static func makeIpv4AddressList() throws -> [SocketAddressV4] {
[SocketAddressV4("127.0.0.1:50222")!, SocketAddressV4("127.0.0.1:50212")!]
private static func spawnTestEndpoint(offset: Int32) -> Endpoint {
Endpoint(ipAddress: IPv4Address("127.0.0.1:50222"), port: 42 + offset, domainName: "unit.test.com")
}

private static func spawnTestEndpointList(offset: Int32) -> [Endpoint] {
[Self.spawnTestEndpoint(offset: offset), Self.spawnTestEndpoint(offset: offset + 1)]
}

private static func makeTransaction() throws -> NodeCreateTransaction {
Expand All @@ -42,8 +47,8 @@ internal final class NodeCreateTransactionTests: XCTestCase {
)
.accountId(AccountId.fromString("0.0.5007"))
.description(testDescription)
.gossipEndpoints(try Self.makeIpv4AddressList())
.serviceEndpoints(try Self.makeIpv4AddressList())
.gossipEndpoints(spawnTestEndpointList(offset: 0))
.serviceEndpoints(spawnTestEndpointList(offset: 2))
.gossipCaCertificate(Self.testGossipCertificate)
.grpcCertificateHash(Self.testGrpcCertificateHash)
.adminKey(Key.single(Resources.privateKey.publicKey))
Expand All @@ -65,18 +70,18 @@ internal final class NodeCreateTransactionTests: XCTestCase {
}

internal func testFromProtoBody() throws {
let protoData = try Com_Hedera_Hapi_Node_Addressbook_NodeCreateTransactionBody.with { proto in
let gossipEndpoints = Self.spawnTestEndpointList(offset: 0)
let serviceEndpoints = Self.spawnTestEndpointList(offset: 2)
let protoData = Com_Hedera_Hapi_Node_Addressbook_NodeCreateTransactionBody.with { proto in
proto.accountID = Resources.accountId.toProtobuf()
proto.description_p = Self.testDescription
proto.gossipEndpoint = try Self.makeIpv4AddressList().map { $0.toProtobuf() }
proto.serviceEndpoint = try Self.makeIpv4AddressList().map { $0.toProtobuf() }
proto.gossipEndpoint = gossipEndpoints.map { $0.toProtobuf() }
proto.serviceEndpoint = serviceEndpoints.map { $0.toProtobuf() }
proto.gossipCaCertificate = Self.testGossipCertificate
proto.grpcCertificateHash = Self.testGrpcCertificateHash
proto.adminKey = Key.single(Resources.publicKey).toProtobuf()
}

let endpoints = try Self.makeIpv4AddressList()

let protoBody = Proto_TransactionBody.with { proto in
proto.nodeCreate = protoData
proto.transactionID = Resources.txId.toProtobuf()
Expand All @@ -93,15 +98,15 @@ internal final class NodeCreateTransactionTests: XCTestCase {
XCTAssertEqual(tx.serviceEndpoints.count, 2)

for (index, endpoint) in tx.gossipEndpoints.enumerated() {
XCTAssertEqual(endpoint.ip, endpoints[index].ip)
XCTAssertEqual(endpoint.port, endpoints[index].port)
XCTAssertEqual(endpoint.domainName, endpoints[index].domainName)
XCTAssertEqual(endpoint.ipAddress, gossipEndpoints[index].ipAddress)
XCTAssertEqual(endpoint.port, gossipEndpoints[index].port)
XCTAssertEqual(endpoint.domainName, gossipEndpoints[index].domainName)
}

for (index, endpoint) in tx.serviceEndpoints.enumerated() {
XCTAssertEqual(endpoint.ip, endpoints[index].ip)
XCTAssertEqual(endpoint.port, endpoints[index].port)
XCTAssertEqual(endpoint.domainName, endpoints[index].domainName)
XCTAssertEqual(endpoint.ipAddress, serviceEndpoints[index].ipAddress)
XCTAssertEqual(endpoint.port, serviceEndpoints[index].port)
XCTAssertEqual(endpoint.domainName, serviceEndpoints[index].domainName)
}
}

Expand All @@ -128,23 +133,23 @@ internal final class NodeCreateTransactionTests: XCTestCase {

internal func testGetSetGossipEndpoints() throws {
let tx = NodeCreateTransaction()
let endpoints = try Self.makeIpv4AddressList()
let endpoints = Self.spawnTestEndpointList(offset: Int32(0))
tx.gossipEndpoints(endpoints)

for (index, endpoint) in tx.gossipEndpoints.enumerated() {
XCTAssertEqual(endpoint.ip, endpoints[index].ip)
XCTAssertEqual(endpoint.ipAddress, endpoints[index].ipAddress)
XCTAssertEqual(endpoint.port, endpoints[index].port)
XCTAssertEqual(endpoint.domainName, endpoints[index].domainName)
}
}

internal func testGetSetServiceEndpoints() throws {
let tx = NodeCreateTransaction()
let endpoints = try Self.makeIpv4AddressList()
let endpoints = Self.spawnTestEndpointList(offset: Int32(2))
tx.serviceEndpoints(endpoints)

for (index, endpoint) in tx.serviceEndpoints.enumerated() {
XCTAssertEqual(endpoint.ip, endpoints[index].ip)
XCTAssertEqual(endpoint.ipAddress, endpoints[index].ipAddress)
XCTAssertEqual(endpoint.port, endpoints[index].port)
XCTAssertEqual(endpoint.domainName, endpoints[index].domainName)
}
Expand Down
Loading

0 comments on commit 5c21298

Please sign in to comment.