-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
320 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
111 changes: 111 additions & 0 deletions
111
Blockchain/Sources/Blockchain/Validator/WorkPackagePoolService.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import TracingUtils | ||
import Utils | ||
|
||
private actor WorkPackageStorage { | ||
var logger: Logger! | ||
var pendingWorkPackages: SortedUniqueArray<WorkPackageAndOutput> = .init() | ||
var epoch: EpochIndex = 0 | ||
// add core | ||
// var core: CoreIndex = 0 | ||
let ringContext: Bandersnatch.RingContext | ||
var verifier: Bandersnatch.Verifier! | ||
var entropy: Data32 = .init() | ||
|
||
init(ringContext: Bandersnatch.RingContext) { | ||
self.ringContext = ringContext | ||
} | ||
|
||
func setLogger(_ logger: Logger) { | ||
self.logger = logger | ||
} | ||
|
||
func update(state: StateRef, config: ProtocolConfigRef) throws { | ||
// change epoch to core? | ||
let newEpoch = state.value.timeslot.timeslotToEpochIndex(config: config) | ||
if epoch != newEpoch { | ||
logger.info("Updating verifier for epoch \(newEpoch)") | ||
// TODO: change to core verifier | ||
let commitment = try Bandersnatch.RingCommitment(data: state.value.safroleState.ticketsVerifier) | ||
verifier = Bandersnatch.Verifier(ctx: ringContext, commitment: commitment) | ||
epoch = newEpoch | ||
entropy = state.value.entropyPool.t3 | ||
pendingWorkPackages.removeAll() | ||
} | ||
} | ||
|
||
func add(packages: [WorkPackageAndOutput], config: ProtocolConfigRef) { | ||
for package in packages { | ||
guard validatePackage(package, config: config) else { | ||
logger.warning("Invalid work package: \(package)") | ||
continue | ||
} | ||
pendingWorkPackages.insert(package) | ||
} | ||
} | ||
|
||
private func validatePackage(_: WorkPackageAndOutput, config _: ProtocolConfigRef) -> Bool { | ||
// TODO: add validate logic | ||
true | ||
} | ||
|
||
func removeWorkPackages(workPackages: [WorkPackageAndOutput]) { | ||
pendingWorkPackages.remove { guarantee in | ||
workPackages.contains { $0.guarantee == guarantee.guarantee } | ||
} | ||
} | ||
|
||
func getWorkPackage(for _: CoreIndex) -> SortedUniqueArray<WorkPackageAndOutput> { | ||
// return pendingWorkPackages.filter { $0.guarantee.workReport.coreIndex == core } | ||
pendingWorkPackages | ||
} | ||
} | ||
|
||
public final class WorkPackagePoolService: ServiceBase, @unchecked Sendable { | ||
private var storage: WorkPackageStorage | ||
private let dataProvider: BlockchainDataProvider | ||
|
||
public init( | ||
config: ProtocolConfigRef, | ||
dataProvider: BlockchainDataProvider, | ||
eventBus: EventBus | ||
) async { | ||
self.dataProvider = dataProvider | ||
|
||
let ringContext = try! Bandersnatch.RingContext(size: UInt(config.value.totalNumberOfValidators)) | ||
storage = WorkPackageStorage(ringContext: ringContext) | ||
|
||
super.init(id: "WorkPackagePoolService", config: config, eventBus: eventBus) | ||
await storage.setLogger(logger) | ||
|
||
await subscribe(RuntimeEvents.WorkPackagesGenerated.self, id: "WorkPackagePool.WorkPackagesGenerated") { [weak self] event in | ||
try await self?.on(workPackagesGenerated: event) | ||
} | ||
|
||
await subscribe(RuntimeEvents.BlockFinalized.self, id: "WorkPackagePool.BlockFinalized") { [weak self] event in | ||
try await self?.on(blockFinalized: event) | ||
} | ||
} | ||
|
||
private func on(workPackagesGenerated event: RuntimeEvents.WorkPackagesGenerated) async throws { | ||
let state = try await dataProvider.getBestState() | ||
try await storage.update(state: state, config: config) | ||
await storage.add(packages: event.items, config: config) | ||
} | ||
|
||
private func on(blockFinalized event: RuntimeEvents.BlockFinalized) async throws { | ||
let block = try await dataProvider.getBlock(hash: event.hash) | ||
// await storage.removeWorkPackages(workPackages: block.extrinsic.reports.guarantees.) | ||
} | ||
|
||
public func update(state: StateRef, config: ProtocolConfigRef) async throws { | ||
try await storage.update(state: state, config: config) | ||
} | ||
|
||
public func addWorkPackages(packages: [WorkPackageAndOutput]) async throws { | ||
await storage.add(packages: packages, config: config) | ||
} | ||
|
||
public func getWorkPackage(for core: CoreIndex) async -> SortedUniqueArray<WorkPackageAndOutput> { | ||
await storage.getWorkPackage(for: core) | ||
} | ||
} |
60 changes: 60 additions & 0 deletions
60
Blockchain/Tests/BlockchainTests/WorkPackagePoolServiceTests.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import Foundation | ||
import Testing | ||
import TracingUtils | ||
import Utils | ||
|
||
@testable import Blockchain | ||
|
||
struct WorkPackagePoolServiceTests { | ||
let config: ProtocolConfigRef | ||
let timeProvider: MockTimeProvider | ||
let dataProvider: BlockchainDataProvider | ||
let eventBus: EventBus | ||
let keystore: KeyStore | ||
let storeMiddleware: StoreMiddleware | ||
let workPackagecPoolService: WorkPackagePoolService | ||
|
||
let ringContext: Bandersnatch.RingContext | ||
|
||
init() async throws { | ||
config = ProtocolConfigRef.dev.mutate { config in | ||
config.ticketEntriesPerValidator = 4 | ||
} | ||
timeProvider = MockTimeProvider(time: 1000) | ||
|
||
let (genesisState, genesisBlock) = try State.devGenesis(config: config) | ||
dataProvider = try await BlockchainDataProvider(InMemoryDataProvider(genesisState: genesisState, genesisBlock: genesisBlock)) | ||
|
||
storeMiddleware = StoreMiddleware() | ||
eventBus = EventBus(eventMiddleware: .serial(Middleware(storeMiddleware), .noError), handlerMiddleware: .noError) | ||
|
||
keystore = try await DevKeyStore(devKeysCount: config.value.totalNumberOfValidators) | ||
|
||
workPackagecPoolService = await WorkPackagePoolService(config: config, dataProvider: dataProvider, eventBus: eventBus) | ||
try await workPackagecPoolService.addWorkPackages(packages: []) | ||
ringContext = try Bandersnatch.RingContext(size: UInt(config.value.totalNumberOfValidators)) | ||
|
||
// setupTestLogger() | ||
} | ||
|
||
@Test | ||
func testAddPendingWorkPackage() async throws { | ||
let state = try await dataProvider.getBestState() | ||
|
||
var allWorkPackages = SortedUniqueArray<WorkPackageAndOutput>() | ||
|
||
for (i, validatorKey) in state.value.nextValidators.enumerated() { | ||
let secretKey = try await keystore.get(Bandersnatch.self, publicKey: Bandersnatch.PublicKey(data: validatorKey.bandersnatch))! | ||
// generate work package | ||
// eventBus.publish | ||
// Wait for the event to be processed | ||
await storeMiddleware.wait() | ||
} | ||
} | ||
|
||
@Test | ||
func testAddAndInvalidWorkPackage() async throws { | ||
let state = try await dataProvider.getBestState() | ||
let validatorKey = state.value.currentValidators[0] | ||
} | ||
} |