Merge pull request #1327 from LukasKorba/1325-Log-metrics

the logger has been extended to log the level as well
there is only partial match of levels between SDK logger levels, OSLogEntryLogLevel and OSLogType so only debug, info, error are fully matched
this is a base for the exporter on client's side
Scan & Enhance logs added
checkpoints updated
every CBP action is measured separately and collects the data, when the sync is done it dumps overview of the run to the logger
next run clears out the previous data and starts to collect fresh reports for the run
This commit is contained in:
Lukas Korba 2023-12-12 18:23:07 +01:00 committed by GitHub
commit ad6ac80ee4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
60 changed files with 630 additions and 586 deletions

View File

@ -4,6 +4,35 @@ All notable changes to this library will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this library adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
# Unreleased
## Changed
The `SDKMetrics` logs data using os_log. The public API `enableMetrics()` and `disableMetrics()` no longer exist. All metrics are automatically logged for every sync run. Extraction of the metrics is up to the client/dev - done by using `OSLogStore`.
## Added
### [#1325] Log metrics
The sync process is measured and detailed metrics are logged for every sync run. The data are logged using os_log so any client can export it. Verbose logs are under `sdkLogs_default` category, `default` level. Sync specific logs use `error` level.
## Checkpoints
Mainnet
````
Sources/ZcashLightClientKit/Resources/checkpoints/mainnet/2270000.json
...
Sources/ZcashLightClientKit/Resources/checkpoints/mainnet/2327500.json
````
Testnet
````
Sources/ZcashLightClientKit/Resources/checkpoints/testnet/2560000.json
...
Sources/ZcashLightClientKit/Resources/checkpoints/testnet/2620000.json
````
# 2.0.3 - 2023-10-20
## Fixed

View File

