From fb20954d84f1362c30eedcdc23161676a69075be Mon Sep 17 00:00:00 2001
From: Jean-Paul Calderone <exarkun@twistedmatrix.com>
Date: Wed, 10 Jun 2020 11:31:32 -0400
Subject: [PATCH] Spend the tokens even if the server *doesn't* already have
 any shares

---
 src/_zkapauthorizer/_storage_client.py        | 21 +++++++++---------
 .../tests/test_storage_protocol.py            | 22 +++++++++++++++++++
 2 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/src/_zkapauthorizer/_storage_client.py b/src/_zkapauthorizer/_storage_client.py
index bcc46d7..684389e 100644
--- a/src/_zkapauthorizer/_storage_client.py
+++ b/src/_zkapauthorizer/_storage_client.py
@@ -311,17 +311,16 @@ class ZKAPAuthorizerStorageClient(object):
             allocated.
         """
         alreadygot, bucketwriters = result
-        if alreadygot:
-            # Passes only need to be spent for buckets that are being
-            # allocated.  Someone already paid for any shares the server
-            # already has.
-            actual_passes = required_passes(
-                self._pass_value,
-                [allocated_size] * len(bucketwriters),
-            )
-            to_spend, to_reset = pass_group.split(range(actual_passes))
-            to_spend.mark_spent()
-            to_reset.reset()
+        # Passes only need to be spent for buckets that are being
+        # allocated.  Someone already paid for any shares the server
+        # already has.
+        actual_passes = required_passes(
+            self._pass_value,
+            [allocated_size] * len(bucketwriters),
+        )
+        to_spend, to_reset = pass_group.split(range(actual_passes))
+        to_spend.mark_spent()
+        to_reset.reset()
 
     @with_rref
     def allocate_buckets(
diff --git a/src/_zkapauthorizer/tests/test_storage_protocol.py b/src/_zkapauthorizer/tests/test_storage_protocol.py
index f1dba77..873b188 100644
--- a/src/_zkapauthorizer/tests/test_storage_protocol.py
+++ b/src/_zkapauthorizer/tests/test_storage_protocol.py
@@ -313,6 +313,9 @@ class ShareTests(TestCase):
         # up between iterations.
         cleanup_storage_server(self.anonymous_storage_server)
 
+        # Oops our pass factory, too. :(
+        self.pass_factory._clear()
+
         alreadygot, allocated = extract_result(
             self.client.allocate_buckets(
                 storage_index,
@@ -354,6 +357,25 @@ class ShareTests(TestCase):
                 ),
             )
 
+        # Enough passes for all the sharenums should have been spent.
+        anticipated_passes = required_passes(
+            self.pass_value,
+            [size] * len(sharenums),
+        )
+
+        self.assertThat(
+            self.pass_factory,
+            MatchesStructure(
+                issued=HasLength(anticipated_passes),
+                spent=HasLength(anticipated_passes),
+
+                returned=HasLength(0),
+                in_use=HasLength(0),
+                invalid=HasLength(0),
+            ),
+        )
+
+
     @given(
         storage_index=storage_indexes(),
         renew_secret=lease_renew_secrets(),
-- 
GitLab