{
 "number": 36091,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/36091",
 "title": "test: Add debug output to common tested types",
 "author": "rustaceanrob",
 "author_association": "MEMBER",
 "created_at": "2026-08-26T11:54:11Z",
 "updated_at": "2026-09-16T13:38:04Z",
 "age_days": 22,
 "draft": false,
 "labels": [
  "Tests"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "e239d936cf0f294760e26c4824c022c0b66d8036",
 "head_ref": "26-8-25-display",
 "head_repo": "rustaceanrob/bitcoin",
 "head_history": [
  {
   "t": "2026-08-30T09:17:53Z",
   "sha": "d550f19567616e103d099a29871cfb9c228dee18"
  },
  {
   "t": "2026-08-31T11:02:25Z",
   "sha": "f9273c8c6d519669d2756a9e1f5f8efd61825a83"
  },
  {
   "t": "2026-09-01T15:23:12Z",
   "sha": "7efdb17af6a3d8fbcea8a4120d26bfc428cee2b6"
  },
  {
   "t": "2026-09-01T16:46:56Z",
   "sha": "7cc37297cf64fd9e0f81664be0eda1e3b573a018"
  },
  {
   "t": "2026-09-01T21:48:11Z",
   "sha": "cb3613294fd4dead87067fae97021f20b0a4aff8"
  },
  {
   "t": "2026-09-02T14:39:22Z",
   "sha": "056bd2582bc96f1fc2b47933badcd4fe85832c3c"
  },
  {
   "t": "2026-09-08T09:17:59Z",
   "sha": "71cef456b6b7f23e55d23be02145ec33c0347132"
  },
  {
   "t": "2026-09-08T09:35:20Z",
   "sha": "0560c013476708771cf9141fda54410cbee07645"
  },
  {
   "t": "2026-09-08T13:31:25Z",
   "sha": "387e443275587a46c25f21ed5e05e02439140a5a"
  },
  {
   "t": "2026-09-15T09:16:33Z",
   "sha": "bd0b35aae17674025e0fd12ae5049a2f74e2687f"
  },
  {
   "t": "2026-09-15T09:26:36Z",
   "sha": "fc42f878cb578f9d91d6b11e8dd6fe2057a54fbc"
  },
  {
   "t": "2026-09-16T09:46:26Z",
   "sha": "e239d936cf0f294760e26c4824c022c0b66d8036"
  }
 ],
 "additions": 394,
 "deletions": 166,
 "changed_files": 18,
 "commit_count": 2,
 "size_bucket": "L",
 "mergeable_state": "clean",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "concept_ack": [
     {
      "login": "sedited",
      "url": "https://github.com/bitcoin/bitcoin/pull/36091#issuecomment-5425021157"
     },
     {
      "login": "brunoerg",
      "url": "https://github.com/bitcoin/bitcoin/pull/36091#issuecomment-5425787470"
     }
    ],
    "stale_ack": [
     {
      "login": "jeanpablojp",
      "url": "https://github.com/bitcoin/bitcoin/pull/36091#issuecomment-5588206021"
     },
     {
      "login": "ismaelsadeeq",
      "url": "https://github.com/bitcoin/bitcoin/pull/36091#issuecomment-5683024597"
     }
    ]
   },
   "conflicts": [
    {
     "number": 36182,
     "title": "fees: return `block_policy` fee rate estimate when `mempool_policy` is not ready",
     "author": "ismaelsadeeq"
    },
    {
     "number": 35713,
     "title": "Remove boost as a unit test runner",
     "author": "rustaceanrob"
    },
    {
     "number": 35581,
     "title": "node: add block template manager and track waitNext fee inflow",
     "author": "ismaelsadeeq"
    },
    {
     "number": 35511,
     "title": "RFC: consensus: Make `CAmount` a class",
     "author": "hodlinator"
    },
    {
     "number": 35139,
     "title": "test: Add thread-safe fast-failing test macros",
     "author": "maflcko"
    },
    {
     "number": 35003,
     "title": "validation: improve block data I/O error handling in P2P paths",
     "author": "furszy"
    }
   ]
  }
 },
 "acks_parsed": {
  "sedited": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-08-26T12:07:02Z",
   "stale": false
  },
  "brunoerg": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-08-26T13:10:10Z",
   "stale": false
  },
  "jeanpablojp": {
   "kind": "ack",
   "hash": "387e443275587a46c25f21ed5e05e02439140a5a",
   "t": "2026-09-08T16:08:54Z",
   "stale": true
  },
  "ismaelsadeeq": {
   "kind": "ack",
   "hash": "fc42f878cb578f9d91d6b11e8dd6fe2057a54fbc",
   "t": "2026-09-15T15:27:46Z",
   "stale": true
  }
 },
 "acks_tally": {
  "ack": 0,
  "stale_ack": 2,
  "concept_ack": 2,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 1,
  "changes_requested": 0,
  "distinct_reviewers": [
   "brunoerg",
   "ismaelsadeeq",
   "jeanpablojp",
   "maflcko",
   "purpleKarrot",
   "sedited"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "clean",
  "last_author_activity": "2026-09-16T09:58:40Z",
  "last_reviewer_activity": "2026-09-15T15:27:46Z",
  "last_reviewer": "ismaelsadeeq",
  "author_silent_days": 1,
  "waiting_on_author_days": 0,
  "days_since_update": 1
 },
 "refs": {
  "mentioned": [
   35713
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 35713,
    "type": "pull",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "Remove boost as a unit test runner"
   }
  ],
  "conflicts": [
   36182,
   35713,
   35581,
   35511,
   35139,
   35003
  ]
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "src/test/bip32_tests.cpp",
  "src/test/script_tests.cpp",
  "src/test/util/common.cpp",
  "src/test/util/common.h",
  "src/test/util/display.h"
 ],
 "body": "If the `<<` operator exists, boost can use this as a debug output when a check fails (besides `BOOST_CHECK`). This adds `<<` for types commonly used across the unit tests that do not yet have a display output. Each callsite that uses these types are then updated to use macros that will print the debug output on failure. All of these display strings would be used as part of #35713, but we can also use them with boost today.\n\nWhat this PR does:\n- Adds debug output for types used across multiple files, or types that have a clear debug string, and migrates the `BOOST_CHECK` calls. This covers the majority of custom types that did not yet have a debug string.\n\nWhat this PR does _not_ do:\n- Migrate `BOOST_CHECK` callsites for types that already _do_ have a debug output (all primitive type comparisons, `CFeeRate`, etc). This would be a much larger refactor and could perhaps be done after.\n- Add debug output for `std::vector<T>` where `T` is streamable. These can be migrated to `BOOST_CHECK_EQUAL_COLLECTIONS`, but is a similar refactor to the one above.\n- Add debug output for `std::vector<unsigned char>` and related. Also a large refactor, and could use discussion.\n- Add debug output for types that would require a `friend` method in the source code (`ByRatio`)",
 "commits": [
  {
   "sha": "b6ec94b70016d132438ac4c0c6b740b5626a6f08",
   "date": "2026-09-16T09:40:15Z",
   "message": "test: Add display `operator<<` overloads to `common.{h,cpp}`\n\nIf the `<<` operator exists, boost can use this as a debug output when a\ncheck fails (besides `BOOST_CHECK`). This adds `<<` for types commonly\nused across the unit tests that do not yet have a display output."
  },
  {
   "sha": "e239d936cf0f294760e26c4824c022c0b66d8036",
   "date": "2026-09-16T09:44:48Z",
   "message": "test: Convert `BOOST_CHECK` macros with known debug string\n\nUsing the previous commit we can improve the error output of these\nchecks by updating the boost macros to a version that prints the values\non failure."
  }
 ],
 "timeline": [
  {
   "t": "2026-08-26T12:07:02Z",
   "kind": "comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "text": "Concept ACK"
  },
  {
   "t": "2026-08-26T13:10:10Z",
   "kind": "comment",
   "who": "brunoerg",
   "assoc": "MEMBER",
   "text": "Concept ACK"
  },
  {
   "t": "2026-08-29T15:07:18Z",
   "kind": "review",
   "who": "jeanpablojp",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "92d7a74c0be5796d481dcd2257f974fd2766ad3f",
   "text": "Concept ACK\n\nLeft three comments."
  },
  {
   "t": "2026-08-29T15:07:18Z",
   "kind": "review_comment",
   "who": "jeanpablojp",
   "assoc": "CONTRIBUTOR",
   "path": "src/test/util/display.h",
   "commit": "cb3613294fd4dead87067fae97021f20b0a4aff8",
   "in_reply_to": null,
   "text": "`feefrac_tests` and `txgraph_tests` only need the `FeeFrac` printers, but this block drags addrman, key_io and protocol in with it. Touching addrman now rebuilds both, and it's about 12k extra preprocessed lines in the first one. Would it be worth splitting this by area?"
  },
  {
   "t": "2026-08-29T15:07:18Z",
   "kind": "review_comment",
   "who": "jeanpablojp",
   "assoc": "CONTRIBUTOR",
   "path": "src/test/util/display.h",
   "commit": "f9273c8c6d519669d2756a9e1f5f8efd61825a83",
   "in_reply_to": null,
   "text": "This one leaves out `nTime` and `nServices`, which `operator==` does compare, so in the two addrv1/addrv2 unserialize checks a regression in time or in flags comes out as `[::1]:0 != [::1]:0`. The `CTxDestination` one prints `CTxDestination()` for `CNoDestination` and `PubKeyDestination`. Worth checking each printer against the type's `operator==`?"
  },
  {
   "t": "2026-08-29T15:07:18Z",
   "kind": "review_comment",
   "who": "jeanpablojp",
   "assoc": "CONTRIBUTOR",
   "path": "src/test/util/display.h",
   "commit": "f9273c8c6d519669d2756a9e1f5f8efd61825a83",
   "in_reply_to": null,
   "text": "`Encode()` asserts on an empty key, which is what `DecodeExtKey` leaves you with when it fails, and that's the value `bip32_tests` compares. I broke the decode to see. The case dies on SIGABRT and takes the following ones with it. On master the same break just prints 17 failures and the suite finishes. Worth a guard here and in the `CExtPubKey` one?"
  },
  {
   "t": "2026-08-30T09:17:53Z",
   "kind": "force_push",
   "who": "rustaceanrob",
   "commit": "d550f19567616e103d099a29871cfb9c228dee18"
  },
  {
   "t": "2026-08-30T09:18:47Z",
   "kind": "review_comment",
   "who": "rustaceanrob",
   "assoc": "MEMBER",
   "path": "src/test/util/display.h",
   "commit": "f9273c8c6d519669d2756a9e1f5f8efd61825a83",
   "in_reply_to": 3886906637,
   "text": "If I understood this correctly I added a length guard for each of these. Lmk if that was what you were suggesting."
  },
  {
   "t": "2026-08-30T09:20:10Z",
   "kind": "review_comment",
   "who": "rustaceanrob",
   "assoc": "MEMBER",
   "path": "src/test/util/display.h",
   "commit": "f9273c8c6d519669d2756a9e1f5f8efd61825a83",
   "in_reply_to": 3886906634,
   "text": "Added additional info for `CAddress` and took a glance through the rest of the `==`, I think all fields should be covered. As far as `CTxDestination`, I added specific displays for each variant and the `CTxDestination` printer now just passes through to those."
  },
  {
   "t": "2026-08-30T09:28:23Z",
   "kind": "review_comment",
   "who": "rustaceanrob",
   "assoc": "MEMBER",
   "path": "src/test/util/display.h",
   "commit": "cb3613294fd4dead87067fae97021f20b0a4aff8",
   "in_reply_to": 3886906633,
   "text": "In the current state of #35713 I have it like this; however, I'm a little hesitant to make this change because having each test translation unit define the `<<` would bloat the tests with additional code that doesn't pertain to the logic of the test. With everything defined in a single file, developers know where to make changes to the debug string, but otherwise it is out of the way. I can adjust if other reviewers agree with this suggestion."
  },
  {
   "t": "2026-08-30T12:02:26Z",
   "kind": "review_comment",
   "who": "jeanpablojp",
   "assoc": "CONTRIBUTOR",
   "path": "src/test/util/display.h",
   "commit": "f9273c8c6d519669d2756a9e1f5f8efd61825a83",
   "in_reply_to": 3886906634,
   "text": "While checking the changes I noticed a small nit. `CService`'s `==` compares `m_net`, which the printer doesn't show, so IPv6 and CJDNS with the same bytes come out identical. `MaybeFlipIPv6toCJDNS` in `advertise_local_address` builds the pair. No check reaches that today."
  },
  {
   "t": "2026-08-30T12:03:13Z",
   "kind": "review_comment",
   "who": "jeanpablojp",
   "assoc": "CONTRIBUTOR",
   "path": "src/test/util/display.h",
   "commit": "f9273c8c6d519669d2756a9e1f5f8efd61825a83",
   "in_reply_to": 3886906637,
   "text": "Yes, that's what I meant. I broke the decode again and now it prints `CExtKey(<invalid>)` and the suite finishes, no SIGABRT. Small thing, the `CExtPubKey` invalid branch says `CPubExtKey`."
  },
  {
   "t": "2026-08-31T11:02:25Z",
   "kind": "force_push",
   "who": "rustaceanrob",
   "commit": "f9273c8c6d519669d2756a9e1f5f8efd61825a83"
  },
  {
   "t": "2026-08-31T11:02:59Z",
   "kind": "review_comment",
   "who": "rustaceanrob",
   "assoc": "MEMBER",
   "path": "src/test/util/display.h",
   "commit": "f9273c8c6d519669d2756a9e1f5f8efd61825a83",
   "in_reply_to": 3886906637,
   "text": "Fixed thanks"
  },
  {
   "t": "2026-08-31T11:04:11Z",
   "kind": "review_comment",
   "who": "rustaceanrob",
   "assoc": "MEMBER",
   "path": "src/test/util/display.h",
   "commit": "f9273c8c6d519669d2756a9e1f5f8efd61825a83",
   "in_reply_to": 3886906634,
   "text": "Added a `net` field to `CService`"
  },
  {
   "t": "2026-09-01T14:24:03Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": "src/test/util/display.h",
   "commit": "cb3613294fd4dead87067fae97021f20b0a4aff8",
   "in_reply_to": 3886906633,
   "text": "Most of the functions can be just the signature and a fwd decl for the type, and the actual stringify can move to a cpp file?\n\nThis saves re-compilation at least in the other cases (`AddressPosition`, etc)\n\nAlso, if this is the new display module, the other stuff should move here from `./src/test/util/common.h` later?"
  },
  {
   "t": "2026-09-01T14:40:40Z",
   "kind": "review_comment",
   "who": "rustaceanrob",
   "assoc": "MEMBER",
   "path": "src/test/util/display.h",
   "commit": "cb3613294fd4dead87067fae97021f20b0a4aff8",
   "in_reply_to": 3886906633,
   "text": "[quoted text omitted]\n\nThis could just as well go into `common`, I was just trying to avoid bloat in that file bc I wasn't sure if debug outputs are \"common\", but I suppose they are.\n\n[quoted text omitted]\nSure, we can go this route. I don't have a strong preference."
  },
  {
   "t": "2026-09-01T15:23:12Z",
   "kind": "force_push",
   "who": "rustaceanrob",
   "commit": "7efdb17af6a3d8fbcea8a4120d26bfc428cee2b6"
  },
  {
   "t": "2026-09-01T15:25:25Z",
   "kind": "review_comment",
   "who": "rustaceanrob",
   "assoc": "MEMBER",
   "path": "src/test/util/display.h",
   "commit": "cb3613294fd4dead87067fae97021f20b0a4aff8",
   "in_reply_to": 3886906633,
   "text": "Moved the definitions to `display.cpp`. Can figure out the `common.h` situation later IMO."
  },
  {
   "t": "2026-09-01T16:11:01Z",
   "kind": "review_comment",
   "who": "purpleKarrot",
   "assoc": "MEMBER",
   "path": "src/test/util/display.h",
   "commit": "7efdb17af6a3d8fbcea8a4120d26bfc428cee2b6",
   "in_reply_to": null,
   "text": "No need for separate template instantiations for each derived type:\n\n```cpp\ninline std::ostream& operator<<(std::ostream& os, const FeeFrac& ff)\n{\n    return os << strprintf(\"FeeFrac(fee=%d, size=%d)\", ff.fee, ff.size);\n}\n```\n\nAnd then you can also move the implementation to the source file forward declare `FeeFrac` in the header."
  },
  {
   "t": "2026-09-01T16:46:56Z",
   "kind": "force_push",
   "who": "rustaceanrob",
   "commit": "7cc37297cf64fd9e0f81664be0eda1e3b573a018"
  },
  {
   "t": "2026-09-01T16:48:00Z",
   "kind": "review_comment",
   "who": "rustaceanrob",
   "assoc": "MEMBER",
   "path": "src/test/util/display.h",
   "commit": "7efdb17af6a3d8fbcea8a4120d26bfc428cee2b6",
   "in_reply_to": 3906040903,
   "text": "I de-templated `ByRatioNegSize` as well because the only intended and current use case is with `FeeFrac`. Updated in latest push."
  },
  {
   "t": "2026-09-01T17:30:12Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": "src/test/util/display.h",
   "commit": "7cc37297cf64fd9e0f81664be0eda1e3b573a018",
   "in_reply_to": null,
   "text": "Why is this pair thing needed? Seems to be a single test-only thing? So either this should be moved to that test, or maybe pair should be handled generally, like the existing optional:\n\n```cpp\ntemplate <typename T>\ninline std::ostream& operator<<(std::ostream& os, const std::optional<T>& v)\n{\n    return v ? os << *v\n             : os << \"std::nullopt\";\n}\n```\n\nEither would allow dropping the includes for this."
  },
  {
   "t": "2026-09-01T21:48:11Z",
   "kind": "force_push",
   "who": "rustaceanrob",
   "commit": "cb3613294fd4dead87067fae97021f20b0a4aff8"
  },
  {
   "t": "2026-09-02T09:23:10Z",
   "kind": "review_comment",
   "who": "rustaceanrob",
   "assoc": "MEMBER",
   "path": "src/test/util/display.h",
   "commit": "7cc37297cf64fd9e0f81664be0eda1e3b573a018",
   "in_reply_to": 3906680864,
   "text": "There is a callsite that uses both `BOOST_CHECK` and `std::pair` on types that do not implement `<<`. #35713 works around this because both types make sense as hex representations, but I couldn't compile after rebasing on this branch because `operator<<` resolved first. I added a `requires requires(std::ostream& os, const T& t, const U& u) { os << t; os << u; }`, which I think it correct. Otherwise yeah this should be general, updated in latest push."
  },
  {
   "t": "2026-09-02T09:49:07Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": "src/test/util/display.h",
   "commit": "7cc37297cf64fd9e0f81664be0eda1e3b573a018",
   "in_reply_to": 3906680864,
   "text": "Ah interesting. I wonder if the hex fallback should be added here (even if unused). The benefit would be that the stringify logic and fallback logic would only need to be reviewed once."
  },
  {
   "t": "2026-09-02T09:52:13Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": "src/test/util/display.h",
   "commit": "cb3613294fd4dead87067fae97021f20b0a4aff8",
   "in_reply_to": 3886906633,
   "text": "[quoted text omitted]\n\nIt probably makes sense for `HasReason` to sit in the same header/module? If all display stuff is grouped with one include, it would seem odd to require another include for `HasReason`. But no strong opinion. Also, not sure how if this will change with https://github.com/bitcoin/bitcoin/pull/35713 and the display+`HasReason` stuff is provided by the framework include?"
  },
  {
   "t": "2026-09-02T10:02:10Z",
   "kind": "review_comment",
   "who": "rustaceanrob",
   "assoc": "MEMBER",
   "path": "src/test/util/display.h",
   "commit": "7cc37297cf64fd9e0f81664be0eda1e3b573a018",
   "in_reply_to": 3906680864,
   "text": "I am currently using `typeid` as additional information in that debug output, but that doesn't seem great since it'll be a mangled type name. Another option is to just add `HexType(0x00..00)`. Either way, seems like that can occur in a different pull since this one is to improve specific callsites?"
  },
  {
   "t": "2026-09-02T10:09:47Z",
   "kind": "review_comment",
   "who": "rustaceanrob",
   "assoc": "MEMBER",
   "path": "src/test/util/display.h",
   "commit": "cb3613294fd4dead87067fae97021f20b0a4aff8",
   "in_reply_to": 3886906633,
   "text": "I intend to invert where the display comes from so `framework` imports `common`. Since `common` and the header here are serving the same purpose, I think I will add these forward decl to `common.h` and make a `common.cpp` here."
  },
  {
   "t": "2026-09-02T10:14:39Z",
   "kind": "review",
   "who": "maflcko",
   "assoc": "MEMBER",
   "state": "APPROVED",
   "commit": "cb3613294fd4dead87067fae97021f20b0a4aff8",
   "text": "approach lgtm.\n\nHaven't looked closely, but all of this seems fine."
  },
  {
   "t": "2026-09-02T14:39:22Z",
   "kind": "force_push",
   "who": "rustaceanrob",
   "commit": "056bd2582bc96f1fc2b47933badcd4fe85832c3c"
  },
  {
   "t": "2026-09-02T14:41:13Z",
   "kind": "review_comment",
   "who": "rustaceanrob",
   "assoc": "MEMBER",
   "path": "src/test/util/display.h",
   "commit": "cb3613294fd4dead87067fae97021f20b0a4aff8",
   "in_reply_to": 3886906633,
   "text": "Added `common.cpp` with the implementations and all forward delc to `common.h` in latest push"
  },
  {
   "t": "2026-09-07T18:53:29Z",
   "kind": "review_comment",
   "who": "ismaelsadeeq",
   "assoc": "MEMBER",
   "path": "src/test/util/common.cpp",
   "commit": "05bd1513be2d9aaeb0a94671024f585f0d3cca15",
   "in_reply_to": null,
   "text": "In \"test: Add display `operator<<` overloads to `common.{h,cpp}`\" 05bd1513be2d9aaeb0a94671024f585f0d3cca15\n\nnit: add context to what we are displaying here and other places.\n\ndiff\n\n```diff\ndiff --git a/src/test/util/common.cpp b/src/test/util/common.cpp\nindex ea9b42525a..6f0229c21e 100644\n--- a/src/test/util/common.cpp\n+++ b/src/test/util/common.cpp\n@@ -44,7 +44,7 @@ std::ostream& operator<<(std::ostream& os, const CExtKey& k)\n     if (!k.key.IsValid()) return os << \"CExtKey(<invalid>)\";\n     unsigned char code[BIP32_EXTKEY_SIZE];\n     k.Encode(code);\n-    return os << strprintf(\"CExtKey(%s)\", HexStr(code));\n+    return os << strprintf(\"CExtKey(encoded=%s)\", HexStr(code));\n }\n\n std::ostream& operator<<(std::ostream& os, const CExtPubKey& k)\n@@ -52,7 +52,7 @@ std::ostream& operator<<(std::ostream& os, const CExtPubKey& k)\n     if (k.pubkey.size() != CPubKey::COMPRESSED_SIZE) return os << \"CExtPubKey(<invalid>)\";\n     unsigned char code[BIP32_EXTKEY_SIZE];\n     k.Encode(code);\n-    return os << strprintf(\"CExtPubKey(%s)\", HexStr(code));\n+    return os << strprintf(\"CExtPubKey(encoded=%s)\", HexStr(code));\n }\n\n std::ostream& operator<<(std::ostream& os, const FeeFrac& ff)\n@@ -67,32 +67,32 @@ std::ostream& operator<<(std::ostream& os, const ByRatioNegSize<FeeFrac>& b)\n\n std::ostream& operator<<(std::ostream& os, const CNoDestination& dest)\n {\n-    return os << strprintf(\"CNoDestination(%s)\", HexStr(dest.GetScript()));\n+    return os << strprintf(\"CNoDestination(script=%s)\", HexStr(dest.GetScript()));\n }\n\n std::ostream& operator<<(std::ostream& os, const PubKeyDestination& dest)\n {\n-    return os << strprintf(\"PubKeyDestination(%s)\", HexStr(dest.GetPubKey()));\n+    return os << strprintf(\"PubKeyDestination(pubkey=%s)\", HexStr(dest.GetPubKey()));\n }\n\n std::ostream& operator<<(std::ostream& os, const PKHash& h)\n {\n-    return os << strprintf(\"PKHash(%s)\", h.ToString());\n+    return os << strprintf(\"PKHash(hash=%s)\", h.ToString());\n }\n\n std::ostream& operator<<(std::ostream& os, const ScriptHash& h)\n {\n-    return os << strprintf(\"ScriptHash(%s)\", h.ToString());\n+    return os << strprintf(\"ScriptHash(hash=%s)\", h.ToString());\n }\n\n std::ostream& operator<<(std::ostream& os, const WitnessV0KeyHash& h)\n {\n-    return os << strprintf(\"WitnessV0KeyHash(%s)\", h.ToString());\n+    return os << strprintf(\"WitnessV0KeyHash(hash=%s)\", h.ToString());\n }\n\n std::ostream& operator<<(std::ostream& os, const WitnessV0ScriptHash& h)\n {\n-    return os << strprintf(\"WitnessV0ScriptHash(%s)\", h.ToString());\n+    return os << strprintf(\"WitnessV0ScriptHash(hash=%s)\", h.ToString());\n }\n\n std::ostream& operator<<(std::ostream& os, const WitnessUnknown& w)\n@@ -107,7 +107,7 @@ std::ostream& operator<<(std::ostream& os, const PayToAnchor& p)\n\n std::ostream& operator<<(std::ostream& os, const WitnessV1Taproot& t)\n {\n-    return os << strprintf(\"WitnessV1Taproot(%s)\", HexStr(t));\n+    return os << strprintf(\"WitnessV1Taproot(program=%s)\", HexStr(t));\n }\n\n std::ostream& operator<<(std::ostream& os, const CTxDestination& dest)\n@@ -118,7 +118,7 @@ std::ostream& operator<<(std::ostream& os, const CTxDestination& dest)\n\n std::ostream& operator<<(std::ostream& os, const CPubKey& pk)\n {\n-    return os << strprintf(\"CPubKey(%s)\", HexStr(pk));\n+    return os << strprintf(\"CPubKey(pubkey=%s)\", HexStr(pk));\n }\n\n std::ostream& operator<<(std::ostream& os, const KeyOriginInfo& info)\n```"
  },
  {
   "t": "2026-09-07T19:05:06Z",
   "kind": "review_comment",
   "who": "ismaelsadeeq",
   "assoc": "MEMBER",
   "path": "src/test/bip32_tests.cpp",
   "commit": "e239d936cf0f294760e26c4824c022c0b66d8036",
   "in_reply_to": null,
   "text": "In \"test: Convert `BOOST_CHECK` macros with known debug string\"  056bd2582bc96f1fc2b47933badcd4fe85832c3c\n\nnit: It will be nice if callers don't have to include this in order to use the displayable macros.  Reviewers now have to point to pr authors so they can use it instead of boost check. Because when u use boost check equal without the include, it won't compile.\n\nShould we make common.h self-advertising so authors discover it without a reviewer? A short header comment listing the types it makes BOOST_CHECK_*-printable, e.g.:\n```cpp\n// Provides operator<< for these types so they can be used with BOOST_CHECK_EQUAL/_NE:\n//   AddressPosition, CService, CAddress, CExtKey/CExtPubKey, FeeFrac, CTxDestination\n//   (+ all its alternatives), CPubKey, KeyOriginInfo, BlockTxPosition, std::pair, ...\n// Include this header in your *_tests.cpp to print values on failure.\n```"
  },
  {
   "t": "2026-09-07T19:07:28Z",
   "kind": "review_comment",
   "who": "ismaelsadeeq",
   "assoc": "MEMBER",
   "path": "src/test/bip32_tests.cpp",
   "commit": "e239d936cf0f294760e26c4824c022c0b66d8036",
   "in_reply_to": null,
   "text": "In \"test: Convert `BOOST_CHECK` macros with known debug string\"  056bd2582bc96f1fc2b47933badcd4fe85832c3c\n\nIt seems you missed some.\n\ndiff\n\n```diff\ndiff --git a/src/test/script_standard_tests.cpp b/src/test/script_standard_tests.cpp\nindex 5022e1f7b4..9c87ba7c91 100644\n--- a/src/test/script_standard_tests.cpp\n+++ b/src/test/script_standard_tests.cpp\n@@ -242,14 +242,14 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)\n     s.clear();\n     s << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;\n     BOOST_CHECK(ExtractDestination(s, address));\n-    BOOST_CHECK(std::get<PKHash>(address) == PKHash(pubkey));\n+    BOOST_CHECK_EQUAL(std::get<PKHash>(address), PKHash(pubkey));\n\n     // TxoutType::SCRIPTHASH\n     CScript redeemScript(s); // initialize with leftover P2PKH script\n     s.clear();\n     s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;\n     BOOST_CHECK(ExtractDestination(s, address));\n-    BOOST_CHECK(std::get<ScriptHash>(address) == ScriptHash(redeemScript));\n+    BOOST_CHECK_EQUAL(std::get<ScriptHash>(address), ScriptHash(redeemScript));\n\n     // TxoutType::MULTISIG\n     s.clear();\n@@ -267,7 +267,7 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)\n     BOOST_CHECK(ExtractDestination(s, address));\n     WitnessV0KeyHash keyhash;\n     CHash160().Write(pubkey).Finalize(keyhash);\n-    BOOST_CHECK(std::get<WitnessV0KeyHash>(address) == keyhash);\n+    BOOST_CHECK_EQUAL(std::get<WitnessV0KeyHash>(address), keyhash);\n\n     // TxoutType::WITNESS_V0_SCRIPTHASH\n     s.clear();\n@@ -275,14 +275,14 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)\n     CSHA256().Write(redeemScript.data(), redeemScript.size()).Finalize(scripthash.begin());\n     s << OP_0 << ToByteVector(scripthash);\n     BOOST_CHECK(ExtractDestination(s, address));\n-    BOOST_CHECK(std::get<WitnessV0ScriptHash>(address) == scripthash);\n+    BOOST_CHECK_EQUAL(std::get<WitnessV0ScriptHash>(address), scripthash);\n\n     // TxoutType::WITNESS_V1_TAPROOT\n     s.clear();\n     auto xpk = XOnlyPubKey(pubkey);\n     s << OP_1 << ToByteVector(xpk);\n     BOOST_CHECK(ExtractDestination(s, address));\n-    BOOST_CHECK(std::get<WitnessV1Taproot>(address) == WitnessV1Taproot(xpk));\n+    BOOST_CHECK_EQUAL(std::get<WitnessV1Taproot>(address), WitnessV1Taproot(xpk));\n\n     // TxoutType::ANCHOR\n     s.clear();\n```"
  },
  {
   "t": "2026-09-07T19:31:57Z",
   "kind": "review_comment",
   "who": "ismaelsadeeq",
   "assoc": "MEMBER",
   "path": "src/test/util/common.h",
   "commit": "e239d936cf0f294760e26c4824c022c0b66d8036",
   "in_reply_to": null,
   "text": "In \"test: Add display `operator<<` overloads to `common.{h,cpp}`\" 05bd1513be2d9aaeb0a94671024f585f0d3cca15\n\nShould we add for script too?\n\n```suggestion\nstd::ostream& operator<<(std::ostream& os, const CScript& script);\n\n```"
  },
  {
   "t": "2026-09-07T19:34:15Z",
   "kind": "review",
   "who": "ismaelsadeeq",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "056bd2582bc96f1fc2b47933badcd4fe85832c3c",
   "text": "Code review ACK 056bd2582bc96f1fc2b47933badcd4fe85832c3c\n\nLeft a few comments. I checked the new test modification and did not see any change in the test invariants."
  },
  {
   "t": "2026-09-08T09:17:59Z",
   "kind": "force_push",
   "who": "rustaceanrob",
   "commit": "71cef456b6b7f23e55d23be02145ec33c0347132"
  },
  {
   "t": "2026-09-08T09:25:12Z",
   "kind": "review_comment",
   "who": "rustaceanrob",
   "assoc": "MEMBER",
   "path": "src/test/util/common.cpp",
   "commit": "05bd1513be2d9aaeb0a94671024f585f0d3cca15",
   "in_reply_to": 3952074729,
   "text": "Makes sense. Applied those changes as well as adding a `addr` field to `CService` and `CAddress`."
  },
  {
   "t": "2026-09-08T09:25:50Z",
   "kind": "review_comment",
   "who": "rustaceanrob",
   "assoc": "MEMBER",
   "path": "src/test/bip32_tests.cpp",
   "commit": "e239d936cf0f294760e26c4824c022c0b66d8036",
   "in_reply_to": 3952129720,
   "text": "Applied those changes, thanks"
  },
  {
   "t": "2026-09-08T09:27:07Z",
   "kind": "review_comment",
   "who": "rustaceanrob",
   "assoc": "MEMBER",
   "path": "src/test/util/common.h",
   "commit": "e239d936cf0f294760e26c4824c022c0b66d8036",
   "in_reply_to": 3952225313,
   "text": "Yeah, definitely, I added a debug output and modified `psbt_tests` and `script_tests` to include it."
  },
  {
   "t": "2026-09-08T09:35:20Z",
   "kind": "force_push",
   "who": "rustaceanrob",
   "commit": "0560c013476708771cf9141fda54410cbee07645"
  },
  {
   "t": "2026-09-08T10:50:26Z",
   "kind": "review_comment",
   "who": "rustaceanrob",
   "assoc": "MEMBER",
   "path": "src/test/bip32_tests.cpp",
   "commit": "e239d936cf0f294760e26c4824c022c0b66d8036",
   "in_reply_to": 3952120727,
   "text": "Added a comment to `common.h` describing the purpose of the file. I think it would be a bit cumbersome to update the list on each addition to this file, and the developer would already be either in the file or one click away, so I noted that debug-available types are listed in the header."
  },
  {
   "t": "2026-09-08T13:13:38Z",
   "kind": "review",
   "who": "jeanpablojp",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "0560c013476708771cf9141fda54410cbee07645",
   "text": "tACK 0560c013476708771cf9141fda54410cbee07645\n\nRebuilt and ran the unit tests on this head. Left one non-blocking nit."
  },
  {
   "t": "2026-09-08T13:13:38Z",
   "kind": "review_comment",
   "who": "jeanpablojp",
   "assoc": "CONTRIBUTOR",
   "path": "src/test/util/common.cpp",
   "commit": "e239d936cf0f294760e26c4824c022c0b66d8036",
   "in_reply_to": null,
   "text": "nit: `ScriptToAsmStr` decodes any push of up to four bytes as a number, so scripts that differ in bytes can come out as the same string.\n\nA P2WPKH scriptPubKey and the same script with `OP_0` replaced by a one-byte zero push, which is no longer a witness program, both print the same, and `psbt_tests` compares exactly `GetScriptForDestination(WitnessV0KeyHash{...})`. Would it be worth adding `hex=%s` alongside?"
  },
  {
   "t": "2026-09-08T13:31:25Z",
   "kind": "force_push",
   "who": "rustaceanrob",
   "commit": "387e443275587a46c25f21ed5e05e02439140a5a"
  },
  {
   "t": "2026-09-08T13:31:55Z",
   "kind": "review_comment",
   "who": "rustaceanrob",
   "assoc": "MEMBER",
   "path": "src/test/util/common.cpp",
   "commit": "e239d936cf0f294760e26c4824c022c0b66d8036",
   "in_reply_to": 3958262109,
   "text": "Nice find. Somewhat unfortunate to make the debug output longer here, but given the ASM will be the most useful a majority of the time, with the possibility of needing to use hex, I added the hex string alongside the ASM in the latest push."
  },
  {
   "t": "2026-09-08T15:30:17Z",
   "kind": "review",
   "who": "ismaelsadeeq",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "387e443275587a46c25f21ed5e05e02439140a5a",
   "text": "reACK 387e443275587a46c25f21ed5e05e02439140a5a, all my suggestions were addressed."
  },
  {
   "t": "2026-09-08T16:08:54Z",
   "kind": "comment",
   "who": "jeanpablojp",
   "assoc": "CONTRIBUTOR",
   "text": "re-ACK 387e443275587a46c25f21ed5e05e02439140a5a"
  },
  {
   "t": "2026-09-14T15:47:31Z",
   "kind": "review_comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "path": "src/test/script_tests.cpp",
   "commit": "e239d936cf0f294760e26c4824c022c0b66d8036",
   "in_reply_to": null,
   "text": "How exhaustive is the conversion supposed to be? In this file alone there seem to be more cases where we compare scriptsigs."
  },
  {
   "t": "2026-09-15T09:16:33Z",
   "kind": "force_push",
   "who": "rustaceanrob",
   "commit": "bd0b35aae17674025e0fd12ae5049a2f74e2687f"
  },
  {
   "t": "2026-09-15T09:24:21Z",
   "kind": "review_comment",
   "who": "rustaceanrob",
   "assoc": "MEMBER",
   "path": "src/test/script_tests.cpp",
   "commit": "e239d936cf0f294760e26c4824c022c0b66d8036",
   "in_reply_to": 4006941579,
   "text": "It is intended to be completely exhaustive for the types with << added here. I ran the following: `rg -nP '\\bBOOST_CHECK(?!_)\\s*\\(\\s*(?=[^()\\n]*(?:==|!=|<=|>=|<|>))[^()\\n]*\\)'` which showed quite a few additional sites I missed that have been updated now (`descriptor_tests`, `key_tests`, `script_standard_tests`, `script_tests`). Should be cleaned up now, updated in latest push.\n\nThat grep also showed a number of sites that could be converted from `BOOST_CHECK` to `BOOST_CHECK_*` bc the types have `operator<<`, but those could be done as follow up or deferred."
  },
  {
   "t": "2026-09-15T09:26:36Z",
   "kind": "force_push",
   "who": "rustaceanrob",
   "commit": "fc42f878cb578f9d91d6b11e8dd6fe2057a54fbc"
  },
  {
   "t": "2026-09-15T15:27:46Z",
   "kind": "comment",
   "who": "ismaelsadeeq",
   "assoc": "MEMBER",
   "text": "reACK fc42f878cb578f9d91d6b11e8dd6fe2057a54fbc\n\nThe recent push converted a few call sites that were supposed to be converted from bare boost check but are left out.\n\nI also used the same `rg -nP '\\bBOOST_CHECK(?!_)\\s*\\(\\s*(?=[^()\\n]*(?:==|!=|<=|>=|<|>))[^()\\n]*\\)'` command and inspected the remaining ones; there are some that can also have a display string like `TxGraph::Ref`. Intentional I guess?\nInteger comparisons are left untouched as well. Also intentional?\n\nThe PR description should be more explicit about this and the rationale.\n\nThis is a nice cleanup consequence of the main goal, which is replacing the framework, and I support it, but AFAICT only the first commit is needed ed9dd305702f58bfb1872434d135cd3858cb4010 for the main PR https://github.com/bitcoin/bitcoin/pull/35713,"
  },
  {
   "t": "2026-09-16T09:46:26Z",
   "kind": "force_push",
   "who": "rustaceanrob",
   "commit": "e239d936cf0f294760e26c4824c022c0b66d8036"
  },
  {
   "t": "2026-09-16T09:58:40Z",
   "kind": "comment",
   "who": "rustaceanrob",
   "assoc": "MEMBER",
   "text": "Thanks, I updated the description to be more thorough as far as what this seeks to accomplish.\n\n[quoted text omitted]\nYes, added to description\n\n[quoted text omitted]\nWhat is being compared in those tests is `std::vector<std::vector<TxGraph::Ref*>>`, which is more nuanced. Also updated the description."
  }
 ],
 "labels_log": [
  {
   "t": "2026-08-26T11:54:14Z",
   "action": "labeled",
   "label": "Tests",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-26T13:32:48Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-26T15:48:15Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-08T09:36:08Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-08T10:36:05Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-15T09:28:25Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-15T10:29:14Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 17715,
 "text_tokens_estimate": 4428,
 "changed_paths": [
  "src/test/addrman_tests.cpp",
  "src/test/bip32_tests.cpp",
  "src/test/descriptor_tests.cpp",
  "src/test/feefrac_tests.cpp",
  "src/test/key_tests.cpp",
  "src/test/mempool_fee_estimator_tests.cpp",
  "src/test/miner_tests.cpp",
  "src/test/net_tests.cpp",
  "src/test/netbase_tests.cpp",
  "src/test/psbt_tests.cpp",
  "src/test/rbf_tests.cpp",
  "src/test/script_standard_tests.cpp",
  "src/test/script_tests.cpp",
  "src/test/txgraph_tests.cpp",
  "src/test/txindex_tests.cpp",
  "src/test/util/CMakeLists.txt",
  "src/test/util/common.cpp",
  "src/test/util/common.h"
 ],
 "files": [
  {
   "path": "src/test/addrman_tests.cpp",
   "add": 15,
   "del": 15
  },
  {
   "path": "src/test/bip32_tests.cpp",
   "add": 7,
   "del": 6
  },
  {
   "path": "src/test/descriptor_tests.cpp",
   "add": 13,
   "del": 6
  },
  {
   "path": "src/test/feefrac_tests.cpp",
   "add": 27,
   "del": 26
  },
  {
   "path": "src/test/key_tests.cpp",
   "add": 10,
   "del": 10
  },
  {
   "path": "src/test/mempool_fee_estimator_tests.cpp",
   "add": 14,
   "del": 13
  },
  {
   "path": "src/test/miner_tests.cpp",
   "add": 2,
   "del": 2
  },
  {
   "path": "src/test/net_tests.cpp",
   "add": 16,
   "del": 16
  },
  {
   "path": "src/test/netbase_tests.cpp",
   "add": 4,
   "del": 2
  },
  {
   "path": "src/test/psbt_tests.cpp",
   "add": 4,
   "del": 3
  },
  {
   "path": "src/test/rbf_tests.cpp",
   "add": 21,
   "del": 10
  },
  {
   "path": "src/test/script_standard_tests.cpp",
   "add": 19,
   "del": 19
  },
  {
   "path": "src/test/script_tests.cpp",
   "add": 31,
   "del": 31
  },
  {
   "path": "src/test/txgraph_tests.cpp",
   "add": 4,
   "del": 3
  },
  {
   "path": "src/test/txindex_tests.cpp",
   "add": 5,
   "del": 4
  },
  {
   "path": "src/test/util/CMakeLists.txt",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/test/util/common.cpp",
   "add": 146,
   "del": 0
  },
  {
   "path": "src/test/util/common.h",
   "add": 55,
   "del": 0
  }
 ],
 "test_lines": 560,
 "git": {
  "head": "e239d936cf0f294760e26c4824c022c0b66d8036",
  "head_matches_backup": true,
  "base": "794a753958a7d4c03d6deadd6740d32d9bd6dbb5",
  "commits": [
   {
    "sha": "b6ec94b700",
    "subject": "test: Add display `operator<<` overloads to `common.{h,cpp}`",
    "files": 3,
    "add": 202,
    "del": 0
   },
   {
    "sha": "e239d936cf",
    "subject": "test: Convert `BOOST_CHECK` macros with known debug string",
    "files": 15,
    "add": 192,
    "del": 166
   }
  ],
  "patch_truncated": true
 },
 "input_hash": "c3376b37ac9c3e7d",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}