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:
pass
sock = announce_peer.get_socket()
sock.send(
sock.sendall(
command_to_byte(GossipCommands.ANNOUNCE) + our_transport_address)
if int.from_bytes(sock.recv(1), 'big') != 1:
logger.warn(

View File

@ -1,5 +1,5 @@
from queue import Queue
from threading import Timer
from threading import Thread, Timer
from time import sleep
from secrets import choice
import traceback
@ -11,20 +11,24 @@ from blockdb import add_block_to_db
import logger
from ..constants import BLACKHOLE_EVADE_TIMER_SECS, MAX_OUTBOUND_DANDELION_EDGE
from ..commands import GossipCommands, command_to_byte
from .. import dandelion
if TYPE_CHECKING:
from ordered_set import OrderedSet
from onionrblocks import Block
from ..peer import Peer
from ..dandelion.phase import DandelionPhase
import socket
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']):
"""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:
peer: 'Peer' = choice(peer_set - exclude_set)
except IndexError:
@ -35,13 +39,46 @@ def _setup_edge(
logger.debug(traceback.format_exc())
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']],
peer_set: OrderedSet['Peer'],
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
# for black hole attack
for block_q in block_queues:
@ -49,14 +86,23 @@ def stem_out(
lambda q: set(map(add_block_to_db, q)),
BLACKHOLE_EVADE_TIMER_SECS, list(block_q.queue))
# don't bother if there are no possible outbound edges
if not len(peer_set):
sleep(1)
return
peer_sockets: List['socket.socket'] = []
# Pick edges randomly
# Using orderedset for the tried edges to ensure random pairing with queue
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
# 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
MAX_OUTBOUND_DANDELION_EDGE = 2