Work on stemout

This commit is contained in:
Kevin F 2022-03-13 00:35:22 -06:00
parent 19159ffa06
commit 9bf16c5758
3 changed files with 56 additions and 10 deletions

View File

@ -18,7 +18,7 @@ def do_announce(peer_set):
except AttributeError: except AttributeError:
pass pass
sock = announce_peer.get_socket() sock = announce_peer.get_socket()
sock.send( sock.sendall(
command_to_byte(GossipCommands.ANNOUNCE) + our_transport_address) command_to_byte(GossipCommands.ANNOUNCE) + our_transport_address)
if int.from_bytes(sock.recv(1), 'big') != 1: if int.from_bytes(sock.recv(1), 'big') != 1:
logger.warn( logger.warn(

View File

@ -1,5 +1,5 @@
from queue import Queue from queue import Queue
from threading import Timer from threading import Thread, Timer
from time import sleep from time import sleep
from secrets import choice from secrets import choice
import traceback import traceback
@ -11,20 +11,24 @@ from blockdb import add_block_to_db
import logger import logger
from ..constants import BLACKHOLE_EVADE_TIMER_SECS, MAX_OUTBOUND_DANDELION_EDGE from ..constants import BLACKHOLE_EVADE_TIMER_SECS, MAX_OUTBOUND_DANDELION_EDGE
from ..commands import GossipCommands, command_to_byte
from .. import dandelion
if TYPE_CHECKING: if TYPE_CHECKING:
from ordered_set import OrderedSet from ordered_set import OrderedSet
from onionrblocks import Block from onionrblocks import Block
from ..peer import Peer from ..peer import Peer
from ..dandelion.phase import DandelionPhase from ..dandelion.phase import DandelionPhase
import socket
class NotEnoughEdges(ValueError): pass # noqa class NotEnoughEdges(ValueError): pass # noqa
class StemConnectionDenied(ConnectionRefusedError): pass # noqa
def _setup_edge( async def _setup_edge(
peer_set: OrderedSet['Peer'], exclude_set: OrderedSet['Peer']): peer_set: OrderedSet['Peer'], exclude_set: OrderedSet['Peer']):
"""Negotiate stem connection with random peer, add to exclude set if fail""" """Negotiate stem connection with random peer, add to exclu set if fail"""
try: try:
peer: 'Peer' = choice(peer_set - exclude_set) peer: 'Peer' = choice(peer_set - exclude_set)
except IndexError: except IndexError:
@ -35,13 +39,46 @@ def _setup_edge(
logger.debug(traceback.format_exc()) logger.debug(traceback.format_exc())
exclude_set.add(peer) exclude_set.add(peer)
try:
s.sendall(command_to_byte(GossipCommands.PUT_BLOCKS))
if s.recv(1) == dandelion.StemAcceptResult.DENY:
raise StemConnectionDenied
except StemConnectionDenied:
logger.debug(
"Stem connection denied (peer has too many) " +
f"{peer.transport_address}")
except Exception:
logger.warn(
"Error asking peer to establish stem connection" +
traceback.format_exc(), terminal=True)
else:
# Return peer socket if it is in stem reception mode successfully
return s
finally:
# If peer is good or bad, exclude it no matter what
exclude_set.add(peer)
# If they won't accept stem blocks, close the socket
s.close()
def stem_out( async def _do_stem_stream(
peer_socket: 'socket.socket',
block_queue: Queue['Block'],
d_phase: 'DandelionPhase'):
return
async def stem_out(
block_queues: Tuple[Queue['Block'], Queue['Block']], block_queues: Tuple[Queue['Block'], Queue['Block']],
peer_set: OrderedSet['Peer'], peer_set: OrderedSet['Peer'],
d_phase: 'DandelionPhase'): d_phase: 'DandelionPhase'):
# don't bother if there are no possible outbound edges
if not len(peer_set):
sleep(1)
return
# Spawn threads with deep copied block queue to add to db after time # Spawn threads with deep copied block queue to add to db after time
# for black hole attack # for black hole attack
for block_q in block_queues: for block_q in block_queues:
@ -49,14 +86,23 @@ def stem_out(
lambda q: set(map(add_block_to_db, q)), lambda q: set(map(add_block_to_db, q)),
BLACKHOLE_EVADE_TIMER_SECS, list(block_q.queue)) BLACKHOLE_EVADE_TIMER_SECS, list(block_q.queue))
# don't bother if there are no possible outbound edges peer_sockets: List['socket.socket'] = []
if not len(peer_set):
sleep(1)
return
# Pick edges randomly # Pick edges randomly
# Using orderedset for the tried edges to ensure random pairing with queue # Using orderedset for the tried edges to ensure random pairing with queue
tried_edges: OrderedSet['Peer'] = OrderedSet() tried_edges: OrderedSet['Peer'] = OrderedSet()
while len(peer_sockets) < MAX_OUTBOUND_DANDELION_EDGE:
try:
peer_sockets.append(_setup_edge(peer_set, tried_edges))
except NotEnoughEdges:
logger.debug("Not able to build enough peers for stemout")
break
finally:
if not d_phase.is_stem_phase() or d_phase.remaining_time() < 5:
logger.error(
"Did not stem out any blocks in time, " +
"if this happens regularly you may be under attack",
terminal=True)

View File

@ -6,7 +6,7 @@ BLOCK_ID_SIZE = 128
DANDELION_EPOCH_LENGTH = 60 DANDELION_EPOCH_LENGTH = 60
# Magic number i made up, not really specified in dandelion++ paper # Magic number i made up, not really specified in dandelion++ paper
MAX_INBOUND_DANDELION_EDGE = 50 # Mainly picked to avoid slowlorisstor browser dvm 16 MAX_INBOUND_DANDELION_EDGE = 50 # Mainly picked to avoid slowloris
# Dandelion subgraph is aprox 4-regular # Dandelion subgraph is aprox 4-regular
MAX_OUTBOUND_DANDELION_EDGE = 2 MAX_OUTBOUND_DANDELION_EDGE = 2