implemented peer exchange

This commit is contained in:
Kevin Froman 2021-02-05 02:19:23 +00:00
parent b4127c9836
commit f4182cb996
4 changed files with 44 additions and 16 deletions

View File

@ -2,8 +2,6 @@
Handle commands for the torgossip server Handle commands for the torgossip server
""" """
from onionrblocks import generators
from onionrblocks.generators import anonvdf
import blockio import blockio
import onionrblocks import onionrblocks
@ -26,9 +24,13 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
def peer_exchange(peers: 'Peers', num_of_peers: bytes): def peer_exchange(peers: 'Peers', num_of_peers: bytes):
#7 """command 7: exchange a number of our top performing peers"""
num_of_peers = int.from_bytes(num_of_peers, 'little') num_of_peers = int(chr(int.from_bytes(num_of_peers, 'little')))
return peers.get_highest_score_peers(num_of_peers) peers = peers.get_highest_score_peers(num_of_peers)
just_addresses = []
for i in peers:
just_addresses.append(i[0])
return b''.join(just_addresses)
def put_block(safe_db, block): def put_block(safe_db, block):
@ -41,7 +43,7 @@ def put_block(safe_db, block):
safe_db) safe_db)
except ValueError: except ValueError:
pass pass
except Exception as e: except Exception as _: # noqa
return b"0" return b"0"
return b"1" return b"1"

View File

@ -29,7 +29,7 @@ class TorGossipPeers: # name it this way to avoid collisions in SharedState
PACK_FORMAT = "qQ" PACK_FORMAT = "qQ"
def __init__(self, encrypt=True): def __init__(self, encrypt=False):
self.db = safedb.SafeDB( self.db = safedb.SafeDB(
identify_home() + "/torgossip-peers.db", protected=encrypt) identify_home() + "/torgossip-peers.db", protected=encrypt)
@ -54,18 +54,30 @@ class TorGossipPeers: # name it this way to avoid collisions in SharedState
self.db.put(peer, pack(self.PACK_FORMAT, score, seen)) self.db.put(peer, pack(self.PACK_FORMAT, score, seen))
def get_highest_score_peers(self, max=5): def get_highest_score_peers(self, max):
assert max >= 1 assert max >= 1
peer = self.db.db_conn.firstkey() peer = self.db.db_conn.firstkey()
if peer == b'enc':
peer = self.db.db_conn.nextkey(peer)
print('p', peer)
assert len(peer) == 34
if not peer:
return []
top = [(peer, self.db.get(peer))] top = [(peer, self.db.get(peer))]
for peer in self.db.db_conn.nextkey(peer): while peer:
peer = self.db.db_conn.nextkey(peer)
if not peer:
break
if peer == b"enc":
continue
peer_data = self.db.get(peer) peer_data = self.db.get(peer)
overwrite = None overwrite = None
if len(top) != max: if len(top) != max:
top.append((peer, peer_data)) top.append((peer, peer_data))
peer = self.db.db_conn.nextkey(peer)
continue continue
for count, cur_top in enumerate(top): for count, cur_top in enumerate(top):
# if peer score is greater than any set peer, overwrite # if peer score is greater than any set peer, overwrite
@ -75,16 +87,17 @@ class TorGossipPeers: # name it this way to avoid collisions in SharedState
break # below else won't execute, so it will be overwritten break # below else won't execute, so it will be overwritten
else: else:
# if not overwriting, go to next peer # if not overwriting, go to next peer
peer = self.db.db_conn.nextkey(peer)
continue continue
top[overwrite] = (peer, peer_data) top[overwrite] = (peer, peer_data)
return top return top
def add_score(self, peer, new_score): def add_score(self, peer, plus):
shrunk = self._shrink_peer_address(peer) shrunk = self._shrink_peer_address(peer)
score, _ = unpack("qQ", self.db.get(shrunk)) score, _ = unpack("qQ", self.db.get(shrunk))
self._pack_and_store_info( self._pack_and_store_info(
shrunk, new_score=score + new_score) shrunk, new_score=score + plus)
def update_seen(self, peer): def update_seen(self, peer):
peer = self._shrink_peer_address(peer) peer = self._shrink_peer_address(peer)
@ -92,3 +105,7 @@ class TorGossipPeers: # name it this way to avoid collisions in SharedState
def add_peer(self, peer): def add_peer(self, peer):
self._pack_and_store_info(peer) self._pack_and_store_info(peer)
def remove_peer(self, peer):
peer = self._shrink_peer_address(peer)
del self.db.db_conn[peer]

View File

@ -1,7 +1,7 @@
import socket import socket
import os import os
import secrets import secrets
from base64 import b32encode from base64 import b32decode, b32encode
from utils import identifyhome from utils import identifyhome
from onionrblocks import blockcreator from onionrblocks import blockcreator
@ -73,10 +73,15 @@ def torgossip_runtest(test_manager):
shared_state.get_by_string("SafeDB").get('bl-tbt')) - 64 shared_state.get_by_string("SafeDB").get('bl-tbt')) - 64
# test peer list # test peer list
#fake_peer = _fake_onion() fake_peer = _fake_onion()
#shared_state.get_by_string('TorGossipPeers').add_peer(fake_peer) shared_state.get_by_string('TorGossipPeers').add_peer(fake_peer)
#s.sendall(b'71') shared_state.get_by_string('TorGossipPeers').add_score(fake_peer, 100000)
#assert s.recv(100) == fake_peer s.sendall(b'71')
stored = s.recv(1000)
expected = b32decode(fake_peer.replace('.onion', '')).replace(b'.onion', b'')
print(stored, expected)
assert stored == expected
shared_state.get_by_string('TorGossipPeers').remove_peer(fake_peer)
s.sendall(b'9') s.sendall(b'9')
assert s.recv(64) == b"BYE" assert s.recv(64) == b"BYE"

View File

@ -82,6 +82,10 @@ def start_server(shared_state):
conn.sendall( conn.sendall(
commandhandlers.handle_check_block( commandhandlers.handle_check_block(
shared_state.get_by_string('SafeDB'), data)) shared_state.get_by_string('SafeDB'), data))
elif cmd == GossipCommands.PEER_EXCHANGE:
conn.sendall(
commandhandlers.peer_exchange(
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: