{
 "number": 36442,
 "input_hash": "60931fd990203586",
 "model": "ledger",
 "prompt_hash": null,
 "created": "2026-10-24T01:18:07+00:00",
 "result": {
  "summary": "Refactors output descriptor parsing and BIP32 keypath handling so multipath descriptors are represented as a single `Descriptor` object rather than immediately expanding into a vector of separate descriptors. Replaces raw integer derivation vectors with a dedicated `KeyPath` class composed of `KeyPathElement` objects that preserve multipath branches and the original hardening character. Updates `Parse` to return a single `std::unique_ptr<Descriptor>`, providing `GetMultipathExpansion()` and `IsMultipath()` for subsystems that require individual paths.",
  "problem": "Multipath descriptor strings were treated purely as syntactic sugar and discarded during parsing, splitting into multiple distinct descriptors. As a result, the original multipath string could not be preserved, round-tripped, or returned by RPCs like `getdescriptorinfo`.",
  "card": "Represents multipath descriptors natively in a single Descriptor object rather than immediately expanding them during parsing. Previously, multipath syntax was discarded upon parsing as syntactic sugar, which prevented RPCs like getdescriptorinfo from returning or round-tripping the original multipath descriptor string. Derivation path parsing is refactored into KeyPath and KeyPathElement classes to retain multipath steps and hardening formats, while callers requiring individual paths use GetMultipathExpansion. This change enables downstream work in #36443.",
  "evidence": [
   "PR description: 'Currently, multipath descriptor strings treat the multipath specifiers as syntactic sugar. Once we finish parsing such a string, the multipath elements are lost as the result is the multiple distinct descriptors that the multipath is a shorthand for. This means that we are unable to return the multipath string for such descriptors.'",
   "test/functional/rpc_getdescriptorinfo.py: asserts that `getdescriptorinfo(desc)[\"descriptor\"]` now returns the unexpanded multipath descriptor rather than `descsum_create(expanded_descs[0])`."
  ],
  "scope_notes": "A wide-reaching refactor that replaces `std::vector<uint32_t>` derivation paths across wallet, descriptor, signing, and BIP32 utility code with custom `KeyPath` and `KeyPathElement` abstractions, affecting call sites across the codebase.",
  "changed_since_previous": "Rebased or updated since the previous version with no major architectural changes.",
  "thread": {
   "last_event_at": "2026-10-23T04:50:03Z",
   "events": 4,
   "head_sha": "74915efa6e19b1d7b51ba0842726904e4f46e399",
   "schema_floor": 2,
   "schema": 2
  },
  "waiting_on": [
   {
    "at": "2026-10-23",
    "id": "r:5624021942",
    "on": "author",
    "url": "https://github.com/bitcoin/bitcoin/pull/36442#pullrequestreview-5624021942",
    "what": "address the migratewallet hardening bug reported by fametrano"
   }
  ],
  "risk": {
   "level": "high",
   "touches": [
    "wallet",
    "rpc_api"
   ],
   "why": "Mistakes in derivation path parsing or child key derivation could cause wallets to generate wrong addresses, misplace keys, or fail to find expected transaction outputs."
  },
  "discussion": {
   "author_status": "last statement processed 2026-10-23",
   "open_concerns": [
    "fametrano: migratewallet turns every step of an imported key's origin path into a hardened step because SingleKeyPathElement::Unserialize assigns a bool to std::optional<char> m_hardened",
    "fametrano: Consider adding a release note since descriptors mixing h and ' now print, with their checksum, differently from v31.1",
    "fametrano: Only engage m_hardened for a hardened step so that unhardened steps read from disk stay unhardened"
   ],
   "resolved_concerns": []
  },
  "reviewability": {
   "state": "Paused",
   "label": "Waiting on author",
   "reason": "Open objections from fametrano with no author reply for 9 days; review would repeat what has been asked."
  },
  "agreement": {
   "state": "Blocked",
   "summary": "Blocked: objection that needs a change, nobody has replied (fametrano)",
   "reason": "fametrano reported a regression in SingleKeyPathElement::Unserialize causing migratewallet to mark all derivation steps hardened, offered an inline fix, and suggested a release note for descriptor marker display changes.",
   "evidence": [
    "fametrano (objection, correctness, must be changed, open): migratewallet turns every step of an imported key's origin path into a hardened step because SingleKeyPathElement::Unserialize assigns a bool to std::optional<char> m_hardened",
    "fametrano (suggestion, maintenance, must be answered, open): Consider adding a release note since descriptors mixing h and ' now print, with their checksum, differently from v31.1",
    "fametrano (suggestion, correctness, must be changed, open): Only engage m_hardened for a hardened step so that unhardened steps read from disk stay unhardened",
    "w0xlt: Concept ACK",
    "Sjors: Concept ACK"
   ],
   "objections": [
    {
     "reviewer": "fametrano",
     "association": "CONTRIBUTOR",
     "type": "objection",
     "kind": "correctness",
     "harm": "migratewallet turns every step of an imported key's origin path into a hardened step because SingleKeyPathElement::Unserialize assigns a bool to std::optional<char> m_hardened",
     "request": "",
     "question": "",
     "text": "migratewallet turns every step of an imported key's origin path into a hardened step because SingleKeyPathElement::Unserialize assigns a bool to std::optional<char> m_hardened",
     "clears_with": "change",
     "blocking": true,
     "status": "open",
     "status_note": "",
     "cleared": false,
     "author_replied": false,
     "others_replied": false,
     "fix_pushed": false,
     "replies": [],
     "evidence": "2026-10-23: 'On this head, `migratewallet` turns every step of an imported key's origin path into a hardened step.'",
     "url": "https://github.com/bitcoin/bitcoin/pull/36442#pullrequestreview-5624021942",
     "id": "r:5624021942",
     "at": "2026-10-23",
     "status_at": null,
     "status_by": null,
     "resolution_evidence": "",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "fametrano",
     "association": "CONTRIBUTOR",
     "type": "suggestion",
     "kind": "maintenance",
     "harm": "",
     "request": "Consider adding a release note since descriptors mixing h and ' now print, with their checksum, differently from v31.1",
     "question": "",
     "text": "Consider adding a release note since descriptors mixing h and ' now print, with their checksum, differently from v31.1",
     "clears_with": "answer",
     "blocking": false,
     "status": "open",
     "status_note": "",
     "cleared": false,
     "author_replied": false,
     "others_replied": false,
     "fix_pushed": false,
     "replies": [],
     "evidence": "2026-10-23: 'A descriptor mixing `h` and `'` thus prints, with its checksum, differently from v31.1, which may deserve a release note.'",
     "url": "https://github.com/bitcoin/bitcoin/pull/36442#pullrequestreview-5624021942",
     "id": "r:5624021942#2",
     "at": "2026-10-23",
     "status_at": null,
     "status_by": null,
     "resolution_evidence": "",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "fametrano",
     "association": "CONTRIBUTOR",
     "type": "suggestion",
     "kind": "correctness",
     "harm": "",
     "request": "Only engage m_hardened for a hardened step so that unhardened steps read from disk stay unhardened",
     "question": "",
     "text": "Only engage m_hardened for a hardened step so that unhardened steps read from disk stay unhardened",
     "clears_with": "change",
     "blocking": true,
     "status": "open",
     "status_note": "",
     "cleared": false,
     "author_replied": false,
     "others_replied": false,
     "fix_pushed": false,
     "replies": [],
     "evidence": "2026-10-23: 'Engaged only for a hardened step, so an unhardened step read from disk stays unhardened:'",
     "url": "https://github.com/bitcoin/bitcoin/pull/36442#discussion_r4356192920",
     "id": "rc:4356192920",
     "at": "2026-10-23",
     "status_at": null,
     "status_by": null,
     "resolution_evidence": "",
     "pin": null,
     "from_schema": 2
    }
   ],
   "support": [
    {
     "reviewer": "w0xlt",
     "reason": "",
     "substantive": false,
     "verdict": "Concept ACK",
     "id": "c:6066053885",
     "url": "https://github.com/bitcoin/bitcoin/pull/36442#issuecomment-6066053885",
     "at": "2026-10-08",
     "association": "CONTRIBUTOR",
     "evidence": "none",
     "areas": []
    },
    {
     "reviewer": "Sjors",
     "reason": "",
     "substantive": false,
     "verdict": "Concept ACK",
     "id": "c:6307917577",
     "url": "https://github.com/bitcoin/bitcoin/pull/36442#issuecomment-6307917577",
     "at": "2026-10-21",
     "association": "MEMBER",
     "evidence": "none",
     "areas": []
    }
   ],
   "participants": [
    {
     "login": "w0xlt",
     "stance": "support",
     "note": "Concept ACK",
     "association": "CONTRIBUTOR",
     "comments": 1,
     "first": "2026-10-08",
     "last": "2026-10-08"
    },
    {
     "login": "Sjors",
     "stance": "support",
     "note": "Concept ACK",
     "association": "MEMBER",
     "comments": 1,
     "first": "2026-10-21",
     "last": "2026-10-21"
    },
    {
     "login": "fametrano",
     "stance": "objection",
     "note": "reported migratewallet hardening regression and suggested a release note",
     "association": "CONTRIBUTOR",
     "comments": 2,
     "first": "2026-10-23",
     "last": "2026-10-23"
    }
   ],
   "derivation": "objection that needs a change, nobody has replied (fametrano)",
   "model_state": null,
   "corrections": [],
   "notes": "fametrano reported a regression in SingleKeyPathElement::Unserialize causing migratewallet to mark all derivation steps hardened, offered an inline fix, and suggested a release note for descriptor marker display changes."
  },
  "dependencies": {
   "depends_on": [],
   "enables": [
    "#36443"
   ]
  },
  "categories": [
   {
    "name": "mining",
    "member": false,
    "evidence": "Touches src/rpc/mining.cpp only for a mechanical type update to derivation paths.",
    "band": "Unranked",
    "reason_tag": "cleanup",
    "score": 0.0,
    "factors": {
     "bug_severity": 0,
     "leverage": 2,
     "performance": 0,
     "security_stability": 0,
     "user_value": 2
    },
    "rationale": "Mechanical call-site adjustment to derivation path types does not affect mining logic or template generation."
   },
   {
    "name": "rpc",
    "member": false,
    "evidence": "Changes getdescriptorinfo output in src/rpc/output_script.cpp as a direct result of descriptor object changes.",
    "band": "Unranked",
    "reason_tag": "cleanup",
    "score": 0.0,
    "factors": {
     "bug_severity": 0,
     "leverage": 2,
     "performance": 0,
     "security_stability": 0,
     "user_value": 2
    },
    "rationale": "The change to getdescriptorinfo output is the behavior of the underlying descriptor engine exposed via RPC rather than an RPC framework change."
   },
   {
    "name": "tests",
    "member": false,
    "evidence": "Touches test and benchmark files only to update them for descriptor and BIP32 derivation path API changes.",
    "band": "Unranked",
    "reason_tag": "cleanup",
    "score": 0.0,
    "factors": {
     "bug_severity": 0,
     "leverage": 2,
     "performance": 0,
     "security_stability": 0,
     "user_value": 2
    },
    "rationale": "Edits to fuzz tests, unit tests, and benchmarks merely update test cases to follow the modified descriptor interfaces."
   },
   {
    "name": "utils",
    "member": true,
    "evidence": "Substantially refactors src/util/bip32.cpp and src/util/bip32.h (+261/-38) to introduce structured KeyPath and KeyPathElement primitives.",
    "band": "P3",
    "reason_tag": "cleanup",
    "score": 0.35,
    "factors": {
     "bug_severity": 0,
     "leverage": 2,
     "performance": 0,
     "security_stability": 0,
     "user_value": 2
    },
    "rationale": "Replaces raw vector<uint32_t> derivation paths with structured KeyPath abstractions in shared BIP32 utilities. This improves type safety and derivation path parsing across consumers, though the primary motivation is descriptor-layer functionality."
   },
   {
    "name": "wallet",
    "member": true,
    "evidence": "Has the Descriptors label, heavily alters src/script/descriptor.cpp, and updates wallet storage and scriptpubkeyman handling for multipath descriptors.",
    "band": "P2",
    "reason_tag": "new feature",
    "score": 0.65,
    "factors": {
     "bug_severity": 0,
     "leverage": 2,
     "performance": 0,
     "security_stability": 0,
     "user_value": 2
    },
    "rationale": "Preserves multipath descriptor strings instead of prematurely expanding and discarding them during parsing. As stated in the description, 'Once we finish parsing such a string, the multipath elements are lost... This means that we are unable to return the multipath string for such descriptors'; representing them in a single object resolves this limitation and unblocks follow-on work like #36443."
   }
  ],
  "confidence": "high",
  "uncertainties": [],
  "needs": []
 },
 "cost_usd": 0.0,
 "source": {
  "record": "2026-10-24T01:18:07+00:00",
  "code": "2026-10-09T01:22:03+00:00",
  "judgments": 5
 }
}