Compare commits

...

5 commits

Author SHA1 Message Date
Sebastian Falbesoner
081a6f6c1f
Merge 23ee07dd0f into c5e44a0435 2025-04-29 11:51:31 +02:00
merge-script
c5e44a0435
Merge bitcoin/bitcoin#32369: test: Use the correct node for doubled keypath test
Some checks are pending
CI / macOS 14 native, arm64, fuzz (push) Waiting to run
CI / Windows native, VS 2022 (push) Waiting to run
CI / Windows native, fuzz, VS 2022 (push) Waiting to run
CI / Linux->Windows cross, no tests (push) Waiting to run
CI / Windows, test cross-built (push) Blocked by required conditions
CI / ASan + LSan + UBSan + integer, no depends, USDT (push) Waiting to run
CI / test each commit (push) Waiting to run
CI / macOS 14 native, arm64, no depends, sqlite only, gui (push) Waiting to run
32d55e28af test: Use the correct node for doubled keypath test (Ava Chow)

Pull request description:

  #29124 had a silent merge conflict with #32350 which resulted in it using the wrong node. Fix the test to use the correct v22 node.

ACKs for top commit:
  maflcko:
    lgtm ACK 32d55e28af
  rkrux:
    ACK 32d55e28af
  BrandonOdiwuor:
    Code Review ACK 32d55e28af

Tree-SHA512: 1e0231985beb382b16e1d608c874750423d0502388db0c8ad450b22d17f9d96f5e16a6b44948ebda5efc750f62b60d0de8dd20131f449427426a36caf374af92
2025-04-29 09:59:42 +01:00
Ava Chow
32d55e28af test: Use the correct node for doubled keypath test 2025-04-28 14:44:17 -07:00
Sebastian Falbesoner
23ee07dd0f test: add test for decoding PSBT with MuSig2 PSBT key types (BIP 373) 2025-04-18 23:23:03 +02:00
Sebastian Falbesoner
e5537de0ab test: add constants for MuSig2 PSBT key types (BIP 373)
Also, support serialization of lists of byte-strings as PSBTMap values,
which will be simply concatenated without any compact-size prefixes
(neither for the individual items nor for the size of the list).
2025-04-18 23:23:03 +02:00
3 changed files with 80 additions and 1 deletions

View file

