[tor-commits] [stem/master] Parse 'bandwidth-file-digest' lines from votes

atagar at torproject.org atagar at torproject.org
Mon Nov 19 18:44:52 UTC 2018


commit e810cc093a6469e26fe57789f064cb627f017e64
Author: Damian Johnson <atagar at torproject.org>
Date:   Mon Nov 19 10:43:00 2018 -0800

    Parse 'bandwidth-file-digest' lines from votes
    
    Parsing of a newly added field...
    
      https://gitweb.torproject.org/torspec.git/commit/?id=1b686ef
---
 docs/change_log.rst                               |  3 ++-
 stem/descriptor/networkstatus.py                  | 21 +++++++++++++++++++
 test/unit/descriptor/networkstatus/document_v3.py | 25 +++++++++++++++++++++++
 3 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/docs/change_log.rst b/docs/change_log.rst
index 0c427784..2fb3ae7e 100644
--- a/docs/change_log.rst
+++ b/docs/change_log.rst
@@ -53,6 +53,7 @@ The following are only available within Stem's `git repository
 
   * Added :func:`~stem.descriptor.Descriptor.type_annotation` method (:trac:`28397`)
   * Added the **hash_type** and **encoding** arguments to `ServerDescriptor <api/descriptor/server_descriptor.html#stem.descriptor.server_descriptor.ServerDescriptor.digest>`_ and `ExtraInfo's <api/descriptor/extrainfo_descriptor.html#stem.descriptor.extrainfo_descriptor.ExtraInfoDescriptor.digest>`_ digest methods (:trac:`28398`)
+  * Added the network status vote's new bandwidth_file_digest attribute (:spec:`1b686ef`)
   * Added :func:`~stem.descriptor.networkstatus.NetworkStatusDocumentV3.is_valid` and :func:`~stem.descriptor.networkstatus.NetworkStatusDocumentV3.is_fresh` methods (:trac:`28448`)
   * DescriptorDownloader crashed if **use_mirrors** is set (:trac:`28393`)
   * Don't download from Serge, a bridge authority that frequently timeout
@@ -102,7 +103,7 @@ and the `stem.directory module <api/directory.html>`_.
   * `Fallback directory v2 support <https://lists.torproject.org/pipermail/tor-dev/2017-December/012721.html>`_, which adds *nickname* and *extrainfo*
   * Added the *orport_v6* attribute to the :class:`~stem.directory.Authority` class
   * Added server descriptor's new is_hidden_service_dir attribute
-  * Added the network status vote's new bandwidth_file attribute (:spec:`84591df`)
+  * Added the network status vote's new bandwidth_file_headers attribute (:spec:`84591df`)
   * Added the microdescriptor router status entry's new or_addresses attribute (:trac:`26405`, :spec:`fdc8f3e8`)
   * Don't retry downloading descriptors when we've timed out
   * Don't download from tor26, an authority that frequently timeout
