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 }