Merge branch 'mergenick' into mergenickmaster
This commit is contained in:
commit
b47da779cb
@ -44,12 +44,6 @@ if sys.version_info[0] == 2 or sys.version_info[1] < onionrvalues.MIN_PY_VERSION
|
|||||||
sys.stderr.write('Error, Onionr requires Python 3.%s+\n' % (onionrvalues.MIN_PY_VERSION,))
|
sys.stderr.write('Error, Onionr requires Python 3.%s+\n' % (onionrvalues.MIN_PY_VERSION,))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Ensure Python interpreter is not optimized TODO: Remove asserts and replace with ifs
|
|
||||||
from utils import detectoptimization
|
|
||||||
if detectoptimization.detect_optimization():
|
|
||||||
sys.stderr.write('Error, Onionr cannot be run with an optimized Python interpreter\n')
|
|
||||||
sys.exit(2)
|
|
||||||
|
|
||||||
# Create Onionr data directories, must be done before most imports
|
# Create Onionr data directories, must be done before most imports
|
||||||
from utils import createdirs
|
from utils import createdirs
|
||||||
createdirs.create_dirs()
|
createdirs.create_dirs()
|
||||||
|
@ -65,7 +65,7 @@ def announce_node(daemon):
|
|||||||
data['random'] = existingRand
|
data['random'] = existingRand
|
||||||
else:
|
else:
|
||||||
daemon.announceProgress[peer] = True
|
daemon.announceProgress[peer] = True
|
||||||
proof = onionrproofs.DataPOW(combinedNodes, forceDifficulty=onionrvalues.ANNOUNCE_POW)
|
proof = onionrproofs.DataPOW(combinedNodes, minDifficulty=onionrvalues.ANNOUNCE_POW)
|
||||||
del daemon.announceProgress[peer]
|
del daemon.announceProgress[peer]
|
||||||
try:
|
try:
|
||||||
data['random'] = base64.b64encode(proof.waitForResult()[1])
|
data['random'] = base64.b64encode(proof.waitForResult()[1])
|
||||||
|
@ -19,7 +19,7 @@ def verify_POW(blockContent):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
difficulty = onionrproofs.getDifficultyForNewBlock(blockContent, ourBlock=False)
|
difficulty = onionrproofs.getDifficultyForNewBlock(blockContent)
|
||||||
|
|
||||||
if difficulty < int(config.get('general.minimum_block_pow')):
|
if difficulty < int(config.get('general.minimum_block_pow')):
|
||||||
difficulty = int(config.get('general.minimum_block_pow'))
|
difficulty = int(config.get('general.minimum_block_pow'))
|
||||||
|
@ -17,91 +17,64 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
'''
|
'''
|
||||||
import multiprocessing, nacl.encoding, nacl.hash, nacl.utils, time, math, threading, binascii, sys, json
|
import multiprocessing, nacl.encoding, nacl.hash, nacl.utils, time, math, threading, binascii, sys, json, sys
|
||||||
import config, logger, onionrblockapi, storagecounter
|
import config, logger, onionrblockapi, storagecounter
|
||||||
from onionrutils import bytesconverter
|
from onionrutils import bytesconverter
|
||||||
from onionrcrypto import hashers
|
from onionrcrypto import hashers
|
||||||
config.reload()
|
config.reload()
|
||||||
|
|
||||||
def getDifficultyModifier():
|
def getDifficultyModifier():
|
||||||
'''returns the difficulty modifier for block storage based
|
'''returns the difficulty modifier for block storage based
|
||||||
on a variety of factors, currently only disk use.
|
on a variety of factors, currently only disk use.
|
||||||
'''
|
'''
|
||||||
retData = 0
|
percentUse = storagecounter.StorageCounter().getPercent()
|
||||||
useFunc = storagecounter.StorageCounter().get_percent
|
difficultyIncrease = math.floor(4 * percentUse) # difficulty increase is a step function
|
||||||
|
|
||||||
percentUse = useFunc()
|
return difficultyIncrease
|
||||||
|
|
||||||
if percentUse >= 0.50:
|
def getDifficultyForNewBlock(data):
|
||||||
retData += 1
|
|
||||||
elif percentUse >= 0.75:
|
|
||||||
retData += 2
|
|
||||||
elif percentUse >= 0.95:
|
|
||||||
retData += 3
|
|
||||||
|
|
||||||
return retData
|
|
||||||
|
|
||||||
def getDifficultyForNewBlock(data, ourBlock=True):
|
|
||||||
'''
|
'''
|
||||||
Get difficulty for block. Accepts size in integer, Block instance, or str/bytes full block contents
|
Get difficulty for block. Accepts size in integer, Block instance, or str/bytes full block contents
|
||||||
'''
|
'''
|
||||||
retData = 0
|
|
||||||
dataSize = 0
|
|
||||||
if isinstance(data, onionrblockapi.Block):
|
if isinstance(data, onionrblockapi.Block):
|
||||||
dataSize = len(data.getRaw().encode('utf-8'))
|
dataSizeInBytes = len(bytesconverter.str_to_bytes(data.getRaw()))
|
||||||
else:
|
else:
|
||||||
dataSize = len(bytesconverter.str_to_bytes(data))
|
dataSizeInBytes = len(bytesconverter.str_to_bytes(data))
|
||||||
|
|
||||||
if ourBlock:
|
minDifficulty = config.get('general.minimum_send_pow', 4)
|
||||||
minDifficulty = config.get('general.minimum_send_pow', 4)
|
totalDifficulty = max(minDifficulty, math.floor(dataSizeInBytes / 1000000.0)) + getDifficultyModifier()
|
||||||
else:
|
|
||||||
minDifficulty = config.get('general.minimum_block_pow', 4)
|
|
||||||
|
|
||||||
retData = max(minDifficulty, math.floor(dataSize / 100000)) + getDifficultyModifier()
|
return totalDifficulty
|
||||||
|
|
||||||
return retData
|
return retData
|
||||||
|
|
||||||
def getHashDifficulty(h: str):
|
def getHashDifficulty(h: str):
|
||||||
'''
|
'''
|
||||||
Return the amount of leading zeroes in a hex hash string (h)
|
Return the amount of leading zeroes in a hex hash string (hexHash)
|
||||||
'''
|
'''
|
||||||
difficulty = 0
|
return len(h) - len(h.lstrip('0'))
|
||||||
for character in h:
|
|
||||||
if character == '0':
|
|
||||||
difficulty += 1
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
return difficulty
|
|
||||||
|
|
||||||
def hashMeetsDifficulty(h):
|
def hashMeetsDifficulty(hexHash):
|
||||||
'''
|
'''
|
||||||
Return bool for a hash string to see if it meets pow difficulty defined in config
|
Return bool for a hash string to see if it meets pow difficulty defined in config
|
||||||
'''
|
'''
|
||||||
hashDifficulty = getHashDifficulty(h)
|
hashDifficulty = getHashDifficulty(hexHash)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
expected = int(config.get('general.minimum_block_pow'))
|
expected = int(config.get('general.minimum_block_pow'))
|
||||||
except TypeError:
|
except TypeError:
|
||||||
raise ValueError('Missing general.minimum_block_pow config')
|
raise ValueError('Missing general.minimum_block_pow config')
|
||||||
if hashDifficulty >= expected:
|
|
||||||
return True
|
return hashDifficulty >= expected
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
class DataPOW:
|
class DataPOW:
|
||||||
def __init__(self, data, forceDifficulty=0, threadCount = 1):
|
def __init__(self, data, minDifficulty = 0, threadCount = 1):
|
||||||
self.foundHash = False
|
|
||||||
self.difficulty = 0
|
|
||||||
self.data = data
|
self.data = data
|
||||||
self.threadCount = threadCount
|
self.threadCount = threadCount
|
||||||
|
self.difficulty = max(minDifficulty, getDifficultyForNewBlock(data))
|
||||||
self.rounds = 0
|
self.rounds = 0
|
||||||
self.hashing = False
|
self.hashing = False
|
||||||
|
self.foundHash = False
|
||||||
if forceDifficulty == 0:
|
|
||||||
dataLen = sys.getsizeof(data)
|
|
||||||
self.difficulty = math.floor(dataLen / 1000000)
|
|
||||||
if self.difficulty <= 2:
|
|
||||||
self.difficulty = 4
|
|
||||||
else:
|
|
||||||
self.difficulty = forceDifficulty
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.data = self.data.encode()
|
self.data = self.data.encode()
|
||||||
@ -124,9 +97,6 @@ class DataPOW:
|
|||||||
self.hashing = True
|
self.hashing = True
|
||||||
self.reporting = reporting
|
self.reporting = reporting
|
||||||
iFound = False # if current thread is the one that found the answer
|
iFound = False # if current thread is the one that found the answer
|
||||||
answer = ''
|
|
||||||
heartbeat = 200000
|
|
||||||
hbCount = 0
|
|
||||||
|
|
||||||
while self.hashing:
|
while self.hashing:
|
||||||
rand = nacl.utils.random()
|
rand = nacl.utils.random()
|
||||||
@ -183,7 +153,7 @@ class DataPOW:
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
class POW:
|
class POW:
|
||||||
def __init__(self, metadata, data, threadCount = 1, forceDifficulty=0):
|
def __init__(self, metadata, data, threadCount = 1, minDifficulty=0):
|
||||||
self.foundHash = False
|
self.foundHash = False
|
||||||
self.difficulty = 0
|
self.difficulty = 0
|
||||||
self.data = data
|
self.data = data
|
||||||
@ -198,8 +168,8 @@ class POW:
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if forceDifficulty > 0:
|
if minDifficulty > 0:
|
||||||
self.difficulty = forceDifficulty
|
self.difficulty = minDifficulty
|
||||||
else:
|
else:
|
||||||
# Calculate difficulty. Dumb for now, may use good algorithm in the future.
|
# Calculate difficulty. Dumb for now, may use good algorithm in the future.
|
||||||
self.difficulty = getDifficultyForNewBlock(bytes(json_metadata + b'\n' + self.data))
|
self.difficulty = getDifficultyForNewBlock(bytes(json_metadata + b'\n' + self.data))
|
||||||
@ -218,10 +188,7 @@ class POW:
|
|||||||
self.hashing = True
|
self.hashing = True
|
||||||
self.reporting = reporting
|
self.reporting = reporting
|
||||||
iFound = False # if current thread is the one that found the answer
|
iFound = False # if current thread is the one that found the answer
|
||||||
answer = ''
|
nonce = int(binascii.hexlify(nacl.utils.random(64)), 16)
|
||||||
hbCount = 0
|
|
||||||
nonce = int(binascii.hexlify(nacl.utils.random(2)), 16)
|
|
||||||
startNonce = nonce
|
|
||||||
while self.hashing:
|
while self.hashing:
|
||||||
#token = nacl.hash.blake2b(rand + self.data).decode()
|
#token = nacl.hash.blake2b(rand + self.data).decode()
|
||||||
self.metadata['pow'] = nonce
|
self.metadata['pow'] = nonce
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
'''
|
|
||||||
Onionr - Private P2P Communication
|
|
||||||
|
|
||||||
Detect if Python is being run in optimized mode or not, which has security considerations for assert statements
|
|
||||||
'''
|
|
||||||
'''
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
'''
|
|
||||||
|
|
||||||
def detect_optimization():
|
|
||||||
'''Returns true if Python is run in optimized mode (-o), based on optimization ignoring assert statements'''
|
|
||||||
try:
|
|
||||||
assert True is False
|
|
||||||
except AssertionError:
|
|
||||||
return False
|
|
||||||
return True
|
|
@ -1,6 +1,4 @@
|
|||||||
import netcontroller
|
import netcontroller
|
||||||
|
|
||||||
def has_tor():
|
def has_tor():
|
||||||
if netcontroller.tor_binary() is None:
|
return netcontroller.tor_binary() is not None
|
||||||
return False
|
|
||||||
return True
|
|
Loading…
Reference in New Issue
Block a user