diff --git a/ref/c/segwit_addr.c b/ref/c/segwit_addr.c index a1164e7..390b3da 100644 --- a/ref/c/segwit_addr.c +++ b/ref/c/segwit_addr.c @@ -189,21 +189,43 @@ int segwit_addr_encode(char *output, const char *hrp, int witver, const uint8_t return bech32_encode(output, hrp, data, datalen, enc); } -int segwit_addr_decode(int* witver, uint8_t* witdata, size_t* witdata_len, const char* hrp, const char* addr) { +int segwit_addr_decode_detailed(int* witver, uint8_t* witdata, size_t* witdata_len, + char *hrp_out, const char* addr) +{ uint8_t data[84]; char hrp_actual[84]; size_t data_len; + bech32_encoding enc = bech32_decode(hrp_actual, data, &data_len, addr); if (enc == BECH32_ENCODING_NONE) return 0; if (data_len == 0 || data_len > 65) return 0; - if (strncmp(hrp, hrp_actual, 84) != 0) return 0; if (data[0] > 16) return 0; - if (data[0] == 0 && enc != BECH32_ENCODING_BECH32) return 0; - if (data[0] > 0 && enc != BECH32_ENCODING_BECH32M) return 0; + *witdata_len = 0; + *witver = data[0]; + if (!convert_bits(witdata, witdata_len, 8, data + 1, data_len - 1, 5, 0)) return 0; if (*witdata_len < 2 || *witdata_len > 40) return 0; if (data[0] == 0 && *witdata_len != 20 && *witdata_len != 32) return 0; - *witver = data[0]; + + if (data[0] == 0 && enc != BECH32_ENCODING_BECH32) return 0; + if (data[0] > 0 && enc != BECH32_ENCODING_BECH32M) return 0; + + if(hrp_out) { + strncpy(hrp_out, hrp_actual, 20); + } + + return 1; +} + +int segwit_addr_decode(int* witver, uint8_t* witdata, size_t* witdata_len, const char* hrp, const char* addr) { + + char hrp_actual[84]; + + int ok = segwit_addr_decode_detailed(witver, witdata, witdata_len, hrp_actual, addr); + if (!ok) return 0; + + if (strncmp(hrp, hrp_actual, 84) != 0) return 0; + return 1; } diff --git a/ref/c/segwit_addr.h b/ref/c/segwit_addr.h index 511970a..096870f 100644 --- a/ref/c/segwit_addr.h +++ b/ref/c/segwit_addr.h @@ -24,6 +24,13 @@ #include +/** Supported encodings. */ +typedef enum { + BECH32_ENCODING_NONE, + BECH32_ENCODING_BECH32, + BECH32_ENCODING_BECH32M +} bech32_encoding; + /** Encode a SegWit address * @@ -65,12 +72,26 @@ int segwit_addr_decode( const char* addr ); -/** Supported encodings. */ -typedef enum { - BECH32_ENCODING_NONE, - BECH32_ENCODING_BECH32, - BECH32_ENCODING_BECH32M -} bech32_encoding; + +/** Decode a SegWit address, capturing HRP. + * + * Out: ver: Pointer to an int that will be updated to contain the witness + * program version (between 0 and 16 inclusive). + * prog: Pointer to a buffer of size 40 that will be updated to + * contain the witness program bytes. + * prog_len: Pointer to a size_t that will be updated to contain the length + * of bytes in prog. + * hrp_out: Pointer to char[20] to hold observed HRP value, or NULL if not wanted. + * addr: Pointer to the null-terminated address. + * Returns 1 if successful. + */ +int segwit_addr_decode_detailed( + int* ver, + uint8_t* prog, + size_t* prog_len, + char *hrp_out, + const char* addr +); /** Encode a Bech32 or Bech32m string *