diff --git a/README.md b/README.md index 8e893cf..a6b975e 100644 --- a/README.md +++ b/README.md @@ -26,10 +26,10 @@ You can also run all the tests: make test ``` -### Installing prerequirements +### Installing prerequisites If the above doesn't work, you probably need to install some -prerequirements. For example, on a fresh Debian 10 ("buster") system: +prerequisites. For example, on a fresh Debian 10 ("buster") system: ``` sudo apt-get install make gcc g++ @@ -69,11 +69,11 @@ int main() { std::cout << bstr << std::endl; // decode - bech32::HrpAndDp hd = bech32::decode(bstr); + bech32::DecodedResult decodedResult = bech32::decode(bstr); - assert(hrp == hd.hrp); - assert(data == hd.dp); - assert(bech32::Encoding::Bech32m == hd.encoding); + assert(hrp == decodedResult.hrp); + assert(data == decodedResult.dp); + assert(bech32::Encoding::Bech32m == decodedResult.encoding); } ``` @@ -103,17 +103,17 @@ int main() { printf("%s\n", bstring->string); // allocate memory for decoded data - bech32_HrpAndDp * hrpdp = bech32_create_HrpAndDp(bstring->string); + bech32_DecodedResult * decodedResult = bech32_create_DecodedResult(bstring->string); // decode - assert(bech32_decode(hrpdp, bstring->string) == E_BECH32_SUCCESS); - assert(strcmp(hrpdp->hrp, hrp) == 0); - assert(hrpdp->dp[0] == dp[0]); - assert(hrpdp->dp[4] == dp[4]); - assert(ENCODING_BECH32M == hrpdp->encoding); + assert(bech32_decode(decodedResult, bstring->string) == E_BECH32_SUCCESS); + assert(strcmp(decodedResult->hrp, hrp) == 0); + assert(decodedResult->dp[0] == dp[0]); + assert(decodedResult->dp[4] == dp[4]); + assert(ENCODING_BECH32M == decodedResult->encoding); // free memory - bech32_free_HrpAndDp(hrpdp); + bech32_free_DecodedResult(decodedResult); bech32_free_bstring(bstring); } ``` @@ -127,11 +127,11 @@ The Bech32 data encoding format was first proposed by Pieter Wuille in early 201 [BIP 0173](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki). Later, in November 2019, Pieter published some research regarding that an exponent used in the bech32 checksum algorithm (value = 1) may not be optimal for the error detecting properties of bech32. In February 2021, Pieter published -[BIP 0350](http://www.example.com) reporting that "exhaustive analysis" showed the best possible exponent value is +[BIP 0350](https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki) reporting that "exhaustive analysis" showed the best possible exponent value is 0x2bc830a3. This improved variant of Bech32 is called "Bech32m". When decoding a possible bech32 encoded string, libbech32 returns an enum value showing whether bech32m or bech32 -was used to encode. This can be seen in the exaples above. +was used to encode. This can be seen in the examples above. When encoding data, libbech32 defaults to using the new exponent value of 0x2bc830a3. If the original exponent value of 1 is desired, then the following functions may be used: diff --git a/examples/c_example.c b/examples/c_example.c index ff0401d..dda7f62 100644 --- a/examples/c_example.c +++ b/examples/c_example.c @@ -23,17 +23,17 @@ void encodeAndDecode() { assert(strcmp(expected, bstring->string) == 0); // allocate memory for decoded data - bech32_HrpAndDp * hrpdp = bech32_create_HrpAndDp(bstring->string); + bech32_DecodedResult * decodedResult = bech32_create_DecodedResult(bstring->string); // decode - assert(bech32_decode(hrpdp, bstring->string) == E_BECH32_SUCCESS); - assert(strcmp(hrpdp->hrp, "example") == 0); - assert(hrpdp->dp[0] == 0); - assert(hrpdp->dp[8] == 8); - assert(ENCODING_BECH32M == hrpdp->encoding); + assert(bech32_decode(decodedResult, bstring->string) == E_BECH32_SUCCESS); + assert(strcmp(decodedResult->hrp, "example") == 0); + assert(decodedResult->dp[0] == 0); + assert(decodedResult->dp[8] == 8); + assert(ENCODING_BECH32M == decodedResult->encoding); // free memory - bech32_free_HrpAndDp(hrpdp); + bech32_free_DecodedResult(decodedResult); bech32_free_bstring(bstring); } @@ -48,25 +48,25 @@ void decodeAndEncode() { assert(bech32_stripUnknownChars(bstr, sizeof(bstr), bstr, sizeof(bstr)) == E_BECH32_SUCCESS); // allocate memory for decoded data - bech32_HrpAndDp * hrpdp = bech32_create_HrpAndDp(bstr); + bech32_DecodedResult * decodedResult = bech32_create_DecodedResult(bstr); // decode - assert(bech32_decode(hrpdp, bstr) == E_BECH32_SUCCESS); - assert(strcmp(hrpdp->hrp, "example") == 0); - assert(hrpdp->dp[0] == 0); - assert(hrpdp->dp[8] == 8); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_SUCCESS); + assert(strcmp(decodedResult->hrp, "example") == 0); + assert(decodedResult->dp[0] == 0); + assert(decodedResult->dp[8] == 8); // create output array for bech32 string - bech32_bstring *bstring = bech32_create_bstring_from_HrpAndDp(hrpdp); + bech32_bstring *bstring = bech32_create_bstring_from_DecodedResult(decodedResult); // encode - assert(bech32_encode(bstring, hrpdp->hrp, hrpdp->dp, hrpdp->dplen) == E_BECH32_SUCCESS); + assert(bech32_encode(bstring, decodedResult->hrp, decodedResult->dp, decodedResult->dplen) == E_BECH32_SUCCESS); // encoding of "cleaned" decoded data should match expected string assert(strcmp(expected, bstring->string) == 0); // free memory - bech32_free_HrpAndDp(hrpdp); + bech32_free_DecodedResult(decodedResult); bech32_free_bstring(bstring); } @@ -94,13 +94,13 @@ void badDecoding_corruptData() { bstr[10] = 'x'; // allocate memory for decoded data - bech32_HrpAndDp * hrpdp = bech32_create_HrpAndDp(bstr); + bech32_DecodedResult * decodedResult = bech32_create_DecodedResult(bstr); // decode - assert(bech32_decode(hrpdp, bstr) == E_BECH32_INVALID_CHECKSUM); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_INVALID_CHECKSUM); // free memory - bech32_free_HrpAndDp(hrpdp); + bech32_free_DecodedResult(decodedResult); } void badDecoding_corruptChecksum() { @@ -111,13 +111,13 @@ void badDecoding_corruptChecksum() { bstr[19] = 'q'; // allocate memory for decoded data - bech32_HrpAndDp * hrpdp = bech32_create_HrpAndDp(bstr); + bech32_DecodedResult * decodedResult = bech32_create_DecodedResult(bstr); // decode - assert(bech32_decode(hrpdp, bstr) == E_BECH32_INVALID_CHECKSUM); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_INVALID_CHECKSUM); // free memory - bech32_free_HrpAndDp(hrpdp); + bech32_free_DecodedResult(decodedResult); } int main() { diff --git a/examples/c_usage_example.c b/examples/c_usage_example.c index f720835..de7f13a 100644 --- a/examples/c_usage_example.c +++ b/examples/c_usage_example.c @@ -23,16 +23,16 @@ int main() { printf("%s\n", bstring->string); // allocate memory for decoded data - bech32_HrpAndDp * hrpdp = bech32_create_HrpAndDp(bstring->string); + bech32_DecodedResult * decodedResult = bech32_create_DecodedResult(bstring->string); // decode - assert(bech32_decode(hrpdp, bstring->string) == E_BECH32_SUCCESS); - assert(strcmp(hrpdp->hrp, hrp) == 0); - assert(hrpdp->dp[0] == dp[0]); - assert(hrpdp->dp[4] == dp[4]); - assert(ENCODING_BECH32M == hrpdp->encoding); + assert(bech32_decode(decodedResult, bstring->string) == E_BECH32_SUCCESS); + assert(strcmp(decodedResult->hrp, hrp) == 0); + assert(decodedResult->dp[0] == dp[0]); + assert(decodedResult->dp[4] == dp[4]); + assert(ENCODING_BECH32M == decodedResult->encoding); // free memory - bech32_free_HrpAndDp(hrpdp); + bech32_free_DecodedResult(decodedResult); bech32_free_bstring(bstring); } diff --git a/examples/cpp_example.cpp b/examples/cpp_example.cpp index c5fe020..0f73a38 100644 --- a/examples/cpp_example.cpp +++ b/examples/cpp_example.cpp @@ -20,11 +20,11 @@ void encodeAndDecode() { assert(expected == bstr); // decode - bech32::HrpAndDp hd = bech32::decode(bstr); + bech32::DecodedResult decodedResult = bech32::decode(bstr); - assert(hrp == hd.hrp); - assert(data == hd.dp); - assert(bech32::Encoding::Bech32m == hd.encoding); + assert(hrp == decodedResult.hrp); + assert(data == decodedResult.dp); + assert(bech32::Encoding::Bech32m == decodedResult.encoding); } void decodeAndEncode() { @@ -33,18 +33,17 @@ void decodeAndEncode() { std::string bstr = " example1:qpz!r--y9#x8&%&%ge-8-sqgv "; std::string expected = "example1qpzry9x8ge8sqgv"; // decode - make sure to strip invalid characters before trying to decode - bech32::HrpAndDp hd = bech32::decode(bech32::stripUnknownChars(bstr)); + bech32::DecodedResult decodedResult = bech32::decode(bech32::stripUnknownChars(bstr)); // verify decoding - assert(!hd.hrp.empty() && !hd.dp.empty()); - assert(bech32::Encoding::Bech32m == hd.encoding); + assert(!decodedResult.hrp.empty() && !decodedResult.dp.empty()); + assert(bech32::Encoding::Bech32m == decodedResult.encoding); // encode - bstr = bech32::encode(hd.hrp, hd.dp); + bstr = bech32::encode(decodedResult.hrp, decodedResult.dp); // encoding of "cleaned" decoded data should match expected string assert(bstr == expected); - } void badEncoding() { @@ -71,12 +70,11 @@ void badDecoding_corruptData() { bstr[10] = 'x'; // decode - bech32::HrpAndDp hd = bech32::decode(bstr); + bech32::DecodedResult decodedResult = bech32::decode(bstr); // verify decoding failed - assert(hd.hrp.empty() && hd.dp.empty()); - assert(bech32::Encoding::None == hd.encoding); - + assert(decodedResult.hrp.empty() && decodedResult.dp.empty()); + assert(bech32::Encoding::Invalid == decodedResult.encoding); } void badDecoding_corruptChecksum() { @@ -87,12 +85,11 @@ void badDecoding_corruptChecksum() { bstr[19] = 'q'; // decode - bech32::HrpAndDp hd = bech32::decode(bstr); + bech32::DecodedResult decodedResult = bech32::decode(bstr); // verify decoding failed - assert(hd.hrp.empty() && hd.dp.empty()); - assert(bech32::Encoding::None == hd.encoding); - + assert(decodedResult.hrp.empty() && decodedResult.dp.empty()); + assert(bech32::Encoding::Invalid == decodedResult.encoding); } int main() { diff --git a/examples/cpp_usage_example.cpp b/examples/cpp_usage_example.cpp index 63671da..991a04f 100644 --- a/examples/cpp_usage_example.cpp +++ b/examples/cpp_usage_example.cpp @@ -19,9 +19,9 @@ int main() { std::cout << bstr << std::endl; // decode - bech32::HrpAndDp hd = bech32::decode(bstr); + bech32::DecodedResult decodedResult = bech32::decode(bstr); - assert(hrp == hd.hrp); - assert(data == hd.dp); - assert(bech32::Encoding::Bech32m == hd.encoding); + assert(hrp == decodedResult.hrp); + assert(data == decodedResult.dp); + assert(bech32::Encoding::Bech32m == decodedResult.encoding); } diff --git a/include/libbech32/libbech32.h b/include/libbech32/libbech32.h index 2a61df9..034c2bf 100644 --- a/include/libbech32/libbech32.h +++ b/include/libbech32/libbech32.h @@ -11,9 +11,8 @@ namespace bech32 { // Encoding: denotes which encoding was used for a bech32 string enum Encoding { - None, // no encoding was detected - Unknown, // encoding has not yet been determined - Bech32, // encoding uses original checksum constant (1) + Invalid, // no or invalid encoding was detected + Bech32, // encoding used original checksum constant (1) Bech32m // encoding used default checksum constant (M = 0x2bc830a3) }; @@ -23,7 +22,7 @@ namespace bech32 { // Represents the payload within a bech32 string. // hrp: the human-readable part // dp: the data part - struct HrpAndDp { + struct DecodedResult { Encoding encoding; std::string hrp; std::vector dp; @@ -40,7 +39,7 @@ namespace bech32 { std::string encodeUsingOriginalConstant(const std::string & hrp, const std::vector & dp); // decode a bech32 string, returning the "human-readable part" and a "data part" - HrpAndDp decode(const std::string & bstring); + DecodedResult decode(const std::string & bstring); namespace limits { @@ -94,8 +93,7 @@ typedef struct bech32_bstring_s { * Encoding: denotes which encoding was used for a bech32 string */ typedef enum bech32_encoding_e { - ENCODING_NONE, // no encoding was detected - ENCODING_UNKNOWN, // encoding has not yet been determined + ENCODING_INVALID, // no or invalid encoding was detected ENCODING_BECH32, // encoding uses original checksum constant (1) ENCODING_BECH32M // encoding used default checksum constant (M = 0x2bc830a3) } bech32_encoding; @@ -109,13 +107,13 @@ typedef enum bech32_encoding_e { * dp: the data part * dplen: length of the data part */ -typedef struct bech32_HrpAndDp_s { +typedef struct bech32_DecodedResult_s { bech32_encoding encoding; char * hrp; size_t hrplen; unsigned char * dp; size_t dplen; -} bech32_HrpAndDp; +} bech32_DecodedResult; /** * Possible error codes @@ -145,22 +143,22 @@ extern const char *bech32_errordesc[]; extern const char * bech32_strerror(bech32_error error_code); /** - * Allocates memory for a bech32_HrpAndDp struct based on the size of the bech32 string passed in. + * Allocates memory for a bech32_DecodedResult struct based on the size of the bech32 string passed in. * - * This memory must be freed using the bech32_free_HrpAndDp function. + * This memory must be freed using the bech32_free_DecodedResult function. * * @param str the bech32 string to be decoded by bech32_decode() * - * @return a pointer to a new bech32_HrpAndDp struct, or NULL if error + * @return a pointer to a new bech32_DecodedResult struct, or NULL if error */ -extern bech32_HrpAndDp * bech32_create_HrpAndDp(const char *str); +extern bech32_DecodedResult * bech32_create_DecodedResult(const char *str); /** - * Frees memory for a bech32_HrpAndDp struct. + * Frees memory for a bech32_DecodedResult struct. * - * @param hrpAndDp pointer to a bech32_HrpAndDp struct + * @param decodedResult pointer to a bech32_DecodedResult struct */ -extern void bech32_free_HrpAndDp(bech32_HrpAndDp *hrpAndDp); +extern void bech32_free_DecodedResult(bech32_DecodedResult *decodedResult); /** * Computes final length for a to-be-encoded bech32 string @@ -185,15 +183,15 @@ extern size_t bech32_compute_encoded_string_length(size_t hrplen, size_t dplen); extern bech32_bstring * bech32_create_bstring(size_t hrplen, size_t dplen); /** - * Allocates memory for a to-be-encoded bech32 string based on the size of the bech32_HrpAndDp struct + * Allocates memory for a to-be-encoded bech32 string based on the size of the bech32_DecodedResult struct * * This memory must be freed using the bech32_free_bstring function. * - * @param hrpAndDp a pointer to a bech32_HrpAndDp struct + * @param decodedResult a pointer to a bech32_DecodedResult struct * * @return a pointer to a new bech32_bstring struct, or NULL if error */ -extern bech32_bstring * bech32_create_bstring_from_HrpAndDp(bech32_HrpAndDp *hrpAndDp); +extern bech32_bstring * bech32_create_bstring_from_DecodedResult(bech32_DecodedResult *decodedResult); /** * Frees memory for a bech32 string. @@ -255,14 +253,14 @@ extern bech32_error bech32_encode_using_original_constant( /** * decode a bech32 string, returning the "human-readable part" and a "data part" * - * @param output pointer to struct to copy the decoded "human-readable part" and "data part" + * @param decodedResult pointer to struct to copy the decoded "human-readable part" and "data part" * @param str the bech32 string to decode * - * @return E_BECH32_SUCCESS on success, others on error (i.e., output is NULL, hrp/dp not + * @return E_BECH32_SUCCESS on success, others on error (i.e., decodedResult is NULL, hrp/dp not * long enough for decoded bech32 data) */ extern bech32_error bech32_decode( - bech32_HrpAndDp *output, + bech32_DecodedResult *decodedResult, const char *str); #ifdef __cplusplus diff --git a/libbech32/bech32.cpp b/libbech32/bech32.cpp index 4db1810..757f5bd 100644 --- a/libbech32/bech32.cpp +++ b/libbech32/bech32.cpp @@ -6,11 +6,12 @@ namespace { using namespace bech32::limits; - // exponent used in checksum generation, taken from recommendation - // in: https://github.com/sipa/bips/blob/bip-bech32m/bip-bech32m.mediawiki + // exponent used in checksum generation. see: + // https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki + // https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki const unsigned int M = 0x2bc830a3; - /** The Bech32 character set for encoding. The index into this string gives the char + /** The Bech32 character set for encoding. The index into this array gives the char * each value is mapped to, i.e., 0 -> 'q', 10 -> '2', etc. This comes from the table * in BIP-0173 */ const char charset[VALID_CHARSET_SIZE] = { @@ -85,18 +86,22 @@ namespace { return bstring.find_last_of(bech32::separator); } + // extract the hrp from the string + std::string extractHumanReadablePart(const std::string & bstring) { + auto pos = findSeparatorPosition(bstring); + return bstring.substr(0, pos); + } - // split the hrp from the dp - bech32::HrpAndDp splitString(const std::string & bstring) { + // extract the dp from the string + std::vector extractDataPart(const std::string & bstring) { auto pos = findSeparatorPosition(bstring); - std::string hrp = bstring.substr(0, pos); std::string dpstr = bstring.substr(pos+1); // convert dpstr to dp vector std::vector dp(bstring.size() - (pos + 1)); for(std::string::size_type i = 0; i < dpstr.size(); ++i) { dp[i] = static_cast(dpstr[i]); } - return {bech32::Encoding::Unknown, hrp, dp}; + return dp; } void convertToLowercase(std::string & str) { @@ -290,26 +295,25 @@ namespace bech32 { } // decode a bech32 string, returning the "human-readable part" and a "data part" - HrpAndDp decode(const std::string & bstring) { + DecodedResult decode(const std::string & bstring) { rejectBStringThatIsntWellFormed(bstring); - HrpAndDp b = splitString(bstring); - rejectHRPTooShort(b.hrp); - rejectHRPTooLong(b.hrp); - rejectDPTooShort(b.dp); - convertToLowercase(b.hrp); - mapDP(b.dp); - if (verifyChecksum(b.hrp, b.dp)) { - stripChecksum(b.dp); - b.encoding = bech32::Encoding::Bech32m; - return b; + std::string hrp = extractHumanReadablePart(bstring); + std::vector dp = extractDataPart(bstring); + rejectHRPTooShort(hrp); + rejectHRPTooLong(hrp); + rejectDPTooShort(dp); + convertToLowercase(hrp); + mapDP(dp); + if (verifyChecksum(hrp, dp)) { + stripChecksum(dp); + return {bech32::Encoding::Bech32m, hrp, dp}; } - else if (verifyChecksumUsingOriginalConstant(b.hrp, b.dp)) { - stripChecksum(b.dp); - b.encoding = bech32::Encoding::Bech32; - return b; + else if (verifyChecksumUsingOriginalConstant(hrp, dp)) { + stripChecksum(dp); + return {bech32::Encoding::Bech32, hrp, dp}; } else { - return HrpAndDp(); + return DecodedResult(); } } @@ -345,16 +349,16 @@ const char * bech32_strerror(bech32_error error_code) { } /** - * Allocates memory for a bech32_HrpAndDp struct based on the size of the bech32 string passed in. + * Allocates memory for a bech32_DecodedResult struct based on the size of the bech32 string passed in. * - * This memory must be freed using the bech32_free_HrpAndDp function. + * This memory must be freed using the bech32_free_DecodedResult function. * * @param str the bech32 string to be decoded by bech32_decode() * - * @return a pointer to a new bech32_HrpAndDp struct, or NULL if error + * @return a pointer to a new bech32_DecodedResult struct, or NULL if error */ extern "C" -bech32_HrpAndDp * bech32_create_HrpAndDp(const char *str) { +bech32_DecodedResult * bech32_create_DecodedResult(const char *str) { if(str == nullptr) return nullptr; // the storage needed for a decoded bech32 string can be easily determined by the @@ -372,10 +376,10 @@ bech32_HrpAndDp * bech32_create_HrpAndDp(const char *str) { size_t number_of_data_characters = inputStr.length() - number_of_hrp_characters - - 1 // for separator character + - bech32::limits::SEPARATOR_LENGTH - bech32::limits::CHECKSUM_LENGTH; - auto hrpdp = static_cast(malloc(sizeof (bech32_HrpAndDp))); + auto hrpdp = static_cast(malloc(sizeof (bech32_DecodedResult))); if(hrpdp == nullptr) return nullptr; hrpdp->hrplen = number_of_hrp_characters; @@ -392,23 +396,23 @@ bech32_HrpAndDp * bech32_create_HrpAndDp(const char *str) { return nullptr; } - hrpdp->encoding = ENCODING_UNKNOWN; + hrpdp->encoding = ENCODING_INVALID; return hrpdp; } /** - * Frees memory for a bech32_HrpAndDp struct. + * Frees memory for a bech32_DecodedResult struct. * - * @param hrpAndDp a pointer to a bech32_HrpAndDp struct + * @param decodedResult a pointer to a bech32_DecodedResult struct */ extern "C" -void bech32_free_HrpAndDp(bech32_HrpAndDp *hrpAndDp) { - if(hrpAndDp == nullptr) +void bech32_free_DecodedResult(bech32_DecodedResult *decodedResult) { + if(decodedResult == nullptr) return; - free(hrpAndDp->dp); - free(hrpAndDp->hrp); - free(hrpAndDp); + free(decodedResult->dp); + free(decodedResult->hrp); + free(decodedResult); } /** @@ -445,21 +449,21 @@ bech32_bstring * bech32_create_bstring(size_t hrplen, size_t dplen) { } /** - * Allocates memory for a to-be-encoded bech32 string based on the size of the bech32_HrpAndDp struct + * Allocates memory for a to-be-encoded bech32 string based on the size of the bech32_DecodedResult struct * * This memory must be freed using the bech32_free_bstring function. * - * @param hrpAndDp a pointer to a bech32_HrpAndDp struct + * @param decodedResult a pointer to a bech32_DecodedResult struct * * @return a pointer to a new bech32_bstring struct, or NULL if error */ extern "C" -bech32_bstring * bech32_create_bstring_from_HrpAndDp(bech32_HrpAndDp *hrpAndDp) { - if(hrpAndDp == nullptr) +bech32_bstring * bech32_create_bstring_from_DecodedResult(bech32_DecodedResult *decodedResult) { + if(decodedResult == nullptr) return nullptr; - if(hrpAndDp->hrplen < 1) + if(decodedResult->hrplen < 1) return nullptr; - return bech32_create_bstring(hrpAndDp->hrplen, hrpAndDp->dplen); + return bech32_create_bstring(decodedResult->hrplen, decodedResult->dplen); } /** @@ -484,7 +488,7 @@ void bech32_free_bstring(bech32_bstring *bstring) { * @param dst pointer to memory to put the cleaned string * @param src pointer to the string to be cleaned * - * @return E_BECH32_SUCCESS on success, others on error (input/output is NULL, output not + * @return E_BECH32_SUCCESS on success, others on error (e.g., input/output is NULL, output not * long enough for string) */ extern "C" @@ -519,7 +523,7 @@ bech32_error bech32_stripUnknownChars( * @param dp pointer to the "data part" * @param dplen the length of the "data part" array * - * @return E_BECH32_SUCCESS on success, others on error (i.e., hrp/dp/bstring is NULL, bstring not + * @return E_BECH32_SUCCESS on success, others on error (e.g., hrp/dp/bstring is NULL, bstring not * long enough for bech32 string) */ extern "C" @@ -564,7 +568,7 @@ bech32_error bech32_encode( * @param dp pointer to the "data part" * @param dplen the length of the "data part" array * - * @return E_BECH32_SUCCESS on success, others on error (i.e., hrp/dp/sbtring is NULL, bstring not + * @return E_BECH32_SUCCESS on success, others on error (e.g., hrp/dp/sbtring is NULL, bstring not * long enough for bech32 string) */ extern "C" @@ -603,46 +607,46 @@ bech32_error bech32_encode_using_original_constant( /** * decode a bech32 string, returning the "human-readable part" and a "data part" * - * @param output pointer to struct to copy the decoded "human-readable part" and "data part" + * @param decodedResult pointer to struct to copy the decoded "human-readable part" and "data part" * @param str the bech32 string to decode * - * @return E_BECH32_SUCCESS on success, others on error (i.e., output is NULL, hrp/dp not + * @return E_BECH32_SUCCESS on success, others on error (e.g., output is NULL, hrp/dp not * long enough for decoded bech32 data) */ extern "C" -bech32_error bech32_decode(bech32_HrpAndDp *output, char const *str) { +bech32_error bech32_decode(bech32_DecodedResult *decodedResult, char const *str) { - if(output == nullptr) + if(decodedResult == nullptr) return E_BECH32_NULL_ARGUMENT; - if(output->hrp == nullptr) + if(decodedResult->hrp == nullptr) return E_BECH32_NULL_ARGUMENT; - if(output->dp == nullptr) + if(decodedResult->dp == nullptr) return E_BECH32_NULL_ARGUMENT; if(str == nullptr) return E_BECH32_NULL_ARGUMENT; std::string inputStr(str); - bech32::HrpAndDp hrpAndDp; + bech32::DecodedResult localResult; try { - hrpAndDp = bech32::decode(inputStr); + localResult = bech32::decode(inputStr); } catch (std::exception &) { // todo: convert exception message return E_BECH32_UNKNOWN_ERROR; } - if(hrpAndDp.hrp.empty() && hrpAndDp.dp.empty()) + if(localResult.hrp.empty() && localResult.dp.empty()) return E_BECH32_INVALID_CHECKSUM; - if(hrpAndDp.hrp.size() > output->hrplen) + if(localResult.hrp.size() > decodedResult->hrplen) return E_BECH32_LENGTH_TOO_SHORT; - if(hrpAndDp.dp.size() > output->dplen) + if(localResult.dp.size() > decodedResult->dplen) return E_BECH32_LENGTH_TOO_SHORT; - output->encoding = static_cast(hrpAndDp.encoding); - std::copy_n(hrpAndDp.hrp.begin(), hrpAndDp.hrp.size(), output->hrp); - output->hrp[hrpAndDp.hrp.size()] = '\0'; - std::copy_n(hrpAndDp.dp.begin(), hrpAndDp.dp.size(), output->dp); + decodedResult->encoding = static_cast(localResult.encoding); + std::copy_n(localResult.hrp.begin(), localResult.hrp.size(), decodedResult->hrp); + decodedResult->hrp[localResult.hrp.size()] = '\0'; + std::copy_n(localResult.dp.begin(), localResult.dp.size(), decodedResult->dp); return E_BECH32_SUCCESS; } diff --git a/test/testbech32/bech32_api_tests.cpp b/test/testbech32/bech32_api_tests.cpp index 4ca04e5..2344433 100644 --- a/test/testbech32/bech32_api_tests.cpp +++ b/test/testbech32/bech32_api_tests.cpp @@ -31,33 +31,33 @@ void decode_minimalExample_isSuccessful() { std::string bstr = "a1lqfn3a"; std::string expectedHrp = "a"; - bech32::HrpAndDp hd = bech32::decode(bstr); + bech32::DecodedResult decodedResult = bech32::decode(bstr); - assert(expectedHrp == hd.hrp); - assert(bech32::Encoding::Bech32m == hd.encoding); + assert(expectedHrp == decodedResult.hrp); + assert(bech32::Encoding::Bech32m == decodedResult.encoding); } void decode_longExample_isSuccessful() { std::string bstr = "abcdef1l7aum6echk45nj3s0wdvt2fg8x9yrzpqzd3ryx"; std::string expectedHrp = "abcdef"; - bech32::HrpAndDp hd = bech32::decode(bstr); + bech32::DecodedResult decodedResult = bech32::decode(bstr); - assert(expectedHrp == hd.hrp); - assert(bech32::Encoding::Bech32m == hd.encoding); + assert(expectedHrp == decodedResult.hrp); + assert(bech32::Encoding::Bech32m == decodedResult.encoding); - assert(hd.dp[0] == '\x1f'); // first 'l' in above dp part - assert(hd.dp[31] == '\0'); // last 'q' in above dp part + assert(decodedResult.dp[0] == '\x1f'); // first 'l' in above dp part + assert(decodedResult.dp[31] == '\0'); // last 'q' in above dp part } void decode_minimalExampleBadChecksum_isUnsuccessful() { std::string bstr = "a1lqfn3q"; // last 'q' should be a 'a' std::string expectedHrp = "a"; - bech32::HrpAndDp hd = bech32::decode(bstr); + bech32::DecodedResult decodedResult = bech32::decode(bstr); - assert(hd.hrp.empty()); - assert(hd.dp.empty()); + assert(decodedResult.hrp.empty()); + assert(decodedResult.dp.empty()); } void decode_whenMethodThrowsException_isUnsuccessful() { @@ -67,7 +67,7 @@ void decode_whenMethodThrowsException_isUnsuccessful() { std::string expectedHrp = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; try { - bech32::HrpAndDp hd = bech32::decode(bstr); + bech32::DecodedResult decodedResult = bech32::decode(bstr); } catch (std::runtime_error &e) { assert(std::string(e.what()) == "bech32 string too long"); @@ -122,12 +122,12 @@ void decode_and_encode_minimalExample_producesSameResult() { std::string bstr1 = "a1lqfn3a"; std::string expectedHrp = "a"; - bech32::HrpAndDp hd = bech32::decode(bstr1); + bech32::DecodedResult decodedResult = bech32::decode(bstr1); - assert(expectedHrp == hd.hrp); - assert(bech32::Encoding::Bech32m == hd.encoding); + assert(expectedHrp == decodedResult.hrp); + assert(bech32::Encoding::Bech32m == decodedResult.encoding); - std::string bstr2 = bech32::encode(hd.hrp, hd.dp); + std::string bstr2 = bech32::encode(decodedResult.hrp, decodedResult.dp); assert(bstr1 == bstr2); } @@ -136,12 +136,12 @@ void decode_and_encode_smallExample_producesSameResult() { std::string bstr1 = "xyz1pzrs3usye"; std::string expectedHrp = "xyz"; - bech32::HrpAndDp hd = bech32::decode(bstr1); + bech32::DecodedResult decodedResult = bech32::decode(bstr1); - assert(expectedHrp == hd.hrp); - assert(bech32::Encoding::Bech32m == hd.encoding); + assert(expectedHrp == decodedResult.hrp); + assert(bech32::Encoding::Bech32m == decodedResult.encoding); - std::string bstr2 = bech32::encode(hd.hrp, hd.dp); + std::string bstr2 = bech32::encode(decodedResult.hrp, decodedResult.dp); assert(bstr1 == bstr2); } @@ -150,12 +150,12 @@ void decode_and_encode_longExample_producesSameResult() { std::string bstr1 = "abcdef1l7aum6echk45nj3s0wdvt2fg8x9yrzpqzd3ryx"; std::string expectedHrp = "abcdef"; - bech32::HrpAndDp hd = bech32::decode(bstr1); + bech32::DecodedResult decodedResult = bech32::decode(bstr1); - assert(expectedHrp == hd.hrp); - assert(bech32::Encoding::Bech32m == hd.encoding); + assert(expectedHrp == decodedResult.hrp); + assert(bech32::Encoding::Bech32m == decodedResult.encoding); - std::string bstr2 = bech32::encode(hd.hrp, hd.dp); + std::string bstr2 = bech32::encode(decodedResult.hrp, decodedResult.dp); assert(bstr1 == bstr2); } @@ -166,23 +166,23 @@ void decode_c1_minimalExample_isSuccessful() { std::string bstr = "a12uel5l"; std::string expectedHrp = "a"; - bech32::HrpAndDp hd = bech32::decode(bstr); + bech32::DecodedResult decodedResult = bech32::decode(bstr); - assert(expectedHrp == hd.hrp); - assert(bech32::Encoding::Bech32 == hd.encoding); + assert(expectedHrp == decodedResult.hrp); + assert(bech32::Encoding::Bech32 == decodedResult.encoding); } void decode_c1_longExample_isSuccessful() { std::string bstr = "abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw"; std::string expectedHrp = "abcdef"; - bech32::HrpAndDp hd = bech32::decode(bstr); + bech32::DecodedResult decodedResult = bech32::decode(bstr); - assert(expectedHrp == hd.hrp); - assert(bech32::Encoding::Bech32 == hd.encoding); + assert(expectedHrp == decodedResult.hrp); + assert(bech32::Encoding::Bech32 == decodedResult.encoding); - assert(hd.dp[0] == '\0'); // first 'q' in above dp part - assert(hd.dp[31] == '\x1f'); // last 'l' in above dp part + assert(decodedResult.dp[0] == '\0'); // first 'q' in above dp part + assert(decodedResult.dp[31] == '\x1f'); // last 'l' in above dp part } void encode_c1_minimalExample_isSuccessful() { @@ -205,12 +205,12 @@ void decode_and_encode_c1_minimalExample_producesSameResult() { std::string bstr1 = "a12uel5l"; std::string expectedHrp = "a"; - bech32::HrpAndDp hd = bech32::decode(bstr1); + bech32::DecodedResult decodedResult = bech32::decode(bstr1); - assert(expectedHrp == hd.hrp); - assert(bech32::Encoding::Bech32 == hd.encoding); + assert(expectedHrp == decodedResult.hrp); + assert(bech32::Encoding::Bech32 == decodedResult.encoding); - std::string bstr2 = bech32::encodeUsingOriginalConstant(hd.hrp, hd.dp); + std::string bstr2 = bech32::encodeUsingOriginalConstant(decodedResult.hrp, decodedResult.dp); assert(bstr1 == bstr2); } @@ -219,12 +219,12 @@ void decode_and_encode_c1_smallExample_producesSameResult() { std::string bstr1 = "xyz1pzr9dvupm"; std::string expectedHrp = "xyz"; - bech32::HrpAndDp hd = bech32::decode(bstr1); + bech32::DecodedResult decodedResult = bech32::decode(bstr1); - assert(expectedHrp == hd.hrp); - assert(bech32::Encoding::Bech32 == hd.encoding); + assert(expectedHrp == decodedResult.hrp); + assert(bech32::Encoding::Bech32 == decodedResult.encoding); - std::string bstr2 = bech32::encodeUsingOriginalConstant(hd.hrp, hd.dp); + std::string bstr2 = bech32::encodeUsingOriginalConstant(decodedResult.hrp, decodedResult.dp); assert(bstr1 == bstr2); } @@ -233,12 +233,12 @@ void decode_and_encode_c1_longExample_producesSameResult() { std::string bstr1 = "abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw"; std::string expectedHrp = "abcdef"; - bech32::HrpAndDp hd = bech32::decode(bstr1); + bech32::DecodedResult decodedResult = bech32::decode(bstr1); - assert(expectedHrp == hd.hrp); - assert(bech32::Encoding::Bech32 == hd.encoding); + assert(expectedHrp == decodedResult.hrp); + assert(bech32::Encoding::Bech32 == decodedResult.encoding); - std::string bstr2 = bech32::encodeUsingOriginalConstant(hd.hrp, hd.dp); + std::string bstr2 = bech32::encodeUsingOriginalConstant(decodedResult.hrp, decodedResult.dp); assert(bstr1 == bstr2); } diff --git a/test/testbech32/bech32_c_api_tests.c b/test/testbech32/bech32_c_api_tests.c index 36d6223..7110889 100644 --- a/test/testbech32/bech32_c_api_tests.c +++ b/test/testbech32/bech32_c_api_tests.c @@ -79,85 +79,85 @@ void decode_withBadArgs_isUnsuccessful() { { // input is null char *bstr = NULL; - bech32_HrpAndDp *hrpdp = malloc(sizeof(bech32_HrpAndDp)); - hrpdp->hrplen = 10; - hrpdp->hrp = (char *) calloc(hrpdp->hrplen, 1); - hrpdp->dplen = 10; - hrpdp->dp = (unsigned char *) calloc(hrpdp->dplen, 1); + bech32_DecodedResult *decodedResult = malloc(sizeof(bech32_DecodedResult)); + decodedResult->hrplen = 10; + decodedResult->hrp = (char *) calloc(decodedResult->hrplen, 1); + decodedResult->dplen = 10; + decodedResult->dp = (unsigned char *) calloc(decodedResult->dplen, 1); - assert(bech32_decode(hrpdp, bstr) == E_BECH32_NULL_ARGUMENT); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_NULL_ARGUMENT); - free(hrpdp->dp); - free(hrpdp->hrp); - free(hrpdp); + free(decodedResult->dp); + free(decodedResult->hrp); + free(decodedResult); } { // output is null char bstr[] = "xyz1pzrs3usye"; - bech32_HrpAndDp *hrpdp = NULL; + bech32_DecodedResult *decodedResult = NULL; - assert(bech32_decode(hrpdp, bstr) == E_BECH32_NULL_ARGUMENT); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_NULL_ARGUMENT); } { // hrp is null char bstr[] = "xyz1pzrs3usye"; - bech32_HrpAndDp *hrpdp = malloc(sizeof(bech32_HrpAndDp)); - hrpdp->dplen = 10; - hrpdp->dp = (unsigned char *) calloc(hrpdp->dplen, 1); - hrpdp->hrp = NULL; + bech32_DecodedResult *decodedResult = malloc(sizeof(bech32_DecodedResult)); + decodedResult->dplen = 10; + decodedResult->dp = (unsigned char *) calloc(decodedResult->dplen, 1); + decodedResult->hrp = NULL; - assert(bech32_decode(hrpdp, bstr) == E_BECH32_NULL_ARGUMENT); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_NULL_ARGUMENT); - free(hrpdp->dp); - free(hrpdp); + free(decodedResult->dp); + free(decodedResult); } { // dp is null char bstr[] = "xyz1pzrs3usye"; - bech32_HrpAndDp *hrpdp = malloc(sizeof(bech32_HrpAndDp)); - hrpdp->hrplen = 1; - hrpdp->hrp = (char *) calloc(hrpdp->hrplen, 1); - hrpdp->dp = NULL; + bech32_DecodedResult *decodedResult = malloc(sizeof(bech32_DecodedResult)); + decodedResult->hrplen = 1; + decodedResult->hrp = (char *) calloc(decodedResult->hrplen, 1); + decodedResult->dp = NULL; - assert(bech32_decode(hrpdp, bstr) == E_BECH32_NULL_ARGUMENT); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_NULL_ARGUMENT); - free(hrpdp->hrp); - free(hrpdp); + free(decodedResult->hrp); + free(decodedResult); } { // allocated hrp is too short char bstr[] = "xyz1pzrs3usye"; - bech32_HrpAndDp *hrpdp = malloc(sizeof(bech32_HrpAndDp)); - hrpdp->hrplen = 1; - hrpdp->hrp = (char *) calloc(hrpdp->hrplen, 1); - hrpdp->dplen = 10; - hrpdp->dp = (unsigned char *) calloc(hrpdp->dplen, 1); + bech32_DecodedResult *decodedResult = malloc(sizeof(bech32_DecodedResult)); + decodedResult->hrplen = 1; + decodedResult->hrp = (char *) calloc(decodedResult->hrplen, 1); + decodedResult->dplen = 10; + decodedResult->dp = (unsigned char *) calloc(decodedResult->dplen, 1); - assert(bech32_decode(hrpdp, bstr) == E_BECH32_LENGTH_TOO_SHORT); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_LENGTH_TOO_SHORT); - free(hrpdp->dp); - free(hrpdp->hrp); - free(hrpdp); + free(decodedResult->dp); + free(decodedResult->hrp); + free(decodedResult); } { // allocated dp is too short char bstr[] = "xyz1pzrs3usye"; - bech32_HrpAndDp *hrpdp = malloc(sizeof(bech32_HrpAndDp)); - hrpdp->hrplen = 10; - hrpdp->hrp = (char *) calloc(hrpdp->hrplen, 1); - hrpdp->dplen = 1; - hrpdp->dp = (unsigned char *) calloc(hrpdp->dplen, 1); + bech32_DecodedResult *decodedResult = malloc(sizeof(bech32_DecodedResult)); + decodedResult->hrplen = 10; + decodedResult->hrp = (char *) calloc(decodedResult->hrplen, 1); + decodedResult->dplen = 1; + decodedResult->dp = (unsigned char *) calloc(decodedResult->dplen, 1); - assert(bech32_decode(hrpdp, bstr) == E_BECH32_LENGTH_TOO_SHORT); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_LENGTH_TOO_SHORT); - free(hrpdp->dp); - free(hrpdp->hrp); - free(hrpdp); + free(decodedResult->dp); + free(decodedResult->hrp); + free(decodedResult); } } @@ -165,38 +165,38 @@ void decode_minimalExample_isSuccessful() { char bstr[] = "a1lqfn3a"; char expectedHrp[] = "a"; - bech32_HrpAndDp * hrpdp = bech32_create_HrpAndDp(bstr); + bech32_DecodedResult * decodedResult = bech32_create_DecodedResult(bstr); - assert(bech32_decode(hrpdp, bstr) == E_BECH32_SUCCESS); - assert(strcmp(hrpdp->hrp, expectedHrp) == 0); - assert(ENCODING_BECH32M == hrpdp->encoding); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_SUCCESS); + assert(strcmp(decodedResult->hrp, expectedHrp) == 0); + assert(ENCODING_BECH32M == decodedResult->encoding); - bech32_free_HrpAndDp(hrpdp); + bech32_free_DecodedResult(decodedResult); } void decode_longExample_isSuccessful() { char bstr[] = "abcdef1l7aum6echk45nj3s0wdvt2fg8x9yrzpqzd3ryx"; char expectedHrp[] = "abcdef"; - bech32_HrpAndDp * hrpdp = bech32_create_HrpAndDp(bstr); + bech32_DecodedResult * decodedResult = bech32_create_DecodedResult(bstr); - assert(bech32_decode(hrpdp, bstr) == E_BECH32_SUCCESS); - assert(strcmp(hrpdp->hrp, expectedHrp) == 0); - assert(hrpdp->dp[0] == '\x1f'); // first 'l' in above dp part - assert(hrpdp->dp[31] == '\0'); // last 'q' in above dp part - assert(ENCODING_BECH32M == hrpdp->encoding); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_SUCCESS); + assert(strcmp(decodedResult->hrp, expectedHrp) == 0); + assert(decodedResult->dp[0] == '\x1f'); // first 'l' in above dp part + assert(decodedResult->dp[31] == '\0'); // last 'q' in above dp part + assert(ENCODING_BECH32M == decodedResult->encoding); - bech32_free_HrpAndDp(hrpdp); + bech32_free_DecodedResult(decodedResult); } void decode_minimalExampleBadChecksum_isUnsuccessful() { char bstr[] = "a1lqfn3q"; // last 'q' should be a 'a' - bech32_HrpAndDp * hrpdp = bech32_create_HrpAndDp(bstr); + bech32_DecodedResult * decodedResult = bech32_create_DecodedResult(bstr); - assert(bech32_decode(hrpdp, bstr) == E_BECH32_INVALID_CHECKSUM); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_INVALID_CHECKSUM); - bech32_free_HrpAndDp(hrpdp); + bech32_free_DecodedResult(decodedResult); } void decode_whenCppMethodThrowsException_isUnsuccessful() { @@ -205,11 +205,11 @@ void decode_whenCppMethodThrowsException_isUnsuccessful() { // and returns an error code char bstr[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw"; - bech32_HrpAndDp * hrpdp = bech32_create_HrpAndDp(bstr); + bech32_DecodedResult * decodedResult = bech32_create_DecodedResult(bstr); - assert(bech32_decode(hrpdp, bstr) == E_BECH32_UNKNOWN_ERROR); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_UNKNOWN_ERROR); - bech32_free_HrpAndDp(hrpdp); + bech32_free_DecodedResult(decodedResult); } void encode_withBadArgs_isUnsuccessful() { @@ -244,7 +244,7 @@ void encode_withBadArgs_isUnsuccessful() { bech32_bstring bstring; bstring.length = 12; // length should (strlen(hrp) + 1 + sizeof(dp) + 6) = 13, but here we will mistakenly set it to 12 bstring.string = (char *)calloc(bstring.length + 1, 1); //string size should be = string.length + 1 for '\0' - // Could also use bech32_create_bstring() to avoid this problem. + // Should use bech32_create_bstring() to avoid this problem. assert(bech32_encode(&bstring, hrp, dp, sizeof(dp)) == E_BECH32_LENGTH_TOO_SHORT); free(bstring.string); @@ -304,19 +304,19 @@ void decode_and_encode_minimalExample_producesSameResult() { char expectedHrp[] = "a"; const size_t expectedDpSize = 0; // 0 = num chars after '1', minus 6 for checksum chars - bech32_HrpAndDp * hrpdp = bech32_create_HrpAndDp(bstr); + bech32_DecodedResult * decodedResult = bech32_create_DecodedResult(bstr); - assert(bech32_decode(hrpdp, bstr) == E_BECH32_SUCCESS); - assert(strcmp(hrpdp->hrp, expectedHrp) == 0); - assert(hrpdp->dplen == expectedDpSize); - assert(ENCODING_BECH32M == hrpdp->encoding); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_SUCCESS); + assert(strcmp(decodedResult->hrp, expectedHrp) == 0); + assert(decodedResult->dplen == expectedDpSize); + assert(ENCODING_BECH32M == decodedResult->encoding); - bech32_bstring *bstring = bech32_create_bstring(hrpdp->hrplen, hrpdp->dplen); + bech32_bstring *bstring = bech32_create_bstring(decodedResult->hrplen, decodedResult->dplen); - assert(bech32_encode(bstring, hrpdp->hrp, hrpdp->dp, hrpdp->dplen) == E_BECH32_SUCCESS); + assert(bech32_encode(bstring, decodedResult->hrp, decodedResult->dp, decodedResult->dplen) == E_BECH32_SUCCESS); assert(strcmp(bstr, bstring->string) == 0); - bech32_free_HrpAndDp(hrpdp); + bech32_free_DecodedResult(decodedResult); bech32_free_bstring(bstring); } @@ -325,19 +325,19 @@ void decode_and_encode_smallExample_producesSameResult() { char expectedHrp[] = "xyz"; const size_t expectedDpSize = 3; // 3 = num chars after '1', minus 6 for checksum chars - bech32_HrpAndDp * hrpdp = bech32_create_HrpAndDp(bstr); + bech32_DecodedResult * decodedResult = bech32_create_DecodedResult(bstr); - assert(bech32_decode(hrpdp, bstr) == E_BECH32_SUCCESS); - assert(strcmp(hrpdp->hrp, expectedHrp) == 0); - assert(hrpdp->dplen == expectedDpSize); - assert(ENCODING_BECH32M == hrpdp->encoding); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_SUCCESS); + assert(strcmp(decodedResult->hrp, expectedHrp) == 0); + assert(decodedResult->dplen == expectedDpSize); + assert(ENCODING_BECH32M == decodedResult->encoding); - bech32_bstring *bstring = bech32_create_bstring(hrpdp->hrplen, hrpdp->dplen); + bech32_bstring *bstring = bech32_create_bstring(decodedResult->hrplen, decodedResult->dplen); - assert(bech32_encode(bstring, hrpdp->hrp, hrpdp->dp, hrpdp->dplen) == E_BECH32_SUCCESS); + assert(bech32_encode(bstring, decodedResult->hrp, decodedResult->dp, decodedResult->dplen) == E_BECH32_SUCCESS); assert(strcmp(bstr, bstring->string) == 0); - bech32_free_HrpAndDp(hrpdp); + bech32_free_DecodedResult(decodedResult); bech32_free_bstring(bstring); } @@ -346,19 +346,19 @@ void decode_and_encode_longExample_producesSameResult() { char expectedHrp[] = "abcdef"; const size_t expectedDpSize = 32; // 32 = num chars after '1', minus 6 for checksum chars - bech32_HrpAndDp * hrpdp = bech32_create_HrpAndDp(bstr); + bech32_DecodedResult * decodedResult = bech32_create_DecodedResult(bstr); - assert(bech32_decode(hrpdp, bstr) == E_BECH32_SUCCESS); - assert(strcmp(hrpdp->hrp, expectedHrp) == 0); - assert(hrpdp->dplen == expectedDpSize); - assert(ENCODING_BECH32M == hrpdp->encoding); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_SUCCESS); + assert(strcmp(decodedResult->hrp, expectedHrp) == 0); + assert(decodedResult->dplen == expectedDpSize); + assert(ENCODING_BECH32M == decodedResult->encoding); - bech32_bstring *bstring = bech32_create_bstring(hrpdp->hrplen, hrpdp->dplen); + bech32_bstring *bstring = bech32_create_bstring(decodedResult->hrplen, decodedResult->dplen); - assert(bech32_encode(bstring, hrpdp->hrp, hrpdp->dp, expectedDpSize) == E_BECH32_SUCCESS); + assert(bech32_encode(bstring, decodedResult->hrp, decodedResult->dp, expectedDpSize) == E_BECH32_SUCCESS); assert(strcmp(bstr, bstring->string) == 0); - bech32_free_HrpAndDp(hrpdp); + bech32_free_DecodedResult(decodedResult); bech32_free_bstring(bstring); } @@ -368,28 +368,28 @@ void decode_c1_minimalExample_isSuccessful() { char bstr[] = "a12uel5l"; char expectedHrp[] = "a"; - bech32_HrpAndDp * hrpdp = bech32_create_HrpAndDp(bstr); + bech32_DecodedResult * decodedResult = bech32_create_DecodedResult(bstr); - assert(bech32_decode(hrpdp, bstr) == E_BECH32_SUCCESS); - assert(strcmp(hrpdp->hrp, expectedHrp) == 0); - assert(ENCODING_BECH32 == hrpdp->encoding); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_SUCCESS); + assert(strcmp(decodedResult->hrp, expectedHrp) == 0); + assert(ENCODING_BECH32 == decodedResult->encoding); - bech32_free_HrpAndDp(hrpdp); + bech32_free_DecodedResult(decodedResult); } void decode_c1_longExample_isSuccessful() { char bstr[] = "abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw"; char expectedHrp[] = "abcdef"; - bech32_HrpAndDp * hrpdp = bech32_create_HrpAndDp(bstr); + bech32_DecodedResult * decodedResult = bech32_create_DecodedResult(bstr); - assert(bech32_decode(hrpdp, bstr) == E_BECH32_SUCCESS); - assert(strcmp(hrpdp->hrp, expectedHrp) == 0); - assert(hrpdp->dp[0] == '\0'); // first 'q' in above dp part - assert(hrpdp->dp[31] == '\x1f'); // last 'l' in above dp part - assert(ENCODING_BECH32 == hrpdp->encoding); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_SUCCESS); + assert(strcmp(decodedResult->hrp, expectedHrp) == 0); + assert(decodedResult->dp[0] == '\0'); // first 'q' in above dp part + assert(decodedResult->dp[31] == '\x1f'); // last 'l' in above dp part + assert(ENCODING_BECH32 == decodedResult->encoding); - bech32_free_HrpAndDp(hrpdp); + bech32_free_DecodedResult(decodedResult); } void encode_c1_minimalExample_isSuccessful() { @@ -421,19 +421,19 @@ void decode_and_encode_c1_minimalExample_producesSameResult() { char expectedHrp[] = "a"; const size_t expectedDpSize = 0; // 0 = num chars after '1', minus 6 for checksum chars - bech32_HrpAndDp * hrpdp = bech32_create_HrpAndDp(bstr); + bech32_DecodedResult * decodedResult = bech32_create_DecodedResult(bstr); - assert(bech32_decode(hrpdp, bstr) == E_BECH32_SUCCESS); - assert(strcmp(hrpdp->hrp, expectedHrp) == 0); - assert(hrpdp->dplen == expectedDpSize); - assert(ENCODING_BECH32 == hrpdp->encoding); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_SUCCESS); + assert(strcmp(decodedResult->hrp, expectedHrp) == 0); + assert(decodedResult->dplen == expectedDpSize); + assert(ENCODING_BECH32 == decodedResult->encoding); - bech32_bstring *bstring = bech32_create_bstring(hrpdp->hrplen, hrpdp->dplen); + bech32_bstring *bstring = bech32_create_bstring(decodedResult->hrplen, decodedResult->dplen); - assert(bech32_encode_using_original_constant(bstring, hrpdp->hrp, hrpdp->dp, hrpdp->dplen) == E_BECH32_SUCCESS); + assert(bech32_encode_using_original_constant(bstring, decodedResult->hrp, decodedResult->dp, decodedResult->dplen) == E_BECH32_SUCCESS); assert(strcmp(bstr, bstring->string) == 0); - bech32_free_HrpAndDp(hrpdp); + bech32_free_DecodedResult(decodedResult); bech32_free_bstring(bstring); } @@ -442,19 +442,19 @@ void decode_and_encode_c1_smallExample_producesSameResult() { char expectedHrp[] = "xyz"; const size_t expectedDpSize = 3; // 3 = num chars after '1', minus 6 for checksum chars - bech32_HrpAndDp * hrpdp = bech32_create_HrpAndDp(bstr); + bech32_DecodedResult * decodedResult = bech32_create_DecodedResult(bstr); - assert(bech32_decode(hrpdp, bstr) == E_BECH32_SUCCESS); - assert(strcmp(hrpdp->hrp, expectedHrp) == 0); - assert(hrpdp->dplen == expectedDpSize); - assert(ENCODING_BECH32 == hrpdp->encoding); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_SUCCESS); + assert(strcmp(decodedResult->hrp, expectedHrp) == 0); + assert(decodedResult->dplen == expectedDpSize); + assert(ENCODING_BECH32 == decodedResult->encoding); - bech32_bstring *bstring = bech32_create_bstring(hrpdp->hrplen, hrpdp->dplen); + bech32_bstring *bstring = bech32_create_bstring(decodedResult->hrplen, decodedResult->dplen); - assert(bech32_encode_using_original_constant(bstring, hrpdp->hrp, hrpdp->dp, hrpdp->dplen) == E_BECH32_SUCCESS); + assert(bech32_encode_using_original_constant(bstring, decodedResult->hrp, decodedResult->dp, decodedResult->dplen) == E_BECH32_SUCCESS); assert(strcmp(bstr, bstring->string) == 0); - bech32_free_HrpAndDp(hrpdp); + bech32_free_DecodedResult(decodedResult); bech32_free_bstring(bstring); } @@ -463,19 +463,19 @@ void decode_and_encode_c1_longExample_producesSameResult() { char expectedHrp[] = "abcdef"; const size_t expectedDpSize = 32; // 32 = num chars after '1', minus 6 for checksum chars - bech32_HrpAndDp * hrpdp = bech32_create_HrpAndDp(bstr); + bech32_DecodedResult * decodedResult = bech32_create_DecodedResult(bstr); - assert(bech32_decode(hrpdp, bstr) == E_BECH32_SUCCESS); - assert(strcmp(hrpdp->hrp, expectedHrp) == 0); - assert(hrpdp->dplen == expectedDpSize); - assert(ENCODING_BECH32 == hrpdp->encoding); + assert(bech32_decode(decodedResult, bstr) == E_BECH32_SUCCESS); + assert(strcmp(decodedResult->hrp, expectedHrp) == 0); + assert(decodedResult->dplen == expectedDpSize); + assert(ENCODING_BECH32 == decodedResult->encoding); - bech32_bstring *bstring = bech32_create_bstring(hrpdp->hrplen, hrpdp->dplen); + bech32_bstring *bstring = bech32_create_bstring(decodedResult->hrplen, decodedResult->dplen); - assert(bech32_encode_using_original_constant(bstring, hrpdp->hrp, hrpdp->dp, hrpdp->dplen) == E_BECH32_SUCCESS); + assert(bech32_encode_using_original_constant(bstring, decodedResult->hrp, decodedResult->dp, decodedResult->dplen) == E_BECH32_SUCCESS); assert(strcmp(bstr, bstring->string) == 0); - bech32_free_HrpAndDp(hrpdp); + bech32_free_DecodedResult(decodedResult); bech32_free_bstring(bstring); } @@ -494,43 +494,43 @@ void test_stripUnknownChars() { stripUnknownChars_withFunkyString_returnsStrippedString(); } -void create_HrpAndDp_storage_withNullInput_returnsNull() { - bech32_HrpAndDp *p = bech32_create_HrpAndDp(NULL); +void create_DecodedResult_storage_withNullInput_returnsNull() { + bech32_DecodedResult *p = bech32_create_DecodedResult(NULL); assert(p == NULL); } -void create_HrpAndDp_storage_withZeroLengthInput_returnsNull() { +void create_DecodedResult_storage_withZeroLengthInput_returnsNull() { char empty[] = ""; - bech32_HrpAndDp *p = bech32_create_HrpAndDp(empty); + bech32_DecodedResult *p = bech32_create_DecodedResult(empty); assert(p == NULL); } -void create_HrpAndDp_storage_withMalformedInput_returnsNull() { +void create_DecodedResult_storage_withMalformedInput_returnsNull() { char tooShort[] = "a1a"; - bech32_HrpAndDp *p = bech32_create_HrpAndDp(tooShort); + bech32_DecodedResult *p = bech32_create_DecodedResult(tooShort); assert(p == NULL); char noSeparator[] = "aaaaaaaa"; - p = bech32_create_HrpAndDp(noSeparator); + p = bech32_create_DecodedResult(noSeparator); assert(p == NULL); char checksumTooShort[] = "aa1qqqqq"; - p = bech32_create_HrpAndDp(checksumTooShort); + p = bech32_create_DecodedResult(checksumTooShort); assert(p == NULL); } -void create_HrpAndDp_storage_minimalExample_isSuccessful() { +void create_DecodedResult_storage_minimalExample_isSuccessful() { char bstr[] = "a12uel5l"; - bech32_HrpAndDp *p = bech32_create_HrpAndDp(bstr); + bech32_DecodedResult *p = bech32_create_DecodedResult(bstr); assert(p != NULL); - bech32_free_HrpAndDp(p); + bech32_free_DecodedResult(p); } -void create_HrpAndDp_storage_smallExample_isSuccessful() { +void create_DecodedResult_storage_smallExample_isSuccessful() { char bstr[] = "xyz1pzr9dvupm"; - bech32_HrpAndDp *p = bech32_create_HrpAndDp(bstr); + bech32_DecodedResult *p = bech32_create_DecodedResult(bstr); assert(p != NULL); - bech32_free_HrpAndDp(p); + bech32_free_DecodedResult(p); } void create_encoded_string_storage_withMalformedInput_returnsNull() { @@ -551,63 +551,63 @@ void create_encoded_string_storage_smallExample_isSuccessful() { bech32_free_bstring(bstring); } -void create_encoded_string_storage_from_HrpAndDp_withNullInput_returnsNull() { - bech32_bstring *bstring = bech32_create_bstring_from_HrpAndDp(NULL); +void create_encoded_string_storage_from_DecodedResult_withNullInput_returnsNull() { + bech32_bstring *bstring = bech32_create_bstring_from_DecodedResult(NULL); assert(bstring == NULL); } -void create_encoded_string_storage_from_HrpAndDp_withMalformedInput_returnsNull() { - // create a valid bech32_HrpAndDp, then corrupt it for testing +void create_encoded_string_storage_from_DecodedResult_withMalformedInput_returnsNull() { + // create a valid bech32_DecodedResult, then corrupt it for testing char bstr[] = "xyz1pzr9dvupm"; - bech32_HrpAndDp *hd = bech32_create_HrpAndDp(bstr); + bech32_DecodedResult *decodedResult = bech32_create_DecodedResult(bstr); // hrp too short - hd->hrplen = 0; - bech32_bstring *bstring = bech32_create_bstring_from_HrpAndDp(hd); + decodedResult->hrplen = 0; + bech32_bstring *bstring = bech32_create_bstring_from_DecodedResult(decodedResult); assert(bstring == NULL); - bech32_free_HrpAndDp(hd); + bech32_free_DecodedResult(decodedResult); } -void create_encoded_string_storage_from_HrpAndDp_minimalExample_isSuccessful() { +void create_encoded_string_storage_from_DecodedResult_minimalExample_isSuccessful() { char bstr[] = "a12uel5l"; - bech32_HrpAndDp *hd = bech32_create_HrpAndDp(bstr); - assert(hd != NULL); + bech32_DecodedResult *decodedResult = bech32_create_DecodedResult(bstr); + assert(decodedResult != NULL); - bech32_bstring *bstring = bech32_create_bstring_from_HrpAndDp(hd); + bech32_bstring *bstring = bech32_create_bstring_from_DecodedResult(decodedResult); assert(bstring != NULL); - bech32_free_HrpAndDp(hd); + bech32_free_DecodedResult(decodedResult); bech32_free_bstring(bstring); } -void create_encoded_string_storage_from_HrpAndDp_smallExample_isSuccessful() { +void create_encoded_string_storage_from_DecodedResult_smallExample_isSuccessful() { char bstr[] = "xyz1pzr9dvupm"; - bech32_HrpAndDp *hd = bech32_create_HrpAndDp(bstr); - assert(hd != NULL); + bech32_DecodedResult *decodedResult = bech32_create_DecodedResult(bstr); + assert(decodedResult != NULL); - bech32_bstring *bstring = bech32_create_bstring_from_HrpAndDp(hd); + bech32_bstring *bstring = bech32_create_bstring_from_DecodedResult(decodedResult); assert(bstring != NULL); - bech32_free_HrpAndDp(hd); + bech32_free_DecodedResult(decodedResult); bech32_free_bstring(bstring); } void test_memoryAllocation() { - create_HrpAndDp_storage_withNullInput_returnsNull(); - create_HrpAndDp_storage_withZeroLengthInput_returnsNull(); - create_HrpAndDp_storage_withMalformedInput_returnsNull(); - create_HrpAndDp_storage_minimalExample_isSuccessful(); - create_HrpAndDp_storage_smallExample_isSuccessful(); + create_DecodedResult_storage_withNullInput_returnsNull(); + create_DecodedResult_storage_withZeroLengthInput_returnsNull(); + create_DecodedResult_storage_withMalformedInput_returnsNull(); + create_DecodedResult_storage_minimalExample_isSuccessful(); + create_DecodedResult_storage_smallExample_isSuccessful(); create_encoded_string_storage_withMalformedInput_returnsNull(); create_encoded_string_storage_minimalExample_isSuccessful(); create_encoded_string_storage_smallExample_isSuccessful(); - create_encoded_string_storage_from_HrpAndDp_withNullInput_returnsNull(); - create_encoded_string_storage_from_HrpAndDp_withMalformedInput_returnsNull(); - create_encoded_string_storage_from_HrpAndDp_minimalExample_isSuccessful(); - create_encoded_string_storage_from_HrpAndDp_smallExample_isSuccessful(); + create_encoded_string_storage_from_DecodedResult_withNullInput_returnsNull(); + create_encoded_string_storage_from_DecodedResult_withMalformedInput_returnsNull(); + create_encoded_string_storage_from_DecodedResult_minimalExample_isSuccessful(); + create_encoded_string_storage_from_DecodedResult_smallExample_isSuccessful(); } void tests_using_default_checksum_constant() { diff --git a/test/testbech32/test_Bech32.cpp b/test/testbech32/test_Bech32.cpp index 9c66c25..84e2622 100644 --- a/test/testbech32/test_Bech32.cpp +++ b/test/testbech32/test_Bech32.cpp @@ -315,32 +315,48 @@ RC_GTEST_PROP(Bech32TestRC, findLastSeparatorCharacterPosition, () RC_ASSERT(findSeparatorPosition(str) == pos2); } -// check that we can split strings based on the separator -TEST(Bech32Test, split_strings) { - std::string data("ab1cd"); - bech32::HrpAndDp b = splitString(data); - ASSERT_EQ(b.hrp, "ab"); - ASSERT_EQ(b.dp[0], 'c'); - ASSERT_EQ(b.dp.size(), 2); - - data = "ab1"; - b = splitString(data); - ASSERT_EQ(b.hrp, "ab"); - ASSERT_TRUE(b.dp.empty()); +// check that we can extract the human readable part of the string +TEST(Bech32Test, extractHumanReadablePart) { + std::string str("ab1cd"); + std::string hrp = extractHumanReadablePart(str); + ASSERT_EQ(hrp, "ab"); - data = "1cd"; - b = splitString(data); - ASSERT_EQ(b.hrp, ""); - ASSERT_EQ(b.dp[0], 'c'); - ASSERT_EQ(b.dp.size(), 2); + str = "ab1"; + hrp = extractHumanReadablePart(str); + ASSERT_EQ(hrp, "ab"); - data = "1"; - b = splitString(data); - ASSERT_EQ(b.hrp, ""); - ASSERT_TRUE(b.dp.empty()); + str = "1cd"; + hrp = extractHumanReadablePart(str); + ASSERT_EQ(hrp, ""); + + str = "1"; + hrp = extractHumanReadablePart(str); + ASSERT_EQ(hrp, ""); +} + +// check that we can extract the data part of the string +TEST(Bech32Test, extractDataPart) { + std::string str("ab1cd"); + std::vector dp = extractDataPart(str); + ASSERT_EQ(dp[0], 'c'); + ASSERT_EQ(dp.size(), 2); + + str = "ab1"; + dp = extractDataPart(str); + ASSERT_TRUE(dp.empty()); + + str = "1cd"; + dp = extractDataPart(str); + ASSERT_EQ(dp.size(), 2); + ASSERT_EQ(dp[0], 'c'); + ASSERT_EQ(dp[1], 'd'); + + str = "1"; + dp = extractDataPart(str); + ASSERT_TRUE(dp.empty()); } -RC_GTEST_PROP(Bech32TestRC, checkSplitString, () +RC_GTEST_PROP(Bech32TestRC, checkExtractSubstrings, () ) { // generate string with chars between a-z and 0-9 const auto str1 = @@ -361,46 +377,49 @@ RC_GTEST_PROP(Bech32TestRC, checkSplitString, () // combine the strings, with a separator character between auto str = str1 + bech32::separator + str2; - bech32::HrpAndDp b = splitString(str); + std::string hrp = extractHumanReadablePart(str); + std::vector dp = extractDataPart(str); - RC_ASSERT(b.hrp == str1); - RC_ASSERT(b.dp.size() == str2.length()); + RC_ASSERT(hrp == str1); + RC_ASSERT(dp.size() == str2.length()); + for(size_t i=0; i dp = extractDataPart(str); + ASSERT_NO_THROW(mapDP(dp)); + ASSERT_EQ(dp[0], '\x1d'); + ASSERT_EQ(dp[1], '\x18'); + ASSERT_EQ(dp[2], '\x0d'); - data = "ACB1DEF"; - b = splitString(data); - ASSERT_NO_THROW(mapDP(b.dp)); - ASSERT_EQ(b.dp[0], '\x0d'); - ASSERT_EQ(b.dp[1], '\x19'); - ASSERT_EQ(b.dp[2], '\x09'); + str = "ACB1DEF"; + dp = extractDataPart(str); + ASSERT_NO_THROW(mapDP(dp)); + ASSERT_EQ(dp[0], '\x0d'); + ASSERT_EQ(dp[1], '\x19'); + ASSERT_EQ(dp[2], '\x09'); - data = "ACB1abc"; - b = splitString(data); - ASSERT_THROW(mapDP(b.dp), std::runtime_error); // throws because 'b' is invalid character + str = "ACB1abc"; + dp = extractDataPart(str); + ASSERT_THROW(mapDP(dp), std::runtime_error); // throws because 'b' is invalid character } // check that we can expand the hrp @@ -436,88 +455,100 @@ TEST(Bech32Test, polymod) { // check the verifyChecksum method TEST(Bech32Test, verifyChecksum_good) { - std::string data("a1lqfn3a"); - bech32::HrpAndDp b = splitString(data); - convertToLowercase(b.hrp); - mapDP(b.dp); - ASSERT_TRUE(verifyChecksum(b.hrp, b.dp)); - - data = "A1LQFN3A"; - b = splitString(data); - convertToLowercase(b.hrp); - mapDP(b.dp); - ASSERT_TRUE(verifyChecksum(b.hrp, b.dp)); - - data = "abcdef1l7aum6echk45nj3s0wdvt2fg8x9yrzpqzd3ryx"; - b = splitString(data); - convertToLowercase(b.hrp); - mapDP(b.dp); - ASSERT_TRUE(verifyChecksum(b.hrp, b.dp)); - - data = "split1checkupstagehandshakeupstreamerranterredcaperredlc445v"; - b = splitString(data); - convertToLowercase(b.hrp); - mapDP(b.dp); - ASSERT_TRUE(verifyChecksum(b.hrp, b.dp)); - - data = "an83characterlonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11sg7hg6"; - b = splitString(data); - convertToLowercase(b.hrp); - mapDP(b.dp); - ASSERT_TRUE(verifyChecksum(b.hrp, b.dp)); - - data = "11llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllludsr8"; - b = splitString(data); - convertToLowercase(b.hrp); - mapDP(b.dp); - ASSERT_TRUE(verifyChecksum(b.hrp, b.dp)); + std::string str("a1lqfn3a"); + std::string hrp = extractHumanReadablePart(str); + std::vector dp = extractDataPart(str); + convertToLowercase(hrp); + mapDP(dp); + ASSERT_TRUE(verifyChecksum(hrp, dp)); + + str = "A1LQFN3A"; + hrp = extractHumanReadablePart(str); + dp = extractDataPart(str); + convertToLowercase(hrp); + mapDP(dp); + ASSERT_TRUE(verifyChecksum(hrp, dp)); + + str = "abcdef1l7aum6echk45nj3s0wdvt2fg8x9yrzpqzd3ryx"; + hrp = extractHumanReadablePart(str); + dp = extractDataPart(str); + convertToLowercase(hrp); + mapDP(dp); + ASSERT_TRUE(verifyChecksum(hrp, dp)); + + str = "split1checkupstagehandshakeupstreamerranterredcaperredlc445v"; + hrp = extractHumanReadablePart(str); + dp = extractDataPart(str); + convertToLowercase(hrp); + mapDP(dp); + ASSERT_TRUE(verifyChecksum(hrp, dp)); + + str = "an83characterlonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11sg7hg6"; + hrp = extractHumanReadablePart(str); + dp = extractDataPart(str); + convertToLowercase(hrp); + mapDP(dp); + ASSERT_TRUE(verifyChecksum(hrp, dp)); + + str = "11llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllludsr8"; + hrp = extractHumanReadablePart(str); + dp = extractDataPart(str); + convertToLowercase(hrp); + mapDP(dp); + ASSERT_TRUE(verifyChecksum(hrp, dp)); } // check the verifyChecksum method // these are simply the "good" tests from above with a single character changed TEST(Bech32Test, verifyChecksum_bad) { - std::string data("a1lqfn33"); - bech32::HrpAndDp b = splitString(data); - convertToLowercase(b.hrp); - mapDP(b.dp); - ASSERT_FALSE(verifyChecksum(b.hrp, b.dp)); - - data = "A1LQFN33"; - b = splitString(data); - convertToLowercase(b.hrp); - mapDP(b.dp); - ASSERT_FALSE(verifyChecksum(b.hrp, b.dp)); - - data = "abcdef1l7aum6echk45nj3s0wdvt2fg8x9yrzpqzd3ryy"; - b = splitString(data); - convertToLowercase(b.hrp); - mapDP(b.dp); - ASSERT_FALSE(verifyChecksum(b.hrp, b.dp)); - - data = "split1checkupstagehandshakeupstreamerranterredcaperredlc445s"; - b = splitString(data); - convertToLowercase(b.hrp); - mapDP(b.dp); - ASSERT_FALSE(verifyChecksum(b.hrp, b.dp)); - - data = "an83characterlonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11sg7hg7"; - b = splitString(data); - convertToLowercase(b.hrp); - mapDP(b.dp); - ASSERT_FALSE(verifyChecksum(b.hrp, b.dp)); - - data = "11llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllludsrc"; - b = splitString(data); - convertToLowercase(b.hrp); - mapDP(b.dp); - ASSERT_FALSE(verifyChecksum(b.hrp, b.dp)); + std::string str("a1lqfn33"); + std::string hrp = extractHumanReadablePart(str); + std::vector dp = extractDataPart(str); + convertToLowercase(hrp); + mapDP(dp); + ASSERT_FALSE(verifyChecksum(hrp, dp)); + + str = "A1LQFN33"; + hrp = extractHumanReadablePart(str); + dp = extractDataPart(str); + convertToLowercase(hrp); + mapDP(dp); + ASSERT_FALSE(verifyChecksum(hrp, dp)); + + str = "abcdef1l7aum6echk45nj3s0wdvt2fg8x9yrzpqzd3ryy"; + hrp = extractHumanReadablePart(str); + dp = extractDataPart(str); + convertToLowercase(hrp); + mapDP(dp); + ASSERT_FALSE(verifyChecksum(hrp, dp)); + + str = "split1checkupstagehandshakeupstreamerranterredcaperredlc445s"; + hrp = extractHumanReadablePart(str); + dp = extractDataPart(str); + convertToLowercase(hrp); + mapDP(dp); + ASSERT_FALSE(verifyChecksum(hrp, dp)); + + str = "an83characterlonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11sg7hg7"; + hrp = extractHumanReadablePart(str); + dp = extractDataPart(str); + convertToLowercase(hrp); + mapDP(dp); + ASSERT_FALSE(verifyChecksum(hrp, dp)); + + str = "11llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllludsrc"; + hrp = extractHumanReadablePart(str); + dp = extractDataPart(str); + convertToLowercase(hrp); + mapDP(dp); + ASSERT_FALSE(verifyChecksum(hrp, dp)); } // check the main bech32 decode method TEST(Bech32Test, decode_good) { std::string data("a1lqfn3a"); - bech32::HrpAndDp b = bech32::decode(data); + bech32::DecodedResult b = bech32::decode(data); ASSERT_EQ(b.encoding, bech32::Encoding::Bech32m); ASSERT_EQ(b.hrp, "a"); ASSERT_TRUE(b.dp.empty()); @@ -653,25 +684,25 @@ TEST(Bech32Test, encode_good) { // check that we can decode and then encode back to the original TEST(Bech32Test, check_decode_encode) { std::string data("a1lqfn3a"); - bech32::HrpAndDp bs = bech32::decode(data); - ASSERT_EQ(bs.encoding, bech32::Encoding::Bech32m); - ASSERT_EQ(bs.hrp, "a"); - ASSERT_TRUE(bs.dp.empty()); - std::string enc = bech32::encode(bs.hrp, bs.dp); + bech32::DecodedResult decodedResult = bech32::decode(data); + ASSERT_EQ(decodedResult.encoding, bech32::Encoding::Bech32m); + ASSERT_EQ(decodedResult.hrp, "a"); + ASSERT_TRUE(decodedResult.dp.empty()); + std::string enc = bech32::encode(decodedResult.hrp, decodedResult.dp); ASSERT_EQ(enc, data); data = "abcdef1l7aum6echk45nj3s0wdvt2fg8x9yrzpqzd3ryx"; - bs = bech32::decode(data); - ASSERT_EQ(bs.encoding, bech32::Encoding::Bech32m); - ASSERT_EQ(bs.hrp, "abcdef"); - enc = bech32::encode(bs.hrp, bs.dp); + decodedResult = bech32::decode(data); + ASSERT_EQ(decodedResult.encoding, bech32::Encoding::Bech32m); + ASSERT_EQ(decodedResult.hrp, "abcdef"); + enc = bech32::encode(decodedResult.hrp, decodedResult.dp); ASSERT_EQ(enc, data); data = "split1checkupstagehandshakeupstreamerranterredcaperredlc445v"; - bs = bech32::decode(data); - ASSERT_EQ(bs.encoding, bech32::Encoding::Bech32m); - ASSERT_EQ(bs.hrp, "split"); - enc = bech32::encode(bs.hrp, bs.dp); + decodedResult = bech32::decode(data); + ASSERT_EQ(decodedResult.encoding, bech32::Encoding::Bech32m); + ASSERT_EQ(decodedResult.hrp, "split"); + enc = bech32::encode(decodedResult.hrp, decodedResult.dp); ASSERT_EQ(enc, data); } @@ -706,7 +737,7 @@ RC_GTEST_PROP(Bech32TestRC, encodeThenDecodeShouldProduceInitialData, () } std::string bstr = bech32::encode(str1, data); - bech32::HrpAndDp b = bech32::decode(bstr); + bech32::DecodedResult b = bech32::decode(bstr); RC_ASSERT(str1 == b.hrp); RC_ASSERT(data == b.dp); @@ -720,7 +751,6 @@ TEST(Bech32Test, encode_empty_args) { } TEST(Bech32Test, strip_unknown_chars) { - std::string bStr; EXPECT_EQ(bech32::stripUnknownChars("tx1-rqqq-qqqq-qmhu-qk"), "tx1rqqqqqqqqmhuqk"); // TODO Not sure what to do about the extra '1' in the next test. We leave it in // because we leave in the separator character, but I think the test might be expected