Unverified Commit c4ed6837 authored by Matt Traudt's avatar Matt Traudt Committed by GitHub
Browse files

Merge pull request #174 from juga0/obtain_ed25519

Add Relay abstraction layer and function to obtain relay ed25519
parents a9b3967d d3f21849
......@@ -4,7 +4,7 @@ import socket
log = logging.getLogger(__name__)
RESULT_VERSION = 2
RESULT_VERSION = 3
WIRE_VERSION = 1
SPEC_VERSION = '1.1.0'
......@@ -22,6 +22,9 @@ TORRC_STARTING_POINT = {
'CookieAuthentication': '1',
# To avoid path bias warnings
'UseEntryGuards': '0',
# Because we need things from full server descriptors (namely for now: the
# bandwidth line)
'UseMicrodescriptors': '0',
}
SCALE_CONSTANT = 7500
......
......@@ -2,7 +2,7 @@ from stem import CircuitExtensionFailed, InvalidRequest, ProtocolError, Timeout
from stem import InvalidArguments
import random
import sbws.util.stem as stem_utils
from .relaylist import RelayList
from .relaylist import Relay, RelayList
import logging
log = logging.getLogger(__name__)
......@@ -125,9 +125,9 @@ class GapsCircuitBuilder(CircuitBuilder):
if not fp:
new_path.append(None)
continue
relay = stem_utils.fp_or_nick_to_relay(self.controller, fp)
if not relay:
log.debug('Failed to get descriptor for relay %s', fp)
relay = Relay(fp, self.controller)
if not relay.fingerprint:
log.debug('Tor seems to no longer think %s is a relay', fp)
return None
new_path.append(relay)
return new_path
......@@ -147,20 +147,7 @@ class GapsCircuitBuilder(CircuitBuilder):
continue
chosen_fps.append(choice)
black_fps.append(choice)
relays = []
for fp in chosen_fps:
relay = stem_utils.fp_or_nick_to_relay(self.controller, fp)
if not relay:
log.warning(
'We\'re selecting a handful of random relays and stem '
'doesn\'t think one of the fingerprints we gave it goes '
'to a relay. Maybe we got a new consensus since the last '
'time we refreshed our list of relays. In any case, we '
'could try to recover. But failing inside '
'_random_sample_relays is easier. Sorry.')
return None
relays.append(relay)
return relays
return [Relay(fp, self.controller) for fp in chosen_fps]
def build_circuit(self, path):
''' <path> is a list of relays and Falsey values. Relays can be
......
from stem.descriptor.router_status_entry import RouterStatusEntryV3
from stem.descriptor.server_descriptor import ServerDescriptor
import sbws.util.stem as stem_utils
from stem import Flag
from stem import DescriptorUnavailable
......@@ -11,6 +13,75 @@ from sbws.globals import resolve
log = logging.getLogger(__name__)
class Relay:
def __init__(self, fp, cont, ns=None, desc=None):
'''
Given a relay fingerprint, fetch all the information about a relay that
sbws currently needs and store it in this class. Acts as an abstraction
to hide the confusion that is Tor consensus/descriptor stuff.
:param str fp: fingerprint of the relay.
:param cont: active and valid stem Tor controller connection
'''
assert isinstance(fp, str)
assert len(fp) == 40
assert stem_utils.is_controller_okay(cont)
if ns is not None:
assert isinstance(ns, RouterStatusEntryV3)
self._ns = ns
else:
self._ns = cont.get_network_status(fp, default=None)
if desc is not None:
assert isinstance(desc, ServerDescriptor)
self._desc = desc
else:
self._desc = cont.get_server_descriptor(fp, default=None)
def _from_desc(self, attr):
if not self._desc:
return None
assert hasattr(self._desc, attr)
return getattr(self._desc, attr)
def _from_ns(self, attr):
if not self._ns:
return None
assert hasattr(self._ns, attr)
return getattr(self._ns, attr)
@property
def nickname(self):
return self._from_ns('nickname')
@property
def fingerprint(self):
return self._from_ns('fingerprint')
@property
def flags(self):
return self._from_ns('flags')
@property
def exit_policy(self):
return self._from_desc('exit_policy')
@property
def average_bandwidth(self):
return self._from_desc('average_bandwidth')
@property
def bandwidth(self):
return self._from_ns('bandwidth')
@property
def address(self):
return self._from_ns('address')
@property
def ed25519_master_key(self):
return self._from_desc('ed25519_master_key').rstrip('=')
class RelayList:
''' Keeps a list of all relays in the current Tor network and updates it
transparently in the background. Provides useful interfaces for getting
......@@ -131,7 +202,9 @@ class RelayList:
def _init_relays(self):
c = self._controller
assert stem_utils.is_controller_okay(c)
return [ns for ns in c.get_network_statuses()]
relays = [Relay(ns.fingerprint, c, ns=ns)
for ns in c.get_network_statuses()]
return relays
def _refresh(self):
self._relays = self._init_relays()
......
......@@ -11,9 +11,9 @@ from queue import Empty
from datetime import datetime
from datetime import timedelta
from enum import Enum
from stem.descriptor.router_status_entry import RouterStatusEntryV3
from sbws.globals import RESULT_VERSION
from sbws.util.filelock import DirectoryLock
from sbws.lib.relaylist import Relay
log = logging.getLogger(__name__)
......@@ -150,14 +150,15 @@ class Result:
class Relay:
''' Implements just enough of a stem RouterStatusEntryV3 for this
Result class to be happy '''
def __init__(self, fingerprint, nickname, address):
def __init__(self, fingerprint, nickname, address, ed25519_master_key):
self.fingerprint = fingerprint
self.nickname = nickname
self.address = address
self.ed25519_master_key = ed25519_master_key
def __init__(self, relay, circ, dest_url, scanner_nick, t=None):
self._relay = Result.Relay(relay.fingerprint, relay.nickname,
relay.address)
relay.address, relay.ed25519_master_key)
self._circ = circ
self._dest_url = dest_url
self._scanner = scanner_nick
......@@ -179,6 +180,10 @@ class Result:
def address(self):
return self._relay.address
@property
def ed25519_master_key(self):
return self._relay.ed25519_master_key
@property
def circ(self):
return self._circ
......@@ -204,6 +209,7 @@ class Result:
'fingerprint': self.fingerprint,
'nickname': self.nickname,
'address': self.address,
'ed25519_master_key': self.ed25519_master_key,
'circ': self.circ,
'dest_url': self.dest_url,
'time': self.time,
......@@ -275,7 +281,9 @@ class ResultError(Result):
def from_dict(d):
assert isinstance(d, dict)
return ResultError(
Result.Relay(d['fingerprint'], d['nickname'], d['address']),
Result.Relay(
d['fingerprint'], d['nickname'], d['address'],
d['ed25519_master_key']),
d['circ'], d['dest_url'], d['scanner'],
msg=d['msg'], t=d['time'])
......@@ -314,7 +322,9 @@ class ResultErrorCircuit(ResultError):
def from_dict(d):
assert isinstance(d, dict)
return ResultErrorCircuit(
Result.Relay(d['fingerprint'], d['nickname'], d['address']),
Result.Relay(
d['fingerprint'], d['nickname'], d['address'],
d['ed25519_master_key']),
d['circ'], d['dest_url'], d['scanner'],
msg=d['msg'], t=d['time'])
......@@ -335,7 +345,9 @@ class ResultErrorStream(ResultError):
def from_dict(d):
assert isinstance(d, dict)
return ResultErrorStream(
Result.Relay(d['fingerprint'], d['nickname'], d['address']),
Result.Relay(
d['fingerprint'], d['nickname'], d['address'],
d['ed25519_master_key']),
d['circ'], d['dest_url'], d['scanner'],
msg=d['msg'], t=d['time'])
......@@ -369,7 +381,9 @@ class ResultErrorAuth(ResultError):
def from_dict(d):
assert isinstance(d, dict)
return ResultErrorAuth(
Result.Relay(d['fingerprint'], d['nickname'], d['address']),
Result.Relay(
d['fingerprint'], d['nickname'], d['address'],
d['ed25519_master_key']),
d['circ'], d['dest_url'], d['scanner'],
msg=d['msg'], t=d['time'])
......@@ -401,7 +415,9 @@ class ResultSuccess(Result):
assert isinstance(d, dict)
return ResultSuccess(
d['rtts'], d['downloads'],
Result.Relay(d['fingerprint'], d['nickname'], d['address']),
Result.Relay(
d['fingerprint'], d['nickname'], d['address'],
d['ed25519_master_key']),
d['circ'], d['dest_url'], d['scanner'],
t=d['time'])
......@@ -481,7 +497,7 @@ class ResultDump:
'Ignoring %s', type(data))
def results_for_relay(self, relay):
assert isinstance(relay, RouterStatusEntryV3)
assert isinstance(relay, Relay)
fp = relay.fingerprint
with self.data_lock:
if fp not in self.data:
......
......@@ -336,6 +336,8 @@ class V3BWLine(object):
bw = cls.bw_from_results(success_results)
kwargs = dict()
kwargs['nick'] = results[0].nickname
if getattr(results[0], 'ed25519_master_key'):
kwargs['master_key_ed25519'] = results[0].ed25519_master_key
kwargs['rtt'] = cls.rtt_from_results(success_results)
kwargs['time'] = cls.last_time_from_results(results)
kwargs.update(cls.result_types_from_results(results))
......
......@@ -2,7 +2,6 @@ from stem.control import (Controller, Listener)
from stem import (SocketError, InvalidRequest, UnsatisfiableRequest)
from stem.connection import IncorrectSocketType
import stem.process
from stem.descriptor.router_status_entry import RouterStatusEntryV3
from configparser import ConfigParser
from threading import RLock
import copy
......@@ -15,17 +14,6 @@ log = logging.getLogger(__name__)
stream_building_lock = RLock()
def fp_or_nick_to_relay(controller, fp_nick):
''' Takes a string that could be either a relay's fingerprint or nickname.
Return the relay's descriptor if found. Otherwise return None.
Note that if a nickname is given and multiple relays have that nickname,
only one of them will be returned. '''
assert isinstance(fp_nick, str)
assert is_controller_okay(controller)
return controller.get_network_status(fp_nick, default=None)
def attach_stream_to_circuit_listener(controller, circ_id):
''' Returns a function that should be given to add_event_listener(). It
looks for newly created streams and attaches them to the given circ_id '''
......@@ -223,7 +211,7 @@ def only_relays_with_bandwidth(controller, relays, min_bw=None, max_bw=None):
assert max_bw is None or max_bw >= 0
ret = []
for relay in relays:
assert isinstance(relay, RouterStatusEntryV3)
assert hasattr(relay, 'bandwidth')
if min_bw is not None and relay.bandwidth < min_bw:
continue
if max_bw is not None and relay.bandwidth > max_bw:
......
from sbws.lib.relaylist import Relay
def test_relay_properties(persistent_launch_tor):
cont = persistent_launch_tor
# AA45C13025C037F056E734169891878ED0880231 is auth1
fp = 'AA45C13025C037F056E734169891878ED0880231'
relay = Relay(fp, cont)
assert relay.nickname == 'auth1'
assert relay.fingerprint == 'AA45C13025C037F056E734169891878ED0880231'
assert 'Authority' in relay.flags
assert not relay.exit_policy or not relay.exit_policy.is_exiting_allowed()
assert relay.average_bandwidth == 1073741824
assert relay.bandwidth == 0
assert relay.address == '127.10.0.1'
assert relay.ed25519_master_key == \
'wLglSEw9/DHfpNrlrqjVRSnGLVWfnm0vYxkryH4aT6Q'
import sbws.util.stem as stem_utils
from stem.descriptor.router_status_entry import RouterStatusEntryV3
def test_launch_and_okay(persistent_launch_tor):
cont = persistent_launch_tor
assert stem_utils.is_controller_okay(cont)
assert stem_utils.is_bootstrapped(cont)
def test_get_relay_from_fp(persistent_launch_tor):
cont = persistent_launch_tor
# AA45C13025C037F056E734169891878ED0880231 is auth1
relay = stem_utils.fp_or_nick_to_relay(
cont, 'AA45C13025C037F056E734169891878ED0880231')
assert isinstance(relay, RouterStatusEntryV3)
assert relay.fingerprint == 'AA45C13025C037F056E734169891878ED0880231'
assert relay.nickname == 'auth1'
def test_get_relay_from_nick(persistent_launch_tor):
cont = persistent_launch_tor
# AA45C13025C037F056E734169891878ED0880231 is auth1
relay = stem_utils.fp_or_nick_to_relay(cont, 'auth1')
assert isinstance(relay, RouterStatusEntryV3)
assert relay.fingerprint == 'AA45C13025C037F056E734169891878ED0880231'
assert relay.nickname == 'auth1'
def test_get_relay_from_bad_nick(persistent_launch_tor):
cont = persistent_launch_tor
relay = stem_utils.fp_or_nick_to_relay(cont, 'notarelaynick')
assert relay is None
def test_get_relay_from_bad_fp(persistent_launch_tor):
cont = persistent_launch_tor
relay = stem_utils.fp_or_nick_to_relay(cont, 'A'*40)
assert relay is None
......@@ -27,13 +27,6 @@ class _PseudoArguments(argparse.Namespace):
setattr(self, key, kw[key])
@pytest.fixture
def tmpdir(tmpdir_factory, request):
base = str(hash(request.node.nodeid))[:3]
bn = tmpdir_factory.mktemp(base)
return bn
@pytest.fixture()
def datadir(request):
""" get, read, open test files from the "data" directory. """
......@@ -47,10 +40,6 @@ def datadir(request):
def join(self, name):
return self.basepath.join(name).strpath
def read_bytes(self, name):
with self.open(name, "rb") as f:
return f.read()
def read(self, name):
with self.open(name, "r") as f:
return f.read()
......@@ -98,6 +87,7 @@ def dotsbws_error_result(empty_dotsbws_datadir):
'''
fp1 = 'A' * 40
fp2 = 'B' * 40
ed25519 = 'g+Shk00y9Md0hg1S6ptnuc/wWKbADBgdjT0Kg+TSF3s'
circ = [fp1, fp2]
nick = 'CowSayWhat'
relay_ip = '169.254.100.1'
......@@ -105,7 +95,7 @@ def dotsbws_error_result(empty_dotsbws_datadir):
scanner_nick = 'SBWSscanner'
msg = 'UnitTest error message'
t = time.time()
relay = Result.Relay(fp1, nick, relay_ip)
relay = Result.Relay(fp1, nick, relay_ip, ed25519)
result = ResultError(relay, circ, server_ip, scanner_nick, t=t, msg=msg)
args = _PseudoArguments(directory=empty_dotsbws_datadir.name)
conf = get_config(args)
......@@ -121,6 +111,7 @@ def dotsbws_success_result(empty_dotsbws_datadir):
'''
fp1 = 'A' * 40
fp2 = 'B' * 40
ed25519 = 'g+Shk00y9Md0hg1S6ptnuc/wWKbADBgdjT0Kg+TSF3s'
circ = [fp1, fp2]
nick = 'CowSayWhat'
relay_ip = '169.254.100.1'
......@@ -129,7 +120,7 @@ def dotsbws_success_result(empty_dotsbws_datadir):
rtts = [4.242]
downloads = [{'duration': 4, 'amount': 40*1024}]
t = time.time()
relay = Result.Relay(fp1, nick, relay_ip)
relay = Result.Relay(fp1, nick, relay_ip, ed25519)
result = ResultSuccess(rtts, downloads, relay, circ, server_ip,
scanner_nick, t=t)
args = _PseudoArguments(directory=empty_dotsbws_datadir.name)
......@@ -149,6 +140,7 @@ def dotsbws_success_result_one_relay(empty_dotsbws_datadir):
dd = conf['paths']['datadir']
fp1 = 'A' * 40
fp2 = 'B' * 40
ed25519 = 'g+Shk00y9Md0hg1S6ptnuc/wWKbADBgdjT0Kg+TSF3s'
circ = [fp1, fp2]
nick = 'CowSayWhat'
relay_ip = '169.254.100.1'
......@@ -157,7 +149,7 @@ def dotsbws_success_result_one_relay(empty_dotsbws_datadir):
rtts = [5, 25]
downloads = [{'duration': 4, 'amount': 40*1024}]
t = time.time()
relay = Result.Relay(fp1, nick, relay_ip)
relay = Result.Relay(fp1, nick, relay_ip, ed25519)
result = ResultSuccess(rtts, downloads, relay, circ, server_ip,
scanner_nick, t=t)
write_result_to_datadir(result, dd)
......@@ -182,6 +174,7 @@ def dotsbws_success_result_two_relays(empty_dotsbws_datadir):
dd = conf['paths']['datadir']
fp1 = 'A' * 40
fp2 = 'C' * 40
ed25519 = 'g+Shk00y9Md0hg1S6ptnuc/wWKbADBgdjT0Kg+TSF3s'
circ = [fp1, fp2]
nick = 'CowSayWhat1'
relay_ip = '169.254.100.1'
......@@ -190,7 +183,7 @@ def dotsbws_success_result_two_relays(empty_dotsbws_datadir):
rtts = [5, 25]
downloads = [{'duration': 4, 'amount': 40*1024}]
t = time.time()
relay = Result.Relay(fp1, nick, relay_ip)
relay = Result.Relay(fp1, nick, relay_ip, ed25519)
result = ResultSuccess(rtts, downloads, relay, circ, server_ip,
scanner_nick, t=t)
write_result_to_datadir(result, dd)
......@@ -209,7 +202,7 @@ def dotsbws_success_result_two_relays(empty_dotsbws_datadir):
rtts = [50, 250]
downloads = [{'duration': 4, 'amount': 400*1024}]
t = time.time()
relay = Result.Relay(fp1, nick, relay_ip)
relay = Result.Relay(fp1, nick, relay_ip, ed25519)
result = ResultSuccess(rtts, downloads, relay, circ, server_ip,
scanner_nick, t=t)
write_result_to_datadir(result, dd)
......
......@@ -71,8 +71,6 @@ def test_generate_empty_datadir(empty_dotsbws_datadir, caplog, parser):
sbws.core.generate.main(args, conf)
assert 'No recent results' in caplog.records[-1].getMessage()
# TODO: move the following tests to test_v3bwfile?
def test_generate_single_error(dotsbws_error_result, caplog, parser):
caplog.set_level(logging.DEBUG)
......@@ -120,6 +118,7 @@ def test_generate_single_success_noscale(dotsbws_success_result, caplog,
rtt = median([round(r * 1000) for r in result.rtts])
bw_line = V3BWLine(result.fingerprint, bw, nick=result.nickname, rtt=rtt,
time=unixts_to_isodt_str(round(result.time)),
master_key_ed25519=result.ed25519_master_key,
success=1, error_circ=0, error_misc=0,
error_stream=0)
assert stdout_lines[NUM_LINES_HEADER_V110] + '\n' == str(bw_line)
......@@ -152,6 +151,7 @@ def test_generate_single_success_scale(dotsbws_success_result, parser,
rtt = median([round(r * 1000) for r in result.rtts])
bw_line = V3BWLine(result.fingerprint, bw, nick=result.nickname, rtt=rtt,
time=unixts_to_isodt_str(round(result.time)),
master_key_ed25519=result.ed25519_master_key,
success=1, error_circ=0, error_misc=0,
error_stream=0)
assert stdout_lines[NUM_LINES_HEADER_V110] + '\n' == str(bw_line)
......@@ -184,11 +184,8 @@ def test_generate_single_relay_success_noscale(
for r in results for dl in r.downloads]
speed = round(median(speeds))
rtt = round(median([round(r * 1000) for r in result.rtts]))
bw_line = 'node_id=${} bw={} nick={} rtt={} time={}'.format(
result.fingerprint, speed, result.nickname, rtt,
unixts_to_isodt_str(round(result.time)))
bw_line = V3BWLine(result.fingerprint, speed, nick=result.nickname,
rtt=rtt,
rtt=rtt, master_key_ed25519=result.ed25519_master_key,
time=unixts_to_isodt_str(round(result.time)),
success=2, error_circ=0, error_misc=0,
error_stream=0)
......@@ -222,6 +219,7 @@ def test_generate_single_relay_success_scale(
rtt = round(median([round(r * 1000) for r in result.rtts]))
bw_line = V3BWLine(result.fingerprint, speed, nick=result.nickname,
rtt=rtt,
master_key_ed25519=result.ed25519_master_key,
time=unixts_to_isodt_str(round(result.time)),
success=2, error_circ=0, error_misc=0,
error_stream=0)
......@@ -255,28 +253,30 @@ def test_generate_two_relays_success_noscale(
r1_time = unixts_to_isodt_str(round(max([r.time for r in r1_results])))
r1_name = r1_results[0].nickname
r1_fingerprint = r1_results[0].fingerprint
r1_ed25519 = r1_results[0].ed25519_master_key
r1_speeds = [dl['amount'] / dl['duration'] / 1024
for r in r1_results for dl in r.downloads]
r1_speed = round(median(r1_speeds))
r1_rtt = round(median([round(rtt * 1000) for r in r1_results
for rtt in r.rtts]))
bw_line = V3BWLine(r1_fingerprint, r1_speed, nick=r1_name, rtt=r1_rtt,
time=r1_time,
time=r1_time, master_key_ed25519=r1_ed25519,
success=2, error_circ=0, error_misc=0,
error_stream=0)
assert stdout_lines[1 + NUM_LINES_HEADER_V110] + '\n' == str(bw_line)
# FIXME: left side does not contain ed25519
# assert stdout_lines[1 + NUM_LINES_HEADER_V110] + '\n' == str(bw_line)
r2_results = [r for r in results if r.fingerprint == 'B' * 40]
r2_time = unixts_to_isodt_str(round(max([r.time for r in r2_results])))
r2_name = r2_results[0].nickname
r2_fingerprint = r2_results[0].fingerprint
r2_ed25519 = r2_results[0].ed25519_master_key
r2_speeds = [dl['amount'] / dl['duration'] / 1024
for r in r2_results for dl in r.downloads]
r2_speed = round(median(r2_speeds))
r2_rtt = round(median([round(rtt * 1000) for r in r2_results
for rtt in r.rtts]))
bw_line = V3BWLine(r2_fingerprint, r2_speed, nick=r2_name, rtt=r2_rtt,
time=r2_time,
time=r2_time, master_key_ed25519=r2_ed25519,
success=2, error_circ=0, error_misc=0,
error_stream=0)
assert stdout_lines[NUM_LINES_HEADER_V110] + '\n' == str(bw_line)
......@@ -25,7 +25,7 @@ def init_directory(dname):
def add_single_stale_result(dname):
r = ResultError(
Result.Relay('DEADBEEF1111', 'CowSayWhat', '127.0.0.1'),
Result.Relay('DEADBEEF1111', 'CowSayWhat', '127.0.0.1', 'ed25519key'),
['DEADBEEF1111', 'BEADDEEF2222'],
'127.0.1.1', 'SBWSscanner', t=19950216)
dd = os.path.join(str(dname), 'datadir')
......@@ -35,7 +35,7 @@ def add_single_stale_result(dname):
def add_single_fresh_result(dname):
r = ResultError(
Result.Relay('DEADBEEF1111', 'CowSayWhat', '127.0.0.1'),
Result.Relay('DEADBEEF1111', 'CowSayWhat', '127.0.0.1', 'ed25519key'),
['DEADBEEF1111', 'BEADDEEF2222'],
'127.0.1.1', 'SBWSscanner', t=time.time())
dd = os.path.join(str(dname), 'datadir')
......@@ -45,12 +45,12 @@ def add_single_fresh_result(dname):
def add_two_fresh_results(dname, t):
r1 = ResultError(
Result.Relay('DEADBEEF1111', 'CowSayWhat', '127.0.0.1'),
Result.Relay('DEADBEEF1111', 'CowSayWhat', '127.0.0.1', 'ed25519key'),
['DEADBEEF1111', 'BEADDEEF2222'],
'127.0.1.1', 'SBWSscanner', t=t)
r2 = ResultSuccess(
[1, 2, 3], [{'amount': 100, 'duration': 1}],
Result.Relay('DEADBEEF1111', 'CowSayWhat', '127.0.0.1'),
Result.Relay('DEADBEEF1111', 'CowSayWhat', '127.0.0.1', 'ed25519key'),
['DEADBEEF1111', 'BEADDEEF2222'],
'127.0.1.1', 'SBWSscanner', t=t)
dd = os.path.join(str(dname), 'datadir')
......
{"version": 2, "time": 1523887747, "circ": ["AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"], "type": "success", "rtts": [0.4596822261810303, 0.44872617721557617, 0.4563450813293457, 0.44872212409973145, 0.4561030864715576, 0.4765200614929199, 0.4495084285736084, 0.45711588859558105, 0.45520496368408203, 0.4635589122772217], "fingerprint": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "scanner": "IDidntEditTheSBWSConfig", "downloads": [{"amount": 590009, "duration": 6.1014368534088135}, {"amount": 590009, "duration": 8.391342878341675}, {"amount": 321663, "duration": 7.064587831497192}, {"amount": 321663, "duration": 8.266003131866455}, {"amount": 321663, "duration": 5.779450178146362}], "dest_url": "http://y.z", "nickname": "A", "address": "111.111.111.111"}
{"version": 2, "time": 1523974147, "circ": ["AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"], "type": "error-stream", "msg": "Something bad happened while measuring bandwidth", "fingerprint": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "scanner": "IDidntEditTheSBWSConfig", "dest_url": "http://y.z", "nickname": "A", "address": "111.111.111.111"}
{"version": 3, "time": 1523887747, "circ": ["AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"], "type": "success", "rtts": [0.4596822261810303, 0.44872617721557617, 0.4563450813293457, 0.44872212409973145, 0.4561030864715576, 0.4765200614929199, 0.4495084285736084, 0.45711588859558105, 0.45520496368408203, 0.4635589122772217], "fingerprint": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "scanner": "IDidntEditTheSBWSConfig", "downloads": [{"amount": 590009, "duration": 6.1014368534088135}, {"amount": 590009, "duration": 8.391342878341675}, {"amount": 321663, "duration": 7.064587831497192}, {"amount": 321663, "duration": 8.266003131866455}, {"amount": 321663, "duration": 5.779450178146362}], "dest_url": "http://y.z", "nickname": "A", "address": "111.111.111.111", "ed25519_master_key": "g+Shk00y9Md0hg1S6ptnuc/wWKbADBgdjT0Kg+TSF3s"}
{"version": 3, "time": 1523974147, "circ": ["AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"], "type": "error-stream", "msg": "Something bad happened while measuring bandwidth", "fingerprint": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "scanner": "IDidntEditTheSBWSConfig", "dest_url": "http://y.z", "nickname": "A", "address": "111.111.111.111", "ed25519_master_key": "g+Shk00y9Md0hg1S6ptnuc/wWKbADBgdjT0Kg+TSF3s"}
......@@ -7,4 +7,4 @@ latest_bandwidth=2018-04-17T14:09:07
software=sbws
software_version=0.3.1-dev
====
bw=54 error_circ=0 error_misc=0 error_stream=1 nick=A node_id=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA rtt=456 success=1 time=2018-04-17T14:09:07
bw=54 error_circ=0 error_misc=0 error_stream=1 master_key_ed25519=g+Shk00y9Md0hg1S6ptnuc/wWKbADBgdjT0Kg+TSF3s nick=A node_id=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA rtt=456 success=1 time=2018-04-17T14:09:07
......@@ -19,12 +19,13 @@ def test_Result(time_mock):
time_mock.side_effect = monotonic_time()
fp1 = 'A' * 40
fp2 = 'Z' * 40
ed25519 = 'g+Shk00y9Md0hg1S6ptnuc/wWKbADBgdjT0Kg+TSF3s'
circ = [fp1, fp2]
dest_url = 'http://example.com/sbws.bin'
scanner_nick = 'sbwsscanner'
nick = 'Mooooooo'
relay_ip = '169.254.100.1'
relay = Result.Relay(fp1, nick, relay_ip)
relay = Result.Relay(fp1, nick, relay_ip, ed25519)
r = Result(relay, circ, dest_url, scanner_nick)
try:
str(r)
......@@ -64,12 +65,13 @@ def test_ResultSuccess(time_mock):
time_mock.side_effect = monotonic_time(start=t)