From 1b52464df578753739e02e3fa1a37f40b54309dd Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone <exarkun@twistedmatrix.com> Date: Mon, 8 Nov 2021 14:10:21 -0500 Subject: [PATCH] test unrecognized unsuccessful redemption reason case, and fix it --- src/_zkapauthorizer/controller.py | 10 +++++++ src/_zkapauthorizer/tests/test_controller.py | 29 ++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/_zkapauthorizer/controller.py b/src/_zkapauthorizer/controller.py index 62d65c8..d86a8b8 100644 --- a/src/_zkapauthorizer/controller.py +++ b/src/_zkapauthorizer/controller.py @@ -78,6 +78,14 @@ class Unpaid(Exception): """ +class UnrecognizedFailureReason(Exception): + """ + An attempt was made to redeem a voucher and the response contained an unknown reason. + + The redemption attempt may be automatically retried at some point. + """ + + @attr.s class RedemptionResult(object): """ @@ -522,6 +530,8 @@ class RistrettoRedeemer(object): elif reason == u"unpaid": raise Unpaid(voucher) + raise UnrecognizedFailureReason() + self._log.info( "Redeemed: {public_key} {proof} {count}", public_key=result[u"public-key"], diff --git a/src/_zkapauthorizer/tests/test_controller.py b/src/_zkapauthorizer/tests/test_controller.py index a87548d..51aa113 100644 --- a/src/_zkapauthorizer/tests/test_controller.py +++ b/src/_zkapauthorizer/tests/test_controller.py @@ -58,6 +58,7 @@ from twisted.web.resource import ErrorPage, Resource from zope.interface import implementer from ..controller import ( + UnrecognizedFailureReason, AlreadySpent, DoubleSpendRedeemer, ErrorRedeemer, @@ -885,6 +886,34 @@ class RistrettoRedeemerTests(TestCase): ), ) + @given(voucher_objects(), voucher_counters(), integers(min_value=0, max_value=100)) + def test_redemption_unknown_response(self, voucher, counter, extra_tokens): + """ + If the issuer returns a failure without a recognizable reason then + ``RistrettoRedeemer.redeemWithCounter`` returns a ``Deferred`` that + fails with ``UnrecognizedFailureReason``. + """ + num_tokens = counter + extra_tokens + issuer = UnsuccessfulRedemption(u"mysterious") + treq = treq_for_loopback_ristretto(issuer) + redeemer = RistrettoRedeemer(treq, NOWHERE) + random_tokens = redeemer.random_tokens_for_voucher(voucher, counter, num_tokens) + d = redeemer.redeemWithCounter( + voucher, + counter, + random_tokens, + ) + self.assertThat( + d, + failed( + AfterPreprocessing( + lambda f: f.value, + IsInstance(UnrecognizedFailureReason), + ), + ), + ) + + @given(voucher_objects(), voucher_counters(), integers(min_value=0, max_value=100)) def test_bad_ristretto_redemption(self, voucher, counter, extra_tokens): """ -- GitLab