Add BRC-Z: Bitcoin Script to and from Bitcoin BASIC — a compiler and a decompiler - #228
Open
sun-dive wants to merge 1 commit into
Open
Add BRC-Z: Bitcoin Script to and from Bitcoin BASIC — a compiler and a decompiler#228sun-dive wants to merge 1 commit into
sun-dive wants to merge 1 commit into
Conversation
Bitcoin Script is a stack machine with no names and no structure a reader can hold. It is also the machine underneath every infix expression evaluator written for an 8-bit micro: v = v + f/m - v*d becomes the same sequence of stack operations in either. This proposes a BASIC dialect in one-to-one correspondence with the opcode set, and both translations between them. The decompiler is the half without precedent. A compiler reports what an author meant; a decompiler reports what the bytes say, including bytes the reader did not write. That matters because a covenant cannot be amended: a permanent constant sits inside a few thousand opcodes, one edit moves every offset behind it, and what gets verified is a mental model rather than the script — so errors surface after publication and funding, when nothing can change. Normative: 35 words mapped to their opcodes, with = and SAMEBYTES kept distinct because OP_NUMEQUAL and OP_EQUAL disagree about a padded zero; branch arms checked for equal stack shape and emission refused otherwise; FOR unrolled with static bounds; DIM widths bounded 1..75, above which OP_PUSHDATA1 shifts every offset after the field; a construct with no opcode refused with a reason rather than approximated; and a decompiler that reads scripts it did not produce, modifies nothing, and reports loss of stack tracking rather than guessing. It sits above BRC-15 and BRC-106 rather than competing with them. Those operate at one token per opcode and recover no structure; this operates on sequences and recovers expressions, blocks and named state, so it is lossy in spelling and exact in behaviour. The layers compose. Four examples are given in both languages, including the same Rule 110 source compiled with the loop in the script and with the loop in the chain, arriving at the same state. On Turing completeness the document states the distinction carefully: a single script is total, a script iterates perfectly well, and what it cannot do is run an unknown number of times. The chain does not supply the looping — it supplies the not knowing when to stop. A timestamp server has no unbounded time to offer a computation that will never finish. The implementation is linked for use and published on chain for permanence; the archive recovered from that transaction was unpacked and its tests run. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request:
Proposes a new standard by creating a new markdown file in the appropriate directory and requests discussion and assignment of a BRC number
Summary
Bitcoin Script is a stack machine with no names, no types and no structure a reader can hold. It is also, almost exactly, the machine underneath every infix expression evaluator written for an 8-bit microcomputer:
v = v + f/m - v*dbecomes the same sequence of stack operations in either.This proposes Bitcoin BASIC — a BASIC dialect in one-to-one correspondence with the opcode set — and both translations between it and Script: a compiler, and a decompiler that renders a deployed locking script back into readable form.
The decompiler is the half without precedent. A compiler reports what an author meant; a decompiler reports what the bytes say, including bytes the reader did not write, fetched from the chain, belonging to somebody else.
That matters because a covenant cannot be amended. A permanent constant sits somewhere inside a few thousand opcodes, one edit moves every offset and depth behind it, and what gets verified in practice is a mental model of the script rather than the script — so errors surface after publication and funding, when nothing can be changed.
Relationship to BRC-15 and BRC-106
This sits above the existing representations rather than competing with them, and the document says so explicitly.
BRC-15 and BRC-106 operate at one token per opcode: lossless, exact opcode sequence, and no structure recovered.
OP_ADDstates that an addition occurs; it does not state that a line readsv = v + f/m - v*d, nor which bytes of a script are its mutable state.Bitcoin BASIC operates on sequences of opcodes and recovers structure — expressions, conditional blocks, named state fields, loop bodies where the loop survives in the script. It is therefore lossy in spelling and exact in behaviour. The layers compose: Bitcoin BASIC to Script, and Script to ASM under BRC-15 or BRC-106.
Normative content, briefly
=andSAMEBYTESMUST stay distinct:OP_NUMEQUALcompares numbers andOP_EQUALcompares byte strings, and0,-0and a padded zero are one number and three different byte strings.FORMUST be unrolled with static bounds and a bounded expansion; Script has no backward jump for a loop to compile to.DIMwidths are the widths carried, bounded 1–75, above whichOP_PUSHDATA1adds a length byte and shifts every offset after the field.^folds at compile time and fails if either side is unknown until the script runs.Examples and evidence
Four examples are given in both languages — an expression and a balanced conditional with their emitted opcodes in hex, noughts and crosses indexing by modular arithmetic in the absence of arrays, and Rule 110 compiled from one source with the loop in the script and with the loop in the chain, arriving at the same state.
On Turing completeness the document is deliberately careful. A single script is total. But a script iterates perfectly well — Rule 110 advances thirty-one cells per generation, unrolled, inside one script. What it cannot do is run an unknown number of times, and that is the only thing the chain is needed for: the chain does not supply the looping, it supplies the not knowing when to stop. The qualification is stated as the tape rather than the loop, since the deployed instance carries 31 cells.
Implementation
To use it: https://grafverse.com/basic.html — compiles, decompiles, and reads a script off the chain, with no installation and no build step.
To verify it, or to have it outlast this document: the archive is published on chain, so the reference implementation is a payload rather than a link.
The archive was recovered from that transaction, unpacked, and its three test suites run — 42/42, 18/18 and 10/10 — so verification is reproducible from the txid alone. The compiler and decompiler import only an opcode-number table and a type that erases at runtime: an implementation in another language needs a list of opcode numbers and nothing more.
Filed as BRC-Z for number assignment.