Merge branch 'mergenick' into mergenickmaster

This commit is contained in:
Kevin Froman 2019-09-10 21:08:35 -05:00
commit b47da779cb
6 changed files with 29 additions and 97 deletions

View File

@ -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.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
from utils import createdirs
createdirs.create_dirs()
@ -65,4 +59,4 @@ def onionr_main():
return
if __name__ == "__main__":
onionr_main()
onionr_main()

View File

@ -65,7 +65,7 @@ def announce_node(daemon):
data['random'] = existingRand
else:
daemon.announceProgress[peer] = True
proof = onionrproofs.DataPOW(combinedNodes, forceDifficulty=onionrvalues.ANNOUNCE_POW)
proof = onionrproofs.DataPOW(combinedNodes, minDifficulty=onionrvalues.ANNOUNCE_POW)
del daemon.announceProgress[peer]
try:
data['random'] = base64.b64encode(proof.waitForResult()[1])

View File

@ -19,7 +19,7 @@ def verify_POW(blockContent):
except AttributeError:
pass
difficulty = onionrproofs.getDifficultyForNewBlock(blockContent, ourBlock=False)
difficulty = onionrproofs.getDifficultyForNewBlock(blockContent)
if difficulty < int(config.get('general.minimum_block_pow')):
difficulty = int(config.get('general.minimum_block_pow'))

View File

@ -17,91 +17,64 @@
You should have received a copy of the GNU General Public License
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
from onionrutils import bytesconverter
from onionrcrypto import hashers
config.reload()
def getDifficultyModifier():
'''returns the difficulty modifier for block storage based
on a variety of factors, currently only disk use.
'''
retData = 0
useFunc = storagecounter.StorageCounter().get_percent
percentUse = storagecounter.StorageCounter().getPercent()
difficultyIncrease = math.floor(4 * percentUse) # difficulty increase is a step function
percentUse = useFunc()
return difficultyIncrease
if percentUse >= 0.50:
retData += 1
elif percentUse >= 0.75:
retData += 2
elif percentUse >= 0.95:
retData += 3
return retData
def getDifficultyForNewBlock(data, ourBlock=True):
def getDifficultyForNewBlock(data):
'''
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):
dataSize = len(data.getRaw().encode('utf-8'))
dataSizeInBytes = len(bytesconverter.str_to_bytes(data.getRaw()))
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)
else:
minDifficulty = config.get('general.minimum_block_pow', 4)
minDifficulty = config.get('general.minimum_send_pow', 4)
totalDifficulty = max(minDifficulty, math.floor(dataSizeInBytes / 1000000.0)) + getDifficultyModifier()
retData = max(minDifficulty, math.floor(dataSize / 100000)) + getDifficultyModifier()
return totalDifficulty
return retData
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
for character in h:
if character == '0':
difficulty += 1
else:
break
return difficulty
return len(h) - len(h.lstrip('0'))
def hashMeetsDifficulty(h):
def hashMeetsDifficulty(hexHash):
'''
Return bool for a hash string to see if it meets pow difficulty defined in config
'''
hashDifficulty = getHashDifficulty(h)
hashDifficulty = getHashDifficulty(hexHash)
try:
expected = int(config.get('general.minimum_block_pow'))
except TypeError:
raise ValueError('Missing general.minimum_block_pow config')
if hashDifficulty >= expected:
return True
else:
return False
return hashDifficulty >= expected
class DataPOW:
def __init__(self, data, forceDifficulty=0, threadCount = 1):
self.foundHash = False
self.difficulty = 0
def __init__(self, data, minDifficulty = 0, threadCount = 1):
self.data = data
self.threadCount = threadCount
self.difficulty = max(minDifficulty, getDifficultyForNewBlock(data))
self.rounds = 0
self.hashing = 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
self.foundHash = False
try:
self.data = self.data.encode()
@ -124,9 +97,6 @@ class DataPOW:
self.hashing = True
self.reporting = reporting
iFound = False # if current thread is the one that found the answer
answer = ''
heartbeat = 200000
hbCount = 0
while self.hashing:
rand = nacl.utils.random()
@ -183,7 +153,7 @@ class DataPOW:
return result
class POW:
def __init__(self, metadata, data, threadCount = 1, forceDifficulty=0):
def __init__(self, metadata, data, threadCount = 1, minDifficulty=0):
self.foundHash = False
self.difficulty = 0
self.data = data
@ -198,8 +168,8 @@ class POW:
except AttributeError:
pass
if forceDifficulty > 0:
self.difficulty = forceDifficulty
if minDifficulty > 0:
self.difficulty = minDifficulty
else:
# Calculate difficulty. Dumb for now, may use good algorithm in the future.
self.difficulty = getDifficultyForNewBlock(bytes(json_metadata + b'\n' + self.data))
@ -218,10 +188,7 @@ class POW:
self.hashing = True
self.reporting = reporting
iFound = False # if current thread is the one that found the answer
answer = ''
hbCount = 0
nonce = int(binascii.hexlify(nacl.utils.random(2)), 16)
startNonce = nonce
nonce = int(binascii.hexlify(nacl.utils.random(64)), 16)
while self.hashing:
#token = nacl.hash.blake2b(rand + self.data).decode()
self.metadata['pow'] = nonce

View File

@ -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

View File

@ -1,6 +1,4 @@
import netcontroller
def has_tor():
if netcontroller.tor_binary() is None:
return False
return True
return netcontroller.tor_binary() is not None