From c8b9a224e70f70ccc638b2c4200a505cdf024efd Mon Sep 17 00:00:00 2001 From: Samuel Dobson Date: Tue, 23 Nov 2021 12:17:34 +1300 Subject: [PATCH] Report encoding type in bech32 error message --- src/bech32.cpp | 8 +++++++- src/test/bech32_tests.cpp | 8 ++++---- test/functional/rpc_invalid_address_message.py | 10 +++++----- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/bech32.cpp b/src/bech32.cpp index ec69965d07d..7585ee944ca 100644 --- a/src/bech32.cpp +++ b/src/bech32.cpp @@ -7,6 +7,7 @@ #include #include +#include namespace bech32 { @@ -539,6 +540,7 @@ std::string LocateErrors(const std::string& str, std::vector& error_locatio // We attempt error detection with both bech32 and bech32m, and choose the one with the fewest errors // We can't simply use the segwit version, because that may be one of the errors + std::optional error_encoding; for (Encoding encoding : {Encoding::BECH32, Encoding::BECH32M}) { std::vector possible_errors; // Recall that (ExpandHRP(hrp) ++ values) is interpreted as a list of coefficients of a polynomial @@ -657,9 +659,13 @@ std::string LocateErrors(const std::string& str, std::vector& error_locatio if (error_locations.empty() || (!possible_errors.empty() && possible_errors.size() < error_locations.size())) { error_locations = std::move(possible_errors); + if (!error_locations.empty()) error_encoding = encoding; } } - return "Invalid checksum"; + return error_encoding == Encoding::BECH32M ? "Invalid Bech32m checksum" + : error_encoding == Encoding::BECH32 ? "Invalid Bech32 checksum" + : "Invalid checksum"; + } } // namespace bech32 diff --git a/src/test/bech32_tests.cpp b/src/test/bech32_tests.cpp index 7601ead5b84..5d851a97353 100644 --- a/src/test/bech32_tests.cpp +++ b/src/test/bech32_tests.cpp @@ -87,8 +87,8 @@ BOOST_AUTO_TEST_CASE(bech32_testvectors_invalid) {"Invalid separator position", {0}}, {"Invalid character or mixed case", {3, 4, 5, 7}}, {"Invalid character or mixed case", {3}}, - {"Invalid checksum", {11}}, - {"Invalid checksum", {9, 16}}, + {"Invalid Bech32 checksum", {11}}, + {"Invalid Bech32 checksum", {9, 16}}, }; static_assert(std::size(CASES) == std::size(ERRORS), "Bech32 CASES and ERRORS should have the same length"); @@ -140,8 +140,8 @@ BOOST_AUTO_TEST_CASE(bech32m_testvectors_invalid) {"Invalid checksum", {}}, {"Invalid separator position", {0}}, {"Invalid separator position", {0}}, - {"Invalid checksum", {21}}, - {"Invalid checksum", {13, 32}}, + {"Invalid Bech32m checksum", {21}}, + {"Invalid Bech32m checksum", {13, 32}}, }; static_assert(std::size(CASES) == std::size(ERRORS), "Bech32m CASES and ERRORS should have the same length"); diff --git a/test/functional/rpc_invalid_address_message.py b/test/functional/rpc_invalid_address_message.py index 1aaeddbf009..fcc49d0a759 100755 --- a/test/functional/rpc_invalid_address_message.py +++ b/test/functional/rpc_invalid_address_message.py @@ -67,13 +67,13 @@ class InvalidAddressErrorMessageTest(BitcoinTestFramework): self.check_invalid(BECH32_INVALID_VERSION, 'Invalid Bech32 address witness version') self.check_invalid(BECH32_INVALID_V0_SIZE, 'Invalid Bech32 v0 address data size') self.check_invalid(BECH32_TOO_LONG, 'Bech32 string too long', list(range(90, 108))) - self.check_invalid(BECH32_ONE_ERROR, 'Invalid checksum', [9]) - self.check_invalid(BECH32_TWO_ERRORS, 'Invalid checksum', [22, 43]) - self.check_invalid(BECH32_ONE_ERROR_CAPITALS, 'Invalid checksum', [38]) + self.check_invalid(BECH32_ONE_ERROR, 'Invalid Bech32 checksum', [9]) + self.check_invalid(BECH32_TWO_ERRORS, 'Invalid Bech32 checksum', [22, 43]) + self.check_invalid(BECH32_ONE_ERROR_CAPITALS, 'Invalid Bech32 checksum', [38]) self.check_invalid(BECH32_NO_SEPARATOR, 'Missing separator') self.check_invalid(BECH32_INVALID_CHAR, 'Invalid Base 32 character', [8]) - self.check_invalid(BECH32_MULTISIG_TWO_ERRORS, 'Invalid checksum', [19, 30]) - self.check_invalid(BECH32_WRONG_VERSION, 'Invalid checksum', [5]) + self.check_invalid(BECH32_MULTISIG_TWO_ERRORS, 'Invalid Bech32 checksum', [19, 30]) + self.check_invalid(BECH32_WRONG_VERSION, 'Invalid Bech32 checksum', [5]) # Valid Bech32 self.check_valid(BECH32_VALID)