commit 6e40a303a96fccd2db3e0370efc3d7d4c54d82a4 Author: Damian Johnson atagar@torproject.org Date: Mon May 7 10:57:39 2018 -0700
Deprecate is_bandwidth_authority attribute
This is a moving target that isn't tracked in tor, so I don't think we'll track it in Stem either. Folks can download the votes to check who is/isn't a bandwidth auth. This is how it's defined (providing bandwidth measurements in votes), after all. --- .../example/votes_by_bandwidth_authorities.py | 14 ++++---- stem/directory.py | 38 +++++++++------------- test/integ/directory/authority.py | 22 +------------ test/unit/directory/authority.py | 1 - 4 files changed, 24 insertions(+), 51 deletions(-)
diff --git a/docs/_static/example/votes_by_bandwidth_authorities.py b/docs/_static/example/votes_by_bandwidth_authorities.py index 9504bd94..840d50d8 100644 --- a/docs/_static/example/votes_by_bandwidth_authorities.py +++ b/docs/_static/example/votes_by_bandwidth_authorities.py @@ -7,11 +7,10 @@ queries = {} downloader = stem.descriptor.remote.DescriptorDownloader()
for authority in stem.directory.Authority.from_cache().values(): - if authority.is_bandwidth_authority: - queries[authority.nickname] = downloader.query( - '/tor/status-vote/current/authority', - endpoints = [(authority.address, authority.dir_port)], - ) + queries[authority.nickname] = downloader.query( + '/tor/status-vote/current/authority', + endpoints = [(authority.address, authority.dir_port)], + )
for authority_name, query in queries.items(): try: @@ -25,6 +24,9 @@ for authority_name, query in queries.items(): else: unmeasured += 1
- print(' %i measured entries and %i unmeasured' % (measured, unmeasured)) + if measured == 0: + print(' %s is not a bandwidth authority' % authority_name) + else: + print(' %i measured entries and %i unmeasured' % (measured, unmeasured)) except Exception as exc: print(" failed to get the vote (%s)" % exc) diff --git a/stem/directory.py b/stem/directory.py index 7b78696a..c70cbecf 100644 --- a/stem/directory.py +++ b/stem/directory.py @@ -2,7 +2,7 @@ # See LICENSE for licensing information
""" -Directories with `tor descriptor information +Directories that provide `relay descriptor information <../tutorials/mirror_mirror_on_the_wall.html>`_. At a very high level tor works as follows...
@@ -60,7 +60,7 @@ except ImportError:
GITWEB_AUTHORITY_URL = 'https://gitweb.torproject.org/tor.git/plain/src/or/auth_dirs.inc' GITWEB_FALLBACK_URL = 'https://gitweb.torproject.org/tor.git/plain/src/or/fallback_dirs.inc' -CACHE_PATH = os.path.join(os.path.dirname(__file__), 'cached_fallbacks.cfg') +FALLBACK_CACHE_PATH = os.path.join(os.path.dirname(__file__), 'cached_fallbacks.cfg')
AUTHORITY_NAME = re.compile('"(\S+) orport=(\d+) .*"') AUTHORITY_V3IDENT = re.compile('"v3ident=([\dA-F]{40}) "') @@ -78,14 +78,14 @@ FALLBACK_IPV6 = re.compile('" ipv6=[([\da-f:]+)]:(\d+)"')
class Directory(object): """ - Relay we can contact for directory information. + Relay we can contact for descriptor information.
Our :func:`~stem.directory.Directory.from_cache` and :func:`~stem.directory.Directory.from_remote` functions key off a different identifier based on our subclass...
- * **Authority** keys off the nickname. - * **Fallback** keys off fingerprints. + * :class:`~stem.directory.Authority` keys off the nickname. + * :class:`~stem.directory.Fallback` keys off fingerprints.
This is because authorities are highly static and canonically known by their names, whereas fallbacks vary more and don't necessarily have a nickname to @@ -112,8 +112,8 @@ class Directory(object): def from_cache(): """ Provides cached Tor directory information. This information is hardcoded - into Tor and occasionally changes, so the information this provides might - not necessarily match the latest version of tor. + into Tor and occasionally changes, so the information provided by this + method may not necessarily match the latest version of tor.
.. versionadded:: 1.5.0
@@ -169,14 +169,16 @@ class Authority(Directory): """ Tor directory authority, a special type of relay `hardcoded into tor https://gitweb.torproject.org/tor.git/plain/src/or/auth_dirs.inc`_ - that enumerates the other relays within the network. + to enumerate the relays in the network.
.. versionchanged:: 1.3.0 Added the is_bandwidth_authority attribute.
+ .. deprecated:: 1.7.0 + The is_bandwidth_authority attribute is deprecated and will be removed in + the future. + :var str v3ident: identity key fingerprint used to sign votes and consensus - :var bool is_bandwidth_authority: **True** if this is a bandwidth authority, - **False** otherwise """
def __init__(self, address = None, or_port = None, dir_port = None, fingerprint = None, nickname = None, v3ident = None, is_bandwidth_authority = False): @@ -357,7 +359,7 @@ class Fallback(Directory): self.header = header if header else OrderedDict()
@staticmethod - def from_cache(path = CACHE_PATH): + def from_cache(path = FALLBACK_CACHE_PATH): conf = stem.util.conf.Config() conf.load(path) headers = OrderedDict([(k.split('.', 1)[1], conf.get(k)) for k in conf.keys() if k.startswith('header.')]) @@ -375,7 +377,7 @@ class Fallback(Directory): attr[attr_name] = conf.get(key)
if not attr[attr_name] and attr_name not in ('nickname', 'has_extrainfo', 'orport6_address', 'orport6_port'): - raise IOError("'%s' is missing from %s" % (key, CACHE_PATH)) + raise IOError("'%s' is missing from %s" % (key, FALLBACK_CACHE_PATH))
if not connection.is_valid_ipv4_address(attr['address']): raise IOError("'%s.address' was an invalid IPv4 address (%s)" % (fingerprint, attr['address'])) @@ -540,7 +542,7 @@ class Fallback(Directory): return section_lines
@staticmethod - def _write(fallbacks, tor_commit, stem_commit, headers, path = CACHE_PATH): + def _write(fallbacks, tor_commit, stem_commit, headers, path = FALLBACK_CACHE_PATH): """ Persists fallback directories to a location in a way that can be read by from_cache(). @@ -635,7 +637,6 @@ DIRECTORY_AUTHORITIES = { address = '128.31.0.39', or_port = 9101, dir_port = 9131, - is_bandwidth_authority = True, fingerprint = '9695DFC35FFEB861329B9F1AB04C46397020CE31', v3ident = 'D586D18309DED4CD6D57C18FDB97EFA96D330566', ), @@ -644,7 +645,6 @@ DIRECTORY_AUTHORITIES = { address = '86.59.21.38', or_port = 443, dir_port = 80, - is_bandwidth_authority = False, fingerprint = '847B1F850344D7876491A54892F904934E4EB85D', v3ident = '14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4', ), @@ -653,7 +653,6 @@ DIRECTORY_AUTHORITIES = { address = '194.109.206.212', or_port = 443, dir_port = 80, - is_bandwidth_authority = False, fingerprint = '7EA6EAD6FD83083C538F44038BBFA077587DD755', v3ident = 'E8A9C45EDE6D711294FADF8E7951F4DE6CA56B58', ), @@ -662,7 +661,6 @@ DIRECTORY_AUTHORITIES = { address = '131.188.40.189', or_port = 443, dir_port = 80, - is_bandwidth_authority = True, fingerprint = 'F2044413DAC2E02E3D6BCF4735A19BCA1DE97281', v3ident = 'ED03BB616EB2F60BEC80151114BB25CEF515B226', ), @@ -671,7 +669,6 @@ DIRECTORY_AUTHORITIES = { address = '193.23.244.244', or_port = 443, dir_port = 80, - is_bandwidth_authority = False, fingerprint = '7BE683E65D48141321C5ED92F075C55364AC7123', v3ident = '0232AF901C31A04EE9848595AF9BB7620D4C5B2E', ), @@ -680,7 +677,6 @@ DIRECTORY_AUTHORITIES = { address = '171.25.193.9', or_port = 80, dir_port = 443, - is_bandwidth_authority = True, fingerprint = 'BD6A829255CB08E66FBE7D3748363586E46B3810', v3ident = '49015F787433103580E3B66A1707A00E60F2D15B', ), @@ -689,7 +685,6 @@ DIRECTORY_AUTHORITIES = { address = '154.35.175.225', or_port = 443, dir_port = 80, - is_bandwidth_authority = True, fingerprint = 'CF6D0AAFB385BE71B8E111FC5CFF4B47923733BC', v3ident = 'EFCBE720AB3A82B99F9E953CD5BF50F7EEFC7B97', ), @@ -698,7 +693,6 @@ DIRECTORY_AUTHORITIES = { address = '199.58.81.140', or_port = 443, dir_port = 80, - is_bandwidth_authority = False, fingerprint = '74A910646BCEEFBCD2E874FC1DC997430F968145', v3ident = '23D15D965BC35114467363C165C4F724B64B4F66', ), @@ -707,7 +701,6 @@ DIRECTORY_AUTHORITIES = { address = '204.13.164.118', or_port = 443, dir_port = 80, - is_bandwidth_authority = True, fingerprint = '24E2F139121D4394C54B5BCC368B3B411857C413', v3ident = '27102BC123E7AF1D4741AE047E160C91ADC76B21', ), @@ -716,7 +709,6 @@ DIRECTORY_AUTHORITIES = { address = '37.218.247.217', or_port = 443, dir_port = 80, - is_bandwidth_authority = False, fingerprint = '1D8F3A91C37C5D1C4C19B1AD1D0CFBE8BF72D8E1', v3ident = None, # does not vote in the consensus ), diff --git a/test/integ/directory/authority.py b/test/integ/directory/authority.py index fc5eb13e..c188fae3 100644 --- a/test/integ/directory/authority.py +++ b/test/integ/directory/authority.py @@ -15,24 +15,4 @@ class TestAuthority(unittest.TestCase): Check if the cached authorities we bundle are up to date. """
- cached_authorities = stem.directory.Authority.from_cache() - latest_authorities = stem.directory.Authority.from_remote() - - for nickname in cached_authorities: - if nickname not in latest_authorities: - self.fail('%s is no longer a directory authority in tor' % nickname) - - for nickname in latest_authorities: - if nickname not in cached_authorities: - self.fail('%s is now a directory authority in tor' % nickname) - - # tor doesn't note if an autority is a bwauth or not, so we need to exclude - # that from our comparison - - for attr in ('address', 'or_port', 'dir_port', 'fingerprint', 'nickname', 'v3ident'): - for auth in cached_authorities.values(): - cached_value = getattr(auth, attr) - latest_value = getattr(latest_authorities[auth.nickname], attr) - - if cached_value != latest_value: - self.fail('The %s of the %s authority is %s in tor but %s in stem' % (attr, auth.nickname, latest_value, cached_value)) + self.assertEqual(stem.directory.Authority.from_cache(), stem.directory.Authority.from_remote()) diff --git a/test/unit/directory/authority.py b/test/unit/directory/authority.py index dcee4916..431cbf52 100644 --- a/test/unit/directory/authority.py +++ b/test/unit/directory/authority.py @@ -36,7 +36,6 @@ class TestAuthority(unittest.TestCase): 'fingerprint': '0756B7CD4DFC8182BE23143FAC0642F515182CEB', 'nickname': 'rueckgrat', 'v3ident': '23D15D965BC35114467363C165C4F724B64B4F66', - 'is_bandwidth_authority': False, }
self.assertEqual(stem.directory.Authority(**authority_attr), stem.directory.Authority(**authority_attr))