-
Notifications
You must be signed in to change notification settings - Fork 176
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Basic output descriptor functions (generate only)
- Loading branch information
Showing
3 changed files
with
110 additions
and
0 deletions.
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,85 @@ | ||
|
||
# Descriptor checksum calculation code taken from | ||
# https://github.com/bitcoin-core/HWI/blob/master/hwilib/descriptor.py | ||
|
||
def poly_mod(c: int, val: int) -> int: | ||
""" | ||
:meta private: | ||
Function to compute modulo over the polynomial used for descriptor checksums | ||
From: https://github.com/bitcoin/bitcoin/blob/master/src/script/descriptor.cpp | ||
""" | ||
c0 = c >> 35 | ||
c = ((c & 0x7ffffffff) << 5) ^ val | ||
if (c0 & 1): | ||
c ^= 0xf5dee51989 | ||
if (c0 & 2): | ||
c ^= 0xa9fdca3312 | ||
if (c0 & 4): | ||
c ^= 0x1bab10e32d | ||
if (c0 & 8): | ||
c ^= 0x3706b1677a | ||
if (c0 & 16): | ||
c ^= 0x644d626ffd | ||
return c | ||
|
||
|
||
def descriptor_checksum(desc: str) -> str: | ||
""" | ||
Compute the checksum for a descriptor | ||
:param desc: The descriptor string to compute a checksum for | ||
:return: A checksum | ||
""" | ||
INPUT_CHARSET = "0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\"\\ " | ||
CHECKSUM_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" | ||
|
||
c = 1 | ||
cls = 0 | ||
clscount = 0 | ||
for ch in desc: | ||
pos = INPUT_CHARSET.find(ch) | ||
if pos == -1: | ||
return "" | ||
c = poly_mod(c, pos & 31) | ||
cls = cls * 3 + (pos >> 5) | ||
clscount += 1 | ||
if clscount == 3: | ||
c = poly_mod(c, cls) | ||
cls = 0 | ||
clscount = 0 | ||
if clscount > 0: | ||
c = poly_mod(c, cls) | ||
for j in range(0, 8): | ||
c = poly_mod(c, 0) | ||
c ^= 1 | ||
|
||
ret = [''] * 8 | ||
for j in range(0, 8): | ||
ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31] | ||
return ''.join(ret) | ||
|
||
|
||
def add_checksum(desc: str) -> str: | ||
""" | ||
Compute and attach the checksum for a descriptor | ||
:param desc: The descriptor string to add a checksum to | ||
:return: Descriptor with checksum | ||
""" | ||
return desc + "#" + descriptor_checksum(desc) | ||
|
||
|
||
def get_address_descriptor(address: str) -> str: | ||
return add_checksum("addr({})".format(address)) | ||
|
||
|
||
def get_xpub_descriptor(xpub_key: str, address_type: str) -> str: | ||
if address_type == "p2pkh": | ||
function = "pkh" | ||
elif address_type == "p2sh-p2wpkh" or address_type == "p2wpkh": | ||
function = "wpkh" | ||
else: | ||
raise Exception("Unsupported address type {}".format(address_type)) | ||
descriptor = "{}({}/*)".format(function, xpub_key) | ||
if address_type == "p2sh-p2wpkh": | ||
descriptor = "sh({})".format(descriptor) | ||
return add_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,23 @@ | ||
import jmbitcoin as btc | ||
|
||
|
||
def test_address_descriptors(): | ||
assert(btc.get_address_descriptor("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i") == | ||
"addr(1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i)#ns3f5w84") | ||
assert(btc.get_address_descriptor("3CMNFxN1oHBc4R1EpboAL5yzHGgE611Xou") == | ||
"addr(3CMNFxN1oHBc4R1EpboAL5yzHGgE611Xou)#swk5gt6w") | ||
assert(btc.get_address_descriptor("bc1qt493axn3wl4gzjxvfg03vkacre0m6f2gzfhv5t") == | ||
"addr(bc1qt493axn3wl4gzjxvfg03vkacre0m6f2gzfhv5t)#q8mdrmlw") | ||
|
||
|
||
def test_xpub_descriptors(): | ||
assert(btc.get_xpub_descriptor( | ||
"xpub6CMAJ67vZWVXuzjzYXUoJgWrmuvFRiqiUG4dwoXNFmJtpTH3WgviANNxGyZYo27zxbMuqhDDym6fnBxmGaYoxr6LHgNDo1eEghkXHTX4Jnx", "p2pkh") == | ||
"pkh(xpub6CMAJ67vZWVXuzjzYXUoJgWrmuvFRiqiUG4dwoXNFmJtpTH3WgviANNxGyZYo27zxbMuqhDDym6fnBxmGaYoxr6LHgNDo1eEghkXHTX4Jnx/*)#flej8438") | ||
assert(btc.get_xpub_descriptor( | ||
"xpub6CMAJ67vZWVXuzjzYXUoJgWrmuvFRiqiUG4dwoXNFmJtpTH3WgviANNxGyZYo27zxbMuqhDDym6fnBxmGaYoxr6LHgNDo1eEghkXHTX4Jnx", "p2sh-p2wpkh") == | ||
"sh(wpkh(xpub6CMAJ67vZWVXuzjzYXUoJgWrmuvFRiqiUG4dwoXNFmJtpTH3WgviANNxGyZYo27zxbMuqhDDym6fnBxmGaYoxr6LHgNDo1eEghkXHTX4Jnx/*))#f2940w8j") | ||
assert(btc.get_xpub_descriptor( | ||
"xpub6CMAJ67vZWVXuzjzYXUoJgWrmuvFRiqiUG4dwoXNFmJtpTH3WgviANNxGyZYo27zxbMuqhDDym6fnBxmGaYoxr6LHgNDo1eEghkXHTX4Jnx", "p2wpkh") == | ||
"wpkh(xpub6CMAJ67vZWVXuzjzYXUoJgWrmuvFRiqiUG4dwoXNFmJtpTH3WgviANNxGyZYo27zxbMuqhDDym6fnBxmGaYoxr6LHgNDo1eEghkXHTX4Jnx/*)#keekqdjc") | ||
|