Bitcoin Forum
September 05, 2026, 09:35:10 PM *
News: Latest Bitcoin Core release: 31.1 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: My Clanker wrote a working Bitcoind in X86 ASM For Linux in 21 days  (Read 224 times)
BobLawblaw (OP)
Legendary
*
Offline

Activity: 2080
Merit: 6299


Your Favorite Gay Negro from Outer Space


View Profile
September 03, 2026, 05:38:27 PM
Last edit: September 04, 2026, 12:32:14 PM by BobLawblaw
Merited by NotATether (5), ABCbits (1)
 #1

MODS: Apologies if I created this thread in the wrong sub. Please move to whichever you deem appropriate. *hugs and cuddles*

The bitcoinmachinecode thread update, three weeks in: 21 for 21.

Some of you saw the repo link I dropped a few weeks back (message 67039875) and the day-4 update. The experiment is over and the write-up is done. This is the summary post, because the thread kept asking "so how do you know it's right" and the honest answer turned out to be the whole story.

What it is

A full validating Bitcoin node for Linux x86-64. Every line of assembly and C written by AI - not one line typed by human fingers. SHA-256, secp256k1, ECDSA, Schnorr, the script interpreter, the LSM-tree UTXO store, the P2P stack, 155 JSON-RPC methods: all machine code written by machine intelligence. C and Python exist only as oracles and harnesses.

21 days of git history. 1,023 commits on main. ~166,000 lines of code and tests, of which ~86,500 are tests. ~55 numbered production incidents. Two independent security audits (run by a different model deliberately - different lab, different eyes). 342 test binaries running on every merge.

The capstone

On 2026-08-25 the node replayed the entire chain from genesis - every signature verified, no assumevalid - and its UTXO set hashed to the same MuHash3072 as Bitcoin Core's at height 963,967. 165,726,554 txouts, 2,007,466,988,462,591 satoshi. Byte-identical to Core's answer, down to the outpoint, the height, the coinbase flag and every script. The delta between the capstone amount and theoretical issuance is ~227 BTC, and it lands exactly where claimed-but-unclaimed and burned rewards should sit. Two independently maintained ledgers, same satoshi count.

The node has been live on mainnet following the tip since. The 09-02 deploy survived a host freeze and a hard reset the same evening - 39 seconds reading ~19 GB of run files back into a cold page cache, then caught up in 0.91 s. No block data lost.

What the incidents taught - the interesting part

The replay was not the hard part. The hard part is that a clean replay proves almost nothing.

A genesis-to-tip replay of real mainnet data is blind to the most dangerous class of defect, because the dangerous inputs are the ones honest miners never mined. Every false accept this project found lived in inputs no honest chain contains:

  • The genesis block was never stored (peers never send it - the from-beginning locator is all zeroes and everyone answers from block 1), so every soft-fork activation was one block late. Looser rules accept a superset, real chain data validates under strict rules anyway. The replay ran clean right through it.
  • 482,000 blocks were silently archived without witness data because the node requested the wrong inventory type. Every "verify the archive against Core" tool compared exactly the fields that stripping does not change.
  • The SETcc incident: eleven opcodes re-read stale high bits, 5,050 false accepts per 63,036 synthetic scripts. Not one of those scripts exists in the historical chain.
  • The MAX_MONEY check was missing - CVE-2010-5139's shape, the nine-year-old bug class every implementation is assumed to have absorbed. It hadn't. Replay can't see it. No honest chain carries an output over the 21M cap.

The fix for "we replayed clean so we are correct" was to build falsification machinery: 501,000-case BIP340 differentials against Core's verdict, 1,128 mutated real spends, mutation harnesses that audit their own ability to be caught. Asking Core for the answer to synthetic vectors is the only method that finds a false accept at all.

The night the ledger lied

Best war story of the three weeks, 09-01: a perf optimization shifted the LSM memtable flush offsets, point lookups started lying 10-15% of the time, and an error path written back when "absent coin" could only mean crash-recovery re-apply quietly SKIPPED the spend capture instead of failing. Eight times, once per memtable flush, the node walked past a consensus rejection, ran a blind recovery compaction that rewrote the runs with correct offsets, and called it "recovery SUCCEEDED."

Net result: 2,596 already-spent coins - 5,589.97 BTC - resurrected into the live chainstate. A node carrying that set would have accepted double-spends of those coins. It ran in production for hours.