@ -29,8 +29,12 @@ from test_framework.psbt import (
PSBT_IN_SHA256,
PSBT_IN_HASH160,
PSBT_IN_HASH256,
PSBT_IN_MUSIG2_PARTIAL_SIG,
PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS,
PSBT_IN_MUSIG2_PUB_NONCE,
PSBT_IN_NON_WITNESS_UTXO,
PSBT_IN_WITNESS_UTXO,
PSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS,
PSBT_OUT_TAP_TREE,
)
from test_framework.script import CScript, OP_TRUE
@ -959,6 +963,74 @@ class PSBTTest(BitcoinTestFramework):
assert hash.hex() in res_input[preimage_key]
assert_equal(res_input[preimage_key][hash.hex()], preimage.hex())
self.log.info("Test decoding PSBT with MuSig2 per-input and per-output types")
# create 2-of-2 musig2 using fake aggregate key, leaf hash, pubnonce, and partial sig
# TODO: actually implement MuSig2 aggregation (for decoding only it doesn't matter though)
_, in_pubkey1 = generate_keypair()
_, in_pubkey2 = generate_keypair()
_, in_fake_agg_pubkey = generate_keypair()
fake_leaf_hash = randbytes(32)
fake_pubnonce = randbytes(66)
fake_partialsig = randbytes(32)
tx = CTransaction()
tx.vin = [CTxIn(outpoint=COutPoint(hash=int('ee' * 32, 16), n=0), scriptSig=b"")]
tx.vout = [CTxOut(nValue=0, scriptPubKey=b"")]
psbt = PSBT()
psbt.g = PSBTMap({PSBT_GLOBAL_UNSIGNED_TX: tx.serialize()})
participant1_keydata = in_pubkey1 + in_fake_agg_pubkey + fake_leaf_hash
psbt.i = [PSBTMap({
bytes([PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS]) + in_fake_agg_pubkey: [in_pubkey1, in_pubkey2],
bytes([PSBT_IN_MUSIG2_PUB_NONCE]) + participant1_keydata: fake_pubnonce,
bytes([PSBT_IN_MUSIG2_PARTIAL_SIG]) + participant1_keydata: fake_partialsig,
})]
_, out_pubkey1 = generate_keypair()
_, out_pubkey2 = generate_keypair()
_, out_fake_agg_pubkey = generate_keypair()
psbt.o = [PSBTMap({
bytes([PSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS]) + out_fake_agg_pubkey: [out_pubkey1, out_pubkey2],
})]
res = self.nodes[0].decodepsbt(psbt.to_base64())
assert_equal(len(res["inputs"]), 1)
res_input = res["inputs"][0]
assert_equal(len(res["outputs"]), 1)
res_output = res["outputs"][0]
assert "musig2_participant_pubkeys" in res_input
in_participant_pks = res_input["musig2_participant_pubkeys"][0]
assert "aggregate_pubkey" in in_participant_pks
assert_equal(in_participant_pks["aggregate_pubkey"], in_fake_agg_pubkey.hex())
assert "participant_pubkeys" in in_participant_pks
assert_equal(in_participant_pks["participant_pubkeys"], [in_pubkey1.hex(), in_pubkey2.hex()])
assert "musig2_pubnonces" in res_input
in_pubnonce = res_input["musig2_pubnonces"][0]
assert "participant_pubkey" in in_pubnonce
assert_equal(in_pubnonce["participant_pubkey"], in_pubkey1.hex())
assert "aggregate_pubkey" in in_pubnonce
assert_equal(in_pubnonce["aggregate_pubkey"], in_fake_agg_pubkey.hex())
assert "leaf_hash" in in_pubnonce
assert_equal(in_pubnonce["leaf_hash"], fake_leaf_hash.hex())
assert "pubnonce" in in_pubnonce
assert_equal(in_pubnonce["pubnonce"], fake_pubnonce.hex())
assert "musig2_partial_sigs" in res_input
in_partialsig = res_input["musig2_partial_sigs"][0]
assert "participant_pubkey" in in_partialsig
assert_equal(in_partialsig["participant_pubkey"], in_pubkey1.hex())
assert "aggregate_pubkey" in in_pubnonce
assert_equal(in_partialsig["aggregate_pubkey"], in_fake_agg_pubkey.hex())
assert "leaf_hash" in in_partialsig
assert_equal(in_partialsig["leaf_hash"], fake_leaf_hash.hex())
assert "partial_sig" in in_partialsig
assert_equal(in_partialsig["partial_sig"], fake_partialsig.hex())
assert "musig2_participant_pubkeys" in res_output
out_participant_pks = res_output["musig2_participant_pubkeys"][0]
assert "aggregate_pubkey" in out_participant_pks
assert_equal(out_participant_pks["aggregate_pubkey"], out_fake_agg_pubkey.hex())
assert "participant_pubkeys" in out_participant_pks
assert_equal(out_participant_pks["participant_pubkeys"], [out_pubkey1.hex(), out_pubkey2.hex()])
self.log.info("Test that combining PSBTs with different transactions fails")
tx = CTransaction()
tx.vin = [CTxIn(outpoint=COutPoint(hash=int('aa' * 32, 16), n=0), scriptSig=b"")]

View file

@ -50,6 +50,9 @@ PSBT_IN_TAP_LEAF_SCRIPT = 0x15
PSBT_IN_TAP_BIP32_DERIVATION = 0x16
PSBT_IN_TAP_INTERNAL_KEY = 0x17
PSBT_IN_TAP_MERKLE_ROOT = 0x18
PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS = 0x1a
PSBT_IN_MUSIG2_PUB_NONCE = 0x1b
PSBT_IN_MUSIG2_PARTIAL_SIG = 0x1c
PSBT_IN_PROPRIETARY = 0xfc
# per-output types
@ -61,6 +64,7 @@ PSBT_OUT_SCRIPT = 0x04
PSBT_OUT_TAP_INTERNAL_KEY = 0x05
PSBT_OUT_TAP_TREE = 0x06
PSBT_OUT_TAP_BIP32_DERIVATION = 0x07
PSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS = 0x08
PSBT_OUT_PROPRIETARY = 0xfc
@ -88,6 +92,9 @@ class PSBTMap:
for k,v in self.map.items():
if isinstance(k, int) and 0 <= k and k <= 255:
k = bytes([k])
if isinstance(v, list):
assert any(type(elem) is bytes for elem in v)
v = b"".join(v) # simply concatenate the byte-strings w/o size prefixes
m += ser_compact_size(len(k)) + k
m += ser_compact_size(len(v)) + v
m += b"\x00"

View file

@ -87,7 +87,7 @@ class BackwardsCompatibilityTest(BitcoinTestFramework):
# 0.21.x and 22.x would both produce bad derivation paths when topping up an inactive hd chain
# Make sure that this is being automatically cleaned up by migration
node_master = self.nodes[1]
node_v22 = self.nodes[self.num_nodes - 5]
node_v22 = self.nodes[self.num_nodes - 3]
wallet_name = "bad_deriv_path"
node_v22.createwallet(wallet_name=wallet_name, descriptors=False)
bad_deriv_wallet = node_v22.get_wallet_rpc(wallet_name)