diff --git a/Blockchain/Package.resolved b/Blockchain/Package.resolved index fdd3bd60..2a4fb336 100644 --- a/Blockchain/Package.resolved +++ b/Blockchain/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "72d6aa1fce2803c836be5d4b1c239fb67e531e7ed4619f96c34745064c756ba8", + "originHash" : "70f026b0b2979b5824592ab2cbdf4ae1a235fd69ecef967a7fbc6585ba704548", "pins" : [ { "identity" : "blake2.swift", @@ -76,10 +76,10 @@ { "identity" : "swift-syntax", "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-syntax.git", + "location" : "https://github.com/swiftlang/swift-syntax.git", "state" : { - "revision" : "4c6cc0a3b9e8f14b3ae2307c5ccae4de6167ac2c", - "version" : "600.0.0-prerelease-2024-06-12" + "revision" : "0687f71944021d616d34d922343dcef086855920", + "version" : "600.0.1" } }, { @@ -87,8 +87,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-testing.git", "state" : { - "branch" : "0.10.0", - "revision" : "69d59cfc76e5daf498ca61f5af409f594768eef9" + "branch" : "release/6.0", + "revision" : "18c42c19cac3fafd61cab1156d4088664b7424ae" } } ], diff --git a/Blockchain/Package.swift b/Blockchain/Package.swift index 9f02304c..9976fd04 100644 --- a/Blockchain/Package.swift +++ b/Blockchain/Package.swift @@ -20,7 +20,7 @@ let package = Package( .package(path: "../Utils"), .package(path: "../TracingUtils"), .package(path: "../PolkaVM"), - .package(url: "https://github.com/apple/swift-testing.git", branch: "0.10.0"), + .package(url: "https://github.com/apple/swift-testing.git", branch: "6.0.0"), ], targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. diff --git a/Blockchain/Sources/Blockchain/Blockchain.swift b/Blockchain/Sources/Blockchain/Blockchain.swift index d7e36c3a..42a8e019 100644 --- a/Blockchain/Sources/Blockchain/Blockchain.swift +++ b/Blockchain/Sources/Blockchain/Blockchain.swift @@ -33,7 +33,10 @@ public final class Blockchain: ServiceBase, @unchecked Sendable { logger.debug("block already imported", metadata: ["hash": "\(block.hash)"]) return } - + // TODO: if current block is light + // check if dataProvider.hasGuaranteedWorkReport + // send workReportDistribution waiting for response + // save to full block try await withSpan("importBlock") { span in span.attributes.blockHash = block.hash.description diff --git a/Blockchain/Sources/Blockchain/BlockchainDataProvider/BlockchainDataProvider.swift b/Blockchain/Sources/Blockchain/BlockchainDataProvider/BlockchainDataProvider.swift index f186abd1..de8bf2da 100644 --- a/Blockchain/Sources/Blockchain/BlockchainDataProvider/BlockchainDataProvider.swift +++ b/Blockchain/Sources/Blockchain/BlockchainDataProvider/BlockchainDataProvider.swift @@ -58,6 +58,18 @@ public actor BlockchainDataProvider { } extension BlockchainDataProvider { + public func hasGuaranteedWorkReport(hash: Data32) async throws -> Bool { + try await dataProvider.hasGuaranteedWorkReport(hash: hash) + } + + public func getGuaranteedWorkReport(hash: Data32) async throws -> GuaranteedWorkReportRef? { + try await dataProvider.getGuaranteedWorkReport(hash: hash) + } + + public func add(guaranteedWorkReport: GuaranteedWorkReportRef) async throws { + try await dataProvider.add(guaranteedWorkReport: guaranteedWorkReport) + } + public func hasBlock(hash: Data32) async throws -> Bool { try await dataProvider.hasBlock(hash: hash) } diff --git a/Blockchain/Sources/Blockchain/BlockchainDataProvider/BlockchainDataProviderProtocol.swift b/Blockchain/Sources/Blockchain/BlockchainDataProvider/BlockchainDataProviderProtocol.swift index 8c8ac352..1dd5241d 100644 --- a/Blockchain/Sources/Blockchain/BlockchainDataProvider/BlockchainDataProviderProtocol.swift +++ b/Blockchain/Sources/Blockchain/BlockchainDataProvider/BlockchainDataProviderProtocol.swift @@ -1,6 +1,7 @@ import Utils public protocol BlockchainDataProviderProtocol: Sendable { + func hasGuaranteedWorkReport(hash: Data32) async throws -> Bool func hasBlock(hash: Data32) async throws -> Bool func hasState(hash: Data32) async throws -> Bool func isHead(hash: Data32) async throws -> Bool @@ -9,6 +10,8 @@ public protocol BlockchainDataProviderProtocol: Sendable { func getHeader(hash: Data32) async throws -> HeaderRef? + func getGuaranteedWorkReport(hash: Data32) async throws -> GuaranteedWorkReportRef? + func getBlock(hash: Data32) async throws -> BlockRef? func getState(hash: Data32) async throws -> StateRef? @@ -26,6 +29,7 @@ public protocol BlockchainDataProviderProtocol: Sendable { /// return empty set if not found func getBlockHash(byNumber number: UInt32) async throws -> Set + func add(guaranteedWorkReport: GuaranteedWorkReportRef) async throws func add(block: BlockRef) async throws func add(state: StateRef) async throws func setFinalizedHead(hash: Data32) async throws @@ -33,7 +37,7 @@ public protocol BlockchainDataProviderProtocol: Sendable { /// throw BlockchainDataProviderError.noData if parent is not a head func updateHead(hash: Data32, parent: Data32) async throws - /// remove header, block and state + /// remove header, block, workReport, state func remove(hash: Data32) async throws var genesisBlockHash: Data32 { get } diff --git a/Blockchain/Sources/Blockchain/BlockchainDataProvider/InMemoryDataProvider.swift b/Blockchain/Sources/Blockchain/BlockchainDataProvider/InMemoryDataProvider.swift index 3f9c1b57..44f07143 100644 --- a/Blockchain/Sources/Blockchain/BlockchainDataProvider/InMemoryDataProvider.swift +++ b/Blockchain/Sources/Blockchain/BlockchainDataProvider/InMemoryDataProvider.swift @@ -9,6 +9,7 @@ public actor InMemoryDataProvider { private var blockByHash: [Data32: BlockRef] = [:] private var stateByBlockHash: [Data32: StateRef] = [:] private var hashByTimeslot: [TimeslotIndex: Set] = [:] + private var guaranteedWorkReports: [Data32: GuaranteedWorkReportRef] = [:] public let genesisBlockHash: Data32 public init(genesisState: StateRef, genesisBlock: BlockRef) async { @@ -22,6 +23,18 @@ public actor InMemoryDataProvider { } extension InMemoryDataProvider: BlockchainDataProviderProtocol { + public func hasGuaranteedWorkReport(hash: Data32) async throws -> Bool { + guaranteedWorkReports[hash] != nil + } + + public func getGuaranteedWorkReport(hash: Data32) async throws -> GuaranteedWorkReportRef? { + guaranteedWorkReports[hash] + } + + public func add(guaranteedWorkReport: GuaranteedWorkReportRef) async throws { + guaranteedWorkReports[guaranteedWorkReport.value.workReport.hash()] = guaranteedWorkReport + } + public func getKeys(prefix: Data32, count: UInt32, startKey: Data32?, blockHash: Data32?) async throws -> [String] { guard let stateRef = try getState(hash: blockHash ?? genesisBlockHash) else { return [] @@ -120,6 +133,7 @@ extension InMemoryDataProvider: BlockchainDataProviderProtocol { let timeslot = blockByHash[hash]?.header.timeslot ?? stateByBlockHash[hash]?.value.timeslot stateByBlockHash.removeValue(forKey: hash) blockByHash.removeValue(forKey: hash) + guaranteedWorkReports.removeValue(forKey: hash) if let timeslot { hashByTimeslot[timeslot]?.remove(hash) diff --git a/Blockchain/Sources/Blockchain/BlockchainServices.swift b/Blockchain/Sources/Blockchain/BlockchainServices.swift index 82f5676a..f866c51b 100644 --- a/Blockchain/Sources/Blockchain/BlockchainServices.swift +++ b/Blockchain/Sources/Blockchain/BlockchainServices.swift @@ -23,6 +23,9 @@ public class BlockchainServices: @unchecked Sendable { private var _guaranteeingService: GuaranteeingService? private weak var _guaranteeingServiceRef: GuaranteeingService? + private var _dataAvailabilityService: DataAvailabilityService? + private weak var _dataAvailabilityServiceRef: DataAvailabilityService? + private let schedulerService: ServiceBase2 public init( @@ -63,6 +66,7 @@ public class BlockchainServices: @unchecked Sendable { _blockchain = nil _blockAuthor = nil _guaranteeingService = nil + _dataAvailabilityService = nil if let _blockchainRef { fatalError("BlockchainServices: blockchain still alive. retain count: \(_getRetainCount(_blockchainRef))") @@ -75,6 +79,30 @@ public class BlockchainServices: @unchecked Sendable { if let _guaranteeingServiceRef { fatalError("BlockchainServices: guaranteeingService still alive. retain count: \(_getRetainCount(_guaranteeingServiceRef))") } + + if let _dataAvailabilityServiceRef { + fatalError( + "BlockchainServices: dataAvailabilityService still alive. retain count: \(_getRetainCount(_dataAvailabilityServiceRef))" + ) + } + } + + public var dataAvailabilityService: DataAvailabilityService { + get async { + if let _dataAvailabilityService { + return _dataAvailabilityService + } + _dataAvailabilityService = await DataAvailabilityService( + config: config, + eventBus: eventBus, + scheduler: scheduler, + dataProvider: dataProvider, + dataStore: dataStore + ) + _dataAvailabilityServiceRef = _dataAvailabilityService + await _dataAvailabilityService!.onSyncCompleted() + return _dataAvailabilityService! + } } public var blockchain: Blockchain { diff --git a/Blockchain/Sources/Blockchain/RuntimeProtocols/RuntimeEvents.swift b/Blockchain/Sources/Blockchain/RuntimeProtocols/RuntimeEvents.swift index 4429fbe8..25594416 100644 --- a/Blockchain/Sources/Blockchain/RuntimeProtocols/RuntimeEvents.swift +++ b/Blockchain/Sources/Blockchain/RuntimeProtocols/RuntimeEvents.swift @@ -236,6 +236,21 @@ public enum RuntimeEvents { } } + public struct WorkReportReceivedResponse: Event { + public let workReportHash: Data32 + public let result: Result + + public init(workReportHash: Data32) { + self.workReportHash = workReportHash + result = .success(()) + } + + public init(workReportHash: Data32, error: Error) { + self.workReportHash = workReportHash + result = .failure(error) + } + } + public struct WorkReportRequestReceived: Event { public let workReportHash: Data32 @@ -275,23 +290,6 @@ public enum RuntimeEvents { } } - // Response to work report request - public struct WorkReportRequestResponse: Event { - public var workReportHash: Data32 - - public let result: Result - - public init(workReportHash: Data32, workReport: WorkReport) { - self.workReportHash = workReportHash - result = .success(workReport) - } - - public init(workReportHash: Data32, error: Error) { - self.workReportHash = workReportHash - result = .failure(error) - } - } - public struct AuditShardRequestReceived: Event { public let erasureRoot: Data32 public let shardIndex: UInt32 diff --git a/Blockchain/Sources/Blockchain/Types/GuaranteedWorkReport.swift b/Blockchain/Sources/Blockchain/Types/GuaranteedWorkReport.swift new file mode 100644 index 00000000..7dc441c7 --- /dev/null +++ b/Blockchain/Sources/Blockchain/Types/GuaranteedWorkReport.swift @@ -0,0 +1,42 @@ +import Codec +import Foundation +import Utils + +public struct GuaranteedWorkReport: Sendable, Equatable, Codable, Hashable { + public let workReport: WorkReport + public let slot: UInt32 + public let signatures: [ValidatorSignature] + + public init( + workReport: WorkReport, + slot: UInt32, + signatures: [ValidatorSignature] + ) { + self.workReport = workReport + self.slot = slot + self.signatures = signatures + } +} + +extension GuaranteedWorkReport: Hashable32 { + public func hash() -> Data32 { + try! JamEncoder.encode(self).blake2b256hash() + } +} + +extension GuaranteedWorkReport: Dummy { + public typealias Config = ProtocolConfigRef + public static func dummy(config: Config) -> GuaranteedWorkReport { + GuaranteedWorkReport( + workReport: WorkReport.dummy(config: config), + slot: 0, + signatures: [] + ) + } +} + +extension GuaranteedWorkReport { + public func asRef() -> GuaranteedWorkReportRef { + GuaranteedWorkReportRef(self) + } +} diff --git a/Blockchain/Sources/Blockchain/Types/GuaranteedWorkReportRef.swift b/Blockchain/Sources/Blockchain/Types/GuaranteedWorkReportRef.swift new file mode 100644 index 00000000..289f891e --- /dev/null +++ b/Blockchain/Sources/Blockchain/Types/GuaranteedWorkReportRef.swift @@ -0,0 +1,22 @@ +import Codec +import Foundation +import Utils + +public final class GuaranteedWorkReportRef: RefWithHash, @unchecked Sendable { + public var workReport: WorkReport { value.workReport } + public var slot: UInt32 { value.slot } + public var signatures: [ValidatorSignature] { value.signatures } + override public var description: String { + "GuaranteedWorkReport(hash: \(workReport.hash()), timeslot: \(slot))" + } +} + +extension GuaranteedWorkReportRef: Codable { + public convenience init(from decoder: Decoder) throws { + try self.init(.init(from: decoder)) + } + + public func encode(to encoder: Encoder) throws { + try value.encode(to: encoder) + } +} diff --git a/Blockchain/Sources/Blockchain/Validator/DataAvailabilityService.swift b/Blockchain/Sources/Blockchain/Validator/DataAvailabilityService.swift index d90d571b..56d7990a 100644 --- a/Blockchain/Sources/Blockchain/Validator/DataAvailabilityService.swift +++ b/Blockchain/Sources/Blockchain/Validator/DataAvailabilityService.swift @@ -16,9 +16,12 @@ public enum DataAvailabilityError: Error { case invalidSegmentsRoot case invalidDataLength case pagedProofsGenerationError + case invalidWorkReportSlot + case invalidWorkReport + case insufficientSignatures } -public final class DataAvailabilityService: ServiceBase2, @unchecked Sendable { +public final class DataAvailabilityService: ServiceBase2, @unchecked Sendable, OnSyncCompleted { private let dataProvider: BlockchainDataProvider private let dataStore: DataStore @@ -40,6 +43,16 @@ public final class DataAvailabilityService: ServiceBase2, @unchecked Sendable { } } + public func onSyncCompleted() async { + await subscribe(RuntimeEvents.WorkReportReceived.self, id: "DataAvailabilityService.WorkReportReceived") { [weak self] event in + await self?.handleWorkReportReceived(event) + } + } + + public func handleWorkReportReceived(_ event: RuntimeEvents.WorkReportReceived) async { + await workReportDistribution(workReport: event.workReport, slot: event.slot, signatures: event.signatures) + } + /// Purge old data from the data availability stores /// - Parameter epoch: The current epoch index public func purge(epoch _: EpochIndex) async { @@ -180,6 +193,49 @@ public final class DataAvailabilityService: ServiceBase2, @unchecked Sendable { true } + // MARK: - Work-report Distribution (CE 135) + + public func workReportDistribution( + workReport: WorkReport, + slot: UInt32, + signatures: [ValidatorSignature] + ) async { + let hash = workReport.hash() + + do { + // verify slot + if await isSlotValid(slot) { + throw DataAvailabilityError.invalidWorkReportSlot + } + // verify signatures + try await validate(signatures: signatures) + + // store guaranteedWorkReport + let report = GuaranteedWorkReport( + workReport: workReport, + slot: slot, + signatures: signatures + ) + try await dataProvider.add(guaranteedWorkReport: GuaranteedWorkReportRef(report)) + // response success result + publish(RuntimeEvents.WorkReportReceivedResponse(workReportHash: hash)) + } catch { + publish(RuntimeEvents.WorkReportReceivedResponse(workReportHash: hash, error: error)) + } + } + + private func isSlotValid(_ slot: UInt32) async -> Bool { + let currentSlot = await dataProvider.bestHead.timeslot + return slot + 5 >= currentSlot && slot <= currentSlot + 3 + } + + private func validate(signatures: [ValidatorSignature]) async throws { + guard signatures.count >= 3 else { + throw DataAvailabilityError.insufficientSignatures + } + // TODO: more validates + } + // MARK: - Shard Distribution (CE 137) /// Distribute shards to validators diff --git a/Blockchain/Sources/Blockchain/Validator/GuaranteeingService.swift b/Blockchain/Sources/Blockchain/Validator/GuaranteeingService.swift index ebe21000..3b7c8fa5 100644 --- a/Blockchain/Sources/Blockchain/Validator/GuaranteeingService.swift +++ b/Blockchain/Sources/Blockchain/Validator/GuaranteeingService.swift @@ -352,9 +352,14 @@ public final class GuaranteeingService: ServiceBase2, @unchecked Sendable, OnBef let currentTime = timeProvider.getTime() let timeslot = currentTime.timeToTimeslot(config: config) + 1 - logger.info("Generated work report", - metadata: ["reportHash": "\(workReportHash)", "timeslot": "\(timeslot)", "signatures": "\(sigs.count)"]) - + // Save GuaranteedWorkReport to local db + try await dataProvider + .add(guaranteedWorkReport: + GuaranteedWorkReportRef(GuaranteedWorkReport( + workReport: workReport, + slot: timeslot, + signatures: sigs + ))) // Distribute the guaranteed work-report to all current validators publish(RuntimeEvents.WorkReportGenerated( workReport: workReport, diff --git a/Blockchain/Tests/BlockchainTests/BlockchainDataProviderTests.swift b/Blockchain/Tests/BlockchainTests/BlockchainDataProviderTests.swift index 8b4320e0..f326fffc 100644 --- a/Blockchain/Tests/BlockchainTests/BlockchainDataProviderTests.swift +++ b/Blockchain/Tests/BlockchainTests/BlockchainDataProviderTests.swift @@ -185,4 +185,33 @@ struct BlockchainDataProviderTests { #expect(try await provider.hasBlock(hash: block.hash) == false) #expect(try await provider.hasState(hash: block.hash) == false) } + + @Test func guaranteedWorkReportOperations() async throws { + // Create a dummy work report and guaranteed work report + let workReport = WorkReport.dummy(config: config) + let guaranteedReport = GuaranteedWorkReport( + workReport: workReport, + slot: 1, + signatures: [] + ) + let reportRef = guaranteedReport.asRef() + + // Test adding and retrieving + try await provider.add(guaranteedWorkReport: reportRef) + + // Verify existence + #expect(try await provider.hasGuaranteedWorkReport(hash: workReport.hash())) + + // Verify retrieval + let retrieved = try await provider.getGuaranteedWorkReport(hash: workReport.hash()) + #expect(retrieved?.hash == reportRef.hash) + } + + @Test func guaranteedWorkReportOperationsErrors() async throws { + let nonExistentHash = Data32.random() + // Test checking non-existent report + #expect(try await provider.hasGuaranteedWorkReport(hash: nonExistentHash) == false) + // Test getting non-existent report + #expect(try await provider.getGuaranteedWorkReport(hash: nonExistentHash) == nil) + } } diff --git a/Boka/Package.resolved b/Boka/Package.resolved deleted file mode 100644 index 3221b295..00000000 --- a/Boka/Package.resolved +++ /dev/null @@ -1,339 +0,0 @@ -{ - "originHash" : "21fd16bf620160741466e113b8b7b90cd924166bfee31bc2fb85ad79912ba6dc", - "pins" : [ - { - "identity" : "async-channels", - "kind" : "remoteSourceControl", - "location" : "https://github.com/gh123man/Async-Channels.git", - "state" : { - "revision" : "e4c71cd0364532d34b27e76f4ab7229abaaaefb4", - "version" : "1.0.2" - } - }, - { - "identity" : "async-http-client", - "kind" : "remoteSourceControl", - "location" : "https://github.com/swift-server/async-http-client.git", - "state" : { - "revision" : "64abc77edf1ef81e69bd90a2ac386de615c8e8ea", - "version" : "1.23.0" - } - }, - { - "identity" : "async-kit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/vapor/async-kit.git", - "state" : { - "revision" : "e048c8ee94967e8d8a1c2ec0e1156d6f7fa34d31", - "version" : "1.20.0" - } - }, - { - "identity" : "blake2.swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/tesseract-one/Blake2.swift.git", - "state" : { - "revision" : "29c55c8fe42d6661e5a32cc5bbbad1fff64fd01e", - "version" : "0.2.0" - } - }, - { - "identity" : "console-kit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/vapor/console-kit.git", - "state" : { - "revision" : "78c0dd739df8cb9ee14a8bbbf770facc4fc3402a", - "version" : "4.15.0" - } - }, - { - "identity" : "grpc-swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/grpc/grpc-swift.git", - "state" : { - "revision" : "3ef3a9f42a11bfca767de880f1a0aedd2b65b840", - "version" : "1.24.1" - } - }, - { - "identity" : "lrucache", - "kind" : "remoteSourceControl", - "location" : "https://github.com/nicklockwood/LRUCache.git", - "state" : { - "revision" : "542f0449556327415409ededc9c43a4bd0a397dc", - "version" : "1.0.7" - } - }, - { - "identity" : "multipart-kit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/vapor/multipart-kit.git", - "state" : { - "revision" : "a31236f24bfd2ea2f520a74575881f6731d7ae68", - "version" : "4.7.0" - } - }, - { - "identity" : "routing-kit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/vapor/routing-kit.git", - "state" : { - "revision" : "8c9a227476555c55837e569be71944e02a056b72", - "version" : "4.9.1" - } - }, - { - "identity" : "swift-algorithms", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-algorithms.git", - "state" : { - "revision" : "f6919dfc309e7f1b56224378b11e28bab5bccc42", - "version" : "1.2.0" - } - }, - { - "identity" : "swift-argument-parser", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-argument-parser.git", - "state" : { - "revision" : "41982a3656a71c768319979febd796c6fd111d5c", - "version" : "1.5.0" - } - }, - { - "identity" : "swift-asn1", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-asn1.git", - "state" : { - "revision" : "7faebca1ea4f9aaf0cda1cef7c43aecd2311ddf6", - "version" : "1.3.0" - } - }, - { - "identity" : "swift-async-algorithms", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-async-algorithms.git", - "state" : { - "revision" : "5c8bd186f48c16af0775972700626f0b74588278", - "version" : "1.0.2" - } - }, - { - "identity" : "swift-atomics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-atomics.git", - "state" : { - "revision" : "cd142fd2f64be2100422d658e7411e39489da985", - "version" : "1.2.0" - } - }, - { - "identity" : "swift-certificates", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-certificates.git", - "state" : { - "revision" : "1fbb6ef21f1525ed5faf4c95207b9c11bea27e94", - "version" : "1.6.1" - } - }, - { - "identity" : "swift-collections", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-collections.git", - "state" : { - "revision" : "671108c96644956dddcd89dd59c203dcdb36cec7", - "version" : "1.1.4" - } - }, - { - "identity" : "swift-crypto", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-crypto.git", - "state" : { - "revision" : "ffca28be3c9c6a86a579949d23f68818a4b9b5d8", - "version" : "3.8.0" - } - }, - { - "identity" : "swift-distributed-tracing", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-distributed-tracing.git", - "state" : { - "revision" : "6483d340853a944c96dbcc28b27dd10b6c581703", - "version" : "1.1.2" - } - }, - { - "identity" : "swift-http-types", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-http-types", - "state" : { - "revision" : "ae67c8178eb46944fd85e4dc6dd970e1f3ed6ccd", - "version" : "1.3.0" - } - }, - { - "identity" : "swift-log", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-log.git", - "state" : { - "revision" : "9cb486020ebf03bfa5b5df985387a14a98744537", - "version" : "1.6.1" - } - }, - { - "identity" : "swift-metrics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-metrics.git", - "state" : { - "revision" : "e0165b53d49b413dd987526b641e05e246782685", - "version" : "2.5.0" - } - }, - { - "identity" : "swift-nio", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio.git", - "state" : { - "revision" : "665206000b8307cab5ac51203d29b0f232d7e31b", - "version" : "2.74.0" - } - }, - { - "identity" : "swift-nio-extras", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-extras.git", - "state" : { - "revision" : "d1ead62745cc3269e482f1c51f27608057174379", - "version" : "1.24.0" - } - }, - { - "identity" : "swift-nio-http2", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-http2.git", - "state" : { - "revision" : "eaa71bb6ae082eee5a07407b1ad0cbd8f48f9dca", - "version" : "1.34.1" - } - }, - { - "identity" : "swift-nio-ssl", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-ssl.git", - "state" : { - "revision" : "7b84abbdcef69cc3be6573ac12440220789dcd69", - "version" : "2.27.2" - } - }, - { - "identity" : "swift-nio-transport-services", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-transport-services.git", - "state" : { - "revision" : "dbace16f126fdcd80d58dc54526c561ca17327d7", - "version" : "1.22.0" - } - }, - { - "identity" : "swift-numerics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-numerics", - "state" : { - "branch" : "main", - "revision" : "e30276bff2ff5ed80566fbdca49f50aa160b0e83" - } - }, - { - "identity" : "swift-otel", - "kind" : "remoteSourceControl", - "location" : "https://github.com/slashmo/swift-otel.git", - "state" : { - "revision" : "90d63b478fbc4c97f396c1cf9ad011979a83f10b", - "version" : "0.10.1" - } - }, - { - "identity" : "swift-protobuf", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-protobuf.git", - "state" : { - "revision" : "ebc7251dd5b37f627c93698e4374084d98409633", - "version" : "1.28.2" - } - }, - { - "identity" : "swift-service-context", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-service-context.git", - "state" : { - "revision" : "0c62c5b4601d6c125050b5c3a97f20cce881d32b", - "version" : "1.1.0" - } - }, - { - "identity" : "swift-service-lifecycle", - "kind" : "remoteSourceControl", - "location" : "https://github.com/swift-server/swift-service-lifecycle.git", - "state" : { - "revision" : "24c800fb494fbee6e42bc156dc94232dc08971af", - "version" : "2.6.1" - } - }, - { - "identity" : "swift-syntax", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-syntax.git", - "state" : { - "revision" : "0687f71944021d616d34d922343dcef086855920", - "version" : "600.0.1" - } - }, - { - "identity" : "swift-system", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-system.git", - "state" : { - "revision" : "d2ba781702a1d8285419c15ee62fd734a9437ff5", - "version" : "1.3.2" - } - }, - { - "identity" : "swift-testing", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-testing.git", - "state" : { - "branch" : "0.10.0", - "revision" : "69d59cfc76e5daf498ca61f5af409f594768eef9" - } - }, - { - "identity" : "swift-w3c-trace-context", - "kind" : "remoteSourceControl", - "location" : "https://github.com/slashmo/swift-w3c-trace-context.git", - "state" : { - "revision" : "3da4b79545b38cf5551f1c525d800756f38cb697", - "version" : "1.0.0-beta.3" - } - }, - { - "identity" : "vapor", - "kind" : "remoteSourceControl", - "location" : "https://github.com/vapor/vapor.git", - "state" : { - "revision" : "1466c50e4ad39072143e2fcdf13b4ba11be375a0", - "version" : "4.106.0" - } - }, - { - "identity" : "websocket-kit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/vapor/websocket-kit.git", - "state" : { - "revision" : "4232d34efa49f633ba61afde365d3896fc7f8740", - "version" : "2.15.0" - } - } - ], - "version" : 3 -} diff --git a/Boka/Package.swift b/Boka/Package.swift index 35a89f20..ca126167 100644 --- a/Boka/Package.swift +++ b/Boka/Package.swift @@ -14,7 +14,7 @@ let package = Package( .package(url: "https://github.com/slashmo/swift-otel.git", from: "0.9.0"), .package(url: "https://github.com/swift-server/swift-service-lifecycle.git", from: "2.6.0"), .package(url: "https://github.com/vapor/console-kit.git", from: "4.15.0"), - .package(url: "https://github.com/apple/swift-testing.git", branch: "0.10.0"), + .package(url: "https://github.com/apple/swift-testing.git", branch: "6.0.0"), .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.5.0"), ], targets: [ diff --git a/Codec/Package.resolved b/Codec/Package.resolved deleted file mode 100644 index aa699247..00000000 --- a/Codec/Package.resolved +++ /dev/null @@ -1,24 +0,0 @@ -{ - "originHash" : "027931fd6146ff8a703e948ec61abe2a52a77db3285ba4722225d611e17904e6", - "pins" : [ - { - "identity" : "swift-syntax", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-syntax.git", - "state" : { - "revision" : "515f79b522918f83483068d99c68daeb5116342d", - "version" : "600.0.0-prerelease-2024-08-14" - } - }, - { - "identity" : "swift-testing", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-testing.git", - "state" : { - "branch" : "0.10.0", - "revision" : "69d59cfc76e5daf498ca61f5af409f594768eef9" - } - } - ], - "version" : 3 -} diff --git a/Codec/Package.swift b/Codec/Package.swift index c8cf459c..6a0307fe 100644 --- a/Codec/Package.swift +++ b/Codec/Package.swift @@ -16,7 +16,7 @@ let package = Package( ), ], dependencies: [ - .package(url: "https://github.com/apple/swift-testing.git", branch: "0.10.0"), + .package(url: "https://github.com/apple/swift-testing.git", branch: "6.0.0"), ], targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. diff --git a/Database/Package.resolved b/Database/Package.resolved deleted file mode 100644 index 66a2c042..00000000 --- a/Database/Package.resolved +++ /dev/null @@ -1,105 +0,0 @@ -{ - "originHash" : "71ac75472e411174f6e43bdf064f1565f45d087a55de16d382092ae064ca91eb", - "pins" : [ - { - "identity" : "blake2.swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/tesseract-one/Blake2.swift.git", - "state" : { - "revision" : "29c55c8fe42d6661e5a32cc5bbbad1fff64fd01e", - "version" : "0.2.0" - } - }, - { - "identity" : "lrucache", - "kind" : "remoteSourceControl", - "location" : "https://github.com/nicklockwood/LRUCache.git", - "state" : { - "revision" : "542f0449556327415409ededc9c43a4bd0a397dc", - "version" : "1.0.7" - } - }, - { - "identity" : "swift-asn1", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-asn1.git", - "state" : { - "revision" : "7faebca1ea4f9aaf0cda1cef7c43aecd2311ddf6", - "version" : "1.3.0" - } - }, - { - "identity" : "swift-crypto", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-crypto.git", - "state" : { - "revision" : "ff0f781cf7c6a22d52957e50b104f5768b50c779", - "version" : "3.10.0" - } - }, - { - "identity" : "swift-distributed-tracing", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-distributed-tracing.git", - "state" : { - "revision" : "6483d340853a944c96dbcc28b27dd10b6c581703", - "version" : "1.1.2" - } - }, - { - "identity" : "swift-log", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-log.git", - "state" : { - "revision" : "96a2f8a0fa41e9e09af4585e2724c4e825410b91", - "version" : "1.6.2" - } - }, - { - "identity" : "swift-metrics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-metrics.git", - "state" : { - "revision" : "e0165b53d49b413dd987526b641e05e246782685", - "version" : "2.5.0" - } - }, - { - "identity" : "swift-numerics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-numerics.git", - "state" : { - "branch" : "main", - "revision" : "e30276bff2ff5ed80566fbdca49f50aa160b0e83" - } - }, - { - "identity" : "swift-service-context", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-service-context.git", - "state" : { - "revision" : "0c62c5b4601d6c125050b5c3a97f20cce881d32b", - "version" : "1.1.0" - } - }, - { - "identity" : "swift-syntax", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-syntax.git", - "state" : { - "revision" : "4c6cc0a3b9e8f14b3ae2307c5ccae4de6167ac2c", - "version" : "600.0.0-prerelease-2024-06-12" - } - }, - { - "identity" : "swift-testing", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-testing.git", - "state" : { - "branch" : "0.10.0", - "revision" : "69d59cfc76e5daf498ca61f5af409f594768eef9" - } - } - ], - "version" : 3 -} diff --git a/Database/Package.swift b/Database/Package.swift index e820ad24..ca635b23 100644 --- a/Database/Package.swift +++ b/Database/Package.swift @@ -19,7 +19,7 @@ let package = Package( .package(path: "../Blockchain"), .package(path: "../Codec"), .package(path: "../Utils"), - .package(url: "https://github.com/apple/swift-testing.git", branch: "0.10.0"), + .package(url: "https://github.com/apple/swift-testing.git", branch: "6.0.0"), ], targets: [ .target( diff --git a/Database/Sources/Database/RocksDBBackend.swift b/Database/Sources/Database/RocksDBBackend.swift index 54396e37..fd2b8392 100644 --- a/Database/Sources/Database/RocksDBBackend.swift +++ b/Database/Sources/Database/RocksDBBackend.swift @@ -24,6 +24,7 @@ public final class RocksDBBackend: Sendable { private let stateValue: Store> private let stateRefs: Store> private let stateRefsRaw: Store> + private let guaranteedWorkReports: Store> public let genesisBlockHash: Data32 @@ -40,7 +41,7 @@ public final class RocksDBBackend: Sendable { stateValue = Store(db: db, column: .state, coder: BinaryCoder(config: config, prefix: Data([1]))) stateRefs = Store(db: db, column: .stateRefs, coder: BinaryCoder(config: config, prefix: Data([0]))) stateRefsRaw = Store(db: db, column: .stateRefs, coder: BinaryCoder(config: config, prefix: Data([1]))) - + guaranteedWorkReports = Store(db: db, column: .guaranteedWorkReports, coder: JamCoder(config: config)) genesisBlockHash = genesisBlock.hash let genesis = try meta.get(key: MetaKey.genesisHash.key) @@ -72,6 +73,19 @@ public final class RocksDBBackend: Sendable { } extension RocksDBBackend: BlockchainDataProviderProtocol { + public func hasGuaranteedWorkReport(hash: Data32) async throws -> Bool { + try guaranteedWorkReports.exists(key: hash) + } + + public func getGuaranteedWorkReport(hash: Data32) async throws -> GuaranteedWorkReportRef? { + try guaranteedWorkReports.get(key: hash) + } + + public func add(guaranteedWorkReport: GuaranteedWorkReportRef) async throws { + let hash = guaranteedWorkReport.workReport.hash() + try guaranteedWorkReports.put(key: hash, value: guaranteedWorkReport) + } + public func getKeys(prefix: Data32, count: UInt32, startKey: Data32?, blockHash: Data32?) async throws -> [String] { logger.trace(""" getKeys() prefix: \(prefix), count: \(count), @@ -211,7 +225,7 @@ extension RocksDBBackend: BlockchainDataProviderProtocol { // TODO: batch delete try blocks.delete(key: hash) - + try guaranteedWorkReports.delete(key: hash) if let block = try await getBlock(hash: hash) { try blockHashByTimeslot.delete(key: block.header.timeslot) } diff --git a/Database/Sources/Database/Stores.swift b/Database/Sources/Database/Stores.swift index 51c732c2..910234a2 100644 --- a/Database/Sources/Database/Stores.swift +++ b/Database/Sources/Database/Stores.swift @@ -23,6 +23,9 @@ enum StoreId: UInt8, ColumnFamilyKey { // 0x00 + node hash => ref count // 0x01 + value hash => ref count case stateRefs = 4 + // guaranteedWorkReports + // workReportHash => guaranteedWorkReport + case guaranteedWorkReports = 5 } enum MetaKey: UInt8 { diff --git a/JAMTests/Package.resolved b/JAMTests/Package.resolved deleted file mode 100644 index 8a4e0f98..00000000 --- a/JAMTests/Package.resolved +++ /dev/null @@ -1,96 +0,0 @@ -{ - "originHash" : "d1c16170b6583ee1b137012237d778a580dd5133ce298fe722c0dd6851f6018d", - "pins" : [ - { - "identity" : "blake2.swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/tesseract-one/Blake2.swift.git", - "state" : { - "revision" : "29c55c8fe42d6661e5a32cc5bbbad1fff64fd01e", - "version" : "0.2.0" - } - }, - { - "identity" : "lrucache", - "kind" : "remoteSourceControl", - "location" : "https://github.com/nicklockwood/LRUCache.git", - "state" : { - "revision" : "542f0449556327415409ededc9c43a4bd0a397dc", - "version" : "1.0.7" - } - }, - { - "identity" : "swift-crypto", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-crypto.git", - "state" : { - "revision" : "33f65a3cbc52f8c19295723af9cbecc2195484e1", - "version" : "3.5.0" - } - }, - { - "identity" : "swift-distributed-tracing", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-distributed-tracing.git", - "state" : { - "revision" : "11c756c5c4d7de0eeed8595695cadd7fa107aa19", - "version" : "1.1.1" - } - }, - { - "identity" : "swift-log", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-log.git", - "state" : { - "revision" : "9cb486020ebf03bfa5b5df985387a14a98744537", - "version" : "1.6.1" - } - }, - { - "identity" : "swift-metrics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-metrics.git", - "state" : { - "revision" : "e0165b53d49b413dd987526b641e05e246782685", - "version" : "2.5.0" - } - }, - { - "identity" : "swift-numerics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-numerics", - "state" : { - "branch" : "main", - "revision" : "e30276bff2ff5ed80566fbdca49f50aa160b0e83" - } - }, - { - "identity" : "swift-service-context", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-service-context.git", - "state" : { - "revision" : "0c62c5b4601d6c125050b5c3a97f20cce881d32b", - "version" : "1.1.0" - } - }, - { - "identity" : "swift-syntax", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-syntax.git", - "state" : { - "revision" : "4c6cc0a3b9e8f14b3ae2307c5ccae4de6167ac2c", - "version" : "600.0.0-prerelease-2024-06-12" - } - }, - { - "identity" : "swift-testing", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-testing.git", - "state" : { - "branch" : "0.10.0", - "revision" : "69d59cfc76e5daf498ca61f5af409f594768eef9" - } - } - ], - "version" : 3 -} diff --git a/JAMTests/Package.swift b/JAMTests/Package.swift index 99e636a5..8aff67c0 100644 --- a/JAMTests/Package.swift +++ b/JAMTests/Package.swift @@ -21,7 +21,7 @@ let package = Package( .package(path: "../TracingUtils"), .package(path: "../Blockchain"), .package(path: "../PolkaVM"), - .package(url: "https://github.com/apple/swift-testing.git", branch: "0.10.0"), + .package(url: "https://github.com/apple/swift-testing.git", branch: "6.0.0"), ], targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. diff --git a/Networking/Package.swift b/Networking/Package.swift index ee9b929a..87038171 100644 --- a/Networking/Package.swift +++ b/Networking/Package.swift @@ -19,7 +19,7 @@ let package = Package( .package(path: "../Utils"), .package(url: "https://github.com/apple/swift-log.git", from: "1.6.0"), .package(url: "https://github.com/apple/swift-certificates.git", from: "1.5.0"), - .package(url: "https://github.com/apple/swift-testing.git", branch: "0.10.0"), + .package(url: "https://github.com/apple/swift-testing.git", branch: "6.0.0"), .package(url: "https://github.com/gh123man/Async-Channels.git", from: "1.0.2"), ], targets: [ diff --git a/Node/Package.resolved b/Node/Package.resolved deleted file mode 100644 index 88a24089..00000000 --- a/Node/Package.resolved +++ /dev/null @@ -1,276 +0,0 @@ -{ - "originHash" : "fd50b22dcf258877cc79f49fe7cb855a71ce6974bd1a2732a13b0d3e49c057fc", - "pins" : [ - { - "identity" : "async-channels", - "kind" : "remoteSourceControl", - "location" : "https://github.com/gh123man/Async-Channels.git", - "state" : { - "revision" : "e4c71cd0364532d34b27e76f4ab7229abaaaefb4", - "version" : "1.0.2" - } - }, - { - "identity" : "async-http-client", - "kind" : "remoteSourceControl", - "location" : "https://github.com/swift-server/async-http-client.git", - "state" : { - "revision" : "0ae99db85b2b9d1e79b362bd31fd1ffe492f7c47", - "version" : "1.21.2" - } - }, - { - "identity" : "async-kit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/vapor/async-kit.git", - "state" : { - "revision" : "e048c8ee94967e8d8a1c2ec0e1156d6f7fa34d31", - "version" : "1.20.0" - } - }, - { - "identity" : "blake2.swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/tesseract-one/Blake2.swift.git", - "state" : { - "revision" : "29c55c8fe42d6661e5a32cc5bbbad1fff64fd01e", - "version" : "0.2.0" - } - }, - { - "identity" : "console-kit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/vapor/console-kit.git", - "state" : { - "revision" : "9f7932f22ab6f64aafadc14491e694179b7d0f6f", - "version" : "4.14.3" - } - }, - { - "identity" : "lrucache", - "kind" : "remoteSourceControl", - "location" : "https://github.com/nicklockwood/LRUCache.git", - "state" : { - "revision" : "542f0449556327415409ededc9c43a4bd0a397dc", - "version" : "1.0.7" - } - }, - { - "identity" : "multipart-kit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/vapor/multipart-kit.git", - "state" : { - "revision" : "a31236f24bfd2ea2f520a74575881f6731d7ae68", - "version" : "4.7.0" - } - }, - { - "identity" : "routing-kit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/vapor/routing-kit.git", - "state" : { - "revision" : "8c9a227476555c55837e569be71944e02a056b72", - "version" : "4.9.1" - } - }, - { - "identity" : "swift-algorithms", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-algorithms.git", - "state" : { - "revision" : "f6919dfc309e7f1b56224378b11e28bab5bccc42", - "version" : "1.2.0" - } - }, - { - "identity" : "swift-asn1", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-asn1.git", - "state" : { - "revision" : "7faebca1ea4f9aaf0cda1cef7c43aecd2311ddf6", - "version" : "1.3.0" - } - }, - { - "identity" : "swift-atomics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-atomics.git", - "state" : { - "revision" : "cd142fd2f64be2100422d658e7411e39489da985", - "version" : "1.2.0" - } - }, - { - "identity" : "swift-certificates", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-certificates.git", - "state" : { - "revision" : "1fbb6ef21f1525ed5faf4c95207b9c11bea27e94", - "version" : "1.6.1" - } - }, - { - "identity" : "swift-collections", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-collections.git", - "state" : { - "revision" : "671108c96644956dddcd89dd59c203dcdb36cec7", - "version" : "1.1.4" - } - }, - { - "identity" : "swift-crypto", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-crypto.git", - "state" : { - "revision" : "bc1c29221f6dfeb0ebbfbc98eb95cd3d4967868e", - "version" : "3.4.0" - } - }, - { - "identity" : "swift-distributed-tracing", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-distributed-tracing.git", - "state" : { - "revision" : "11c756c5c4d7de0eeed8595695cadd7fa107aa19", - "version" : "1.1.1" - } - }, - { - "identity" : "swift-http-types", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-http-types", - "state" : { - "revision" : "ae67c8178eb46944fd85e4dc6dd970e1f3ed6ccd", - "version" : "1.3.0" - } - }, - { - "identity" : "swift-log", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-log.git", - "state" : { - "revision" : "9cb486020ebf03bfa5b5df985387a14a98744537", - "version" : "1.6.1" - } - }, - { - "identity" : "swift-metrics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-metrics.git", - "state" : { - "revision" : "e0165b53d49b413dd987526b641e05e246782685", - "version" : "2.5.0" - } - }, - { - "identity" : "swift-nio", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio.git", - "state" : { - "revision" : "4c4453b489cf76e6b3b0f300aba663eb78182fad", - "version" : "2.70.0" - } - }, - { - "identity" : "swift-nio-extras", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-extras.git", - "state" : { - "revision" : "d1ead62745cc3269e482f1c51f27608057174379", - "version" : "1.24.0" - } - }, - { - "identity" : "swift-nio-http2", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-http2.git", - "state" : { - "revision" : "b5f7062b60e4add1e8c343ba4eb8da2e324b3a94", - "version" : "1.34.0" - } - }, - { - "identity" : "swift-nio-ssl", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-ssl.git", - "state" : { - "revision" : "a9fa5efd86e7ce2e5c1b6de113262e58035ca251", - "version" : "2.27.1" - } - }, - { - "identity" : "swift-nio-transport-services", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-transport-services.git", - "state" : { - "revision" : "38ac8221dd20674682148d6451367f89c2652980", - "version" : "1.21.0" - } - }, - { - "identity" : "swift-numerics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-numerics", - "state" : { - "branch" : "main", - "revision" : "e30276bff2ff5ed80566fbdca49f50aa160b0e83" - } - }, - { - "identity" : "swift-service-context", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-service-context.git", - "state" : { - "revision" : "0c62c5b4601d6c125050b5c3a97f20cce881d32b", - "version" : "1.1.0" - } - }, - { - "identity" : "swift-syntax", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-syntax.git", - "state" : { - "revision" : "0687f71944021d616d34d922343dcef086855920", - "version" : "600.0.1" - } - }, - { - "identity" : "swift-system", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-system.git", - "state" : { - "revision" : "d2ba781702a1d8285419c15ee62fd734a9437ff5", - "version" : "1.3.2" - } - }, - { - "identity" : "swift-testing", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-testing.git", - "state" : { - "branch" : "0.10.0", - "revision" : "69d59cfc76e5daf498ca61f5af409f594768eef9" - } - }, - { - "identity" : "vapor", - "kind" : "remoteSourceControl", - "location" : "https://github.com/vapor/vapor.git", - "state" : { - "revision" : "1466c50e4ad39072143e2fcdf13b4ba11be375a0", - "version" : "4.106.0" - } - }, - { - "identity" : "websocket-kit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/vapor/websocket-kit.git", - "state" : { - "revision" : "4232d34efa49f633ba61afde365d3896fc7f8740", - "version" : "2.15.0" - } - } - ], - "version" : 3 -} diff --git a/Node/Package.swift b/Node/Package.swift index a7a3e4d7..9b22869b 100644 --- a/Node/Package.swift +++ b/Node/Package.swift @@ -22,7 +22,7 @@ let package = Package( .package(path: "../TracingUtils"), .package(path: "../Utils"), .package(path: "../Database"), - .package(url: "https://github.com/apple/swift-testing.git", branch: "0.10.0"), + .package(url: "https://github.com/apple/swift-testing.git", branch: "6.0.3"), .package(url: "https://github.com/gh123man/Async-Channels.git", from: "1.0.2"), ], targets: [ diff --git a/Node/Sources/Node/NetworkingProtocol/CommonEphemeral/CERequest.swift b/Node/Sources/Node/NetworkingProtocol/CommonEphemeral/CERequest.swift index f8e4cfec..903247f8 100644 --- a/Node/Sources/Node/NetworkingProtocol/CommonEphemeral/CERequest.swift +++ b/Node/Sources/Node/NetworkingProtocol/CommonEphemeral/CERequest.swift @@ -15,7 +15,7 @@ public enum CERequest: Sendable, Equatable, Hashable { case safroleTicket2(SafroleTicketMessage) case workPackageSubmission(WorkPackageSubmissionMessage) case workPackageSharing(WorkPackageSharingMessage) - case workReportDistrubution(WorkReportDistributionMessage) + case workReportDistribution(WorkReportDistributionMessage) case workReportRequest(WorkReportRequestMessage) case shardDistribution(ShardDistributionMessage) case auditShardRequest(AuditShardRequestMessage) @@ -45,7 +45,7 @@ extension CERequest: RequestProtocol { try message.encode() case let .workPackageSharing(message): try message.encode() - case let .workReportDistrubution(message): + case let .workReportDistribution(message): try message.encode() case let .workReportRequest(message): try message.encode() @@ -84,8 +84,8 @@ extension CERequest: RequestProtocol { .workPackageSubmission case .workPackageSharing: .workPackageSharing - case .workReportDistrubution: - .workReportDistrubution + case .workReportDistribution: + .workReportDistribution case .workReportRequest: .workReportRequest case .shardDistribution: @@ -123,7 +123,7 @@ extension CERequest: RequestProtocol { WorkPackageSubmissionMessage.self case .workPackageSharing: WorkPackageSharingMessage.self - case .workReportDistrubution: + case .workReportDistribution: WorkReportDistributionMessage.self case .workReportRequest: WorkReportRequestMessage.self @@ -168,9 +168,9 @@ extension CERequest: RequestProtocol { case .workPackageSharing: guard let message = data as? WorkPackageSharingMessage else { return nil } return .workPackageSharing(message) - case .workReportDistrubution: + case .workReportDistribution: guard let message = data as? WorkReportDistributionMessage else { return nil } - return .workReportDistrubution(message) + return .workReportDistribution(message) case .workReportRequest: guard let message = data as? WorkReportRequestMessage else { return nil } return .workReportRequest(message) diff --git a/Node/Sources/Node/NetworkingProtocol/NetworkManager.swift b/Node/Sources/Node/NetworkingProtocol/NetworkManager.swift index abc341c5..af5abf3d 100644 --- a/Node/Sources/Node/NetworkingProtocol/NetworkManager.swift +++ b/Node/Sources/Node/NetworkingProtocol/NetworkManager.swift @@ -112,6 +112,13 @@ public final class NetworkManager: Sendable { ) { [weak self] event in await self?.on(beforeEpochChange: event) } + + await subscriptions.subscribe( + RuntimeEvents.WorkReportGenerated.self, + id: "NetworkManager.WorkReportGenerated" + ) { [weak self] event in + await self?.on(workReportGenerated: event) + } } } @@ -218,6 +225,7 @@ public final class NetworkManager: Sendable { private func on(workPackageBundleReady event: RuntimeEvents.WorkPackageBundleReady) async { await withSpan("NetworkManager.on(workPackageBundleReady)", logger: logger) { _ in let target = event.target + let resp = try await send(to: target, message: .workPackageSharing(.init( coreIndex: event.coreIndex, segmentsRootMappings: event.segmentsRootMappings, @@ -248,7 +256,7 @@ public final class NetworkManager: Sendable { let currentValidators = event.state.currentValidators let nextValidators = event.state.nextValidators let allValidators = Set([currentValidators.array, nextValidators.array].joined()) - + print("NetworkManager.onBeforeEpoch \(allValidators)") var peerIdByPublicKey: [Data32: PeerId] = [:] for validator in allValidators { if let addr = NetAddr(address: validator.metadataString) { @@ -263,6 +271,20 @@ public final class NetworkManager: Sendable { } } + private func on(workReportGenerated event: RuntimeEvents.WorkReportGenerated) async { + logger.trace("sending guaranteed work-report", + metadata: ["slot": "\(event.slot)", + "signatures": "\(event.signatures.count)"]) + await broadcast( + to: .currentValidators, + message: .workReportDistribution(.init( + workReport: event.workReport, + slot: event.slot, + signatures: event.signatures + )) + ) + } + public var peersCount: Int { network.peersCount } @@ -312,7 +334,7 @@ struct HandlerImpl: NetworkProtocolHandler { } return [encoder.data] case let .stateRequest(message): - try blockchain + blockchain .publish( event: RuntimeEvents .StateRequestReceived( @@ -375,7 +397,8 @@ struct HandlerImpl: NetworkProtocolHandler { } let (workReportHash, signature) = try resp.result.get() return try [JamEncoder.encode(workReportHash, signature)] - case let .workReportDistrubution(message): + case let .workReportDistribution(message): + let hash = message.workReport.hash() blockchain .publish( event: RuntimeEvents @@ -385,13 +408,19 @@ struct HandlerImpl: NetworkProtocolHandler { signatures: message.signatures ) ) + + let resp = try await blockchain.waitFor(RuntimeEvents.WorkReportReceivedResponse.self) { event in + hash == event.workReportHash + } + if case let .failure(error) = resp.result { + throw error // failed + } return [] case let .workReportRequest(message): - blockchain.publish(event: RuntimeEvents.WorkReportRequestReceived(workReportHash: message.workReportHash)) - // TODO: waitfor WorkReportRequestResponse - // let resp = try await blockchain.waitFor(RuntimeEvents.WorkReportRequestResponse.self) { event in - // message.workReportHash == event.workReport.hash() - // } + let workReportRef = try await blockchain.dataProvider.getGuaranteedWorkReport(hash: message.workReportHash) + if let workReport = workReportRef { + return try [JamEncoder.encode(workReport.value)] + } return [] case let .shardDistribution(message): blockchain diff --git a/Node/Sources/Node/StreamKind.swift b/Node/Sources/Node/StreamKind.swift index 8121f735..85d64065 100644 --- a/Node/Sources/Node/StreamKind.swift +++ b/Node/Sources/Node/StreamKind.swift @@ -11,7 +11,7 @@ public enum CommonEphemeralStreamKind: UInt8, StreamKindProtocol { case safroleTicket2 = 132 case workPackageSubmission = 133 case workPackageSharing = 134 - case workReportDistrubution = 135 + case workReportDistribution = 135 case workReportRequest = 136 case shardDistribution = 137 case auditShardRequest = 138 diff --git a/Node/Tests/NodeTests/Mocks/MockNetwork.swift b/Node/Tests/NodeTests/Mocks/MockNetwork.swift index 9aea0242..1394f5d3 100644 --- a/Node/Tests/NodeTests/Mocks/MockNetwork.swift +++ b/Node/Tests/NodeTests/Mocks/MockNetwork.swift @@ -127,7 +127,7 @@ final class MockNetwork: NetworkProtocol { idx += 1 } - return idx == toCheck.count + return idx >= toCheck.count } } diff --git a/Node/Tests/NodeTests/NetworkManagerTests.swift b/Node/Tests/NodeTests/NetworkManagerTests.swift index 9dd10c0f..0a73d343 100644 --- a/Node/Tests/NodeTests/NetworkManagerTests.swift +++ b/Node/Tests/NodeTests/NetworkManagerTests.swift @@ -86,8 +86,11 @@ struct NetworkManagerTests { let workReportHash = Data32(repeating: 2) let signature = Ed25519Signature(repeating: 3) let expectedResp = try JamEncoder.encode(workReportHash, signature) - network.state.write { $0.simulatedResponseData = [expectedResp] } - + await services.publishOnBeforeEpochEvent() + network.state.write { + $0.simulatedResponseData = [expectedResp] + $0.simulatedPeerRole = .validator + } // Publish WorkPackagesReceived event await services.blockchain .publish(event: RuntimeEvents.WorkPackageBundleReady( @@ -96,31 +99,18 @@ struct NetworkManagerTests { bundle: bundle, segmentsRootMappings: segmentsRootMappings )) + try? await Task.sleep(for: .milliseconds(1000)) // Wait for event processing let events = await storeMiddleware.wait() - // Verify network calls - #expect( - network.contain(calls: [ - .init(function: "connect", parameters: ["address": devPeers.first!, "role": PeerRole.validator]), - .init(function: "sendToPeer", parameters: [ - "peerId": PeerId(publicKey: key.ed25519.data.data, address: NetAddr(address: "127.0.0.1:5000")!), - "message": CERequest.workPackageSharing(.init( - coreIndex: 1, - segmentsRootMappings: segmentsRootMappings, - bundle: bundle - )), - ]), - ]), - "network calls: \(network.calls)" - ) + #expect(network.calls.count == 3) - let event = try #require(events.first { $0 is RuntimeEvents.WorkPackageBundleReceivedReply } as? RuntimeEvents - .WorkPackageBundleReceivedReply) - #expect(event.source == key.ed25519.data) - #expect(event.workReportHash == workReportHash) - #expect(event.signature == signature) + let event = events.first { $0 is RuntimeEvents.WorkPackageBundleReceivedReply } as? RuntimeEvents + .WorkPackageBundleReceivedReply + #expect(event?.source == key.ed25519.data) + #expect(event?.workReportHash == workReportHash) + #expect(event?.signature == signature) } @Test @@ -241,6 +231,38 @@ struct NetworkManagerTests { #expect(block.hash == services.genesisBlock.hash) } + @Test + func testWorkPackageBundleReadyInvalidResponse() async throws { + // Here, we configure the mock network to provide an empty response. + // That should trigger the "WorkPackageSharing response is invalid" path, + // preventing publication of a WorkPackageBundleReceivedReply event. + + network.state.write { $0.simulatedResponseData = [] } + + // Since the dev peer public key in the mock is all zeros, + // we'll use Data32(repeating: 0) for the target to avoid a peerNotFound error. + let target = Data32(repeating: 0) + let bundle = WorkPackageBundle.dummy(config: services.config) + let segmentsRootMappings = [SegmentsRootMapping( + workPackageHash: Data32(), + segmentsRoot: Data32() + )] + + await services.blockchain.publish(event: RuntimeEvents.WorkPackageBundleReady( + target: target, + coreIndex: 321, + bundle: bundle, + segmentsRootMappings: segmentsRootMappings + )) + + // Wait for async processing + let events = await storeMiddleware.wait() + let reply = events.first(where: { $0 is RuntimeEvents.WorkPackageBundleReceivedReply }) + + // Verify no event was published + #expect(reply == nil) + } + @Test func testHandleWorkPackageSubmission() async throws { // Create work package and extrinsics @@ -304,44 +326,32 @@ struct NetworkManagerTests { } @Test - func testWorkPackageBundleReadyInvalidResponse() async throws { - // Here, we configure the mock network to provide an empty response. - // That should trigger the "WorkPackageSharing response is invalid" path, - // preventing publication of a WorkPackageBundleReceivedReply event. - - network.state.write { $0.simulatedResponseData = [] } - - // Since the dev peer public key in the mock is all zeros, - // we'll use Data32(repeating: 0) for the target to avoid a peerNotFound error. - let target = Data32(repeating: 0) - let bundle = WorkPackageBundle.dummy(config: services.config) - let segmentsRootMappings = [SegmentsRootMapping( - workPackageHash: Data32(), - segmentsRoot: Data32() - )] - - await services.blockchain.publish(event: RuntimeEvents.WorkPackageBundleReady( - target: target, - coreIndex: 321, - bundle: bundle, - segmentsRootMappings: segmentsRootMappings + func testHandleWorkReportDistribution() async throws { + let workReport = WorkReport.dummy(config: services.config) + let slot: UInt32 = 123 + let signature = ValidatorSignature(validatorIndex: 0, signature: Ed25519Signature(repeating: 20)) + let signatures = [signature, signature, signature] + let distributionMessage = CERequest.workReportDistribution(WorkReportDistributionMessage( + workReport: workReport, + slot: slot, + signatures: signatures )) - // Wait for async processing - let events = await storeMiddleware.wait() - let reply = events.first(where: { $0 is RuntimeEvents.WorkPackageBundleReceivedReply }) + let message = try WorkReportDistributionMessage.decode(data: distributionMessage.encode(), config: services.config) + #expect(slot == message.slot) - // Verify no event was published - #expect(reply == nil) + _ = await services.dataAvailabilityService + let data = try await network.handler.handle(ceRequest: distributionMessage) + await storeMiddleware.wait() + #expect(data == []) } @Test - func testHandleWorkReportDistribution() async throws { + func testHandleInvalidWorkReportDistribution() async throws { let workReport = WorkReport.dummy(config: services.config) let slot: UInt32 = 123 let signatures = [ValidatorSignature(validatorIndex: 0, signature: Ed25519Signature(repeating: 20))] - - let distributionMessage = CERequest.workReportDistrubution(WorkReportDistributionMessage( + let distributionMessage = CERequest.workReportDistribution(WorkReportDistributionMessage( workReport: workReport, slot: slot, signatures: signatures @@ -350,21 +360,11 @@ struct NetworkManagerTests { let message = try WorkReportDistributionMessage.decode(data: distributionMessage.encode(), config: services.config) #expect(slot == message.slot) - _ = try await network.handler.handle(ceRequest: distributionMessage) - - let events = await storeMiddleware.wait() - - let receivedEvent = events.first { - if let event = $0 as? RuntimeEvents.WorkReportReceived { - return event.workReport.hash() == workReport.hash() - } - return false - } as? RuntimeEvents.WorkReportReceived + _ = await services.dataAvailabilityService - let event = try #require(receivedEvent) - #expect(event.workReport == workReport) - #expect(event.slot == slot) - #expect(event.signatures == signatures) + await #expect(throws: Error.self) { + _ = try await network.handler.handle(ceRequest: distributionMessage) + } } @Test @@ -378,19 +378,10 @@ struct NetworkManagerTests { let message = try WorkReportRequestMessage.decode(data: requestMessage.encode(), config: services.config) #expect(workReportHash == message.workReportHash) - _ = try await network.handler.handle(ceRequest: requestMessage) - - let events = await storeMiddleware.wait() - - let receivedEvent = events.first { - if let event = $0 as? RuntimeEvents.WorkReportRequestReceived { - return event.workReportHash == workReportHash - } - return false - } as? RuntimeEvents.WorkReportRequestReceived + let data = try await network.handler.handle(ceRequest: requestMessage) - let event = try #require(receivedEvent) - #expect(event.workReportHash == workReportHash) + await storeMiddleware.wait() + #expect(data == []) } @Test diff --git a/Node/Tests/NodeTests/NodeTests.swift b/Node/Tests/NodeTests/NodeTests.swift index 010f21e9..36d18162 100644 --- a/Node/Tests/NodeTests/NodeTests.swift +++ b/Node/Tests/NodeTests/NodeTests.swift @@ -85,6 +85,11 @@ final class NodeTests { await #expect(throws: StateBackendError.self) { _ = try await validatorNode.blockchain.dataProvider.getStorage(key: Data32.random(), blockHash: nil) } + let guaranteedWorkReport = GuaranteedWorkReport.dummy(config: .dev) + let hash = guaranteedWorkReport.workReport.hash() + try await validatorNode.blockchain.dataProvider.add(guaranteedWorkReport: GuaranteedWorkReportRef(guaranteedWorkReport)) + #expect(try await (validatorNode.blockchain.dataProvider.getGuaranteedWorkReport(hash: hash)) != nil) + #expect(try await validatorNode.blockchain.dataProvider.hasGuaranteedWorkReport(hash: hash) == true) } @Test func sync() async throws { diff --git a/PolkaVM/Package.resolved b/PolkaVM/Package.resolved deleted file mode 100644 index a57c3ba5..00000000 --- a/PolkaVM/Package.resolved +++ /dev/null @@ -1,96 +0,0 @@ -{ - "originHash" : "5f5f6662e0a341792801f498df286aec16ade8bbccd3121439d34662fc774385", - "pins" : [ - { - "identity" : "blake2.swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/tesseract-one/Blake2.swift.git", - "state" : { - "revision" : "29c55c8fe42d6661e5a32cc5bbbad1fff64fd01e", - "version" : "0.2.0" - } - }, - { - "identity" : "lrucache", - "kind" : "remoteSourceControl", - "location" : "https://github.com/nicklockwood/LRUCache.git", - "state" : { - "revision" : "542f0449556327415409ededc9c43a4bd0a397dc", - "version" : "1.0.7" - } - }, - { - "identity" : "swift-crypto", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-crypto.git", - "state" : { - "revision" : "46072478ca365fe48370993833cb22de9b41567f", - "version" : "3.5.2" - } - }, - { - "identity" : "swift-distributed-tracing", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-distributed-tracing.git", - "state" : { - "revision" : "11c756c5c4d7de0eeed8595695cadd7fa107aa19", - "version" : "1.1.1" - } - }, - { - "identity" : "swift-log", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-log.git", - "state" : { - "revision" : "9cb486020ebf03bfa5b5df985387a14a98744537", - "version" : "1.6.1" - } - }, - { - "identity" : "swift-metrics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-metrics.git", - "state" : { - "revision" : "e0165b53d49b413dd987526b641e05e246782685", - "version" : "2.5.0" - } - }, - { - "identity" : "swift-numerics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-numerics", - "state" : { - "branch" : "main", - "revision" : "e30276bff2ff5ed80566fbdca49f50aa160b0e83" - } - }, - { - "identity" : "swift-service-context", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-service-context.git", - "state" : { - "revision" : "0c62c5b4601d6c125050b5c3a97f20cce881d32b", - "version" : "1.1.0" - } - }, - { - "identity" : "swift-syntax", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-syntax.git", - "state" : { - "revision" : "4c6cc0a3b9e8f14b3ae2307c5ccae4de6167ac2c", - "version" : "600.0.0-prerelease-2024-06-12" - } - }, - { - "identity" : "swift-testing", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-testing.git", - "state" : { - "branch" : "0.10.0", - "revision" : "69d59cfc76e5daf498ca61f5af409f594768eef9" - } - } - ], - "version" : 3 -} diff --git a/PolkaVM/Package.swift b/PolkaVM/Package.swift index 88e789e1..30ebea01 100644 --- a/PolkaVM/Package.swift +++ b/PolkaVM/Package.swift @@ -17,7 +17,7 @@ let package = Package( dependencies: [ .package(path: "../Utils"), .package(path: "../TracingUtils"), - .package(url: "https://github.com/apple/swift-testing.git", branch: "0.10.0"), + .package(url: "https://github.com/apple/swift-testing.git", branch: "6.0.0"), .package(url: "https://github.com/apple/swift-log.git", from: "1.6.0"), .package(url: "https://github.com/nicklockwood/LRUCache.git", from: "1.0.7"), ], diff --git a/RPC/Package.resolved b/RPC/Package.resolved deleted file mode 100644 index 6a32554f..00000000 --- a/RPC/Package.resolved +++ /dev/null @@ -1,249 +0,0 @@ -{ - "originHash" : "0eb45f2fc8fa9cfa864623c83d1048088ec88a1e8a0d9e55289c5970e6ea29bd", - "pins" : [ - { - "identity" : "async-http-client", - "kind" : "remoteSourceControl", - "location" : "https://github.com/swift-server/async-http-client.git", - "state" : { - "revision" : "64abc77edf1ef81e69bd90a2ac386de615c8e8ea", - "version" : "1.23.0" - } - }, - { - "identity" : "async-kit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/vapor/async-kit.git", - "state" : { - "revision" : "e048c8ee94967e8d8a1c2ec0e1156d6f7fa34d31", - "version" : "1.20.0" - } - }, - { - "identity" : "blake2.swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/tesseract-one/Blake2.swift.git", - "state" : { - "revision" : "29c55c8fe42d6661e5a32cc5bbbad1fff64fd01e", - "version" : "0.2.0" - } - }, - { - "identity" : "console-kit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/vapor/console-kit.git", - "state" : { - "revision" : "78c0dd739df8cb9ee14a8bbbf770facc4fc3402a", - "version" : "4.15.0" - } - }, - { - "identity" : "lrucache", - "kind" : "remoteSourceControl", - "location" : "https://github.com/nicklockwood/LRUCache.git", - "state" : { - "revision" : "542f0449556327415409ededc9c43a4bd0a397dc", - "version" : "1.0.7" - } - }, - { - "identity" : "multipart-kit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/vapor/multipart-kit.git", - "state" : { - "revision" : "a31236f24bfd2ea2f520a74575881f6731d7ae68", - "version" : "4.7.0" - } - }, - { - "identity" : "routing-kit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/vapor/routing-kit.git", - "state" : { - "revision" : "8c9a227476555c55837e569be71944e02a056b72", - "version" : "4.9.1" - } - }, - { - "identity" : "swift-algorithms", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-algorithms.git", - "state" : { - "revision" : "f6919dfc309e7f1b56224378b11e28bab5bccc42", - "version" : "1.2.0" - } - }, - { - "identity" : "swift-atomics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-atomics.git", - "state" : { - "revision" : "cd142fd2f64be2100422d658e7411e39489da985", - "version" : "1.2.0" - } - }, - { - "identity" : "swift-collections", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-collections.git", - "state" : { - "revision" : "671108c96644956dddcd89dd59c203dcdb36cec7", - "version" : "1.1.4" - } - }, - { - "identity" : "swift-crypto", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-crypto.git", - "state" : { - "revision" : "ffca28be3c9c6a86a579949d23f68818a4b9b5d8", - "version" : "3.8.0" - } - }, - { - "identity" : "swift-distributed-tracing", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-distributed-tracing.git", - "state" : { - "revision" : "6483d340853a944c96dbcc28b27dd10b6c581703", - "version" : "1.1.2" - } - }, - { - "identity" : "swift-http-types", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-http-types", - "state" : { - "revision" : "ae67c8178eb46944fd85e4dc6dd970e1f3ed6ccd", - "version" : "1.3.0" - } - }, - { - "identity" : "swift-log", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-log.git", - "state" : { - "revision" : "9cb486020ebf03bfa5b5df985387a14a98744537", - "version" : "1.6.1" - } - }, - { - "identity" : "swift-metrics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-metrics.git", - "state" : { - "revision" : "e0165b53d49b413dd987526b641e05e246782685", - "version" : "2.5.0" - } - }, - { - "identity" : "swift-nio", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio.git", - "state" : { - "revision" : "665206000b8307cab5ac51203d29b0f232d7e31b", - "version" : "2.74.0" - } - }, - { - "identity" : "swift-nio-extras", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-extras.git", - "state" : { - "revision" : "d1ead62745cc3269e482f1c51f27608057174379", - "version" : "1.24.0" - } - }, - { - "identity" : "swift-nio-http2", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-http2.git", - "state" : { - "revision" : "eaa71bb6ae082eee5a07407b1ad0cbd8f48f9dca", - "version" : "1.34.1" - } - }, - { - "identity" : "swift-nio-ssl", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-ssl.git", - "state" : { - "revision" : "7b84abbdcef69cc3be6573ac12440220789dcd69", - "version" : "2.27.2" - } - }, - { - "identity" : "swift-nio-transport-services", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-transport-services.git", - "state" : { - "revision" : "dbace16f126fdcd80d58dc54526c561ca17327d7", - "version" : "1.22.0" - } - }, - { - "identity" : "swift-numerics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-numerics.git", - "state" : { - "branch" : "main", - "revision" : "e30276bff2ff5ed80566fbdca49f50aa160b0e83" - } - }, - { - "identity" : "swift-service-context", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-service-context.git", - "state" : { - "revision" : "0c62c5b4601d6c125050b5c3a97f20cce881d32b", - "version" : "1.1.0" - } - }, - { - "identity" : "swift-syntax", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-syntax.git", - "state" : { - "revision" : "0687f71944021d616d34d922343dcef086855920", - "version" : "600.0.1" - } - }, - { - "identity" : "swift-system", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-system.git", - "state" : { - "revision" : "d2ba781702a1d8285419c15ee62fd734a9437ff5", - "version" : "1.3.2" - } - }, - { - "identity" : "swift-testing", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-testing.git", - "state" : { - "branch" : "0.10.0", - "revision" : "69d59cfc76e5daf498ca61f5af409f594768eef9" - } - }, - { - "identity" : "vapor", - "kind" : "remoteSourceControl", - "location" : "https://github.com/vapor/vapor.git", - "state" : { - "revision" : "1466c50e4ad39072143e2fcdf13b4ba11be375a0", - "version" : "4.106.0" - } - }, - { - "identity" : "websocket-kit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/vapor/websocket-kit.git", - "state" : { - "revision" : "4232d34efa49f633ba61afde365d3896fc7f8740", - "version" : "2.15.0" - } - } - ], - "version" : 3 -} diff --git a/RPC/Package.swift b/RPC/Package.swift index bebdb1c7..52dd2da2 100644 --- a/RPC/Package.swift +++ b/RPC/Package.swift @@ -18,10 +18,9 @@ let package = Package( dependencies: [ .package(path: "../Blockchain"), .package(path: "../Utils"), - .package(url: "https://github.com/vapor/vapor.git", from: "4.106.0"), + .package(url: "https://github.com/vapor/vapor.git", branch: "4.107.0"), .package(url: "https://github.com/vapor/async-kit.git", from: "1.20.0"), - .package(url: "https://github.com/apple/swift-testing.git", branch: "0.10.0"), - + .package(url: "https://github.com/apple/swift-testing.git", branch: "6.0.0"), ], targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. @@ -43,5 +42,6 @@ let package = Package( .product(name: "Testing", package: "swift-testing"), ] ), - ] + ], + swiftLanguageModes: [.version("6")] ) diff --git a/RPC/Tests/RPCTests/BuilderHandlersTests.swift b/RPC/Tests/RPCTests/BuilderHandlersTests.swift index 91707a39..cc91dcfa 100644 --- a/RPC/Tests/RPCTests/BuilderHandlersTests.swift +++ b/RPC/Tests/RPCTests/BuilderHandlersTests.swift @@ -36,7 +36,7 @@ final class BuilderRPCControllerTests { let req = JSONRequest(jsonrpc: "2.0", method: "builder_submitWorkPackage", params: params, id: 0) var buffer = ByteBuffer() try buffer.writeJSONEncodable(req) - try await app.test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res async in + try await app.testable().test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res async in #expect(res.status == .ok) let resp = try? res.content.decode(JSONResponse.self, using: JSONDecoder()) #expect(resp?.result?.value as? JSON == .boolean(true)) diff --git a/RPC/Tests/RPCTests/ChainHandlesTests.swift b/RPC/Tests/RPCTests/ChainHandlesTests.swift index 85824b5b..e29173d0 100644 --- a/RPC/Tests/RPCTests/ChainHandlesTests.swift +++ b/RPC/Tests/RPCTests/ChainHandlesTests.swift @@ -72,10 +72,10 @@ final class ChainRPCControllerTests { let req = JSONRequest(jsonrpc: "2.0", method: "chain_getBlock", params: params, id: 1) var buffer = ByteBuffer() try buffer.writeJSONEncodable(req) - try await app.test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res async in + try await app.testable().test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res async in #expect(res.status == .ok) let resp = try! res.content.decode(JSONResponse.self, using: JSONDecoder()) - #expect(resp.result!.value != nil) + #expect(resp.result?.value != nil) } try await app.asyncShutdown() } @@ -87,10 +87,10 @@ final class ChainRPCControllerTests { let req = JSONRequest(jsonrpc: "2.0", method: "chain_getBlockHash", params: params, id: 2) var buffer = ByteBuffer() try buffer.writeJSONEncodable(req) - try await app.test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res async in + try await app.testable().test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res async in #expect(res.status == .ok) let resp = try! res.content.decode(JSONResponse.self, using: JSONDecoder()) - #expect(resp.result!.value != nil) + #expect(resp.result?.value != nil) } try await app.asyncShutdown() } @@ -100,7 +100,7 @@ final class ChainRPCControllerTests { let req = JSONRequest(jsonrpc: "2.0", method: "chain_getFinalizedHead", params: nil, id: 3) var buffer = ByteBuffer() try buffer.writeJSONEncodable(req) - try await app.test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res async in + try await app.testable().test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res async in #expect(res.status == .ok) let resp = try! res.content.decode(JSONResponse.self, using: JSONDecoder()) #expect(resp.result!.value != nil) @@ -115,7 +115,7 @@ final class ChainRPCControllerTests { let req = JSONRequest(jsonrpc: "2.0", method: "chain_getHeader", params: params, id: 4) var buffer = ByteBuffer() try buffer.writeJSONEncodable(req) - try await app.test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res async in + try await app.testable().test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res async in #expect(res.status == .ok) let resp = try! res.content.decode(JSONResponse.self, using: JSONDecoder()) #expect(resp.result!.value != nil) diff --git a/RPC/Tests/RPCTests/KeystoreHandlersTests.swift b/RPC/Tests/RPCTests/KeystoreHandlersTests.swift index ad35802b..17c85330 100644 --- a/RPC/Tests/RPCTests/KeystoreHandlersTests.swift +++ b/RPC/Tests/RPCTests/KeystoreHandlersTests.swift @@ -45,7 +45,7 @@ final class KeystoreHandlersTests { let req = JSONRequest(jsonrpc: "2.0", method: "keys_create", params: params, id: 0) var buffer = ByteBuffer() try buffer.writeJSONEncodable(req) - try await app.test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res async in + try await app.testable().test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res async in #expect(res.status == .ok) let resp = try? res.content.decode(JSONResponse.self, using: JSONDecoder()) #expect(resp?.result?.value is JSON) @@ -65,7 +65,7 @@ final class KeystoreHandlersTests { let req = JSONRequest(jsonrpc: "2.0", method: "keys_list", params: .array([]), id: 0) var buffer = ByteBuffer() try buffer.writeJSONEncodable(req) - try await app.test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res async in + try await app.testable().test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res async in #expect(res.status == .ok) let resp = try? res.content.decode(JSONResponse.self, using: JSONDecoder()) #expect((resp?.result?.value as! JSON).array!.count >= 2) @@ -81,7 +81,7 @@ final class KeystoreHandlersTests { let req = JSONRequest(jsonrpc: "2.0", method: "keys_hasKey", params: params, id: 0) var buffer = ByteBuffer() try buffer.writeJSONEncodable(req) - try await app.test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res async in + try await app.testable().test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res async in #expect(res.status == .ok) let resp = try? res.content.decode(JSONResponse.self, using: JSONDecoder()) #expect((resp?.result!.value as! JSON).bool == true) diff --git a/RPC/Tests/RPCTests/StateHandlersTests.swift b/RPC/Tests/RPCTests/StateHandlersTests.swift index 64c20ed5..e691f677 100644 --- a/RPC/Tests/RPCTests/StateHandlersTests.swift +++ b/RPC/Tests/RPCTests/StateHandlersTests.swift @@ -34,10 +34,10 @@ final class StateHandlersTests { let req = JSONRequest(jsonrpc: "2.0", method: "state_getKeys", params: params, id: 1) var buffer = ByteBuffer() try buffer.writeJSONEncodable(req) - try await app.test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res async in + try await app.testable().test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res async in #expect(res.status == .ok) let resp = try! res.content.decode(JSONResponse.self, using: JSONDecoder()) - #expect(resp.result!.value != nil) + #expect(resp.result?.value != nil) } try await app.asyncShutdown() } @@ -49,10 +49,10 @@ final class StateHandlersTests { let req = JSONRequest(jsonrpc: "2.0", method: "state_getStorage", params: params, id: 2) var buffer = ByteBuffer() try buffer.writeJSONEncodable(req) - try await app.test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res async in + try await app.testable().test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res async in #expect(res.status == .ok) let resp = try! res.content.decode(JSONResponse.self, using: JSONDecoder()) - #expect(resp.result!.value != nil) + #expect(resp.result?.value != nil) } try await app.asyncShutdown() } diff --git a/RPC/Tests/RPCTests/SystemHandlersTests.swift b/RPC/Tests/RPCTests/SystemHandlersTests.swift index 14baa069..628e57b4 100644 --- a/RPC/Tests/RPCTests/SystemHandlersTests.swift +++ b/RPC/Tests/RPCTests/SystemHandlersTests.swift @@ -53,7 +53,7 @@ final class SystemHandlersTests { let req = JSONRequest(jsonrpc: "2.0", method: "system_health", params: nil, id: 1) var buffer = ByteBuffer() try buffer.writeJSONEncodable(req) - try app.test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res in + try app.testable().test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res in #expect(res.status == .ok) let resp = try res.content.decode(JSONResponse.self, using: JSONDecoder()) #expect((resp.result!.value as! Utils.JSON).bool == true) @@ -64,7 +64,7 @@ final class SystemHandlersTests { let req = JSONRequest(jsonrpc: "2.0", method: "system_implementation", params: nil, id: 2) var buffer = ByteBuffer() try buffer.writeJSONEncodable(req) - try app.test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res in + try app.testable().test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res in #expect(res.status == .ok) let resp = try res.content.decode(JSONResponse.self, using: JSONDecoder()) #expect((resp.result!.value as! Utils.JSON).string == "Boka") @@ -75,7 +75,7 @@ final class SystemHandlersTests { let req = JSONRequest(jsonrpc: "2.0", method: "system_version", params: nil, id: 3) var buffer = ByteBuffer() try buffer.writeJSONEncodable(req) - try app.test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res in + try app.testable().test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res in #expect(res.status == .ok) let resp = try res.content.decode(JSONResponse.self, using: JSONDecoder()) #expect((resp.result!.value as! Utils.JSON).string == "0.0.1") @@ -86,7 +86,7 @@ final class SystemHandlersTests { let req = JSONRequest(jsonrpc: "2.0", method: "system_properties", params: nil, id: 4) var buffer = ByteBuffer() try buffer.writeJSONEncodable(req) - try app.test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res in + try app.testable().test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res in #expect(res.status == .ok) let resp = try res.content.decode(JSONResponse.self, using: JSONDecoder()) #expect(resp.result?.value != nil) @@ -97,7 +97,7 @@ final class SystemHandlersTests { let req = JSONRequest(jsonrpc: "2.0", method: "system_nodeRoles", params: nil, id: 5) var buffer = ByteBuffer() try buffer.writeJSONEncodable(req) - try app.test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res in + try app.testable().test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res in #expect(res.status == .ok) let resp = try res.content.decode(JSONResponse.self, using: JSONDecoder()) #expect((resp.result!.value as! Utils.JSON).array == []) @@ -108,7 +108,7 @@ final class SystemHandlersTests { let req = JSONRequest(jsonrpc: "2.0", method: "system_chain", params: nil, id: 6) var buffer = ByteBuffer() try buffer.writeJSONEncodable(req) - try app.test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res in + try app.testable().test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res in #expect(res.status == .ok) let resp = try res.content.decode(JSONResponse.self, using: JSONDecoder()) #expect((resp.result!.value as! Utils.JSON).string == "dev") diff --git a/RPC/Tests/RPCTests/TelemetryHandlersTests.swift b/RPC/Tests/RPCTests/TelemetryHandlersTests.swift index 195bae74..d7ea7b7e 100644 --- a/RPC/Tests/RPCTests/TelemetryHandlersTests.swift +++ b/RPC/Tests/RPCTests/TelemetryHandlersTests.swift @@ -41,7 +41,7 @@ final class TelemetryHandlersTests { let req = JSONRequest(jsonrpc: "2.0", method: "telemetry_name", params: nil, id: 1) var buffer = ByteBuffer() try buffer.writeJSONEncodable(req) - try app.test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res in + try app.testable().test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res in #expect(res.status == .ok) let resp = try res.content.decode(JSONResponse.self, using: JSONDecoder()) #expect((resp.result!.value as! Utils.JSON).string == "TestNode") @@ -52,7 +52,7 @@ final class TelemetryHandlersTests { let req = JSONRequest(jsonrpc: "2.0", method: "telemetry_peersCount", params: nil, id: 2) var buffer = ByteBuffer() try buffer.writeJSONEncodable(req) - try app.test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res in + try app.testable().test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res in #expect(res.status == .ok) let resp = try res.content.decode(JSONResponse.self, using: JSONDecoder()) #expect((resp.result!.value as! Utils.JSON).number == 42) @@ -63,7 +63,7 @@ final class TelemetryHandlersTests { let req = JSONRequest(jsonrpc: "2.0", method: "telemetry_networkKey", params: nil, id: 3) var buffer = ByteBuffer() try buffer.writeJSONEncodable(req) - try app.test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res in + try app.testable().test(.POST, "/", headers: ["Content-Type": "application/json"], body: buffer) { res in #expect(res.status == .ok) let resp = try res.content.decode(JSONResponse.self, using: JSONDecoder()) #expect((resp.result!.value as! Utils.JSON).string == "Ed25519:TestKey") diff --git a/Tools/Package.swift b/Tools/Package.swift index d88d75a7..3c9cddf1 100644 --- a/Tools/Package.swift +++ b/Tools/Package.swift @@ -14,7 +14,7 @@ let package = Package( .package(path: "../TracingUtils"), .package(path: "../Utils"), .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.5.0"), - .package(url: "https://github.com/ajevans99/swift-json-schema.git", exact: "0.2.1"), + .package(url: "https://github.com/ajevans99/swift-json-schema.git", from: "0.3.2"), .package(url: "https://github.com/wickwirew/Runtime.git", from: "2.2.7"), ], targets: [ diff --git a/Tools/Sources/Tools/OpenRPC.swift b/Tools/Sources/Tools/OpenRPC.swift index 7b84a8d3..ec3a81d7 100644 --- a/Tools/Sources/Tools/OpenRPC.swift +++ b/Tools/Sources/Tools/OpenRPC.swift @@ -31,7 +31,9 @@ struct OpenRPC: AsyncParsableCommand { name: h.method, summary: h.summary, description: nil, - params: h.requestType.types.enumerated().map { createSpecContent(type: $1, name: h.requestNames[safe: $0]) }, + params: h.requestType.types.enumerated().map { + createSpecContent(type: $1, name: h.requestNames[safe: $0]) + }, result: createSpecContent(type: h.responseType, name: nil), examples: nil ) @@ -46,6 +48,8 @@ struct OpenRPC: AsyncParsableCommand { } } +// MARK: - Optional Type Check + private protocol OptionalProtocol { static var wrappedType: Any.Type { get } } @@ -56,14 +60,45 @@ extension Optional: OptionalProtocol { } } +// MARK: - Type Erasure Wrapper + +struct AnyJSONSchemaComponent: JSONSchemaComponent, @unchecked Sendable { + typealias Output = Any + + private var _schemaValue: [KeywordIdentifier: JSONValue] + private let _parse: @Sendable (JSONValue) -> Parsed + + init(wrapped component: some JSONSchemaComponent) { + _schemaValue = component.schemaValue + _parse = { value in component.parse(value).map { $0 as Any } } + } + + var schemaValue: [KeywordIdentifier: JSONValue] { + get { _schemaValue } + set { + _schemaValue = newValue + } + } + + func parse(_ value: JSONValue) -> Parsed { + _parse(value) + } +} + +// 👇 Wrap helper for nicer syntax +func wrap(_ schema: any JSONSchemaComponent) -> AnyJSONSchemaComponent { + .init(wrapped: schema) +} + +// MARK: - Builder helpers + func build(@JSONSchemaBuilder _ content: () -> any JSONSchemaComponent) -> any JSONSchemaComponent { content() } func createSpecContent(type: Any.Type, name: String?) -> SpecContent { - // if it is optional - if let type = type as? OptionalProtocol.Type { - return createSpecContentInner(type: type.wrappedType, required: false) + if let optionalType = type as? OptionalProtocol.Type { + return createSpecContentInner(type: optionalType.wrappedType, required: false) } else { return createSpecContentInner(type: type, required: true) } @@ -74,37 +109,39 @@ func createSpecContent(type: Any.Type, name: String?) -> SpecContent { summary: nil, description: nil, required: required, - schema: getSchema(type: type).definition + schema: getSchema(type: type).definition() ) } } +// MARK: - Type Descriptions + protocol TypeDescription { static var name: String { get } - static var schema: any JSONSchemaComponent { get } } func getName(type: Any.Type) -> String { - if let type = type as? TypeDescription.Type { - return type.name + if let t = type as? TypeDescription.Type { + return t.name } return String(describing: type) } func getSchema(type: Any.Type) -> any JSONSchemaComponent { - if let type = type as? TypeDescription.Type { - return type.schema + if let t = type as? TypeDescription.Type { + return t.schema } let info = try! typeInfo(of: type) + switch info.kind { case .struct, .class: return build { JSONObject { for field in info.properties { JSONProperty(key: field.name) { - getSchema(type: field.type) + wrap(getSchema(type: field.type)) } } }.title(getName(type: type)) @@ -116,6 +153,8 @@ func getSchema(type: Any.Type) -> any JSONSchemaComponent { } } +// MARK: - Conformances + extension Optional: TypeDescription { static var name: String { "Optional<\(getName(type: Wrapped.self))>" @@ -127,33 +166,18 @@ extension Optional: TypeDescription { } extension Bool: TypeDescription { - static var name: String { - "Bool" - } - - static var schema: any JSONSchemaComponent { - JSONBoolean() - } + static var name: String { "Bool" } + static var schema: any JSONSchemaComponent { JSONBoolean() } } extension String: TypeDescription { - static var name: String { - "String" - } - - static var schema: any JSONSchemaComponent { - JSONString() - } + static var name: String { "String" } + static var schema: any JSONSchemaComponent { JSONString() } } extension BinaryInteger where Self: TypeDescription { - static var name: String { - String(describing: Self.self) - } - - static var schema: any JSONSchemaComponent { - JSONInteger() - } + static var name: String { String(describing: Self.self) } + static var schema: any JSONSchemaComponent { JSONInteger() } } extension Int8: TypeDescription {} @@ -168,36 +192,23 @@ extension UInt64: TypeDescription {} extension UInt: TypeDescription {} extension Data: TypeDescription { - static var name: String { - "Data" - } - + static var name: String { "Data" } static var schema: any JSONSchemaComponent { - JSONString() - .title(name) - .pattern("^0x[0-9a-fA-F]*$") + JSONString().title(name).pattern("^0x[0-9a-fA-F]*$") } } extension FixedSizeData: TypeDescription { - static var name: String { - "Data\(T.value)" - } - + static var name: String { "Data\(T.value)" } static var schema: any JSONSchemaComponent { - JSONString() - .title(name) - .pattern("^0x[0-9a-fA-F]{\(T.value * 2)}$") + JSONString().title(name).pattern("^0x[0-9a-fA-F]{\(T.value * 2)}$") } } extension Array: TypeDescription { - static var name: String { - "Array<\(getName(type: Element.self))>" - } - + static var name: String { "Array<\(getName(type: Element.self))>" } static var schema: any JSONSchemaComponent { - JSONArray().items { getSchema(type: Element.self) } + JSONArray { wrap(getSchema(type: Element.self)) } } } @@ -217,7 +228,7 @@ extension Set: TypeDescription { } static var schema: any JSONSchemaComponent { - JSONArray().items { getSchema(type: Element.self) } + JSONArray { wrap(getSchema(type: Element.self)) } } } @@ -231,7 +242,7 @@ extension LimitedSizeArray: TypeDescription { } static var schema: any JSONSchemaComponent { - JSONArray().items { getSchema(type: T.self) } + JSONArray { wrap(getSchema(type: T.self)) } } } @@ -241,15 +252,12 @@ extension ConfigLimitedSizeArray: TypeDescription { } static var schema: any JSONSchemaComponent { - JSONArray().items { getSchema(type: T.self) } + JSONArray { wrap(getSchema(type: T.self)) } } } extension Ref: TypeDescription { - static var name: String { - getName(type: T.self) - } - + static var name: String { getName(type: T.self) } static var schema: any JSONSchemaComponent { getSchema(type: T.self) } diff --git a/Utils/Package.resolved b/Utils/Package.resolved index 8c7162ca..06816716 100644 --- a/Utils/Package.resolved +++ b/Utils/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "3af4fa15534a1d00e66459fc585003c2f7835023bebcf2a960f70e34d14438b2", + "originHash" : "3847f043e8fc69c774b86676c165ce04729f02b98bdfdfe1c869bf7e3be10c62", "pins" : [ { "identity" : "blake2.swift", @@ -67,10 +67,10 @@ { "identity" : "swift-syntax", "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-syntax.git", + "location" : "https://github.com/swiftlang/swift-syntax.git", "state" : { - "revision" : "4c6cc0a3b9e8f14b3ae2307c5ccae4de6167ac2c", - "version" : "600.0.0-prerelease-2024-06-12" + "revision" : "0687f71944021d616d34d922343dcef086855920", + "version" : "600.0.1" } }, { @@ -78,8 +78,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-testing.git", "state" : { - "branch" : "0.10.0", - "revision" : "69d59cfc76e5daf498ca61f5af409f594768eef9" + "branch" : "release/6.0", + "revision" : "18c42c19cac3fafd61cab1156d4088664b7424ae" } } ], diff --git a/Utils/Package.swift b/Utils/Package.swift index 17386e22..e28854b5 100644 --- a/Utils/Package.swift +++ b/Utils/Package.swift @@ -20,7 +20,7 @@ let package = Package( .package(path: "../TracingUtils"), .package(url: "https://github.com/tesseract-one/Blake2.swift.git", from: "0.2.0"), .package(url: "https://github.com/apple/swift-crypto.git", "1.0.0" ..< "4.0.0"), - .package(url: "https://github.com/apple/swift-testing.git", branch: "0.10.0"), + .package(url: "https://github.com/apple/swift-testing.git", branch: "6.0.0"), .package(url: "https://github.com/apple/swift-numerics.git", branch: "main"), ], targets: [ diff --git a/boka.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/boka.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 82640dcc..d625cece 100644 --- a/boka.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/boka.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "b28090dfdf5ab8e8dee9a65a599ae5b90407e31d8811503956bc2c2b1fdeaa66", + "originHash" : "29f4f0920a303b91d3ab3d9a73e42e497b83eeafb0e20a02a020e5dbbc9bd47c", "pins" : [ { "identity" : "async-channels", @@ -15,8 +15,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/swift-server/async-http-client.git", "state" : { - "revision" : "0ae99db85b2b9d1e79b362bd31fd1ffe492f7c47", - "version" : "1.21.2" + "revision" : "333f51104b75d1a5b94cb3b99e4c58a3b442c9f7", + "version" : "1.25.2" } }, { @@ -186,8 +186,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/ajevans99/swift-json-schema.git", "state" : { - "revision" : "671f1777a96343b99435d2eb8af72bcb49d175bd", - "version" : "0.2.1" + "revision" : "707fc4c2d53138e8fbb4ee9e6669b050ba4b2239", + "version" : "0.3.2" } }, { @@ -213,8 +213,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-nio.git", "state" : { - "revision" : "4c4453b489cf76e6b3b0f300aba663eb78182fad", - "version" : "2.70.0" + "revision" : "c51907a839e63ebf0ba2076bba73dd96436bd1b9", + "version" : "2.81.0" } }, { @@ -312,8 +312,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-system.git", "state" : { - "revision" : "d2ba781702a1d8285419c15ee62fd734a9437ff5", - "version" : "1.3.2" + "revision" : "a34201439c74b53f0fd71ef11741af7e7caf01e1", + "version" : "1.4.2" } }, { @@ -330,8 +330,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/vapor/vapor.git", "state" : { - "revision" : "1466c50e4ad39072143e2fcdf13b4ba11be375a0", - "version" : "4.106.0" + "revision" : "87b0edd2633c35de543cb7573efe5fbf456181bc", + "version" : "4.114.1" } }, {