work on getting new blocks in communicator2

This commit is contained in:
Kevin Froman 2018-06-15 00:45:07 -05:00
parent 6cb69c7187
commit 21786c6885
No known key found for this signature in database
GPG Key ID: 0D414D0FE405B63B
4 changed files with 73 additions and 23 deletions

View File

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

View File

@ -37,6 +37,8 @@ class OnionrCommunicatorDaemon:
self.threadCounts = {} self.threadCounts = {}
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):
@ -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
@ -102,8 +142,25 @@ class OnionrCommunicatorDaemon:
logger.debug('failed to connect to ' + address) logger.debug('failed to connect to ' + address)
else: else:
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')
@ -126,14 +183,6 @@ class OnionrCommunicatorDaemon:
else: else:
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'''
@ -148,20 +197,11 @@ class OnionrCommunicatorDaemon:
if announceCount == announceAmount: if announceCount == announceAmount:
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)

View File

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

View File

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