
13 changed files with 344 additions and 33 deletions
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
kj7oltega2clc6a2g2z5argxwrdz5b2yb4dcztfuuetup5pozr4ogxqd.onion,ilv54tw2ppfhuylzscdp3kutjoohvnmhhkcv65c7mfczkexeahsqvqid.onion |
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
aai7opy5q6innjpb2zgviexvbenhpne7lggnh4lumudojwga2m4wbaqd |
@ -0,0 +1,88 @@
@@ -0,0 +1,88 @@
|
||||
import os, uuid |
||||
from sqlite3 import Time |
||||
import socket |
||||
from queue import Queue |
||||
from time import sleep |
||||
import secrets |
||||
|
||||
|
||||
TEST_DIR = 'testdata/%s-%s' % (str(uuid.uuid4())[:6], os.path.basename(__file__)) + '/' |
||||
print("Test directory:", TEST_DIR) |
||||
os.environ["ONIONR_HOME"] = TEST_DIR |
||||
|
||||
from threading import Thread |
||||
import asyncio |
||||
import unittest |
||||
import sys |
||||
sys.path.append(".") |
||||
sys.path.append("src/") |
||||
from unittest.mock import patch |
||||
|
||||
import onionrblocks |
||||
|
||||
|
||||
from filepaths import gossip_server_socket_file |
||||
from gossip.client import block_queue_processing |
||||
from gossip import client |
||||
from gossip.blockqueues import gossip_block_queues |
||||
from gossip.peerset import gossip_peer_set |
||||
|
||||
|
||||
BLOCK_MAX_SIZE = 1024 * 2000 |
||||
BLOCK_MAX_SIZE_LEN = len(str(BLOCK_MAX_SIZE)) |
||||
BLOCK_ID_SIZE = 128 |
||||
BLOCK_STREAM_OFFSET_DIGITS = 8 |
||||
MAX_PEERS = 10 |
||||
TRANSPORT_SIZE_BYTES = 64 |
||||
|
||||
server_file = TEST_DIR + 'test_serv.sock' |
||||
|
||||
|
||||
def gen_random_block(): |
||||
return onionrblocks.create_anonvdf_block(os.urandom(12), b'txt', 3600) |
||||
|
||||
|
||||
test_blocks = [] |
||||
|
||||
test_thread = [] |
||||
|
||||
test_block_count = 5 |
||||
for i in range(test_block_count): |
||||
test_blocks.append(gen_random_block()) |
||||
|
||||
|
||||
class MockPeer: |
||||
def __init__(self): |
||||
self.transport_address = secrets.token_hex(16) |
||||
def __hash__(self): |
||||
return hash(self.transport_address) |
||||
|
||||
|
||||
def get_socket(self, timeout): |
||||
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) |
||||
s.connect(server_file) |
||||
return s |
||||
|
||||
class MockPhase: |
||||
def __init__(self): |
||||
return |
||||
def remaining_time(self): |
||||
return 120 |
||||
def is_stem_phase(self): |
||||
return False |
||||
|
||||
|
||||
class OnionrGossipClientBlockChoice(unittest.TestCase): |
||||
|
||||
|
||||
@patch('gossip.client.dandelionstem.stem_out') |
||||
@patch('gossip.client.store_blocks') |
||||
def test_client_block_processing_fluff_phase(self, mock_store_blocks, mock_stem_out): |
||||
gossip_peer_set.add(MockPeer()) |
||||
|
||||
client.dandelion_phase = MockPhase() |
||||
block_queue_processing() |
||||
self.assertTrue(mock_store_blocks.called) |
||||
|
||||
|
||||
unittest.main() |
@ -0,0 +1,70 @@
@@ -0,0 +1,70 @@
|
||||
from time import sleep, time |
||||
import sys |
||||
from hashlib import shake_128 |
||||
import secrets |
||||
import asyncio |
||||
import unittest |
||||
sys.path.append(".") |
||||
sys.path.append("src/") |
||||
from gossip.dandelion import phase |
||||
|
||||
|
||||
class FakePhase: |
||||
def __init__(self, seed, epoch_interval_secs: int): |
||||
self.seed = seed |
||||
assert len(self.seed) == 32 |
||||
self.epoch = int(time()) |
||||
self.epoch_interval = epoch_interval_secs |
||||
self._is_stem = bool(secrets.randbits(1)) |
||||
self.phase_id = b'' |
||||
|
||||
|
||||
def _update_stem_phase(self, cur_time): |
||||
self.epoch = cur_time |
||||
# Hash the self.seed with the time stamp to produce 8 pseudorandom bytes |
||||
# Produce an len(8) byte string for time as well for year 2038 problem |
||||
self.phase_id = shake_128( |
||||
self.seed + |
||||
int.to_bytes(cur_time, 8, 'big')).digest(8) |
||||
|
||||
# Use first byte of phase id as random source for stem phase picking |
||||
if self.phase_id[0] % 2: |
||||
self._is_stem = True |
||||
else: |
||||
self._is_stem = False |
||||
|
||||
|
||||
def remaining_time(self) -> int: |
||||
current_time = int(time()) |
||||
|
||||
return max(0, self.epoch_interval - (current_time - self.epoch)) |
||||
|
||||
def is_stem_phase(self) -> bool: |
||||
current_time = int(time()) |
||||
if current_time - self.epoch >= self.epoch_interval: |
||||
self._update_stem_phase(current_time) |
||||
return self._is_stem |
||||
|
||||
|
||||
class OnionrGossipTestDandelionPhase(unittest.TestCase): |
||||
|
||||
def test_dandelion_phase(self): |
||||
epoch = 3 # seconds |
||||
seed = phase.seed |
||||
self.assertTrue(len(seed) == 32) |
||||
p = phase.DandelionPhase(epoch) |
||||
fake_p = FakePhase(phase.seed, epoch) |
||||
|
||||
assert p.phase_id == fake_p.phase_id |
||||
|
||||
def test_dandelion_phase_both(self): |
||||
epoch = 3 # seconds |
||||
seed = phase.seed |
||||
self.assertTrue(len(seed) == 32) |
||||
p = phase.DandelionPhase(epoch) |
||||
fake_p = FakePhase(phase.seed, epoch) |
||||
|
||||
assert p.phase_id == fake_p.phase_id |
||||
|
||||
|
||||
unittest.main() |
@ -0,0 +1,129 @@
@@ -0,0 +1,129 @@
|
||||
import os, uuid |
||||
from sqlite3 import Time |
||||
import socket |
||||
from queue import Queue |
||||
from time import sleep |
||||
import secrets |
||||
|
||||
|
||||
TEST_DIR = 'testdata/%s-%s' % (str(uuid.uuid4())[:6], os.path.basename(__file__)) + '/' |
||||
print("Test directory:", TEST_DIR) |
||||
os.environ["ONIONR_HOME"] = TEST_DIR |
||||
|
||||
from threading import Thread |
||||
import asyncio |
||||
import unittest |
||||
import sys |
||||
sys.path.append(".") |
||||
sys.path.append("src/") |
||||
from unittest.mock import patch |
||||
|
||||
from ordered_set import OrderedSet |
||||
from gossip import peerset |
||||
|
||||
|
||||
import onionrblocks |
||||
|
||||
import blockdb |
||||
|
||||
from gossip.peerset import gossip_peer_set |
||||
from gossip.client import stream_from_peers |
||||
|
||||
|
||||
|
||||
from filepaths import gossip_server_socket_file |
||||
|
||||
|
||||
BLOCK_MAX_SIZE = 1024 * 2000 |
||||
BLOCK_MAX_SIZE_LEN = len(str(BLOCK_MAX_SIZE)) |
||||
BLOCK_ID_SIZE = 128 |
||||
BLOCK_STREAM_OFFSET_DIGITS = 8 |
||||
MAX_PEERS = 10 |
||||
TRANSPORT_SIZE_BYTES = 64 |
||||
|
||||
server_file = TEST_DIR + 'test_serv.sock' |
||||
|
||||
|
||||
def gen_random_block(): |
||||
return onionrblocks.create_anonvdf_block(os.urandom(12), b'txt', 3600) |
||||
|
||||
|
||||
test_blocks = [] |
||||
|
||||
test_thread = [] |
||||
|
||||
test_block_count = 5 |
||||
for i in range(test_block_count): |
||||
test_blocks.append(gen_random_block()) |
||||
|
||||
already_have_blocks = [] |
||||
|
||||
duplicated_block = [False] |
||||
|
||||
for bl in secrets.SystemRandom().sample(test_blocks, 3): |
||||
blockdb.add_block_to_db(bl) |
||||
already_have_blocks.append(bl.id) |
||||
|
||||
|
||||
def _server(): |
||||
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s: |
||||
s.bind(server_file) |
||||
s.listen(1) |
||||
conn, _ = s.accept() |
||||
with conn: |
||||
conn.recv(1) |
||||
conn.recv(BLOCK_STREAM_OFFSET_DIGITS) |
||||
for bl in test_blocks: |
||||
conn.sendall(bl.id) |
||||
choice = conn.recv(1) |
||||
if choice == int(1).to_bytes(1, 'big') \ |
||||
and bl.id in already_have_blocks: |
||||
duplicated_block[0] = True |
||||
print('duplicated block') |
||||
elif choice == int(0).to_bytes(1, 'big') and bl.id in already_have_blocks: |
||||
print('skipping block correctly') |
||||
continue |
||||
|
||||
conn.sendall(str(len(bl.raw)).encode('utf-8').zfill(BLOCK_MAX_SIZE_LEN)) |
||||
conn.sendall(bl.raw) |
||||
conn.recv(1) |
||||
|
||||
|
||||
Thread(target=_server, daemon=True).start() |
||||
|
||||
class MockPeer: |
||||
def __init__(self): |
||||
self.transport_address = secrets.token_hex(16) |
||||
def __hash__(self): |
||||
return hash(self.transport_address) |
||||
|
||||
|
||||
def get_socket(self, timeout): |
||||
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) |
||||
s.connect(server_file) |
||||
return s |
||||
|
||||
|
||||
class OnionrGossipClientDiffuse(unittest.TestCase): |
||||
|
||||
|
||||
def test_client_stream_have(self): |
||||
|
||||
gossip_peer_set.add(MockPeer()) |
||||
|
||||
t = Thread(target=stream_from_peers, daemon=True) |
||||
test_thread.append(t) |
||||
test_thread[0].start() |
||||
|
||||
c = 0 |
||||
while c < 10: |
||||
c += 1 |
||||
if len(list(blockdb.get_blocks_after_timestamp(0))) == test_block_count: |
||||
break |
||||
sleep(1) |
||||
else: |
||||
raise TimeoutError("Did not stream blocks in time") |
||||
|
||||
self.assertFalse(duplicated_block[0]) |
||||
|
||||
unittest.main() |
Loading…
Reference in new issue