{
 "number": 35443,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/35443",
 "title": "tests: add functional test for tr musig2 miniscript decaying multisig",
 "author": "mjdietzx",
 "author_association": "CONTRIBUTOR",
 "created_at": "2026-06-02T16:02:07Z",
 "updated_at": "2026-08-27T11:22:02Z",
 "age_days": 107,
 "draft": false,
 "labels": [
  "Tests"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "e5880944cba298c04ad5fe4acd2c6208784554cc",
 "head_ref": "test_tr_miniscript_decaying_multiscript_descriptor",
 "head_repo": "mjdietzx/bitcoin",
 "head_history": [],
 "additions": 190,
 "deletions": 0,
 "changed_files": 3,
 "commit_count": 1,
 "size_bucket": "M",
 "mergeable_state": "blocked",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "concept_ack": [
     {
      "login": "rkrux",
      "url": "https://github.com/bitcoin/bitcoin/pull/35443#pullrequestreview-4420054963"
     }
    ]
   },
   "conflicts": []
  }
 },
 "acks_parsed": {
  "rkrux": {
   "kind": "concept_ack",
   "hash": "e588094",
   "t": "2026-06-03T15:25:42Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 0,
  "stale_ack": 0,
  "concept_ack": 1,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 0,
  "changes_requested": 0,
  "distinct_reviewers": [
   "rkrux"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "blocked",
  "last_author_activity": "2026-06-03T16:57:14Z",
  "last_reviewer_activity": "2026-06-03T15:25:42Z",
  "last_reviewer": "rkrux",
  "author_silent_days": 105,
  "waiting_on_author_days": 0,
  "days_since_update": 21
 },
 "refs": {
  "mentioned": [],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [],
  "conflicts": []
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [],
 "body": "This is closely based on [test/functional/wallet_miniscript_decaying_multisig_descriptor_psbt.py](https://github.com/bitcoin/bitcoin/blob/master/test/functional/wallet_miniscript_decaying_multisig_descriptor_psbt.py) both in code and concept. It builds the same \"decaying\" multisig that starts as 4-of-4 and decays to 3-of-4, 2-of-4, and finally 1-of-4 at each future halvening block height, but as a Taproot output, combining Taproot, Miniscript, and MuSig2 in a single descriptor of the form `tr(musig(key_1,key_2,key_3,key_4),thresh(4,pk(key_1),s:pk(key_2),s:pk(key_3),s:pk(key_4),sln:after(t1),sln:after(t2),sln:after(t3)))`. While every signer is available the 4-of-4 is spent through the Taproot key path using a MuSig2 aggregate of the participants, which is the cheapest and most private spend, while the Miniscript script path is a fallback used only when a key becomes inaccessible, so a lost key never permanently strands the funds and the key path stays available even after the multisig has fully decayed. As with the `wsh` version the signers are plain single-key wallets and the multisig is watch-only, so everything needed to sign (including the MuSig2 participant pubkeys) is carried in the PSBT and signers never import the multisig descriptor. It serves as integration testing for Taproot, Miniscript, and MuSig2 descriptors working together, and like the `wsh` test is meant to be documentation as much as a functional test, so it is kept as simple and readable as possible.\n\nNote: this thresh-based design has BIP110-invalid script-path spends. `sln:after` compiles to `OP_IF` in the tapscript leaf (the key-path spend is unaffected). I implemented an alternative that avoids this by splitting the decay into separate timelocked `multi_a` tapleaves (no `OP_IF`) in [e0482ec](https://github.com/bitcoin/bitcoin/commit/e0482eca19d520ff69dcdd59c676affc5ecf7c66). It's a quick, less-thoroughly-tested implementation, but I wanted to present it in case reviewers prefer that approach.",
 "commits": [
  {
   "sha": "e5880944cba298c04ad5fe4acd2c6208784554cc",
   "date": "2026-06-02T15:52:22Z",
   "message": "tests: add functional test for tr musig2 miniscript decaying multisig"
  }
 ],
 "timeline": [
  {
   "t": "2026-06-03T15:25:42Z",
   "kind": "review",
   "who": "rkrux",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "e5880944cba298c04ad5fe4acd2c6208784554cc",
   "text": "Concept ACK e588094\n\nBased on a cursory glance, there is a lot of similarity with the other test mentioned in the PR description along with a duplicated method.\n\nConsider merging these two files into one while getting rid of the duplication?"
  },
  {
   "t": "2026-06-03T16:57:14Z",
   "kind": "comment",
   "who": "mjdietzx",
   "assoc": "CONTRIBUTOR",
   "text": "[quoted text omitted]\n\nCorrect, the two tests are (intentionally) similar. This is meant to be a \"baby step\" improving the privacy of  `wallet_miniscript_decaying_multisig_descriptor_psbt.py`\n\nSo they are generally the same aside from `_spend_keypath` and the test conditions exercising that.\n\nThat said, my preference is keeping these tests separate to prioritize them being maximally simple and easy to follow. I think the \"documentation\" value of these tests is greater than the test coverage provided. So in that spirit I intentionally duplicated some code to keep these tests elegant and straightforward incase someone references it while creating a wallet.\n\nThanks for the valid feedback, if more reviewers prefer consolidating I am open to it! These tests could be easily combined (also the OG `test/functional/wallet_multisig_descriptor_psbt.py`). But I preferred the 3 part series showing my preferred multisig in core as new technology matures: basic m-of-n => decaying miniscript => this."
  }
 ],
 "labels_log": [
  {
   "t": "2026-06-02T16:02:11Z",
   "action": "labeled",
   "label": "Tests",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 3381,
 "text_tokens_estimate": 845,
 "changed_paths": [
  "doc/descriptors.md",
  "test/functional/test_runner.py",
  "test/functional/wallet_taproot_decaying_multisig_descriptor_psbt.py"
 ],
 "files": [
  {
   "path": "doc/descriptors.md",
   "add": 13,
   "del": 0
  },
  {
   "path": "test/functional/test_runner.py",
   "add": 1,
   "del": 0
  },
  {
   "path": "test/functional/wallet_taproot_decaying_multisig_descriptor_psbt.py",
   "add": 176,
   "del": 0
  }
 ],
 "test_lines": 177,
 "git": {
  "head": "e5880944cba298c04ad5fe4acd2c6208784554cc",
  "head_matches_backup": true,
  "base": "fbe628756cc417dd4b6ccd9d3a709ca8e2f6023c",
  "commits": [
   {
    "sha": "e5880944cb",
    "subject": "tests: add functional test for tr musig2 miniscript decaying multisig",
    "files": 3,
    "add": 190,
    "del": 0
   }
  ],
  "patch_truncated": false
 },
 "input_hash": "418456dbd36dbb62",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}