New POW calculation module #1284
|
@ -25,6 +25,7 @@ import state
|
||||||
import tr
|
import tr
|
||||||
from debug import logger
|
from debug import logger
|
||||||
import l10n
|
import l10n
|
||||||
|
import workprover.utils
|
||||||
|
|
||||||
|
|
||||||
class objectProcessor(threading.Thread):
|
class objectProcessor(threading.Thread):
|
||||||
|
@ -610,13 +611,13 @@ class objectProcessor(threading.Thread):
|
||||||
and not BMConfigParser().has_section(toAddress):
|
and not BMConfigParser().has_section(toAddress):
|
||||||
# If I'm not friendly with this person:
|
# If I'm not friendly with this person:
|
||||||
if not shared.isAddressInMyAddressBookSubscriptionsListOrWhitelist(fromAddress):
|
if not shared.isAddressInMyAddressBookSubscriptionsListOrWhitelist(fromAddress):
|
||||||
requiredNonceTrialsPerByte = BMConfigParser().getint(
|
byteDifficulty = BMConfigParser().getint(toAddress, "noncetrialsperbyte")
|
||||||
toAddress, 'noncetrialsperbyte')
|
lengthExtension = BMConfigParser().getint(toAddress, "payloadlengthextrabytes")
|
||||||
requiredPayloadLengthExtraBytes = BMConfigParser().getint(
|
|
||||||
toAddress, 'payloadlengthextrabytes')
|
byteDifficulty = max(defaults.networkDefaultProofOfWorkNonceTrialsPerByte, byteDifficulty)
|
||||||
if not protocol.isProofOfWorkSufficient(
|
lengthExtension = max(defaults.networkDefaultPayloadLengthExtraBytes, lengthExtension)
|
||||||
data, requiredNonceTrialsPerByte,
|
|
||||||
requiredPayloadLengthExtraBytes):
|
if not workprover.utils.checkWorkSufficient(data, byteDifficulty, lengthExtension):
|
||||||
logger.info(
|
logger.info(
|
||||||
'Proof of work in msg is insufficient only because'
|
'Proof of work in msg is insufficient only because'
|
||||||
' it does not meet our higher requirement.')
|
' it does not meet our higher requirement.')
|
||||||
|
|
|
@ -56,8 +56,6 @@ def signal_handler(signal, frame):
|
||||||
# on Windows this isn't triggered, but it's fine,
|
# on Windows this isn't triggered, but it's fine,
|
||||||
# it has its own process termination thing
|
# it has its own process termination thing
|
||||||
raise SystemExit
|
raise SystemExit
|
||||||
if "PoolWorker" in process.name:
|
|
||||||
raise SystemExit
|
|
||||||
if process.name == "ForkingSolver":
|
if process.name == "ForkingSolver":
|
||||||
return
|
return
|
||||||
if threading.current_thread().name not in ("PyBitmessage", "MainThread"):
|
if threading.current_thread().name not in ("PyBitmessage", "MainThread"):
|
||||||
|
|
|
@ -7,6 +7,8 @@ from inventory import Inventory
|
||||||
from network.dandelion import Dandelion
|
from network.dandelion import Dandelion
|
||||||
import protocol
|
import protocol
|
||||||
import state
|
import state
|
||||||
|
import workprover.utils
|
||||||
|
import defaults
|
||||||
|
|
||||||
class BMObjectInsufficientPOWError(Exception):
|
class BMObjectInsufficientPOWError(Exception):
|
||||||
errorCodes = ("Insufficient proof of work")
|
errorCodes = ("Insufficient proof of work")
|
||||||
|
@ -52,7 +54,11 @@ class BMObject(object):
|
||||||
|
|
||||||
def checkProofOfWorkSufficient(self):
|
def checkProofOfWorkSufficient(self):
|
||||||
# Let us check to make sure that the proof of work is sufficient.
|
# Let us check to make sure that the proof of work is sufficient.
|
||||||
if not protocol.isProofOfWorkSufficient(self.data):
|
if not workprover.utils.checkWorkSufficient(
|
||||||
|
self.data,
|
||||||
|
defaults.networkDefaultProofOfWorkNonceTrialsPerByte,
|
||||||
|
defaults.networkDefaultPayloadLengthExtraBytes
|
||||||
|
):
|
||||||
logger.info('Proof of work is insufficient.')
|
logger.info('Proof of work is insufficient.')
|
||||||
raise BMObjectInsufficientPOWError()
|
raise BMObjectInsufficientPOWError()
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ from helper_sql import sqlExecute
|
||||||
from version import softwareVersion
|
from version import softwareVersion
|
||||||
import inventory
|
import inventory
|
||||||
import queues
|
import queues
|
||||||
|
import workprover.utils
|
||||||
|
|
||||||
|
|
||||||
# Service flags
|
# Service flags
|
||||||
|
@ -187,35 +188,6 @@ def checkSocksIP(host):
|
||||||
state.socksIP = BMConfigParser().get("bitmessagesettings", "sockshostname")
|
state.socksIP = BMConfigParser().get("bitmessagesettings", "sockshostname")
|
||||||
return state.socksIP == host
|
return state.socksIP == host
|
||||||
|
|
||||||
def isProofOfWorkSufficient(data,
|
|
||||||
nonceTrialsPerByte=0,
|
|
||||||
payloadLengthExtraBytes=0,
|
|
||||||
recvTime=0):
|
|
||||||
"""
|
|
||||||
Validate an object's Proof of Work using method described in:
|
|
||||||
https://bitmessage.org/wiki/Proof_of_work
|
|
||||||
Arguments:
|
|
||||||
int nonceTrialsPerByte (default: from default.py)
|
|
||||||
int payloadLengthExtraBytes (default: from default.py)
|
|
||||||
float recvTime (optional) UNIX epoch time when object was
|
|
||||||
received from the network (default: current system time)
|
|
||||||
Returns:
|
|
||||||
True if PoW valid and sufficient, False in all other cases
|
|
||||||
"""
|
|
||||||
if nonceTrialsPerByte < defaults.networkDefaultProofOfWorkNonceTrialsPerByte:
|
|
||||||
nonceTrialsPerByte = defaults.networkDefaultProofOfWorkNonceTrialsPerByte
|
|
||||||
if payloadLengthExtraBytes < defaults.networkDefaultPayloadLengthExtraBytes:
|
|
||||||
payloadLengthExtraBytes = defaults.networkDefaultPayloadLengthExtraBytes
|
|
||||||
endOfLifeTime, = unpack('>Q', data[8:16])
|
|
||||||
TTL = endOfLifeTime - (int(recvTime) if recvTime else int(time.time()))
|
|
||||||
if TTL < 300:
|
|
||||||
TTL = 300
|
|
||||||
POW, = unpack('>Q', hashlib.sha512(hashlib.sha512(data[
|
|
||||||
:8] + hashlib.sha512(data[8:]).digest()).digest()).digest()[0:8])
|
|
||||||
return POW <= 2 ** 64 / (nonceTrialsPerByte *
|
|
||||||
(len(data) + payloadLengthExtraBytes +
|
|
||||||
((TTL * (len(data) + payloadLengthExtraBytes)) / (2 ** 16))))
|
|
||||||
|
|
||||||
|
|
||||||
# Packet creation
|
# Packet creation
|
||||||
|
|
||||||
|
@ -406,7 +378,11 @@ def checkAndShareObjectWithPeers(payload):
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if not isProofOfWorkSufficient(payload):
|
if not workprover.utils.checkWorkSufficient(
|
||||||
|
payload,
|
||||||
|
defaults.networkDefaultProofOfWorkNonceTrialsPerByte,
|
||||||
|
defaults.networkDefaultPayloadLengthExtraBytes
|
||||||
|
):
|
||||||
logger.info("Proof of work is insufficient")
|
logger.info("Proof of work is insufficient")
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -316,8 +316,6 @@ class singleWorker(threading.Thread, helper_threading.StoppableThread):
|
||||||
self.sendRawObject(*arguments)
|
self.sendRawObject(*arguments)
|
||||||
elif command == "cancelRawObject":
|
elif command == "cancelRawObject":
|
||||||
self.cancelRawObject(*arguments)
|
self.cancelRawObject(*arguments)
|
||||||
elif command == "resetPoW":
|
|
||||||
pass
|
|
||||||
elif command == "GPUError":
|
elif command == "GPUError":
|
||||||
self.handleGPUError(*arguments)
|
self.handleGPUError(*arguments)
|
||||||
elif command == "taskDone":
|
elif command == "taskDone":
|
||||||
|
|
|
@ -69,9 +69,11 @@ class TestUtils(unittest.TestCase):
|
||||||
|
|
||||||
utils.time.time = lambda: expiryTime - 293757.5
|
utils.time.time = lambda: expiryTime - 293757.5
|
||||||
self.assertFalse(utils.checkWorkSufficient(payload, byteDifficulty, lengthExtension))
|
self.assertFalse(utils.checkWorkSufficient(payload, byteDifficulty, lengthExtension))
|
||||||
|
self.assertFalse(utils.checkWorkSufficient(payload, byteDifficulty, lengthExtension, expiryTime - 293757.5))
|
||||||
|
|
||||||
utils.time.time = lambda: expiryTime - 293757
|
utils.time.time = lambda: expiryTime - 293757
|
||||||
self.assertTrue(utils.checkWorkSufficient(payload, byteDifficulty, lengthExtension))
|
self.assertTrue(utils.checkWorkSufficient(payload, byteDifficulty, lengthExtension))
|
||||||
|
self.assertTrue(utils.checkWorkSufficient(payload, byteDifficulty, lengthExtension, expiryTime - 293757))
|
||||||
|
|
||||||
utils.time.time = originalTime
|
utils.time.time = originalTime
|
||||||
|
|
||||||
|
|
|
@ -27,9 +27,12 @@ def checkProof(nonce, initialHash, target):
|
||||||
|
|
||||||
return trial <= target
|
return trial <= target
|
||||||
|
|
||||||
def checkWorkSufficient(payload, byteDifficulty, lengthExtension):
|
def checkWorkSufficient(payload, byteDifficulty, lengthExtension, receivedTime = None):
|
||||||
|
if receivedTime is None:
|
||||||
|
receivedTime = int(time.time())
|
||||||
|
|
||||||
expiryTime, = struct.unpack(">Q", payload[8: 16])
|
expiryTime, = struct.unpack(">Q", payload[8: 16])
|
||||||
minimumTTL = max(300, expiryTime - int(time.time()))
|
minimumTTL = max(300, expiryTime - receivedTime)
|
||||||
|
|
||||||
nonce = payload[: 8]
|
nonce = payload[: 8]
|
||||||
initialHash = calculateInitialHash(payload[8: ])
|
initialHash = calculateInitialHash(payload[8: ])
|
||||||
|
|
Reference in New Issue
Block a user