-
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.
Merge branch 'master' into dev_actor
* master: update and fix testvectors (#146) validator service tests (#145) safrole service tests (#143) fix log filtering (#142) improve logging (#141) refactor and more tests (#140) Block author tickets (#139) block author tests (#138) Fix accessor (#137) tests for DispatchQueueScheduler (#136) update readme use external libs (#133) use saturating number for gas and balance (#135) pvm accumulate functions and inovcation (#132)
- Loading branch information
Showing
111 changed files
with
9,191 additions
and
1,200 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,3 +12,7 @@ insert_final_newline=true | |
[*.swift] | ||
indent_style=space | ||
tab_width=4 | ||
|
||
[*.yml] | ||
indent_style=tab | ||
indent_size=2 |
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
143 changes: 119 additions & 24 deletions
143
Blockchain/Sources/Blockchain/BlockchainDataProvider/BlockchainDataProvider.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 |
---|---|---|
@@ -1,37 +1,132 @@ | ||
import TracingUtils | ||
import Utils | ||
|
||
public enum BlockchainDataProviderError: Error { | ||
case noData | ||
private let logger = Logger(label: "BlockchainDataProvider") | ||
|
||
private struct BlockchainStorage: Sendable { | ||
var bestHead: Data32 | ||
var bestHeadTimeslot: TimeslotIndex | ||
var finalizedHead: Data32 | ||
} | ||
|
||
public final class BlockchainDataProvider { | ||
private let storage: ThreadSafeContainer<BlockchainStorage> | ||
private let dataProvider: BlockchainDataProviderProtocol | ||
|
||
public init(_ dataProvider: BlockchainDataProviderProtocol) async throws { | ||
let heads = try await dataProvider.getHeads() | ||
var bestHead: (HeaderRef, Data32)? | ||
for head in heads { | ||
guard let header = try? await dataProvider.getHeader(hash: head) else { | ||
continue | ||
} | ||
if bestHead == nil || header.value.timeslot > bestHead!.0.value.timeslot { | ||
bestHead = (header, head) | ||
} | ||
} | ||
let finalizedHead = try await dataProvider.getFinalizedHead() | ||
|
||
storage = ThreadSafeContainer(.init( | ||
bestHead: bestHead?.1 ?? Data32(), | ||
bestHeadTimeslot: bestHead?.0.value.timeslot ?? 0, | ||
finalizedHead: finalizedHead | ||
)) | ||
|
||
self.dataProvider = dataProvider | ||
} | ||
|
||
public var bestHead: Data32 { | ||
storage.value.bestHead | ||
} | ||
|
||
public var finalizedHead: Data32 { | ||
storage.value.finalizedHead | ||
} | ||
|
||
public func blockImported(block: BlockRef, state: StateRef) async throws { | ||
try await add(block: block) | ||
try await add(state: state) | ||
try await updateHead(hash: block.hash, parent: block.header.parentHash) | ||
|
||
if block.header.timeslot > storage.value.bestHeadTimeslot { | ||
storage.write { storage in | ||
storage.bestHead = block.hash | ||
storage.bestHeadTimeslot = block.header.timeslot | ||
} | ||
} | ||
|
||
logger.debug("block imported: \(block.hash)") | ||
} | ||
} | ||
|
||
public protocol BlockchainDataProvider: Sendable { | ||
func hasBlock(hash: Data32) async throws -> Bool | ||
func hasState(hash: Data32) async throws -> Bool | ||
func isHead(hash: Data32) async throws -> Bool | ||
// expose BlockchainDataProviderProtocol | ||
extension BlockchainDataProvider { | ||
public func hasBlock(hash: Data32) async throws -> Bool { | ||
try await dataProvider.hasBlock(hash: hash) | ||
} | ||
|
||
public func hasState(hash: Data32) async throws -> Bool { | ||
try await dataProvider.hasState(hash: hash) | ||
} | ||
|
||
public func isHead(hash: Data32) async throws -> Bool { | ||
try await dataProvider.isHead(hash: hash) | ||
} | ||
|
||
public func getHeader(hash: Data32) async throws -> HeaderRef { | ||
try await dataProvider.getHeader(hash: hash) | ||
} | ||
|
||
public func getBlock(hash: Data32) async throws -> BlockRef { | ||
try await dataProvider.getBlock(hash: hash) | ||
} | ||
|
||
public func getState(hash: Data32) async throws -> StateRef { | ||
try await dataProvider.getState(hash: hash) | ||
} | ||
|
||
public func getFinalizedHead() async throws -> Data32 { | ||
try await dataProvider.getFinalizedHead() | ||
} | ||
|
||
public func getHeads() async throws -> Set<Data32> { | ||
try await dataProvider.getHeads() | ||
} | ||
|
||
public func getBlockHash(byTimeslot timeslot: TimeslotIndex) async throws -> Set<Data32> { | ||
try await dataProvider.getBlockHash(byTimeslot: timeslot) | ||
} | ||
|
||
public func add(block: BlockRef) async throws { | ||
logger.debug("adding block: \(block.hash)") | ||
|
||
try await dataProvider.add(block: block) | ||
} | ||
|
||
/// throw BlockchainDataProviderError.noData if not found | ||
func getHeader(hash: Data32) async throws -> HeaderRef | ||
public func add(state: StateRef) async throws { | ||
logger.debug("adding state: \(state.value.lastBlockHash)") | ||
|
||
/// throw BlockchainDataProviderError.noData if not found | ||
func getBlock(hash: Data32) async throws -> BlockRef | ||
try await dataProvider.add(state: state) | ||
} | ||
|
||
/// throw BlockchainDataProviderError.noData if not found | ||
func getState(hash: Data32) async throws -> StateRef | ||
public func setFinalizedHead(hash: Data32) async throws { | ||
logger.debug("setting finalized head: \(hash)") | ||
|
||
/// throw BlockchainDataProviderError.noData if not found | ||
func getFinalizedHead() async throws -> Data32 | ||
func getHeads() async throws -> Set<Data32> | ||
try await dataProvider.setFinalizedHead(hash: hash) | ||
storage.write { storage in | ||
storage.finalizedHead = hash | ||
} | ||
} | ||
|
||
/// return empty set if not found | ||
func getBlockHash(byTimeslot timeslot: TimeslotIndex) async throws -> Set<Data32> | ||
public func updateHead(hash: Data32, parent: Data32) async throws { | ||
logger.debug("updating head: \(hash) with parent: \(parent)") | ||
|
||
func add(block: BlockRef) async throws | ||
func add(state: StateRef) async throws | ||
func setFinalizedHead(hash: Data32) async throws | ||
try await dataProvider.updateHead(hash: hash, parent: parent) | ||
} | ||
|
||
/// throw BlockchainDataProviderError.noData if parent is not a head | ||
func updateHead(hash: Data32, parent: Data32) async throws | ||
public func remove(hash: Data32) async throws { | ||
logger.debug("removing block: \(hash)") | ||
|
||
/// remove header, block and state | ||
func remove(hash: Data32) async throws | ||
try await dataProvider.remove(hash: hash) | ||
} | ||
} |
Oops, something went wrong.