github.com/fozzysec/SiaPrime@v0.0.0-20190612043147-66c8e8d11fe3/modules/miningpool/worker.go (about)

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