Skip to content

resubmit: Add phoenix-like queuesize option & Retry submit support #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 41 additions & 12 deletions BitcoinMiner.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ def __init__(self, device, options):
self.failback_attempt_count = 0
self.pool = None

self.queuesize = self.options.queuesize
self.currentworkpool = None

self.postdata = {'method': 'getwork', 'id': 'json'}
self.connection = None

Expand Down Expand Up @@ -189,16 +192,23 @@ def mine(self):
if self.stop: return
try:
with self.lock:
update = self.update = (self.update or time() - self.lastWork > if_else(self.longPollActive, LONG_POLL_MAX_ASKRATE, self.options.askrate))
update = self.update = (self.update or (self.workQueue.qsize() < self.queuesize - 1) or time() - self.lastWork > if_else(self.longPollActive, LONG_POLL_MAX_ASKRATE, self.options.askrate))
if update:
work = self.getwork()
if self.update:
self.queueWork(work)

retry = []
while not self.resultQueue.empty():
result = self.resultQueue.get(False)
with self.lock:
rv = self.sendResult(result)
if rv is False:
retry.append(result)
if retry:
for result in retry:
self.resultQueue.put(result)

sleep(1)
except Exception:
self.sayLine("Unexpected error:")
Expand Down Expand Up @@ -227,14 +237,17 @@ def sendResult(self, result):
d = ''.join([d[:136], pack('I', long(result['data'][1])).encode('hex'), d[144:152], pack('I', long(result['output'][i])).encode('hex'), d[160:]])
hashid = pack('I', long(h[6])).encode('hex')
accepted = self.getwork(d)
if accepted != None:
if accepted != None and accepted is not False:
self.blockFound(hashid, accepted)
self.shareCount[if_else(accepted, 1, 0)] += 1
elif accepted is False:
self.sayLine('%s, %s', (hashid, 'ERROR (will resend)'))
return False

def connect(self, host, timeout):
if self.proto == 'https':
return httplib.HTTPSConnection(self.host, strict=True, timeout=timeout)
return httplib.HTTPConnection(self.host, strict=True, timeout=timeout)
def connect(self, host, timeout, proto='http'):
if proto == 'https':
return httplib.HTTPSConnection(host, strict=True, timeout=timeout)
return httplib.HTTPConnection(host, strict=True, timeout=timeout)

def getwork(self, data=None):
save_pool = None
Expand All @@ -247,7 +260,7 @@ def getwork(self, data=None):
self.sayLine("Attempting to fail back to primary pool")
self.failback_getwork_count += 1
if not self.connection:
self.connection = self.connect(self.host, TIMEOUT)
self.connection = self.connect(self.host, TIMEOUT, self.proto)
if data is None:
self.getworkCount += 1
self.postdata['params'] = if_else(data, [data], [])
Expand Down Expand Up @@ -281,6 +294,7 @@ def getwork(self, data=None):
pool = self.servers[self.backup_pool_index]
self.backup_pool_index += 1
self.setpool(pool)
return False

def setpool(self, pool):
self.pool = pool
Expand All @@ -290,6 +304,11 @@ def setpool(self, pool):
self.sayLine('Setting pool %s @ %s', (user, host))
self.headers = {"User-Agent": USER_AGENT, "Authorization": 'Basic ' + b64encode('%s:%s' % (user, pwd))}
self.connection = None
with self.lock:
while not self.resultQueue.empty():
self.resultQueue.get(False)
while not self.workQueue.empty():
self.workQueue.get(False)

def request(self, connection, url, headers, data=None):
result = response = None
Expand All @@ -309,7 +328,10 @@ def request(self, connection, url, headers, data=None):
self.longPollURL = response.getheader('X-Long-Polling', '')
self.updateTime = response.getheader('X-Roll-NTime', '')
result = loads(response.read())
if result['error']: raise RPCError(result['error']['message'])
if result['error']:
if result['error'].has_key('message'):
raise RPCError(result['error']['message'])
else: raise RPCError(result['error'])
return (connection, result)
finally:
if not result or not response or (response.version == 10 and response.getheader('connection', '') != 'keep-alive') or response.getheader('connection', '') == 'close':
Expand All @@ -332,8 +354,8 @@ def longPollThread(self):
if url == '': url = '/'
try:
if not connection:
connection = self.connect(host, LONG_POLL_TIMEOUT)
self.sayLine("LP connected to %s", host)
connection = self.connect(host, LONG_POLL_TIMEOUT, parsedUrl.scheme)
self.sayLine("LP connected to %s%s", (host, url))
self.longPollActive = True
(connection, result) = self.request(connection, url, self.headers)
self.longPollActive = False
Expand Down Expand Up @@ -367,12 +389,13 @@ def miningThread(self):
while True:
sleep(self.options.frameSleep)
if self.stop: return
if (not work) or (not self.workQueue.empty()):
if not work:
try:
work = self.workQueue.get(True, 1)
except Empty: continue
else:
if not work: continue
self.currentworkpool = self.pool

noncesLeft = self.hashspace
data = np.array(unpack('IIIIIIIIIIIIIIII', work['data'][128:].decode('hex')), dtype=np.uint32)
Expand All @@ -381,6 +404,12 @@ def miningThread(self):
targetQ= int(work['target'], 16) / 2**224
state2 = partial(state, data, f)
calculateF(state, data, f, state2)
if self.lastBlock != work['data'][48:56]:
work = None
continue
if self.currentworkpool != self.pool:
work = None
continue

self.miner.search( queue, (globalThreads, ), (self.options.worksize, ),
state[0], state[1], state[2], state[3], state[4], state[5], state[6], state[7],
Expand Down Expand Up @@ -439,7 +468,7 @@ def miningThread(self):
self.update = True
noncesLeft += 0xFFFFFFFFFFFF
elif 0xFFFFFFFFFFF < noncesLeft < 0xFFFFFFFFFFFF:
self.sayLine('warning: job finished, miner is idle')
if self.workQueue.empty(): self.sayLine('warning: job finished, miner is idle')
work = None
elif now - lastNTime > 1:
data[1] = bytereverse(bytereverse(data[1]) + 1)
Expand Down
1 change: 1 addition & 0 deletions poclbm.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
parser.add_option('--failback', dest='failback', default=2, help='attempt to fail back to the primary pool every N getworks, default 2', type='int')
parser.add_option('--verbose', dest='verbose', action='store_true', help='verbose output, suitable for redirection to log file')
parser.add_option('--platform', dest='platform', default=-1, help='use platform by id', type='int')
parser.add_option('--queuesize', dest='queuesize', default=1, help='the size of work queue, default 1', type='int')
(options, args) = parser.parse_args()

platforms = cl.get_platforms()
Expand Down