diff --git a/src/_zkapauthorizer/_plugin.py b/src/_zkapauthorizer/_plugin.py index 4ba84ddd840e6a56e7cf54fd0ed6ae8bc3449f40..a1935a562ad674d8895951d19d2881977357c192 100644 --- a/src/_zkapauthorizer/_plugin.py +++ b/src/_zkapauthorizer/_plugin.py @@ -175,12 +175,24 @@ class ZKAPAuthorizer(object): ) - def get_client_resource(self, node_config): + def get_client_resource(self, node_config, default_token_count=None): + """ + Get an ``IZKAPRoot`` for the given node configuration. + + :param allmydata.node._Config node_config: The configuration object + for the relevant node. + + :param int default_token_count: Configure the payment controller with + a default number of tokens to request during voucher redemption. + This is only used if a number of tokens isn't specified at the + point of redemption. + """ from twisted.internet import reactor return resource_from_configuration( node_config, store=self._get_store(node_config), redeemer=self._get_redeemer(node_config, None, reactor), + default_token_count=default_token_count, ) diff --git a/src/_zkapauthorizer/controller.py b/src/_zkapauthorizer/controller.py index bee2bf301eca18189507fbb0394f43627da16560..720366e1c64738bae7770696431a5f2291c4ce19 100644 --- a/src/_zkapauthorizer/controller.py +++ b/src/_zkapauthorizer/controller.py @@ -90,9 +90,6 @@ from .model import ( Error as model_Error, ) -# The number of tokens to submit with a voucher redemption. -NUM_TOKENS = 512000 - RETRY_INTERVAL = timedelta(minutes=3) class AlreadySpent(Exception): @@ -535,6 +532,10 @@ class PaymentController(object): the voucher. The data store marks the voucher as redeemed and stores the unblinded tokens for use by the storage client. + :ivar int default_token_count: The number of tokens to request when + redeeming a voucher, if no other count is given when the redemption is + started. + :ivar dict[unicode, datetime] _active: A mapping from voucher identifiers which currently have redemption attempts in progress to timestamps when the attempt began. @@ -551,6 +552,7 @@ class PaymentController(object): store = attr.ib() redeemer = attr.ib() + default_token_count = attr.ib() _clock = attr.ib( default=attr.Factory(partial(namedAny, "twisted.internet.reactor")), @@ -664,7 +666,7 @@ class PaymentController(object): # number of passes that can be constructed is still only the size of # the set of random tokens. if num_tokens is None: - num_tokens = NUM_TOKENS + num_tokens = self.default_token_count tokens = self._get_random_tokens_for_voucher(voucher, num_tokens) return self._perform_redeem(voucher, tokens) diff --git a/src/_zkapauthorizer/resource.py b/src/_zkapauthorizer/resource.py index 8841479122b40287f0086c0b2ba426cd76063742..79c8d3146e82c3d42b5c5a9f404ee8496eaafd85 100644 --- a/src/_zkapauthorizer/resource.py +++ b/src/_zkapauthorizer/resource.py @@ -58,6 +58,10 @@ from .controller import ( get_redeemer, ) +# The number of tokens to submit with a voucher redemption. +NUM_TOKENS = 512000 + + class IZKAPRoot(IResource): """ The root of the resource tree of this plugin's client web presence. @@ -66,7 +70,7 @@ class IZKAPRoot(IResource): controller = Attribute("The ``PaymentController`` used by this resource tree.") -def from_configuration(node_config, store, redeemer=None): +def from_configuration(node_config, store, redeemer=None, default_token_count=None): """ Instantiate the plugin root resource using data from its configuration section, **storageclient.plugins.privatestorageio-zkapauthz-v1**, in the @@ -93,7 +97,9 @@ def from_configuration(node_config, store, redeemer=None): None, None, ) - controller = PaymentController(store, redeemer) + if default_token_count is None: + default_token_count = NUM_TOKENS + controller = PaymentController(store, redeemer, default_token_count) root = Resource() root.store = store root.controller = controller diff --git a/src/_zkapauthorizer/tests/test_client_resource.py b/src/_zkapauthorizer/tests/test_client_resource.py index 402ea78c41cc0cbd449858c7895f50295d5248f1..f901d020fa1e23d9b26c141369996560d00a0d44 100644 --- a/src/_zkapauthorizer/tests/test_client_resource.py +++ b/src/_zkapauthorizer/tests/test_client_resource.py @@ -130,9 +130,6 @@ from ..model import ( VoucherStore, memory_connect, ) -from ..controller import ( - NUM_TOKENS, -) from ..resource import ( from_configuration, ) @@ -156,6 +153,9 @@ from .matchers import ( Provides, ) +# A small number of tokens to work with in the tests. +NUM_TOKENS = 10 + TRANSIENT_ERROR = u"something went wrong, who knows what" # Helper to work-around https://github.com/twisted/treq/issues/161 @@ -251,6 +251,7 @@ def root_from_config(config, now): now, memory_connect, ), + default_token_count=NUM_TOKENS, ) @@ -911,10 +912,7 @@ class VoucherTests(TestCase): created=now, state=Redeemed( finished=now, - # Value duplicated from - # PaymentController.redeem - # default. Should do this better. - token_count=100, + token_count=NUM_TOKENS, ), ).marshal() for voucher diff --git a/src/_zkapauthorizer/tests/test_controller.py b/src/_zkapauthorizer/tests/test_controller.py index dec0176991e75bc905b725fd6a08ba165c4b1d3c..0dd8bdd7d982f14eea28abfbe27adb34cc81bd7a 100644 --- a/src/_zkapauthorizer/tests/test_controller.py +++ b/src/_zkapauthorizer/tests/test_controller.py @@ -139,6 +139,7 @@ class PaymentControllerTests(TestCase): controller = PaymentController( store, NonRedeemer(), + default_token_count=10, ) controller.redeem(voucher) @@ -157,6 +158,7 @@ class PaymentControllerTests(TestCase): controller = PaymentController( store, DummyRedeemer(), + default_token_count=10, ) controller.redeem(voucher) @@ -165,7 +167,7 @@ class PaymentControllerTests(TestCase): persisted_voucher.state, Equals(model_Redeemed( finished=now, - token_count=100, + token_count=10, )), ) @@ -179,6 +181,7 @@ class PaymentControllerTests(TestCase): controller = PaymentController( store, DoubleSpendRedeemer(), + default_token_count=10, ) controller.redeem(voucher) @@ -204,6 +207,7 @@ class PaymentControllerTests(TestCase): unpaid_controller = PaymentController( store, UnpaidRedeemer(), + default_token_count=10, ) unpaid_controller.redeem(voucher) @@ -219,6 +223,7 @@ class PaymentControllerTests(TestCase): success_controller = PaymentController( store, DummyRedeemer(), + default_token_count=10, ) self.assertThat( @@ -247,7 +252,8 @@ class PaymentControllerTests(TestCase): controller = PaymentController( store, UnpaidRedeemer(), - clock, + default_token_count=10, + clock=clock, ) controller.redeem(voucher) # It fails this time. diff --git a/src/_zkapauthorizer/tests/test_plugin.py b/src/_zkapauthorizer/tests/test_plugin.py index e9c8eecc3ce3290ca8bafb2f286b600442f47c6a..41c2dd43f4b3bd240ec9bbf852fe19e93c328de0 100644 --- a/src/_zkapauthorizer/tests/test_plugin.py +++ b/src/_zkapauthorizer/tests/test_plugin.py @@ -461,7 +461,7 @@ class ClientResourceTests(TestCase): nodedir = tempdir.join(b"node") config = get_config(nodedir, b"tub.port") self.assertThat( - storage_server.get_client_resource(config), + storage_server.get_client_resource(config, default_token_count=10), Provides([IResource]), )