1 from stratum import settings
4 log = stratum.logger.get_logger('BasicShareLimiter')
7 dbi = DBInterface.DBInterface()
8 dbi.clear_worker_diff()
10 from twisted.internet import defer
11 from mining.interfaces import Interfaces
14 ''' This is just a customized ring buffer '''
16 def __init__(self, size_max):
23 if len(self.data) == self.max:
25 self.__class__ = SpeedBufferFull
27 return sum(self.data) / self.cur
36 class SpeedBufferFull:
37 def __init__(self, n):
38 raise "you should use SpeedBuffer"
40 self.data[self.cur] = x
41 self.cur = (self.cur + 1) % self.max
43 return sum(self.data) / self.max
49 self.__class__ = SpeedBuffer
53 class BasicShareLimiter(object):
55 self.worker_stats = {}
56 self.target = settings.VDIFF_TARGET
57 self.retarget = settings.VDIFF_RETARGET
58 self.variance = self.target * (float(settings.VDIFF_VARIANCE_PERCENT) / float(100))
59 self.tmin = self.target - self.variance
60 self.tmax = self.target + self.variance
61 self.buffersize = self.retarget / self.target * 4
62 # TODO: trim the hash of inactive workers
64 def submit(self, connection_ref, job_id, current_difficulty, timestamp, worker_name):
66 # Init the stats for this worker if it isn't set.
67 if worker_name not in self.worker_stats or self.worker_stats[worker_name]['last_ts'] < ts - settings.DB_USERCACHE_TIME :
68 self.worker_stats[worker_name] = {'last_rtc': (ts - self.retarget / 2), 'last_ts': ts, 'buffer': SpeedBuffer(self.buffersize) }
69 dbi.update_worker_diff(worker_name, settings.POOL_TARGET)
72 # Standard share update of data
73 self.worker_stats[worker_name]['buffer'].append(ts - self.worker_stats[worker_name]['last_ts'])
74 self.worker_stats[worker_name]['last_ts'] = ts
75 # Do We retarget? If not, we're done.
76 if ts - self.worker_stats[worker_name]['last_rtc'] < self.retarget and self.worker_stats[worker_name]['buffer'].size() > 0:
79 # Set up and log our check
80 self.worker_stats[worker_name]['last_rtc'] = ts
81 avg = self.worker_stats[worker_name]['buffer'].avg()
82 log.info("Checking Retarget for %s (%i) avg. %i target %i+-%i" % (worker_name, current_difficulty, avg,
83 self.target, self.variance))
85 log.info("Reseting avg = 1 since it's SOOO low")
88 # Figure out our Delta-Diff
89 ddiff = int((float(current_difficulty) * (float(self.target) / float(avg))) - current_difficulty)
90 if (avg > self.tmax and current_difficulty > settings.POOL_TARGET):
91 # For fractional -0.1 ddiff's just drop by 1
94 # Don't drop below POOL_TARGET
95 if (ddiff + current_difficulty) < settings.POOL_TARGET:
96 ddiff = settings.POOL_TARGET - current_difficulty
98 # For fractional 0.1 ddiff's just up by 1
101 # Don't go above BITCOIN_DIFF
103 else: # If we are here, then we should not be retargeting.
106 # At this point we are retargeting this worker
107 new_diff = current_difficulty + ddiff
108 log.info("Retarget for %s %i old: %i new: %i" % (worker_name, ddiff, current_difficulty, new_diff))
110 self.worker_stats[worker_name]['buffer'].clear()
111 session = connection_ref().get_session()
112 session['prev_diff'] = session['difficulty']
113 session['prev_jobid'] = job_id
114 session['difficulty'] = new_diff
115 connection_ref().rpc('mining.set_difficulty', [new_diff, ], is_notification=True)
116 dbi.update_worker_diff(worker_name, new_diff)