2828
2929#ifdef BUILD_ELEMENTS
3030
31+ #define CHECKSUM_BLECH32 0x1
32+ #define CHECKSUM_BLECH32M 0x455972a3350f7a1ull
33+
3134static uint64_t blech32_polymod_step (uint64_t pre ) {
3235 uint8_t b = pre >> 55 ;
3336 return ((pre & 0x7fffffffffffffULL ) << 5 ) ^
@@ -53,7 +56,7 @@ static const int8_t blech32_charset_rev[128] = {
5356
5457#define WALLY_BLECH32_MAXLEN ((size_t) 1000)
5558
56- static int blech32_encode (char * output , const char * hrp , const uint8_t * data , size_t data_len , size_t max_input_len ) {
59+ static int blech32_encode (char * output , const char * hrp , const uint8_t * data , size_t data_len , size_t max_input_len , bool is_blech32m ) {
5760 uint64_t chk = 1 ;
5861 size_t i = 0 ;
5962 while (hrp [i ] != 0 ) {
@@ -81,15 +84,15 @@ static int blech32_encode(char *output, const char *hrp, const uint8_t *data, si
8184 for (i = 0 ; i < 12 ; ++ i ) {
8285 chk = blech32_polymod_step (chk );
8386 }
84- chk ^= 1 ;
87+ chk ^= is_blech32m ? CHECKSUM_BLECH32M : CHECKSUM_BLECH32 ;
8588 for (i = 0 ; i < 12 ; ++ i ) {
8689 * (output ++ ) = blech32_charset [(chk >> ((11 - i ) * 5 )) & 0x1f ];
8790 }
8891 * output = 0 ;
8992 return 1 ;
9093}
9194
92- static int blech32_decode (char * hrp , uint8_t * data , size_t * data_len , const char * input , size_t max_input_len ) {
95+ static int blech32_decode (char * hrp , uint8_t * data , size_t * data_len , const char * input , size_t max_input_len , bool * is_blech32m ) {
9396 uint64_t chk = 1 ;
9497 size_t i ;
9598 size_t input_len = strlen (input );
@@ -143,7 +146,8 @@ static int blech32_decode(char *hrp, uint8_t *data, size_t *data_len, const char
143146 if (have_lower && have_upper ) {
144147 return 0 ;
145148 }
146- return chk == 1 ;
149+ * is_blech32m = chk == CHECKSUM_BLECH32M ;
150+ return chk == CHECKSUM_BLECH32 || chk == CHECKSUM_BLECH32M ;
147151}
148152
149153static int blech32_convert_bits (uint8_t * out , size_t * outlen , int outbits , const uint8_t * in , size_t inlen , int inbits , int pad ) {
@@ -168,28 +172,31 @@ static int blech32_convert_bits(uint8_t *out, size_t *outlen, int outbits, const
168172 return 1 ;
169173}
170174
171- static int blech32_addr_encode (char * output , const char * hrp , int witver , const uint8_t * witprog , size_t witprog_len ) {
175+ static int blech32_addr_encode (char * output , const char * hrp , uint8_t witver , const uint8_t * witprog , size_t witprog_len ) {
172176 uint8_t data [WALLY_BLECH32_MAXLEN ];
173177 size_t datalen = 0 ;
174- if (witver < 0 || witver > 16 ) goto fail ;
178+ if (witver > 16 ) goto fail ;
175179 if (witver == 0 && witprog_len != 53 && witprog_len != 65 ) goto fail ;
176180 if (witprog_len < 2 || witprog_len > 65 ) goto fail ;
177181 data [0 ] = witver ;
178182 blech32_convert_bits (data + 1 , & datalen , 5 , witprog , witprog_len , 8 , 1 );
179183 ++ datalen ;
180- return blech32_encode (output , hrp , data , datalen , WALLY_BLECH32_MAXLEN );
184+ return blech32_encode (output , hrp , data , datalen , WALLY_BLECH32_MAXLEN , witver != 0 );
181185fail :
182186 wally_clear_2 (data , sizeof (data ), (void * )witprog , witprog_len );
183187 return 0 ;
184188}
185189
186- static int blech32_addr_decode (int * witver , uint8_t * witdata , size_t * witdata_len , const char * hrp , const char * addr ) {
190+ static int blech32_addr_decode (uint8_t * witver , uint8_t * witdata , size_t * witdata_len , const char * hrp , const char * addr ) {
187191 uint8_t data [WALLY_BLECH32_MAXLEN ];
188192 char hrp_actual [WALLY_BLECH32_MAXLEN ];
189193 size_t data_len ;
190- if (!blech32_decode (hrp_actual , data , & data_len , addr , WALLY_BLECH32_MAXLEN )) goto fail ;
194+ bool is_blech32m = false;
195+ if (!blech32_decode (hrp_actual , data , & data_len , addr , WALLY_BLECH32_MAXLEN , & is_blech32m )) goto fail ;
191196 if (data_len == 0 || data_len > (WALLY_BLECH32_MAXLEN - 4 )) goto fail ;
192197 if (strncmp (hrp , hrp_actual , WALLY_BLECH32_MAXLEN - 5 ) != 0 ) goto fail ;
198+ if (data [0 ] == 0 && is_blech32m ) goto fail ;
199+ if (data [0 ] != 0 && !is_blech32m ) goto fail ;
193200 if (data [0 ] > 16 ) goto fail ;
194201 * witdata_len = 0 ;
195202 if (!blech32_convert_bits (witdata , witdata_len , 8 , data + 1 , data_len - 1 , 5 , 0 )) goto fail ;
@@ -210,9 +217,9 @@ int wally_confidential_addr_to_addr_segwit(
210217{
211218 unsigned char buf [WALLY_BLECH32_MAXLEN ];
212219 unsigned char * hash_bytes_p = & buf [EC_PUBLIC_KEY_LEN - 2 ];
213- int witver = 0 ;
214220 size_t written = 0 ;
215221 int ret ;
222+ uint8_t witver ;
216223
217224 if (output )
218225 * output = NULL ;
@@ -222,11 +229,11 @@ int wally_confidential_addr_to_addr_segwit(
222229
223230 if (!blech32_addr_decode (& witver , buf , & written , confidential_addr_family , address ))
224231 ret = WALLY_EINVAL ;
225- else if (witver != 0 || ( written != 53 && written != 65 ) )
226- ret = WALLY_EINVAL ; /* Only v0 witness programs are currently allowed */
232+ else if (written != 53 && written != 65 )
233+ ret = WALLY_EINVAL ;
227234 else {
228235 written = written - EC_PUBLIC_KEY_LEN + 2 ;
229- hash_bytes_p [0 ] = ( unsigned char ) witver ;
236+ hash_bytes_p [0 ] = value_to_op_n ( witver ) ;
230237 hash_bytes_p [1 ] = (unsigned char ) (written - 2 );
231238 ret = wally_addr_segwit_from_bytes (hash_bytes_p , written ,
232239 addr_family , 0 , output );
@@ -243,17 +250,16 @@ int wally_confidential_addr_segwit_to_ec_public_key(
243250 size_t len )
244251{
245252 unsigned char buf [WALLY_BLECH32_MAXLEN ];
246- int witver = 0 ;
247253 size_t written = 0 ;
248254 int ret = WALLY_OK ;
255+ uint8_t witver ;
249256
250257 if (!address || !bytes_out || !confidential_addr_family || len != EC_PUBLIC_KEY_LEN )
251258 return WALLY_EINVAL ;
252259
253- /* Only v0 witness programs are currently allowed */
254260 if (!blech32_addr_decode (& witver , buf , & written , confidential_addr_family , address ))
255261 ret = WALLY_EINVAL ;
256- else if (witver != 0 || ( written != 53 && written != 65 ) )
262+ else if (written != 53 && written != 65 )
257263 ret = WALLY_EINVAL ;
258264 else
259265 memcpy (bytes_out , buf , EC_PUBLIC_KEY_LEN );
@@ -275,6 +281,7 @@ int wally_confidential_addr_from_addr_segwit(
275281 unsigned char * hash_bytes_p = & buf [EC_PUBLIC_KEY_LEN - 2 ];
276282 size_t written = SHA256_LEN + 2 ;
277283 int ret ;
284+ size_t witver ;
278285
279286 if (output )
280287 * output = NULL ;
@@ -284,25 +291,32 @@ int wally_confidential_addr_from_addr_segwit(
284291 strlen (confidential_addr_family ) >= WALLY_BLECH32_MAXLEN )
285292 return WALLY_EINVAL ;
286293
287- /* get v0 witness programs script */
294+ /* get witness program's script */
288295 ret = wally_addr_segwit_to_bytes (address , addr_family , 0 ,
289296 hash_bytes_p , written , & written );
290297 if (ret == WALLY_OK ) {
291- if ((written != (HASH160_LEN + 2 )) && (written != (SHA256_LEN + 2 )))
298+ if ((written != (HASH160_LEN + 2 )) && (written != (SHA256_LEN + 2 ))) {
292299 ret = WALLY_EINVAL ;
293- else {
294- /* Copy the confidentialKey / v0 witness programs */
295- memcpy (buf , pub_key , pub_key_len );
296- written -= 2 ; /* ignore witnessVersion & hashSize */
297- written += EC_PUBLIC_KEY_LEN ;
298- if (!blech32_addr_encode (result , confidential_addr_family , 0 , buf , written ))
299- return WALLY_ERROR ;
300+ goto done ;
301+ }
300302
301- * output = wally_strdup (result );
302- ret = (* output ) ? WALLY_OK : WALLY_ENOMEM ;
303+ if (!script_is_op_n (hash_bytes_p [0 ], true, & witver )) {
304+ ret = WALLY_EINVAL ;
305+ goto done ;
303306 }
307+
308+ /* Copy the confidentialKey / witness program */
309+ memcpy (buf , pub_key , pub_key_len );
310+ written -= 2 ; /* ignore witnessVersion & hashSize */
311+ written += EC_PUBLIC_KEY_LEN ;
312+ if (!blech32_addr_encode (result , confidential_addr_family , witver & 0xff , buf , written ))
313+ return WALLY_ERROR ;
314+
315+ * output = wally_strdup (result );
316+ ret = (* output ) ? WALLY_OK : WALLY_ENOMEM ;
304317 }
305318
319+ done :
306320 wally_clear (buf , sizeof (buf ));
307321 wally_clear (result , sizeof (result ));
308322 return ret ;
0 commit comments