[tor-commits] [sbws/master] Initial revision of RelayNS/Relay class

pastly at torproject.org pastly at torproject.org
Thu Jun 14 13:29:50 UTC 2018


commit c56eeaa962a33079685bbb7c30c944a594197275
Author: Matt Traudt <sirmatt at ksu.edu>
Date:   Thu Jun 7 20:54:11 2018 -0400

    Initial revision of RelayNS/Relay class
    
    With unused support for ed25519 keys
---
 sbws/globals.py                         |   3 +
 sbws/lib/relaylist.py                   | 120 ++++++++++++++++++--------------
 sbws/lib/resultdump.py                  |   4 +-
 sbws/util/stem.py                       |   3 +-
 tests/integration/lib/test_relaylist.py |  17 +++++
 tests/unit/conftest.py                  |  50 +------------
 tests/unit/lib/test_relaylist.py        |  13 ----
 7 files changed, 93 insertions(+), 117 deletions(-)

diff --git a/sbws/globals.py b/sbws/globals.py
index a6621ab..a16682c 100644
--- a/sbws/globals.py
+++ b/sbws/globals.py
@@ -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
diff --git a/sbws/lib/relaylist.py b/sbws/lib/relaylist.py
index 6d0743d..c0ca9ad 100644
--- a/sbws/lib/relaylist.py
+++ b/sbws/lib/relaylist.py
@@ -1,5 +1,5 @@
 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
@@ -13,16 +13,73 @@ from sbws.globals import resolve
 log = logging.getLogger(__name__)
 
 
