0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-02 09:46:52 -05:00

Make Bech32 LocateErrors return error list rather than using out-arg

This commit is contained in:
Samuel Dobson 2021-12-04 12:49:27 +13:00
parent 2fa4fd1961
commit a4fe70171b
4 changed files with 22 additions and 23 deletions

View file

@ -396,23 +396,28 @@ DecodeResult Decode(const std::string& str) {
} }
/** Find index of an incorrect character in a Bech32 string. */ /** Find index of an incorrect character in a Bech32 string. */
std::string LocateErrors(const std::string& str, std::vector<int>& error_locations) { std::pair<std::string, std::vector<int>> LocateErrors(const std::string& str) {
std::vector<int> error_locations{};
if (str.size() > 90) { if (str.size() > 90) {
error_locations.resize(str.size() - 90); error_locations.resize(str.size() - 90);
std::iota(error_locations.begin(), error_locations.end(), 90); std::iota(error_locations.begin(), error_locations.end(), 90);
return "Bech32 string too long"; return std::make_pair("Bech32 string too long", std::move(error_locations));
} }
if (!CheckCharacters(str, error_locations)){ if (!CheckCharacters(str, error_locations)){
return "Invalid character or mixed case"; return std::make_pair("Invalid character or mixed case", std::move(error_locations));
} }
size_t pos = str.rfind('1'); size_t pos = str.rfind('1');
if (pos == str.npos) { if (pos == str.npos) {
return "Missing separator"; return std::make_pair("Missing separator", std::vector<int>{});
} }
if (pos == 0 || pos + 7 > str.size()) { if (pos == 0 || pos + 7 > str.size()) {
error_locations.push_back(pos); error_locations.push_back(pos);
return "Invalid separator position"; return std::make_pair("Invalid separator position", std::move(error_locations));
} }
std::string hrp; std::string hrp;
for (size_t i = 0; i < pos; ++i) { for (size_t i = 0; i < pos; ++i) {
hrp += LowerCase(str[i]); hrp += LowerCase(str[i]);
@ -425,7 +430,7 @@ std::string LocateErrors(const std::string& str, std::vector<int>& error_locatio
int8_t rev = CHARSET_REV[c]; int8_t rev = CHARSET_REV[c];
if (rev == -1) { if (rev == -1) {
error_locations.push_back(i); error_locations.push_back(i);
return "Invalid Base 32 character"; return std::make_pair("Invalid Base 32 character", std::move(error_locations));
} }
values[i - pos - 1] = rev; values[i - pos - 1] = rev;
} }
@ -545,8 +550,7 @@ std::string LocateErrors(const std::string& str, std::vector<int>& error_locatio
} }
} else { } else {
// No errors // No errors
error_locations.clear(); return std::make_pair("", std::vector<int>{});
return "";
} }
if (error_locations.empty() || (!possible_errors.empty() && possible_errors.size() < error_locations.size())) { if (error_locations.empty() || (!possible_errors.empty() && possible_errors.size() < error_locations.size())) {
@ -554,10 +558,11 @@ std::string LocateErrors(const std::string& str, std::vector<int>& error_locatio
if (!error_locations.empty()) error_encoding = encoding; if (!error_locations.empty()) error_encoding = encoding;
} }
} }
return error_encoding == Encoding::BECH32M ? "Invalid Bech32m checksum" std::string error_message = error_encoding == Encoding::BECH32M ? "Invalid Bech32m checksum"
: error_encoding == Encoding::BECH32 ? "Invalid Bech32 checksum" : error_encoding == Encoding::BECH32 ? "Invalid Bech32 checksum"
: "Invalid checksum"; : "Invalid checksum";
return std::make_pair(error_message, std::move(error_locations));
} }
} // namespace bech32 } // namespace bech32

View file

@ -46,7 +46,7 @@ struct DecodeResult
DecodeResult Decode(const std::string& str); DecodeResult Decode(const std::string& str);
/** Return the positions of errors in a Bech32 string. */ /** Return the positions of errors in a Bech32 string. */
std::string LocateErrors(const std::string& str, std::vector<int>& error_locations); std::pair<std::string, std::vector<int>> LocateErrors(const std::string& str);
} // namespace bech32 } // namespace bech32

View file

@ -188,13 +188,9 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
} }
// Perform Bech32 error location // Perform Bech32 error location
if (!error_locations) { auto res = bech32::LocateErrors(str);
std::vector<int> dummy_errors; error_str = res.first;
error_str = bech32::LocateErrors(str, dummy_errors); if (error_locations) *error_locations = std::move(res.second);
} else {
error_str = bech32::LocateErrors(str, *error_locations);
}
return CNoDestination(); return CNoDestination();
} }
} // namespace } // namespace

View file

@ -97,8 +97,7 @@ BOOST_AUTO_TEST_CASE(bech32_testvectors_invalid)
const auto& err = ERRORS[i]; const auto& err = ERRORS[i];
const auto dec = bech32::Decode(str); const auto dec = bech32::Decode(str);
BOOST_CHECK(dec.encoding == bech32::Encoding::INVALID); BOOST_CHECK(dec.encoding == bech32::Encoding::INVALID);
std::vector<int> error_locations; auto [error, error_locations] = bech32::LocateErrors(str);
std::string error = bech32::LocateErrors(str, error_locations);
BOOST_CHECK_EQUAL(err.first, error); BOOST_CHECK_EQUAL(err.first, error);
BOOST_CHECK(err.second == error_locations); BOOST_CHECK(err.second == error_locations);
i++; i++;
@ -150,8 +149,7 @@ BOOST_AUTO_TEST_CASE(bech32m_testvectors_invalid)
const auto& err = ERRORS[i]; const auto& err = ERRORS[i];
const auto dec = bech32::Decode(str); const auto dec = bech32::Decode(str);
BOOST_CHECK(dec.encoding == bech32::Encoding::INVALID); BOOST_CHECK(dec.encoding == bech32::Encoding::INVALID);
std::vector<int> error_locations; auto [error, error_locations] = bech32::LocateErrors(str);
std::string error = bech32::LocateErrors(str, error_locations);
BOOST_CHECK_EQUAL(err.first, error); BOOST_CHECK_EQUAL(err.first, error);
BOOST_CHECK(err.second == error_locations); BOOST_CHECK(err.second == error_locations);
i++; i++;