gitlab.com/SiaPrime/SiaPrime@v1.4.1/modules/miningpool/worker.go (about)

     1  package pool
     2  
     3  import (
     4  	"path/filepath"
     5  	"time"
     6  
     7  	"github.com/sasha-s/go-deadlock"
     8  
     9  	"gitlab.com/SiaPrime/SiaPrime/persist"
    10  )
    11  
    12  // A WorkerRecord is used to track worker information in memory
    13  type WorkerRecord struct {
    14  	name            string
    15  	workerID        int64
    16  	shareDifficulty float64
    17  	parent          *Client
    18  }
    19  
    20  // A Worker is an instance of one miner.  A Client often represents a user and the
    21  // worker represents a single miner.  There is a one to many client worker relationship
    22  type Worker struct {
    23  	mu deadlock.RWMutex
    24  	wr WorkerRecord
    25  	s  *Session
    26  	// utility
    27  	log *persist.Logger
    28  }
    29  
    30  func newWorker(c *Client, name string, s *Session) (*Worker, error) {
    31  	p := c.Pool()
    32  	// id := p.newStratumID()
    33  	w := &Worker{
    34  		wr: WorkerRecord{
    35  			// workerID: id(),
    36  			name:   name,
    37  			parent: c,
    38  		},
    39  		s: s,
    40  	}
    41  
    42  	var err error
    43  
    44  	// Create the perist directory if it does not yet exist.
    45  	dirname := filepath.Join(p.persistDir, "clients", c.Name())
    46  	err = p.dependencies.mkdirAll(dirname, 0700)
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	// Initialize the logger, and set up the stop call that will close the
    52  	// logger.
    53  	w.log, err = p.dependencies.newLogger(filepath.Join(dirname, name+".log"))
    54  
    55  	return w, err
    56  }
    57  
    58  func (w *Worker) printID() string {
    59  	w.mu.RLock()
    60  	defer w.mu.RUnlock()
    61  
    62  	return ssPrintID(w.wr.workerID)
    63  }
    64  
    65  // Name return the worker's name, typically a wallet address
    66  func (w *Worker) Name() string {
    67  	w.mu.RLock()
    68  	defer w.mu.RUnlock()
    69  
    70  	return w.wr.name
    71  }
    72  
    73  // SetName sets the worker's name
    74  func (w *Worker) SetName(n string) {
    75  	w.mu.Lock()
    76  	defer w.mu.Unlock()
    77  	w.wr.name = n
    78  }
    79  
    80  // Parent returns the worker's client
    81  func (w *Worker) Parent() *Client {
    82  	w.mu.RLock()
    83  	defer w.mu.RUnlock()
    84  
    85  	return w.wr.parent
    86  }
    87  
    88  // SetParent sets the worker's client
    89  func (w *Worker) SetParent(p *Client) {
    90  	w.mu.Lock()
    91  	defer w.mu.Unlock()
    92  	w.wr.parent = p
    93  }
    94  
    95  // Session returns the tcp session associated with the worker
    96  func (w *Worker) Session() *Session {
    97  	w.mu.RLock()
    98  	defer w.mu.RUnlock()
    99  
   100  	return w.s
   101  }
   102  
   103  // SetSession sets the tcp session associated with the worker
   104  func (w *Worker) SetSession(s *Session) {
   105  	w.mu.Lock()
   106  	defer w.mu.Unlock()
   107  	w.s = s
   108  }
   109  
   110  // IncrementShares creates a new share according to current session difficulty
   111  // for the worker to work on
   112  func (w *Worker) IncrementShares(sessionDifficulty float64, reward float64) {
   113  	p := w.s.Client.pool
   114  	cbid := p.cs.CurrentBlock().ID()
   115  	blockTarget, _ := p.cs.ChildTarget(cbid)
   116  	blockDifficulty, _ := blockTarget.Difficulty().Uint64()
   117  
   118  	sessionTarget, _ := difficultyToTarget(sessionDifficulty)
   119  	siaSessionDifficulty, _ := sessionTarget.Difficulty().Uint64()
   120  	shareRatio := caculateRewardRatio(sessionTarget.Difficulty().Big(), blockTarget.Difficulty().Big())
   121  	shareReward := shareRatio * reward
   122  	// w.log.Printf("shareRatio: %f, shareReward: %f", shareRatio, shareReward)
   123  
   124  	share := &Share{
   125  		userid:          w.Parent().cr.clientID,
   126  		workerid:        w.wr.workerID,
   127  		height:          int64(p.cs.Height()) + 1,
   128  		valid:           true,
   129  		difficulty:      sessionDifficulty,
   130  		shareDifficulty: float64(siaSessionDifficulty),
   131  		reward:          reward,
   132  		blockDifficulty: blockDifficulty,
   133  		shareReward:     shareReward,
   134  		time:            time.Now(),
   135  	}
   136  
   137  	w.s.Shift().IncrementShares(share)
   138  }
   139  
   140  // IncrementInvalidShares adds a record of an invalid share submission
   141  func (w *Worker) IncrementInvalidShares() {
   142  	w.s.Shift().IncrementInvalid()
   143  }
   144  
   145  // SetLastShareTime specifies the last time a share was submitted during the
   146  // current shift
   147  func (w *Worker) SetLastShareTime(t time.Time) {
   148  	w.s.Shift().SetLastShareTime(t)
   149  }
   150  
   151  // LastShareTime returns the last time a share was submitted during the
   152  // current shift
   153  func (w *Worker) LastShareTime() time.Time {
   154  	return w.s.Shift().LastShareTime()
   155  }
   156  
   157  // CurrentDifficulty returns the average difficulty of all instances of this worker
   158  func (w *Worker) CurrentDifficulty() float64 {
   159  	pool := w.wr.parent.Pool()
   160  	d := pool.dispatcher
   161  	d.mu.Lock()
   162  	defer d.mu.Unlock()
   163  	workerCount := uint64(0)
   164  	currentDiff := float64(0.0)
   165  	for _, h := range d.handlers {
   166  		if h.s.Client != nil && h.s.Client.Name() == w.Parent().Name() && h.s.CurrentWorker.Name() == w.Name() {
   167  			currentDiff += h.s.CurrentDifficulty()
   168  			workerCount++
   169  		}
   170  	}
   171  	if workerCount == 0 {
   172  		return 0.0
   173  	}
   174  	return currentDiff / float64(workerCount)
   175  }
   176  
   177  // Online checks if the worker has a tcp session associated with it
   178  func (w *Worker) Online() bool {
   179  	return w.s != nil
   180  }