[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [stem/master] Add stem.descriptor.get_bandwidth_file()
commit a4ecadb65c467fe277f205b47a2e3c93897d9891
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Thu May 30 11:00:31 2019 -0700
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
---
docs/_static/example/bandwidth_stats.py | 11 +++++
docs/change_log.rst | 1 +
docs/tutorials/double_double_toil_and_trouble.rst | 4 ++
docs/tutorials/examples/bandwidth_stats.rst | 48 ++++++++++++++++++++
stem/descriptor/remote.py | 53 +++++++++++++++++++----
5 files changed, 109 insertions(+), 8 deletions(-)
diff --git a/docs/_static/example/bandwidth_stats.py b/docs/_static/example/bandwidth_stats.py
new file mode 100644
index 00000000..e7e11ceb
--- /dev/null
+++ b/docs/_static/example/bandwidth_stats.py
@@ -0,0 +1,11 @@
+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('')
diff --git a/docs/change_log.rst b/docs/change_log.rst
index fc09eabc..fec98f5b 100644
--- a/docs/change_log.rst
+++ b/docs/change_log.rst
@@ -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`)
diff --git a/docs/tutorials/double_double_toil_and_trouble.rst b/docs/tutorials/double_double_toil_and_trouble.rst
index 6e5df2cf..b631d479 100644
--- a/docs/tutorials/double_double_toil_and_trouble.rst
+++ b/docs/tutorials/double_double_toil_and_trouble.rst
@@ -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?
diff --git a/docs/tutorials/examples/bandwidth_stats.rst b/docs/tutorials/examples/bandwidth_stats.rst
new file mode 100644
index 00000000..3cfddfea
--- /dev/null
+++ b/docs/tutorials/examples/bandwidth_stats.rst
@@ -0,0 +1,48 @@
+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
+
diff --git a/stem/descriptor/remote.py b/stem/descriptor/remote.py
index c663276b..ab2fc091 100644
--- a/stem/descriptor/remote.py
+++ b/stem/descriptor/remote.py
@@ -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,16 +1101,22 @@ 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:
- raise ValueError("Unable to determine the descriptor type for '%s'" % resource)
+ 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)
def get_authorities():
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits