You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Obviously, the current calculation for Mina is incorrect because NC = Total active validators, as observed here:
I inspected the logic and causes of issues in calculation in mina.go and there are several which I addressed in the code below:
Added totalStake Calculation:
var totalStake float64 was added to accumulate the sum of all stake percentages.
Adjusted Loop Exit Condition:
Changed from if len(response.Content) == 0 to if len(response.Content) == 0 || pageNo >= response.TotalPages to ensure it stops correctly.
Sorting Updated:
Original sorting and reversing were replaced with a direct descending order sort using sort.Slice.
Threshold Calculation Modified:
Adjusted thresholdPercent to be dynamically calculated as totalStake * 0.50 to match the 50% of the total stake.
Changes in calcNakamotoCoefficientForMina:
Modified to take totalStake as a parameter and calculate the correct threshold dynamically.
I suggest you correct the mina.go code in the following way so that calculation is accurate:
package chains
import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"log"
"net/http"
"sort"
"time"
)
type MinaResponse struct {
Content []struct {
Pk string `json:"pk"`
Name string `json:"name"`
StakePercent float64 `json:"stakePercent"`
CanonicalBlock int `json:"canonicalBlock"`
SocialTelegram string `json:"socialTelegram"`
}
TotalPages int `json:"totalPages"`
TotalElements int `json:"totalElements"`
}
type MinaErrorResponse struct {
Id int `json:"id"`
Jsonrpc string `json:"jsonrpc"`
Error string `json:"error"`
}
func reverse(numbers []float64) {
for i, j := 0, len(numbers)-1; i < j; i, j = i+1, j-1 {
numbers[i], numbers[j] = numbers[j], numbers[i]
}
}
func Mina() (int, error) {
var votingPowers []float64
var totalStake float64 // Added: variable to track the total stake
pageNo, entriesPerPage := 0, 50
url := ""
ctx, cancelFunc := context.WithTimeout(context.Background(), 10*time.Second)
defer cancelFunc()
for true {
// Check the most active url in the network logs here: https://mina.staketab.com/validators/stake
// Sometimes it changes, like once it changed from mina.staketab.com to t-mina.staketab.com
// Once, it was https://mina.staketab.com:8181/api/validator/all/
url = fmt.Sprintf("https://minascan.io/mainnet/api/api/validators/?page=%d&size=%d&sortBy=amount_staked&type=active&findStr=&orderBy=DESC", pageNo, entriesPerPage)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
log.Println(err)
return 0, errors.New("create get request for mina")
}
resp, err := new(http.Client).Do(req)
if err != nil {
log.Println(err)
return 0, errors.New("get request unsuccessful")
}
defer resp.Body.Close() // Moved this line to ensure the body is always closed, even if an error occurs
body, err := io.ReadAll(resp.Body)
if err != nil {
return 0, err
}
var response MinaResponse
err = json.Unmarshal(body, &response)
if err != nil {
return 0, err
}
// Original code:
// if len(response.Content) == 0 {
// break
// }
// Updated condition: Break if no content or all pages have been fetched
if len(response.Content) == 0 || pageNo >= response.TotalPages {
break
}
// loop through the validators voting powers
for _, ele := range response.Content {
votingPowers = append(votingPowers, ele.StakePercent)
totalStake += ele.StakePercent // Added: Accumulate total stake of all validators
}
// increment counters
pageNo += 1
}
// Original sorting and reversal:
// sort.Float64s(votingPowers)
// reverse(votingPowers)
// Updated sorting: Sort voting powers in descending order
sort.Slice(votingPowers, func(i, j int) bool {
return votingPowers[i] > votingPowers[j]
})
// now we're ready to calculate the Nakamoto coefficient
nakamotoCoefficient := calcNakamotoCoefficientForMina(votingPowers, totalStake) // Modified to pass totalStake
fmt.Println("The Nakamoto coefficient for Mina is", nakamotoCoefficient)
return nakamotoCoefficient, nil
}
func calcNakamotoCoefficientForMina(votingPowers []float64, totalStake float64) int { // Modified to accept totalStake
// Original threshold calculation:
// var cumulativePercent, thresholdPercent float64 = 0.00, 50.00
// Updated to calculate the actual 50% threshold based on total stake
var cumulativePercent float64 = 0.00
thresholdPercent := totalStake * 0.50 // Calculate 50% threshold dynamically based on total stake
nakamotoCoefficient := 0
for _, vpp := range votingPowers {
// since this is the actual voting percentage, no need to multiply with 100
cumulativePercent += vpp
nakamotoCoefficient += 1
// Check if cumulative voting power exceeds 50% of total stake
if cumulativePercent >= thresholdPercent {
break
}
}
return nakamotoCoefficient
}
Local test of calculation using the above code:
The text was updated successfully, but these errors were encountered:
Hi there,
Obviously, the current calculation for Mina is incorrect because NC = Total active validators, as observed here:
I inspected the logic and causes of issues in calculation in
mina.go
and there are several which I addressed in the code below:var totalStake float64 was added to accumulate the sum of all stake percentages.
Changed from if len(response.Content) == 0 to if len(response.Content) == 0 || pageNo >= response.TotalPages to ensure it stops correctly.
Original sorting and reversing were replaced with a direct descending order sort using sort.Slice.
Adjusted thresholdPercent to be dynamically calculated as totalStake * 0.50 to match the 50% of the total stake.
Changes in calcNakamotoCoefficientForMina:
I suggest you correct the
mina.go
code in the following way so that calculation is accurate:Local test of calculation using the above code:
The text was updated successfully, but these errors were encountered: