# (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