diff --git a/sdk/task/task.go b/sdk/task/task.go index 361756a6..cfa8c4ca 100644 --- a/sdk/task/task.go +++ b/sdk/task/task.go @@ -122,6 +122,7 @@ func (t *BaseTask) filterEligibleSupernodesParallel(parent context.Context, sns // Step 0 — shared state for this pass keep := make([]bool, len(sns)) + rejectionReasons := make([]string, len(sns)) var wg sync.WaitGroup sem := make(chan struct{}, prefilterParallelism) preClients := make(map[string]net.SupernodeClient) @@ -161,6 +162,7 @@ func (t *BaseTask) filterEligibleSupernodesParallel(parent context.Context, sns client, err := clientFactory.CreateClient(probeCtx, sn) if err != nil { // Unable to connect → ineligible; cancel sibling + rejectionReasons[i] = fmt.Sprintf("connection failed: %v", err) cancel() return } @@ -172,12 +174,26 @@ func (t *BaseTask) filterEligibleSupernodesParallel(parent context.Context, sns healthOK = true } else { // Health failed → ineligible; cancel sibling + if err != nil { + rejectionReasons[i] = fmt.Sprintf("health check failed: %v", "") + } else if h == nil { + rejectionReasons[i] = "health check returned nil" + } else { + rejectionReasons[i] = fmt.Sprintf("health status: %v (expected SERVING)", h.Status) + } cancel() return } // (2) One-liner peers>1 gate using Status API to ensure network liveness if st, err := client.GetSupernodeStatus(probeCtx); err != nil || st == nil || st.Network == nil || st.Network.PeersCount <= 1 { healthOK = false + if err != nil { + rejectionReasons[i] = fmt.Sprintf("status check failed: %v", "") + } else if st == nil || st.Network == nil { + rejectionReasons[i] = "status or network info unavailable" + } else { + rejectionReasons[i] = fmt.Sprintf("insufficient peers: %d (need > 1)", st.Network.PeersCount) + } cancel() return } @@ -191,6 +207,14 @@ func (t *BaseTask) filterEligibleSupernodesParallel(parent context.Context, sns balanceOK = true } else { // Insufficient or error → ineligible; cancel sibling + if err != nil { + rejectionReasons[i] = fmt.Sprintf("balance check failed: %v", err) + } else if bal == nil || bal.Balance == nil { + rejectionReasons[i] = "balance info unavailable" + } else { + actualLUME := bal.Balance.Amount.Quo(sdkmath.NewInt(1_000_000)) + rejectionReasons[i] = fmt.Sprintf("insufficient balance: %s LUME (need >= 1 LUME)", actualLUME.String()) + } cancel() } }() @@ -215,7 +239,34 @@ func (t *BaseTask) filterEligibleSupernodesParallel(parent context.Context, sns } wg.Wait() - // Step 2 — build output preserving original order + // Step 2 — log eligibility results + t.logger.Info(parent, "Supernode eligibility check started") + acceptedCount := 0 + rejectedCount := 0 + for i, sn := range sns { + endpoint := sn.GrpcEndpoint + if endpoint == "" { + endpoint = sn.CosmosAddress // fallback to address if endpoint not available + } + + if keep[i] { + t.logger.Debug(parent, "Supernode accepted", "endpoint", endpoint) + acceptedCount++ + } else { + reason := rejectionReasons[i] + if reason == "" { + reason = "unknown reason" + } + t.logger.Debug(parent, "Supernode rejected", "endpoint", endpoint, "reason", reason) + rejectedCount++ + } + } + t.logger.Info(parent, "Supernode eligibility check completed", + "accepted", acceptedCount, + "rejected", rejectedCount, + "total", len(sns)) + + // Step 3 — build output preserving original order out := make(lumera.Supernodes, 0, len(sns)) for i, sn := range sns { if keep[i] { diff --git a/testnet_version_check.sh b/testnet_version_check.sh index e3a53a4a..48073736 100755 --- a/testnet_version_check.sh +++ b/testnet_version_check.sh @@ -8,7 +8,7 @@ set -o pipefail # Usage: ./check_versions.sh (no args) TIMEOUT=10 -API_URL="https://lcd.testnet.lumera.io/LumeraProtocol/lumera/supernode/list_super_nodes?pagination.limit=1000&pagination.count_total=true" +API_URL="https://lcd.testnet.lumera.io/LumeraProtocol/lumera/supernode/v1/list_super_nodes?pagination.limit=1000&pagination.count_total=true" TOTAL_CHECKED=0 UNREACHABLE_COUNT=0