diff --git a/stem/descriptor/networkstatus.py b/stem/descriptor/networkstatus.py
index 6c14097f..bc34f5b4 100644
--- a/stem/descriptor/networkstatus.py
+++ b/stem/descriptor/networkstatus.py
@@ -135,6 +135,7 @@ HEADER_STATUS_DOCUMENT_FIELDS = (
   ('shared-rand-previous-value', True, True, False),
   ('shared-rand-current-value', True, True, False),
   ('bandwidth-file-headers', True, False, False),
+  ('bandwidth-file-digest', True, False, False),
   ('recommended-client-protocols', True, True, False),
   ('recommended-relay-protocols', True, True, False),
   ('required-client-protocols', True, True, False),
@@ -796,6 +797,18 @@ def _parse_bandwidth_file_headers(descriptor, entries):
   descriptor.bandwidth_file_headers = results
 
 
+def _parse_bandwidth_file_digest(descriptor, entries):
+  # "bandwidth-file-digest" 1*(SP algorithm "=" digest)
+
+  value = _value('bandwidth-file-digest', entries)
+  results = {}
+
+  for key, val in _mappings_for('bandwidth-file-digest', value):
+    results[key] = val
+
+  descriptor.bandwidth_file_digest = results
+
+
 _parse_header_valid_after_line = _parse_timestamp_line('valid-after', 'valid_after')
 _parse_header_fresh_until_line = _parse_timestamp_line('fresh-until', 'fresh_until')
 _parse_header_valid_until_line = _parse_timestamp_line('valid-until', 'valid_until')
@@ -867,6 +880,9 @@ class NetworkStatusDocumentV3(NetworkStatusDocument):
   :var dict required_relay_protocols: required protocols for relays
   :var dict bandwidth_file_headers: headers from the bandwidth authority that
     generated this vote
+  :var dict bandwidth_file_digest: hashes of the bandwidth authority file used
+    to generate this vote, this is a mapping of hash functions to their resulting
+    digest value
 
   **\*** attribute is either required when we're parsed with validation or has
   a default value, others are left as None if undefined
@@ -898,6 +914,9 @@ class NetworkStatusDocumentV3(NetworkStatusDocument):
 
   .. versionchanged:: 1.7.0
      Added the bandwidth_file_headers attributbute.
+
+  .. versionchanged:: 1.8.0
+     Added the bandwidth_file_digest attributbute.
   """
 
   ATTRIBUTES = {
@@ -929,6 +948,7 @@ class NetworkStatusDocumentV3(NetworkStatusDocument):
     'shared_randomness_current_reveal_count': (None, _parse_shared_rand_current_value),
     'shared_randomness_current_value': (None, _parse_shared_rand_current_value),
     'bandwidth_file_headers': ({}, _parse_bandwidth_file_headers),
+    'bandwidth_file_digest': ({}, _parse_bandwidth_file_digest),
 
     'signatures': ([], _parse_footer_directory_signature_line),
     'bandwidth_weights': ({}, _parse_footer_bandwidth_weights_line),
@@ -957,6 +977,7 @@ class NetworkStatusDocumentV3(NetworkStatusDocument):
     'shared-rand-previous-value': _parse_shared_rand_previous_value,
     'shared-rand-current-value': _parse_shared_rand_current_value,
     'bandwidth-file-headers': _parse_bandwidth_file_headers,
+    'bandwidth-file-digest': _parse_bandwidth_file_digest,
   }
 
   FOOTER_PARSER_FOR_LINE = {
diff --git a/test/unit/descriptor/networkstatus/document_v3.py b/test/unit/descriptor/networkstatus/document_v3.py
index a9e5f35b..92100141 100644
--- a/test/unit/descriptor/networkstatus/document_v3.py
+++ b/test/unit/descriptor/networkstatus/document_v3.py
@@ -1312,6 +1312,31 @@ DnN5aFtYKiTc19qIC7Nmo+afPdDEf0MlJvEOP5EWl3w=
     document = NetworkStatusDocumentV3(content, False)
     self.assertEqual({}, document.bandwidth_file_headers)
 
+  def test_bandwidth_file_digest(self):
+    """
+    Parses a 'bandwidth-file-digest' line of votes.
+    """
+
+    test_values = {
+      '': {},
+      'sha1=': {'sha1': ''},
+      'sha1=abc=def': {'sha1': 'abc=def'},
+      'sha1=123': {'sha1': '123'},
+      'sha1=123 sha256=456': {'sha1': '123', 'sha256': '456'},
+    }
+
+    for test_value, expected_value in test_values.items():
+      document = NetworkStatusDocumentV3.create({'vote-status': 'vote', 'bandwidth-file-digest': test_value})
+      self.assertEqual(expected_value, document.bandwidth_file_digest)
+
+    # field must be key=value mappings
+
+    content = NetworkStatusDocumentV3.content({'vote-status': 'vote', 'bandwidth-file-digest': 'key_without_value'})
+    self.assertRaises(ValueError, NetworkStatusDocumentV3, content, True)
+
+    document = NetworkStatusDocumentV3(content, False)
+    self.assertEqual({}, document.bandwidth_file_digest)
+
   def test_with_legacy_directory_authorities(self):
     """
     Includes both normal authorities and those following the '-legacy' format.



More information about the tor-commits mailing list