From 50eeb9c9d620895c0d63664d610ea4cfe7b81a34 Mon Sep 17 00:00:00 2001 From: Bitflash Date: Thu, 30 Jul 2026 18:22:45 -0300 Subject: mine: put the block height in the coinbase, so two can never be identical (#59) Nothing in a coinbase belonged to the block it was in. The transaction was a function of three things: the difficulty, a counter, and the payout key. nBits holds still for long stretches, and bnExtraNonce is a local that restarts at zero whenever the miner does, so the same combination comes round again and produces a byte-identical transaction with the same txid. Two blocks then name the same transaction. The index keeps whichever arrived last, and the outputs of the first stop being reachable, with nothing logged and nothing shown. It has already happened twice on the main chain -- coinbase c9e56f7131 at heights 841 and 859, e635f4441f at 845 and 860 -- and 100 BTF are gone because of it. #58 has the full account. Putting the height first makes two coinbases at different heights unequal by construction, whatever the counter and the key do afterwards. Nothing validates coinbase content today, so this changes only what this node produces: blocks stay acceptable to every node already on the network, with no coordination and no activation height. Requiring the height, and enforcing BIP30 on top of it, is the separate coordinated step that this one has to come before. Verified by mining with the patch: the coinbase reads 5104ffff0f1f0101 -- OP_1 for height 1, then nBits, then the counter -- and the scriptSig is 8 bytes against the 100-byte ceiling in CheckTransaction. --- src/main.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index f4e6ce2..c77448d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2883,7 +2883,25 @@ bool BitcoinMiner(int nThreadId) CTransaction txNew; txNew.vin.resize(1); txNew.vin[0].prevout.SetNull(); - txNew.vin[0].scriptSig << nBits << ++bnExtraNonce; + // The height comes first and is what makes this transaction unique. + // + // Without it nothing in the coinbase belongs to the block: it is a + // function of the difficulty, a counter, and the payout key. nBits + // holds still for long stretches and bnExtraNonce is a local that + // restarts at zero whenever the miner does, so the same combination + // comes round again and produces a byte-identical transaction with the + // same txid. Two blocks then name the same transaction and the index + // keeps whichever arrived last, which silently destroys the outputs of + // the first. It has already happened twice on this chain, at heights + // 859 and 860 (#58). + // + // Two coinbases at different heights can now never be identical, no + // matter what the counter or the key do. + // + // Nothing validates coinbase content, so this changes only what we + // produce -- nodes that do not upgrade accept these blocks unchanged. + // Requiring the height is a separate, coordinated step. + txNew.vin[0].scriptSig << (pindexPrev ? pindexPrev->nHeight + 1 : 0) << nBits << ++bnExtraNonce; txNew.vout.resize(1); // Always pay coinbase to own wallet key. In operator mode, the pool // server distributes shares to miners via SendMoney() after each block. -- cgit v1.2.3