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 }