Skip to content

Instantly share code, notes, and snippets.

@rem1niscence
Last active July 31, 2025 15:18
Show Gist options
  • Save rem1niscence/802dc339fb78bf7ac34dc85eb608050e to your computer and use it in GitHub Desktop.
Save rem1niscence/802dc339fb78bf7ac34dc85eb608050e to your computer and use it in GitHub Desktop.
query non signers
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