Decentralisation series · BSV, standards & engineering
When two BSV
implementations disagree.
An independent implementation becomes useful at precisely the moment it produces an inconvenient result. The question is whether we investigate the disagreement or ask its author to use the approved library.
It is easy to favour competition while every competitor returns the same answer. The more revealing occasion is a failure report: a request that one wallet accepts and another rejects, a certificate that one parser reads and another cannot, or a transaction whose reported status changes according to the service being asked.
Someone will suggest that the newcomer should stop making trouble and copy the established implementation. Sometimes copying a well-tested component is sensible engineering. As a general answer to disagreement, however, it leaves us with an awkward definition of independence. You may write your own software, provided it cannot tell us anything the incumbent does not already believe.
My argument for BSV is more demanding. Keep the underlying validity rules dependable. Let developers choose their application architectures and adopt useful standards voluntarily. When implementations disagree, require an explanation that another engineer can reproduce. Then attach the correction to the layer that actually failed. A documentation error, a local policy choice and a transaction-validation defect require different repairs.
This follows the argument in A Standard Is an Invitation, Not a Throne, but takes up a narrower question: who supplies the evidence when two implementations both claim to be right?
1. Locate the disagreement before judging it
The BSV protocol reference defines its subject around the rules determining transaction and block validity. It separates that subject from wallets, transport, RPC interfaces and configurable miner policy. The reference also records upgrade history and the block heights at which rules apply. A careful historical test therefore identifies its validation context rather than applying an undated description to every old transaction.
The associated policy-versus-consensus notes distinguish validity from a node's relay or mining choices. A transaction rejected under one operator's local policy can still satisfy the validity rules. That does not promise that another operator will accept it, or that a particular service will relay it at the offered fee.
These distinctions prevent an ordinary business refusal from being promoted into a constitutional crisis. A service may decline a workload it cannot support. A wallet may omit an optional integration. A commercial operator may set prices. Those choices should be stated honestly; none should be described as a new base rule merely because the operator would find universal adoption convenient.
For an investigation, I would begin with four questions:
- Validity: do the parties disagree about a fully specified transaction or block under the applicable BSV rules and state?
- Interface: do they disagree about the meaning or encoding of a request under a particular voluntary specification?
- Policy: do they understand the request identically but make different documented admission or service decisions?
- Operation: did the requested work fail, remain pending, or complete without its reply reaching the caller?
This is a proposed diagnostic classification, not an additional BSV standard. Its purpose is to stop four different arguments being conducted under the same error message. A system that reports all four as “invalid” has thrown away information its customers and engineers need.
2. A document can be wrong without the foundation moving
A concrete example appeared on 29 October 2026. The BRC repository merged pull request 356, a correction to the Certificate Struct table in the BSV BRC-100 wallet interface. The merged diff puts serialNumber before subject, specifies fixed 32-byte decoded values for type and serialNumber, and places the signature after the fields without a length prefix.
The pull request describes the change as aligning the document with existing wire behaviour, not changing implementations. It cites specific implementation locations and reports that a reader following the previous table could fail on existing certificate frames. Those are the contributor's account and supporting references; I have inspected the public change, not independently executed the cited implementations. The change concerns a wallet-interface certificate representation, not BSV transaction-validity rules.
The useful lesson is the method. “The document says so” and “our software works” are each incomplete answers when the document and the software appear to disagree. An implementer needs the exact document revision, the actual bytes, the parsing result and the reason for preferring one interpretation. A correction can then be evaluated without converting the reputation of a maintainer into a substitute for evidence.
Nor should this example become an excuse to follow every incumbent accident forever. Sometimes deployed behaviour is a bug. Sometimes prose is ambiguous. Sometimes a proposed correction would introduce an incompatible change rather than clarify the existing interface. Those cases must be distinguished, with affected users and implementations identified.
The BRC repository guidance says substantial revisions should receive a new standard rather than disrupt existing implementations. It also asks readers to examine status notes and the relevant normative documents, rather than assume that a later number alone settles precedence. That is a useful discipline for voluntary coordination. It provides a way to describe change without pretending that every application must join it.
3. Make the failure portable
A disagreement is much easier to resolve when it can leave the original developer's laptop. “It fails on my machine” is a beginning. A small, public case that another implementation can replay is an engineering asset.
For a proposed conformance case, I would publish the input bytes or request, the relevant specification revision and section, the expected result, and the reasoning connecting the two. Where state matters, the package must include enough non-secret state to reproduce the result. Record dependency versions, configuration and the point at which an external service enters the experiment. Remove credentials and customer information rather than treating disclosure as the price of credibility.
Begin with something deliberately small. The BSV transaction reference specifies CompactSize count and length prefixes. Four boundary examples for an encoder are:
252 → fc253 → fd fd 0065,535 → fd ff ff65,536 → fe 00 00 01 00
The values are decimal and the byte sequences hexadecimal. They illustrate the transition between encoding widths and the little-endian payload. They are not complete transactions, spendable outputs, or evidence that any wallet has passed a conformance suite. They say nothing by themselves about script execution, available inputs or block acceptance.
The smallness is useful. If two encoders disagree here, we do not need a production payment or an argument about an entire architecture to begin the investigation. We can identify the first differing byte. If they agree here but fail on a larger object, we have eliminated one possible explanation without declaring the system correct.
Then add negative and incomplete cases to the relevant component's tests: truncated data, an impossible declared length, an unexpected field, and a request made without the required authority. Each expected result needs its own basis. Do not assume that every component must reject the same input at the same stage. A streaming decoder awaiting more bytes and a parser told that the input is complete are answering different questions.
The published evidence should include what was not tested. Four arithmetic examples are four arithmetic examples. A successful serializer round trip is a serializer result. Neither should be sold as a security audit, a full wallet evaluation, or a proof of network-wide agreement.
4. Choose the right equality
Differential testing compares implementations, but a comparison needs a definition of agreement. Sometimes the correct comparison is byte-for-byte identity. Sometimes it is a decoded value. Sometimes it is a permitted state transition or a refusal that leaves protected state unchanged.
Suppose a test begins with a fixed object and a fully specified canonical encoding. Comparing the encoded bytes is sensible. Suppose instead that two wallets are asked to construct a payment and may choose different eligible inputs or different change arrangements. Different transaction bytes do not, by themselves, identify a defect. The experiment must control the permitted choices or compare the obligations the request actually imposes.
This is a methodological example, not a report about a particular wallet. The error it exposes is common in test design: requiring identity where the contract allows choice, then treating the exercise of that choice as non-conformance.
The converse is equally dangerous. Two interfaces may display the same reassuring word while describing different states. “Accepted” could refer to a local request, a provider's processing queue or a network observation. A test that compares only the displayed word can certify agreement by ignoring the event the customer cares about.
Specify the observation before collecting it. If the claim concerns a parser, record the decoded structure and consumed bytes. If it concerns authorisation, record the permitted and refused transitions. If it concerns submission, record the submission boundary and the remaining uncertainty. An unobserved result should remain unobserved, however attractive a green indicator might look on the demonstration screen.
A good comparison is demanding in the right place. It does not require identical internals. It requires evidence that each implementation honours the promise it claims to make.
5. Agreement is not a vote on the rules
Three implementations returning one answer and a fourth returning another establishes a disagreement. It does not establish which answer is correct. All three may share a parser, a test fixture, a copied assumption or the same undocumented behaviour. Counting brand names is a poor substitute for examining dependencies.
Independence has several dimensions. Teams can be separately managed while using the same library. Code can be separately written while following the same mistaken example. A test oracle can contain the defect that every tested implementation has learned to reproduce. An honest comparison should say where independence exists and where it does not.
Shared components are not inherently a problem. They can reduce cost and improve maintenance. The problem is claiming four independent confirmations when the relevant decision was made once and copied four times.
The response to a mismatch should therefore be a reasoned disposition: incorrect expectation, implementation defect, documentation ambiguity, unsupported feature, differing policy, or insufficient evidence. Preserve the failing input and the explanation. If the disagreement concerns the base rules, investigate it against the applicable validity contract and its pinned implementation evidence; a popularity poll among application vendors cannot repair it.
This also limits the authority of the person operating the test suite. A test maintainer should explain why a case has its expected answer and accept corrections to the suite itself. Otherwise the conformance service quietly becomes another gatekeeper, with the specification serving as decoration behind its desk.
Publish the cases under terms that permit independent use. Let others run them without purchasing approval from their author. A standard is more credible when an implementer can discover a mistake in its tests without first asking the test operator for permission to disagree.
6. Assign the repair, and keep the customer informed
Technical openness does not make responsibility collective and therefore unlocatable. The business operating a wallet or service chose its dependencies, made claims to users and accepted particular work. When something fails, the customer needs an accountable response from that business, not a tour of the project's organisational chart.
I would expect an incident account to separate five things: what was promised, which observations are established, what remains uncertain, the immediate protection for affected users, and the correction with its regression test. Where a dependency is responsible for the defect, identify it. That explanation informs the repair; it does not make the customer's problem disappear.
A provider may reasonably stop accepting a risky class of new work while investigating. It should explain the restriction and distinguish it from a change to BSV's base rules. Another provider may be able to support the same work safely. Preserving room for that difference is one of the practical benefits of competition.
Voluntary standards impose real discipline on those who claim to implement them. A company cannot advertise compatibility, fail the relevant contract and then invoke experimentation as immunity from criticism. Equally, declining a voluntary interface does not excuse an unsupported accusation that an alternative violates the base protocol. State the claim accurately and bring the evidence that belongs to it.
The correction should be proportionate. Repair a parser at the parser. Clarify a table at the table. Explain a service policy as a service policy. Do not redesign the foundation merely to protect one implementation from the consequences of its own assumptions.
7. Leave a reproducible answer
The measure of decentralised engineering is not how many projects repeat a statement of independence. It is whether a new participant can implement a defined boundary, discover a disagreement, publish the evidence and obtain a reasoned answer without surrendering the right to build differently.
That requires stable base rules, useful voluntary conventions and people willing to take responsibility for the products they operate. It also requires the modest discipline of keeping a failing input after the argument has ended.
A resolved disagreement can leave something valuable: a more precise specification, a corrected implementation, a documented policy boundary, or a test that prevents the same defect returning. A suppressed disagreement leaves a quieter discussion and an unchanged risk.
I would rather have the awkward test case. Make it small enough to inspect, complete enough to reproduce and open enough for the next implementation to use. Then fix what it shows. That is a better contribution to BSV than asking every independent developer to become an enthusiastic customer of the same answer.