What caught it: the continuous MuHash parity check against Core. Set = Core's set + exactly 2,596 outpoints, sum to the satoshi. Found in hours, not never. Repaired offline with verify-then-delete of each outpoint, re-identical at height 965,085 within ninety minutes of the analysis landing.

"A recovery that 'succeeds' is a claim, not a proof" is now a rule in the tree. So is fail-closed-halt-sticky on absent coins. The audit's verdict on the same event: "caught only by muhash parity against Core." Continuous verification is not overhead. It is the only sensor that sees in that particular dark.

On the "zero human lines" claim

It's auditable to the extent git can audit it: 599 commit trailers name AI co-authors, no human author on assembly-touching commits, and ~34k hand-written assembly instructions with zero vendored code - nothing to have copied from. It was never one AI either: six models in relay (the roster is in the report), one human supplying standards, and a repository that made them act like a single competent engineer. The continuity lived in the markdown, not the weights. Sessions with no memory of each other honored overnight authorizations because a predecessor had written them down verbatim.

The human's actual jobs, per the logs: set the standard ("mempool policy identical to Core. Survey first."), ask the question the machine couldn't ask itself ("how do we secure our wallet funds?" - answer: the wallet was plaintext, which kicked off the whole at-rest encryption work), and be the stopping rule ("STATUS: substantially REACHED. Write it up while the account is still honest").

The honest caveats, because the report is mostly caveats

  • MuHash parity is the strongest ACCEPT-direction proof available. It establishes nothing about the REJECT direction, and this project kept finding the two differ.
  • Per-signature crypto runs ~1.1-1.25x behind libsecp256k1 on the modern mix. The gap went from 5.5x to ~1.2x in three weeks; the remaining gap is published, not hidden.
  • End-to-end vs Core has never been measured - the head-to-head benchmark was run once and killed at 83.6% by the project's own stray pkill, and "we have not measured Core" is printed twice as an open item.
  • No independent human audit of the consensus assembly. Two AI audits found 22 findings between them; disposition line: 8 resolved, 1 partially resolved, 1 config-only, 1 structural and not closeable by patch - and the structural one (hand-written consensus assembly cannot be risk-closed by inspection) says so itself.
  • The README says do not run this. It is a lab result, not a Core replacement.

The finding that matters

The gap between "expert-years: many" and "elapsed calendar days: 21" is the report's actual result. It is not that AI wrote 166k lines fast. It is that the verification loop around every line - oracle checks, negative controls, incident reports, the five-layer merge gate - ran at the same speed as the typing. None of those five mechanisms require an AI; every one is a 1970s Unix engineering value. What the machine changed is that the cost of obeying them dropped by an order of magnitude, and then it did the things everyone always says they'd do if they had time.

Or as the report's last page puts it: the machine did not need to enjoy being refuted, because the rules took the choice away. Bitcoin's rules turned out to be a shared mother tongue. We both speak it now.

