Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

a basic telemetry rpc #186

Merged
merged 9 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Networking/Sources/Networking/Peer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,11 @@ public final class Peer<Handler: StreamHandler>: Sendable {
}
}
}

// there should be only one connection per peer
public func getPeersCount() -> Int {
impl.connections.value.byId.values.count
}
}

final class PeerImpl<Handler: StreamHandler>: Sendable {
Expand Down
4 changes: 4 additions & 0 deletions Node/Sources/Node/NetworkingProtocol/Network.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ public final class Network: Sendable {
public func listenAddress() throws -> NetAddr {
try peer.listenAddress()
}

public func getPeersCount() -> Int {
peer.getPeersCount()
}
}

struct HandlerDef: StreamHandler {
Expand Down
4 changes: 4 additions & 0 deletions Node/Sources/Node/NetworkingProtocol/NetworkManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ public final class NetworkManager: Sendable {
)
}
}

public func getPeersCount() -> Int {
network.getPeersCount()
}
}

struct HandlerImpl: NetworkProtocolHandler {
Expand Down
4 changes: 3 additions & 1 deletion Node/Sources/Node/Node.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,10 @@ public class Node {
devPeers: Set(config.peers)
)

let nodeDataSource = NodeDataSource(blockchain: blockchain, chainDataProvider: dataProvider, networkManager: network)

rpcServer = try config.rpc.map {
try Server(config: $0, source: blockchain)
try Server(config: $0, source: nodeDataSource)
}
}

Expand Down
35 changes: 35 additions & 0 deletions Node/Sources/Node/NodeDataSource.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import Blockchain
import RPC
import Utils

public final class NodeDataSource: DataSource {
public let blockchain: Blockchain
public let chainDataProvider: BlockchainDataProvider
public let networkManager: NetworkManager

public init(blockchain: Blockchain, chainDataProvider: BlockchainDataProvider, networkManager: NetworkManager) {
self.blockchain = blockchain
self.chainDataProvider = chainDataProvider
self.networkManager = networkManager
}

public func importBlock(_ block: BlockRef) async throws {
try await blockchain.importBlock(block)
}

public func getBestBlock() async throws -> BlockRef {
try await chainDataProvider.getBlock(hash: chainDataProvider.bestHead)
}

public func getBlock(hash: Data32) async throws -> BlockRef? {
try await chainDataProvider.getBlock(hash: hash)
}

public func getState(hash: Data32) async throws -> StateRef? {
try await chainDataProvider.getState(hash: hash)
}

public func getPeersCount() async throws -> Int {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what network info we should expose, and is it only one peer per node?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the Peer class is our own peer server, we can get number of connections from it as there should only be one connections per remote peer

networkManager.getPeersCount()
}
}
4 changes: 2 additions & 2 deletions Node/Sources/Node/ValidatorNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ public class ValidatorNode: Node {
dataProvider: dataProvider
)

let genesisState = try await blockchain.getState(hash: blockchain.dataProvider.genesisBlockHash)
let genesisState = try await dataProvider.getState(hash: blockchain.dataProvider.genesisBlockHash)

await validator.on(genesis: genesisState!)
await validator.on(genesis: genesisState)
}
}
16 changes: 0 additions & 16 deletions RPC/Sources/RPC/DataSource/Blockchain+DataSource.swift

This file was deleted.

3 changes: 2 additions & 1 deletion RPC/Sources/RPC/DataSource/DataSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Utils
public protocol DataSource: Sendable {
func getBestBlock() async throws -> BlockRef
func getBlock(hash: Data32) async throws -> BlockRef?

func importBlock(_: BlockRef) async throws
func getState(hash: Data32) async throws -> StateRef?
func getPeersCount() async throws -> Int
}
34 changes: 32 additions & 2 deletions RPC/Sources/RPC/Handlers/ChainHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ struct ChainHandler {

return [
"chain_getBlock": handler.getBlock,
"chain_getState": handler.getState,
]
}

Expand All @@ -20,10 +21,39 @@ struct ChainHandler {
throw JSONError(code: -32602, message: "Invalid block hash")
}
let block = try await source.getBlock(hash: data32)
return block.map { ["hash": $0.hash.description, "parentHash": $0.header.parentHash.description] }
return block.map { [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just return block, which implements Encodable

"hash": $0.hash.description,
"parentHash": $0.header.parentHash.description,
] }
} else {
let block = try await source.getBestBlock()
return ["hash": block.hash.description, "parentHash": block.header.parentHash.description]
return [
"hash": block.hash.description,
"parentHash": block.header.parentHash.description,
]
}
}

func getState(request: JSONRequest) async throws -> any Encodable {
let hash = request.params?["hash"] as? String
if let hash {
guard let data = Data(fromHexString: hash), let data32 = Data32(data) else {
throw JSONError(code: -32602, message: "Invalid block hash")
}
let state = try await source.getState(hash: data32)
// return state root for now
return [
"stateRoot": state?.stateRoot.description,
"blockHash": hash.description,
]
} else {
// return best block state by default
let block = try await source.getBestBlock()
let state = try await source.getState(hash: block.hash)
return [
"stateRoot": state?.stateRoot.description,
"blockHash": block.hash.description,
]
}
}
}
5 changes: 5 additions & 0 deletions RPC/Sources/RPC/Handlers/SystemHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ struct SystemHandler {

return [
"system_health": handler.health,
"system_name": handler.name,
]
}

func health(request _: JSONRequest) async throws -> any Encodable {
true
}

func name(request _: JSONRequest) async throws -> any Encodable {
"Boka"
}
}
26 changes: 26 additions & 0 deletions RPC/Sources/RPC/Handlers/TelemetryHandler.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Blockchain
import Foundation
import Utils

struct TelemetryHandler {
let source: DataSource

static func getHandlers(source: DataSource) -> [String: JSONRPCHandler] {
let handler = TelemetryHandler(source: source)

return [
"telemetry_getUpdate": handler.getUpdate,
]
}

func getUpdate(request _: JSONRequest) async throws -> any Encodable {
let block = try await source.getBestBlock()
let peerCount = try await source.getPeersCount()
return [
"name": "Boka",
"chainHead": block.header.timeslot.description,
"blockHash": block.hash.description,
"peerCount": peerCount.description,
]
}
}
1 change: 1 addition & 0 deletions RPC/Sources/RPC/Server.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class Server {

var handlers: [String: JSONRPCHandler] = SystemHandler.getHandlers()
handlers.merge(ChainHandler.getHandlers(source: source)) { _, new in new }
handlers.merge(TelemetryHandler.getHandlers(source: source)) { _, new in new }

// Register routes
let rpcController = JSONRPCController(handlers: handlers)
Expand Down
25 changes: 0 additions & 25 deletions RPC/Tests/RPCTests/MockDataSource.swift

This file was deleted.