Jason Dreyzehner (b5cd19f6) at 13 Nov 23:13
Format upgrade_status.name for external use
... and 354 more commits
Thanks @cculianu, those changes look great!
On upgrade_status.name: that field is intended to be passed right along to rarely-updated UIs without requiring a change each year (people already have to upgrade BCHN), so I'd prefer it keep that format: May ${year} Upgrade (${network}net). e.g. for this year:
May 2026 Upgrade (mainnet)May 2026 Upgrade (scalenet)May 2026 Upgrade (test4net)May 2026 Upgrade (chipnet)That makes it 100% clear what you're looking at straight from the JSON response, and downstream UIs can also render it without an update.
E.g. bch-rpc-explorer already expects that (merged in this PR) and uses it directly for the upgrade title:
| Time to Upgrade | Screenshot |
|---|---|
| 13 days before |
![]() |
| 1 day before |
![]() |
| ~4 hours before |
![]() |
| ~42 min before |
![]() |
| Pending postactivation block |
![]() |
| After upgrade |
![]() |
BCHN upgraded, new upgrade_status
|
![]() |
The network is already displayed above, so the bch-rpc-explorer simply trims the last (...) from upgrade_status.name.
On the other hand, if we go with an internal name like Upgrade12, all polished UIs will have to be modified to understand the new internal name each year. Currenly, the above screenshots would render Upgrade12 in each heading where you see May 2026 Upgrade, and the bch-rpc-explorer code would need to be manually changed each year.
In fact, next year isn't even Upgrade13, so the generic bch-rpc-explorer code I might have written for this response would render: May 4040 Upgrade. (Extracting the 12 and adding 2013, which would have worked for several years now, but would be fooled by Upgrade2027.)
Also want to add: I consider it important that the "upgrade_status.name API" is resilient to years with multiple upgrades.
E.g. if a surprise, working quantum computer is announced in August 2029, creating sudden urgency for one final quantum-readiness upgrade, we don't want edge tooling and UIs to break or look bad all over the ecosystem. Any set-and-forget systems (like bch-rpc-explorer) should simply be reading from this name, and will have no problem accepting Nov 2029 Upgrade (mainnet). Operators will only need to update BCHN, no need to scramble and update other software.
(Note, also there's no need to go more granular than month in this field. It's essentially the upgrade's most-canonical "marketing title", so hypothetically, if there were ever two consensus changes in the same month, the second is almost certainly an emergency patch, and the wider industry shouldn't need to disambiguate their marketing titles – the second change likely fixed a critical bug in the first.)
I also experimented with whether or not Chipnet should render an "earlier" name, i.e. Nov 2025 Upgrade (chipnet), but this is a lot worse for downstream setups: you want a consistent key across networks to be able to map upgrades to what they're supposed to do; a shifting date between networks makes things a lot harder to reason about downstream. For the same reason, I also strongly recommend May 2026 Upgrade (mainnet) keep the (mainnet) part, despite it being reasonable to drop (better to have downstream software always assume it will be there for every network.
null fieldsLikewise, sending back null rather than leaving out missing fields makes it a lot easier for downstream software to discover fields and verify they're handling things correctly (which is otherwise quite tough, since you naturally only have one chance to get it right in production for each upgrade – best to have it as fool-proof as possible).
Anyways, I tried a lot of response shapes – sending back "year" separately, making the response more structured rather than a single "name" string, incorporating upgrade "features" and/or "CHIP" titles, numbers, etc. – and after experimenting with using those results in downstream software, it's very hard to beat the reliability and effectiveness of the May ${year} Upgrade (${network}net) format, so I strongly prefer it. Would that be alright with you @cculianu?
TLDR:
upgrade_status.name switch back to May ${year} Upgrade (${network}net),Jason Dreyzehner (14a565ac) at 12 Nov 20:00
Merge branch 'push_node_expiry_may_2027' into 'master'
... and 347 more commits
Jason Dreyzehner (cd221aac) at 12 Nov 19:22
Add getblockchaininfo.upgrade_status support and tests
Extracted and cleaned up getblockchaininfo.upgrade_status support/tests from cculianu/bitcoin-cash-node!60 (more background there)
getblockchaininfo.upgrade_status
Every year, it's a pain to follow when exactly the upgrade is happening, and people rely on hacked-together scripts or single-points-of-failure to monitor the upgrade. (Coincidentally, one of the best sources every year, http://cash.coin.dance/, happens to be down at the moment I'm writing this.)
IMO, anyone running BCHN should be able to easily see the status of the most relevant upgrade(s) for the node's currently configured network. This was actually available in 2015 at getblockchaininfo.softforks (see BTC docs here), but was deleted without replacement after the BCH-BTC split.
Example output before an upgrade activates:
"upgrade_status": {
"name": "Upgrade12",
"mempool_activated": false,
"mempool_activation_mtp": 1757937600,
"block_preactivation_height": null,
"block_preactivation_hash": null,
"block_postactivation_height": null,
"block_postactivation_hash": null,
"software_expiration_time": 1763208000
},
And after an upgrade activates (the locked-in status for the Sept 2025 tempnet):
"upgrade_status": {
"name": "Upgrade12",
"mempool_activated": true,
"mempool_activation_mtp": 1757937600,
"block_preactivation_height": 271015,
"block_preactivation_hash": "00000000023062becd19275fa2ec7cbe32d3eb5329708ccb006143865f010af7",
"block_postactivation_height": 271016,
"block_postactivation_hash": "00000000163a426b4dfe4a484b8753c918f58b8cb9bf716cbf7be2d871867bc4",
"software_expiration_time": 1763208000,
},
-expire=0 and/or modifying-upgrade2027activationtime=.
software_expiration_time key-upgrade12activationtime=
Jason Dreyzehner (fd089cea) at 12 Nov 19:04
Add getblockchaininfo.upgrade_status support and tests
... and 350 more commits
Thanks for the statement!
[...] included in the May 2023 consensus changes:
Ok if I correct this to 2026?
This is a very rough draft implementing several user/developer experience features surrounding network upgrades. It's the same code originally published here: https://github.com/bitjson/bchn/tree/tempnet and discussed here: https://bitcoincashresearch.org/t/tempnet-2026-chipnet-upgrade-pre-upgrade-testing/1675/4?u=bitjson
I hope this is a good starting point for discussing implementing some (not all) of these features in BCHN.
Caveat: I'm perpetually a C++ amateur. This implementation is a combination of me hacking things together + test-driven LLM autocompletion + manual review and testing. I only polished the parts where I expected this draft could be useful – UX and documentation. The code is just beyond "works", probably not "correct", and definitely not "fast".
Ultimately, if any of these features are pulled into BCHN, I think the C++ code in this initial implementation should tossed in the trash, and only the user-facing design, RPC calls, descriptions, naming, docs, etc. should be pulled into focused MRs.
Tempnet" network designation
It's very useful for pre-chipnet upgrade testing to have a designation for temporary networks. Avoids clobbering your chipnet data directory, simplifies setup for testers, allows us to polish the UX/DevX by e.g. (as implemented here) making tempnet nodes expire shortly after the expected chipnet upgrade (so that properly configured nodes will simply stop and re-join the real chipnet when automatically restarted).
getblockchaininfo.upgrade_status
Every year, it's a pain to follow when exactly the upgrade is happening, and people rely on hacked-together scripts or single-points-of-failure to monitor the upgrade. (Coincidentally, one of the best sources every year, http://cash.coin.dance/, happens to be down at the moment I'm writing this.)
IMO, anyone running BCHN should be able to easily see the status of the most relevant upgrade(s) for the node's currently configured network. This was actually available in 2015 at getblockchaininfo.softforks (see BTC docs here), but was deleted without replacement after the BCH-BTC split.
Example output before an upgrade activates:
"upgrade_status": {
"name": "May 2026 Upgrade (tempnet)",
"mempool_activation_mtp": 1757937600,
"block_preactivation_height": null,
"block_preactivation_hash": null,
"block_postactivation_height": null,
"block_postactivation_hash": null,
"software_expiration_mtp": 1763208000,
"mempool_activated": false
},
And after an upgrade activates (the locked-in status for the Sept 2025 tempnet):
"upgrade_status": {
"name": "May 2026 Upgrade (tempnet)",
"mempool_activation_mtp": 1757937600,
"block_preactivation_height": 271015,
"block_preactivation_hash": "00000000023062becd19275fa2ec7cbe32d3eb5329708ccb006143865f010af7",
"block_postactivation_height": 271016,
"block_postactivation_hash": "00000000163a426b4dfe4a484b8753c918f58b8cb9bf716cbf7be2d871867bc4",
"software_expiration_mtp": 1763208000,
"mempool_activated": true
},
I iterated a bit on upgrade status information that's most useful to application developers. I actually confused myself (and LLMs in several places) with the existing "activation block" terminology in the first commit; the second commit adopts a clearer terminology that is harder for application developers to misunderstand:
I didn't fully find-replace "activation block" with the clarified "preactivation" and "postactivation" terminology throughout the whole codebase, but I think that might be a good idea to make off-by-one errors/underhandedness harder to miss. This MR just implements the terminology in upgrade_status and some of the new code/tests.
queuebroadcasttx, gettxbroadcastqueue, cancelbroadcasttx
A simple, local broadcast queue (where sends are triggered by a locktime MTP or height being hit) would significantly simplify tooling for a lot of DeFi and advanced applications, like time-locked security vaults, inheritance systems, etc.
Currently, these applications need stateful monitoring infrastructure that is error prone, hard to test, and easily broken by local networking issues. Instead, it would be ideal if application developers can control (via RPC: queuebroadcasttx, gettxbroadcastqueue, cancelbroadcasttx) a simple, local BCHN-managed queue.
Such a local queue also happens to be extremely useful for network upgrades too by allowing developers and companies to easily queue of post-activation transactions. This really reduces the effort required to demonstrate clean launches right after network upgrades – devs should be on podcasts, livestreams, at conferences, etc. bragging about their product at the moment of upgrade – not babysitting their hacked together launch tooling
This draft implementation is ultra simple: in memory only, queue is deleted on shutdown. If it's not too difficult, I'd request (for ~20% more value) that queuebroadcasttx accept an optional persist option (default: false) that saves the queued transaction to disk in case the node shuts down before it's sent.
I wasn't confident I'd be implementing this reasonably, so I only implemented the default non-persistent behavior – dropping the transaction – (which I think is safer against application-level bugs that accidentally queue too many transactions and get the node OOM killed). But making persistence an option would add another chunk of value (especially for upgrades), by making very long-term persistence more reliable.
This item makes Tempnet/Chipnet upgrades more predictable by letting nodes require that a specific transaction be included in the postactivation block. Today, this is done manually by large miners on whichever network is being upgraded. In the same sense as above – we want developers to be free to livestream/celebrate upgrades, not waiting around to park blocks via RPC.
Having a built-in capability to set your node to require "following the upgrade" makes it a lot easier to prevent shenanigans on Tempnet and Chipnet upgrade days. (We haven't had this problem yet, but it would be trivial to aggressively re-org a tempnet or chipnet right around the upgrade to cause chaos and hurt confidence. We usually have a lot of mining power standing by ready to defend, but it would be a lot nicer if every BCHN node could simply be preset to refuse a postactivation block which doesn't have a previously-prepared, trustless covenant transaction like the one I've prepared for the 2025 Nov Chipnet upgrade. This would again free up BCH devs during the actual upgrades.)
Again, these are proposed BCHN features, not necessarily related to the 2026 CHIPs. These features could reasonably be contributed to master (one at a time), and the 2026 CHIPs then rebased on top. I hacked these features into this WIP branch to make the Sept. 15 Tempnet a little easier to launch, but please consider this MR a UX draft/prototype.
Jason Dreyzehner (a59fc965) at 09 Oct 17:00
Clarify preactivation vs. postactivation block, fix resync issue
... and 381 more commits
Thanks for working on this @A60AB5450353F40E!
Just adding a note here too: I think P2S outputs still need their own new "type" in JSON responses. E.g. https://2026-tempnet.chaingraph.cash/tx/57b73d879dfff363a9103b3731d4e14a9f7410b158b5c1e608b2c424a5c3d130 still shows a p2s output as "nonstandard", even after the upgrade is activated:
{
"txid": "57b73d879dfff363a9103b3731d4e14a9f7410b158b5c1e608b2c424a5c3d130",
"hash": "57b73d879dfff363a9103b3731d4e14a9f7410b158b5c1e608b2c424a5c3d130",
"version": 2,
"size": 264,
"locktime": 0,
"vin": [
{
"txid": "9ff6028fe49fc8a635168cd422221b4d0926d9ade95931039284c2a5b8e8d406",
"vout": 0,
"scriptSig": {
"asm": "30440220030326f313c74e118ac62ff0a2e03e8e50403369b0603f014cbf4dd81300adde02201937139d220497bb073076f4cccefa8635347936afdc6d96d170a101376797ce[ALL|FORKID] 023a96bc5b21118c71c2e2a87596174586edf3df1cd859a9a9bdd6fe3352c13551",
"hex": "4730440220030326f313c74e118ac62ff0a2e03e8e50403369b0603f014cbf4dd81300adde02201937139d220497bb073076f4cccefa8635347936afdc6d96d170a101376797ce4121023a96bc5b21118c71c2e2a87596174586edf3df1cd859a9a9bdd6fe3352c13551"
},
"sequence": 4294967294
}
],
"vout": [
{
"value": 0.0001,
"n": 0,
"scriptPubKey": {
"asm": "00517b658c6b7d936c73916677 -1 OP_DEFINE 6 -1 OP_INVOKE OP_EQUALVERIFY 13 -1 OP_INVOKE OP_TXVERSION 2 OP_TXOUTPUTCOUNT 1 OP_TXLOCKTIME OP_OUTPUTVALUE 0 OP_2DUP OP_OUTPUTTOKENAMOUNT OP_3DUP OP_INPUTSEQUENCENUMBER OP_OUTPUTBYTECODE OP_INVERT -81148303506325 2 6 OP_LSHIFTNUM 0 OP_OUTPUTTOKENCOMMITMENT OP_SIZE OP_SWAP OP_BIN2NUM 0 0 OP_OUTPOINTTXHASH 0 OP_OUTPUTTOKENCATEGORY OP_BEGIN OP_EQUALVERIFY OP_DEPTH OP_NOT OP_UNTIL OP_TXINPUTCOUNT 1 OP_EQUAL",
"hex": "0d00517b658c6b7d936c739166774f89564f8a885d4f8ac252c451c5cc006ed36fcbcd830695fbcdcfcdc952568d00d2827c810000c800d16588749166c35187",
"type": "nonstandard"
}
},
{
"value": 0.01001636,
"n": 1,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 738a53805e89e816312aa08907edb1cd3f5c5f70 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a914738a53805e89e816312aa08907edb1cd3f5c5f7088ac",
"reqSigs": 1,
"type": "pubkeyhash",
"addresses": [
"bchtest:qpec55uqt6y7s93392sgjpldk8xn7hzlwqwtdsysm0"
]
}
}
],
"hex": "020000000106d4e8b8a5c28492033159e9add926094d1b2222d48c1635a6c89fe48f02f69f000000006a4730440220030326f313c74e118ac62ff0a2e03e8e50403369b0603f014cbf4dd81300adde02201937139d220497bb073076f4cccefa8635347936afdc6d96d170a101376797ce4121023a96bc5b21118c71c2e2a87596174586edf3df1cd859a9a9bdd6fe3352c13551feffffff021027000000000000400d00517b658c6b7d936c739166774f89564f8a885d4f8ac252c451c5cc006ed36fcbcd830695fbcdcfcdc952568d00d2827c810000c800d16588749166c35187a4480f00000000001976a914738a53805e89e816312aa08907edb1cd3f5c5f7088ac00000000",
"blockhash": "000000002fc6ba2fc08016eccd285f52ae9c701517d7c34acb60fff8a5de4766",
"confirmations": 696,
"time": 1757645381,
"blocktime": 1757645381
}