Skip to content

Commit

Permalink
skywire-cli reward calc (#1668)
Browse files Browse the repository at this point in the history
* add subcommand: skywire-cli reward calc

* fix make check errors

* fix make check errors

* fix make check errors

* fix make check errors

* fix make check errors
  • Loading branch information
0pcom authored Nov 27, 2023
1 parent 7c59949 commit 2683198
Showing 1 changed file with 164 additions and 1 deletion.
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)
}
},
}

0 comments on commit 2683198

Please sign in to comment.