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 }