Skip to content

Commit

Permalink
Rpc refactoring (#227)
Browse files Browse the repository at this point in the history
* rpc wip

* wip

* server name could be null

* rpc refactoring

* show rpc methods

* fix
  • Loading branch information
xlc authored Nov 21, 2024
1 parent 7fcb90c commit 4626c64
Show file tree
Hide file tree
Showing 25 changed files with 434 additions and 190 deletions.
2 changes: 0 additions & 2 deletions Blockchain/Sources/Blockchain/State/State+Genesis.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,4 @@ extension State {

return (StateRef(state), block)
}
// TODO: add file genesis
// public static func fileGenesis(config: ProtocolConfigRef) throws -> State
}
8 changes: 8 additions & 0 deletions Blockchain/Sources/Blockchain/State/State.swift
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,14 @@ public struct State: Sendable {
await backend.rootHash
}
}

public func read(key: Data32) async throws -> Data? {
let res = try layer[key].map { try JamEncoder.encode($0) }
if let res {
return res
}
return try await backend.readRaw(key)
}
}

extension State {
Expand Down
8 changes: 6 additions & 2 deletions Blockchain/Sources/Blockchain/State/StateBackend.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,15 @@ public final class StateBackend: Sendable {
return ret
}

public func write(_ values: any Sequence<(key: any StateKey, value: (Codable & Sendable)?)>) async throws {
try await trie.update(values.map { try (key: $0.key.encode(), value: $0.value.map { try JamEncoder.encode($0) }) })
public func write(_ values: any Sequence<(key: Data32, value: (Codable & Sendable)?)>) async throws {
try await trie.update(values.map { try (key: $0.key, value: $0.value.map { try JamEncoder.encode($0) }) })
try await trie.save()
}

public func readRaw(_ key: Data32) async throws -> Data? {
try await trie.read(key: key)
}

public func writeRaw(_ values: [(key: Data32, value: Data?)]) async throws {
try await trie.update(values)
try await trie.save()
Expand Down
111 changes: 63 additions & 48 deletions Blockchain/Sources/Blockchain/State/StateLayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,190 +22,190 @@ private enum StateLayerValue: Sendable {
}

// @unchecked because AnyHashable is not Sendable
public struct StateLayer: @unchecked Sendable {
private var changes: [AnyHashable: StateLayerValue] = [:]
public struct StateLayer: Sendable {
private var changes: [Data32: StateLayerValue] = [:]

public init(backend: StateBackend) async throws {
let results = try await backend.batchRead(StateKeys.prefetchKeys)

for (key, value) in results {
changes[AnyHashable(key)] = try .init(value.unwrap())
changes[key.encode()] = try .init(value.unwrap())
}
}

public init(changes: [(key: any StateKey, value: Codable & Sendable)]) {
for (key, value) in changes {
self.changes[AnyHashable(key)] = .value(value)
self.changes[key.encode()] = .value(value)
}
}

// α: The core αuthorizations pool.
public var coreAuthorizationPool: StateKeys.CoreAuthorizationPoolKey.Value {
get {
changes[StateKeys.CoreAuthorizationPoolKey()]!.value()!
changes[StateKeys.CoreAuthorizationPoolKey().encode()]!.value()!
}
set {
changes[StateKeys.CoreAuthorizationPoolKey()] = .init(newValue)
changes[StateKeys.CoreAuthorizationPoolKey().encode()] = .init(newValue)
}
}

// φ: The authorization queue.
public var authorizationQueue: StateKeys.AuthorizationQueueKey.Value {
get {
changes[StateKeys.AuthorizationQueueKey()]!.value()!
changes[StateKeys.AuthorizationQueueKey().encode()]!.value()!
}
set {
changes[StateKeys.AuthorizationQueueKey()] = .init(newValue)
changes[StateKeys.AuthorizationQueueKey().encode()] = .init(newValue)
}
}

// β: Information on the most recent βlocks.
public var recentHistory: StateKeys.RecentHistoryKey.Value {
get {
changes[StateKeys.RecentHistoryKey()]!.value()!
changes[StateKeys.RecentHistoryKey().encode()]!.value()!
}
set {
changes[StateKeys.RecentHistoryKey()] = .init(newValue)
changes[StateKeys.RecentHistoryKey().encode()] = .init(newValue)
}
}

// γ: State concerning Safrole.
public var safroleState: StateKeys.SafroleStateKey.Value {
get {
changes[StateKeys.SafroleStateKey()]!.value()!
changes[StateKeys.SafroleStateKey().encode()]!.value()!
}
set {
changes[StateKeys.SafroleStateKey()] = .init(newValue)
changes[StateKeys.SafroleStateKey().encode()] = .init(newValue)
}
}

// ψ: past judgements
public var judgements: StateKeys.JudgementsKey.Value {
get {
changes[StateKeys.JudgementsKey()]!.value()!
changes[StateKeys.JudgementsKey().encode()]!.value()!
}
set {
changes[StateKeys.JudgementsKey()] = .init(newValue)
changes[StateKeys.JudgementsKey().encode()] = .init(newValue)
}
}

// η: The eηtropy accumulator and epochal raηdomness.
public var entropyPool: StateKeys.EntropyPoolKey.Value {
get {
changes[StateKeys.EntropyPoolKey()]!.value()!
changes[StateKeys.EntropyPoolKey().encode()]!.value()!
}
set {
changes[StateKeys.EntropyPoolKey()] = .init(newValue)
changes[StateKeys.EntropyPoolKey().encode()] = .init(newValue)
}
}

// ι: The validator keys and metadata to be drawn from next.
public var validatorQueue: StateKeys.ValidatorQueueKey.Value {
get {
changes[StateKeys.ValidatorQueueKey()]!.value()!
changes[StateKeys.ValidatorQueueKey().encode()]!.value()!
}
set {
changes[StateKeys.ValidatorQueueKey()] = .init(newValue)
changes[StateKeys.ValidatorQueueKey().encode()] = .init(newValue)
}
}

// κ: The validator κeys and metadata currently active.
public var currentValidators: StateKeys.CurrentValidatorsKey.Value {
get {
changes[StateKeys.CurrentValidatorsKey()]!.value()!
changes[StateKeys.CurrentValidatorsKey().encode()]!.value()!
}
set {
changes[StateKeys.CurrentValidatorsKey()] = .init(newValue)
changes[StateKeys.CurrentValidatorsKey().encode()] = .init(newValue)
}
}

// λ: The validator keys and metadata which were active in the prior epoch.
public var previousValidators: StateKeys.PreviousValidatorsKey.Value {
get {
changes[StateKeys.PreviousValidatorsKey()]!.value()!
changes[StateKeys.PreviousValidatorsKey().encode()]!.value()!
}
set {
changes[StateKeys.PreviousValidatorsKey()] = .init(newValue)
changes[StateKeys.PreviousValidatorsKey().encode()] = .init(newValue)
}
}

// ρ: The ρending reports, per core, which are being made available prior to accumulation.
public var reports: StateKeys.ReportsKey.Value {
get {
changes[StateKeys.ReportsKey()]!.value()!
changes[StateKeys.ReportsKey().encode()]!.value()!
}
set {
changes[StateKeys.ReportsKey()] = .init(newValue)
changes[StateKeys.ReportsKey().encode()] = .init(newValue)
}
}

// τ: The most recent block’s τimeslot.
public var timeslot: StateKeys.TimeslotKey.Value {
get {
changes[StateKeys.TimeslotKey()]!.value()!
changes[StateKeys.TimeslotKey().encode()]!.value()!
}
set {
changes[StateKeys.TimeslotKey()] = .init(newValue)
changes[StateKeys.TimeslotKey().encode()] = .init(newValue)
}
}

// χ: The privileged service indices.
public var privilegedServices: StateKeys.PrivilegedServicesKey.Value {
get {
changes[StateKeys.PrivilegedServicesKey()]!.value()!
changes[StateKeys.PrivilegedServicesKey().encode()]!.value()!
}
set {
changes[StateKeys.PrivilegedServicesKey()] = .init(newValue)
changes[StateKeys.PrivilegedServicesKey().encode()] = .init(newValue)
}
}

// π: The activity statistics for the validators.
public var activityStatistics: StateKeys.ActivityStatisticsKey.Value {
get {
changes[StateKeys.ActivityStatisticsKey()]!.value()!
changes[StateKeys.ActivityStatisticsKey().encode()]!.value()!
}
set {
changes[StateKeys.ActivityStatisticsKey()] = .init(newValue)
changes[StateKeys.ActivityStatisticsKey().encode()] = .init(newValue)
}
}

// ϑ: The accumulation queue.
public var accumulationQueue: StateKeys.AccumulationQueueKey.Value {
get {
changes[StateKeys.AccumulationQueueKey()]!.value()!
changes[StateKeys.AccumulationQueueKey().encode()]!.value()!
}
set {
changes[StateKeys.AccumulationQueueKey()] = .init(newValue)
changes[StateKeys.AccumulationQueueKey().encode()] = .init(newValue)
}
}

// ξ: The accumulation history.
public var accumulationHistory: StateKeys.AccumulationHistoryKey.Value {
get {
changes[StateKeys.AccumulationHistoryKey()]!.value()!
changes[StateKeys.AccumulationHistoryKey().encode()]!.value()!
}
set {
changes[StateKeys.AccumulationHistoryKey()] = .init(newValue)
changes[StateKeys.AccumulationHistoryKey().encode()] = .init(newValue)
}
}

// δ: The (prior) state of the service accounts.
public subscript(serviceAccount index: ServiceIndex) -> StateKeys.ServiceAccountKey.Value? {
get {
changes[StateKeys.ServiceAccountKey(index: index)]?.value()
changes[StateKeys.ServiceAccountKey(index: index).encode()]?.value()
}
set {
changes[StateKeys.ServiceAccountKey(index: index)] = .init(newValue)
changes[StateKeys.ServiceAccountKey(index: index).encode()] = .init(newValue)
}
}

// s
public subscript(serviceAccount index: ServiceIndex, storageKey key: Data32) -> StateKeys.ServiceAccountStorageKey.Value? {
get {
changes[StateKeys.ServiceAccountStorageKey(index: index, key: key)]?.value()
changes[StateKeys.ServiceAccountStorageKey(index: index, key: key).encode()]?.value()
}
set {
changes[StateKeys.ServiceAccountStorageKey(index: index, key: key)] = .init(newValue)
changes[StateKeys.ServiceAccountStorageKey(index: index, key: key).encode()] = .init(newValue)
}
}

Expand All @@ -214,10 +214,10 @@ public struct StateLayer: @unchecked Sendable {
serviceAccount index: ServiceIndex, preimageHash hash: Data32
) -> StateKeys.ServiceAccountPreimagesKey.Value? {
get {
changes[StateKeys.ServiceAccountPreimagesKey(index: index, hash: hash)]?.value()
changes[StateKeys.ServiceAccountPreimagesKey(index: index, hash: hash).encode()]?.value()
}
set {
changes[StateKeys.ServiceAccountPreimagesKey(index: index, hash: hash)] = .init(newValue)
changes[StateKeys.ServiceAccountPreimagesKey(index: index, hash: hash).encode()] = .init(newValue)
}
}

Expand All @@ -227,36 +227,51 @@ public struct StateLayer: @unchecked Sendable {
) -> StateKeys.ServiceAccountPreimageInfoKey.Value? {
get {
changes[
StateKeys.ServiceAccountPreimageInfoKey(index: index, hash: hash, length: length)
StateKeys.ServiceAccountPreimageInfoKey(
index: index, hash: hash, length: length
).encode()
]?.value()
}
set {
changes[StateKeys.ServiceAccountPreimageInfoKey(index: index, hash: hash, length: length)] = .init(newValue)
changes[
StateKeys.ServiceAccountPreimageInfoKey(
index: index, hash: hash, length: length
).encode()
] = .init(newValue)
}
}
}

extension StateLayer {
public func toKV() -> some Sequence<(key: any StateKey, value: (Codable & Sendable)?)> {
changes.map { (key: $0.key.base as! any StateKey, value: $0.value.value()) }
public func toKV() -> some Sequence<(key: Data32, value: (Codable & Sendable)?)> {
changes.map { (key: $0.key, value: $0.value.value()) }
}
}

extension StateLayer {
public func read<Key: StateKey>(_ key: Key) -> Key.Value? {
changes[key] as? Key.Value
changes[key.encode()] as? Key.Value
}

public mutating func write<Key: StateKey>(_ key: Key, value: Key.Value?) {
changes[key] = .init(value)
changes[key.encode()] = .init(value)
}

public subscript(key: any StateKey) -> (Codable & Sendable)? {
get {
changes[AnyHashable(key)]?.value()
changes[key.encode()]?.value()
}
set {
changes[key.encode()] = .init(newValue)
}
}

public subscript(key: Data32) -> (Codable & Sendable)? {
get {
changes[key]?.value()
}
set {
changes[AnyHashable(key)] = .init(newValue)
changes[key] = .init(newValue)
}
}
}
3 changes: 2 additions & 1 deletion Boka/Sources/Boka.swift
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ struct Boka: AsyncParsableCommand {
rpc: rpcConfig,
network: networkConfig,
peers: peers,
local: local
local: local,
name: name
)

let node: Node = if validator {
Expand Down
4 changes: 2 additions & 2 deletions Codec/Sources/Codec/JamEncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ public class JamEncoder {
encoder = EncodeContext(Data(capacity: capacity))
}

public func encode(_ value: some Encodable) throws {
public func encode(_ value: any Encodable) throws {
try encoder.encode(value)
}

public static func encode(_ value: some Encodable) throws -> Data {
public static func encode(_ value: any Encodable) throws -> Data {
let encoder = if let value = value as? EncodedSize {
JamEncoder(capacity: value.encodedSize)
} else {
Expand Down
2 changes: 1 addition & 1 deletion Networking/Sources/MsQuicSwift/QuicListener.swift
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ private final class ListenerHandle: Sendable {
localAddress: NetAddr(quicAddr: evtInfo.pointee.LocalAddress.pointee),
remoteAddress: NetAddr(quicAddr: evtInfo.pointee.RemoteAddress.pointee),
negotiatedAlpn: Data(bytes: evtInfo.pointee.NegotiatedAlpn, count: Int(evtInfo.pointee.NegotiatedAlpnLength)),
serverName: String(
serverName: evtInfo.pointee.ServerNameLength == 0 ? "" : String(
bytes: Data(bytes: evtInfo.pointee.ServerName, count: Int(evtInfo.pointee.ServerNameLength)),
encoding: .utf8
) ?? ""
Expand Down
2 changes: 1 addition & 1 deletion Node/Sources/Node/Genesis.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ extension Genesis {
var kv = [String: Data]()
for (key, value) in state.value.layer.toKV() {
if let value {
kv[key.encode().toHexString()] = try JamEncoder.encode(value)
kv[key.toHexString()] = try JamEncoder.encode(value)
}
}
return try ChainSpec(
Expand Down
Loading

0 comments on commit 4626c64

Please sign in to comment.