-class RelayNS(RouterStatusEntryV3):
-    """Inherit from RouterStatusEntryV3 and add the attribute
-    master_key_ed25519.
+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')
 
-    :param str ed25519: the ed25519 master key base 64 encoded.
-    """
-    def __init__(self, ed25519=None, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        if ed25519 is not None:
-            self.master_key_ed25519 = ed25519
+    @property
+    def ed25519_master_key(self):
+        return self._from_desc('ed25519_master_key').rstrip('=')
 
 
 class RelayList:
@@ -82,40 +139,6 @@ class RelayList:
         # return [r for r in relays if r.measured is not None]
         return [r for r in relays if not r.is_unmeasured]
 
-    def relay_ed25519_master_key(self, ns):
-        """Obtain ed25519 master key of the relay represented by
-        the network status relay line.
-
-        :param RouterStatusEntryV3 ns: the network status relay
-        :returns: str, the ed25519 master key base 64 encoded without
-            trailing '='s.
-        """
-        # In theory this is never going to be the case?
-        if ns.identifier is None or ns.identifier_type != 'ed25519':
-            log.debug('Getting microdescriptor to obtain ed25519 identity.')
-            mdesc = self._controller.get_microdescriptor(ns.fingerprint, None)
-            if mdesc is not None:
-                if 'ed25519' in mdesc.identifiers.keys():
-                    ed25519 = mdesc.identifiers['ed25519'].rstrip('=')
-                    log.debug('Found ed25519 master key.')
-                    return ed25519
-                log.debug('No ed25519 master-key found')
-            log.debug('Could not get microdescriptor')
-            # In case Tor can not retrive microdescriptors,
-            # try with server descriptors.
-            log.debug('Getting server descriptor to obtain '
-                      'ed25519 master key.')
-            sdesc = self._controller.get_server_descriptor(ns.fingerprint,
-                                                           None)
-            if sdesc is not None:
-                ed25519 = sdesc.ed25519_master_key().rstrip('=')
-                log.debug('Found ed25519 master key.')
-                return ed25519
-            log.debug('Could not get server descriptor')
-            return None
-        log.debug('Relay has already ed25519 master key')
-        return ns.identifier
-
     def exits_can_exit_to(self, host, port):
         '''
         Return exits that can MOST LIKELY exit to the given host:port. **host**
@@ -179,13 +202,8 @@ class RelayList:
     def _init_relays(self):
         c = self._controller
         assert stem_utils.is_controller_okay(c)
-        relays = []
-        # for each network status relay, obtain the ed25519 master key
-        # and generate a new list of RelayNS objects
-        for ns in c.get_network_statuses():
-            ed25519 = self.relay_ed25519_master_key(ns)
-            rns = RelayNS(ed25519=ed25519, content=ns._raw_contents)
-            relays.append(rns)
+        relays = [Relay(ns.fingerprint, c, ns=ns)
+                  for ns in c.get_network_statuses()]
         return relays
 
     def _refresh(self):
diff --git a/sbws/lib/resultdump.py b/sbws/lib/resultdump.py
index 7cff36f..ffa493d 100644
--- a/sbws/lib/resultdump.py
+++ b/sbws/lib/resultdump.py
@@ -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__)
 
@@ -481,7 +481,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:
diff --git a/sbws/util/stem.py b/sbws/util/stem.py
index 5291bba..0341d74 100644
--- a/sbws/util/stem.py
+++ b/sbws/util/stem.py
@@ -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
@@ -223,7 +222,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:
diff --git a/tests/integration/lib/test_relaylist.py b/tests/integration/lib/test_relaylist.py
new file mode 100644
index 0000000..8f16ef8
--- /dev/null
+++ b/tests/integration/lib/test_relaylist.py
@@ -0,0 +1,17 @@
+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'
diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py
index 2847fe1..0701646 100644
--- a/tests/unit/conftest.py
+++ b/tests/unit/conftest.py
@@ -2,9 +2,8 @@ from sbws.lib.resultdump import ResultError
 from sbws.lib.resultdump import ResultSuccess
 from sbws.lib.resultdump import Result
 from sbws.lib.resultdump import write_result_to_datadir
-from sbws.util.config import get_config, _get_default_config
+from sbws.util.config import get_config
 from sbws.util.parser import create_parser
-import sbws.util.stem as stem_utils
 import sbws.core.init
 from tempfile import TemporaryDirectory
 import pytest
@@ -28,53 +27,6 @@ class _PseudoArguments(argparse.Namespace):
             setattr(self, key, kw[key])
 
 
- at pytest.fixture
-def tmpdir(tmpdir_factory, request):
-    base = str(hash(request.node.nodeid))[:3]
-    bn = tmpdir_factory.mktemp(base)
-    return bn
-
-
- at pytest.fixture()
-def datadir(request):
-    """ get, read, open test files from the "data" directory. """
-    class D:
-        def __init__(self, basepath):
-            self.basepath = basepath
-
-        def open(self, name, mode="r"):
-            return self.basepath.join(name).open(mode)
-
-        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()
-
-        def readlines(self, name):
-            with self.open(name, "r") as f:
-                return f.readlines()
-    return D(request.fspath.dirpath("data"))
-
-
- at pytest.fixture()
-def start_tor(request, tmpdir):
-    """Star Tor or connect to existing socket in a temporal directory."""
-    conf = _get_default_config()
-    home = tmpdir.join('.sbws')
-    conf['paths']['sbws_home'] = home.strpath
-    controller, _ = stem_utils.init_controller(
-                                 path=conf['tor']['control_socket'])
-    if not controller:
-        controller = stem_utils.launch_tor(conf)
-    return controller
-
-
 @pytest.fixture(scope='session')
 def parser():
     return create_parser()
diff --git a/tests/unit/lib/test_relaylist.py b/tests/unit/lib/test_relaylist.py
deleted file mode 100644
index cdb71c2..0000000
--- a/tests/unit/lib/test_relaylist.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from sbws.lib.relaylist import RelayList
-
-
-def test_relaylist_master_key_ed25519(start_tor):
-    # This test starts tor, so it is slow. And it will fail whenever there are
-    # network problems
-    controller = start_tor
-    rl = RelayList(None, None, controller)
-    relay = [r for r in rl.relays if r.nickname == 'moria1'][0]
-    assert relay.fingerprint == '9695DFC35FFEB861329B9F1AB04C46397020CE31'
-    assert relay.identifier is None
-    assert relay.master_key_ed25519 == \
-        'yp0fwtp4aa/VMyZJGz8vN7Km3zYet1YBZwqZEk1CwHI'





More information about the tor-commits mailing list