Skip to content

Commit edcb81f

Browse files
7layermagikclaude
andcommitted
Bump solana-snapshot-finder-go to fix histogram bar panic
Updates the snapshot finder dependency to include the fix for negative strings.Repeat in version distribution histogram bars. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 3b64210 commit edcb81f

File tree

3 files changed

+50
-60
lines changed

3 files changed

+50
-60
lines changed

go.mod

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ require (
111111
require (
112112
filippo.io/edwards25519 v1.0.0
113113
github.com/Overclock-Validator/bgls v0.0.0-20250309141600-b7db1bfbf3fa
114-
github.com/Overclock-Validator/solana-snapshot-finder-go v0.0.0-20251229023828-edd283e1db59
114+
github.com/Overclock-Validator/solana-snapshot-finder-go v0.0.0-20260223201452-d8363b514fc0
115115
github.com/Overclock-Validator/wide v0.0.0-20250221123529-f80959d02044
116116
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
117117
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
@@ -145,7 +145,6 @@ require (
145145
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
146146
github.com/modern-go/reflect2 v1.0.2 // indirect
147147
github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 // indirect
148-
github.com/nixberg/chacha-rng-go v0.1.0
149148
github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a
150149
github.com/panjf2000/ants/v2 v2.10.0
151150
github.com/pierrec/lz4/v4 v4.1.22

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ github.com/Overclock-Validator/crypto v0.0.0-20250307094320-aaf52fac5261 h1:Y715
1212
github.com/Overclock-Validator/crypto v0.0.0-20250307094320-aaf52fac5261/go.mod h1:ZhRHOaVg8I1gg0VK4wmqOQPnlgPgKFT9McZ+TCW/hBA=
1313
github.com/Overclock-Validator/gnark-crypto v0.0.0-20250309203346-2a67ed08a105 h1:mP6FWHZ8ddcmbE8UTrVVI2Mi2c24aqX/8p12Vn6zokQ=
1414
github.com/Overclock-Validator/gnark-crypto v0.0.0-20250309203346-2a67ed08a105/go.mod h1:Poczuq3dbt+CwyTKgOjGaEwJOMP7YxQobF7QhgNcguk=
15-
github.com/Overclock-Validator/solana-snapshot-finder-go v0.0.0-20251229023828-edd283e1db59 h1:feitrhIizLqjrve6eKpW7v5MyRmUIEt/tBS/4EQVzMo=
16-
github.com/Overclock-Validator/solana-snapshot-finder-go v0.0.0-20251229023828-edd283e1db59/go.mod h1:5Ta/wyu0gfzgktCaW1N9vjSwM81Dy3tdty9ruJgBm88=
15+
github.com/Overclock-Validator/solana-snapshot-finder-go v0.0.0-20260223201452-d8363b514fc0 h1:elgavEQb8l7Zn3gS3Y+2/98PlUylOWdlM3V1VumQ7mA=
16+
github.com/Overclock-Validator/solana-snapshot-finder-go v0.0.0-20260223201452-d8363b514fc0/go.mod h1:XbqbvMA2NKeosY0w3WdBOpCg2eYJesBjfE4cNt9HSE8=
1717
github.com/Overclock-Validator/wide v0.0.0-20250221123529-f80959d02044 h1:ph9gnWIY116AWT/iCfXoPe9/cn2aWx2uJBuLdf/LyEE=
1818
github.com/Overclock-Validator/wide v0.0.0-20250221123529-f80959d02044/go.mod h1:hEf1+Hyc8cRJzEKo448RtaFGZzpP2RVNrfBTTEvkThs=
1919
github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=

pkg/snapshotdl/snapshotdl.go

Lines changed: 47 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ package snapshotdl
33
import (
44
"context"
55
"fmt"
6+
stdlog "log"
67
"strconv"
78
"strings"
9+
"sync"
810
"time"
911

1012
"github.com/Overclock-Validator/mithril/pkg/mlog"
@@ -13,6 +15,26 @@ import (
1315
"github.com/Overclock-Validator/solana-snapshot-finder-go/pkg/snapshot"
1416
)
1517

18+
// stdlogMu protects global log config changes from racing if multiple
19+
// snapshot flows run concurrently.
20+
var stdlogMu sync.Mutex
21+
22+
// suppressStdlogTimestamps temporarily strips stdlib log flags/prefix so
23+
// snapshot-finder output matches Mithril style. Caller must defer the
24+
// returned restore function.
25+
func suppressStdlogTimestamps() func() {
26+
stdlogMu.Lock()
27+
oldFlags := stdlog.Flags()
28+
oldPrefix := stdlog.Prefix()
29+
stdlog.SetFlags(0)
30+
stdlog.SetPrefix("")
31+
return func() {
32+
stdlog.SetFlags(oldFlags)
33+
stdlog.SetPrefix(oldPrefix)
34+
stdlogMu.Unlock()
35+
}
36+
}
37+
1638
// SnapshotInfo contains details about a selected snapshot source.
1739
// This is returned by GetSnapshotURLWithInfo for display purposes.
1840
type SnapshotInfo struct {
@@ -176,7 +198,6 @@ func (sc SnapshotConfig) toInternalConfig(path string) config.Config {
176198
AllowedNodeVersions: sc.AllowedNodeVersions,
177199
MaxFullSnapshots: sc.MaxFullSnapshots,
178200
SafetyMarginSlots: sc.SafetyMarginSlots,
179-
Quiet: true, // Mithril prints its own summary
180201
}
181202
}
182203

@@ -290,6 +311,7 @@ func DownloadSnapshot(ctx context.Context, rpcEndpoints []string, path string) (
290311
// The returned URL can be passed directly to snapshot processing functions
291312
// which will stream the data from HTTP (no disk download required).
292313
func GetSnapshotURL(ctx context.Context, snapCfg SnapshotConfig) (string, int, int, error) {
314+
defer suppressStdlogTimestamps()()
293315
cfg := snapCfg.toInternalConfig("")
294316

295317
// Step 1: Get reference slot from multiple RPCs for reliability
@@ -317,7 +339,7 @@ func GetSnapshotURL(ctx context.Context, snapCfg SnapshotConfig) (string, int, i
317339

318340
// Step 4: Sort and select best nodes by download speed
319341
// Note: This also populates filter pipeline stats in ProbeStats
320-
bestNodes, _, speedStats := rpc.SortBestNodesWithStats(results, cfg, stats, referenceSlot)
342+
bestNodes, _ := rpc.SortBestNodesWithStats(results, cfg, stats, referenceSlot)
321343
if len(bestNodes) == 0 {
322344
return "", 0, 0, fmt.Errorf("no suitable nodes found with snapshots")
323345
}
@@ -331,8 +353,7 @@ func GetSnapshotURL(ctx context.Context, snapCfg SnapshotConfig) (string, int, i
331353
MinVersion: cfg.MinNodeVersion,
332354
AllowedVersions: cfg.AllowedNodeVersions,
333355
}
334-
stats.PrintNodeDiscoveryReport()
335-
stats.PrintFilterPipeline(filterCfg, speedStats)
356+
stats.PrintReport(filterCfg)
336357
}
337358

338359
// Step 5: Get snapshot URL from best nodes (with configurable fallback)
@@ -399,6 +420,7 @@ func GetSnapshotURL(ctx context.Context, snapCfg SnapshotConfig) (string, int, i
399420
// This is like GetSnapshotURL but returns a SnapshotInfo struct with additional
400421
// details useful for display (node IP, version, speed, age).
401422
func GetSnapshotURLWithInfo(ctx context.Context, snapCfg SnapshotConfig) (*SnapshotInfo, error) {
423+
defer suppressStdlogTimestamps()()
402424
cfg := snapCfg.toInternalConfig("")
403425

404426
// Step 1: Get reference slot from multiple RPCs for reliability
@@ -424,11 +446,6 @@ func GetSnapshotURLWithInfo(ctx context.Context, snapCfg SnapshotConfig) (*Snaps
424446
// This prevents selecting a fast full snapshot that has no compatible incrementals
425447
results, incBaseStats := filterByIncrementalBaseMatch(results)
426448

427-
// Print Node Discovery Report (before speed testing)
428-
if stats != nil {
429-
stats.PrintNodeDiscoveryReport()
430-
}
431-
432449
// Print incremental base match stats
433450
if incBaseStats.totalWithFull > 0 {
434451
mlog.Log.Infof("Incremental base matching: %d/%d full snapshots have compatible incrementals (%d unique base slots)",
@@ -442,49 +459,23 @@ func GetSnapshotURLWithInfo(ctx context.Context, snapCfg SnapshotConfig) (*Snaps
442459
// Step 4: Sort and select best nodes by download speed
443460
// Note: This also populates filter pipeline stats in ProbeStats
444461
mlog.Log.Infof("Testing download speeds (Stage 1 + Stage 2)...")
445-
bestNodes, rankedNodes, speedStats := rpc.SortBestNodesWithStats(results, cfg, stats, referenceSlot)
462+
bestNodes, rankedNodes := rpc.SortBestNodesWithStats(results, cfg, stats, referenceSlot)
446463
if len(bestNodes) == 0 {
447464
return nil, fmt.Errorf("no suitable nodes found with snapshots (check incremental base matching)")
448465
}
449466

450-
// Print Stage 2 candidates as a table (no timestamps)
451-
maxCandidates := 8
452-
if len(rankedNodes) < maxCandidates {
453-
maxCandidates = len(rankedNodes)
454-
}
455-
candidates := make([]rpc.RankedNodeInfo, maxCandidates)
456-
for i := 0; i < maxCandidates; i++ {
457-
rn := rankedNodes[i]
458-
candidates[i] = rpc.RankedNodeInfo{
459-
Rank: i + 1,
460-
RPC: rn.Result.RPC,
461-
Version: rn.Result.Version,
462-
RTTMs: int(rn.Result.Latency), // Latency is already in milliseconds
463-
SpeedS1: rn.S1.MedianMBs,
464-
SpeedS2: rn.S2.MinMBs,
465-
}
466-
}
467-
rpc.PrintStage2CandidatesTable(candidates)
468-
469-
// Print Filter Pipeline with speed test stats (after speed testing, before source selection)
470-
filterCfg := rpc.FilterConfig{
471-
MaxRTTMs: cfg.MaxRTTMs,
472-
FullThreshold: cfg.FullThreshold,
473-
IncThreshold: cfg.IncrementalThreshold,
474-
MinVersion: cfg.MinNodeVersion,
475-
AllowedVersions: cfg.AllowedNodeVersions,
476-
}
467+
// Print statistics report (after filtering is complete)
477468
if stats != nil {
478-
stats.PrintFilterPipeline(filterCfg, speedStats)
469+
filterCfg := rpc.FilterConfig{
470+
MaxRTTMs: cfg.MaxRTTMs,
471+
FullThreshold: cfg.FullThreshold,
472+
IncThreshold: cfg.IncrementalThreshold,
473+
MinVersion: cfg.MinNodeVersion,
474+
AllowedVersions: cfg.AllowedNodeVersions,
475+
}
476+
stats.PrintReport(filterCfg)
479477
}
480478

481-
// Speed test log writing disabled - uncomment to enable
482-
// if speedStats != nil && snapCfg.LogDir != "" {
483-
// if err := speedStats.WriteSpeedTestLog(snapCfg.LogDir, filterCfg); err != nil {
484-
// mlog.Log.Infof("Warning: failed to write speed test log: %v", err)
485-
// }
486-
// }
487-
488479
// Step 5: Get snapshot URL from best nodes (with configurable fallback)
489480
var snapshotURL string
490481
var snapshotSlot int
@@ -574,6 +565,7 @@ func GetSnapshotURLWithInfo(ctx context.Context, snapCfg SnapshotConfig) (*Snaps
574565

575566
// DownloadSnapshotWithConfig is like DownloadSnapshot but accepts custom config
576567
func DownloadSnapshotWithConfig(ctx context.Context, path string, snapCfg SnapshotConfig) (string, int, int, error) {
568+
defer suppressStdlogTimestamps()()
577569
cfg := snapCfg.toInternalConfig(path)
578570

579571
// Step 1: Get reference slot from multiple RPCs for reliability
@@ -601,7 +593,7 @@ func DownloadSnapshotWithConfig(ctx context.Context, path string, snapCfg Snapsh
601593

602594
// Step 4: Sort and select best nodes by download speed
603595
// Note: This also populates filter pipeline stats in ProbeStats
604-
bestNodes, _, speedStats := rpc.SortBestNodesWithStats(results, cfg, stats, referenceSlot)
596+
bestNodes, _ := rpc.SortBestNodesWithStats(results, cfg, stats, referenceSlot)
605597
if len(bestNodes) == 0 {
606598
return "", 0, 0, fmt.Errorf("no suitable nodes found with snapshots")
607599
}
@@ -615,8 +607,7 @@ func DownloadSnapshotWithConfig(ctx context.Context, path string, snapCfg Snapsh
615607
MinVersion: cfg.MinNodeVersion,
616608
AllowedVersions: cfg.AllowedNodeVersions,
617609
}
618-
stats.PrintNodeDiscoveryReport()
619-
stats.PrintFilterPipeline(filterCfg, speedStats)
610+
stats.PrintReport(filterCfg)
620611
}
621612

622613
// Step 5: Download snapshot from best nodes (with configurable fallback)
@@ -694,6 +685,7 @@ func DownloadIncrementalSnapshot(rpcEndpoints []string, path string, referenceSl
694685

695686
// DownloadIncrementalSnapshotWithConfig is like DownloadIncrementalSnapshot but accepts custom config
696687
func DownloadIncrementalSnapshotWithConfig(path string, referenceSlot int, fullSnapshotSlot int, snapCfg SnapshotConfig) (string, int, int, error) {
688+
defer suppressStdlogTimestamps()()
697689
cfg := snapCfg.toInternalConfig(path)
698690
ctx := context.Background()
699691

@@ -720,8 +712,7 @@ func DownloadIncrementalSnapshotWithConfig(path string, referenceSlot int, fullS
720712
MinVersion: cfg.MinNodeVersion,
721713
AllowedVersions: cfg.AllowedNodeVersions,
722714
}
723-
stats.PrintNodeDiscoveryReport()
724-
stats.PrintFilterPipeline(filterCfg, nil)
715+
stats.PrintReport(filterCfg)
725716
}
726717

727718
// Step 3: Filter to only nodes with matching incremental base slot FIRST
@@ -740,7 +731,7 @@ func DownloadIncrementalSnapshotWithConfig(path string, referenceSlot int, fullS
740731
}
741732

742733
// Step 3.5: Apply threshold filtering with two-pass approach
743-
bestNodes, rankedNodes, _ := rpc.SortBestRPCsFilteredBySlot(
734+
bestNodes, rankedNodes := rpc.SortBestRPCsFilteredBySlot(
744735
baseMatchingResults, cfg, stats, int64(fullSnapshotSlot), referenceSlot)
745736

746737
// Pass 2: If no matches, relax incremental threshold
@@ -751,7 +742,7 @@ func DownloadIncrementalSnapshotWithConfig(path string, referenceSlot int, fullS
751742

752743
relaxedCfg := cfg
753744
relaxedCfg.IncrementalThreshold = relaxedThreshold
754-
bestNodes, rankedNodes, _ = rpc.SortBestRPCsFilteredBySlot(
745+
bestNodes, rankedNodes = rpc.SortBestRPCsFilteredBySlot(
755746
baseMatchingResults, relaxedCfg, nil, int64(fullSnapshotSlot), referenceSlot)
756747
}
757748

@@ -867,6 +858,7 @@ func extractFullSnapshotSlot(path string) int {
867858
// b. Speed (faster downloads preferred when end slots are equal)
868859
// 4. Try multiple candidates for resilience (uses MaxSnapshotURLAttempts)
869860
func GetIncrementalSnapshotURL(fullSnapshotURL string, referenceSlot int, fullSnapshotSlot int, snapCfg SnapshotConfig) (string, int, int, error) {
861+
defer suppressStdlogTimestamps()()
870862
cfg := snapCfg.toInternalConfig("")
871863
ctx := context.Background()
872864

@@ -927,8 +919,7 @@ func GetIncrementalSnapshotURL(fullSnapshotURL string, referenceSlot int, fullSn
927919
MinVersion: cfg.MinNodeVersion,
928920
AllowedVersions: cfg.AllowedNodeVersions,
929921
}
930-
stats.PrintNodeDiscoveryReport()
931-
stats.PrintFilterPipeline(filterCfg, nil)
922+
stats.PrintReport(filterCfg)
932923
}
933924

934925
// Step 2.1: Filter to only nodes with matching base slot FIRST (before threshold filtering)
@@ -952,7 +943,7 @@ func GetIncrementalSnapshotURL(fullSnapshotURL string, referenceSlot int, fullSn
952943
var matchingNodes []rpc.RankedNode
953944

954945
// Pass 1: Apply normal incremental threshold
955-
_, rankedNodes, _ := rpc.SortBestRPCsFilteredBySlot(
946+
_, rankedNodes := rpc.SortBestRPCsFilteredBySlot(
956947
baseMatchingResults, cfg, stats, int64(fullSnapshotSlot), referenceSlot)
957948
for _, node := range rankedNodes {
958949
matchingNodes = append(matchingNodes, node)
@@ -968,7 +959,7 @@ func GetIncrementalSnapshotURL(fullSnapshotURL string, referenceSlot int, fullSn
968959
relaxedCfg := cfg
969960
relaxedCfg.IncrementalThreshold = relaxedThreshold
970961

971-
_, rankedNodesRelaxed, _ := rpc.SortBestRPCsFilteredBySlot(
962+
_, rankedNodesRelaxed := rpc.SortBestRPCsFilteredBySlot(
972963
baseMatchingResults, relaxedCfg, nil, int64(fullSnapshotSlot), referenceSlot)
973964
for _, node := range rankedNodesRelaxed {
974965
matchingNodes = append(matchingNodes, node)

0 commit comments

Comments
 (0)