Skip to content

Commit 52fde8a

Browse files
authored
Network handler (#182)
* async data input * NetAddr refactoring * decode and pipe messages * up message * handler safrole message * everything linked * logging fix * wip * fix message parsing * decoder fix * fix * workaround * fix * genesis block is known block * fix * fix test * update * fix * fix * allow more delays * fix * fix * fix
1 parent 637ec4d commit 52fde8a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+991
-472
lines changed

Blockchain/Sources/Blockchain/Blockchain.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,8 @@ public final class Blockchain: ServiceBase, @unchecked Sendable {
5454

5555
publish(RuntimeEvents.BlockFinalized(hash: hash))
5656
}
57+
58+
public func publish(event: some Event) {
59+
publish(event)
60+
}
5761
}

Blockchain/Sources/Blockchain/BlockchainDataProvider/BlockchainDataProvider.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,15 @@ public final class BlockchainDataProvider: Sendable {
1717
let heads = try await dataProvider.getHeads()
1818
var bestHead: (HeaderRef, Data32)?
1919
for head in heads {
20-
guard let header = try? await dataProvider.getHeader(hash: head) else {
21-
continue
22-
}
20+
let header = try await dataProvider.getHeader(hash: head)
2321
if bestHead == nil || header.value.timeslot > bestHead!.0.value.timeslot {
2422
bestHead = (header, head)
2523
}
2624
}
2725
let finalizedHead = try await dataProvider.getFinalizedHead()
2826

2927
storage = ThreadSafeContainer(.init(
30-
bestHead: bestHead?.1 ?? Data32(),
28+
bestHead: bestHead?.1 ?? dataProvider.genesisBlockHash,
3129
bestHeadTimeslot: bestHead?.0.value.timeslot ?? 0,
3230
finalizedHead: finalizedHead
3331
))
@@ -129,4 +127,8 @@ extension BlockchainDataProvider {
129127

130128
try await dataProvider.remove(hash: hash)
131129
}
130+
131+
public var genesisBlockHash: Data32 {
132+
dataProvider.genesisBlockHash
133+
}
132134
}

Blockchain/Sources/Blockchain/BlockchainDataProvider/BlockchainDataProviderProtocol.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,6 @@ public protocol BlockchainDataProviderProtocol: Sendable {
3434

3535
/// remove header, block and state
3636
func remove(hash: Data32) async throws
37+
38+
var genesisBlockHash: Data32 { get }
3739
}

