Before you paste anything
Every check on this page runs in your browser. Nothing you type is sent anywhere, and there is no form submission, no analytics, and no third-party script. The page's content security policy restricts connections to this origin, and the only request it makes is a read of vectors/generated/golden.json from this same site, used for the self test at the bottom.
This is a protocol inspection tool. It does not build, sign, or broadcast Bitcoin transactions, and it never asks for a private key. Paste public keys and marker scripts only.
The main tool
Do these two records form a pair?
Paste a marker script into each side. Side A is the predecessor, side B is the proposed successor. Each half is first checked on its own, then the two are checked against each other. A half that is malformed can never pair, and two well-formed halves can still fail to belong together.
Record pair
Accepts a full marker script starting with 6a, or a bare payload starting with 544e444d.
The record that already exists on chain.
The record that claims to follow it.
Paste a marker into each side, or load the published vectors below.
How to read a failure
Every failing line names the rule it enforces and the stable reason a conforming parser emits. Those reasons are not advisory labels. Rule INV-3 requires an implementation to return the lowest failing code, so if you are writing tests, the reason shown for the first structural failure is the one your implementation must produce.
| Symptom | Rule | Reason emitted |
|---|---|---|
| Non-minimal push, wrong payload length, trailing bytes | REC-6 | BAD_MARKER_ENCODING_OR_LENGTH |
Marker format byte other than 0x01 | REC-7 | UNKNOWN_MARKER_FORMAT |
| Network byte disagrees between the halves | ID-3 | WRONG_NETWORK |
| Namespace field disagrees between the halves | ID-5 | WRONG_NAMESPACE |
| Successor sequence is not predecessor plus one | PAIR-5 | BAD_STATE_SEQUENCE |
| Successor claims to follow a terminal record | ST-3 | PREDECESSOR_NOT_ACTIVE |
| MARK chapter commitment is all zero | REC-8 | BAD_COMMITMENT |
The other pair
Do these two keys form a carrier?
The record pair above is the protocol layer. This is the Bitcoin layer underneath it. Two compressed public keys determine one carrier address completely, and the sort order decides which key is side A.
Carrier pair
Compressed secp256k1 public keys only, 33 bytes each. Never paste a private key into any web page.
Order does not matter here. The tool sorts and tells you.
Both keys must be valid points, and they must differ.
Paste a compressed public key into each side.
The curve check is real. The tool tests that the x coordinate lies in the field and that
x³ + 7 is a quadratic residue, so a 33-byte string with a plausible
prefix but no corresponding point is rejected rather than accepted. That is the
difference between rule PAIR-1 and a length check.
Identity
Derive a namespace and an object key
Rules ID-5 and ID-6 are pure functions of the binding. Change any input and every downstream value changes with it, which is exactly why an alternate INIT is a different protocol rather than a different deployment.
Binding derivation
Transaction identifiers are entered in display order, the way Bitcoin Core shows them. The tool reverses them once for you.
The network byte is part of the commitment, so the same INIT on two chains gives two namespaces.
SHA256 of tandem.md as raw bytes.
Leave empty to derive the namespace alone.
The values prefilled above are the ones the published corpus uses, so on first load this
panel should reproduce
38025b6fb909d2f22226ee9ea7e3a0e895c589792a93393c136ad502c608d221 and
5e355bac07710f3bc3b271902b8deda97c52893518bf9bac8a080c318659cb52 exactly.
If it does not, something is wrong and you should not trust the rest of this page.
Proof that the tool is honest
Vector self test
A verifier you cannot audit is just an assertion. On load, this page runs its own rules against the repository's published golden corpus, rehashes every published preimage, and rebuilds both Merkle roots from their leaves. The results are below, computed in your browser at page load.
Loading the published corpus.
tandem.md section 13.2 states the event-leaf preimage is 374 bytes with a 16-byte domain tag. The measurement above, taken from the published preimages themselves, is 371 bytes: a 13-byte domain tag plus the 358 field bytes the same sentence correctly states. The independent Rust verifier asserts 371 at the same point. This is documented as erratum 1 rather than quietly worked around.
Honesty
What this tool does not check
The panels above take markers and keys. They do not take transactions, and they have no view of the chain. That rules out a large part of validation, and pretending otherwise would be worse than useless.
| Not checked here | Why | Where it is checked |
|---|---|---|
| Signatures, DER encoding, low-S, sighash type | Needs the full transaction and its prevout amounts | The Rust verifier's service boundary, see the verifier page |
| Input and output counts, roles, and sequences | Needs the transaction, not the marker | Rules OP-1 to OP-6 |
| Fee positivity and the exact split | Needs input and output values | Rule PAIR-3.3 |
| Whether a predecessor is actually active | Needs indexed chain state at a height | Indexer semantics |
| Confirmation provenance, that prevouts confirmed in an earlier block | Needs block heights | Rule OP-6 note, tandem.md section 5.3 |
| Whether a MARK reproduces the predecessor carrier script | Needs both transactions | Rule PAIR-6 |
| Chapter and close manifest content | Content availability is never validity | JSON Schema reference |
A passing verdict here means the two halves are consistent with each other as far as their markers can express. It is a necessary condition, never a sufficient one. Do not treat it as a statement about a real transaction on a real chain.