On some operating systems, Python doesn't provide the expected ripemd160
implementation anymore, so the reference implementation fails to start.
E.g. in Ubuntu 22.04:
----------------------------------------------------------------------------------------------
$ ./reference.py send_and_receive_test_vectors.json
Simple send: two inputs
Traceback (most recent call last):
File "/usr/lib/python3.10/hashlib.py", line 160, in __hash_new
return _hashlib.new(name, data, **kwargs)
ValueError: [digital envelope routines] unsupported
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/thestack/bips/bip-0352/./reference.py", line 228, in <module>
pubkey = get_pubkey_from_input(vin)
File "/home/thestack/bips/bip-0352/./reference.py", line 46, in get_pubkey_from_input
pubkey_hash = hash160(pubkey_bytes)
File "/home/thestack/bips/bip-0352/bitcoin_utils.py", line 130, in hash160
return hashlib.new("ripemd160", hashlib.sha256(s).digest()).digest()
File "/usr/lib/python3.10/hashlib.py", line 166, in __hash_new
return __get_builtin_constructor(name)(data)
File "/usr/lib/python3.10/hashlib.py", line 123, in __get_builtin_constructor
raise ValueError('unsupported hash type ' + name)
ValueError: unsupported hash type ripemd160
----------------------------------------------------------------------------------------------
Fix this by providing a manual implementation, taken from the functional test framework
of Bitcoin Core. See corresponding issue https://github.com/bitcoin/bitcoin/issues/23710 and
PR https://github.com/bitcoin/bitcoin/pull/23716
The first paragraph is taken from BIP-327, with the sentence
about MAJOR version zero removed, as it's not relevant here
(we don't track the pre-merge history).
The input data for the test vector is taken from the signet transaction
fe788cf6578d547819def43d79e6c8f0153d4885f5a343d12bd03f34507aabd6
which spends two P2WPKH inputs with negated pubkeys (x, y) and (x, -y)
from the funding transaction 3a286147b25e16ae80aff406f2673c6e565418c40f45c071245cdebc8a94174e
(see also https://github.com/bitcoin-core/secp256k1/pull/1519#issuecomment-2143167510
and the output from the script in the previous commit message).
Co-authored-by: josibake <josibake@protonmail.com>
The test vector data was generated with a Python script
(see bc15ea8d0f/contrib/silentpayments/submit_input_pubkeys_infinity_tx.py),
leading to the following output:
---------------------------------------------------------------------------------------------------------
Privkey 1: a6df6a0bb448992a301df4258e06a89fe7cf7146f59ac3bd5ff26083acb22ceb
Privkey 2: 592095f44bb766d5cfe20bda71f9575ed2df6b9fb9addc7e5fdffe0923841456
Pubkey 1: 02557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975
Pubkey 2: 03557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975
scriptPubKey 1: 00149d9e24f9fab4e35bf1a6df4b46cb533296ac0792
scriptPubKey 2: 00149860538b5575962776ed0814ae222c7d60c72d7b
Address 1: tb1qnk0zf706kn34hudxma95dj6nx2t2cpujz7j5t5
Address 2: tb1qnps98z64wktzwahdpq22ug3v04svwttm7gs8wn
-> Funding tx submitted: 3a286147b25e16ae80aff406f2673c6e565418c40f45c071245cdebc8a94174e
Taproot output address for spending tx: tb1pqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqkgkkf5
-> Spending tx submitted: fe788cf6578d547819def43d79e6c8f0153d4885f5a343d12bd03f34507aabd6
---------------------------------------------------------------------------------------------------------
For both sender and receiver, generating the input hash is currently
listed as the first step. This already involves summing up the public
keys, even though summing up key material (private keys for sender,
public keys of inputs for receiver) is then again listed explicitly
in later steps.
It seems to be more obvious and less redundant (and also hopefully less
confusing for readers) to reorder the instructions to calculate the
input_hash _after_ the key aggregation is done to reuse the result. In
case of the sender, the private key sum has to be multiplicated with G
in order to the get to the corresponding input pubkey sum.
This also corresponds to the current BIP352 implementation in the
secp256k1 library (https://github.com/bitcoin-core/secp256k1/pull/1519).
The reference implementation in Python here is adapted for the sender
side, the receiver side has already generated the input_hash after
summing up the pubkeys.
User behavior has clearly indicated a strong demand for the
resolution of human-readable names into payment instructions. This
BIP defines a protocol to do so using only the DNS, providing for
the ability to query such resolutions privately, while utilizing
DNSSEC to provide compact and simple to verify proofs of mappings.