github.com/fozzysec/SiaPrime@v0.0.0-20190612043147-66c8e8d11fe3/cmd/spc/miningpoolcmd.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "sort" 6 7 "github.com/spf13/cobra" 8 "SiaPrime/node/api" 9 ) 10 11 var ( 12 poolCmd = &cobra.Command{ 13 Use: "pool", 14 Short: "Perform pool actions", 15 Long: "Perform pool actions and view pool status.", 16 Run: wrap(poolcmd), 17 } 18 19 poolConfigCmd = &cobra.Command{ 20 Use: "config [setting] [value]", 21 Short: "Read/Modify pool settings", 22 Long: `Read/Modify pool settings. 23 24 Available settings: 25 name: Name you select for your pool 26 poolid Unique string for this pool (needed when sharing database) 27 acceptingshares: Is your pool accepting shares 28 networkport: Stratum port for your pool 29 dbconnection: "internal" or connection string for shared database (pgsql only for now) 30 operatorpercentage: What percentage of the block reward goes to the pool operator 31 operatorwallet: Pool operator sia wallet address <required if percentage is not 0> 32 poolwallet: Operating account for the pool <required> 33 `, 34 Run: wrap(poolconfigcmd), 35 } 36 poolClientsCmd = &cobra.Command{ 37 Use: "clients", 38 Short: "List clients", 39 Long: "List client overview, use pool client <clientname> for details", 40 Run: wrap(poolclientscmd), 41 } 42 43 /* 44 poolClientCmd = &cobra.Command{ 45 Use: "client <clientname>", 46 Short: "Get client details", 47 Long: "Get client details by name", 48 Run: wrap(poolclientcmd), 49 } 50 51 poolBlocksCmd = &cobra.Command{ 52 Use: "blocks", 53 Short: "Get blocks info", 54 Long: "Get list of found blocks", 55 Run: wrap(poolblockscmd), 56 } 57 58 poolBlockCmd = &cobra.Command{ 59 Use: "block <blocknum>", 60 Short: "Get block details", 61 Long: "Get block specific details by block number", 62 Run: wrap(poolblockcmd), 63 } 64 */ 65 ) 66 67 // poolcmd is the handler for the command `siac pool`. 68 // Prints the status of the pool. 69 func poolcmd() { 70 config, err := httpClient.MiningPoolConfigGet() 71 if err != nil { 72 die("Could not get pool config:", err) 73 } 74 fmt.Printf(`Pool status: 75 76 Pool config: 77 Pool Name: %s 78 Pool ID: %d 79 Pool Stratum Port %d 80 DB Connection %s 81 Pool Wallet: %s 82 `, 83 config.Name, config.PoolID, config.NetworkPort, 84 config.DBConnection, config.PoolWallet) 85 } 86 87 // poolconfigcmd is the handler for the command `siac pool config [parameter] [value]` 88 func poolconfigcmd(param, value string) { 89 var err error 90 switch param { 91 case "operatorwallet": 92 case "name": 93 case "operatorpercentage": 94 case "acceptingshares": 95 case "networkport": 96 case "dbconnection": 97 case "poolid": 98 case "poolwallet": 99 default: 100 die("Unknown pool config parameter: ", param) 101 } 102 err = httpClient.MiningPoolConfigPost(param, value) 103 if err != nil { 104 die("Could not update pool settings:", err) 105 106 } 107 } 108 109 func poolclientscmd() { 110 clients, err := httpClient.MiningPoolClientsGet() 111 if err != nil { 112 die("Could not get pool clients:", err) 113 } 114 fmt.Printf("Clients List:\n\n") 115 fmt.Printf("Number of Clients: %d\nNumber of Workers: %d\n\n", clients.NumberOfClients, clients.NumberOfWorkers) 116 fmt.Printf("Client Name \n") 117 fmt.Printf("---------------------------------------------------------------------------- \n") 118 sort.Sort(ByClientName(clients.Clients)) 119 for _, c := range clients.Clients { 120 fmt.Printf("% 76.76s \n", c.ClientName) 121 } 122 } 123 124 /* 125 func poolclientcmd(name string) { 126 client, err := httpClient.MiningPoolClientGet(name) 127 if err != nil { 128 die("Could not get pool client: ", err) 129 } 130 reward := big.NewInt(0) 131 reward.SetString(client.Balance, 10) 132 currency := types.NewCurrency(reward) 133 fmt.Printf("\nClient Name: % 76.76s\nBlocks Mined: % -10d Balance: %s\n\n", client.ClientName, client.BlocksMined, currencyUnits(currency)) 134 fmt.Printf(" Per Current Block\n") 135 fmt.Printf("Worker Name Work Diff Shares Share*Diff Stale(%%) Invalid(%%) Blocks Found Last Share Time\n") 136 fmt.Printf("---------------- -------- ------- --------- -------- -------- -------- ----------------\n") 137 sort.Sort(ByWorkerName(client.Workers)) 138 for _, w := range client.Workers { 139 var stale, invalid float64 140 if w.SharesThisBlock == 0 { 141 stale = 0.0 142 invalid = 0.0 143 } else { 144 stale = float64(w.StaleSharesThisBlock) / float64(w.SharesThisBlock) * 100.0 145 invalid = float64(w.InvalidSharesThisBlock) / float64(w.SharesThisBlock) * 100.0 146 } 147 fmt.Printf("% -16s % 8.3f % 8d % 8d % 8.3f % 8.3f % 8d %v\n", 148 w.WorkerName, w.CurrentDifficulty, w.SharesThisBlock, uint64(w.CumulativeDifficulty), 149 stale, invalid, w.BlocksFound, shareTime(w.LastShareTime)) 150 } 151 152 txs, err := httpClient.MiningPoolTransactionsGet(name) 153 if err != nil { 154 return 155 } 156 fmt.Printf("\nTransactions:\n") 157 fmt.Printf("%-19s %-10s %s\n", "Timestamp", "Change", "Memo") 158 fmt.Printf("------------------- ---------- --------------------------------------------\n") 159 for _, t := range txs { 160 change := big.NewInt(0) 161 change.SetString(t.BalanceChange, 10) 162 currency := types.NewCurrency(change) 163 fmt.Printf("%-19s %-10s %s\n", t.TxTime.Format(time.RFC822), currencyUnits(currency), t.Memo) 164 } 165 } 166 167 func shareTime(t time.Time) string { 168 if t.IsZero() { 169 return " never" 170 } 171 172 if time.Now().Sub(t).Seconds() < 1 { 173 return " now" 174 } 175 176 switch { 177 case time.Now().Sub(t).Hours() > 1: 178 return fmt.Sprintf(" %s", t.Format(time.RFC822)) 179 case time.Now().Sub(t).Minutes() > 1: 180 return fmt.Sprintf(" %.2f minutes ago", time.Now().Sub(t).Minutes()) 181 default: 182 return fmt.Sprintf(" %.2f seconds ago", time.Now().Sub(t).Seconds()) 183 } 184 } 185 186 func poolblockscmd() { 187 blocks, err := httpClient.MiningPoolBlocksGet() 188 if err != nil { 189 die("Could not get pool blocks: ", err) 190 } 191 fmt.Printf("Blocks List:\n") 192 fmt.Printf("%-10s %-10s %-19s %-10s %s\n", "Blocks", "Height", "Timestamp", "Reward", "Status") 193 fmt.Printf("---------- ---------- ------------------- ------ -------------------\n") 194 for _, b := range blocks { 195 reward := big.NewInt(0) 196 reward.SetString(b.BlockReward, 10) 197 currency := types.NewCurrency(reward) 198 fmt.Printf("% 10d % 10d %19s %-10s %s\n", b.BlockNumber, b.BlockHeight, 199 b.BlockTime.Format(time.RFC822), currencyUnits(currency), b.BlockStatus) 200 } 201 } 202 203 func poolblockcmd(name string) { 204 blocks, err := httpClient.MiningPoolBlocksGet() 205 if err != nil { 206 die("Could not get pool blocks: ", err) 207 } 208 var blockID uint64 209 var blocksInfo api.MiningPoolBlocksInfo 210 match := false 211 fmt.Sscanf(name, "%d", &blockID) 212 for _, blocksInfo = range blocks { 213 if blocksInfo.BlockNumber == blockID { 214 match = true 215 break 216 } 217 } 218 block, err := httpClient.MiningPoolBlockGet(name) 219 if err != nil { 220 die("Could not get pool block:", err) 221 } 222 if match == false { 223 fmt.Printf("Current Block\n\n") 224 } else { 225 reward := big.NewInt(0) 226 reward.SetString(blocksInfo.BlockReward, 10) 227 currency := types.NewCurrency(reward) 228 fmt.Printf("%-10s %-10s %-19s %-10s %s\n", "Blocks", "Height", "Timestamp", "Reward", "Status") 229 fmt.Printf("%-10d %-10d %-19s %-10s %s\n\n", blocksInfo.BlockNumber, blocksInfo.BlockHeight, 230 blocksInfo.BlockTime.Format(time.RFC822), currencyUnits(currency), blocksInfo.BlockStatus) 231 } 232 233 fmt.Printf("Client Name Reward %% Block Reward\n") 234 fmt.Printf("---------------------------------------------------------------------------- -------- ------------\n") 235 for _, b := range block { 236 reward := big.NewInt(0) 237 reward.SetString(b.ClientReward, 10) 238 currency := types.NewCurrency(reward) 239 fmt.Printf("%-76.76s %9.2f %12.12s\n", b.ClientName, b.ClientPercentage, currencyUnits(currency)) 240 } 241 } 242 */ 243 244 // ByClientName contains mining pool client info 245 type ByClientName []api.MiningPoolClientInfo 246 247 func (a ByClientName) Len() int { return len(a) } 248 func (a ByClientName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 249 func (a ByClientName) Less(i, j int) bool { return a[i].ClientName < a[j].ClientName } 250 251 // ByWorkerName contains mining pool worker info 252 type ByWorkerName []api.PoolWorkerInfo 253 254 func (a ByWorkerName) Len() int { return len(a) } 255 func (a ByWorkerName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 256 func (a ByWorkerName) Less(i, j int) bool { return a[i].WorkerName < a[j].WorkerName }