[Addition, the problem was solved
down here]
Let's begin with this private key
0000000000000000000000000000000000000000000000000000000000000001
Using any good old tool, bitcoinutils included, it gives us
Private key compressed (WIF): KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn
Public key compressed (HEX): 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
HASH160 uncompressed: 91b24bf9f5288532960ac687abb035127b1d28a5
HASH160 compressed: 751e76e8199196d454941c45d1b3a323f1433bd6
Legacy uncompressed public address (P2PKH): 1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm
Legacy compressed public address (P2PKH): 1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH
Nested segwit public address (P2SH-P2WPKH): 3JvL6Ymt8MVWiCNHC7oWU6nLeHNJKLZGLN
Native segwit public address (P2WPKH): bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4
I won't go into legacy or nested segwit here, but I would like to mention how we easily derive the native segwit public address using the HASH160 compressed
bitcoinutils.bech32.encode('bc',0,bytes.fromhex('751e76e8199196d454941c45d1b3a323f1433bd6'))
#bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4
(Likewise, we can produce the segwit bech32 (P2WSH) address by using the single SHA256 of the compressed public key to get bc1qpac4ht6afshdx2tctnhjnetz7u6g3j9zhwwmc4cqkdsa2jumq42qd3drf7; another thread.)
However, here is where I need your help.
I know that the P2TR address corresponding to this private key and its witness program are
Tweaked Taproot public address (P2TR): bc1pmfr3p9j00pfxjh0zmgp99y8zftmd3s5pmedqhyptwy6lm87hf5sspknck9
Witness program (HEX): da4710964f7852695de2da025290e24af6d8c281de5a0b902b7135fd9fd74d21
since I can quickly arrive at them using
bitcoinutilsI can furthermore reproduce and verify it with:
bitcoinutils.bech32.encode('bc',1,bytes.fromhex('da4710964f7852695de2da025290e24af6d8c281de5a0b902b7135fd9fd74d21'))
#bc1pmfr3p9j00pfxjh0zmgp99y8zftmd3s5pmedqhyptwy6lm87hf5sspknck9
However, I fail to reverse how bitcoilutils does it. Specifically, this function from
here that generates the tweaked public key...
def tagged_hash(data: bytes, tag: str) -> bytes:
"""
Tagged hashes ensure that hashes used in one context can not be used in another.
It is used extensively in Taproot
A tagged hash is: SHA256( SHA256("TapTweak") ||
SHA256("TapTweak") ||
data
)
"""
tag_digest = hashlib.sha256(tag.encode()).digest()
return hashlib.sha256(tag_digest + tag_digest + data).digest()
... gives me a headache.
I don't see it. How do you go from the 32-byte x-only public address to that witness program?
In other words, how do I reproduce this transformation in Python (without relying on bitcoinutils as a mystery box library)?
Input: 79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
to
Output: da4710964f7852695de2da025290e24af6d8c281de5a0b902b7135fd9fd74d21
Need your help! I'm not sure what the library uses as its standard "TapTweak", and I get confused by bitcoinutil's nested (pun intended) code.
How do we use hashlib only and arrive at the same tweaked witness program, and thus the identical P2TR public address? I am very well aware you are allowed to use whatever as "TapTweak". Can we, however, simply reproduce the "library recipe"? What is its standard "TapTweak," and how to arrive at this public address, given the data above, using simple Python?
Many thanks.