Last active
July 31, 2025 15:18
-
-
Save rem1niscence/802dc339fb78bf7ac34dc85eb608050e to your computer and use it in GitHub Desktop.
query non signers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"encoding/base64" | |
"encoding/hex" | |
"encoding/json" | |
"fmt" | |
"io" | |
"maps" | |
"net/http" | |
"os" | |
"sort" | |
"strconv" | |
"sync" | |
) | |
type NonSigner struct { | |
Address string `json:"address"` | |
Counter int `json:"counter"` | |
} | |
type RequestBody struct { | |
Height int `json:"height"` | |
} | |
type AddressCount struct { | |
Address string | |
Count int | |
} | |
type SafeAddressCounter struct { | |
mu sync.Mutex | |
counts map[string]int | |
} | |
func (s *SafeAddressCounter) Add(address string, count int) { | |
s.mu.Lock() | |
defer s.mu.Unlock() | |
s.counts[address] += count | |
} | |
func (s *SafeAddressCounter) GetCounts() map[string]int { | |
s.mu.Lock() | |
defer s.mu.Unlock() | |
result := make(map[string]int) | |
maps.Copy(result, s.counts) | |
return result | |
} | |
func main() { | |
if len(os.Args) != 4 { | |
fmt.Println("Usage: go run main.go <url> <height> <count downwards>") | |
os.Exit(1) | |
} | |
url := os.Args[1] | |
if url == "" { | |
fmt.Println("URL is required") | |
os.Exit(1) | |
} | |
height, err := strconv.Atoi(os.Args[2]) | |
if err != nil { | |
fmt.Printf("Error parsing height: %v\n", err) | |
os.Exit(1) | |
} | |
count, err := strconv.Atoi(os.Args[3]) | |
if err != nil { | |
fmt.Printf("Error parsing count: %v\n", err) | |
os.Exit(1) | |
} | |
addressCounter := &SafeAddressCounter{ | |
counts: make(map[string]int), | |
} | |
fmt.Printf("Querying from height %d for %d blocks in parallel...\n", height, count) | |
var wg sync.WaitGroup | |
const maxConcurrency = 100 | |
semaphore := make(chan struct{}, maxConcurrency) | |
for i := 0; i < count; i++ { | |
wg.Add(1) | |
go func(heightOffset int) { | |
defer wg.Done() | |
// Acquire semaphore | |
semaphore <- struct{}{} | |
defer func() { <-semaphore }() | |
currentHeight := height - heightOffset | |
fmt.Printf("Querying height %d...\n", currentHeight) | |
nonSigners, err := queryNonSigners(url, currentHeight) | |
if err != nil { | |
fmt.Printf("Error querying height %d: %v\n", currentHeight, err) | |
return | |
} | |
for _, ns := range nonSigners { | |
// Convert base64 to hex | |
hexAddress, err := base64ToHex(ns.Address) | |
if err != nil { | |
fmt.Printf("Error converting address %s to hex: %v\n", ns.Address, err) | |
continue | |
} | |
addressCounter.Add(hexAddress, ns.Counter) | |
} | |
}(i) | |
} | |
wg.Wait() | |
addressCounts := addressCounter.GetCounts() | |
var results []AddressCount | |
for addr, count := range addressCounts { | |
results = append(results, AddressCount{Address: addr, Count: count}) | |
} | |
sort.Slice(results, func(i, j int) bool { | |
return results[i].Count > results[j].Count | |
}) | |
fmt.Println("\nNon-signer counts (descending order):") | |
fmt.Println("=====================================") | |
for _, result := range results { | |
fmt.Printf("Address: %s, Count: %d\n", result.Address, result.Count) | |
} | |
} | |
func queryNonSigners(url string, height int) ([]NonSigner, error) { | |
requestBody := RequestBody{Height: height} | |
jsonData, err := json.Marshal(requestBody) | |
if err != nil { | |
return nil, fmt.Errorf("error marshaling request: %v", err) | |
} | |
resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonData)) | |
if err != nil { | |
return nil, fmt.Errorf("error making POST request: %v", err) | |
} | |
defer resp.Body.Close() | |
if resp.StatusCode != http.StatusOK { | |
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode) | |
} | |
body, err := io.ReadAll(resp.Body) | |
if err != nil { | |
return nil, fmt.Errorf("error reading response body: %v", err) | |
} | |
var nonSigners []NonSigner | |
err = json.Unmarshal(body, &nonSigners) | |
if err != nil { | |
return nil, fmt.Errorf("error unmarshaling response: %v", err) | |
} | |
return nonSigners, nil | |
} | |
func base64ToHex(base64Str string) (string, error) { | |
decoded, err := base64.StdEncoding.DecodeString(base64Str) | |
if err != nil { | |
return "", fmt.Errorf("error decoding base64: %v", err) | |
} | |
return hex.EncodeToString(decoded), nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment