This repository has been archived by the owner on Oct 28, 2022. It is now read-only.
/
GetMerkleBlocksTask.swift
90 lines (69 loc) · 2.6 KB
/
GetMerkleBlocksTask.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import Foundation
class GetMerkleBlocksTask: PeerTask {
private let allowedIdleTime = 60.0
private var blockHashes: [BlockHash]
private var pendingMerkleBlocks = [MerkleBlock]()
init(blockHashes: [BlockHash], dateGenerator: @escaping () -> Date = Date.init) {
self.blockHashes = blockHashes
super.init(dateGenerator: dateGenerator)
}
override func start() {
let items = blockHashes.map { blockHash in
InventoryItem(type: InventoryItem.ObjectType.filteredBlockMessage.rawValue, hash: blockHash.headerHash)
}
requester?.getData(items: items)
resetTimer()
}
override func handle(merkleBlock: MerkleBlock) -> Bool {
guard let blockHash = blockHashes.first(where: { blockHash in blockHash.headerHash == merkleBlock.headerHash }) else {
return false
}
resetTimer()
merkleBlock.height = blockHash.height > 0 ? blockHash.height : nil
if merkleBlock.complete {
handle(completeMerkleBlock: merkleBlock)
} else {
pendingMerkleBlocks.append(merkleBlock)
}
return true
}
override func handle(transaction: Transaction) -> Bool {
if let index = pendingMerkleBlocks.index(where: { $0.transactionHashes.contains(transaction.dataHash) }) {
resetTimer()
let block = pendingMerkleBlocks[index]
block.transactions.append(transaction)
if block.complete {
pendingMerkleBlocks.remove(at: index)
handle(completeMerkleBlock: block)
}
return true
}
return false
}
override func checkTimeout() {
if let lastActiveTime = lastActiveTime {
if dateGenerator().timeIntervalSince1970 - lastActiveTime > allowedIdleTime {
if blockHashes.isEmpty {
delegate?.handle(completedTask: self)
} else {
delegate?.handle(failedTask: self, error: TimeoutError())
}
}
}
}
private func handle(completeMerkleBlock merkleBlock: MerkleBlock) {
if let index = blockHashes.index(where: { $0.headerHash == merkleBlock.headerHash }) {
blockHashes.remove(at: index)
}
delegate?.handle(merkleBlock: merkleBlock)
if blockHashes.isEmpty {
delegate?.handle(completedTask: self)
}
}
func equalTo(_ task: GetMerkleBlocksTask?) -> Bool {
guard let task = task else {
return false
}
return blockHashes == task.blockHashes
}
}