I don't think such concrete Python code has been published elsewhere; correct me if I'm wrong. Anyways, here we go.
Let's start with some imports and two functions:
import hashlib, base58, bitcoinutils.bech32
from fastecdsa import keys, curve, ecdsa, point
curve = curve.secp256k1
def privkey_to_pubkey_hex(privkey, compressed=False):
#Accept 64 char HEX, WIF and arbitrary length integer numbers as inputs
try: #Is it WIF?
privkey_hex = base58.b58decode_check(privkey).hex()
privkey_hex = privkey_hex.replace('0x','')
if len(privkey_hex) == 68:
privkey_hex = privkey_hex[2:-2]
if len(privkey_hex) == 66:
privkey_hex = privkey_hex[2:]
except:
pass
try: #Is it HEX?
if int(str(privkey),16):
privkey_hex = privkey
privkey_hex = privkey_hex.replace('0x','')
if len(privkey_hex) == 68:
privkey_hex = privkey_hex[2:-2]
if len(privkey_hex) == 66:
privkey_hex = privkey_hex[2:]
except:
pass
try: #Is it INT?
if isinstance(privkey, int):
privkey_hex = hex(privkey)[2:].zfill(64)
except:
pass
try:
privkey_int = int(privkey_hex,16)
pub_key = keys.get_public_key(privkey_int, curve)
uncompressed_public_key = '04'+str(hex(pub_key.x)[2:]).zfill(64)+str(hex(pub_key.y)[2:]).zfill(64)
if compressed==False:
return uncompressed_public_key
else:
if int(str(pub_key.y)) % 2 == 0:
compressed_public_key = '02'
else:
compressed_public_key = '03'
compressed_public_key += str(uncompressed_public_key[2:66])
return compressed_public_key
except:
pass
def decompress_point(x, curve):
y_squared = (x**3 + curve.a * x + curve.b) % curve.p
y = pow(y_squared, (curve.p + 1) // 4, curve.p)
if y % 2 == 0:
return point.Point(x, y, curve=curve)
else:
return point.Point(x, curve.p - y, curve=curve)
And in action:
seed = '0000000000000000000000000000000000000000000000000000000000000001'
short_x = privkey_to_pubkey_hex(seed, compressed=True)[2:]
tag_hash = hashlib.sha256('TapTweak'.encode()).hexdigest()
tagged_hash = hashlib.sha256(bytes.fromhex(tag_hash + tag_hash + short_x)).hexdigest()
tagged_hash_pubx = privkey_to_pubkey_hex(tagged_hash, compressed=True)[2:]
point1 = decompress_point(int(short_x, 16), curve)
point2 = decompress_point(int(tagged_hash_pubx, 16), curve)
point_add = point1 + point2
tweaked_witness = hex(point_add.x)[2:]
print(bitcoinutils.bech32.encode('bc', 1, bytes.fromhex(tweaked_witness)))
Tweaked Taproot demystified - mission accomplished - the output is the desired Taproot public address!
bc1pmfr3p9j00pfxjh0zmgp99y8zftmd3s5pmedqhyptwy6lm87hf5sspknck9
Yay.
Thank you for all your support. This was the least user-friendly address generation code thus far