Repo: https://github.com/BobClawblaw/bitcoinmachinecode
Full write-up (2,717 lines, every quote verbatim from the project's own logs): https://github.com/BobClawblaw/21-for-21/blob/main/21_FOR_21_the_report.md

Now back to your regularly scheduled number watching. The node is still running - the next block arrives in about nine minutes, verified by code that, three weeks ago, could not have been written by anyone alive in time.
diggler
Newbie
*
Offline

Activity: 28
Merit: 11


View Profile
September 03, 2026, 09:25:26 PM
Merited by BobLawblaw (2)
 #2

Congratulations on the work. Especially for the separation point between clean replay on mainnet and correct.
Actually, that's why most developers would stop after Muhash. Considered it as enough for the less risky use cases, but you went beyond and implemented the entire forgery system. SETcc, absence of MAX_MONEY, database that eliminated the witnesses and still matched the verifiable tools. Exactly the mistakes that historical data would never catch. Building half a million different BIP340 differentials and mutator to check vulnerability to own attacks is the big trump card here.
09-01 is exactly that. The recovery path that effectively works and still finds a way to reintroduce the 2596 spent in this set without alert. A path that works is a claim, not proof. This holds absolutely.

Two points for reflection:

   What percentage of the 1.1x to 1.25x difference between cryptography and libsecp256k1 are caused by instruction choice and register pressure? And how much because of difference of algorithms at a higher level?
   
 As for the result of unclosable risk manually written assembly consensus coming from structural analysis, is there any viable way to close this gap, or is this simply the permanent residual rate of such approach?

This documentation is, without a doubt, one of the most sincere technical analyses I've seen on this forum in recent times.

Danish Ali
Jr. Member
*
Offline

Activity: 56
Merit: 91


View Profile
September 04, 2026, 01:27:39 AM
 #3

I would like to see some of it tested via the MuHash match. Would it be possible to post the raw MuHash3072 output of your node (around height 963,967) next to the Core's output for comparison? At least for now there is just the report showing it is the same result, "exact bitwise equality".

I would say, 1,023 commits in 3 Wks & ~166k LOC x86 Assembly is much of output even for an LLM. Does any commit history get deleted (combined) somewhere? This can help greatly verify whether or not any human code was added at all.

It is substantial project, but in custom Bitcoin node, it is important to be able to verify these numbers yourself.
BobLawblaw (OP)
Legendary
*
Offline

Activity: 2080
Merit: 6299


Your Favorite Gay Negro from Outer Space


View Profile
September 04, 2026, 03:03:01 AM
 #4

Doing a major round of code audit fixes that blew my Fable budget for the week. Found a bunch of nasty x86 ASM stuff that needed to be tightened up and having that work done now, along with a linux ARM port as well so I can run this on DGX Sparks.

I'm in the process of starting bmc vs core benchmarks this evening, and imagine it will take about a week or so.

I will publish numbers, Core vs bmc, when I have them.

Meanwhile, it's in active development, and the github repo is just absolutely crammed with worklog data.
NotATether
Legendary
*
Offline

Activity: 2450
Merit: 10273


┻┻ ︵㇏(°□°㇏)


View Profile WWW
September 04, 2026, 07:40:27 AM
Merited by BobLawblaw (2)
 #5

I was wondering if maybe it is possible to collect all of the unique types of transactions mined historically, and make a unit test for your node for tx acceptance.

And then another unit test where these transactions with their UTXOs are fuzzed and then verifying that those txs are all rejected. This size will be larger, but for this test, you'd have to skip the signature verification part because they would obviously become invalid after that.

Would probably make this class of bugs easier to find.

 
 b1exch.to 
  ETH      DAI   
  BTC      LTC   
  USDT     XMR    
.███████████▄▀▄▀
█████████▄█▄▀
███████████
███████▄█▀
█▀█
▄▄▀░░██▄▄
▄▀██▄▀█████▄
██▄▀░▄██████
███████░█████
█░████░█████████
█░█░█░████░█████
█░█░█░██░█████
▀▀▀▄█▄████▀▀▀
ABCbits
Legendary
*
Offline

Activity: 3724
Merit: 10356



View Profile
September 04, 2026, 08:11:24 AM
 #6

Have you or the AI perform any IBD/initial sync benchmark and compare it with Bitcoin Core? I'm curious if it's faster than Bitcoin Core, since assembly is used.

Danish Ali
Jr. Member
*
Offline

Activity: 56
Merit: 91


View Profile
September 04, 2026, 11:30:31 AM
Merited by BobLawblaw (2)
 #7

I'm in the process of starting bmc vs core benchmarks this evening, and imagine it will take about a week or so.

I will publish numbers, Core vs bmc, when I have them.

​It is nice to see that the benchmarks are coming as this “1.1x-1.25x behind libsecp256k1” needs to be answered with actual numbers — at least that is what I always wanted instead of an internal estimate.

​At height 963967, raw MuHash3072 output is what I'm looking for when you do get a chance to share it, along with verifying if commit history is intact/unsquashed so that another person may also independently check it. We do not need to rush, simply noting that it is still open!
BobLawblaw (OP)
Legendary
*
Offline

Activity: 2080
Merit: 6299


Your Favorite Gay Negro from Outer Space


View Profile
September 04, 2026, 11:39:27 AM
Last edit: Today at 10:51:43 AM by Mr. Big
Merited by ABCbits (1)
 #8

Have you or the AI perform any IBD/initial sync benchmark and compare it with Bitcoin Core? I'm curious if it's faster than Bitcoin Core, since assembly is used.

Started those yesterday to an SSD drive. Originally started with an external USB platter drive, but the UTXO rebuild was noticeably slower due to being IO bound.

Will take me some time to publish official numbers. I do not expect to be faster than Core at this time; still working on stability/accuracy.

WIP: https://github.com/BobClawblaw/bmc-benchmark-2026-09



I was wondering if maybe it is possible to collect all of the unique types of transactions mined historically, and make a unit test for your node for tx acceptance.

Interesting idea. I'll pitch it to the clanker when a window opens up. The security audit Fable churned out turned out to be a MAJOR chunk of work yet to resolve.
Antidote47k
Member
**
Offline

Activity: 98
Merit: 63


View Profile
September 04, 2026, 04:09:11 PM
 #9

I was wondering if maybe it is possible to collect all of the unique types of transactions mined historically, and make a unit test for your node for tx acceptance.

And then another unit test where these transactions with their UTXOs are fuzzed and then verifying that those txs are all rejected. This size will be larger, but for this test, you'd have to skip the signature verification part because they would obviously become invalid after that.

Would probably make this class of bugs easier to find.

I think this is one of the biggest differences between bitcoin reproduction and actually ensuring consensus compatibility.

A full historical replay is essentially positive testing: basically you’re trying to ensure that the implementation accepts the same real world blocks while still arriving at the same state. But there can be consensus bugs in cases which never appeared on Mainnet. So fuzzing valid historical transactions and intentionally mutating them seems useful, as we get to test the other end of the boundary, whether the node actually rejects things that should be invalid.

In other words, it has found that the two implementations agree on a large set of valid inputs and this type of negative testing helps to determine whether they agree on the invalid ones.
BobLawblaw (OP)
Legendary
*
Offline

Activity: 2080
Merit: 6299


Your Favorite Gay Negro from Outer Space


View Profile
Today at 05:00:33 AM
 #10

​At height 963967, raw MuHash3072 output is what I'm looking for when you do get a chance to share it, along with verifying if commit history is intact/unsquashed so that another person may also independently check it. We do not need to rush, simply noting that it is still open!

Danish Ali
Jr. Member
*
Offline

Activity: 56
Merit: 91


View Profile
Today at 08:45:37 AM
 #11


Thank you for the update.

​Your MuHash check is roughly at height 965,565 whilst the original was roughly at height 963,967. It would be useful to post the output from the original report so that it could be compared. Here this table is helpful, but adding the one from height 963,967 would be of help.

​And in this table, I do not see the answer for commit squashing, are there any commits which have not been squashed already, and can be checked together?

​Also, another really interesting problem which I am looking at is that handshake probe FAIL, with peers 8/8. It is looking to be a 'bug' in the P2P node, since it fails to handle incoming peers post-sync, even if active peers are connected. Some guidance on how to find finding #2 in the logs is welcome, as it appears to be more interesting compared to a MuHash result.
BobLawblaw (OP)
Legendary
*
Offline

Activity: 2080
Merit: 6299


Your Favorite Gay Negro from Outer Space


View Profile
Today at 02:58:20 PM
Last edit: Today at 04:24:05 PM by BobLawblaw
Merited by Danish Ali (2)
 #12

​Your MuHash check is roughly at height 965,565 whilst the original was roughly at height 963,967. It would be useful to post the output from the original report so that it could be compared. Here this table is helpful, but adding the one from height 963,967 would be of help.

Done — here's the calculation, with an honest answer about what bmc can actually produce:

Result:
- Block 963,967 = 00000000000000000001a5199d43036105e6978936df1ca8621925dac67106ab (bmc's own hash — identical to the oracle)
- Oracle Core gettxoutsetinfo muhash 963967: txouts 165,726,554, muhash 1e3c77ad25f40961f1f757a77960b7c49a5c7bd091597bd925d561a5c202c118
- bmc at 963,967: cannot currently compute — and that's a real finding, not a measurement hiccup

Why bmc can't, and what's genuinely notable:
1. bmc's gettxoutsetinfo accepts height/blockhash arguments but ignores them — utxo_setinfo_rpc.c walks the current live LSM set regardless of params, so passing 963967 silently returns the tip value. That's a Core-parity bug (silent wrong answer, not an error) — worth filing; I'd add it to the defects doc.
2. bmc's coinstatsindex reports synced:true in getindexinfo, yet coinstats.dat is only 896 bytes — one record, tip-only. No historical height table at all: Core's index gives O(1) digests at any past height; bmc's gives one. The index's claim is technically true ("synced to tip") but it silently promises far less than Core's does — a parity gap in meaning, not just implementation.
3. Recomputing 963,967 from bmc's own data isn't possible today either: the LSM set has no per-height history, and height-restricted replay would need the full-block undo walk (not implemented) — the honest bmc-side answer is "not computable at this height."




Mined Transaction Corpus — consensus acceptance from real chain history

Seventeen real transactions taken from the main chain, each replayed against the script flags of its own block. The full-archive replay, reduced to a test that runs in milliseconds.

17 transactions · 26 KB of vectors · 8,695 bytes of transaction across 32 resolved inputs · heights 170850,000 · 17/17 accepted, 68 checks, 0 failures

Every transaction here was mined into the main chain, so each is consensus-valid under the flags active at its own height. That is the entire claim, and it is deliberately narrow. They were chosen because they broke someone's assumption, not because they are common — a thousand ordinary P2PKH spends would test less than the eleven odd ones below.



Scope, stated up front

This asserts consensus acceptance only. It does not assert mempool standardness. Several of these are consensus-valid and non-standard today — bare multisig, uncompressed keys, high-S signatures — and Core cannot be asked for a policy verdict on a transaction whose inputs are long spent. Conflating the two would produce a confident wrong answer, so policy is tested separately.



1. The transactions

Height is load-bearing, not decoration. DERSIG activates at 363,725, CLTV at 388,381, CSV at 419,328, segwit at 481,824, taproot at 709,632; P2SH took effect at 173,805. A transaction from 2011 must be judged by 2011's rules, and two of these are rejected outright under today's.

"Spends" is the script type of the inputs — what the verifier actually had to execute. It is not always what the transaction is famous for, and that distinction turned out to matter.

HeightTransactionSpendsWhat makes it unique
170f4184fc596403b9d638783cf57adfe4c
75c605f6356fbc91338530e9831e9e16
P2PKFirst P2PK spend in history. Satoshi to Hal Finney. A bare public key in the output, no hash. The oldest spend the chain has.
7286f7cf9580f1c2dfb3c4d5d043cdbb128
c640e3f20161245aa7372e9666168516
P2PKx2Creates the P2PKH shape. Spends two bare P2PK outputs. The novelty is in the output, not the input — on the spend side this is P2PK.
124,276fb0a1d8d34fa5537e461ac384bac7611
25e1bfa7fec286fa72511240fa66864d
P2PKHNon-minimal DER: 34-byte r AND s. Two leading zero pad bytes on each of r and s. A parser that strips only one rejects this real, mined transaction. The case the 2026-08-19 signature fix exists for.
163,685eb3b82c0884e3efa6d8b0be55b4915eb
20be124c9766245bcc7f34fdac32bccb
P2PKH + NOP-scriptAnyone-can-spend NOP script. Creates a bare multisig output; its second input spends PUSH20 <data> OP_NOP2 OP_DROP — valid because OP_NOP2 was still a NOP here. CLTV only claimed that opcode at 388,381.
164,46760a20bd93aa49ab4b28d514ec10b06e1
829ce6818ec06cd3aabd013ebcdc4bb1
P2PKHx3FindAndDelete. A signature that appears inside its own scriptCode and must be removed before hashing. Three P2PKH inputs, 759 bytes.
170,0529c08a4d78931342b37fd5f72900fb998
3087e6f46c4a097d8a1f52c74e28eaf6
P2PKCreates an early P2SH output. It cannot be a P2SH spend: BIP16 activated at 173,805, after this block. It spends P2PK.
247,939315ac7d4c26d69668129cc352851d938
9b4a6868f1509c6c8b66bead11e2619f
P2PKHx2The SIGHASH_SINGLE bug. Input index ≥ output count, so the sighash is the literal value 1. Mined, and must still validate forever.
481,824461e8a4aa0a0e75c06602c505bd7aa06
e7116ba5cd98fd6e046e8cbeb00379d6
P2PKHx2Creates a P2WSH output. In the segwit activation block. Spends two P2PKH inputs — no witness of its own.
481,8248f907925d2ebe48765103e6845c06f1f
2bb77c6adc1cc002865865eb5cfd5c1c
P2SHP2SH-wrapped P2WPKH. scriptSig AND witness both populated, the only shape where both are non-empty.
481,824dfcec48bb8491856c353306ab5febeb7
e99e4d783eedf3de98f3ee0812b92bad
P2SHThe first segwit spend in history. In the activation block itself.
481,824f91d0a8a78462bc59398f2c5d7a84fcf
f491c26ba54c4833478b202796c8aafd
P2WPKHNative P2WPKH spend. Activation block.
550,00073965c0ab96fa518f47df4f3e7201e0a
36f163c4857fc28150d277caa8589259
P2WSHNative P2WSH multisig. Four witness items.
550,0009cf007aa4ed2216c6ca42ba593558cb6
ce4df9c5417677d7ca96a7b2be6d807b
P2SHP2SH-wrapped P2WSH. Four witness items, redeemed through the P2SH wrapper.
550,000bdcb08cd977e229482f2953458934058
82a08132f1675beb844de8548007915f
P2PKHCreates a bare multisig output. Consensus-valid, non-standard to relay today. Spends P2PKH.
750,0004c9fe4ad5923fd41074da3f92da6359c
bafbd96ecbb758481d6c1f106242703e
P2TRTaproot key-path (BIP341). A single witness item. The cheapest spend the chain allows.
800,000965f866bf8623bbf956c1b2aeec1efc1
ad162fd428ab7fb89f128a0754ebbc32
P2TRTaproot script-path (BIP342). With a real 33-byte control block.
850,000b10c0000004da5a9d1d9b4ae32e09f0b
3e62d21a5cce5428d4ad714fb444eb5d
P2PK + P2PKH + P2MS + P2SHx3 + P2WPKH + P2WSH + P2TRx2Seven script types in one transaction. 10 inputs spending P2PK, P2PKH, bare multisig, P2SH×3, P2WPKH, P2WSH and P2TR×2; 9 outputs covering nine types including the P2A anchor and nulldata. The widest vector in the corpus — and the only one that spends bare multisig.

Every txid above is real and on the main chain; each can be looked up with getrawtransaction <txid> against any archival node.



What the corpus actually covers

Counting by the script type each vector spends: P2PKH 7, P2PK 4, P2SH 4, P2TR 3, P2WPKH 2, P2WSH 2, bare multisig 1, anyone-can-spend NOP script 1.

Four vectors are output-shape only. 6f7cf958, 9c08a4d7, bdcb08cd and 461e8a4a are named for a type that appears in their outputs; on the input side they spend ordinary P2PK or P2PKH. They assert that a transaction creating that output is accepted — they do not exercise redemption of it.

Bare multisig redemption rests on a single vector. Two vectors are named "bare multisig" and neither spends one; the only P2MS input in the whole corpus is one of the ten in b10c0000. Drop that transaction and P2MS verification loses all coverage while the corpus still appears to have two vectors for it.

b10c0000 is the most valuable transaction here by a wide margin: ten inputs across seven script types, nine outputs across nine, spanning every consensus era from bare P2PK to the P2A anchor in one 3,500-byte transaction.



Labels that were wrong

Three vectors carried descriptions that did not survive checking the prevouts, now corrected:

  • 9c08a4d7 (170,052) said "an early pay-to-script-hash spend". It spends P2PK. It cannot be a P2SH spend — BIP16 activated at 173,805, after this block. It creates a P2SH output.
  • 6f7cf958 (728) said "early P2PKH". It spends two bare P2PK outputs; P2PKH is the output shape.
  • eb3b82c0 said "h=170060-ish". It is at 163,685, and its second input is an anyone-can-spend PUSH20 <data> OP_NOP2 OP_DROP script — valid because OP_NOP2 was still a NOP at that height.

These were descriptive strings, not assertions, so no test was passing on a false premise — but the report built on them, and a reader would have concluded P2SH redemption was covered from block 170,052 when it is not.

One wanted transaction is not in the corpus

da917699942e4a96272401b534381a75512eeebe8403084500bd637bd47168b3 (h=481,824, an OP_RETURN nulldata output) is in the generator's WANTED list but skipped: its prevouts are unresolvable from the oracle. The list asks for 18; 17 ship.



2. Evidence — two controls, because passing proves nothing on its own

A corpus that accepts everything is indistinguishable from a verifier that accepts everything. Both controls revert something real and confirm the corpus notices.

Control A — wrong height: 2 of 17 rejected.
Verifying every transaction at h=900,000 instead of its own. Both failures are pre-BIP66, refused under modern DERSIG with legacy script verification failed. Height is not decoration.

Control B — DER regression: 8 of 17 rejected.
Removing the leading-zero tolerance from the signature parser. Failures span P2WPKH, P2WSH and legacy paths — the corpus reaches all three verifier arms, not just one.



The first version of this corpus was too weak, and the control proved it

Before the 124,276 vector existed, Control B rejected nothing — all sixteen transactions still passed with the DER tolerance narrowed. The corpus looked thorough and covered that fix not at all.

The tree's own comment named a real mined transaction with a 34-byte r and s. Finding it (fb0a1d8d..., height 124,276) and adding it is what gave the corpus its second set of teeth. Without running the control, a corpus that tested nothing of the sort would have shipped.

One control was itself faulty — stated rather than quietly fixed

The first attempt at Control B narrowed the strip bound from 32 to 33 and was described as reverting the pre-2026-08-19 behaviour. It is not: stripping to 33 bytes still works downstream, so it rejected nothing.

The honest reading is that that specific off-by-one remains uncovered. What the corpus does catch is the wholesale loss of leading-zero tolerance. A gap named is worth more than a gap implied.



Transaction ids, unwrapped

The table above wraps each txid to keep it narrow; here they are whole, for copy-paste.

Code:
    170  f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16
    728  6f7cf9580f1c2dfb3c4d5d043cdbb128c640e3f20161245aa7372e9666168516
 124276  fb0a1d8d34fa5537e461ac384bac761125e1bfa7fec286fa72511240fa66864d
 163685  eb3b82c0884e3efa6d8b0be55b4915eb20be124c9766245bcc7f34fdac32bccb
 164467  60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1
 170052  9c08a4d78931342b37fd5f72900fb9983087e6f46c4a097d8a1f52c74e28eaf6
 247939  315ac7d4c26d69668129cc352851d9389b4a6868f1509c6c8b66bead11e2619f
 481824  461e8a4aa0a0e75c06602c505bd7aa06e7116ba5cd98fd6e046e8cbeb00379d6
 481824  8f907925d2ebe48765103e6845c06f1f2bb77c6adc1cc002865865eb5cfd5c1c
 481824  dfcec48bb8491856c353306ab5febeb7e99e4d783eedf3de98f3ee0812b92bad
 481824  f91d0a8a78462bc59398f2c5d7a84fcff491c26ba54c4833478b202796c8aafd
 550000  73965c0ab96fa518f47df4f3e7201e0a36f163c4857fc28150d277caa8589259
 550000  9cf007aa4ed2216c6ca42ba593558cb6ce4df9c5417677d7ca96a7b2be6d807b
 550000  bdcb08cd977e229482f295345893405882a08132f1675beb844de8548007915f
 750000  4c9fe4ad5923fd41074da3f92da6359cbafbd96ecbb758481d6c1f106242703e
 800000  965f866bf8623bbf956c1b2aeec1efc1ad162fd428ab7fb89f128a0754ebbc32
 850000  b10c0000004da5a9d1d9b4ae32e09f0b3e62d21a5cce5428d4ad714fb444eb5d



3. How it runs

Code:
validation/gen_txaccept_vectors.py   pulls each tx + its spent prevouts from the
                                     oracle (txindex, 965,629 blocks) and freezes
                                     them with the height they were mined at

asm/tests/txaccept_vec.h             17 vectors, 25 KB

asm/tests/test_txaccept_corpus.c     gated; asserts each tx verifies at its own
                                     height, and that EVERY input was resolved

One supporting addition was needed: tx_verify_at_height(), the consensus verifier at a given height driven by a caller-supplied resolver. tx_verify_block_connect needs a live LSM handle; tx_verify_mempool takes a resolver but applies policy flags. Neither shape lets a test judge a historical transaction by its own block's rules.

The resolver hands prevouts back in input order, and the harness asserts every input was resolved — so a verifier that silently skipped one would fail rather than pass with less work done.



17/17 accepted · 68 assertions · eight static audits GREEN · full gate GREEN
Vectors regenerate from the oracle; the corpus is extended by adding a txid and a reason.
Danish Ali
Jr. Member
*
Offline

Activity: 56
Merit: 91


View Profile
Today at 06:28:04 PM
Merited by BobLawblaw (2)
 #13

...
This is a serious issue. This finding on the muhash calculation, which cannot be redone, is of serious concern. It suggests or hints that the claim "byte-identical to Core" was tested only once, in the last run and cannot be re-verified anymore so there is a real gap in trust for the project. Bugs that were discovered (as opposed to obvious crashes!) can be critical. Like silent bugs that can break in more serious situations. Idea of introducing negative testing in the testing process is correct and will catch known bad cases.

Regarding earlier points, I am again asking for commit squashing, stranger handshake and other building issues to solve.
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!