Blockchain/Sources/Blockchain/BlockchainDataProvider/InMemoryDataProvider.swift

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@ public actor InMemoryDataProvider: Sendable {
77
private var blockByHash: [Data32: BlockRef] = [:]
88
private var stateByBlockHash: [Data32: StateRef] = [:]
99
private var hashByTimeslot: [TimeslotIndex: Set<Data32>] = [:]
10+
public let genesisBlockHash: Data32
1011

11-
public init(genesis: StateRef) async {
12-
heads = [Data32()]
13-
finalizedHead = Data32()
12+
public init(genesisState: StateRef, genesisBlock: BlockRef) async {
13+
genesisBlockHash = genesisBlock.hash
14+
heads = [genesisBlockHash]
15+
finalizedHead = genesisBlockHash
1416

15-
add(state: genesis)
17+
add(block: genesisBlock)
18+
add(state: genesisState)
1619
}
1720
}
1821

@@ -80,8 +83,7 @@ extension InMemoryDataProvider: BlockchainDataProviderProtocol {
8083
// parent needs to be either
8184
// - existing head
8285
// - known block
83-
// - genesis / all zeros
84-
guard heads.remove(parent) != nil || hasBlock(hash: parent) || parent == Data32() else {
86+
guard heads.remove(parent) != nil || hasBlock(hash: parent) else {
8587
throw BlockchainDataProviderError.noData(hash: parent)
8688
}
8789
heads.insert(hash)

Blockchain/Sources/Blockchain/RuntimeProtocols/RuntimeEvents.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ public enum RuntimeEvents {
2020
// New safrole ticket received from network
2121
public struct SafroleTicketsReceived: Event {
2222
public let items: [ExtrinsicTickets.TicketItem]
23+
24+
public init(items: [ExtrinsicTickets.TicketItem]) {
25+
self.items = items
26+
}
2327
}
2428

2529
// New block authored by BlockAuthor service

Blockchain/Sources/Blockchain/Types/RecentHistory.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,15 @@ public struct RecentHistory: Sendable, Equatable, Codable {
3434
extension RecentHistory: Dummy {
3535
public typealias Config = ProtocolConfigRef
3636
public static func dummy(config: Config) -> RecentHistory {
37-
RecentHistory(items: try! ConfigLimitedSizeArray(config: config))
37+
RecentHistory(items: try! ConfigLimitedSizeArray(
38+
config: config,
39+
array: [HistoryItem(
40+
headerHash: Data32(),
41+
mmr: MMR([]),
42+
stateRoot: Data32(),
43+
workReportHashes: ConfigLimitedSizeArray(config: config)
44+
)]
45+
))
3846
}
3947
}
4048

Blockchain/Sources/Blockchain/Types/State+Genesis.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Utils
22

33
extension State {
4-
public static func devGenesis(config: ProtocolConfigRef) throws -> State {
4+
public static func devGenesis(config: ProtocolConfigRef) throws -> (StateRef, BlockRef) {
55
var devKeys = [ValidatorKey]()
66

77
var state = State.dummy(config: config)
@@ -32,7 +32,15 @@ extension State {
3232
)
3333
state.safroleState.ticketsVerifier = commitment.data
3434

35-
return state
35+
let block = BlockRef(Block.dummy(config: config))
36+
try state.recentHistory.items.append(RecentHistory.HistoryItem(
37+
headerHash: block.hash,
38+
mmr: MMR([]),
39+
stateRoot: Data32(),
40+
workReportHashes: ConfigLimitedSizeArray(config: config)
41+
))
42+
43+
return (StateRef(state), block)
3644
}
3745
// TODO: add file genesis
3846
// public static func fileGenesis(config: ProtocolConfigRef) throws -> State

Blockchain/Sources/Blockchain/Types/State.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public struct State: Sendable, Equatable, Codable {
124124

125125
extension State {
126126
public var lastBlockHash: Data32 {
127-
recentHistory.items.last.map(\.headerHash) ?? Data32()
127+
recentHistory.items.last.map(\.headerHash)!
128128
}
129129
}
130130

Blockchain/Tests/BlockchainTests/BlockAuthorTests.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ struct BlockAuthorTests {
2222
config = ProtocolConfigRef.dev
2323
timeProvider = MockTimeProvider(time: 988)
2424

25-
dataProvider = try await BlockchainDataProvider(InMemoryDataProvider(genesis: StateRef(State.devGenesis(config: config))))
25+
let (genesisState, genesisBlock) = try State.devGenesis(config: config)
26+
dataProvider = try await BlockchainDataProvider(InMemoryDataProvider(genesisState: genesisState, genesisBlock: genesisBlock))
2627

2728
storeMiddleware = StoreMiddleware()
2829
eventBus = EventBus(eventMiddleware: Middleware(storeMiddleware))
@@ -45,7 +46,7 @@ struct BlockAuthorTests {
4546

4647
@Test
4748
func createNewBlockWithFallbackKey() async throws {
48-
let genesisState = try await dataProvider.getState(hash: Data32())
49+
let genesisState = try await dataProvider.getState(hash: dataProvider.genesisBlockHash)
4950

5051
let timeslot = timeProvider.getTime().timeToTimeslot(config: config)
5152

@@ -62,7 +63,7 @@ struct BlockAuthorTests {
6263

6364
@Test
6465
func createNewBlockWithTicket() async throws {
65-
let genesisState = try await dataProvider.getState(hash: Data32())
66+
let genesisState = try await dataProvider.getState(hash: dataProvider.genesisBlockHash)
6667
var state = genesisState.value
6768

6869
state.safroleState.ticketsVerifier = try Bandersnatch.RingCommitment(
@@ -108,7 +109,7 @@ struct BlockAuthorTests {
108109

109110
@Test
110111
func scheduleNewBlocks() async throws {
111-
let genesisState = try await dataProvider.getState(hash: Data32())
112+
let genesisState = try await dataProvider.getState(hash: dataProvider.genesisBlockHash)
112113

113114
await blockAuthor.on(genesis: genesisState)
114115

Blockchain/Tests/BlockchainTests/DispatchQueueSchedulerTests.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,23 @@ struct DispatchQueueSchedulerTests {
3838

3939
let diff = try #require(end.value).timeIntervalSince(now) - delay
4040
let diffAbs = abs(diff)
41-
#expect(diffAbs < 0.5)
41+
#expect(diffAbs < 1)
4242
}
4343
}
4444

4545
@Test func scheduleRepeatingTask() async throws {
46-
try await confirmation(expectedCount: 3) { confirm in
47-
let delay = 0.5
46+
try await confirmation(expectedCount: 2) { confirm in
47+
let delay = 1.5
4848
let now = Date()
4949
let executionTimes = ThreadSafeContainer<[Date]>([])
50-
let expectedExecutions = 3
50+
let expectedExecutions = 2
5151

5252
let cancel = scheduler.schedule(delay: delay, repeats: true) {
5353
executionTimes.value.append(Date())
5454
confirm()
5555
}
5656

57-
try await Task.sleep(for: .seconds(1.6))
57+
try await Task.sleep(for: .seconds(3.1))
5858

5959
_ = cancel
6060

@@ -64,7 +64,7 @@ struct DispatchQueueSchedulerTests {
6464
let expectedInterval = delay * Double(index + 1)
6565
let actualInterval = time.timeIntervalSince(now)
6666
let difference = abs(actualInterval - expectedInterval)
67-
#expect(difference < 0.5)
67+
#expect(difference < 1)
6868
}
6969
}
7070
}
@@ -83,13 +83,13 @@ struct DispatchQueueSchedulerTests {
8383

8484
@Test func cancelRepeatingTask() async throws {
8585
try await confirmation(expectedCount: 2) { confirm in
86-
let delay = 0.5
86+
let delay = 1.0
8787

8888
let cancel = scheduler.schedule(delay: delay, repeats: true) {
8989
confirm()
9090
}
9191

92-
try await Task.sleep(for: .seconds(1.2))
92+
try await Task.sleep(for: .seconds(2.2))
9393

9494
cancel.cancel()
9595

0 commit comments

Comments
 (0)