Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add descriptors utils * Pre-commit fixes * Sourcery suggestion
- Loading branch information
1 parent
9670368
commit dc546f0
Showing
4 changed files
with
182 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
#!/usr/bin/env python3 | ||
|
||
# Copyright (C) 2017-2022 The btclib developers | ||
# | ||
# This file is part of btclib. It is subject to the license terms in the | ||
# LICENSE file found in the top-level directory of this distribution. | ||
# | ||
# No part of btclib including this file, may be copied, modified, propagated, | ||
# or distributed except according to the terms contained in the LICENSE file. | ||
"""Descriptors util functions. | ||
BIP 380: https://github.com/bitcoin/bips/blob/master/bip-0380.mediawiki | ||
""" | ||
|
||
from btclib.exceptions import BTClibValueError | ||
|
||
INPUT_CHARSET = "0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\"\\ " | ||
CHECKSUM_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" | ||
GENERATOR = [0xF5DEE51989, 0xA9FDCA3312, 0x1BAB10E32D, 0x3706B1677A, 0x644D626FFD] | ||
|
||
|
||
def __descsum_polymod(symbols): | ||
chk = 1 | ||
for value in symbols: | ||
top = chk >> 35 | ||
chk = (chk & 0x7FFFFFFFF) << 5 ^ value | ||
for i in range(5): | ||
chk ^= GENERATOR[i] if ((top >> i) & 1) else 0 | ||
return chk | ||
|
||
|
||
def __descsum_expand(descriptor_string: str): | ||
"""Perform the character to symbol expansion.""" | ||
groups = [] | ||
symbols = [] | ||
for char in descriptor_string: | ||
if char not in INPUT_CHARSET: | ||
raise BTClibValueError() | ||
index = INPUT_CHARSET.find(char) | ||
symbols.append(index & 31) | ||
groups.append(index >> 5) | ||
if len(groups) == 3: | ||
symbols.append(groups[0] * 9 + groups[1] * 3 + groups[2]) | ||
groups = [] | ||
if len(groups) == 1: | ||
symbols.append(groups[0]) | ||
elif len(groups) == 2: | ||
symbols.append(groups[0] * 3 + groups[1]) | ||
return symbols | ||
|
||
|
||
def descriptor_checksum(descriptor: str) -> str: | ||
"""Compute the descriptor checksum.""" | ||
symbols = __descsum_expand(descriptor) + [0, 0, 0, 0, 0, 0, 0, 0] | ||
checksum = __descsum_polymod(symbols) ^ 1 | ||
return "".join(CHECKSUM_CHARSET[(checksum >> (5 * (7 - i))) & 31] for i in range(8)) | ||
|
||
|
||
def descriptor_from_address(address: str) -> str: | ||
descriptor = f"addr({address})" | ||
return f"{descriptor}#{descriptor_checksum(descriptor)}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
[ | ||
{ | ||
"desc": "pk(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)", | ||
"checksum": "gn28ywm7" | ||
}, | ||
{ | ||
"desc": "pkh(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5)", | ||
"checksum": "8fhd9pwu" | ||
}, | ||
{ | ||
"desc": "wpkh(02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9)", | ||
"checksum": "8zl0zxma" | ||
}, | ||
{ | ||
"desc": "sh(wpkh(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", | ||
"checksum": "qkrrc7je" | ||
}, | ||
{ | ||
"desc": "combo(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)", | ||
"checksum": "lq9sf04s" | ||
}, | ||
{ | ||
"desc": "sh(wsh(pkh(02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13)))", | ||
"checksum": "2wtr0ej5" | ||
}, | ||
{ | ||
"desc": "multi(1,022f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4,025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc)", | ||
"checksum": "hzhjw406" | ||
}, | ||
{ | ||
"desc": "sh(multi(2,022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01,03acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe))", | ||
"checksum": "y9zthqta" | ||
}, | ||
{ | ||
"desc": "sh(sortedmulti(2,03acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe,022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01))", | ||
"checksum": "qwx6n9lh" | ||
}, | ||
{ | ||
"desc": "wsh(multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a))", | ||
"checksum": "en3tu306" | ||
}, | ||
{ | ||
"desc": "sh(wsh(multi(1,03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8,03499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4,02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e)))", | ||
"checksum": "ks05yr6p" | ||
}, | ||
{ | ||
"desc": "pk(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8)", | ||
"checksum": "axav5m0j" | ||
}, | ||
{ | ||
"desc": "pkh(xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw/1/2)", | ||
"checksum": "kczqajcv" | ||
}, | ||
{ | ||
"desc": "pkh([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*)", | ||
"checksum": "ml40v0wf" | ||
}, | ||
{ | ||
"desc": "wsh(multi(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*))", | ||
"checksum": "t2zpj2eu" | ||
}, | ||
{ | ||
"desc": "wsh(sortedmulti(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*))", | ||
"checksum": "v66cvalc" | ||
}, | ||
{ | ||
"desc": "tr(c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5,{pk(fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556),pk(e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13)})", | ||
"checksum": "2rqrdjrh" | ||
}, | ||
{ | ||
"desc": "tr(c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5,sortedmulti_a(2,2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4,5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc))", | ||
"checksum": "tp09wjyq" | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#!/usr/bin/env python3 | ||
|
||
# Copyright (C) 2017-2022 The btclib developers | ||
# | ||
# This file is part of btclib. It is subject to the license terms in the | ||
# LICENSE file found in the top-level directory of this distribution. | ||
# | ||
# No part of btclib including this file, may be copied, modified, propagated, | ||
# or distributed except according to the terms contained in the LICENSE file. | ||
"""Tests for the `btclib.descriptors` module.""" | ||
|
||
import json | ||
from pathlib import Path | ||
|
||
import pytest | ||
|
||
from btclib.descriptors import ( | ||
__descsum_expand, | ||
descriptor_checksum, | ||
descriptor_from_address, | ||
) | ||
from btclib.exceptions import BTClibValueError | ||
|
||
|
||
# descriptors taken from https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md | ||
# checksum calculated using https://docs.rs/bdk/latest/bdk/descriptor/checksum/fn.get_checksum.html | ||
def test_checksum(): | ||
filename = Path(__file__).parent / "_data" / "descriptor_checksums.json" | ||
with open(filename, encoding="utf-8") as file: | ||
data = json.load(file) | ||
|
||
for descriptor_data in data: | ||
descriptor = descriptor_data["desc"] | ||
checksum = descriptor_data["checksum"] | ||
assert descriptor_checksum(descriptor) == checksum | ||
|
||
|
||
def test_invalid_charset(): | ||
with pytest.raises(BTClibValueError): | ||
__descsum_expand("è") | ||
|
||
|
||
def test_addr(): | ||
address = "bc1qnehtvnd4fedkwjq6axfgsrxgllwne3k58rhdh0" | ||
descriptor = "addr(bc1qnehtvnd4fedkwjq6axfgsrxgllwne3k58rhdh0)#s2y3vepm" | ||
assert descriptor_from_address(address) == descriptor |