implemented peer announce in torgossip

This commit is contained in:
Kevin Froman 2021-02-05 04:38:57 +00:00
parent f4182cb996
commit 227472d4dc
5 changed files with 62 additions and 8 deletions

View File

@ -4,6 +4,7 @@ Test Onionr as it is running
""" """
import os import os
from secrets import SystemRandom from secrets import SystemRandom
import traceback
import logger import logger
from onionrutils import epoch from onionrutils import epoch
@ -56,6 +57,16 @@ class OnionrRunTestManager:
self.plugin_tests = [] self.plugin_tests = []
def run_tests(self): def run_tests(self):
try:
assert 1 == 2
except AssertionError:
pass
else:
logger.error(
"Cannot perform runtests when Python interpreter is optimized",
terminal=True)
return
tests = list(RUN_TESTS) tests = list(RUN_TESTS)
tests.extend(self.plugin_tests) tests.extend(self.plugin_tests)
SystemRandom().shuffle(tests) SystemRandom().shuffle(tests)
@ -84,7 +95,7 @@ class OnionrRunTestManager:
logger.error(last.__name__ + ' failed assertions', terminal=True) logger.error(last.__name__ + ' failed assertions', terminal=True)
except Exception as e: except Exception as e:
logger.error(last.__name__ + ' failed with non-asserting exception') logger.error(last.__name__ + ' failed with non-asserting exception')
logger.error(repr(e)) logger.error(traceback.format_exc())
else: else:
ep = str(epoch.get_epoch()) ep = str(epoch.get_epoch())
logger.info(f'All runtime tests passed at {ep}', terminal=True) logger.info(f'All runtime tests passed at {ep}', terminal=True)

View File

@ -2,11 +2,14 @@
Handle commands for the torgossip server Handle commands for the torgossip server
""" """
import traceback
import base64
import blockio import blockio
import logger
import onionrblocks import onionrblocks
from kasten import Kasten from kasten import Kasten
""" """
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -23,7 +26,18 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
def peer_exchange(peers: 'Peers', num_of_peers: bytes): def announce_peer(peers: 'TorGossipPeers', peer_address):
"""command 8: accept a new peer"""
try:
peers.add_peer(peer_address)
except Exception as _:
logger.warn("Error accepting announced peer " + base64.b85encode(peer_address).decode('utf-8'), terminal=True)
logger.warn(traceback.format_exc(), terminal=True)
return b"0"
return b"1"
def peer_exchange(peers: 'TorGossipPeers', num_of_peers: bytes):
"""command 7: exchange a number of our top performing peers""" """command 7: exchange a number of our top performing peers"""
num_of_peers = int(chr(int.from_bytes(num_of_peers, 'little'))) num_of_peers = int(chr(int.from_bytes(num_of_peers, 'little')))
peers = peers.get_highest_score_peers(num_of_peers) peers = peers.get_highest_score_peers(num_of_peers)

View File

@ -59,7 +59,7 @@ class TorGossipPeers: # name it this way to avoid collisions in SharedState
peer = self.db.db_conn.firstkey() peer = self.db.db_conn.firstkey()
if peer == b'enc': if peer == b'enc':
peer = self.db.db_conn.nextkey(peer) peer = self.db.db_conn.nextkey(peer)
print('p', peer)
assert len(peer) == 34 assert len(peer) == 34
if not peer: if not peer:
return [] return []
@ -104,7 +104,7 @@ class TorGossipPeers: # name it this way to avoid collisions in SharedState
self._pack_and_store_info(peer, new_seen=int(time())) self._pack_and_store_info(peer, new_seen=int(time()))
def add_peer(self, peer): def add_peer(self, peer):
self._pack_and_store_info(peer) self.update_seen(peer)
def remove_peer(self, peer): def remove_peer(self, peer):
peer = self._shrink_peer_address(peer) peer = self._shrink_peer_address(peer)

View File

@ -2,6 +2,7 @@ import socket
import os import os
import secrets import secrets
from base64 import b32decode, b32encode from base64 import b32decode, b32encode
from time import sleep
from utils import identifyhome from utils import identifyhome
from onionrblocks import blockcreator from onionrblocks import blockcreator
@ -13,6 +14,11 @@ import blockio
def _fake_onion(): def _fake_onion():
return b32encode(os.urandom(34)).decode('utf-8') + ".onion" return b32encode(os.urandom(34)).decode('utf-8') + ".onion"
def _shrink_peer_address(peer):
# strip .onion and b32decode peer address for lower database mem usage
if len(peer) == 62: # constant time
return b32decode(peer[:-6]) # O(N)
return peer
def torgossip_runtest(test_manager): def torgossip_runtest(test_manager):
@ -74,14 +80,32 @@ def torgossip_runtest(test_manager):
# test peer list # test peer list
fake_peer = _fake_onion() fake_peer = _fake_onion()
fakes = []
for i in range(3):
fake = _fake_onion()
fakes.append(fake)
shared_state.get_by_string('TorGossipPeers').add_peer(fake)
shared_state.get_by_string('TorGossipPeers').add_peer(fake_peer) shared_state.get_by_string('TorGossipPeers').add_peer(fake_peer)
shared_state.get_by_string('TorGossipPeers').add_score(fake_peer, 100000) shared_state.get_by_string('TorGossipPeers').add_score(fake_peer, 100000)
s.sendall(b'71') s.sendall(b'71')
stored = s.recv(1000) stored = s.recv(1000)
expected = b32decode(fake_peer.replace('.onion', '')).replace(b'.onion', b'') expected = _shrink_peer_address(fake_peer)#b32decode(fake_peer.replace('.onion', '')).replace(b'.onion', b'')
print(stored, expected) try:
assert stored == expected assert stored == expected
except AssertionError:
print(stored, '!=', expected)
shared_state.get_by_string('TorGossipPeers').remove_peer(fake_peer) shared_state.get_by_string('TorGossipPeers').remove_peer(fake_peer)
for i in fakes:
shared_state.get_by_string('TorGossipPeers').remove_peer(i)
announce_peer = _fake_onion()
announce_raw = _shrink_peer_address(announce_peer)
s.sendall(b'8' + announce_raw)
assert s.recv(1) == b'1'
print(type(announce_raw), type(shared_state.get_by_string('TorGossipPeers').get_highest_score_peers(100)[0][0]))
assert announce_raw == shared_state.get_by_string('TorGossipPeers').get_highest_score_peers(100)[0][0]
shared_state.get_by_string('TorGossipPeers').remove_peer(announce_raw)
s.sendall(b'9') s.sendall(b'9')
assert s.recv(64) == b"BYE" assert s.recv(64) == b"BYE"

View File

@ -86,6 +86,11 @@ def start_server(shared_state):
conn.sendall( conn.sendall(
commandhandlers.peer_exchange( commandhandlers.peer_exchange(
shared_state.get_by_string('TorGossipPeers'), data)) shared_state.get_by_string('TorGossipPeers'), data))
elif cmd == GossipCommands.ANNOUNCE_PEER:
conn.sendall(
commandhandlers.announce_peer(
shared_state.get_by_string('TorGossipPeers'), data)
)
else: else:
conn.sendall(b'Unknown ' + str(cmd).encode('utf-8')) conn.sendall(b'Unknown ' + str(cmd).encode('utf-8'))
else: else: