Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

skywire-cli reward calc #1668

Merged
merged 6 commits into from
Nov 27, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 164 additions & 1 deletion cmd/skywire-cli/commands/reward/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@ package clireward

import (
"fmt"
"log"
"os"
"sort"
"strconv"
"strings"
"time"

"github.com/bitfield/script"
coincipher "github.com/skycoin/skycoin/src/cipher"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
Expand All @@ -29,7 +34,6 @@ var (
)

func init() {

rewardCmd.Flags().SortFlags = false
if defaultRewardAddress == "" {
//default is genesis address for skycoin blockchain ; for testing
Expand Down Expand Up @@ -196,3 +200,162 @@ func readRewardFile(cmdFlags *pflag.FlagSet) {
output := fmt.Sprintf("Reward address file:\n %s\nreward address:\n %s\n", output, dat)
internal.PrintOutput(cmdFlags, output, output)
}

const yearlyTotalRewards int = 408000

var (
yearlyTotal int
surveyPath string
wdate = time.Now().AddDate(0, 0, -1).Format("2006-01-02")
utfile string
disallowArchitectures string
)

type nodeinfo struct {
SkyAddr string `json:"skycoin_address"`
PK string `json:"public_key"`
Arch string `json:"go_arch"`
IPAddr string `json:"ip_address"`
Share float64 `json:"reward_share"`
Reward float64 `json:"reward_amount"`
}

type ipCount struct {
IP string
Count int
}

type rewardData struct {
SkyAddr string
Reward float64
}

func init() {
RootCmd.AddCommand(rewardCalcCmd)
rewardCalcCmd.Flags().SortFlags = false
rewardCalcCmd.Flags().StringVarP(&wdate, "date", "d", wdate, "date for which to calculate reward")
rewardCalcCmd.Flags().StringVarP(&disallowArchitectures, "noarch", "n", "amd64", "disallowed architectures, comma separated")
rewardCalcCmd.Flags().IntVarP(&yearlyTotal, "year", "y", yearlyTotalRewards, "yearly total rewards")
rewardCalcCmd.Flags().StringVarP(&utfile, "utfile", "u", "ut.txt", "uptime tracker data file")
rewardCalcCmd.Flags().StringVarP(&surveyPath, "path", "p", "./log_collecting", "path to the surveys ")
}

var rewardCalcCmd = &cobra.Command{
Use: "calc",
Short: "calculate rewards from uptime data & collected surveys",
Long: `
Collect surveys: skywire-cli log
Fetch uptimes: skywire-cli ut > ut.txt`,
Run: func(cmd *cobra.Command, args []string) {
_, err := os.Stat(surveyPath)
if os.IsNotExist(err) {
log.Fatal("the path to the surveys does not exist\n", err, "\nfetch the surveys with:\n$ skywire-cli log")
}
_, err = os.Stat(utfile)
if os.IsNotExist(err) {
log.Fatal("uptime tracker data file not found\n", err, "\nfetch the uptime tracker data with:\n$ skywire-cli ut > ut.txt")
}

archMap := make(map[string]struct{})
for _, disallowedarch := range strings.Split(disallowArchitectures, ",") {
if disallowedarch != "" {
archMap[disallowedarch] = struct{}{}
}
}
res, _ := script.File(utfile).Match(strings.TrimRight(wdate, "\n")).Column(1).Slice() //nolint
var nodesInfos []nodeinfo
for _, pk := range res {
nodeInfo := fmt.Sprintf("%s/%s/node-info.json", surveyPath, pk)
ip, _ := script.File(nodeInfo).JQ(`."ip.skycoin.com".ip_address`).Replace(" ", "").Replace(`"`, "").String() //nolint
ip = strings.TrimRight(ip, "\n")
sky, _ := script.File(nodeInfo).JQ(".skycoin_address").Replace(" ", "").Replace(`"`, "").String() //nolint
sky = strings.TrimRight(sky, "\n")
arch, _ := script.File(nodeInfo).JQ(".go_arch").Replace(" ", "").Replace(`"`, "").String() //nolint
arch = strings.TrimRight(arch, "\n")
if _, disallowed := archMap[arch]; !disallowed && ip != "" && strings.Count(ip, ".") == 3 && sky != "" {
ni := nodeinfo{
IPAddr: ip,
SkyAddr: sky,
PK: pk,
Arch: arch,
}
nodesInfos = append(nodesInfos, ni)
}
}
daysThisMonth := float64(time.Date(time.Now().Year(), time.Now().Month()+1, 0, 0, 0, 0, 0, time.UTC).Day())
daysThisYear := float64(int(time.Date(time.Now().Year(), 12, 31, 23, 59, 59, 999999999, time.UTC).Sub(time.Date(time.Now().Year(), 1, 1, 0, 0, 0, 0, time.UTC)).Hours()) / 24)
monthReward := (float64(yearlyTotal) / daysThisYear) * daysThisMonth
dayReward := monthReward / daysThisMonth
wdate = strings.ReplaceAll(wdate, " ", "0")
fmt.Printf("date: %s\n", wdate)
fmt.Printf("days this month: %.4f\n", daysThisMonth)
fmt.Printf("days in the year: %.4f\n", daysThisYear)
fmt.Printf("this month's rewards: %.4f\n", monthReward)
fmt.Printf("reward total: %.4f\n", dayReward)

uniqueIP, _ := script.Echo(func() string { //nolint
var inputStr strings.Builder
for _, ni := range nodesInfos {
inputStr.WriteString(fmt.Sprintf("%s\n", ni.IPAddr))
}
return inputStr.String()
}()).Freq().String() //nolint
var ipCounts []ipCount
lines := strings.Split(uniqueIP, "\n")
for _, line := range lines {
if line != "" {
fields := strings.Fields(line)
if len(fields) == 2 {
count, _ := strconv.Atoi(fields[0]) //nolint
ipCounts = append(ipCounts, ipCount{
IP: fields[1],
Count: count,
})
}
}
}
totalValidShares := 0
for _, ipCount := range ipCounts {
if ipCount.Count <= 8 {
totalValidShares += ipCount.Count
} else {
totalValidShares += 8
}
}
fmt.Printf("Total valid shares: %d\n", totalValidShares)

for i, ni := range nodesInfos {
for _, ipCount := range ipCounts {
if ni.IPAddr == ipCount.IP {
if ipCount.Count <= 8 {
nodesInfos[i].Share = 1.0
} else {
nodesInfos[i].Share = 8.0 / float64(ipCount.Count)
}
break
}
}
nodesInfos[i].Reward = nodesInfos[i].Share / float64(totalValidShares) * dayReward
}

fmt.Println("IP, Skycoin Address, Skywire Public Key, Architecture, Reward Shares, Reward $SKY amout")
for _, ni := range nodesInfos {
fmt.Printf("%s, %s, %s, %s, %4f, %4f\n", ni.IPAddr, ni.SkyAddr, ni.PK, ni.Arch, ni.Share, ni.Reward)
}
rewardSumBySkyAddr := make(map[string]float64)
for _, ni := range nodesInfos {
rewardSumBySkyAddr[ni.SkyAddr] += ni.Reward
}
var sortedSkyAddrs []rewardData
for skyAddr, rewardSum := range rewardSumBySkyAddr {
sortedSkyAddrs = append(sortedSkyAddrs, rewardData{SkyAddr: skyAddr, Reward: rewardSum})
}
sort.Slice(sortedSkyAddrs, func(i, j int) bool {
return sortedSkyAddrs[i].Reward > sortedSkyAddrs[j].Reward
})
fmt.Println("Skycoin Address, Reward Amount")
for _, skyAddrReward := range sortedSkyAddrs {
fmt.Printf("%s, %.4f\n", skyAddrReward.SkyAddr, skyAddrReward.Reward)
}
},
}
Loading