Skip to content

Commit 14c18db

Browse files
committed
disconnect blocks slightly less eagerly
1 parent 960008f commit 14c18db

File tree

3 files changed

+56
-26
lines changed

3 files changed

+56
-26
lines changed

xcode/DirectBindingsApp/DirectBindingsApp/app-batteries/BlockchainObserver.swift

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -206,13 +206,20 @@ class BlockchainObserver {
206206

207207
while addedBlocks.isEmpty || addedBlocks.first!.previousblockhash != self.connectedBlocks.last!.hash {
208208
// we must keep popping until it matches
209-
let trimmedLocalTip = try await self.disconnectBlock()
210-
if trimmedLocalTip.height <= currentChaintipHeight {
211-
// if the trimmed block is simply gone, we cannot retrieve the current block hash hex
212-
let reorgedBlockHash = try await self.getBlockHashHex(height: trimmedLocalTip.height)
213-
let reorgedBlock = try await self.getBlock(hash: reorgedBlockHash)
214-
addedBlocks.insert(reorgedBlock, at: 0)
209+
let trimmingCandidate = self.connectedBlocks.last!
210+
if trimmingCandidate.height > currentChaintipHeight {
211+
// we can disconnect this block without prejudice
212+
try await self.disconnectBlock()
213+
continue
215214
}
215+
let reorgedBlockHash = try await self.getBlockHashHex(height: trimmingCandidate.height)
216+
if reorgedBlockHash == trimmingCandidate.hash {
217+
// this block matches the one we already have
218+
break
219+
}
220+
let reorgedBlock = try await self.getBlock(hash: reorgedBlockHash)
221+
try await self.disconnectBlock()
222+
addedBlocks.insert(reorgedBlock, at: 0)
216223
}
217224

218225
for addedBlock in addedBlocks {
@@ -229,6 +236,8 @@ class BlockchainObserver {
229236

230237
let poppedBlock = self.connectedBlocks.popLast()!
231238

239+
print("disconnecting block \(poppedBlock.height) with hex: \(poppedBlock.hash)")
240+
232241
if self.chainListeners.count > 0 {
233242
let blockHeader = try await self.getBlockHeader(hash: poppedBlock.hash)
234243
for listener in self.chainListeners {
@@ -253,7 +262,7 @@ class BlockchainObserver {
253262
}
254263
}
255264

256-
// print("connecting block \(block.height) with hex: \(block.hash)")
265+
print("connecting block \(block.height) with hex: \(block.hash)")
257266

258267
if self.chainListeners.count > 0 {
259268
let binary = try await self.getBlockBinary(hash: block.hash)

xcode/DirectBindingsApp/DirectBindingsAppTests/test-batteries/bitcoin/BTCHashing.swift

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,27 @@ import Foundation
99
import Crypto
1010

1111
class BTCHashing {
12-
13-
public static let SHA_ZERO_HASH = [UInt8](repeating: 0, count: 32)
14-
public static let RIPEMD_ZERO_HASH = [UInt8](repeating: 0, count: 20)
15-
16-
private static func sha256(_ input: [UInt8]) -> [UInt8] {
17-
let hash = Crypto.SHA256.hash(data: input)
18-
let bytes = Array(hash)
19-
assert(bytes.count == 32)
20-
return bytes
21-
}
22-
23-
static func doubleSha256(_ input: [UInt8]) -> [UInt8] {
24-
return sha256(sha256(input))
25-
}
26-
12+
13+
public static let SHA_ZERO_HASH = [UInt8](repeating: 0, count: 32)
14+
public static let RIPEMD_ZERO_HASH = [UInt8](repeating: 0, count: 20)
15+
16+
private static func sha256(_ input: [UInt8]) -> [UInt8] {
17+
let hash = Crypto.SHA256.hash(data: input)
18+
let bytes = Array(hash)
19+
assert(bytes.count == 32)
20+
return bytes
21+
}
22+
23+
static func doubleSha256(_ input: [UInt8]) -> [UInt8] {
24+
return sha256(sha256(input))
25+
}
26+
27+
static func bytesToHexString(bytes: [UInt8]) -> String {
28+
let format = "%02hhx" // "%02hhX" (uppercase)
29+
return bytes.map {
30+
String(format: format, $0)
31+
}
32+
.joined()
33+
}
34+
2735
}

xcode/DirectBindingsApp/DirectBindingsAppTests/test-batteries/bitcoin/BitcoinTests.swift

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,20 +139,21 @@ public class BitcoinTests: XCTestCase {
139139
if self.initializationComplete {
140140
self.newBlocksDetected += 1
141141
}
142-
print("block connected at height \(height): \(block)")
142+
let blockHash = BTCHashing.bytesToHexString(bytes: BTCHashing.doubleSha256(block))
143+
// print("block connected at height \(height): \(blockHash)")
143144
}
144145

145146
func blockDisconnected(header: [UInt8]?, height: UInt32) {
146147
self.blocksLost += 1
147-
print("block disconnected from height \(height): \(header)")
148+
// print("block disconnected from height \(height): \(header)")
148149
}
149150
}
150151

151152
var listener = Listener()
152153
rpcInterface.registerListener(listener)
153154

154155
try await rpcInterface.preloadMonitor();
155-
async let monitor = try rpcInterface.monitorBlockchain()
156+
// async let monitor = try rpcInterface.monitorBlockchain()
156157
listener.initializationComplete = true
157158

158159
let testAddress = try await rpcInterface.generateAddress()
@@ -163,7 +164,8 @@ public class BitcoinTests: XCTestCase {
163164
try await rpcInterface.mineBlocks(number: 1, coinbaseDestinationAddress: outputAddress)
164165

165166
// sleep for six seconds
166-
try await Task.sleep(nanoseconds: 6_000_000_000)
167+
// try await Task.sleep(nanoseconds: 6_000_000_000)
168+
try await rpcInterface.reconcileChaintips()
167169
XCTAssertEqual(listener.newBlocksDetected, 2)
168170
XCTAssertEqual(listener.blocksLost, 0)
169171

@@ -182,13 +184,24 @@ public class BitcoinTests: XCTestCase {
182184
do {
183185
let testAddress = try await rpcInterface.generateAddress()
184186
let chaintipHash = try await rpcInterface.getChaintipHashHex()
187+
print("chaintip: \(chaintipHash)")
185188
try await rpcInterface.unmineBlock(hash: chaintipHash)
186189
try await rpcInterface.mineBlocks(number: 2, coinbaseDestinationAddress: testAddress)
187190

188191
try await rpcInterface.reconcileChaintips()
189192
XCTAssertEqual(listener.newBlocksDetected, 5)
190193
XCTAssertEqual(listener.blocksLost, 3)
191194
}
195+
196+
do {
197+
let chaintipHash = try await rpcInterface.getChaintipHashHex()
198+
print("chaintip: \(chaintipHash)")
199+
try await rpcInterface.unmineBlock(hash: chaintipHash)
200+
201+
try await rpcInterface.reconcileChaintips()
202+
XCTAssertEqual(listener.newBlocksDetected, 5)
203+
XCTAssertEqual(listener.blocksLost, 4)
204+
}
192205
}
193206

194207
}

0 commit comments

Comments
 (0)