+ re-added old pow system as a different class for things like ed25519 keys
* no longer run communicator threads if they need peers and we have none connectedmaster
parent
f027202ac9
commit
b3b5e5bb50
|
@ -67,23 +67,22 @@ class OnionrCommunicatorDaemon:
|
||||||
if debug or developmentMode:
|
if debug or developmentMode:
|
||||||
OnionrCommunicatorTimers(self, self.heartbeat, 10)
|
OnionrCommunicatorTimers(self, self.heartbeat, 10)
|
||||||
|
|
||||||
# Initalize peer online list
|
|
||||||
logger.warn('Onionr is starting up and is not yet ready to recieve commands.')
|
|
||||||
self.getOnlinePeers()
|
|
||||||
|
|
||||||
# Print nice header thing :)
|
# Print nice header thing :)
|
||||||
if config.get('general.display_header', True):
|
if config.get('general.display_header', True) and not self.shutdown:
|
||||||
self.header()
|
self.header()
|
||||||
|
|
||||||
# Set timers, function reference, seconds
|
# Set timers, function reference, seconds
|
||||||
OnionrCommunicatorTimers(self, self.daemonCommands, 5)
|
OnionrCommunicatorTimers(self, self.daemonCommands, 5)
|
||||||
OnionrCommunicatorTimers(self, self.detectAPICrash, 5)
|
OnionrCommunicatorTimers(self, self.detectAPICrash, 5)
|
||||||
OnionrCommunicatorTimers(self, self.getOnlinePeers, 60)
|
peerPoolTimer = OnionrCommunicatorTimers(self, self.getOnlinePeers, 60)
|
||||||
OnionrCommunicatorTimers(self, self.lookupBlocks, 7)
|
OnionrCommunicatorTimers(self, self.lookupBlocks, 7, requiresPeer=True)
|
||||||
OnionrCommunicatorTimers(self, self.getBlocks, 10)
|
OnionrCommunicatorTimers(self, self.getBlocks, 10, requiresPeer=True)
|
||||||
OnionrCommunicatorTimers(self, self.clearOfflinePeer, 120)
|
OnionrCommunicatorTimers(self, self.clearOfflinePeer, 120)
|
||||||
OnionrCommunicatorTimers(self, self.lookupKeys, 125)
|
OnionrCommunicatorTimers(self, self.lookupKeys, 125, requiresPeer=True)
|
||||||
OnionrCommunicatorTimers(self, self.lookupAdders, 600)
|
OnionrCommunicatorTimers(self, self.lookupAdders, 600, requiresPeer=True)
|
||||||
|
|
||||||
|
# set loop to execute instantly to load up peer pool (replaced old pool init wait)
|
||||||
|
peerPoolTimer.count = (peerPoolTimer.frequency - 1)
|
||||||
|
|
||||||
# Main daemon loop, mainly for calling timers, don't do any complex operations here to avoid locking
|
# Main daemon loop, mainly for calling timers, don't do any complex operations here to avoid locking
|
||||||
try:
|
try:
|
||||||
|
@ -227,8 +226,11 @@ class OnionrCommunicatorDaemon:
|
||||||
for i in range(needed):
|
for i in range(needed):
|
||||||
if len(self.onlinePeers) == 0:
|
if len(self.onlinePeers) == 0:
|
||||||
self.connectNewPeer(useBootstrap=True)
|
self.connectNewPeer(useBootstrap=True)
|
||||||
if len(self.onlinePeers) == 0:
|
if self.shutdown:
|
||||||
logger.warn('Could not connect to any peer.')
|
break
|
||||||
|
else:
|
||||||
|
if len(self.onlinePeers) == 0:
|
||||||
|
logger.warn('Could not connect to any peer.')
|
||||||
self.decrementThreadCount('getOnlinePeers')
|
self.decrementThreadCount('getOnlinePeers')
|
||||||
|
|
||||||
def addBootstrapListToPeerList(self, peerList):
|
def addBootstrapListToPeerList(self, peerList):
|
||||||
|
@ -358,11 +360,12 @@ class OnionrCommunicatorDaemon:
|
||||||
logger.info(logger.colors.fg.lightgreen + '-> ' + str(message) + logger.colors.reset + logger.colors.fg.lightgreen + ' <-\n')
|
logger.info(logger.colors.fg.lightgreen + '-> ' + str(message) + logger.colors.reset + logger.colors.fg.lightgreen + ' <-\n')
|
||||||
|
|
||||||
class OnionrCommunicatorTimers:
|
class OnionrCommunicatorTimers:
|
||||||
def __init__(self, daemonInstance, timerFunction, frequency, makeThread=True, threadAmount=1, maxThreads=5):
|
def __init__(self, daemonInstance, timerFunction, frequency, makeThread=True, threadAmount=1, maxThreads=5, requiresPeer=False):
|
||||||
self.timerFunction = timerFunction
|
self.timerFunction = timerFunction
|
||||||
self.frequency = frequency
|
self.frequency = frequency
|
||||||
self.threadAmount = threadAmount
|
self.threadAmount = threadAmount
|
||||||
self.makeThread = makeThread
|
self.makeThread = makeThread
|
||||||
|
self.requiresPeer = requiresPeer
|
||||||
self.daemonInstance = daemonInstance
|
self.daemonInstance = daemonInstance
|
||||||
self.maxThreads = maxThreads
|
self.maxThreads = maxThreads
|
||||||
self._core = self.daemonInstance._core
|
self._core = self.daemonInstance._core
|
||||||
|
@ -371,25 +374,33 @@ class OnionrCommunicatorTimers:
|
||||||
self.count = 0
|
self.count = 0
|
||||||
|
|
||||||
def processTimer(self):
|
def processTimer(self):
|
||||||
|
|
||||||
# mark how many instances of a thread we have (decremented at thread end)
|
# mark how many instances of a thread we have (decremented at thread end)
|
||||||
self.count += 1
|
|
||||||
try:
|
try:
|
||||||
self.daemonInstance.threadCounts[self.timerFunction.__name__]
|
self.daemonInstance.threadCounts[self.timerFunction.__name__]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
self.daemonInstance.threadCounts[self.timerFunction.__name__] = 0
|
self.daemonInstance.threadCounts[self.timerFunction.__name__] = 0
|
||||||
# execute thread if it is time
|
|
||||||
|
# execute thread if it is time, and we are not missing *required* online peer
|
||||||
if self.count == self.frequency:
|
if self.count == self.frequency:
|
||||||
if self.makeThread:
|
try:
|
||||||
for i in range(self.threadAmount):
|
if self.requiresPeer and len(self.daemonInstance.onlinePeers) == 0:
|
||||||
if self.daemonInstance.threadCounts[self.timerFunction.__name__] >= self.maxThreads:
|
raise onionrexceptions.OnlinePeerNeeded
|
||||||
logger.warn(self.timerFunction.__name__ + ' has too many current threads to start anymore.')
|
except onionrexceptions.OnlinePeerNeeded:
|
||||||
else:
|
pass
|
||||||
self.daemonInstance.threadCounts[self.timerFunction.__name__] += 1
|
|
||||||
newThread = threading.Thread(target=self.timerFunction)
|
|
||||||
newThread.start()
|
|
||||||
else:
|
else:
|
||||||
self.timerFunction()
|
if self.makeThread:
|
||||||
self.count = 0
|
for i in range(self.threadAmount):
|
||||||
|
if self.daemonInstance.threadCounts[self.timerFunction.__name__] >= self.maxThreads:
|
||||||
|
logger.warn(self.timerFunction.__name__ + ' has too many current threads to start anymore.')
|
||||||
|
else:
|
||||||
|
self.daemonInstance.threadCounts[self.timerFunction.__name__] += 1
|
||||||
|
newThread = threading.Thread(target=self.timerFunction)
|
||||||
|
newThread.start()
|
||||||
|
else:
|
||||||
|
self.timerFunction()
|
||||||
|
self.count = -1 # negative 1 because its incremented at bottom
|
||||||
|
self.count += 1
|
||||||
|
|
||||||
shouldRun = False
|
shouldRun = False
|
||||||
debug = True
|
debug = True
|
||||||
|
|
|
@ -25,7 +25,7 @@ import sys
|
||||||
if sys.version_info[0] == 2 or sys.version_info[1] < 5:
|
if sys.version_info[0] == 2 or sys.version_info[1] < 5:
|
||||||
print('Error, Onionr requires Python 3.4+')
|
print('Error, Onionr requires Python 3.4+')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
import os, base64, random, getpass, shutil, subprocess, requests, time, platform, datetime, re, json, getpass
|
import os, base64, random, getpass, shutil, subprocess, requests, time, platform, datetime, re, json, getpass, sqlite3
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
import api, core, config, logger, onionrplugins as plugins, onionrevents as events
|
import api, core, config, logger, onionrplugins as plugins, onionrevents as events
|
||||||
import onionrutils
|
import onionrutils
|
||||||
|
@ -604,7 +604,11 @@ class Onionr:
|
||||||
try:
|
try:
|
||||||
events.event('daemon_stop', onionr = self)
|
events.event('daemon_stop', onionr = self)
|
||||||
net = NetController(config.get('client.port', 59496))
|
net = NetController(config.get('client.port', 59496))
|
||||||
self.onionrCore.daemonQueueAdd('shutdown')
|
try:
|
||||||
|
self.onionrCore.daemonQueueAdd('shutdown')
|
||||||
|
except sqlite3.OperationalError:
|
||||||
|
pass
|
||||||
|
|
||||||
net.killTor()
|
net.killTor()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error('Failed to shutdown daemon.', error = e, timestamp = False)
|
logger.error('Failed to shutdown daemon.', error = e, timestamp = False)
|
||||||
|
|
|
@ -59,7 +59,7 @@ class OnionrCrypto:
|
||||||
with open(self._keyFile, 'w') as keyfile:
|
with open(self._keyFile, 'w') as keyfile:
|
||||||
keyfile.write(self.pubKey + ',' + self.privKey)
|
keyfile.write(self.pubKey + ',' + self.privKey)
|
||||||
with open(self.keyPowFile, 'w') as keyPowFile:
|
with open(self.keyPowFile, 'w') as keyPowFile:
|
||||||
proof = onionrproofs.POW(self.pubKey)
|
proof = onionrproofs.DataPOW(self.pubKey)
|
||||||
logger.info('Doing necessary work to insert our public key')
|
logger.info('Doing necessary work to insert our public key')
|
||||||
while True:
|
while True:
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
|
|
|
@ -26,6 +26,10 @@ class Unknown(Exception):
|
||||||
class Invalid(Exception):
|
class Invalid(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# communicator exceptions
|
||||||
|
class OnlinePeerNeeded(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
# crypto exceptions
|
# crypto exceptions
|
||||||
class InvalidPubkey(Exception):
|
class InvalidPubkey(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -21,6 +21,99 @@
|
||||||
import nacl.encoding, nacl.hash, nacl.utils, time, math, threading, binascii, logger, sys, base64, json
|
import nacl.encoding, nacl.hash, nacl.utils, time, math, threading, binascii, logger, sys, base64, json
|
||||||
import core
|
import core
|
||||||
|
|
||||||
|
class DataPOW:
|
||||||
|
def __init__(self, data, threadCount = 5):
|
||||||
|
self.foundHash = False
|
||||||
|
self.difficulty = 0
|
||||||
|
self.data = data
|
||||||
|
self.threadCount = threadCount
|
||||||
|
|
||||||
|
dataLen = sys.getsizeof(data)
|
||||||
|
self.difficulty = math.floor(dataLen / 1000000)
|
||||||
|
if self.difficulty <= 2:
|
||||||
|
self.difficulty = 4
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.data = self.data.encode()
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.data = nacl.hash.blake2b(self.data)
|
||||||
|
|
||||||
|
logger.info('Computing POW (difficulty: %s)...' % self.difficulty)
|
||||||
|
|
||||||
|
self.mainHash = '0' * 70
|
||||||
|
self.puzzle = self.mainHash[0:min(self.difficulty, len(self.mainHash))]
|
||||||
|
|
||||||
|
myCore = core.Core()
|
||||||
|
for i in range(max(1, threadCount)):
|
||||||
|
t = threading.Thread(name = 'thread%s' % i, target = self.pow, args = (True,myCore))
|
||||||
|
t.start()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def pow(self, reporting = False, myCore = None):
|
||||||
|
startTime = math.floor(time.time())
|
||||||
|
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()
|
||||||
|
token = nacl.hash.blake2b(rand + self.data).decode()
|
||||||
|
#print(token)
|
||||||
|
if self.puzzle == token[0:self.difficulty]:
|
||||||
|
self.hashing = False
|
||||||
|
iFound = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if iFound:
|
||||||
|
endTime = math.floor(time.time())
|
||||||
|
if self.reporting:
|
||||||
|
logger.debug('Found token after %s seconds: %s' % (endTime - startTime, token), timestamp=True)
|
||||||
|
logger.debug('Random value was: %s' % base64.b64encode(rand).decode())
|
||||||
|
self.result = (token, rand)
|
||||||
|
|
||||||
|
def shutdown(self):
|
||||||
|
self.hashing = False
|
||||||
|
self.puzzle = ''
|
||||||
|
|
||||||
|
def changeDifficulty(self, newDiff):
|
||||||
|
self.difficulty = newDiff
|
||||||
|
|
||||||
|
def getResult(self):
|
||||||
|
'''
|
||||||
|
Returns the result then sets to false, useful to automatically clear the result
|
||||||
|
'''
|
||||||
|
|
||||||
|
try:
|
||||||
|
retVal = self.result
|
||||||
|
except AttributeError:
|
||||||
|
retVal = False
|
||||||
|
|
||||||
|
self.result = False
|
||||||
|
return retVal
|
||||||
|
|
||||||
|
def waitForResult(self):
|
||||||
|
'''
|
||||||
|
Returns the result only when it has been found, False if not running and not found
|
||||||
|
'''
|
||||||
|
result = False
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
result = self.getResult()
|
||||||
|
if not self.hashing:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
time.sleep(2)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
self.shutdown()
|
||||||
|
logger.warn('Got keyboard interrupt while waiting for POW result, stopping')
|
||||||
|
return result
|
||||||
|
|
||||||
class POW:
|
class POW:
|
||||||
def __init__(self, metadata, data, threadCount = 5):
|
def __init__(self, metadata, data, threadCount = 5):
|
||||||
self.foundHash = False
|
self.foundHash = False
|
||||||
|
|
Loading…
Reference in New Issue