work on getting new blocks in communicator2
parent
6cb69c7187
commit
21786c6885
|
@ -32,7 +32,7 @@ class API:
|
||||||
'''
|
'''
|
||||||
def validateToken(self, token):
|
def validateToken(self, token):
|
||||||
'''
|
'''
|
||||||
Validate that the client token (hmac) matches the given token
|
Validate that the client token matches the given token
|
||||||
'''
|
'''
|
||||||
try:
|
try:
|
||||||
if not hmac.compare_digest(self.clientToken, token):
|
if not hmac.compare_digest(self.clientToken, token):
|
||||||
|
@ -178,7 +178,6 @@ class API:
|
||||||
@app.route('/public/')
|
@app.route('/public/')
|
||||||
def public_handler():
|
def public_handler():
|
||||||
# Public means it is publicly network accessible
|
# Public means it is publicly network accessible
|
||||||
# TODO, stop hard coding endpoints, use whitelist and serializer.
|
|
||||||
self.validateHost('public')
|
self.validateHost('public')
|
||||||
action = request.args.get('action')
|
action = request.args.get('action')
|
||||||
requestingPeer = request.args.get('myID')
|
requestingPeer = request.args.get('myID')
|
||||||
|
|
|
@ -38,6 +38,8 @@ class OnionrCommunicatorDaemon:
|
||||||
|
|
||||||
self.shutdown = False
|
self.shutdown = False
|
||||||
|
|
||||||
|
self.blockQueue = [] # list of new blocks to download
|
||||||
|
|
||||||
# Clear the daemon queue for any dead messages
|
# Clear the daemon queue for any dead messages
|
||||||
if os.path.exists(self._core.queueDB):
|
if os.path.exists(self._core.queueDB):
|
||||||
self._core.clearDaemonQueue()
|
self._core.clearDaemonQueue()
|
||||||
|
@ -56,6 +58,8 @@ class OnionrCommunicatorDaemon:
|
||||||
OnionrCommunicatorTimers(self, self.daemonCommands, 5)
|
OnionrCommunicatorTimers(self, self.daemonCommands, 5)
|
||||||
OnionrCommunicatorTimers(self, self.detectAPICrash, 12)
|
OnionrCommunicatorTimers(self, self.detectAPICrash, 12)
|
||||||
OnionrCommunicatorTimers(self, self.getOnlinePeers, 60)
|
OnionrCommunicatorTimers(self, self.getOnlinePeers, 60)
|
||||||
|
OnionrCommunicatorTimers(self, self.lookupBlocks, 120)
|
||||||
|
OnionrCommunicatorTimers(self, self.getBlocks, 30)
|
||||||
|
|
||||||
# Main daemon loop, mainly for calling timers, do not do any complex operations here
|
# Main daemon loop, mainly for calling timers, do not do any complex operations here
|
||||||
while not self.shutdown:
|
while not self.shutdown:
|
||||||
|
@ -64,7 +68,43 @@ class OnionrCommunicatorDaemon:
|
||||||
time.sleep(self.delay)
|
time.sleep(self.delay)
|
||||||
logger.info('Goodbye.')
|
logger.info('Goodbye.')
|
||||||
|
|
||||||
|
def lookupBlocks(self):
|
||||||
|
'''Lookup new blocks'''
|
||||||
|
tryAmount = 2
|
||||||
|
newBlocks = ''
|
||||||
|
for i in range(tryAmount):
|
||||||
|
newBlocks = self.peerAction(pickOnlinePeer(), 'getBlockHashes')
|
||||||
|
if newBlocks != False:
|
||||||
|
# if request was a success
|
||||||
|
for i in newBlocks.split('\n'):
|
||||||
|
if self._core.utils.validateHash(i):
|
||||||
|
# if newline seperated string is valid hash
|
||||||
|
if not os.path.exists('data/blocks/' + i + '.db'):
|
||||||
|
# if block does not exist on disk
|
||||||
|
self.blockQueue.append(i)
|
||||||
|
self.decrementThreadCount('lookupBlocks')
|
||||||
|
return
|
||||||
|
|
||||||
|
def getBlocks(self):
|
||||||
|
'''download new blocks'''
|
||||||
|
return
|
||||||
|
|
||||||
|
def pickOnlinePeer(self):
|
||||||
|
'''randomly picks peer from pool without bias (using secrets module)'''
|
||||||
|
retData = ''
|
||||||
|
while True:
|
||||||
|
peerLength = len(self.onlinePeers)
|
||||||
|
try:
|
||||||
|
# get a random online peer, securely. May get stuck in loop if network is lost or if all peers in pool magically disconnect at once
|
||||||
|
retData = self.onlinePeers[self._core._crypto.secrets.randbelow(peerLength)]
|
||||||
|
except IndexError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
return retData
|
||||||
|
|
||||||
def decrementThreadCount(self, threadName):
|
def decrementThreadCount(self, threadName):
|
||||||
|
'''Decrement amount of a thread name if more than zero, called when a function meant to be run in a thread ends'''
|
||||||
if self.threadCounts[threadName] > 0:
|
if self.threadCounts[threadName] > 0:
|
||||||
self.threadCounts[threadName] -= 1
|
self.threadCounts[threadName] -= 1
|
||||||
|
|
||||||
|
@ -104,6 +144,23 @@ class OnionrCommunicatorDaemon:
|
||||||
logger.warn('Could not connect to any peer')
|
logger.warn('Could not connect to any peer')
|
||||||
return retData
|
return retData
|
||||||
|
|
||||||
|
def printOnlinePeers(self):
|
||||||
|
'''logs online peer list'''
|
||||||
|
if len(self.onlinePeers) == 0:
|
||||||
|
logger.warn('No online peers')
|
||||||
|
return
|
||||||
|
for i in self.onlinePeers:
|
||||||
|
logger.info(self.onlinePeers[i])
|
||||||
|
|
||||||
|
def peerAction(self, peer, action, data=''):
|
||||||
|
'''Perform a get request to a peer'''
|
||||||
|
logger.info('Performing ' + action + ' with ' + peer + ' on port ' + str(self.proxyPort))
|
||||||
|
retData = self._core._utils.doGetRequest('http://' + peer + '/public/?action=' + action + '&data=' + data, port=self.proxyPort)
|
||||||
|
if retData == False:
|
||||||
|
self.onlinePeers.remove(peer)
|
||||||
|
self.getOnlinePeers() # Will only add a new peer to pool if needed
|
||||||
|
return retData
|
||||||
|
|
||||||
def heartbeat(self):
|
def heartbeat(self):
|
||||||
'''Show a heartbeat debug message'''
|
'''Show a heartbeat debug message'''
|
||||||
logger.debug('Communicator heartbeat')
|
logger.debug('Communicator heartbeat')
|
||||||
|
@ -127,14 +184,6 @@ class OnionrCommunicatorDaemon:
|
||||||
logger.info('Recieved daemonQueue command:' + cmd[0])
|
logger.info('Recieved daemonQueue command:' + cmd[0])
|
||||||
self.decrementThreadCount('daemonCommands')
|
self.decrementThreadCount('daemonCommands')
|
||||||
|
|
||||||
def printOnlinePeers(self):
|
|
||||||
'''logs online peer list'''
|
|
||||||
if len(self.onlinePeers) == 0:
|
|
||||||
logger.warn('No online peers')
|
|
||||||
return
|
|
||||||
for i in self.onlinePeers:
|
|
||||||
logger.info(self.onlinePeers[i])
|
|
||||||
|
|
||||||
def announce(self, peer):
|
def announce(self, peer):
|
||||||
'''Announce to peers'''
|
'''Announce to peers'''
|
||||||
announceCount = 0
|
announceCount = 0
|
||||||
|
@ -149,19 +198,10 @@ class OnionrCommunicatorDaemon:
|
||||||
logger.warn('Could not introduce node. Try again soon')
|
logger.warn('Could not introduce node. Try again soon')
|
||||||
break
|
break
|
||||||
|
|
||||||
def peerAction(self, peer, action, data=''):
|
|
||||||
'''Perform a get request to a peer'''
|
|
||||||
logger.info('Performing ' + action + ' with ' + peer + ' on port ' + str(self.proxyPort))
|
|
||||||
retData = self._core._utils.doGetRequest('http://' + peer + '/public/?action=' + action + '&data=' + data, port=self.proxyPort)
|
|
||||||
if retData == False:
|
|
||||||
self.onlinePeers.remove(peer)
|
|
||||||
self.getOnlinePeers() # Will only add a new peer to pool if needed
|
|
||||||
return retData
|
|
||||||
|
|
||||||
def detectAPICrash(self):
|
def detectAPICrash(self):
|
||||||
'''exit if the api server crashes/stops'''
|
'''exit if the api server crashes/stops'''
|
||||||
if self._core._utils.localCommand('ping') != 'pong':
|
if self._core._utils.localCommand('ping') != 'pong':
|
||||||
for i in range(4):
|
for i in range(5):
|
||||||
if self._core._utils.localCommand('ping') == 'pong':
|
if self._core._utils.localCommand('ping') == 'pong':
|
||||||
break # break for loop
|
break # break for loop
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
|
@ -92,6 +92,8 @@ class Onionr:
|
||||||
self.onionrCore = core.Core()
|
self.onionrCore = core.Core()
|
||||||
self.onionrUtils = OnionrUtils(self.onionrCore)
|
self.onionrUtils = OnionrUtils(self.onionrCore)
|
||||||
|
|
||||||
|
self.userOS = platform.system()
|
||||||
|
|
||||||
# Handle commands
|
# Handle commands
|
||||||
|
|
||||||
self.debug = False # Whole application debugging
|
self.debug = False # Whole application debugging
|
||||||
|
@ -571,6 +573,7 @@ class Onionr:
|
||||||
logger.info('Using new communicator')
|
logger.info('Using new communicator')
|
||||||
except NameError:
|
except NameError:
|
||||||
pass
|
pass
|
||||||
|
#TODO make runable on windows
|
||||||
subprocess.Popen([communicatorDaemon, "run", str(net.socksPort)])
|
subprocess.Popen([communicatorDaemon, "run", str(net.socksPort)])
|
||||||
logger.debug('Started communicator')
|
logger.debug('Started communicator')
|
||||||
events.event('daemon_start', onionr = self)
|
events.event('daemon_start', onionr = self)
|
||||||
|
|
|
@ -17,7 +17,13 @@
|
||||||
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 nacl.signing, nacl.encoding, nacl.public, nacl.hash, nacl.secret, os, binascii, base64, hashlib, logger, onionrproofs, time, math
|
import nacl.signing, nacl.encoding, nacl.public, nacl.hash, nacl.secret, os, binascii, base64, hashlib, logger, onionrproofs, time, math, sys
|
||||||
|
|
||||||
|
# secrets module was added into standard lib in 3.6+
|
||||||
|
if sys.version_info[0] == 3 and sys.version_info[1] < 6:
|
||||||
|
from dependencies import secrets
|
||||||
|
elif sys.version_info[0] == 3 and sys.version_info[1] >= 6:
|
||||||
|
import secrets
|
||||||
|
|
||||||
class OnionrCrypto:
|
class OnionrCrypto:
|
||||||
def __init__(self, coreInstance):
|
def __init__(self, coreInstance):
|
||||||
|
@ -27,6 +33,8 @@ class OnionrCrypto:
|
||||||
self.pubKey = None
|
self.pubKey = None
|
||||||
self.privKey = None
|
self.privKey = None
|
||||||
|
|
||||||
|
self.secrets = secrets
|
||||||
|
|
||||||
self.pubKeyPowToken = None
|
self.pubKeyPowToken = None
|
||||||
#self.pubKeyPowHash = None
|
#self.pubKeyPowHash = None
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue