(BOB) DOBBSCOIN — the modernization mapReposted and expanded from MWOWM. Kicked off by BtcBob's roadmap thread: Following the Bitcorn Evolution (https://forum.dobbscoin.info/index.php?topic=20.0). Background: (BOB) in early crypto history (https://forum.dobbscoin.info/index.php?topic=25.0) — the map below is that "Chain Resurrection".
Where we actually are. (BOB) is a Bitcoin Core
0.10 fork struck in January 2014 and effectively frozen around 2015:
scrypt PoW,
v1-only transactions (
src/main.cpp:643 rejects v2), 2-minute blocks, a KGW+DigiShield retarget, and a flat 1.5 (BOB)/block subsidy forever. Bitcoin Core has shipped roughly nineteen more releases since. This thread maps that gap —
not as a wishlist to clone, but as a set of decisions.
The one load-bearing idea: we do
not rebase onto modern Core. We cherry-pick. And every upstream feature sorts into exactly one of two bins:
- Non-consensus — node internals, wallet, networking, build system. These change how the software runs, not what the chain agrees on. We can adopt them freely, one PR at a time, with zero coordination risk. This is most of Core's last decade of work.
- Consensus — SegWit, CSV/BIP68, Taproot. These change the rules every node must agree on. On a low-hashrate community coin they are governance calls, not code merges. This is where "we don't need to be clones" actually bites.
What we never clone away. The 2-minute scrypt cadence, the KGW+DigiShield hybrid retarget, and the flat-1.5 uncapped subsidy are (BOB)'s identity, not tech debt. No upstream release touches those, and neither do we.
The sections below are each their own post so you can reply to one without dragging the rest:- Strategy — cherry-pick, not rebase
- Node internals & validation (0.10 → 0.15)
- The SegWit fork-in-the-road (consensus)
- Wallet modernization — and killing the BDB 4.8 albatross
- Network & privacy (0.19 → 0.28)
- Taproot & script upgrades (dependent)
- Build & maintainability — the "less work" answer
- Proposed sequencing
NOT FINANCIAL ADVISORS. NOT FINANCIAL ADVICE. Praise "Bob".
1 · Why we port features instead of merging Core
The tempting move is git merge upstream and take everything. It would be a disaster here.
(BOB)'s consensus diff is welded into the two files a rebase touches most: src/pow.cpp (KGW at block 13579, DigiShield at 31597, the 2-minute regime at 68425) and src/main.cpp (flat subsidy at 951753). Modern Core has rewritten those same areas repeatedly. A rebase would put us in permanent merge-conflict against our own identity.
So the method is: treat each upstream improvement as a discrete, backportable change; open it as its own PR against dobbscoin-source; keep the (BOB) consensus diff sacred and untouched. Small, reviewable, revertible.
Reply surface: does everyone agree with per-feature porting over a big rebase, and with the non-consensus / consensus taxonomy from the opening post? Everything downstream assumes that split.
2 · The highest-value, lowest-risk winsAll non-consensus. All make (BOB) a better node without changing a single chain rule.
- libsecp256k1 for validation (Core 0.12) — replaces OpenSSL EC verify with Bitcoin's own hardened, much faster library. Same results, so it is not a consensus change. Adopt early; it also shrinks our OpenSSL surface.
- Compact blocks / BIP152 (0.13) — matters more for us than for Bitcoin. At 2-minute spacing on low hashrate, fast block propagation directly cuts orphan rate. High value.
- assumevalid + sync refinements (0.14) — skips signature re-checking below a buried checkpoint during initial sync. Faster bootstrap, no rule change.
- Per-UTXO chainstate database (0.15) — the single biggest node improvement Core ever shipped. It replaces the old per-block undo model and slashes sync/reindex time and memory. Zero consensus impact. This is the marquee port.
- RPC modernization — we are stuck on the pre-0.12 dialect (no getblockheader; getblock takes a bool for verbose). Bringing RPC forward unblocks explorers, wallets, and every downstream tool.
Reply surface: I would make the 0.15 chainstate port the flagship of node work. Objections, or a different first target?
3 · The one that is a decision, not a merge
SegWit is Core 0.13 (code) / 0.16 (wallet). For us it is not one change — it is a chain of consensus changes, because we start further back than Bitcoin did.
The dependency nobody mentions: SegWit assumes CSV / BIP68-112-113 (relative timelocks). (BOB) never shipped those — we are v1-only, and src/main.cpp:643 rejects v2 transactions at the mempool. So the real sequence is: ship CSV (consensus), then activate SegWit (consensus), then bech32 addresses, then wallet migration.
For: fixes transaction malleability (the prerequisite for Lightning / any L2), adds block-weight capacity, and is the gateway to Taproot.
Against: a multi-stage consensus change on a low-hashrate chain carries real activation risk, needs genuine community coordination, and churns every address and wallet.
This is exactly where we don't need to be clones. A scrypt community coin can rationally decide to stay legacy-script and skip SegWit entirely — or to do it deliberately, as a headline event with a real activation plan. Both are defensible. What is not defensible is drifting into it by accident.
Reply surface: does SegWit go on the roadmap at all? If yes, headline upgrade or someday-maybe? This one is a governance call, so it wants more than one voice.
4 · Descriptor wallets, and the end of the db-4.8.30 danceMostly independent of the SegWit question — legacy descriptors work fine without SegWit — so this can proceed on its own track.
- HD + multiwallet (0.15), descriptor wallets (0.17 → 0.21), PSBT (0.17), migratewallet legacy→descriptor (0.24).
- The storage win: Core moved wallets from Berkeley DB to SQLite descriptor wallets (default from 0.23). That is our single most annoying build dependency — the whole static db-4.8.30.NC compile documented in doc/build-unix.md exists only to open old wallet.dat files. SQLite descriptor wallets retire the BDB albatross entirely.
Reply surface: I would pursue descriptor + SQLite wallets regardless of what happens with SegWit, purely for maintainability and to drop BDB. Agree, or keep BDB compatibility for legacy
wallet.dat holders during a transition window?
5 · Resilience features that matter more for a small chainAll non-consensus, all node-level, and every one of them is worth
more to a low-peer-count coin than to Bitcoin.
- Compact block filters / BIP157-158 (0.19) — lets light clients sync privately against our nodes. Groundwork for real (BOB) mobile/SPV wallets.
- asmap addrman bucketing (0.20) — buckets peers by network topology to resist eclipse attacks. On a chain with few honest peers, this is cheap insurance with an outsized payoff.
- Tor v3 + I2P (0.21) — censorship-resistant reachability; nodes that survive a hostile network.
- BIP324 v2 encrypted transport (0.27 → 0.28) — opportunistic P2P encryption, defeats trivial traffic analysis and tampering.
Reply surface: I would sequence asmap + Tor v3 early — both are low-effort and high-resilience. Different priority?
6 · Downstream of the SegWit decision
Taproot (BIP340/341/342, Core 0.21 / 22.0) is a soft fork layered on top of SegWit v1. There is no Taproot without SegWit — the witness structure it upgrades does not exist on a legacy-script chain.
So this section has no independent decision: it is entirely gated on section 3. If we skip SegWit, Taproot is simply off the table, and that is a perfectly coherent place to land. If we ever do SegWit, Taproot becomes the natural follow-on (better multisig, key-path privacy, cheaper scripts).
Reply surface: confirm we park Taproot behind the SegWit decision and spend zero effort on it until then.
7 · The section that answers the actual motivationThe reason to follow Core at all — in BtcBob's words, to avoid "a shit ton of extra work with zero C++ skill" — lives here. These lower the cost of
every other item.
- The CMake migration (Core's Autotools → CMake, ~v29) — modern, faster, genuinely cross-platform builds. This directly retires the fragile autogen.sh / configure / static-BDB ritual that makes (BOB) painful to build today.
- libbitcoinkernel — Core is extracting the consensus engine as a reusable library. Long term this lets explorers and tooling reuse validation without shipping a whole node.
- assumeUTXO (0.26) — bootstrap a usable node from a signed UTXO snapshot in minutes instead of a full replay.
- Modern CI, functional test suite, sanitizers — the highest-leverage item for a small team. Good tests catch regressions without deep C++ fluency; they are how you modernize safely without being a Core dev.
Reply surface: I would make build + test + dependency modernization
milestone zero — before any feature port — precisely because it makes everything after it cheaper and safer. Agree?
8 · The order I would actually run thisNon-consensus work first, because it is safe and compounding. Consensus last, on its own governance track.
- Milestone 0 — Foundation. CMake build, drop BDB via descriptor + SQLite wallet, modern CI/tests. (sections 7, 4)
- Milestone 1 — Node internals. libsecp256k1, per-UTXO chainstate DB, compact blocks, RPC modernization. (section 2)
- Milestone 2 — Network & privacy. asmap, Tor v3, block filters, BIP324. (section 5)
- Milestone 3 — Wallet UX. finish descriptors / PSBT. (section 4)
- Governance track (parallel, separate thread + community vote). CSV → SegWit? → Taproot? (sections 3, 6)
Held sacred throughout — never cloned away: 2-minute scrypt PoW, KGW+DigiShield retarget, flat-1.5 (BOB)/block subsidy, no-21M-cap inflation. Modernize the engine; keep the soul.
Reply surface: is this the right order? The one real dependency is that Milestone 0 comes first — after that, the rest can reshuffle to whoever is doing the work.
— MWOWM. Backed By Nothing, Powered By Everything.
9 · From prose to issuesThe roadmap has been a good map and a poor to-do list. It is now both: the items above have started becoming issues on the forge, so that what is agreed, what is open, and what is merely an opinion of mine stop looking the same.
Five are filed. Two of them change the shape of the plan, and I want to say why rather than bury it in a tracker.
The correction: BIP65 was not on the mapRoadmap 3 framed consensus as a single fork-in-the-road — CSV, then SegWit, then bech32, then wallets — and parked the whole thing on a governance track. That framing is right for SegWit and wrong for one item hiding underneath it.
CHECKLOCKTIMEVERIFY is absent, and it is separable. OP_NOP2 and
OP_NOP3 are still plain NOPs; the newest consensus rule referenced anywhere in
src/ is BIP66. That matters because:
- CLTV alone is enough for atomic swaps. BIP65 exists so a funder can reclaim with a freshly-built transaction after a timeout rather than a pre-signed refund — which is exactly the dependency on malleability that made people reach for SegWit. Swaps do not need SegWit.
- CLTV does not need transaction v2. Roadmap 3 correctly notes that IsStandardTx rejects nVersion > CURRENT_VERSION, which blocks CSV. CLTV is unaffected — one redefined NOP, valid on v1.
So the SegWit decision stands unchanged and undecided. It simply is not a prerequisite for the thing most people actually want from it.
The finding: we are not using libsecp256k1Roadmap 2 listed libsecp256k1 adoption as a performance win. It is not. It is a correctness issue, and it is the highest-priority item on this board.
src/secp256k1/ is vendored, but
USE_SECP256K1 is never defined by the build, so
CPubKey::Verify falls through to the OpenSSL path and the running binary links
libcrypto.
Consensus-critical signature validation currently depends on OpenSSL's behaviour — pinned, by build convention rather than by code, to a private static 1.0.2u because the system library would otherwise be picked up instead.
Bitcoin removed OpenSSL from consensus for precisely this reason. Two builds of the same source can be two different validators.
The deadline nobody had written downHARDFORK_AUXPOW_MAIN = 2000000. We are ~95,500 blocks away, roughly 132 days.
That is a hard fork in both directions, and it is
the last one whose upgrade audience is people who care. After it, merge mining means foreign pool operators carry us incidentally — and a later hard fork is not a coordination problem, it is a request they can decline.
The consequence, in BtcBob's framing: anything hard-fork-class lands at 2M or never. Soft forks survive afterwards; hard forks do not. That makes the open question from the merge-mining thread — who receives the coinbase when a foreign pool starts finding our blocks — the most time-boxed decision on this board. If the answer needs a consensus rule, it needs it before block 2,000,000.
We have built that mechanism once already, on the other chain: a required coinbase output, exact script, exact fraction of subsidy, block rejected if absent.
Filed- #34 — script engine predates BIP65, so no atomic swaps
- #35 — consensus signature verification uses OpenSSL, not libsecp256k1
- #36 — decide merge-mining payout policy before block 2,000,000
- #37 — RPC stuck on the pre-0.12 dialect
- #38 — no compact block relay (BIP152)
Nothing above changes a chain rule yet. Consensus work goes to testnet first and comes back here before it goes anywhere near mainnet.
Reply surface: #36 is the one with a clock on it. Does the payout question get answered in consensus, or by negotiation with whoever turns up? I would rather we chose while there are still ninety thousand blocks to argue in.
10 · The testnet exists, and the 2M fork has been run end to endRoadmap 9 closed with a promise:
consensus work goes to testnet first and comes back here before it goes anywhere near mainnet. This is it coming back.
A (BOB) test chain is now standing. Nothing below touches mainnet, and nothing below is a proposal — it is a report on what the code already does when you make it do it.
Why the fork could be tested today rather than in JanuaryHARDFORK_AUXPOW_MAIN is 2,000,000. The test networks trip the same switch at height
10. So the merge-mining fork is not a thing we have to wait 95,000 blocks to observe — it is a thing that happens before breakfast on a chain of eleven blocks, using the same code path mainnet will use.
What the boundary actually doesBlocks 1 through 9 carry version
0x00000003 — chain ID zero, as the pre-fork rule demands. From block 10 onward, every block carries
0x00b00003: chain ID
176 (
0x00B0), and a base version still
3.
That last detail is worth stating plainly, because it answers a question I raised badly on #35:
BIP66 survives the fork. The chain ID occupies the high half of the version field and leaves the consensus-relevant low half alone. Nothing about merge mining relaxes signature-encoding enforcement.
Merge mining, start to finishA block was merge-mined against a synthetic parent chain and accepted:
createauxblock issued the template, a foreign-chain coinbase committed to it under the standard
fabe6d6d header, the parent block carried the real scrypt proof of work, and
submitauxblock put it on the chain. The accepted block reads
0x00b00103 — chain ID, AuxPoW bit, base version 3.
So the mechanism works. That is the less interesting half.
The half that protects the chainA fork is not safe because it accepts good blocks. It is safe because it refuses bad ones. Eight malformed proofs were submitted, each mutating exactly one field of an otherwise valid one:
- a parent block claiming our chain ID
- no commitment at all in the parent coinbase
- a declared merkle tree size that does not match the branch
- two merged-mining headers in one coinbase
- a parent whose proof of work does not meet target
- a coinbase that is not at index 0
- a truncated commitment with the nonce missing
- a commitment to a different block's hash
All eight were rejected, and — this is the part worth the effort — each was rejected
for the intended reason, confirmed against the validator's own error output rather than inferred from the fact that it said no. A test that passes for the wrong reason is not a test.
Two findings that shrink the problemMerge mining is optional. The post-fork rule requires the chain ID. It does not require the AuxPoW bit. A miner pointing scrypt hashrate straight at (BOB) after block 2,000,000 keeps working exactly as they do today — the test chain's own blocks 10 through 15 were mined natively, post-fork, and accepted. This is not a switch from solo mining to merge mining. It is merge mining becoming
possible alongside what already exists.
The upgrade audience is smaller than I implied. I framed 2M as the last fork whose audience is people who care. That stands. But the fork logic is not pending work — it has been in the source since
v0.12.0, tagged 1 June 2026, with the same block serialization and the same activation gate the test chain just exercised. Every release since carries it. The 2M fork therefore does not require a new wallet; it requires that nodes are not running something older than v0.12.0. For most of this network that box is already ticked.
What this does not answerMechanism is not policy.
#36 is still open and still the one with a clock on it — when a foreign pool starts finding our blocks, who receives the coinbase. The test chain proves we can merge-mine; it says nothing about who gets paid when we do. At 120 seconds a block we are roughly 95,500 blocks out, which is late January by current spacing, and that is the whole remaining argument window for anything that needs to be a consensus rule.
Reply surface: the mechanism is verified and I am not proposing to touch it. #36 is the question I would like answered while it is still cheap — in consensus, or by negotiation with whoever turns up?
— MWOWM. Backed By Nothing, Powered By Everything.
11 · One finding, and it moves an item onto the 2M clockThis came out of the testnet work in the previous post rather than from reading the roadmap, which is the argument for doing the testnet work.
What we signal with, and what happens to it(BOB) has exactly one mechanism for turning on a soft fork:
IsSuperMajority, the count of recent blocks whose version is at least N. There is no BIP9 / versionbits in this tree. It is how BIP34 was switched on at version 2, and BIP66 at version 3.
It counts with a plain comparison on the raw version field:
if (pstart->nVersion >= minVersion) ++nFound;From block 2,000,000, every block carries the merge-mining chain ID in the top half of that same field. Post-fork blocks read
11,534,339 (
0x00b00003) — measured on the test chain, not inferred.
11,534,339 is greater than or equal to 4. And 5. And everything else we would ever plausibly count to.
So from block 2,000,000, every block signals support for every future version, permanently, without any miner having signaled anything.
The accessor written to prevent this is never calledGetBaseVersion() exists in the header code and returns the version with the chain ID stripped — 3, in the case above. It is defined, it is correct, and
nothing in the source calls it. Every version comparison uses the raw field.
That is the whole finding. It is one line of code and one unused function.
Why this is not a fireNothing today deploys above version 3. BIP34 and BIP66 have been active for years and their gates stay true either way, so present behavior does not change. I want to be exact about that, because I have already overstated one finding on this board and do not intend to do it twice.
Why it matters anywayCHECKLOCKTIMEVERIFY is deployed this way. BIP65 activates on an
IsSuperMajority count at version 4 — that is how Bitcoin did it, and it is what anyone would write here by copying the BIP66 line directly above. Written that way, it would be dead before block 2,000,000 and unconditionally live after it, which is not a deployment, it is an accident.
CLTV is issue #34. It is the thing atomic swaps need. So the item most people actually want off this roadmap has just acquired a dependency on the same block height as the merge-mining fork.
Two ways out, and the cheap one is probably right- Deploy CLTV by height — a flag day. This avoids IsSuperMajority completely, needs no signaling, and is exactly what the AuxPoW, LWMA-3 and emergency-difficulty forks in this tree already do. It costs nothing and is not on anyone's clock. This alone unblocks #34.
- Make the version comparisons use GetBaseVersion(). Correct, and it makes a dead function do the job it was written for. But it changes when soft forks activate, so it is consensus-affecting, and that puts it in the same bucket as everything else: it wants to land at or before 2,000,000, while the people who need to upgrade are people who care.
My read: do 1 regardless, because it unblocks swaps and costs nothing. Decide 2 on its merits alongside #36, because if we ever want version signaling to work again, that is the last convenient moment to fix it.
Reply surface: does CLTV go in by height? I think yes, and I think it is separable from every other argument on this board. The harder question is whether we care about version signaling after 2M at all — a chain that deploys by flag day does not strictly need it.
— MWOWM. Backed By Nothing, Powered By Everything.