commit 532f906755af6a1d9f281fde5def4e416146d0b2 Author: Damian Johnson atagar@torproject.org Date: Wed Nov 2 10:46:26 2016 -0700
Support downloading microdescriptor consensus
Fantastic, turns out tor supports this!
https://trac.torproject.org/projects/tor/ticket/20501#comment:5
Adding a new get_consensus() arg for getting the microdescriptor consensus. --- docs/change_log.rst | 1 + stem/descriptor/remote.py | 45 ++++++++++++++++++++++++++--------------- test/integ/descriptor/remote.py | 17 ++++++++++++++++ 3 files changed, 47 insertions(+), 16 deletions(-)
diff --git a/docs/change_log.rst b/docs/change_log.rst index 2959f6b..0d8dcf2 100644 --- a/docs/change_log.rst +++ b/docs/change_log.rst @@ -68,6 +68,7 @@ The following are only available within Stem's `git repository * `Shorthand functions for stem.descriptor.remote <api/descriptor/remote.html#stem.descriptor.remote.get_instance>`_ * Added `fallback directory information <api/descriptor/remote.html#stem.descriptor.remote.FallbackDirectory>`_. * Support for ed25519 descriptor fields (:spec:`5a79d67`) + * Support downloading microdescriptor consensus with :func:~stem.descriptor.remote.DescriptorDownloader.get_consensus` (:spec`e788b8f`) * Added consensus and vote's new shared randomness attributes (:spec:`9949f64`) * Added server descriptor's new allow_tunneled_dir_requests attribute (:spec:`8bc30d6`) * Server descriptor validation fails with 'extra-info-digest line had an invalid value' from additions in proposal 228 (:trac:`16227`) diff --git a/stem/descriptor/remote.py b/stem/descriptor/remote.py index b47ee2b..4283616 100644 --- a/stem/descriptor/remote.py +++ b/stem/descriptor/remote.py @@ -160,7 +160,7 @@ def get_extrainfo_descriptors(fingerprints = None, **query_args): return get_instance().get_extrainfo_descriptors(fingerprints, **query_args)
-def get_consensus(authority_v3ident = None, **query_args): +def get_consensus(authority_v3ident = None, microdescriptor = False, **query_args): """ Shorthand for :func:`~stem.descriptor.remote.DescriptorDownloader.get_consensus` @@ -169,7 +169,7 @@ def get_consensus(authority_v3ident = None, **query_args): .. versionadded:: 1.5.0 """
- return get_instance().get_consensus(authority_v3ident, **query_args) + return get_instance().get_consensus(authority_v3ident, microdescriptor, **query_args)
def _guess_descriptor_type(resource): @@ -182,6 +182,8 @@ def _guess_descriptor_type(resource): return 'extra-info 1.0' elif resource.startswith('/tor/micro/'): return 'microdescriptor 1.0' + elif resource.startswith('/tor/status-vote/current/consensus-microdesc'): + return 'network-status-microdesc-consensus-3 1.0' elif resource.startswith('/tor/status-vote/'): return 'network-status-consensus-3 1.0' elif resource.startswith('/tor/keys/'): @@ -236,18 +238,19 @@ class Query(object): https://gitweb.torproject.org/torspec.git/tree/dir-spec.txt`_). Commonly useful ones include...
- ===================================== =========== - Resource Description - ===================================== =========== - /tor/server/all.z all present server descriptors - /tor/server/fp/<fp1>+<fp2>+<fp3>.z server descriptors with the given fingerprints - /tor/extra/all.z all present extrainfo descriptors - /tor/extra/fp/<fp1>+<fp2>+<fp3>.z extrainfo descriptors with the given fingerprints - /tor/micro/d/<hash1>-<hash2>.z microdescriptors with the given hashes - /tor/status-vote/current/consensus.z present consensus - /tor/keys/all.z key certificates for the authorities - /tor/keys/fp/<v3ident1>+<v3ident2>.z key certificates for specific authorities - ===================================== =========== + =============================================== =========== + Resource Description + =============================================== =========== + /tor/server/all.z all present server descriptors + /tor/server/fp/<fp1>+<fp2>+<fp3>.z server descriptors with the given fingerprints + /tor/extra/all.z all present extrainfo descriptors + /tor/extra/fp/<fp1>+<fp2>+<fp3>.z extrainfo descriptors with the given fingerprints + /tor/micro/d/<hash1>-<hash2>.z microdescriptors with the given hashes + /tor/status-vote/current/consensus.z present consensus + /tor/status-vote/current/consensus-microdesc.z present microdescriptor consensus + /tor/keys/all.z key certificates for the authorities + /tor/keys/fp/<v3ident1>+<v3ident2>.z key certificates for specific authorities + =============================================== ===========
The '.z' suffix can be excluded to get a plaintext rather than compressed response. Compression is handled transparently, so this shouldn't matter to @@ -564,6 +567,8 @@ class DescriptorDownloader(object):
return self.query(resource, **query_args)
+ # TODO: drop in python 2.x + def get_microdescriptors(self, hashes, **query_args): """ Provides the microdescriptors with the given hashes. To get these see the @@ -595,14 +600,19 @@ class DescriptorDownloader(object):
return self.query('/tor/micro/d/%s.z' % '-'.join(hashes), **query_args)
- def get_consensus(self, authority_v3ident = None, **query_args): + def get_consensus(self, authority_v3ident = None, microdescriptor = False, **query_args): """ Provides the present router status entries.
+ .. versionchanged:: 1.5.0 + Added the microdescriptor argument. + :param str authority_v3ident: fingerprint of the authority key for which to get the consensus, see `'v3ident' in tor's config.c https://gitweb.torproject.org/tor.git/tree/src/or/config.c#n819`_ for the values. + :param bool microdescriptor: provides the microdescriptor consensus if + **True**, standard consensus otherwise :param query_args: additional arguments for the :class:`~stem.descriptor.remote.Query` constructor
@@ -610,7 +620,10 @@ class DescriptorDownloader(object): entries """
- resource = '/tor/status-vote/current/consensus' + if microdescriptor: + resource = '/tor/status-vote/current/consensus-microdesc' + else: + resource = '/tor/status-vote/current/consensus'
if authority_v3ident: resource += '/%s' % authority_v3ident diff --git a/test/integ/descriptor/remote.py b/test/integ/descriptor/remote.py index 52d29f0..098041d 100644 --- a/test/integ/descriptor/remote.py +++ b/test/integ/descriptor/remote.py @@ -184,6 +184,23 @@ class TestDescriptorDownloader(unittest.TestCase):
@require_online @only_run_once + def test_get_consensus_for_microdescriptors(self): + """ + Exercises the downloader's get_consensus() method for fetching a + microdescriptor consensus. + """ + + downloader = stem.descriptor.remote.DescriptorDownloader(validate = True) + + consensus_query = downloader.get_consensus(microdescriptor = True) + consensus_query.run() + + consensus = list(consensus_query) + self.assertTrue(len(consensus) > 50) + self.assertTrue(isinstance(consensus[0], stem.descriptor.router_status_entry.RouterStatusEntryMicroV3)) + + @require_online + @only_run_once def test_get_key_certificates(self): """ Exercises the downloader's get_key_certificates() method.
tor-commits@lists.torproject.org