Skip to content

Commit

Permalink
Merge pull request dcdpr#4 from danpape/master
Browse files Browse the repository at this point in the history
Fix issues from last pull request
  • Loading branch information
dcdpr authored Feb 19, 2021
2 parents 45865fb + 5f1d37b commit 43c689e
Show file tree
Hide file tree
Showing 10 changed files with 518 additions and 489 deletions.
30 changes: 15 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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++
Expand Down Expand Up @@ -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);
}
```

Expand Down Expand Up @@ -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);
}
```
Expand All @@ -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:
Expand Down
42 changes: 21 additions & 21 deletions examples/c_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -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);
}

Expand Down Expand Up @@ -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() {
Expand All @@ -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() {
Expand Down
14 changes: 7 additions & 7 deletions examples/c_usage_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
31 changes: 14 additions & 17 deletions examples/cpp_example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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() {
Expand All @@ -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() {
Expand All @@ -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() {
Expand Down
8 changes: 4 additions & 4 deletions examples/cpp_usage_example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
42 changes: 20 additions & 22 deletions include/libbech32/libbech32.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
};

Expand All @@ -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<unsigned char> dp;
Expand All @@ -40,7 +39,7 @@ namespace bech32 {
std::string encodeUsingOriginalConstant(const std::string & hrp, const std::vector<unsigned char> & 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 {

Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 43c689e

Please sign in to comment.