Skip to content
Snippets Groups Projects
Commit a4ecadb6 authored by Damian Johnson's avatar Damian Johnson
Browse files

Add stem.descriptor.get_bandwidth_file()

Tor now provides bandwidth files over its DirPort. Adding our corresponding
function to download them...

  https://trac.torproject.org/projects/tor/ticket/26902

From what I can tell these statistics are available in practice for our next
hour's consensus, but not the present one...

  atagar@morrigan:~$ curl -s 128.31.0.34:9131/tor/status-vote/next/bandwidth | wc -l
  8987

  atagar@morrigan:~$ curl -s 128.31.0.34:9131/tor/status-vote/current/bandwidth | wc -l
  0
parent 36dc1ff5
Branches
Tags
No related merge requests found
import stem.descriptor.remote
bandwidth_file = stem.descriptor.remote.get_bandwidth_file().run()[0]
for fingerprint, measurement in bandwidth_file.measurements.items():
print('Relay %s' % fingerprint)
for attr, value in measurement.items():
print(' %s = %s' % (attr, value))
print('')
......@@ -60,6 +60,7 @@ The following are only available within Stem's `git repository
* Ed25519 validity checks are now done though the cryptography module rather than PyNaCl (:trac:`22022`)
* Download compressed descriptors by default (:trac:`29186`)
* Added :func:`stem.descriptor.remote.get_microdescriptors`
* Added :func:`stem.descriptor.remote.get_bandwidth_file` (:trac:`26902`)
* Added :class:`~stem.descriptor.networkstatus.DetachedSignature` parsing (:trac:`28495`)
* Added :func:`~stem.descriptor.__init__.Descriptor.from_str` method (:trac:`28450`)
* Added :func:`~stem.descriptor.__init__.Descriptor.type_annotation` method (:trac:`28397`)
......
......@@ -134,6 +134,10 @@ Descriptors
Example for writing a Tor consensus to disk, and reading it back.
* `Bandwidth Heuristics <examples/bandwidth_stats.html>`_
Download bandwidth authority heuristics about relay capacity.
* `Checking Digests <examples/check_digests.html>`_
Looking for additional integrity that your descriptor is properly signed?
......
Bandwidth Heuristics
====================
.. image:: /_static/buttons/back.png
:target: ../double_double_toil_and_trouble.html
To select the relays it will use Tor consults several factors. Exit policies,
flags, as well as bandwidth heuristics so our circuits are zippy without
overtaxing individual relays.
These statistics are collected by a special subset of our directory authorites
called **bandwidth authorities**. See our `bandwidth file specification
<https://gitweb.torproject.org/torspec.git/tree/bandwidth-file-spec.txt>`_ for
details. Statistics are publicly available and generated each hour...
.. literalinclude:: /_static/example/bandwidth_stats.py
:language: python
::
% python bandwidth_stats.py
Relay 6AD3EA55B87C80971F353EBA710F6550202A9355
scanner = /scanner.5/scan-data/bws-59.4:60.1-done-2019-05-29-05:44:10
measured_at = 1559123050
pid_delta = -0.360692869958
updated_at = 1559123050
pid_error_sum = -0.178566523071
nick = OrphanOrOften
node_id = $6AD3EA55B87C80971F353EBA710F6550202A9355
pid_bw = 538334
bw = 538
pid_error = -0.178566523071
circ_fail = 0.0
Relay 11B6727E38D249C83E20EEB0647BAD4FACECBEB6
scanner = /scanner.8/scan-data/bws-92.4:93.1-done-2019-05-23-16:06:26
measured_at = 1558641986
pid_delta = 0.0352270644197
updated_at = 1558641986
pid_error_sum = -0.822158700788
nick = snap269
node_id = $11B6727E38D249C83E20EEB0647BAD4FACECBEB6
pid_bw = 21124
bw = 21
pid_error = -0.822158700788
circ_fail = 0.0
......@@ -61,6 +61,8 @@ content. For example...
|- get_extrainfo_descriptors - provides present extrainfo descriptors
|- get_microdescriptors - provides present microdescriptors with the given digests
|- get_consensus - provides the present consensus or router status entries
|- get_bandwidth_file - provies bandwidth heuristics used to make the next consensus
|- get_detached_signatures - authority signatures used to make the next consensus
|- get_key_certificates - provides present authority key certificates
+- query - request an arbitrary descriptor resource
......@@ -224,6 +226,18 @@ def get_consensus(authority_v3ident = None, microdescriptor = False, **query_arg
return get_instance().get_consensus(authority_v3ident, microdescriptor, **query_args)
def get_bandwidth_file(**query_args):
"""
Shorthand for
:func:`~stem.descriptor.remote.DescriptorDownloader.get_bandwidth_file`
on our singleton instance.
.. versionadded:: 1.8.0
"""
return get_instance().get_bandwidth_file(**query_args)
def get_detached_signatures(**query_args):
"""
Shorthand for
......@@ -291,6 +305,7 @@ class Query(object):
/tor/micro/d/<hash1>-<hash2> microdescriptors with the given hashes
/tor/status-vote/current/consensus present consensus
/tor/status-vote/current/consensus-microdesc present microdescriptor consensus
/tor/status-vote/next/bandwidth bandwidth authority heuristics for the next consenus
/tor/status-vote/next/consensus-signatures detached signature, used for making the next consenus
/tor/keys/all key certificates for the authorities
/tor/keys/fp/<v3ident1>+<v3ident2> key certificates for specific authorities
......@@ -849,6 +864,22 @@ class DescriptorDownloader(object):
return self.query(resource, **query_args)
def get_bandwidth_file(self, **query_args):
"""
Provides the bandwidth authority heuristics used to make the next
consensus.
.. versionadded:: 1.8.0
:param query_args: additional arguments for the
:class:`~stem.descriptor.remote.Query` constructor
:returns: :class:`~stem.descriptor.remote.Query` for the bandwidth
authority heuristics
"""
return self.query('/tor/status-vote/next/bandwidth', **query_args)
def get_detached_signatures(self, **query_args):
"""
Provides the detached signatures that will be used to make the next
......@@ -1070,15 +1101,21 @@ 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/next/consensus-signatures'):
return '%s 1.0' % DETACHED_SIGNATURE_TYPE
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/'):
return 'dir-key-certificate-3 1.0'
else:
elif resource.startswith('/tor/status-vote/'):
# The following resource urls can be for the present consensus
# (/tor/status-vote/current/*) or the next (/tor/status-vote/next/*).
if resource.endswith('/consensus'):
return 'network-status-consensus-3 1.0'
elif resource.endswith('/consensus-microdesc'):
return 'network-status-microdesc-consensus-3 1.0'
elif resource.endswith('/consensus-signatures'):
return '%s 1.0' % DETACHED_SIGNATURE_TYPE
elif resource.endswith('/bandwidth'):
return 'bandwidth-file 1.0'
raise ValueError("Unable to determine the descriptor type for '%s'" % resource)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment