@@ -6,6 +6,9 @@ import Utils
66public enum GuaranteeingServiceError : Error {
77 case noAuthorizerHash
88 case invalidExports
9+ case invalidWorkPackage
10+ case invalidBundle
11+ case segmentsRootNotFound
912}
1013
1114public final class GuaranteeingService : ServiceBase2 , @unchecked Sendable {
@@ -38,6 +41,10 @@ public final class GuaranteeingService: ServiceBase2, @unchecked Sendable {
3841 await subscribe ( RuntimeEvents . WorkPackagesReceived. self, id: " GuaranteeingService.WorkPackagesReceived " ) { [ weak self] event in
3942 try await self ? . on ( workPackagesReceived: event)
4043 }
44+
45+ await subscribe ( RuntimeEvents . WorkPackageBundleShare. self, id: " GuaranteeingService.WorkPackageBundleShare " ) { [ weak self] event in
46+ try await self ? . on ( workPackageBundle: event)
47+ }
4148 }
4249
4350 public func onSyncCompleted( ) async {
@@ -78,16 +85,89 @@ public final class GuaranteeingService: ServiceBase2, @unchecked Sendable {
7885 }
7986 }
8087
88+ private func on( workPackageBundle event: RuntimeEvents . WorkPackageBundleShare ) async throws {
89+ try await receiveWorkPackageBundle (
90+ coreIndex: event. coreIndex,
91+ segmentsRootMappings: event. segmentsRootMappings,
92+ bundle: event. bundle
93+ )
94+ }
95+
96+ private func on( workPackageBundleReceived _: RuntimeEvents . WorkPackageBundleRecived ) async throws {
97+ // TODO: check somethings
98+ }
99+
100+ // Method to receive a work package bundle
101+ private func receiveWorkPackageBundle(
102+ coreIndex _: CoreIndex ,
103+ segmentsRootMappings: SegmentsRootMappings ,
104+ bundle: WorkPackageBundle
105+ ) async throws {
106+ // Perform basic verification
107+ guard try validateWorkPackageBundle ( bundle, segmentsRootMappings: segmentsRootMappings) else {
108+ throw GuaranteeingServiceError . invalidBundle
109+ }
110+ }
111+
112+ private func validateWorkPackageBundle(
113+ _ bundle: WorkPackageBundle ,
114+ segmentsRootMappings: SegmentsRootMappings
115+ ) throws -> Bool {
116+ // Validate the work package authorization
117+ guard try validateAuthorization ( bundle. workPackage) else {
118+ return false
119+ }
120+
121+ // Validate the segments-root mappings
122+ for mapping in segmentsRootMappings {
123+ guard try validateSegmentsRootMapping ( mapping, for: bundle. workPackage) else {
124+ return false
125+ }
126+ }
127+
128+ return true
129+ }
130+
81131 private func on( workPackagesReceived event: RuntimeEvents . WorkPackagesReceived ) async throws {
82- try await refinePkg ( package : event. workPackageRef )
132+ try await handleWorkPackage ( coreIndex : event. coreIndex , workPackage : event . workPackage , extrinsics : event . extrinsics )
83133 }
84134
85- private func refinePkg( package : WorkPackageRef ) async throws {
135+ // handle Work Package
136+ public func handleWorkPackage( coreIndex: CoreIndex , workPackage: WorkPackageRef , extrinsics: [ Data ] ) async throws {
137+ // Validate the work package
138+ guard try validate ( workPackage: workPackage. value) else {
139+ logger. error ( " Invalid work package: \( workPackage) " )
140+ throw GuaranteeingServiceError . invalidWorkPackage
141+ }
86142 guard let ( validatorIndex, signingKey) = signingKey. value else {
87143 logger. debug ( " not in current validator set, skipping refine " )
88144 return
89145 }
90146
147+ // check & refine
148+ let ( bundle, mappings, workReport) = try await refinePkg (
149+ validatorIndex: validatorIndex,
150+ workPackage: workPackage,
151+ extrinsics: extrinsics
152+ )
153+
154+ // Share work package bundle
155+ let shareWorkBundleEvent = RuntimeEvents . WorkPackageBundleShare (
156+ coreIndex: coreIndex,
157+ bundle: bundle,
158+ segmentsRootMappings: mappings
159+ )
160+ publish ( shareWorkBundleEvent)
161+ // Sign work report & work-report distribution via CE 135
162+ let payload = SigningContext . guarantee + workReport. hash ( ) . data
163+ let signature = try signingKey. sign ( message: payload)
164+ let workReportEvent = RuntimeEvents . WorkReportGenerated ( item: workReport, signature: signature)
165+ publish ( workReportEvent)
166+ }
167+
168+ private func refinePkg( validatorIndex: ValidatorIndex , workPackage: WorkPackageRef ,
169+ extrinsics: [ Data ] ) async throws -> ( WorkPackageBundle , SegmentsRootMappings , WorkReport )
170+ {
91171 let state = try await dataProvider. getState ( hash: dataProvider. bestHead. hash)
92172
93173 // TODO: check for edge cases such as epoch end
@@ -96,24 +176,63 @@ public final class GuaranteeingService: ServiceBase2, @unchecked Sendable {
96176 randomness: state. value. entropyPool. t2,
97177 timeslot: state. value. timeslot + 1
98178 )
179+ // TODO: coreIndex equal with shareWorkPackage coreIndex?
99180 guard let coreIndex = currentCoreAssignment [ safe: Int ( validatorIndex) ] else {
100181 try throwUnreachable ( " invalid validator index/core assignment " )
101182 }
102183
103- let workReport = try await createWorkReport ( for: package , coreIndex: coreIndex)
104- let payload = SigningContext . guarantee + workReport. hash ( ) . data
105- let signature = try signingKey. sign ( message: payload)
106- let event = RuntimeEvents . WorkReportGenerated ( item: workReport, signature: signature)
107- publish ( event)
184+ // Create work report & WorkPackageBundle
185+ return try await createWorkReport (
186+ coreIndex: coreIndex,
187+ workPackage: workPackage,
188+ extrinsics: extrinsics
189+ )
190+ }
191+
192+ private func validateSegmentsRootMapping(
193+ _: SegmentsRootMapping ,
194+ for _: WorkPackage
195+ ) throws -> Bool {
196+ // TODO: Implement logic to validate the segments-root mapping
197+ true // Placeholder
198+ }
199+
200+ private func validateAuthorization( _: WorkPackage ) throws -> Bool {
201+ // TODO: Implement logic to validate the work package authorization
202+ true // Placeholder
203+ }
204+
205+ // TODO: Add validate func
206+ private func validate( workPackage _: WorkPackage ) throws -> Bool {
207+ // 1. Check if it is possible to generate a work-report
208+ // 2. Check all import segments have been retrieved
209+ true
210+ }
211+
212+ private func retrieveImportSegments( for _: WorkPackage ) async throws -> [ Data4104 ] {
213+ // TODO: Implement retrieveImportSegments
214+ // Implement logic to retrieve imported data segments
215+ // For example, fetch from the data availability layer
216+ [ ] // Placeholder
217+ }
218+
219+ private func retrieveJustifications( for _: WorkPackage ) async throws -> [ Data ] {
220+ // TODO: Implement retrieveJustifications
221+ // Implement logic to retrieve justifications for the imported segments
222+ // For example, fetch proofs from the data availability layer
223+ [ ] // Placeholder
108224 }
109225
110226 // workpackage -> workresult -> workreport
111- private func createWorkReport( for workPackage: WorkPackageRef , coreIndex: CoreIndex ) async throws -> WorkReport {
227+ private func createWorkReport( coreIndex: CoreIndex , workPackage: WorkPackageRef ,
228+ extrinsics: [ Data ] ) async throws -> ( WorkPackageBundle , SegmentsRootMappings , WorkReport )
229+ {
112230 let state = try await dataProvider. getState ( hash: dataProvider. bestHead. hash)
113231 let packageHash = workPackage. hash
114232 let corePool = state. value. coreAuthorizationPool [ coreIndex]
115233 let authorizerHash = try corePool. array. first. unwrap ( orError: GuaranteeingServiceError . noAuthorizerHash)
116234 var exportSegmentOffset : UInt16 = 0
235+ var mappings : SegmentsRootMappings = [ ]
117236 // B.2. the authorization output, the result of the Is-Authorized function
118237 // TODO: waiting for authorizationFunction done Mock a result
119238 // let res = try await authorizationFunction.invoke(config: config, serviceAccounts: state.value, package: workPackage, coreIndex:
@@ -160,16 +279,16 @@ public final class GuaranteeingService: ServiceBase2, @unchecked Sendable {
160279
161280 exportSegments. append ( contentsOf: refineRes. exports)
162281 }
163-
164- let ( erasureRoot, length) = try await dataAvailability. exportWorkpackageBundle ( bundle: WorkPackageBundle (
282+ let bundle = try await WorkPackageBundle (
165283 workPackage: workPackage. value,
166- extrinsic: [ ] , // TODO: get extrinsic data
167- importSegments: [ ] ,
168- justifications: [ ]
169- ) )
284+ extrinsic: extrinsics,
285+ importSegments: retrieveImportSegments ( for: workPackage. value) ,
286+ justifications: retrieveJustifications ( for: workPackage. value)
287+ )
288+ let ( erasureRoot, length) = try await dataAvailability. exportWorkpackageBundle ( bundle: bundle)
170289
171290 let segmentRoot = try await dataAvailability. exportSegments ( data: exportSegments, erasureRoot: erasureRoot)
172-
291+ mappings . append ( SegmentsRootMapping ( workPackageHash : packageHash , segmentsRoot : segmentRoot ) )
173292 // TODO: generate or find AvailabilitySpecifications 14.4.1 work-package bundle
174293 let packageSpecification = AvailabilitySpecifications (
175294 workPackageHash: packageHash,
@@ -183,15 +302,15 @@ public final class GuaranteeingService: ServiceBase2, @unchecked Sendable {
183302 for item in state. value. recentHistory. items {
184303 oldLookups. merge ( item. lookup, uniquingKeysWith: { _, new in new } )
185304 }
186- return try WorkReport (
305+ return try ( bundle , mappings , WorkReport (
187306 authorizerHash: authorizerHash,
188307 coreIndex: coreIndex,
189308 authorizationOutput: authorizationOutput,
190309 refinementContext: workPackage. value. context,
191310 packageSpecification: packageSpecification,
192311 lookup: oldLookups,
193312 results: ConfigLimitedSizeArray ( config: config, array: workResults)
194- )
313+ ) )
195314
196315 case let . failure( error) :
197316 logger. error ( " Authorization failed with error: \( error) " )
0 commit comments