mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-09-12 05:32:22 +02:00
Merge bitcoin/bitcoin#35933: psbt: don't abort on invalid MuSig2 derivations
73a94b4545psbt: avoid aborting on invalid MuSig2 derivations (Lőrinc)e3d1e75a51test: characterize MuSig2 derivation aborts (Lőrinc) Pull request description: **Problem:** A PSBT may contain MuSig2 derivation metadata with a hardened child index or a path that derives to a different key. The hardened index aborts during public derivation, while the mismatched key aborts at the result assertion. `analyzepsbt`, `finalizepsbt`, and `descriptorprocesspsbt` all reach this code without a wallet. Even the read-only `analyzepsbt` can force a co-signer service to restart its node after unexpected input. **Fix:** Return failure when a MuSig2 derivation path contains a hardened child index, and skip only the current aggregate when the path derives to a different key so another matching aggregate can still be tried. This follows [#35154](https://github.com/bitcoin/bitcoin/pull/35154), with the related contributions credited in the commits. ACKs for top commit: jeanpablojp: ACK73a94b4545achow101: ACK73a94b4545andrewtoth: ACK73a94b4545Tree-SHA512: d8e28c5a4184154a4427c644ce62423cbcccdc3d82a6293f36fe99055fa04714598bc92c43b526fbcc7c99b231140669c2d0f1b853999d7dc33f949564c90504
This commit is contained in:
@@ -13,6 +13,7 @@ from test_framework.blocktools import (
|
||||
MAX_STANDARD_TX_WEIGHT,
|
||||
)
|
||||
from test_framework.descriptors import descsum_create
|
||||
from test_framework.extendedkey import hardened
|
||||
from test_framework.key import H_POINT
|
||||
from test_framework.messages import (
|
||||
COutPoint,
|
||||
@@ -40,6 +41,8 @@ from test_framework.psbt import (
|
||||
PSBT_IN_MUSIG2_PUB_NONCE,
|
||||
PSBT_IN_NON_WITNESS_UTXO,
|
||||
PSBT_IN_PROPRIETARY,
|
||||
PSBT_IN_TAP_BIP32_DERIVATION,
|
||||
PSBT_IN_TAP_INTERNAL_KEY,
|
||||
PSBT_IN_WITNESS_UTXO,
|
||||
PSBT_IN_FINAL_SCRIPTWITNESS,
|
||||
PSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS,
|
||||
@@ -47,8 +50,8 @@ from test_framework.psbt import (
|
||||
PSBT_OUT_TAP_TREE,
|
||||
PSBT_OUT_SCRIPT,
|
||||
)
|
||||
from test_framework.script import CScript, OP_TRUE, SIGHASH_ALL, SIGHASH_ANYONECANPAY
|
||||
from test_framework.script_util import MIN_STANDARD_TX_NONWITNESS_SIZE
|
||||
from test_framework.script import CScript, OP_TRUE, SIGHASH_ALL, SIGHASH_ANYONECANPAY, hash160
|
||||
from test_framework.script_util import MIN_STANDARD_TX_NONWITNESS_SIZE, output_key_to_p2tr_script
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import (
|
||||
assert_not_equal,
|
||||
@@ -302,6 +305,25 @@ class PSBTTest(BitcoinTestFramework):
|
||||
assert "participant_pubkeys" in out_participant_pks
|
||||
assert_equal(out_participant_pks["participant_pubkeys"], [out_pubkey1.hex(), out_pubkey2.hex()])
|
||||
|
||||
def test_musig2_untrusted_derivation(self):
|
||||
self.log.info("Test MuSig2 aggregate derivation from untrusted PSBT fields")
|
||||
node = self.nodes[0]
|
||||
|
||||
script_pubkey = bytes.fromhex(H_POINT)
|
||||
_, aggregate_pubkey = generate_keypair()
|
||||
_, participant_pubkey = generate_keypair()
|
||||
|
||||
# Both have a matching aggregate fingerprint but cannot derive the script pubkey: 0 derives a different key, hardened(0) cannot be derived at all
|
||||
for index in [0, hardened(0)]:
|
||||
psbt = self.create_psbt(inputs={
|
||||
PSBT_IN_WITNESS_UTXO: CTxOut(nValue=1, scriptPubKey=output_key_to_p2tr_script(script_pubkey)).serialize(),
|
||||
bytes([PSBT_IN_TAP_BIP32_DERIVATION]) + script_pubkey: ser_compact_size(0) + hash160(aggregate_pubkey)[:4] + index.to_bytes(4, "little"),
|
||||
PSBT_IN_TAP_INTERNAL_KEY: script_pubkey,
|
||||
bytes([PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS]) + aggregate_pubkey: [participant_pubkey],
|
||||
}).to_base64()
|
||||
assert_equal(node.analyzepsbt(psbt)["inputs"][0]["is_final"], False)
|
||||
assert_equal(node.finalizepsbt(psbt)["complete"], False)
|
||||
|
||||
def test_combinepsbt_preserves_proprietary_fields(self):
|
||||
self.log.info("Test that combining PSBTs preserves proprietary fields")
|
||||
|
||||
@@ -1500,6 +1522,7 @@ class PSBTTest(BitcoinTestFramework):
|
||||
self.test_psbt_roundtrip()
|
||||
self.test_psbt_version()
|
||||
self.test_psbt_with_invalid_signature()
|
||||
self.test_musig2_untrusted_derivation()
|
||||
|
||||
if __name__ == '__main__':
|
||||
PSBTTest(__file__).main()
|
||||
|
||||
Reference in New Issue
Block a user