Added estimated POW time tooltip

This commit is contained in:
Biryuzovye Kleshni 2018-07-23 08:01:22 +00:00
parent a27b5e9055
commit 2c7d677ccf
4 changed files with 30 additions and 13 deletions

View File

@ -54,6 +54,7 @@ from network.asyncore_pollchoose import set_rates
import sound
import re
import bitmessage_icons_rc # Loads icon resources
import workprover.utils
try:
@ -1876,11 +1877,17 @@ class MyForm(settingsmixin.SMainWindow):
if status.speed == 0:
self.ui.workProverSpeed.setText("")
self.ui.workProverSpeed.setToolTip("")
else:
self.ui.workProverSpeed.setText(
_translate("MainWindow", "%1 kiH / s").arg("{:.1f}".format(status.speed / 1024))
)
self.ui.workProverSpeed.setToolTip("Difficulty: {}, 80 % completion time: {:.1f} s".format(
status.difficulty,
workprover.utils.estimateMaximumIterationsCount(status.difficulty, .8) / status.speed
))
def rerenderMessagelistFromLabels(self):
for messagelist in (self.ui.tableWidgetInbox, self.ui.tableWidgetInboxChans, self.ui.tableWidgetInboxSubscriptions):
for i in range(messagelist.rowCount()):

View File

@ -21,13 +21,14 @@ class Task(object):
previous = None
next = None
def __init__(self, headlessPayload, TTL, expiryTime, target):
def __init__(self, headlessPayload, TTL, expiryTime, target, difficulty):
self.headlessPayload = headlessPayload
self.TTL = TTL
self.expiryTime = expiryTime
self.target = target
self.difficulty = difficulty
Status = collections.namedtuple("Status", ["solverName", "solverStatus", "speed", "tasksCount"])
Status = collections.namedtuple("Status", ["solverName", "solverStatus", "speed", "tasksCount", "difficulty"])
class WorkProver(threading.Thread):
# Seed must be 32 bytes
@ -81,6 +82,7 @@ class WorkProver(threading.Thread):
self.lastTime = utils.getTimePoint()
self.timedIntervals = collections.deque()
self.speed = 0
self.totalDifficulty = 0
self.tasks = {}
self.currentTaskID = None
@ -94,7 +96,7 @@ class WorkProver(threading.Thread):
if self.solver is not None:
status = self.solver.status
self.statusUpdated(Status(self.solverName, status, self.speed, len(self.tasks)))
self.statusUpdated(Status(self.solverName, status, self.speed, len(self.tasks), self.totalDifficulty))
def setSolver(self, name, configuration):
if name is None and self.solverName is None:
@ -145,11 +147,12 @@ class WorkProver(threading.Thread):
self.notifyStatus()
def addTask(self, ID, headlessPayload, TTL, expiryTime, byteDifficulty, lengthExtension):
target = utils.calculateTarget(8 + 8 + len(headlessPayload), TTL, byteDifficulty, lengthExtension)
target, difficulty = utils.calculateTarget(8 + 8 + len(headlessPayload), TTL, byteDifficulty, lengthExtension)
task = Task(headlessPayload, TTL, expiryTime, target)
task = Task(headlessPayload, TTL, expiryTime, target, difficulty)
self.tasks[ID] = task
self.totalDifficulty += difficulty
if self.currentTaskID is None:
task.previous = ID
@ -163,11 +166,14 @@ class WorkProver(threading.Thread):
self.tasks[task.previous].next = ID
self.tasks[task.next].previous = ID
self.notifyStatus()
def cancelTask(self, ID):
if ID not in self.tasks:
return
task = self.tasks.pop(ID)
self.totalDifficulty -= task.difficulty
if len(self.tasks) == 0:
self.currentTaskID = None
@ -178,6 +184,8 @@ class WorkProver(threading.Thread):
if self.currentTaskID == ID:
self.currentTaskID = task.next
self.notifyStatus()
def nextTask(self):
self.currentTaskID = self.tasks[self.currentTaskID].next

View File

@ -44,6 +44,7 @@ byteDifficulty = 1000
lengthExtension = 1000
target = 0x00000f903320b7f6
difficulty = 1078000
seed = binascii.unhexlify("3941c24a1256660a8f65d962954c406dab7bc449317fa087c4a3f1a3ca7d95fd")
timeout = .5
@ -56,8 +57,8 @@ class TestUtils(unittest.TestCase):
self.assertEqual(utils.calculateDoubleHash(payload), doubleHash)
def testCalculateTarget(self):
self.assertEqual(utils.calculateTarget(1000, 1015, 1000, 1000), 0x00000843bf57fed2)
self.assertEqual(utils.calculateTarget(1000, 1016, 1000, 1000), 0x00000842b4a960c2)
self.assertEqual(utils.calculateTarget(1000, 1015, 1000, 1000), (0x00000843bf57fed2, 2030000))
self.assertEqual(utils.calculateTarget(1000, 1016, 1000, 1000), (0x00000842b4a960c2, 2031000))
def testCheckProof(self):
self.assertFalse(utils.checkProof(nonce, initialHash, 0x000002fe91eba355))
@ -75,8 +76,8 @@ class TestUtils(unittest.TestCase):
utils.time.time = originalTime
def testEstimateMaximumIterationsCount(self):
self.assertEqual(utils.estimateMaximumIterationsCount(0x000fffffffffffff, .1), 512)
self.assertEqual(utils.estimateMaximumIterationsCount(target, .8), 1735168)
self.assertEqual(utils.estimateMaximumIterationsCount(4096, .1), 512)
self.assertEqual(utils.estimateMaximumIterationsCount(difficulty, .8), 1735168)
class TestSolver(unittest.TestCase):
def setUp(self):
@ -135,6 +136,8 @@ class TestWorkProver(unittest.TestCase):
linkID = next(iter(IDs))
for i in xrange(len(IDs)):
self.assertGreaterEqual(self.thread.totalDifficulty, 0)
self.assertIn(linkID, IDs)
IDs.remove(linkID)

View File

@ -19,7 +19,7 @@ def calculateTarget(length, TTL, byteDifficulty, lengthExtension):
difficulty = byteDifficulty * (adjustedLength + timeEquivalent)
return 2 ** 64 / difficulty
return 2 ** 64 / difficulty, difficulty
def checkProof(nonce, initialHash, target):
proof = nonce + initialHash
@ -34,13 +34,12 @@ def checkWorkSufficient(payload, byteDifficulty, lengthExtension):
nonce = payload[: 8]
initialHash = calculateInitialHash(payload[8: ])
target = calculateTarget(len(payload), minimumTTL, byteDifficulty, lengthExtension)
target, difficulty = calculateTarget(len(payload), minimumTTL, byteDifficulty, lengthExtension)
return checkProof(nonce, initialHash, target)
def estimateMaximumIterationsCount(target, probability):
def estimateMaximumIterationsCount(difficulty, probability):
coefficient = -math.log(1 - probability)
difficulty = 2. ** 64 / target
return int(coefficient * difficulty + 255) / 256 * 256