60 lines
1.4 KiB
Python
60 lines
1.4 KiB
Python
# (c) Copyright 2018 by Coinkite Inc. This file is covered by license found in COPYING-CC.
|
|
#
|
|
# descriptor.py - Bitcoin Core's descriptors and their specialized checksums.
|
|
#
|
|
# Based on: https://github.com/bitcoin/bitcoin/blob/master/src/script/descriptor.cpp
|
|
#
|
|
|
|
def polymod(c, val):
|
|
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):
|
|
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:
|
|
raise ValueError(ch)
|
|
|
|
c = polymod(c, pos & 31)
|
|
cls = cls * 3 + (pos >> 5)
|
|
clscount += 1
|
|
if clscount == 3:
|
|
c = polymod(c, cls)
|
|
cls = 0
|
|
clscount = 0
|
|
|
|
if clscount > 0:
|
|
c = polymod(c, cls)
|
|
for j in range(0, 8):
|
|
c = polymod(c, 0)
|
|
c ^= 1
|
|
|
|
rv = ''
|
|
for j in range(0, 8):
|
|
rv += CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31]
|
|
|
|
return rv
|
|
|
|
def append_checksum(desc):
|
|
return desc + "#" + descriptor_checksum(desc)
|
|
|
|
# EOF
|