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

Rpc refactoring #227

Merged
merged 7 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
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