@ -24,16 +24,6 @@ class SyncBlocksViewController: UIViewController {
private var queue = DispatchQueue(label: "metrics.queue", qos: .default)
private var enhancingStarted = false
private var accumulatedMetrics: ProcessorMetrics = .initial
private var currentMetric: SDKMetrics.Operation?
private var currentMetricName: String {
guard let currentMetric else { return "" }
switch currentMetric {
case .downloadBlocks: return "download: "
case .scanBlocks: return "scan: "
case .enhancement: return "enhancement: "
case .fetchUTXOs: return "fetchUTXOs: "
}
}
var cancellables: [AnyCancellable] = []
let dateFormatter = DateFormatter()
@ -88,50 +78,14 @@ class SyncBlocksViewController: UIViewController {
"""
progressDataLabel.text = progressText
if let currentMetric {
let report = synchronizer.metrics.popBlock(operation: currentMetric)?.last
metricLabel.text = currentMetricName + report.debugDescription
}
case .upToDate, .stopped:
accumulateMetrics()
summaryLabel.text = "enhancement: \(accumulatedMetrics.debugDescription)"
overallSummary()
case .error:
break
}
}
func accumulateMetrics() {
guard let currentMetric else { return }
if let reports = synchronizer.metrics.popBlock(operation: currentMetric) {
for report in reports {
accumulatedMetrics = .accumulate(accumulatedMetrics, current: report)
}
}
}
func overallSummary() {
let cumulativeSummary = synchronizer.metrics.cumulativeSummary()
let downloadedBlocksReport = cumulativeSummary.downloadedBlocksReport ?? SDKMetrics.ReportSummary.zero
let scannedBlocksReport = cumulativeSummary.scannedBlocksReport ?? SDKMetrics.ReportSummary.zero
let enhancementReport = cumulativeSummary.enhancementReport ?? SDKMetrics.ReportSummary.zero
let fetchUTXOsReport = cumulativeSummary.fetchUTXOsReport ?? SDKMetrics.ReportSummary.zero
let totalSyncReport = cumulativeSummary.totalSyncReport ?? SDKMetrics.ReportSummary.zero
metricLabel.text =
"""
Summary:
downloadedBlocks: min: \(downloadedBlocksReport.minTime) max: \(downloadedBlocksReport.maxTime) avg: \(downloadedBlocksReport.avgTime)
scannedBlocks: min: \(scannedBlocksReport.minTime) max: \(scannedBlocksReport.maxTime) avg: \(scannedBlocksReport.avgTime)
enhancement: min: \(enhancementReport.minTime) max: \(enhancementReport.maxTime) avg: \(enhancementReport.avgTime)
fetchUTXOs: min: \(fetchUTXOsReport.minTime) max: \(fetchUTXOsReport.maxTime) avg: \(fetchUTXOsReport.avgTime)
totalSync: min: \(totalSyncReport.minTime) max: \(totalSyncReport.maxTime) avg: \(totalSyncReport.avgTime)
"""
}
@IBAction func startStop() {
Task { @MainActor in
await doStartStop()
@ -156,7 +110,6 @@ class SyncBlocksViewController: UIViewController {
}
}
synchronizer.metrics.enableMetrics()
try await synchronizer.start()
updateUI()
} catch {
@ -165,7 +118,6 @@ class SyncBlocksViewController: UIViewController {
}
default:
synchronizer.stop()
synchronizer.metrics.disableMetrics()
updateUI()
}
@ -253,17 +205,6 @@ struct ProcessorMetrics {
measuredCount: 0
)
static func accumulate(_ prev: ProcessorMetrics, current: SDKMetrics.BlockMetricReport) -> Self {
.init(
minHeight: prev.minHeight,
maxHeight: prev.maxHeight,
maxDuration: prev.maxDuration,
minDuration: prev.minDuration,
cumulativeDuration: prev.cumulativeDuration + current.duration,
measuredCount: prev.measuredCount + 1
)
}
static func compareDuration(
_ prev: (TimeInterval, CompactBlockRange),
_ current: (TimeInterval, CompactBlockRange),
@ -300,16 +241,6 @@ extension CompactBlockRange {
}
}
extension SDKMetrics.BlockMetricReport: CustomDebugStringConvertible {
public var debugDescription: String {
"""
BlockMetric:
batchSize: \(self.batchSize)
duration: \(self.duration)
"""
}
}
// MARK: Wipe
extension SyncBlocksViewController {

View File

@ -88,6 +88,8 @@ extension EnhanceAction: Action {
if let transactions {
await didUpdate(.foundTransactions(transactions, enhanceRange))
}
} else {
logger.sync("Action called but skipped for not enough blocks scanned from the last time.")
}
return await decideWhatToDoNext(context: context, lastScannedHeight: lastScannedHeight)

View File

@ -11,11 +11,13 @@ final class ProcessSuggestedScanRangesAction {
let rustBackend: ZcashRustBackendWelding
let service: LightWalletService
let logger: Logger
let metrics: SDKMetrics
init(container: DIContainer) {
service = container.resolve(LightWalletService.self)
rustBackend = container.resolve(ZcashRustBackendWelding.self)
logger = container.resolve(Logger.self)
metrics = container.resolve(SDKMetrics.self)
}
}
@ -23,10 +25,17 @@ extension ProcessSuggestedScanRangesAction: Action {
var removeBlocksCacheWhenFailed: Bool { false }
func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext {
logger.info("Getting the suggested scan ranges from the wallet database.")
logger.debug("Getting the suggested scan ranges from the wallet database.")
let scanRanges = try await rustBackend.suggestScanRanges()
logger.sync("CALL suggestScanRanges \(scanRanges)")
for scanRange in scanRanges {
metrics.actionDetail("range \(scanRange.priority) \(scanRange.range)", for: .processSuggestedScanRanges)
}
if let firstRange = scanRanges.first {
logger.sync("PROCESSING range \(firstRange.priority) \(firstRange.range)")
let rangeStartExclusive = firstRange.range.lowerBound - 1
let rangeEndInclusive = firstRange.range.upperBound - 1

View File

@ -50,7 +50,8 @@ extension ScanAction: Action {
let batchRange = batchRangeStart...batchRangeEnd
logger.debug("Starting scan blocks with range: \(batchRange.lowerBound)...\(batchRange.upperBound)")
logger.sync("Starting scan blocks with range \(batchRange.lowerBound)...\(batchRange.upperBound)")
do {
try await blockScanner.scanBlocks(at: batchRange) { [weak self] lastScannedHeight, increment in
let processedHeight = await context.processedHeight

View File

@ -25,7 +25,7 @@ final class UpdateChainTipAction {
func updateChainTip(_ context: ActionContext, time: TimeInterval) async throws {
let latestBlockHeight = try await service.latestBlockHeight()
logger.info("Latest block height is \(latestBlockHeight)")
logger.debug("Latest block height is \(latestBlockHeight)")
try await rustBackend.updateChainTip(height: Int32(latestBlockHeight))
await context.update(lastChainTipUpdateTime: time)
await latestBlocksDataProvider.update(latestBlockHeight)

View File

@ -28,7 +28,7 @@ extension UpdateSubtreeRootsAction: Action {
var request = GetSubtreeRootsArg()
request.shieldedProtocol = .sapling
logger.info("Attempt to get subtree roots, this may fail because lightwalletd may not support Spend before Sync.")
logger.debug("Attempt to get subtree roots, this may fail because lightwalletd may not support Spend before Sync.")
let stream = service.getSubtreeRoots(request)
var roots: [SubtreeRoot] = []
@ -41,7 +41,7 @@ extension UpdateSubtreeRootsAction: Action {
throw ZcashError.serviceSubtreeRootsStreamFailed(LightWalletServiceError.timeOut)
}
logger.info("Sapling tree has \(roots.count) subtrees")
logger.debug("Sapling tree has \(roots.count) subtrees")
do {
try await rustBackend.putSaplingSubtreeRoots(startIndex: UInt64(request.startIndex), roots: roots)

View File

@ -478,6 +478,7 @@ extension CompactBlockProcessor {
// swiftlint:disable:next cyclomatic_complexity
private func run() async {
logger.debug("Starting run")
metrics.cbpStart()
await resetContext()
while true {
@ -513,6 +514,7 @@ extension CompactBlockProcessor {
try Task.checkCancellation()
// Execute action.
metrics.actionStart(state)
context = try await action.run(with: context) { [weak self] event in
await self?.send(event: event)
if let progressChanged = await self?.compactBlockProgress.hasProgressUpdated(event), progressChanged {
@ -633,6 +635,7 @@ extension CompactBlockProcessor {
private func syncFinished() async -> Bool {
logger.debug("Sync finished")
metrics.logCBPOverviewReport(logger)
let latestBlockHeightWhenSyncing = await context.syncControlData.latestBlockHeight
let latestBlockHeight = await latestBlocksDataProvider.latestBlockHeight
// If `latestBlockHeightWhenSyncing` is 0 then it means that there was nothing to sync in last sync process.

View File

@ -196,23 +196,12 @@ actor BlockDownloaderImpl {
logger.debug("Downloading blocks in range: \(range.lowerBound)...\(range.upperBound)")
var startTime = Date()
var counter = 0
var lastDownloadedBlockHeight = -1
let pushMetrics: (BlockHeight, Date, Date) -> Void = { [metrics] _, startTime, finishTime in
metrics.pushProgressReport(
start: startTime,
end: finishTime,
batchSize: maxBlockBufferSize,
operation: .downloadBlocks
)
}
for _ in stride(from: range.lowerBound, to: range.upperBound + 1, by: 1) {
try Task.checkCancellation()
guard let block = try await stream.nextBlock() else { break }
counter += 1
lastDownloadedBlockHeight = block.height
buffer.append(block)
@ -222,17 +211,10 @@ actor BlockDownloaderImpl {
try await blocksBufferWritten(buffer)
buffer.removeAll(keepingCapacity: true)
pushMetrics(block.height, startTime, finishTime)
counter = 0
startTime = finishTime
}
}
if counter > 0 {
pushMetrics(lastDownloadedBlockHeight, startTime, Date())
}
try await storage.write(blocks: buffer)
try await blocksBufferWritten(buffer)
}

View File

@ -96,6 +96,7 @@ extension BlockEnhancerImpl: BlockEnhancer {
guard !transactions.isEmpty else {
logger.debug("no transactions detected on range: \(range.lowerBound)...\(range.upperBound)")
logger.sync("No transactions detected on range: \(range.lowerBound)...\(range.upperBound)")
return nil
}
@ -134,12 +135,10 @@ extension BlockEnhancerImpl: BlockEnhancer {
}
}
metrics.pushProgressReport(
start: startTime,
end: Date(),
batchSize: range.count,
operation: .enhancement
)
let endTime = Date()
let logMsg = "Enhanced \(transactions.count) transaction(s) in \(endTime.timeIntervalSince1970 - startTime.timeIntervalSince1970) for range \(range.lowerBound)...\(range.upperBound)"
logger.sync(logMsg)
metrics.actionDetail(logMsg, for: .enhance)
} catch {
logger.error("error enhancing transactions! \(error)")
throw error

View File

@ -85,13 +85,6 @@ extension UTXOFetcherImpl: UTXOFetcher {
}
}
metrics.pushProgressReport(
start: startTime,
end: Date(),
batchSize: 1,
operation: .fetchUTXOs
)
let result = (inserted: refreshed, skipped: skipped)
if Task.isCancelled {

View File

@ -69,16 +69,10 @@ extension BlockScannerImpl: BlockScanner {
if scannedNewBlocks {
try await didScan(lastScannedHeight, batchSize)
metrics.pushProgressReport(
start: scanStartTime,
end: scanFinishTime,
batchSize: Int(batchSize),
operation: .scanBlocks
)
let heightCount = lastScannedHeight - previousScannedHeight
let seconds = scanFinishTime.timeIntervalSinceReferenceDate - scanStartTime.timeIntervalSinceReferenceDate
logger.debug("Scanned \(heightCount) blocks in \(seconds) seconds")
logger.sync("Scanned \(heightCount) blocks in \(seconds) seconds")
}
await Task.yield()

View File

@ -7,252 +7,131 @@
import Foundation
/// SDK's tool for the measurement of metrics.
/// The barebone API of the `SDKMetrics` is all about turning it on/off, pushing new reports in and popping RAW data out.
/// The processing of data is either left to the user of `SDKMetrics` or anybody can take an advantage of extension APIs
/// providing useful structs and reports.
///
/// Usage:
/// The `SDKMetrics` API has been designed so it has the lowest impact possible on the SDK itself.
/// Reporting of the metrics is already in place but ignored until `enableMetrics()` is called. Once turned on, the data is collected
/// and cumulated to the in memory structural storage until `disableMetrics()` is called.
/// `disableMetrics()` also clears out the in memory storage.
///
/// To collect data and process it there are 2 ways:
///
/// 1.
/// Get RAW data by calling either `popBlock` or `popAllBlockReports`. The post-processing of data is then delegated to the caller.
///
/// 2.
/// Get cumulated data by using an extension APIs. For the summarized collection, call `cumulativeSummary()`.
/// Sometimes, typically when you want to run several iterations, the `cumulateReportsAndStartNewSet()` automatically computes
/// cumulativeSummary, stores it and starts to collect a new set. All summaries can be either processed by a caller,
/// accessing the collection `cumulativeSummaries` directly or values can be merged into one final summary by calling `summarizedCumulativeReports()`.
///
/// We encourage you to check`SDKMetricsTests` and other tests in the Test/PerformanceTests/ folder.
public class SDKMetrics {
public struct BlockMetricReport: Equatable {
public let batchSize: Int
public let startTime: TimeInterval
public let endTime: TimeInterval
public var duration: TimeInterval { endTime - startTime }
}
public enum Operation {
case downloadBlocks
case scanBlocks
case enhancement
case fetchUTXOs
}
public struct SyncReport: Equatable {
public let startTime: TimeInterval
public let endTime: TimeInterval
public var duration: TimeInterval { endTime - startTime }
}
public var cumulativeSummaries: [CumulativeSummary] = []
public var syncReport: SyncReport?
var isEnabled = false
var reports: [Operation: [BlockMetricReport]] = [:]
protocol SDKMetrics {
func cbpStart()
func actionStart(_ action: CBPState)
func actionDetail(_ detail: String, `for` action: CBPState)
func actionStop()
func logCBPOverviewReport(_ logger: Logger)
}
final class SDKMetricsImpl: SDKMetrics {
public struct CBPStateMetricReport: Equatable {
static let zero = Self(runs: 0, startTime: 0, cummulativeTime: 0, maxTime: 0, avgTime: 0)
var runs: Int
var startTime: TimeInterval
var cummulativeTime: TimeInterval
var minTime: TimeInterval = .infinity
var maxTime: TimeInterval
var avgTime: TimeInterval
var details: [String] = []
}
// Compact Block Processor Metrics
var syncs = 0
var cbpStartTime: TimeInterval = 0
var cbpOverview: [CBPState: CBPStateMetricReport] = [:]
var lastActionInRun: CBPState?
public init() { }
/// `SDKMetrics` is disabled by default. Any pushed data are simply ignored until `enableMetrics()` is called.
public func enableMetrics() {
isEnabled = true
func cbpStart() {
syncs += 1
cbpStartTime = Date().timeIntervalSince1970
// reset of previous values
cbpOverview.removeAll()
}
func actionStart(_ action: CBPState) {
actionStop()
lastActionInRun = action
var report = CBPStateMetricReport.zero
if let reportFound = cbpOverview[action] {
report = reportFound
}
report.runs += 1
report.startTime = Date().timeIntervalSince1970
cbpOverview[action] = report
}
public func disableMetrics() {
isEnabled = false
clearAll()
}
/// `SDKMetrics` focuses deeply on sync process and metrics related to it. By default there are reports around
/// block operations like download, validate, etc. This method pushes data on a stack for the specific operation.
func pushProgressReport(
start: Date,
end: Date,
batchSize: Int,
operation: Operation
) {
guard isEnabled else { return }
let blockMetricReport = BlockMetricReport(
batchSize: batchSize,
startTime: start.timeIntervalSinceReferenceDate,
endTime: end.timeIntervalSinceReferenceDate
)
guard reports[operation] != nil else {
reports[operation] = [blockMetricReport]
func actionDetail(_ detail: String, `for` action: CBPState) {
guard var report = cbpOverview[action] else {
return
}
reports[operation]?.append(blockMetricReport)
report.details.append(detail)
cbpOverview[action] = report
}
/// Block synchronisation consists of operations but the whole process is measured also, represented by
/// different struct `SyncReport`, missing specifics for the operations like batch size, etc.
/// Used for the total syncing time report in the first place.
func pushSyncReport(
start: Date,
end: Date
) {
guard isEnabled else { return }
let syncReport = SyncReport(
startTime: start.timeIntervalSinceReferenceDate,
endTime: end.timeIntervalSinceReferenceDate
)
self.syncReport = syncReport
}
/// A method allowing users of the `SDKMetrics` to pop the RAW data out of the system. For the specific `operation`
/// with option to either leave data in the storage or flushing it out and start the next batch of collecting new ones.
public func popBlock(operation: Operation, flush: Bool = false) -> [BlockMetricReport]? {
defer {
if flush { clearReport(operation) }
func actionStop() {
guard let lastActionInRun else {
return
}
return reports[operation]
}
/// A method allowing users of the `SDKMetrics` to pop the RAW data out of the system. This time for all measured operations
/// with option to either leave data in the storage or flushing it out and start the next batch of collecting new ones.
public func popAllBlockReports(flush: Bool = false) -> [Operation: [BlockMetricReport]] {
defer {
if flush { clearAllBlockReports() }
guard var report = cbpOverview[lastActionInRun] else {
return
}
let endTime = Date().timeIntervalSince1970
let runTime = endTime - report.startTime
report.cummulativeTime += runTime
if runTime < report.minTime {
report.minTime = runTime
}
if runTime > report.maxTime {
report.maxTime = runTime
}
return reports
}
func clearReport(_ operation: Operation) {
reports.removeValue(forKey: operation)
}
func clearAllBlockReports() {
reports.removeAll()
cumulativeSummaries.removeAll()
}
func clearAll() {
clearAllBlockReports()
syncReport = nil
}
}
/// This extension provides an API that provides the summary and accumulated reports.
/// The RAW data can pulled out and be processed without this extension but we
/// wanted to provide a way how to get essential summaries right from the SDK.
extension SDKMetrics {
public struct CumulativeSummary: Equatable {
public let downloadedBlocksReport: ReportSummary?
public let scannedBlocksReport: ReportSummary?
public let enhancementReport: ReportSummary?
public let fetchUTXOsReport: ReportSummary?
public let totalSyncReport: ReportSummary?
}
public struct ReportSummary: Equatable {
public let minTime: TimeInterval
public let maxTime: TimeInterval
public let avgTime: TimeInterval
public static let zero = Self(minTime: 0, maxTime: 0, avgTime: 0)
}
/// This method takes all the RAW data and computes a `CumulativeSummary` for every `operation`
/// independently. A `ReportSummary` is the result per `operation`, providing min, max and avg times.
public func cumulativeSummary() -> CumulativeSummary {
let downloadReport = summaryFor(reports: reports[.downloadBlocks])
let scanReport = summaryFor(reports: reports[.scanBlocks])
let enhancementReport = summaryFor(reports: reports[.enhancement])
let fetchUTXOsReport = summaryFor(reports: reports[.fetchUTXOs])
var totalSyncReport: ReportSummary?
if let duration = syncReport?.duration {
totalSyncReport = ReportSummary(minTime: duration, maxTime: duration, avgTime: duration)
if report.runs > 0 {
report.avgTime = report.cummulativeTime / Double(report.runs)
}
return CumulativeSummary(
downloadedBlocksReport: downloadReport,
scannedBlocksReport: scanReport,
enhancementReport: enhancementReport,
fetchUTXOsReport: fetchUTXOsReport,
totalSyncReport: totalSyncReport
)
}
/// This method computes the `CumulativeSummary` for the RAW data already in the system, stores it
/// and leave room for collecting new RAW data. Typical use case is when some code is expected to run several times
/// and every run is expected to be a new data collection.
/// Usage of this API is then typically followed by calling `summarizedCumulativeReports()` which merges all stored
/// cumulative reports into one final report.
public func cumulateReportsAndStartNewSet() {
cumulativeSummaries.append(cumulativeSummary())
reports.removeAll()
syncReport = nil
}
/// This method takes all `CumulativeSummary` reports and merge them all together, providing
/// final `CumulativeSummary` per `operation`, ensuring right min and max values are in the place
/// as well as computes final avg time per `operation`.
public func summarizedCumulativeReports() -> CumulativeSummary? {
var finalSummary: CumulativeSummary?
cumulativeSummaries.forEach { summary in
finalSummary = CumulativeSummary(
downloadedBlocksReport: accumulate(left: finalSummary?.downloadedBlocksReport, right: summary.downloadedBlocksReport),
scannedBlocksReport: accumulate(left: finalSummary?.scannedBlocksReport, right: summary.scannedBlocksReport),
enhancementReport: accumulate(left: finalSummary?.enhancementReport, right: summary.enhancementReport),
fetchUTXOsReport: accumulate(left: finalSummary?.fetchUTXOsReport, right: summary.fetchUTXOsReport),
totalSyncReport: accumulate(left: finalSummary?.totalSyncReport, right: summary.totalSyncReport)
)
}
return finalSummary
cbpOverview[lastActionInRun] = report
}
/// Internal helper method that accumulates `ReportSummary` times.
func accumulate(left: ReportSummary?, right: ReportSummary?) -> ReportSummary? {
guard let left, let right else {
if let right {
return ReportSummary(
minTime: right.minTime,
maxTime: right.maxTime,
avgTime: right.avgTime
)
// swiftlint:disable string_concatenation
func logCBPOverviewReport(_ logger: Logger) {
actionStop()
var resText = "SYNC (\(syncs)) REPORT\n"
resText += "finished in: \(Date().timeIntervalSince1970 - cbpStartTime)\n\n"
for action in cbpOverview {
let report = action.value
resText += """
action: \(action.key)
runs: \(report.runs)
cummulativeTime: \(report.cummulativeTime)
minTime: \(report.minTime)
maxTime: \(report.maxTime)
avgTime: \(report.avgTime)
"""
if !report.details.isEmpty {
resText += "\ndetails:\n"
for detail in report.details {
resText += "\t\(detail)\n"
}
}
return nil
resText += "\n\n"
}
return ReportSummary(
minTime: min(left.minTime, right.minTime),
maxTime: max(left.maxTime, right.maxTime),
avgTime: (left.avgTime + right.avgTime) * 0.5
)
}
/// Internal helper method that computes min, max and avg times for the `BlockMetricReport` collection.
func summaryFor(reports: [BlockMetricReport]?) -> ReportSummary? {
guard let reports, !reports.isEmpty else { return nil }
var min: TimeInterval = 99999999.0
var max: TimeInterval = 0.0
var avg: TimeInterval = 0.0
reports.forEach { report in
let duration = report.duration
avg += duration
if duration > max { max = duration }
if duration < min { min = duration }
}
// reports.count is guarded to never be a zero
avg /= TimeInterval(reports.count)
return ReportSummary(minTime: min, maxTime: max, avgTime: avg)
logger.sync(resText)
}
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2270000",
"hash": "0000000000c4314de2a15c56249dfe277ff51e1d6a179a5ae3c01e709d80f07d",
"time": 1697958631,
"saplingTree": "014c6ab9468d295866f051ee781d91aca0e7542e143680c89f8cb5c9e72a9838720158af6691c73faa4c3afd7efcbbffa362384f1f3f9eef160de6a9c8ac8bd81d391a0000012731c443460effc12a99483ac5d5c9540cf6edc9932bdee163f331df76218c5b000001adfa0efcad0c23520a4e2a6865ecf1fbdae3851d2019340a1caa84c854fa3e0f01229b6ab4de80a3843c039bd50b9687460b5c04c29b4c5d9baef2742bdb816a0c013b67cbdd09009cd311022460c802b77cce63c5e661b4dcd5543ed98cbdccb8660113ea747404c27dbf347dc87f56796d7a7654455cc9f81db36a1da7b2b063661401d9025bc766e91070f70716c15fb3a8f85525c5b082a0bc9ec77cd667e7b07d38015cc47e57f3c7a46b570ec6f664d5e39e67c73bdaee1e006dc32f9d6fbbf2eb2c01090b969f4a6c25a0bcf22b976c7c7a1145320eb0620ff4da3ac1cc6627b2720301f71ed6dee66571dddf2e1cbc239b50cbd1867ac519ccbc491b3a1284f05b860401ca2ef102fb828472bb323b8e334a3f7dd188b4bd043df1f9e5b525b654bf27200001ffdd1a0628296bf274daa5ea13fb57818d678957d49f91ccd69efae0bac249340182ac7ebe2f7e9d8084a38aa8be56b1bd86292babf05f98882a6959cf9d318c110001d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "01b2c39d0a9083b615af23168684321b83b0ffaa65a242f168ffca783520910a34001f01c76b3e598049fe3a88fafc213451d6c6bc4758a52c5620300b9482ebf67caa3201034d2240ab404d03f6231989d1aec297566daafe798a3ce71e61cb6de526aa1200019db5c0c598c9db3e4bf851e29ce058878840d7dad804713a251cf8d8e9d8c50601d4962b21d6711214c867706a8e50b07616e92ee8c867ab3fae5912b86a71c7380001d078599b76eba7ce4b38db395b4ca6c289afb1e139ba0ca4281d33fdc5c23d2701acbca7b28d294abc7cec56fe1ad4e653578e188012d70361700803254f0a8934000001ed0b8645ba722e2aeef2cfff7374a7dba95d92a6438276ddca7c76f6f2a3ae1600012ffae608e1b4d4de4f5ac38068b613d9761ba34d95430e5ec8d058848cc9c0250001dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2272500",
"hash": "000000000101df774d2a45008af97d1cbc62117ce8a2635e8be8432de50c18cd",
"time": 1698147530,
"saplingTree": "018f896dbdedae2e50c0cce982c8204141730b196f745175a82830ca9a47fedf48017a8a234509e3c64c49b5229d8b6589f6389832dfd7ee95696008442827f5116f1a01f16748b8fa01f368a968b5d6f45aa499540bb566314328d4337ea9bad0d69719000001c698abd29732e8d765df5aa15db8652a347aa6dd9e1592f200d3e5bfe66ad26200000129cee479373bc283fdf83c02b3a019178bfa1f8a34a868092a75022cdf43db3a01095b14c824594a5311d7f29406e99dea20cf53b90a27a12df4bdf8b1281fb5080001b099b710de3efd37a880d4372c44c7388d14fdf4a34ca2d97a6ac1acf33d6817000195690f105db42ae533ed2406bd24155128007fb2fbc80676b4e59a05d7aec52100000143d0958ed592bc13ecf47b2664d9087554b43c69f01d23247d1323006a4d750601ffdd1a0628296bf274daa5ea13fb57818d678957d49f91ccd69efae0bac249340182ac7ebe2f7e9d8084a38aa8be56b1bd86292babf05f98882a6959cf9d318c110001d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "01cdcfa81709e09b8ddbbef40c2953d9222f79a7fd490bb0270fb5182ca3f7ba01001f0199ce56729f4c6e25622d23e77c8f8edbb89e1e65bc042d7b08e0b720d2e3fc1800011eb748c95af57b028618c39fc1ef4d2491578c1a91040224fedc95ec3f6a8f2d018422698954742926542754dc904a3e5b8cb7a1b9411df69fa549496be51e4a1700000000000189a2e7029abe265a7acf4227791eae37c48bb19e21cb2f95d9a87e8914f56e3901ed0b8645ba722e2aeef2cfff7374a7dba95d92a6438276ddca7c76f6f2a3ae1600012ffae608e1b4d4de4f5ac38068b613d9761ba34d95430e5ec8d058848cc9c0250001dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2275000",
"hash": "0000000001a1d06d7297d87f0f7e0e49383b0f10dbe3e22e7a66ab1ba9cebf66",
"time": 1698335616,
"saplingTree": "015d9ff1fd129cb09cfb3322c4eb284bbb44a30b4027edf52ca5500a18da76382e01251130dcfbc8dbca704428db2fc252d1b63bfe9d8fa9a3a3ff5ad18fec0c266e1a000170b1341313ab46627dce9b636268c1aa457eea90b5ebcf7f0f0a3b8224d32b630000000001435c8a879c5799d05b4467d5de64193196e1793295cb85464e04aec99ef4b77101e508516f5c55360490aabf7dc59642c75dfa08a6a6532e7deb59a427b792360101b09f2068c37a8e89d92735a8672559c77aa4cb5d15d5a84f7c40d30b248dc15c00013bae7327f0e7b60dd2c09cd29e34da76f79da4f1b7593f611e2cc6cb45dcfc090001602f25e80946cd987a4d570593152f72bfe10b054be88436e82bfd9cbbf0cf06000143d0958ed592bc13ecf47b2664d9087554b43c69f01d23247d1323006a4d750601ffdd1a0628296bf274daa5ea13fb57818d678957d49f91ccd69efae0bac249340182ac7ebe2f7e9d8084a38aa8be56b1bd86292babf05f98882a6959cf9d318c110001d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "010d092947e75a832b868d3dc43cd3d6556e5f3647da76165ac9506fb004930830001f015cc156677f54dc339ddd846e6f94232771f460e8e73e90abec57bd5c7f7cfe34000001f536aced4e2e37cf02ed4b6aa6ac8fb7fa6610f0370020e6d1ac10995d2f8928000001cb1efaf88c34aabae5756dfaaf3d03856d70889efbab49b38496c10987a40a3e0001c13878d4402edfd680750b5cf58e79190819928dc7a553e75d8f14763894ca3d0189a2e7029abe265a7acf4227791eae37c48bb19e21cb2f95d9a87e8914f56e3901ed0b8645ba722e2aeef2cfff7374a7dba95d92a6438276ddca7c76f6f2a3ae1600012ffae608e1b4d4de4f5ac38068b613d9761ba34d95430e5ec8d058848cc9c0250001dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2277500",
"hash": "0000000000a4dd1adf30d25e02984056504ff96d76fae62f7085458695a411a2",
"time": 1698524343,
"saplingTree": "01fc5d5e38cffb57e9dbb61e285b960a1e63f005dc8e7e709fc22014c36088ef3f001a0001de0ed3aa986e08d4e303387490dce97cb7c99e54e02d16256446718935ccb62b000001da1e0dd9a0db7d398862c6cc76b3743b7c33b5a032f3e96644102508c20e473801ad5fef9438eae8dd617eabaa220a1865d6284ae46488b667abe397753c4cd2200000000000000001fb99b6df98e30fbb8d0b50b4d4af9777346c943d2c2718a5df0c531667e6ba530143d0958ed592bc13ecf47b2664d9087554b43c69f01d23247d1323006a4d750601ffdd1a0628296bf274daa5ea13fb57818d678957d49f91ccd69efae0bac249340182ac7ebe2f7e9d8084a38aa8be56b1bd86292babf05f98882a6959cf9d318c110001d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "012d9d285babba1461ab28ef71eb6fc228124379fcc5eeece62a00007c676396150122ef493fe98e3fd2afd981a1c596e1b02837036ef50703860847eb1854bed8351f0000015e25ce67f68c5a9f167148a80d46d897c6ccc05dff8ad80f9f7eb429ff0a3d2b01e2e14918c25cd079460a5088418de57cf996e0b7cee619d1c639ee9ef41c671301cdfa1c1b946fc22d67e3a1a9b0485597625481268119937f4c5816d8eb8fe2390187685cddc66dce2bd8e05e6bb26cbb4dbc57e6d06055012ee17af7956caf132b01ba45e35cc7c794e859b2723b5467389966ed6d2b50d6e487d961d10f8786f41300000000014f4953491ea4a29604f7f1935e3fde4d40851918267a9340aa73d3375b86ed3a012ffae608e1b4d4de4f5ac38068b613d9761ba34d95430e5ec8d058848cc9c0250001dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2280000",
"hash": "000000000140ca5ed3a137186ce43f05f25b260c4655851dfa7bc43ea8a5c72b",
"time": 1698712464,
"saplingTree": "011e05ce06ba3378e547a8a42b98ebb4f6a2c8e73f05361f1b42be375710ce8237001a0001f53aa634664cd779fd9756c12663f4d0629788dbb16554b3a841845c6ac428180001831cf884b406defb117444655fac7c18afd9730a0b73226309e3e541b4e91908014de6d8ce3075eaa6614391761b0aa7c82000ac7c4824718e906165cb836a0b2e016a754768870d1b80d47f335ae06e841586edc9c1d24a0ffcbd27ac0d682f1a3e01978df5cf6aa9b70cd809ea1c47431dc83ff970819d7975297132870a25044105010f081ad9f6048010f58038c0d072a8a0c58955c6b88b561976d47724eaed313a00018e6514477b4ffa248d092e60b08f25ac7bd83b376f17330062ee12e13d29f56c0001730e5ddc4703c047da1756a95be56bd2e4fd3b8985af48e6b47c5ec98b084c090001fb99b6df98e30fbb8d0b50b4d4af9777346c943d2c2718a5df0c531667e6ba530143d0958ed592bc13ecf47b2664d9087554b43c69f01d23247d1323006a4d750601ffdd1a0628296bf274daa5ea13fb57818d678957d49f91ccd69efae0bac249340182ac7ebe2f7e9d8084a38aa8be56b1bd86292babf05f98882a6959cf9d318c110001d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "0148572bb05a2e3580007a9f0f5472130ab275dc5885d0d5170eee00a46dcff83b001f0001096ffd805bb818893d4b2ebdfed87eb1e54a95f66d9af7057c1ccc9bd27ac6060001c641afdad2ab3db87674559f9e3ae5ddbf4751cbea1a89c4c76bbda291635937010eaa5be52e7d91a8a4965a41a3dfe3bb61195d5d529bc354dcc13c3ccd4ba608000001b34d2602cfdab5c035a7ad3b66943a9ed55500fecf62dee06e305893bd7c671a0181fe0236f1875abc9be3db2a15d90d07b8f47ddd820f2c184cecc4c600eab12d0000014f4953491ea4a29604f7f1935e3fde4d40851918267a9340aa73d3375b86ed3a012ffae608e1b4d4de4f5ac38068b613d9761ba34d95430e5ec8d058848cc9c0250001dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2282500",
"hash": "0000000000dea1da65f7c7fb38ddb0b11a6d29c95e1f304cbd04451201282939",
"time": 1698900669,
"saplingTree": "01756a28016aca946bedcb35376db79860fb150163df7246e0127af71ff0a0a020001a01cc10c94b8d4cd542d974a8e7dde7e3d7c41e4b94c9a6eb3c43ee936f562d521b01142843d118ac16ca4e6426e9e874c4a922001e86e7a3dc700e532a8af6b1496500013e7baa0b1252773c12796f433bfd2ef548f272a25b3a454f8a76ef7a0af5ed55016300c5c70e2afe30c30a40e762a6f323798bddf2f5986516649b965ea828ac5500000000015445ffff80d5f45be983d38f5e803facecbbc23fb1199dfad3b11cf3c51926180174488dfd0763a57c02b40c1b9b26fb289357b41cec6191ede85b385ba5288e0800019850bfbfe34e5e816c2f73f9fef1a74c6088e93930517a29a4a0e6000d1b510401fb99b6df98e30fbb8d0b50b4d4af9777346c943d2c2718a5df0c531667e6ba530143d0958ed592bc13ecf47b2664d9087554b43c69f01d23247d1323006a4d750601ffdd1a0628296bf274daa5ea13fb57818d678957d49f91ccd69efae0bac249340182ac7ebe2f7e9d8084a38aa8be56b1bd86292babf05f98882a6959cf9d318c110001d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "01030ed7b60fa7f2cd6fc773e57d1ead213ad15134000d6941a39e766bade6232101a9d4c282339305676f8189c920263fa6e42b82a707e93d6496cf9dec25189f1b1f01a71adf481108cbe2d25c907da3a069d0562a24fa83d058e163fa0b670371953c000001f264831f79e88c3ba899764c723a3f9b929b655b7ef046b78a74019ca14c3c34000174b81a801540db38a2ccc7c7a7b2133fe6d6a1a0ea4dad665319ff21c629940d01126f17a1966531b97f22559213db4af212a340a5a5d77f6b2a2ee020fa89632e014af93d6dd233c0d0e8a6d98b73170f15967d4d3f6e842da9ab822c125ac5c5380001c35b0d064585c89bc92632c1698020ab8182daede7217bd50f223124fd717c0100014f4953491ea4a29604f7f1935e3fde4d40851918267a9340aa73d3375b86ed3a012ffae608e1b4d4de4f5ac38068b613d9761ba34d95430e5ec8d058848cc9c0250001dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2285000",
"hash": "0000000001b67658580edf118870e75c4ab5577059685ddcb24d9c92b443382f",
"time": 1699089648,
"saplingTree": "012d44cc8e1d16e6852fc14639e98736668a7b5d028ab3159c5982940c9299e24f01868f46f3ed9f21ce98d27957a7f33b62c5bc4ebd3451013252c99401097f566e1a01bcc45bef6435eeefc68d237aa2acbe2e95e15997ea1e636fd9210f72ab10ff6d01c56bd1007ac121c76c8d858a74c6f8105e5836faa57fe9341414334ab559c9720186f5b62c921c7053bfde3fff715d8103e1d0bd2a2ddc13ec40dd47c2555df915011489c314b2b11f0e344836151e03a95578552c74f376da2a84022dad6d205d0801c282c5b40f298c8df4f35fb4a256e658b235ddbb0ff5961fc8bf9ded3c5e665f01b70423dee0ff8ef547760df373ae704fd6b659bc23f787bbbdaa3108a6a8661f0001b5d3445be440b9b5e51ca2a79ba867948f5fb528f1647470dad9b2f8edfa702100000000000000000001d1b36bbba8e6e1be8f09baf2b829bafc4ccd89ad25fb730d2b8a995b60fc3a6701d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "01198d97b218abf3a512b1ea5ea22615af4272955033f20043ebf25fb263803414001f0133af1c23ceeb554627b4647ce8ec33986c39e728071ae4940e1b9f833dfb4e000001e80bc8a0c15b7ae11eb61cef6605c3b4c4a550ccd215b49108a03cb8a566c81e00018a886a9ca0854d493406dc6b48d3ad27e67b27473c5ade974309778862d68f1d01ddc8cd44d9f82d7781860ce7d73b1f843f5ec912a129aa68f6207ac5b0195e0700000000016c3d712fa25ffe81b7565bf0970dd2cef0b14df1ba1719ba1589349a10610b2b014f4953491ea4a29604f7f1935e3fde4d40851918267a9340aa73d3375b86ed3a012ffae608e1b4d4de4f5ac38068b613d9761ba34d95430e5ec8d058848cc9c0250001dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2287500",
"hash": "0000000000757aa79361a32650287f111bc1977c1cf671ce0a139f870e014b0c",
"time": 1699277300,
"saplingTree": "0149db9481cf9d90582a6d635957c125163626f0c7dedb00f38d460f2f56a29d3e001a01099b44d4f58af7097a0ade2a0e5c0a575b43bdbc740214b8f23e5d48e987db540193bac04c4aad7b9aa65a15791526e7ff12b0a747db79a1062145f6c34554556b0166a1e7b8e5e92f271074957a8671311de5aa262151b60c78df13b4aa57f1a00e01b637e75c296556d34d65e3d960ec98fadfb1f788071a3d59b2056fe629490337015399c88cb4e5242bb76014c7073f65916318fa6aec9f70007be0cc1f322b2e36000103e597a1d37b8bc6569618464753213c48f71801350fa8fe0b5b38f73b83dc280001d2aee58f847d62b7daab3ad6e7b8036bff83cc6cf7761fe257aaea1c98f5fc13011622bf09c438466da1f14f2e94866e486566fd36edc459779d99102426c00e390001e6bf5bd7ec2b3e8c5bd194500babe084eafde1c0d35a2d3cb640dea7d15ed85e000000000001d1b36bbba8e6e1be8f09baf2b829bafc4ccd89ad25fb730d2b8a995b60fc3a6701d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "013f4e84041192636736575b21268768777a4f3b6f415076dc6f47ebc1bb80643001d84be4fb5cfa5cf4a05ebd02091a254f8c00bc7bc8ba7afdb37b1c392f6f04051f01edd7857eb012cbb1958755fd52919cdcb3787dea8c2a9dd8c660b59f93a8d20701689a937f5e4fa984c43c60ee713dec372ff3eaa1b015249c5382176441b7302b0000014b46453a22fa268cc103f435c9b8af9391312fde360c860151236f630c3dc322018a4eaa3a1fc86c7d4c93132b463c9d3debce2bc9f176eecfa831c6fc5002a827000001c640fc3d8029cb55871f853502c7ac1137cdcf9f9b31746f05f24b5d494d863400016c3d712fa25ffe81b7565bf0970dd2cef0b14df1ba1719ba1589349a10610b2b014f4953491ea4a29604f7f1935e3fde4d40851918267a9340aa73d3375b86ed3a012ffae608e1b4d4de4f5ac38068b613d9761ba34d95430e5ec8d058848cc9c0250001dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2290000",
"hash": "00000000008bb1dde2ae2424eac14ff313cbe98184ff0ce14906a1b598a2e326",
"time": 1699465348,
"saplingTree": "014dd08e5128109754bc3f9cc5bd5792135851ef1ba944f7f11093cd829ee11f6d01847eec9edfe1b553aaa58e4cccd32af9d7b100bd4bd5877a57410614263c98271a01e973c5e44e96837efe3a1445a3090dd8f068235618de1b3989efaa2da638294400000128457ea2dcd149d9bc6396f889f1c87c330a8137d5226d3d4625235882e66654019fc0c24fc03f6111ad1f4bda55890cdde7ea9051693ed025f7b8caa4375d0532000199d133fef0424c9a384a5821d16802aa160eaac03e2de67f8a29a31828b8812301a715b831a08242e508a5c4da866634910c2315a5ed77f5219401297850247670018629eaa956de2399bb1234d32888cba94d3a8ad8abac3a95724ab09d1657a8320001f769333859670184606e0fb23864a2d55507d6f474d0a3bff3510cfb7b8ba7530001251f21b30ba98b69091a40adac6bda1159f58994df1b1e116d277d6ace9b69220000000001d1b36bbba8e6e1be8f09baf2b829bafc4ccd89ad25fb730d2b8a995b60fc3a6701d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "0180a6c82f929467c2d84b698b226e7907054d80d0ef87c72b3f7e752555ef8d060113474a6c7bbfdd7b8b80dfe4e1ced724f3afd8022c507bc9fbbb37ba96b4a0001f0000000000010e67ad6365d0b475918235e8cda31a103f821ccad22dcba4ccef93e3c1c0181501f1130e13dd8ca300a64a4c732a4050230278c621a24eb126e5fd13c9ee8e110e000001e8a2e43418c17ecfd14ac24c026ee73f625633b20f723a46df9aad874efef406016c3d712fa25ffe81b7565bf0970dd2cef0b14df1ba1719ba1589349a10610b2b014f4953491ea4a29604f7f1935e3fde4d40851918267a9340aa73d3375b86ed3a012ffae608e1b4d4de4f5ac38068b613d9761ba34d95430e5ec8d058848cc9c0250001dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2292500",
"hash": "00000000014801ec195f78ec263f748937e51d9b438ff02b7b1ee07f2e710a0b",
"time": 1699654836,
"saplingTree": "01875808c0ce4642dd091aade8d5db6b4927c587efa5ebd0b7457052aa17493a2c001a010e20e6eeb9c9cc2c4b98957158bfce57a8a631c251bd3ab0fd7fd6c13f23482a000001841e41793f8b1b27fd5ca1dea68e6c22b95631405969939c60bd03b258a84f6f0113f375f185305df58801bfcd46d0eb5a6e9ea1c120c07146382960bfb8c053360101924d8f42a1b23bd3e869dd4eac63da1143abdbad6b5c3baec1e3a0d98c786701498d637205c7bbd6b7c88f2c32a89f9c74f32eef493ee616bc18d06ea440dd46018c108fed4b016b60b201ec936fee0598e48c1170a28fccad6a64eab3d628645401a5e6fa13e528a85d8a17f0f63714c4f329a48b30ddab1ea4a2c4db85d1695f6201af6fcef008a3470e0acad2cc76d4ca14091356daa614f64a58a16548e186ab590139006e8a757558976502ee21cc910f297f1f69ebd48082b9ebd396c2a0b04c5c01ea0b9e046b2c7470bee0408fcbd7b49f065fef6c337e37c23ac692fabb28d56501251f21b30ba98b69091a40adac6bda1159f58994df1b1e116d277d6ace9b69220000000001d1b36bbba8e6e1be8f09baf2b829bafc4ccd89ad25fb730d2b8a995b60fc3a6701d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "01447b429e6388b5ae527a23ef66141f7ffc54b1c90621376da94c758499db3d2f001f01db7ab361b645ff9b5e61d31fb42773da682a045d1a432cf8133f530e4ac6a83e0112cabacd9c5bcb20f397f36b9e309ebb939132d8411413f73d895c3f4444780c0000019c001b2a6aba0e7a68d73ee6298b431b8014fa2269355716157814a9480fde2b00000176fd40208c8b7c179cf701e65c4dba33ac2fd75daee86e7894112caabf3f75310136b8e923cc82844773eb4ea694395cc983f01c8ee6d2e7f379e758a572bcab1f01e8a2e43418c17ecfd14ac24c026ee73f625633b20f723a46df9aad874efef406016c3d712fa25ffe81b7565bf0970dd2cef0b14df1ba1719ba1589349a10610b2b014f4953491ea4a29604f7f1935e3fde4d40851918267a9340aa73d3375b86ed3a012ffae608e1b4d4de4f5ac38068b613d9761ba34d95430e5ec8d058848cc9c0250001dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2295000",
"hash": "00000000001ce059723e23b0d3df9d9fb55a5c4f9373c744b3f20571dc462e50",
"time": 1699842627,
"saplingTree": "0170240a7369307d304008700051f4715c7b6e31272439149e57b9c3e5964ca34801894d24c2d36e2e2d1d1b687033d5cca5724cd2dadacf7d5c60c730ef319252151a014401ad1c7122d27d0211b0c8ae3262e5618154f59502bc213aaec3746780603e01ed45eed6f820fef18e7a9b28fb127863fbddc64bddab07b75eaa5659e5d62e180001be77df922409f48462e62dee48efd1919cc4519aeb357cb94b3d21eeecd4c42000019a1747e24ea7c6ecaaedfb546c16aeb0658e7f01bbba9060db9ed3dae55e1c1a000170723be8910c6964fc936e9eae09b4af8b733bdcddfde30d3e2d64d6aa1d8d0700018930903c559e12edd7ccddc2121e688db849318458ef04e8f5bb36e9d2b9045a0001d0470322b61e0c802a5a5ea4c4eed59f122fe2699dd082679db5eca34d35bc0a00017f30bab3d865e778bb8423a91092cb8406cd2b56fa2cfd7902bfc3640d6b6b7200000001d1b36bbba8e6e1be8f09baf2b829bafc4ccd89ad25fb730d2b8a995b60fc3a6701d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "01ad5c9080c6c851baea50e3a6233e518b79026d4ea6907896ecde893149547f30001f018fea81778edf9edaf8118848a5afe66577015dc9a6011344fbb3fcc38a279e2b011f72b50b566081cb11acc23d0a3813424e85b82826b7cecac21860e4d0ccca1201d7ce154714faf6530e987e49becdee999d6d586e2133790d1b5ebf480cbe030d013c52e2d4527af8006bfa08486fb6b623bce8388818f7b912b0fa27d4cdcaf1200001f9e0e127a9952b5a15799e1968b758bf0227e2f62cb684cbb5eaee69d281c511011f1466ece7caaa8db087c09d40937487de8d207804b667932bc346c3dc9ad21e00000000000001d209b8b2dfd0ebb5e08e33d7d2d6ccedd61c67db8ea38cf33a695ab5a80fea1101dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2297500",
"hash": "0000000001157714936cd91baad52b26420f70d878a27f6bab348e2939b5bde5",
"time": 1700031969,
"saplingTree": "016cd61e5ab0ccd09c6076935098c3e8b9aecee2f9d3790431e1399840346c0e0201223fa371110693364a1c1877cdd219dfba7a134aa56a1ac47d55840d6ce665271a000000000001a9e947dab0b2907f94c8465661721d18140c6ab96fbcebf2b9487e72ec17c6000158a00dea151f1ae1790916fb739bb60d1f29a11d8067a64a1fa9a8c8ebab641300018e553358f32f5810dbb1b10b958583336fe2f331fe931fbfb34aacad78a91b630001a383100ed46da6862bfcd0a7b63d7409922e14c4c932960def290ea7befd50260001dfad84b2c2c9959eef6615f690c8cf687f09c70d21421c319af74b392a4e0c2d017f30bab3d865e778bb8423a91092cb8406cd2b56fa2cfd7902bfc3640d6b6b7200000001d1b36bbba8e6e1be8f09baf2b829bafc4ccd89ad25fb730d2b8a995b60fc3a6701d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "01d9588c0a6fe7fb1371c16087a92dd9561fa7fa7078f1ed8305ad69db3637f8350131b39bf4d91f7ffd3915c37ef23544d5e0f2a148f4b52a4d7fc24d2dda89d8041f000000000000015f6bcb933aea63ab62194dc732814b029eb366d5ba1196298b57a08f9083993b0171164246e90fb351e6bb66d6b2633ec0ab366e2dfbd25232330512de884dc32e01f5133a9e365dc1fc1d9a4246dd3670c7b70fa0332a288ee8147de062b4022b150000000001d209b8b2dfd0ebb5e08e33d7d2d6ccedd61c67db8ea38cf33a695ab5a80fea1101dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2300000",
"hash": "00000000005ac7bf0554036dac0c5682fe35efe6979899ab3b84e436b44f0271",
"time": 1700219650,
"saplingTree": "018e44e79d9b50eb410b2b71822dd20cd15ee24b5179d029a3f7b82625efc47d1b01493ed5e5ef4c0925a250b0958e5a5e19a1217b5078d53696127ca74671133b2c1a016a56fc185d21058b1b3c6f9f8d1cf807518aa2ec0b1cf1674e7282ed5c755649012bc9a1ef85304112128c9cb1dadd4cb82061bcb5acc780bb4d8255444050d71201a9e703a68d505d581d2d08f0ace75985c8bd8da07c69412b6b7b24556c45ec4b01d9f91700e846cd65ed188d3104da34c5fdbea9bb33ff395df28efd3e2defbd610000000163a89e43566d3f5c83fe55dc82563460d9f511dbcb24d39b48781e926787873100019d739d626112351a4a29ee7081fb7197170858275ba47de1d89cf03304188e530001a624e057dbe29939e16bfeb1a70d128f9086cb4a13d20e58e759138c2f55f26e01dfad84b2c2c9959eef6615f690c8cf687f09c70d21421c319af74b392a4e0c2d017f30bab3d865e778bb8423a91092cb8406cd2b56fa2cfd7902bfc3640d6b6b7200000001d1b36bbba8e6e1be8f09baf2b829bafc4ccd89ad25fb730d2b8a995b60fc3a6701d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "01e350c1c77aa1f7c85653c14d60b3f0898fb83cdc82340dcb894971dc7cfe1b11001f0000014f114d152411d917850c82ad7b88ff867fdf2d19ecb2a962efc492a4af59b832016c103fedd793dd79bfe0f8ca501da680eb5f4fcea41a175dbd6ae460af516e01000175ebb11b11dff6d75d3b1204616a3c1b88bd321c598bb0ff3209052df7e52f030101b760210f1f8a2c29b2d0048598b2d61152cfd798eaa2137ca1ff5ee745383b000130c3ceff4eea725a232d82f23f6f66ea3ca90758d67dc74407f68eb753c0f72e0116ee4da8c900e170c2dcbfbc660feb1fe8670f9ecd3e0b71b2958791196a2b1800000001d209b8b2dfd0ebb5e08e33d7d2d6ccedd61c67db8ea38cf33a695ab5a80fea1101dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2302500",
"hash": "000000000049a89a8d41f023b486cb6d1548f2a2d64f908a9fbf76e61dacd302",
"time": 1700408079,
"saplingTree": "01b3ac4e9b0e9c2010ccf8f81694c1fa43771fb84630c94b41328138c03cb3c048001a0000000001425472a998fba107d7736e4116a21082412a42a1e3b61d0ff7c1764d52e2d546000188c0404b7d872b78ee9918fd04281d55222afb1b175ad8350eb393046871f43c00000001deed527701b75f6c950b9a7128c98faa3702a38c857b7696da8f11f67e5a3d0001a624e057dbe29939e16bfeb1a70d128f9086cb4a13d20e58e759138c2f55f26e01dfad84b2c2c9959eef6615f690c8cf687f09c70d21421c319af74b392a4e0c2d017f30bab3d865e778bb8423a91092cb8406cd2b56fa2cfd7902bfc3640d6b6b7200000001d1b36bbba8e6e1be8f09baf2b829bafc4ccd89ad25fb730d2b8a995b60fc3a6701d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "01734870baf0efee72311408efab0909c9ad8b7ccaa99c1d37c75fa712a12caf120152075aef8984c941a53bcfffa7c4ef275e3102ba0301078b12ccc84786f647001f000001e3e9c4ff8237d1d9fa922f4d354820042925544f925572f22db6d13c08c01c2c00016d457bc303eb23978ef1832c16ae9ca515f0351c2b8b067a835902239e1f9d1901caa032d62f3164041df40ebaa71e1867abcc1c9e073db8cc0b0db3a8c5d4c71c00016432489114896a710d08486188b0c6d78bd9c1fc304ea923ef8fff3ffc04493c00000183411dfe5993abe0abdd925c9ec970859a893a8ad8f3e07e08cd23f185b3f613000001d209b8b2dfd0ebb5e08e33d7d2d6ccedd61c67db8ea38cf33a695ab5a80fea1101dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2305000",
"hash": "000000000079e81f8f4a7a7488a6cde3ac7042bf862264e73c614e18021fb634",
"time": 1700596777,
"saplingTree": "018b04b540c4a829001b9d9d2482fb225308527158c76ea4cbb0238c3b991db511001a000000000001a937d02e58bfe7c4b694ae884244af95aa79e2cd7cd947b1dad3100ebb2cb62d00000001a007a3456464c26d2d533b6b2493a5f1be94714f7c3fa071802b0ed2175b255801deed527701b75f6c950b9a7128c98faa3702a38c857b7696da8f11f67e5a3d0001a624e057dbe29939e16bfeb1a70d128f9086cb4a13d20e58e759138c2f55f26e01dfad84b2c2c9959eef6615f690c8cf687f09c70d21421c319af74b392a4e0c2d017f30bab3d865e778bb8423a91092cb8406cd2b56fa2cfd7902bfc3640d6b6b7200000001d1b36bbba8e6e1be8f09baf2b829bafc4ccd89ad25fb730d2b8a995b60fc3a6701d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "01c153f59f2dde1049aabede4a2daee3a755f3b6cf394218341dd5c0e3b16df42a01376e4e22cb0ad65701983457eb4a8fc04cc3c92d378642063d2829d74f6bcd071f01f975ad6414124bfc33a98058f6284af7b3da356098a99b9976aeef4b41c2ea0c017da8eda542a9417023dd63717897bfa86470d14f3ca76f6cdb0c9c6309ff49160177c04cc8c4b25f9bfebb5c3ff80c977fe489139d41e67cafc3da11f2924f0e3501aa8759f042284547e9ff050cf4988037c24dd722d910e20f495bd12e2b12b2190000000000011ba71e24c0a4b3b4d3d7aeacc9fdb005e3e8fdd2a0ac4e208b9f8038846fa5230183411dfe5993abe0abdd925c9ec970859a893a8ad8f3e07e08cd23f185b3f613000001d209b8b2dfd0ebb5e08e33d7d2d6ccedd61c67db8ea38cf33a695ab5a80fea1101dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2307500",
"hash": "0000000000c314fa9e022058471f7c22f373049213d66197fd2caff804331c5c",
"time": 1700784785,
"saplingTree": "01fa707068382e014cab53bd955811594ae0b8cb3ccab46d4ed2a67929f08d1c46001a000001895183b4862b58cde910c5d6fba0e46e1f20f15366c29e486e1d76895ad176410115e6ef7132a9cadce028659efc457848ed2e492c8497fe394ff8b05d78300715000001283d2c3554b31ba3fdc549548013737d2c13c2fcfc75ad151c92b0823d0e1c4e00000000000000017c650876ee17479db2e11cb5385df4fc60ae8f8cc8d501fa5dc07a4438e5863a000001d1b36bbba8e6e1be8f09baf2b829bafc4ccd89ad25fb730d2b8a995b60fc3a6701d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "012d3af44ebbce403cbaa3dea8646db860d162620ebc757b828152fac7081fca2c0120149eb5e3ced3ecdf5d2a3e72b17104c62e22afb27884894c11c458d874d6371f00000000000174032ed7794d8fd255551f745978ece0903911d92365d3c17e9b613c32418b3301cd138752ced84e3842b622d56eecd4b56f4b39833760f06f2865186d5b64301201daa313d6b302574f10607d76cd93e712d8dfe12cd944046b02733568e0e012040157269ec6a22f08eea74d8932bcdd0ba7bad60727d5f3173ef3087e5c20f3a201011ba71e24c0a4b3b4d3d7aeacc9fdb005e3e8fdd2a0ac4e208b9f8038846fa5230183411dfe5993abe0abdd925c9ec970859a893a8ad8f3e07e08cd23f185b3f613000001d209b8b2dfd0ebb5e08e33d7d2d6ccedd61c67db8ea38cf33a695ab5a80fea1101dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2310000",
"hash": "00000000003e3be289375a8f4f5ed390b827ae52805a69e69c82adc47a7f638a",
"time": 1700973210,
"saplingTree": "01fe557c21a5d4647046e902864638d20362ccc7a9ef56852483c86bcd20007e0c01fd001f566d9fbd40a11b7f99836983715c36b423d6f7180b2a3da6bc637c22041a015f3279b196009a204d57b38723428f41b694cd5d952e10141c72ad98d4dad14f000001e4096c60afd06552a95caa4d1fdb47ef90671eff98279690d5f8eca38b05e0380001da52ca490452d5e8039117ad108ef6625eb20b0a3ed1543493f221e38830ab0d019dcbbe67345d0ebb294e6f4407495d05d5d7d67bdc05d5c72cc4cb626d38005a0194e6b1b0e859aaa6f334f26787b892653ac7419a99775cefc91a431d94ba8c1801e3295c2b4c5162269534ee66fd4d1883d8c2e28cad49310fe947b7b82dd077010000000000017c650876ee17479db2e11cb5385df4fc60ae8f8cc8d501fa5dc07a4438e5863a000001d1b36bbba8e6e1be8f09baf2b829bafc4ccd89ad25fb730d2b8a995b60fc3a6701d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "01a19219bf964863f94659fbf191ecfaf0c10b07226bb933b5051f6d3908fcf026001f01ff9aeb5da2f0ef643823ce28d831290c9d5f441572593f796dc83f8234f7b9010000017a308fd5603ddb44d460d70e14677b040a08c965a685e2b33e14b530cd6f38270168674fefed9b39ff94de72c22d2bfcdddbc329b4b8464582da502f329267a81301616a84ebf0c29c75d3fdb8bbd3c3c33b6aeee66610ed586aedb11964a2f6da2501533e6416d9ed2a110da9349a52c00022888e54f83858c467538c7f8f5aaac2300001ba23e71929daee1f2746bba3eaf121060d94b58d474053fbf0a6753b7fbce53d0000015e077957f78fdaaa3c9d109d71a37e2eb7b1eabba42e0aa4aa93531189193b280001d209b8b2dfd0ebb5e08e33d7d2d6ccedd61c67db8ea38cf33a695ab5a80fea1101dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2312500",
"hash": "0000000000dba0ccbb7e962de6055896a33ee8a215334e765752225f57f25319",
"time": 1701161717,
"saplingTree": "011b047b029b0223d01a7d07cd5f8f0b66819877dfc005225784dc6e6f006d913a019caeb7e6ada760c4ee6534767e1b67300962caf78c75abba6706e7381efa4c031a00000000018c889ec59634e2526bff2eca96f846c9fb9b228e125c6710ca241190a45a5c080000013f61a08e8d9843a60979fe1c6deb77da4a99fce0bcd7dd1624dfa98c446e194001b6867d2c3c104e649df401daa8373c7b1b2c8d54ca293b779e125b551fefa83f0148a553a0ebae8a53b6ccd8515cba62e04889039e168769eb1ccd11366822ae6900000000017c650876ee17479db2e11cb5385df4fc60ae8f8cc8d501fa5dc07a4438e5863a000001d1b36bbba8e6e1be8f09baf2b829bafc4ccd89ad25fb730d2b8a995b60fc3a6701d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "013e4e8b363581ffbc0a51253ab7c4477b2dede771041dde0fa8560b276f7b481f01d05925ddf7371123f63750935dbffc1083d075e782c479cb804a1ce47ebe07101f011b96f60d6c8c8d6de77f81ae356258bbe4f340c479b9899b55efe815d55a8b3d012b46aec45ecdc454af7d98c7e4e106323e3acd1977174348622bae9d1c2a0e1f000000018cb71ceec37ab14e37db4dec90cae5a29ee5f8e4786522d2144a6c97df0dfe13010e345504f193f43cc185a88d5f1c4b276eff7949f2510b9d38a868f4082c1a370175a1b7b6ebfed2c594767d94bb9f7f5bd9807b64b145ff8d39a237a6cc37b20500018fd27921b6dc15e1e964b30359db1a479820a41e31e5455eeeca0b6d589aab2300015e077957f78fdaaa3c9d109d71a37e2eb7b1eabba42e0aa4aa93531189193b280001d209b8b2dfd0ebb5e08e33d7d2d6ccedd61c67db8ea38cf33a695ab5a80fea1101dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2315000",
"hash": "000000000063c80bca59d74e55af35f6b59c01687d31f26a2b3729b93f98ad28",
"time": 1701350630,
"saplingTree": "01d2519e2c14a29555b9cde40649861b5b0e41342a9dbbdab934b58deea51e326801305bbab496d6038dde6346b4a75f3445209e2727ed96d2f1543b468e523ddf171a0126e16076b2d31d91029d8f11d048530feb242d3907291d612cbff71a2c679b4100012d780487df8dc25aed2aa828a195ac1edfe1a86bdc72d51906334d6ffacf5c390001afbe47945030efce4743e3172c2ede9d3160d0e40d3135c04b0e5bff46a5d32700011181d08141fb96403667db5c5856900cb88efbc0d24f0e38ebfae0c70cb1cd160196327ceab6a4189834bf78a47b558e5eab9610cb7377b07f1c82adddc9f0a33301873041160a4a52846ec91f092822480495858022fbb6f7640070745a5575dd5900010eb533eb674f2ac390ccb7684976b2428b83b8b39e6c43d2f3a43d10eb1bdc3b000000017c650876ee17479db2e11cb5385df4fc60ae8f8cc8d501fa5dc07a4438e5863a000001d1b36bbba8e6e1be8f09baf2b829bafc4ccd89ad25fb730d2b8a995b60fc3a6701d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "0141714549d5769047a201cd12210be13b3cbf373e7e86833719c635addda31a3d01bb6b35e170a530aef78b9ef55ae310fe7877f2a204ef0538c132fde36ae6b5221f0001e3f7122d8c022a6de32e3c08fed433c0591ec14529a5cfa98e7ffa93c6c0c6070001d748a193374b9fb63fa75cde9b338aba2c78a913e2c39e92f55f67b3d805173a000000000000018ad9c06ecaeac466f69d27b659ff3fdf5287171b7df71f822cc167be9e51333b015e077957f78fdaaa3c9d109d71a37e2eb7b1eabba42e0aa4aa93531189193b280001d209b8b2dfd0ebb5e08e33d7d2d6ccedd61c67db8ea38cf33a695ab5a80fea1101dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2317500",
"hash": "00000000000d3facec8102c21e27b796085e726f22a6b4404af403f2e06246ce",
"time": 1701538290,
"saplingTree": "0155db89249b69a58c85c01a4e7c8469ac09ba32bc7f51b25679919e6a7eea911d013d8af6af82a1d198d18332485cd6eebb6e0f74a2c9eabcdf235bf6aedb495d181a00000000011fd68f39cba1dfa0a91a698f5263918918a17cdab23f591b75791ab6bea1531d011958f866e2712bef4e8e0d2c848ac354a357473f77e6d22c94ebc7e2a5b4653a000186fe98e6681eb57ec026a3900596c4cd45f866d5bdce901d6605dbee33b23d020126d05908fadda6bbb60afbb88a504da766b9d75da5aafa4ad5c92e341535ff6f010d99ab6d6e3b3983376306f6e72ab14814473041a883f9922c92fe7b07726d48010eb533eb674f2ac390ccb7684976b2428b83b8b39e6c43d2f3a43d10eb1bdc3b000000017c650876ee17479db2e11cb5385df4fc60ae8f8cc8d501fa5dc07a4438e5863a000001d1b36bbba8e6e1be8f09baf2b829bafc4ccd89ad25fb730d2b8a995b60fc3a6701d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "018478a5883a7f71da8680c223850112fd44301b4e3b56adcdc114c1cea7287a160165732310afaadfd3f4ef6757723826e0085dfd8019e3437d6badd5000db34e1c1f0001bb3758c39242b6c84af5189d705d43551d16737fe72bb67815af188fe6e8b12801d77b815c0b254e0b9ed4ef38667cc24b38a28d1d63a466b432fe7ca15117491b0001563137aeadc46a1380214ce6d8a97660c7dc73b76f56efaf8ec1dedb40f1610b017e14bb5c438d09ccbb47ed8b7c72949398aa3a35f2eb9d0d9917f8dea93a9938013952475147995c96e33405e74d84870b8b76e7095098de777a07df80876a6c290001619564c35b4a3b4ef1f091097f6238c6a9780a3176461afd91a81ac745bdb22000018ad9c06ecaeac466f69d27b659ff3fdf5287171b7df71f822cc167be9e51333b015e077957f78fdaaa3c9d109d71a37e2eb7b1eabba42e0aa4aa93531189193b280001d209b8b2dfd0ebb5e08e33d7d2d6ccedd61c67db8ea38cf33a695ab5a80fea1101dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2320000",
"hash": "00000000003b4ec49e08e7e5bc9d2050a7d8643af4b5eb31d9ee7028612a880f",
"time": 1701727742,
"saplingTree": "01602ab6d2b8b67fbf0e58e9ee8a0b345b39ded68dfc7d62af19907ec9fc4f222d012cf650868b19f72ae52101641c5747365a443ab711e50a25eeb6b472bfac77181a014b0f98696ad26bfe5926936fa8c5de8bb7416cd0dc2301bbc3585ae6c5e1115d017e6af85204c809fcec6dc5602ad709bac1edc817ca70020e69d5b93a987bc42d0000000111a06a46a8a80840c4a4c2f815a29da482223039dce8edbdb6689d7701fa072301af4f78eccdda9fd76545db911714ea06ce7c3c6ae4bd0282433d7f60111d40400001b99a5fc8f04fadae650d5ba9a8c2b3dc2118b201443633bba3094c614a21875d00000186fa0a21fa4284d9c240f071b5af78077c52eaa3dfe191b54419e864544bdf290000017c650876ee17479db2e11cb5385df4fc60ae8f8cc8d501fa5dc07a4438e5863a000001d1b36bbba8e6e1be8f09baf2b829bafc4ccd89ad25fb730d2b8a995b60fc3a6701d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "018431396c97957db93241404a0639bc60ba09a9f2975a2ca24acd59b97c20671901f413e556f6c3e1dfc94e4d72238e85954c46990db1477d6de37af96e518e8c3a1f0117fb0fb518825c203982a62d18a47d951b7bc05e745804db3088ae4bff83df0501f24ad76de4127a948767a3c951b2f7669872b30060f74f277d9dd639ad91373d0145909b77966da09903cf6f9f3775767fd22bd2684d0d5481bc722547c84baf2801e20bbd57e4abb340e725c3e45b11e2586d973cfd8936281ad040551903d10810000001760daff686b68989fa82b07113710706f3c53210f60564c80f05c3650b183733016902d64f2c463444a48030b6f0296dd78195d0ee061d94d76a2708aed4c88235000190b29301c40d674af3e16086be3da02dc7fdd0e41608f224a5189efc4cbea418018ad9c06ecaeac466f69d27b659ff3fdf5287171b7df71f822cc167be9e51333b015e077957f78fdaaa3c9d109d71a37e2eb7b1eabba42e0aa4aa93531189193b280001d209b8b2dfd0ebb5e08e33d7d2d6ccedd61c67db8ea38cf33a695ab5a80fea1101dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2322500",
"hash": "0000000000e8340a4a923642702f5f4c93c1057072f07c4426db57a71b2b05c7",
"time": 1701915899,
"saplingTree": "0130543b861c21671bbfcc2c928df965785d5a3fab1426b73879c0022e6bb79d5a01328a4783881ecd0011aeef5f70d7496a4bc425c94993d3b228cd6c3690ccf4381a0001a93de2cf2543f2fd6f2504e814922c8c9f7b162a1fd4fec6158fd4eff35e95690192dd47b9a4a2c6e72ceb7540848118de3bfd86641538cd84f770aff8ab792d31011144e221bed09d3de04ab1dfa21951d2e606a60432364f820b505b14fa85704c000001a32c4d21a961c0bcef8fc7508948492e8acab31cdd7bb55cded3776c54a67420000154c177cdf9db3c72580ed4490a1aa1cc46e1f360de6a5bee1d3453259781d955018eb775530e562c46105b272abf6a21413fbcfcac2ea017a78bce6499d1b89936000186fa0a21fa4284d9c240f071b5af78077c52eaa3dfe191b54419e864544bdf290000017c650876ee17479db2e11cb5385df4fc60ae8f8cc8d501fa5dc07a4438e5863a000001d1b36bbba8e6e1be8f09baf2b829bafc4ccd89ad25fb730d2b8a995b60fc3a6701d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "01fa516ebcda12379171d2afdc1f59f3180b8ce2ad6c38391b51c0ed4cf7139a3b001f01a08e4fa9dd9def0e83cbd58125938fb596bac3477fd89b36ab821bc33d8cab000195d6948704e2a64a15df1ac9813b0347a662fa40bcd18215a7efc2cae78d9c0d0147cd40f30d1b0bbcffb7e475d9a68c3a16bd8628224545f181d9f2f63a0fce37010938aaf4fb08768aff4a340648326e59d88dc7d0a24c2e562a73b548db6436010001979070a88699d4f746386d66f275107fa863e2805c8a324e4ec026be634dc42101cb98c8c4d66301b255da9cfb983eb45ccc23a73c7ae15850e014929ebd5805300000000000015b40eb9abd1efbc71e5f3b718a42650c8a9353438a71c4362de2f6d98280c72801d209b8b2dfd0ebb5e08e33d7d2d6ccedd61c67db8ea38cf33a695ab5a80fea1101dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2325000",
"hash": "00000000013f351b47fa9808602c2ca9a9eadee3db250ace3aff6f94a05a2c79",
"time": 1702104343,
"saplingTree": "019f014bc938bf342e8fa962df405dfc7f70383ae75a3d84f3d8387b8cfc8fd7040195152d1cd4f6c864e8ae0d72b08e2dda2dcd5e9edaaddc2f5dbb7178b289ad4a1a0109f5e959a861537894bc48e6dde123b710df1d9b3ce0964bd654e57830d17d0a0001f4a87eb83b5988dc58f83e6c0ba540b4bb0dc40e224e88f35fb6cd62b2535c4d0000010d2534d167fbe412ef86ec222ed59380bc162550ce21200c123aefa79d43805a01526b97e22e9413bf11b37c0604401a0d8b693e1b7bb1cc0233cda3a88d4bf24701fe0232c88a5c2333f9523137ef0abff30aba4fc8cf4f9c6cdf82842f67309017000001c8d2d57c894732aa88c35fe01438b84eb067a83f0d09315b76494f27bbab57340186fa0a21fa4284d9c240f071b5af78077c52eaa3dfe191b54419e864544bdf290000017c650876ee17479db2e11cb5385df4fc60ae8f8cc8d501fa5dc07a4438e5863a000001d1b36bbba8e6e1be8f09baf2b829bafc4ccd89ad25fb730d2b8a995b60fc3a6701d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "017f448390aeadd1125100d98fbde772e11d0e91c4860e90e1c0803332cf6f602b0112392d87b5a97ed3e9afb41c7d9b07aaa8e11b623f8e7f61f1d5bf230582a82f1f00017d420d9ad88166b9134bb6cf4d62c3a37d5d268c0b84c3c7f3f3eb34a51cbb3f017fec6d32a455c17cef710dea502f916540006d9a80216982e3b147b1f8f3773c01e2daae27ecf43e2b0105b0affe5e263674e936cbaa9964a0f95f09b1f89cd12b000187535510b6168d9f9e2750143cd792334c4d8c0f712bfb336232f55ba65d261b0001c0db8fd4e6e85447ec9f5568a6fff28abb7b97b5557cf877a45c50cc5bafd20f0120bd425a02ca0ae137d2cb86c65e59f3f49bec197893b17028ca66069ff68c0d000000015b40eb9abd1efbc71e5f3b718a42650c8a9353438a71c4362de2f6d98280c72801d209b8b2dfd0ebb5e08e33d7d2d6ccedd61c67db8ea38cf33a695ab5a80fea1101dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "main",
"height": "2327500",
"hash": "0000000000503558ba505b993ee8e7edac7005ffbf55eaded600679639de2b77",
"time": 1702292824,
"saplingTree": "011c3d10e821079fc295396929ebe3c3dbb027fa0fa049810743adc7a545ca3f1d001a0154e610d47a9580cc8aa570d00f495fed79aaa04be1f5a7e5b0f374fa2a79c7300001d0372bcf02021e31a46589204ddaaf1c3be0c1ab6afea383d268d74b0f60fd010000000142ebd53d9f0b8e01fda3799a041c8349b6d78f6fcd6a273f3ab9142137fbdc0d0000010c381362b8a0a10e2d2fc13e91f593cf74735f774893771e666f7852afb1f24001c8d2d57c894732aa88c35fe01438b84eb067a83f0d09315b76494f27bbab57340186fa0a21fa4284d9c240f071b5af78077c52eaa3dfe191b54419e864544bdf290000017c650876ee17479db2e11cb5385df4fc60ae8f8cc8d501fa5dc07a4438e5863a000001d1b36bbba8e6e1be8f09baf2b829bafc4ccd89ad25fb730d2b8a995b60fc3a6701d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
"orchardTree": "016de0af325e9c46845ba0cc7229d632adc8babf9c3ceb435b73357459c493802201bc556afc0fead4f8ad877abc405019e3e7f22c243066ee91b5839d2494183f001f00016b3996001480b04b641a77e7b76fd0ffe8f111d7cd0c758c33150fb0568c2a1e01f9ebca20fe1e4ef33048f8bddc2e49c8ce7df0dde189d9e9b1ba6ef3ec4d520901de6f9d9db1541b2814aebb15085157c559780f993429a0c506aff765a582ea2501faec26b888c102aa510c66b2df1043aebfae92242e6099a66de3c5f42d31842a018fe817250be193132dfa50e005276d8211acb83e7bcb9947b3e15fb43abe281a0000011da8ae6166aa439a84eefa793cc964d33ac07b03084931c64686b2b64a00023101b93071dc309561911691da735ded9daccadffe308fd65dcada374934bfe8ce1e0000015b40eb9abd1efbc71e5f3b718a42650c8a9353438a71c4362de2f6d98280c72801d209b8b2dfd0ebb5e08e33d7d2d6ccedd61c67db8ea38cf33a695ab5a80fea1101dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "test",
"height": "2560000",
"hash": "001a1df8cd5e636cda82900c4030432017f7aeda9ca60f6c706164732e70fae7",
"time": 1698006275,
"saplingTree": "01b76b5c4c6b1b0797856ce48b060d0c0a32fc9c0873d7bd2df2dc666d634062680010000001e64e209c74e6a23211d48d472f10a90313fd3705afecac8518067299e684460f0001ba113fafff85ecfb63f2b8fefeefd176abad18b332fcbe4617cc377c59259d3f0129e08af8189ff4018093656da1e36422aef2b323ad17c90c1ae06a520fe7935901ece1ab9533870d5cac32a7d18da872b63a200fd7a6f56cea365bb8d64ec34758000001229c65dcabf0d220239a425d9716c9d4ee45201f7e300f7cdc3e02e26af8504f00015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39",
"orchardTree": "0171b2ffcff2bbb7770d8418363b6128491f7b12fd854fa346b696f5a7a187f60c0141b23d5a87625c5c9dfa7689863e97f5bd36b4093f64fee7c28785e7b26f770b1f00018fa3c7f5144f59625d9c2e8113eac210378aa5667faa574ed9033fe2d6f2540e0165ac84927cd3d5fe6889b21711cb332888f2162f1dbe7cf92af562655c8f97030193bbae6d58db67a04ce81d81c529c3eba51215aee8ee356c73aaadab16c662250001f2f62617a99c5ba23fb9842b8816583e7bd124085a538a747857f30226512827000137f6061a5a492f13652bef0cbc396afd913a57bc7f877517ed7b08ca92acd83e000178a68d439d45f555fd4fe08eeeab4545091b53d73da118b6084042c4a4c44d3a00013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "test",
"height": "2570000",
"hash": "002f16febc8fe7cf17ed80593d364d639f5702bf780a91a81642bc195693667c",
"time": 1698650731,
"saplingTree": "01172469ecffe90fd74caecb72e0a8238a0c487c230adc637ef6496dca9da3336701b090011eefc4d43d9b5946d8a2aebcd1dc76c797ab059e51ebcee8aa2c6850141000000000016326709119d4f2bbad47d29b693881cc7c057c1b8776923ce1c3a4317df5444300000155a83a21de7d49c5a147fa4f27e249f8ff599a2e2094ab8a86fa94e0e57606150001229c65dcabf0d220239a425d9716c9d4ee45201f7e300f7cdc3e02e26af8504f00015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39",
"orchardTree": "0193e602be1e5746f0978be494185934e884d0b11c32d601faf88402b2db809f1c015563e319e9e02e7f712e3cf62958a2f6bd1c5f2088796852263f2d561b5a76191f01dbb0162fba11b68d21c5aec3c9df5d29ff36b8e762022d1f61eb1e27427ff6290001d48ad801c0fc9a914533c8e67a74a7a53e7674f2c42b88c93f5dfbe7a1095c3700011ccdc25ac8b1322de8eb13af092cc33d2031b0da53ee35b07a9c944f8631c71801f2f62617a99c5ba23fb9842b8816583e7bd124085a538a747857f30226512827000137f6061a5a492f13652bef0cbc396afd913a57bc7f877517ed7b08ca92acd83e000178a68d439d45f555fd4fe08eeeab4545091b53d73da118b6084042c4a4c44d3a00013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "test",
"height": "2580000",
"hash": "000d717569dcdac9458704cec46eb7fc67ca105a20f6dbbf9b21f0b2a0a87910",
"time": 1699309684,
"saplingTree": "0151e8b859755bfb7cc5a1169da36a21c2f15f0d86c650c12f579cb0d47df1a46c00100001478acbd016a7669a43f925fda51709c64e9a62a4d8308cc927da3ccdfbd0344600000000015b4d7c5fdbd3fc65c60ba67e3c26a5647422620dd326ba2b2aa0b2874aafc93a0155a83a21de7d49c5a147fa4f27e249f8ff599a2e2094ab8a86fa94e0e57606150001229c65dcabf0d220239a425d9716c9d4ee45201f7e300f7cdc3e02e26af8504f00015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39",
"orchardTree": "0153a87f57b6f0117fa5e66f907e43072d174b0dacf7c3579f6e131fd5ef26030401fa13e543f0b9cb6979eeb22dafffffb21384edf3ce061d5695ee4ff50bbc43221f0000000001681015d288503e6d4cca7cb633620cf23988d46109d0dad198361957ecfad60c00000001cf1d91dab12c89f04b9f6a2f650544c23cb24c7fc8c9b7d10830e9c1623cff370178a68d439d45f555fd4fe08eeeab4545091b53d73da118b6084042c4a4c44d3a00013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "test",
"height": "2590000",
"hash": "000e025af081ac1d5deac23db13a487a740c1dd11c8edbe101da87491c59987e",
"time": 1699964905,
"saplingTree": "01c48ab439dfa3023a4072c099ac0d135964ed439c196c76abad469010394c823701a2ebeb57c8b6a5dc11700c5b1b76b5844a1851c43fef162bb05dbceaf39666271001c8e3520813916a8e29b50daad01a379d4bbd4c263d2d4d06bf98e3e7e0cc065901d900f8dc9a7040f29eb91ef95e2f0e063f03c967d6d9dd7daa82aaa71576584501a17c8ee954beeaea9e9dcec6c7971a002fbdd60eadcf6b371dfe5d611041d35b000001a8d2ffd9468989e0bc26d93d585f10414c2f1fa66cf6a9c52f5e40852ca86510015b4d7c5fdbd3fc65c60ba67e3c26a5647422620dd326ba2b2aa0b2874aafc93a0155a83a21de7d49c5a147fa4f27e249f8ff599a2e2094ab8a86fa94e0e57606150001229c65dcabf0d220239a425d9716c9d4ee45201f7e300f7cdc3e02e26af8504f00015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39",
"orchardTree": "0141df0ebfcd40cfc60b565c5d07136853e2125a0fde00181dceceef0d8c5ee538001f000000000001a14e51730f1aac956ca02793a6c274f1bca3a81d368f0ba52ecf14f13b947b3d00012bbdeb10ce1ba239547d675779168586ceab869467a8a36642e0af67ce1bca3301cf1d91dab12c89f04b9f6a2f650544c23cb24c7fc8c9b7d10830e9c1623cff370178a68d439d45f555fd4fe08eeeab4545091b53d73da118b6084042c4a4c44d3a00013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "test",
"height": "2600000",
"hash": "000b9ecc8bd155dedcf64d27771fc79b8b753fef0d8b0a2557eea1c17b0d8fe6",
"time": 1700583151,
"saplingTree": "015ef8ae4e19192fa4762fd53de41e1697e437578938a3617fe09f7a0c94195d55001001c4d0edf589adab2f1c85b1475be801abd5d577cb7767910dbbc8235bdddb5560011eba92d6993e1041fa1351631967a03717bd0f676a03f3844ebdce72d37cb15f0001aa4ed78e33a85295032fd575083045c3fc6f1b9869bde4043b56aa1a48b338040000000001285d51c9dd96d971a1c15b2af0693eff7b8002261be896f3b5b1965b2707642801229c65dcabf0d220239a425d9716c9d4ee45201f7e300f7cdc3e02e26af8504f00015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39",
"orchardTree": "014eb099e4cb8492169d35249d01aadf61efe9f81f54cee545ba16df72319ca42c001f0001a5322460edfd5a6e300456e17093f2c8ce43e022b5c73731c76b1f51afaf882e01aef6f9da0bb0ebaf9e0d8bdccfa66822e82d88c723ebcd215120056e6a1d6a20000001a14e51730f1aac956ca02793a6c274f1bca3a81d368f0ba52ecf14f13b947b3d00012bbdeb10ce1ba239547d675779168586ceab869467a8a36642e0af67ce1bca3301cf1d91dab12c89f04b9f6a2f650544c23cb24c7fc8c9b7d10830e9c1623cff370178a68d439d45f555fd4fe08eeeab4545091b53d73da118b6084042c4a4c44d3a00013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "test",
"height": "2610000",
"hash": "001ec0dab50faa76f18e6f909e47fab55b1c4ca8d3e71ecb2ade5b4cbd0e5fe7",
"time": 1701164195,
"saplingTree": "01dbd359d688208f96a23db7bebb62419f2625e84ad5618866bec96a6343fb564801d54a95397777b995acad192de3e701774cb37b4ccf8725f0f44fd310c75271421001f9170bd1bf292c3e6c18f3e71754965b617b12616a91774b71855405ef74f243000000015f6141cef1b8f811dc43dd394607d67d27082c6f275bd40fe756cd93dd858938010ebe26176758357ad3cdd4b31d1762471121764549f55f456aeb12b337e4936c015288f7d7d6224034bb962401accd8299c2a060bb99d5ed93501fecb93066bf6a0001285d51c9dd96d971a1c15b2af0693eff7b8002261be896f3b5b1965b2707642801229c65dcabf0d220239a425d9716c9d4ee45201f7e300f7cdc3e02e26af8504f00015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39",
"orchardTree": "01a7c5f84910c8cf8415e8b44f63c50db5e2d07aea69fba45ff1a2a66bb5f174010192bc02fd7ebf7fc163e3032222ca582f03031ebfa1716f9809df2aa6451652151f01dc80cc2741d5a3da94b52b6b41ecebb92e7cb7f6d19af5b5b60fdb4b6d59a50a019e9ac8749a2eabf9337fb776d780dfa285cbf54c05536711a46003b7bad84019018754c572f9305fb4eabcb9cfa58b6604d9606315c8a9c6d92a5aa234e15a113201a351dd9405e1391682d06a221bc814b3a4f4a937228507e2308a4e34e6c8922d0001a14e51730f1aac956ca02793a6c274f1bca3a81d368f0ba52ecf14f13b947b3d00012bbdeb10ce1ba239547d675779168586ceab869467a8a36642e0af67ce1bca3301cf1d91dab12c89f04b9f6a2f650544c23cb24c7fc8c9b7d10830e9c1623cff370178a68d439d45f555fd4fe08eeeab4545091b53d73da118b6084042c4a4c44d3a00013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000"
}

View File

@ -0,0 +1,8 @@
{
"network": "test",
"height": "2620000",
"hash": "00139f229081782e5f0238fa02da7b0dd7516a0c6c8f7e3bc1940f841146f32b",
"time": 1701773766,
"saplingTree": "01ee7aef1afcb5615f849cf17167b39c323ca5acac80885697ff0dff0f41f0df6f01d986b6586d59fe113e2fbdf6f03c4e1199c22c3f0b2dff8e3ed544958487b26510000142a19e30b4b3f16d9f1002df18f3b05e7215f050a8b1b749a47f33e5ed9f9e6100000161ae6a6536a4928b9fe11aedb223fe58893f9c337d6c7b0e41cc82509cd780580132f6625f5568d5c36d820f3b5cdf7b9e20b6faa4ba27cc418f5828ab60ec6c2d0175a85ed94a7f19985be0ff968e0b1fa0cb25c1792c4990ab5e6b30d5cfa57f30013aeaf03c22ca18f70275bf195ba855cffad97f3d2d40d1aa991711f2dbf4d52501285d51c9dd96d971a1c15b2af0693eff7b8002261be896f3b5b1965b2707642801229c65dcabf0d220239a425d9716c9d4ee45201f7e300f7cdc3e02e26af8504f00015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39",
"orchardTree": "0173c10050c6cb1d64e5a4552e922cad6387a76cf4385ae8c7ca212d99267eb62e01e925514d92ef5f27f19f6314d00bda50fdaeac24ad7cce8542d91f25f5d523141f0000016219cc01738c79fdadb026ab4f36f02a6a9bebec9e89ff96ea6d58cc24893f060001c9851bb75b703e0d30a1cb1c6073989fc85114ff6e43c5464ad33c789c054a1701a14e51730f1aac956ca02793a6c274f1bca3a81d368f0ba52ecf14f13b947b3d00012bbdeb10ce1ba239547d675779168586ceab869467a8a36642e0af67ce1bca3301cf1d91dab12c89f04b9f6a2f650544c23cb24c7fc8c9b7d10830e9c1623cff370178a68d439d45f555fd4fe08eeeab4545091b53d73da118b6084042c4a4c44d3a00013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000"
}

View File

@ -106,9 +106,6 @@ public protocol Synchronizer: AnyObject {
/// This stream is backed by `PassthroughSubject`. Check `SynchronizerEvent` to see which events may be emitted.
var eventStream: AnyPublisher<SynchronizerEvent, Never> { get }
/// An object that when enabled collects mertrics from the synchronizer
var metrics: SDKMetrics { get }
/// Initialize the wallet. The ZIP-32 seed bytes can optionally be passed to perform
/// database migrations. most of the times the seed won't be needed. If they do and are
/// not provided this will fail with `InitializationResult.seedRequired`. It could

View File

@ -79,7 +79,7 @@ enum Dependencies {
}
container.register(type: SDKMetrics.self, isSingleton: true) { _ in
SDKMetrics()
SDKMetricsImpl()
}
container.register(type: LatestBlocksDataProvider.self, isSingleton: true) { di in

View File

@ -22,7 +22,7 @@ public class SDKSynchronizer: Synchronizer {
private let eventSubject = PassthroughSubject<SynchronizerEvent, Never>()
public var eventStream: AnyPublisher<SynchronizerEvent, Never> { eventSubject.eraseToAnyPublisher() }
public let metrics: SDKMetrics
let metrics: SDKMetrics
public let logger: Logger
// Don't read this variable directly. Use `status` instead. And don't update this variable directly use `updateStatus()` methods instead.
@ -44,7 +44,6 @@ public class SDKSynchronizer: Synchronizer {
private let syncSessionIDGenerator: SyncSessionIDGenerator
private let syncSession: SyncSession
private let syncSessionTicker: SessionTicker
private var syncStartDate: Date?
let latestBlocksDataProvider: LatestBlocksDataProvider
/// Creates an SDKSynchronizer instance
@ -104,6 +103,7 @@ public class SDKSynchronizer: Synchronizer {
func updateStatus(_ newValue: InternalSyncStatus, updateExternalStatus: Bool = true) async {
let oldValue = await underlyingStatus.update(newValue)
logger.info("Synchronizer's status updated from \(oldValue) to \(newValue)")
await notify(oldStatus: oldValue, newStatus: newValue, updateExternalStatus: updateExternalStatus)
}
@ -165,7 +165,6 @@ public class SDKSynchronizer: Synchronizer {
case .stopped, .synced, .disconnected, .error:
await updateStatus(.syncing(0))
syncStartDate = Date()
await blockProcessor.start(retry: retry)
}
}
@ -244,13 +243,6 @@ public class SDKSynchronizer: Synchronizer {
await latestBlocksDataProvider.updateScannedData()
await updateStatus(.synced)
if let syncStartDate {
metrics.pushSyncReport(
start: syncStartDate,
end: Date()
)
}
}
private func foundTransactions(transactions: [ZcashTransaction.Overview], in range: CompactBlockRange) {

View File

@ -16,6 +16,7 @@ public protocol Logger {
func event(_ message: String, file: StaticString, function: StaticString, line: Int)
func warn(_ message: String, file: StaticString, function: StaticString, line: Int)
func error(_ message: String, file: StaticString, function: StaticString, line: Int)
func sync(_ message: String, file: StaticString, function: StaticString, line: Int)
}
extension Logger {
@ -34,6 +35,9 @@ extension Logger {
func error(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
error(message, file: file, function: function, line: line)
}
func sync(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
sync(message, file: file, function: function, line: line)
}
}
/**
@ -45,4 +49,5 @@ struct NullLogger: Logger {
func event(_ message: String, file: StaticString, function: StaticString, line: Int) {}
func warn(_ message: String, file: StaticString, function: StaticString, line: Int) {}
func error(_ message: String, file: StaticString, function: StaticString, line: Int) {}
func sync(_ message: String, file: StaticString, function: StaticString, line: Int) {}
}

View File

@ -23,7 +23,11 @@ public class OSLogger: Logger {
var level: LogLevel
public init(logLevel: LogLevel, category: String = "logs", alias: ZcashSynchronizerAlias? = nil) {
public init(
logLevel: LogLevel,
category: String = "sdkLogs",
alias: ZcashSynchronizerAlias? = nil
) {
self.alias = alias
self.level = logLevel
if let bundleName = Bundle.main.bundleIdentifier {
@ -42,37 +46,14 @@ public class OSLogger: Logger {
line: Int = #line
) {
guard level.rawValue == LogLevel.debug.rawValue else { return }
log(level: "DEBUG 🐞", message: message, file: file, function: function, line: line)
}
public func error(
_ message: String,
file: StaticString = #file,
function: StaticString = #function,
line: Int = #line
) {
guard level.rawValue <= LogLevel.error.rawValue else { return }
log(level: "ERROR 💥", message: message, file: file, function: function, line: line)
}
public func warn(
_ message: String,
file: StaticString = #file,
function: StaticString = #function,
line: Int = #line
) {
guard level.rawValue <= LogLevel.warning.rawValue else { return }
log(level: "WARNING ⚠️", message: message, file: file, function: function, line: line)
}
public func event(
_ message: String,
file: StaticString = #file,
function: StaticString = #function,
line: Int = #line
) {
guard level.rawValue <= LogLevel.event.rawValue else { return }
log(level: "EVENT ⏱", message: message, file: file, function: function, line: line)
log(
level: "DEBUG 🐞",
logType: .debug,
message: message,
file: file,
function: function,
line: line
)
}
public func info(
@ -82,11 +63,86 @@ public class OSLogger: Logger {
line: Int = #line
) {
guard level.rawValue <= LogLevel.info.rawValue else { return }
log(level: "INFO ", message: message, file: file, function: function, line: line)
log(
level: "INFO ",
logType: .info,
message: message,
file: file,
function: function,
line: line
)
}
public func event(
_ message: String,
file: StaticString = #file,
function: StaticString = #function,
line: Int = #line
) {
guard level.rawValue <= LogLevel.event.rawValue else { return }
log(
level: "EVENT ⏱",
logType: .default,
message: message,
file: file,
function: function,
line: line
)
}
public func warn(
_ message: String,
file: StaticString = #file,
function: StaticString = #function,
line: Int = #line
) {
guard level.rawValue <= LogLevel.warning.rawValue else { return }
log(
level: "WARNING ⚠️",
logType: .default,
message: message,
file: file,
function: function,
line: line
)
}
public func error(
_ message: String,
file: StaticString = #file,
function: StaticString = #function,
line: Int = #line
) {
guard level.rawValue <= LogLevel.error.rawValue else { return }
log(
level: "ERROR 💥",
logType: .error,
message: message,
file: file,
function: function,
line: line
)
}
public func sync(
_ message: String,
file: StaticString = #file,
function: StaticString = #function,
line: Int = #line
) {
log(
level: "SYNC_METRIC",
logType: .info,
message: message,
file: file,
function: function,
line: line
)
}
private func log(
level: String,
logType: OSLogType,
message: String,
file: StaticString = #file,
function: StaticString = #function,
@ -99,6 +155,7 @@ public class OSLogger: Logger {
os_log(
"[%{public}@] %{public}@ - %{public}@ - Line: %{public}d -> %{public}@",
log: oslog,
type: logType,
level,
fileName,
String(describing: function),

View File

@ -106,7 +106,7 @@ class BlockStreamingTest: ZcashTestCase {
service: service,
downloaderService: BlockDownloaderServiceImpl(service: service, storage: storage),
storage: storage,
metrics: SDKMetrics(),
metrics: SDKMetricsImpl(),
logger: logger
)
mockContainer.mock(type: BlockDownloader.self, isSingleton: true) { _ in blockDownloader }

View File

@ -62,7 +62,7 @@ class CheckpointSourceTests: XCTestCase {
let birthday = source.birthday(for: 1520000)
// swiftlint:disable line_length
let expected = Checkpoint(
height: 1520000,
hash: "0014a50344a6a43b02421286f6db15dad50cea54f3f0858f044ad0f1b845c395",

View File

@ -332,11 +332,15 @@ final class EnhanceActionTests: ZcashTestCase {
private func setupAction(
_ blockEnhancerMock: BlockEnhancerMock = BlockEnhancerMock(),
_ transactionRepositoryMock: TransactionRepositoryMock = TransactionRepositoryMock(),
_ loggerMock: LoggerMock = LoggerMock()
_ loggerMock: LoggerMock = LoggerMock(),
_ sdkMetricsMock: SDKMetricsMock = SDKMetricsMock()
) -> EnhanceAction {
mockContainer.mock(type: BlockEnhancer.self, isSingleton: true) { _ in blockEnhancerMock }
mockContainer.mock(type: TransactionRepository.self, isSingleton: true) { _ in transactionRepositoryMock }
mockContainer.mock(type: Logger.self, isSingleton: true) { _ in loggerMock }
mockContainer.mock(type: SDKMetrics.self, isSingleton: true) { _ in sdkMetricsMock }
loggerMock.syncFileFunctionLineClosure = { _, _, _, _ in }
let config: CompactBlockProcessor.Configuration = .standard(
for: ZcashNetworkBuilder.network(for: .testnet), walletBirthday: 0

View File

@ -27,7 +27,8 @@ final class ProcessSuggestedScanRangesActionTests: ZcashTestCase {
func testProcessSuggestedScanRangesAction_EmptyScanRanges() async throws {
let loggerMock = LoggerMock()
loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in }
loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in }
loggerMock.syncFileFunctionLineClosure = { _, _, _, _ in }
let tupple = setupAction(loggerMock)
await tupple.rustBackendMock.setSuggestScanRangesClosure({ [] })
@ -39,11 +40,6 @@ final class ProcessSuggestedScanRangesActionTests: ZcashTestCase {
let nextContext = try await processSuggestedScanRangesActionAction.run(with: context) { _ in }
XCTAssertFalse(
loggerMock.debugFileFunctionLineCalled,
"logger.debug() is not expected to be called."
)
let acResult = nextContext.checkStateIs(.finished)
XCTAssertTrue(acResult == .true, "Check of state failed with '\(acResult)'")
} catch {
@ -56,8 +52,13 @@ final class ProcessSuggestedScanRangesActionTests: ZcashTestCase {
loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in }
loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in }
loggerMock.syncFileFunctionLineClosure = { _, _, _, _ in }
let tupple = setupAction(loggerMock)
let sdkMetricsMock = SDKMetricsMock()
sdkMetricsMock.actionDetailForClosure = { _, _ in }
let tupple = setupAction(loggerMock, sdkMetricsMock)
await tupple.rustBackendMock.setSuggestScanRangesClosure({ [
ScanRange(range: 0..<10, priority: .chainTip)
] })
@ -83,7 +84,7 @@ final class ProcessSuggestedScanRangesActionTests: ZcashTestCase {
let enhancedValue = nextContextMock.updateLastEnhancedHeightReceivedLastEnhancedHeight
XCTAssertNil(
enhancedValue,
"context.update(updateLastEnhancedHeight:) is expected to reset the value to nil but received \(enhancedValue)"
"context.update(updateLastEnhancedHeight:) is expected to reset the value to nil but received \(String(describing: enhancedValue))"
)
} else {
XCTFail("`nextContext` is not the ActionContextMock")
@ -94,10 +95,10 @@ final class ProcessSuggestedScanRangesActionTests: ZcashTestCase {
"logger.debug() is not expected to be called."
)
if let infoArguments = loggerMock.infoFileFunctionLineReceivedArguments {
XCTAssertFalse(infoArguments.message.contains("Setting the total range for Spend before Sync to"))
if let syncArguments = loggerMock.syncFileFunctionLineReceivedArguments {
XCTAssertFalse(syncArguments.message.contains("Setting the total range for Spend before Sync to"))
} else {
XCTFail("`infoArguments` unavailable.")
XCTFail("`syncArguments` unavailable.")
}
let acResult = nextContext.checkStateIs(.download)
@ -109,7 +110,8 @@ final class ProcessSuggestedScanRangesActionTests: ZcashTestCase {
// swiftlint:disable large_tuple
private func setupAction(
_ loggerMock: LoggerMock = LoggerMock()
_ loggerMock: LoggerMock = LoggerMock(),
_ sdkMetricsMock: SDKMetricsMock = SDKMetricsMock()
) -> (
action: ProcessSuggestedScanRangesAction,
serviceMock: LightWalletServiceMock,
@ -138,6 +140,7 @@ final class ProcessSuggestedScanRangesActionTests: ZcashTestCase {
mockContainer.mock(type: ZcashRustBackendWelding.self, isSingleton: true) { _ in rustBackendMock }
mockContainer.mock(type: LightWalletService.self, isSingleton: true) { _ in serviceMock }
mockContainer.mock(type: Logger.self, isSingleton: true) { _ in loggerMock }
mockContainer.mock(type: SDKMetrics.self, isSingleton: true) { _ in sdkMetricsMock }
return (
action: ProcessSuggestedScanRangesAction(container: mockContainer),

View File

@ -15,6 +15,7 @@ final class ScanActionTests: ZcashTestCase {
let loggerMock = LoggerMock()
loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in }
loggerMock.syncFileFunctionLineClosure = { _, _, _, _ in }
let scanAction = setupAction(blockScannerMock, loggerMock)
@ -85,6 +86,7 @@ final class ScanActionTests: ZcashTestCase {
let loggerMock = LoggerMock()
loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in }
loggerMock.syncFileFunctionLineClosure = { _, _, _, _ in }
let scanAction = setupAction(blockScannerMock, loggerMock)
let syncContext = ActionContextMock.default()
@ -109,6 +111,7 @@ final class ScanActionTests: ZcashTestCase {
let loggerMock = LoggerMock()
loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in }
loggerMock.syncFileFunctionLineClosure = { _, _, _, _ in }
let scanAction = setupAction(blockScannerMock, loggerMock)
let syncContext = ActionContextMock.default()

View File

@ -29,7 +29,7 @@ final class UpdateChainTipActionTests: ZcashTestCase {
let blockDownloaderMock = BlockDownloaderMock()
let latestBlocksDataProvider = LatestBlocksDataProviderMock()
loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in }
loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in }
blockDownloaderMock.stopDownloadClosure = { }
latestBlocksDataProvider.updateClosure = { _ in }
@ -57,7 +57,7 @@ final class UpdateChainTipActionTests: ZcashTestCase {
let blockDownloaderMock = BlockDownloaderMock()
let latestBlocksDataProvider = LatestBlocksDataProviderMock()
loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in }
loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in }
blockDownloaderMock.stopDownloadClosure = { }
latestBlocksDataProvider.updateClosure = { _ in }

View File

@ -27,7 +27,7 @@ final class UpdateSubtreeRootsActionTests: ZcashTestCase {
func testUpdateSubtreeRootsAction_getSubtreeRootsTimeout() async throws {
let loggerMock = LoggerMock()
loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in }
loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in }
let tupple = setupAction(loggerMock)
let updateSubtreeRootsActionAction = tupple.action
@ -59,7 +59,6 @@ final class UpdateSubtreeRootsActionTests: ZcashTestCase {
func testUpdateSubtreeRootsAction_RootsAvailablePutRootsSuccess() async throws {
let loggerMock = LoggerMock()
loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in }
loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in }
let tupple = setupAction(loggerMock)
@ -77,8 +76,6 @@ final class UpdateSubtreeRootsActionTests: ZcashTestCase {
let nextContext = try await updateSubtreeRootsActionAction.run(with: context) { _ in }
XCTAssertFalse(loggerMock.debugFileFunctionLineCalled, "logger.debug() is not expected to be called.")
let acResult = nextContext.checkStateIs(.updateChainTip)
XCTAssertTrue(acResult == .true, "Check of state failed with '\(acResult)'")
} catch {

View File

@ -1,152 +0,0 @@
//
// SDKMetricsTests.swift
//
//
// Created by Lukáš Korba on 19.12.2022.
//
import XCTest
@testable import ZcashLightClientKit
final class SDKMetricsTests: XCTestCase {
func testPushDownloadBlocksReport() throws {
let metrics = SDKMetrics()
metrics.enableMetrics()
metrics.pushProgressReport(
start: Date(timeIntervalSinceReferenceDate: 0.0),
end: Date(timeIntervalSinceReferenceDate: 1.0),
batchSize: 10,
operation: .downloadBlocks
)
XCTAssertTrue(metrics.popBlock(operation: .downloadBlocks)?.count == 1)
if let reports = metrics.reports[.downloadBlocks], let report = reports.first {
XCTAssertEqual(report, SDKMetrics.BlockMetricReport.placeholderA)
} else {
XCTFail("Not expected to fail.")
}
metrics.disableMetrics()
}
func testPopDownloadBlocksReport() throws {
let metrics = SDKMetrics()
metrics.enableMetrics()
metrics.reports[.downloadBlocks] = [SDKMetrics.BlockMetricReport.placeholderA]
if let reports = metrics.popBlock(operation: .downloadBlocks), let report = reports.first {
XCTAssertEqual(report, SDKMetrics.BlockMetricReport.placeholderA)
} else {
XCTFail("Not expected to fail.")
}
metrics.disableMetrics()
}
func testCumulativeSummary() throws {
let metrics = SDKMetrics()
metrics.enableMetrics()
metrics.reports[.downloadBlocks] = [SDKMetrics.BlockMetricReport.placeholderA]
let summary = SDKMetrics.CumulativeSummary(
downloadedBlocksReport: SDKMetrics.ReportSummary(minTime: 1.0, maxTime: 1.0, avgTime: 1.0),
scannedBlocksReport: nil,
enhancementReport: nil,
fetchUTXOsReport: nil,
totalSyncReport: nil
)
XCTAssertEqual(summary, metrics.cumulativeSummary())
metrics.disableMetrics()
}
func testCumulateAndStartNewSet() throws {
let metrics = SDKMetrics()
metrics.enableMetrics()
metrics.reports[.downloadBlocks] = [SDKMetrics.BlockMetricReport.placeholderA]
metrics.cumulateReportsAndStartNewSet()
metrics.reports[.downloadBlocks] = [SDKMetrics.BlockMetricReport.placeholderA]
metrics.cumulateReportsAndStartNewSet()
metrics.reports[.downloadBlocks] = [SDKMetrics.BlockMetricReport.placeholderA]
metrics.cumulateReportsAndStartNewSet()
XCTAssertTrue(metrics.cumulativeSummaries.count == 3)
let summary = SDKMetrics.CumulativeSummary(
downloadedBlocksReport: SDKMetrics.ReportSummary(minTime: 1.0, maxTime: 1.0, avgTime: 1.0),
scannedBlocksReport: nil,
enhancementReport: nil,
fetchUTXOsReport: nil,
totalSyncReport: nil
)
let summaries = [summary, summary, summary]
XCTAssertEqual(summaries, metrics.cumulativeSummaries)
metrics.disableMetrics()
}
func testCumulativeSummaryMinMaxAvg() throws {
let metrics = SDKMetrics()
metrics.enableMetrics()
metrics.reports[.downloadBlocks] = [SDKMetrics.BlockMetricReport.placeholderA, SDKMetrics.BlockMetricReport.placeholderB]
let summary = SDKMetrics.CumulativeSummary(
downloadedBlocksReport: SDKMetrics.ReportSummary(minTime: 1.0, maxTime: 6.0, avgTime: 3.5),
scannedBlocksReport: nil,
enhancementReport: nil,
fetchUTXOsReport: nil,
totalSyncReport: nil
)
XCTAssertEqual(summary, metrics.cumulativeSummary())
metrics.disableMetrics()
}
func testSummarizedCumulativeReports() throws {
let metrics = SDKMetrics()
metrics.enableMetrics()
metrics.reports[.downloadBlocks] = [SDKMetrics.BlockMetricReport.placeholderA]
metrics.cumulateReportsAndStartNewSet()
metrics.reports[.downloadBlocks] = [SDKMetrics.BlockMetricReport.placeholderB]
metrics.cumulateReportsAndStartNewSet()
let summary = SDKMetrics.CumulativeSummary(
downloadedBlocksReport: SDKMetrics.ReportSummary(minTime: 1.0, maxTime: 6.0, avgTime: 3.5),
scannedBlocksReport: nil,
enhancementReport: nil,
fetchUTXOsReport: nil,
totalSyncReport: nil
)
XCTAssertEqual(metrics.summarizedCumulativeReports(), summary)
metrics.disableMetrics()
}
}
extension SDKMetrics.BlockMetricReport {
static let placeholderA = Self(
batchSize: 10,
startTime: Date(timeIntervalSinceReferenceDate: 0.0).timeIntervalSinceReferenceDate,
endTime: Date(timeIntervalSinceReferenceDate: 1.0).timeIntervalSinceReferenceDate
)
static let placeholderB = Self(
batchSize: 10,
startTime: Date(timeIntervalSinceReferenceDate: 0.0).timeIntervalSinceReferenceDate,
endTime: Date(timeIntervalSinceReferenceDate: 6.0).timeIntervalSinceReferenceDate
)
}

View File

@ -80,7 +80,6 @@ class SynchronizerTests: ZcashTestCase {
guard let synchronizer else { fatalError("Synchronizer not initialized.") }
synchronizer.metrics.enableMetrics()
_ = try await synchronizer.prepare(with: seedBytes, walletBirthday: birthday, for: .existingWallet)
let syncSyncedExpectation = XCTestExpectation(description: "synchronizerSynced Expectation")
@ -93,28 +92,6 @@ class SynchronizerTests: ZcashTestCase {
try await synchronizer.start()
await fulfillment(of: [syncSyncedExpectation], timeout: 100)
synchronizer.metrics.cumulateReportsAndStartNewSet()
}
if let cumulativeSummary = synchronizer?.metrics.summarizedCumulativeReports() {
let downloadedBlocksReport = cumulativeSummary.downloadedBlocksReport ?? .zero
let scannedBlocksReport = cumulativeSummary.scannedBlocksReport ?? .zero
let enhancementReport = cumulativeSummary.enhancementReport ?? .zero
let fetchUTXOsReport = cumulativeSummary.fetchUTXOsReport ?? .zero
let totalSyncReport = cumulativeSummary.totalSyncReport ?? .zero
let downloadedBlockAVGTime = downloadedBlocksReport.avgTime
LoggerProxy.debug("""
testHundredBlocksSync() SUMMARY min max avg REPORT:
downloadedBlocksTimes: min: \(downloadedBlocksReport.minTime) max: \(downloadedBlocksReport.maxTime) avg: \(downloadedBlockAVGTime)
scannedBlocksTimes: min: \(scannedBlocksReport.minTime) max: \(scannedBlocksReport.maxTime) avg: \(scannedBlocksReport.avgTime)
enhancementTimes: min: \(enhancementReport.minTime) max: \(enhancementReport.maxTime) avg: \(enhancementReport.avgTime)
fetchUTXOsTimes: min: \(fetchUTXOsReport.minTime) max: \(fetchUTXOsReport.maxTime) avg: \(fetchUTXOsReport.avgTime)
totalSyncTimes: min: \(totalSyncReport.minTime) max: \(totalSyncReport.maxTime) avg: \(totalSyncReport.avgTime)
""")
}
synchronizer?.metrics.disableMetrics()
}
}

View File

@ -28,5 +28,6 @@ extension TransactionRepository { }
extension UTXOFetcher { }
extension ZcashFileManager { }
extension ZcashRustBackendWelding { }
extension SDKMetrics { }
// sourcery:end:

View File

@ -1110,6 +1110,100 @@ class LoggerMock: Logger {
errorFileFunctionLineClosure!(message, file, function, line)
}
// MARK: - sync
var syncFileFunctionLineCallsCount = 0
var syncFileFunctionLineCalled: Bool {
return syncFileFunctionLineCallsCount > 0
}
var syncFileFunctionLineReceivedArguments: (message: String, file: StaticString, function: StaticString, line: Int)?
var syncFileFunctionLineClosure: ((String, StaticString, StaticString, Int) -> Void)?
func sync(_ message: String, file: StaticString, function: StaticString, line: Int) {
syncFileFunctionLineCallsCount += 1
syncFileFunctionLineReceivedArguments = (message: message, file: file, function: function, line: line)
syncFileFunctionLineClosure!(message, file, function, line)
}
}
class SDKMetricsMock: SDKMetrics {
init(
) {
}
// MARK: - cbpStart
var cbpStartCallsCount = 0
var cbpStartCalled: Bool {
return cbpStartCallsCount > 0
}
var cbpStartClosure: (() -> Void)?
func cbpStart() {
cbpStartCallsCount += 1
cbpStartClosure!()
}
// MARK: - actionStart
var actionStartCallsCount = 0
var actionStartCalled: Bool {
return actionStartCallsCount > 0
}
var actionStartReceivedAction: CBPState?
var actionStartClosure: ((CBPState) -> Void)?
func actionStart(_ action: CBPState) {
actionStartCallsCount += 1
actionStartReceivedAction = action
actionStartClosure!(action)
}
// MARK: - actionDetail
var actionDetailForCallsCount = 0
var actionDetailForCalled: Bool {
return actionDetailForCallsCount > 0
}
var actionDetailForReceivedArguments: (detail: String, action: CBPState)?
var actionDetailForClosure: ((String, CBPState) -> Void)?
func actionDetail(_ detail: String, `for` action: CBPState) {
actionDetailForCallsCount += 1
actionDetailForReceivedArguments = (detail: detail, action: action)
actionDetailForClosure!(detail, action)
}
// MARK: - actionStop
var actionStopCallsCount = 0
var actionStopCalled: Bool {
return actionStopCallsCount > 0
}
var actionStopClosure: (() -> Void)?
func actionStop() {
actionStopCallsCount += 1
actionStopClosure!()
}
// MARK: - logCBPOverviewReport
var logCBPOverviewReportCallsCount = 0
var logCBPOverviewReportCalled: Bool {
return logCBPOverviewReportCallsCount > 0
}
var logCBPOverviewReportReceivedLogger: Logger?
var logCBPOverviewReportClosure: ((Logger) -> Void)?
func logCBPOverviewReport(_ logger: Logger) {
logCBPOverviewReportCallsCount += 1
logCBPOverviewReportReceivedLogger = logger
logCBPOverviewReportClosure!(logger)
}
}
class SaplingParametersHandlerMock: SaplingParametersHandler {
@ -1162,10 +1256,6 @@ class SynchronizerMock: Synchronizer {
get { return underlyingEventStream }
}
var underlyingEventStream: AnyPublisher<SynchronizerEvent, Never>!
var metrics: SDKMetrics {
get { return underlyingMetrics }
}
var underlyingMetrics: SDKMetrics!
var transactions: [ZcashTransaction.Overview] {
get async { return underlyingTransactions }
}