btcvm 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- btcvm-0.1.0/LICENSE +21 -0
- btcvm-0.1.0/PKG-INFO +422 -0
- btcvm-0.1.0/README.md +398 -0
- btcvm-0.1.0/asm.py +116 -0
- btcvm-0.1.0/broadcast.py +84 -0
- btcvm-0.1.0/btcvm.egg-info/PKG-INFO +422 -0
- btcvm-0.1.0/btcvm.egg-info/SOURCES.txt +21 -0
- btcvm-0.1.0/btcvm.egg-info/dependency_links.txt +1 -0
- btcvm-0.1.0/btcvm.egg-info/entry_points.txt +3 -0
- btcvm-0.1.0/btcvm.egg-info/requires.txt +8 -0
- btcvm-0.1.0/btcvm.egg-info/top_level.txt +12 -0
- btcvm-0.1.0/clock.py +44 -0
- btcvm-0.1.0/fleet.py +121 -0
- btcvm-0.1.0/imgfs.py +591 -0
- btcvm-0.1.0/main.py +387 -0
- btcvm-0.1.0/ott.py +3779 -0
- btcvm-0.1.0/programs.py +3 -0
- btcvm-0.1.0/pyproject.toml +56 -0
- btcvm-0.1.0/setup.cfg +4 -0
- btcvm-0.1.0/trace.py +109 -0
- btcvm-0.1.0/vdf.py +65 -0
- btcvm-0.1.0/verify.py +245 -0
- btcvm-0.1.0/vm.py +88 -0
btcvm-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ryan Scarbery
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
btcvm-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: btcvm
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A minimal register machine that executes in lockstep with Bitcoin blocks
|
|
5
|
+
License: MIT
|
|
6
|
+
Keywords: bitcoin,register-machine,vm,blockchain,vdf,cryptography
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Classifier: Topic :: Security :: Cryptography
|
|
13
|
+
Classifier: Topic :: System :: Emulators
|
|
14
|
+
Requires-Python: >=3.11
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
19
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
20
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
21
|
+
Provides-Extra: s3
|
|
22
|
+
Requires-Dist: boto3>=1.34; extra == "s3"
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# btcvm
|
|
26
|
+
|
|
27
|
+
A minimal register machine that executes in lockstep with Bitcoin blocks.
|
|
28
|
+
|
|
29
|
+
Each Bitcoin block triggers a fixed number of VM cycles. After each block, the VM's state is hashed and cryptographically bound to the block hash — producing a verifiable ledger of computation anchored to Bitcoin's clock.
|
|
30
|
+
|
|
31
|
+
## Why
|
|
32
|
+
|
|
33
|
+
Bitcoin is a clock. Every ~10 minutes a new block is mined, and its hash is unpredictable until the moment it's found. This makes it a natural source of consensus timing for off-chain computation.
|
|
34
|
+
|
|
35
|
+
`btcvm` demonstrates the minimal architecture for a Bitcoin-clocked state machine:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
Bitcoin block hash
|
|
39
|
+
↓
|
|
40
|
+
VM executes N cycles
|
|
41
|
+
↓
|
|
42
|
+
commitment = SHA256(block_hash + state_hash)
|
|
43
|
+
↓
|
|
44
|
+
OP_RETURN → committed to Bitcoin (optional)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The resulting ledger is independently verifiable: anyone with the block hashes (publicly available from any Bitcoin node or API) can recompute every commitment and confirm the VM ran exactly as recorded.
|
|
48
|
+
|
|
49
|
+
## Files
|
|
50
|
+
|
|
51
|
+
| File | Description |
|
|
52
|
+
|------|-------------|
|
|
53
|
+
| `vm.py` | Minimal register machine (8 registers, 7 opcodes) |
|
|
54
|
+
| `clock.py` | Bitcoin block clock via blockstream.info API |
|
|
55
|
+
| `programs.py` | Sample programs (fibonacci, countdown) |
|
|
56
|
+
| `vdf.py` | VDF sub-clock — sequential SHA256 chain with tick/verify (v1.2) |
|
|
57
|
+
| `trace.py` | Step-by-step execution trace with Merkle root commitment (v2) |
|
|
58
|
+
| `fleet.py` | N parallel VMs with fleet Merkle root — one OP_RETURN anchors all (v3) |
|
|
59
|
+
| `broadcast.py` | Optional OP_RETURN broadcast via the `bit` library |
|
|
60
|
+
| `main.py` | Orchestrator — runs clock loop, executes VM(s), writes ledger |
|
|
61
|
+
| `verify.py` | Verifies ledger, VDF chain, trace, and fleet Merkle against Bitcoin |
|
|
62
|
+
| `ott.py` | Bitcoin-anchored media archive — images, video, and git repos; also an interactive shell |
|
|
63
|
+
| `test_vm.py` | Unit tests (VM, VDF, trace, fleet) |
|
|
64
|
+
| `test_ott_completion.py` | Unit tests (ott shell tab completion, path handling) |
|
|
65
|
+
| `Makefile` | Common tasks: install, test, lint, run, ott |
|
|
66
|
+
| `completions/` | Bash and Zsh tab completions for `btcvm` and `ott` |
|
|
67
|
+
|
|
68
|
+
## VM
|
|
69
|
+
|
|
70
|
+
The VM has 8 registers (`R0`–`R7`) and 7 opcodes:
|
|
71
|
+
|
|
72
|
+
| Opcode | Description |
|
|
73
|
+
|--------|-------------|
|
|
74
|
+
| `LOAD r, val` | Load immediate value into register |
|
|
75
|
+
| `ADD dst, a, b` | `Rdst = Ra + Rb` |
|
|
76
|
+
| `SUB dst, a, b` | `Rdst = Ra - Rb` |
|
|
77
|
+
| `MUL dst, a, b` | `Rdst = Ra * Rb` |
|
|
78
|
+
| `JMP addr` | Unconditional jump |
|
|
79
|
+
| `JZ r, addr` | Jump if register is zero |
|
|
80
|
+
| `HALT` | Stop execution |
|
|
81
|
+
|
|
82
|
+
Programs are tuples loaded into memory. See `programs.py` for examples.
|
|
83
|
+
|
|
84
|
+
## Usage
|
|
85
|
+
|
|
86
|
+
**Requirements:** Python 3.11+, no runtime dependencies (stdlib only).
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# Install
|
|
90
|
+
pip install -e . # editable install
|
|
91
|
+
make install # same via Makefile
|
|
92
|
+
make dev # with dev deps (pytest, ruff)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### btcvm clock
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# v1 — one entry per Bitcoin block
|
|
99
|
+
python3 main.py fibonacci
|
|
100
|
+
|
|
101
|
+
# v1.2 — VDF sub-clock: 5 ticks per block
|
|
102
|
+
python3 main.py fibonacci --vdf-ticks 5
|
|
103
|
+
|
|
104
|
+
# v2 — trace Merkle root replaces state_hash
|
|
105
|
+
python3 main.py fibonacci --trace
|
|
106
|
+
|
|
107
|
+
# v3 — fleet of 4 parallel VMs, single fleet root per OP_RETURN
|
|
108
|
+
python3 main.py fibonacci --vms 4
|
|
109
|
+
|
|
110
|
+
# Everything combined
|
|
111
|
+
python3 main.py fibonacci --vms 4 --vdf-ticks 3 --trace
|
|
112
|
+
|
|
113
|
+
# Optional: broadcast commitment as OP_RETURN
|
|
114
|
+
pip install bit
|
|
115
|
+
python3 main.py fibonacci --broadcast --wif <your-WIF-key> --network mainnet
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**Getting a wallet for broadcast:**
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
from bit import PrivateKey
|
|
122
|
+
k = PrivateKey()
|
|
123
|
+
print(k.to_wif(), k.address)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Fund the address with ~5000 sats (covers ~8 commitments at low fee rates).
|
|
127
|
+
|
|
128
|
+
**Verifying a ledger:**
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
python3 verify.py # block hashes + commitments
|
|
132
|
+
python3 verify.py --trace-file trace.jsonl # include trace verification
|
|
133
|
+
python3 verify.py --check-txs # also fetch block tx lists
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### ott — Bitcoin-anchored media archive
|
|
137
|
+
|
|
138
|
+
`ott` stores images and video in a content-addressed Merkle tree and commits
|
|
139
|
+
the root to Bitcoin via the btcvm ledger. Images are hashed whole; video files
|
|
140
|
+
are split into 256 KB chunks with a per-file Merkle tree, enabling byte-range
|
|
141
|
+
inclusion proofs.
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
image.jpg → SHA256 ──────────────────────────────────┐
|
|
145
|
+
├─→ global root → Bitcoin
|
|
146
|
+
video.mp4 → [chunk₀, chunk₁, …, chunkₙ] → file root ┘
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# Stage files (images or video — detected by extension). Hashed now — that's
|
|
151
|
+
# what identifies the file and catches duplicates — but not yet copied into
|
|
152
|
+
# object storage or written to the manifest.
|
|
153
|
+
python3 ott.py add photo.jpg family.jpg video.mp4
|
|
154
|
+
|
|
155
|
+
# Show what's staged vs. already archived, and the current Merkle root
|
|
156
|
+
python3 ott.py status
|
|
157
|
+
|
|
158
|
+
# Changed your mind about a staged file? Drop it before it's archived.
|
|
159
|
+
# (Only works pre-commit — once a file's archived, rm can't touch it.)
|
|
160
|
+
python3 ott.py rm family.jpg
|
|
161
|
+
|
|
162
|
+
# Archive everything staged, then commit the Merkle root to the btcvm
|
|
163
|
+
# ledger (sync is a plain alias for commit — same thing, either name)
|
|
164
|
+
python3 ott.py commit
|
|
165
|
+
|
|
166
|
+
# List all archived files
|
|
167
|
+
python3 ott.py list
|
|
168
|
+
|
|
169
|
+
# Generate a wallet key, then anchor the commitment on-chain (optional)
|
|
170
|
+
python3 ott.py keygen --network testnet
|
|
171
|
+
python3 ott.py broadcast --wif <WIF_KEY>
|
|
172
|
+
|
|
173
|
+
# Verify a file is in the archive (Merkle inclusion proof)
|
|
174
|
+
python3 ott.py verify photo.jpg
|
|
175
|
+
|
|
176
|
+
# Prove a specific 256 KB chunk of a video is in the archive
|
|
177
|
+
python3 ott.py verify-chunk video.mp4 3
|
|
178
|
+
|
|
179
|
+
# Verify every ledger commit against real Bitcoin, not just internal state
|
|
180
|
+
python3 ott.py verify-chain
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Interactive shell:**
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
python3 ott.py # or: python3 ott.py shell
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
The shell wraps the same archive with a stateful `cd`-able hierarchy, tab
|
|
190
|
+
completion on every command (archive names, tags, local paths), and a few
|
|
191
|
+
things the flat CLI doesn't have:
|
|
192
|
+
|
|
193
|
+
| Command | Description |
|
|
194
|
+
|---|---|
|
|
195
|
+
| `add [-r] <file>...` | Stage files (git-index style) — hashed now, archived on `commit`/`sync` |
|
|
196
|
+
| `rm <name_or_hash>` | Unstage a pending `add`; refuses once a file's actually committed |
|
|
197
|
+
| `commit` / `sync` | Archive everything staged, then commit the Merkle root to the ledger (same action, either name) |
|
|
198
|
+
| `l [-a] [-t tag] [-b] [dir]` | One-level `ls`-style view of the archive hierarchy (from `orig_path`) |
|
|
199
|
+
| `tree [-a] [-t tag] [-dN] [-b] [dir]` | Recursive tree view; `-d0` for unlimited depth |
|
|
200
|
+
| `cd`, `pwd` | Navigate the *archive* hierarchy (real filesystem nav is `lcd`/`lpwd`) — `cd`'ing to a repo's name instead jumps the real filesystem cwd to that repo's checkout, since repos have no virtual file tree of their own |
|
|
201
|
+
| `list` / `ls [pattern]` | Full flat dump of every path in one table, optionally filtered by regex (bare or `/slash-delimited/`) |
|
|
202
|
+
| `open <name_or_hash>` (alias `o`) | Open an archived file with the OS default handler (prefers the live copy, falls back to the archived one) |
|
|
203
|
+
| `mv <name> <new_path>` | Update an entry's tracked path; moves into an existing dir like real `mv` |
|
|
204
|
+
| `reindex [root]` | One indexed filesystem scan — relocates every stale entry and re-anchors `orig_path` to the archive root |
|
|
205
|
+
| `tag <add\|rm\|list> <pattern> <tagname>` | Bulk-tag entries by regex match against their archive path |
|
|
206
|
+
| `repo <add\|list\|verify\|update\|outdated\|update-all\|tag\|verify-tag\|qr>` | Track a git repo's HEAD and (optionally) a GPG-signed release tag in the archive; `outdated` (alias `o`) checks every tracked repo against its remote, `update-all` (alias `ua`) pulls all of them |
|
|
207
|
+
| `backfill [--workers N]` | Store archive copies for entries on disk but not yet uploaded to the active backend — also the migration path when switching backends (e.g. local → S3). N concurrent (default 8, or `OTT_BACKFILL_WORKERS`); live progress bar on a TTY, one line per file when piped |
|
|
208
|
+
| `verify-objects [--workers N]` | Audit every archived entry against the active backend (existence + size) — for S3 this always queries the bucket directly, bypassing the local cache, so it's the real answer to "did this actually upload" |
|
|
209
|
+
| `bump-fee --wif <WIF> [--fee SAT_PER_VBYTE] [--network testnet\|mainnet]` | CPFP fee bump for a stuck `broadcast` tx — spends the pending change output at a higher fee so miners confirm both together (not RBF). Default 10 sat/vbyte |
|
|
210
|
+
| `verify-chain [-c]` | Verify every ledger commit against real Bitcoin (refetches each block's actual hash) — `-c` also checks the OP_RETURN landed |
|
|
211
|
+
| `keygen [--network]` | Generate a wallet key for `broadcast` (prints WIF + a QR of the address only, never the key) |
|
|
212
|
+
| `broadcast [--wif]` | Broadcast a commitment as a Bitcoin OP_RETURN tx |
|
|
213
|
+
| `qr [hash\|file]` | QR code for a hash, a file's SHA256, or the current Merkle root |
|
|
214
|
+
| `!<cmd>` | Run a real shell command without leaving the shell |
|
|
215
|
+
|
|
216
|
+
Entries missing at their last known path are hidden by default in `l`/`tree`
|
|
217
|
+
(`-a` shows them); `ott reindex` is the real fix.
|
|
218
|
+
|
|
219
|
+
`add` only stages — nothing's copied into object storage or written to the
|
|
220
|
+
manifest until `commit`/`sync`. Names/hashes resolve relative to the current
|
|
221
|
+
archive directory first (`cd`-aware), only falling back to a global search
|
|
222
|
+
if nothing matches locally.
|
|
223
|
+
|
|
224
|
+
**Via Makefile:**
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
make add FILE=photo.jpg
|
|
228
|
+
make verify-file FILE=photo.jpg
|
|
229
|
+
make ott-status
|
|
230
|
+
make ott-list
|
|
231
|
+
make ott-commit
|
|
232
|
+
make ott-clean # remove manifest + ledger
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
**Environment variables:**
|
|
236
|
+
|
|
237
|
+
| Variable | Default | Description |
|
|
238
|
+
|---|---|---|
|
|
239
|
+
| `OTT_MANIFEST` | `ott_manifest.jsonl` | Manifest path |
|
|
240
|
+
| `OTT_LEDGER` | `ott_ledger.jsonl` | Ledger path |
|
|
241
|
+
| `OTT_CHUNK_BYTES` | `262144` (256 KB) | Video chunk size |
|
|
242
|
+
| `OTT_HOME` | `~/.ott` | Archive root when not using a local `.ott/` dir |
|
|
243
|
+
| `OTT_BACKEND` | `local` | Storage backend — `local` or `s3` (needs `pip install btcvm[s3]`) |
|
|
244
|
+
| `OTT_S3_BUCKET` | — | Required when `OTT_BACKEND=s3` |
|
|
245
|
+
| `OTT_S3_PREFIX` | `''` | Optional key prefix within the bucket |
|
|
246
|
+
| `OTT_S3_CACHE_DIR` | `.ott/cache` | Local cache dir for S3-backed objects |
|
|
247
|
+
| `OTT_BACKFILL_WORKERS` | `8` | Default concurrency for `backfill`/`verify-objects` |
|
|
248
|
+
|
|
249
|
+
**Proof chain for a video chunk:**
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
chunk N bytes → SHA256 → chunk hash
|
|
253
|
+
↓ Merkle proof (steps: log₂ chunks)
|
|
254
|
+
file root (= global leaf)
|
|
255
|
+
↓ Merkle proof (steps: log₂ files)
|
|
256
|
+
global root → committed to Bitcoin
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
`verify-chunk` outputs all three levels: bytes-on-disk match, per-file proof, global proof.
|
|
260
|
+
|
|
261
|
+
## Architecture
|
|
262
|
+
|
|
263
|
+
### VDF sub-clock (v1.2)
|
|
264
|
+
|
|
265
|
+
Between Bitcoin blocks the VM fires once per VDF tick. Each tick is `STEPS_PER_TICK` sequential SHA256 evaluations seeded from the previous tick's output. Because SHA256 can't be parallelised in this chained form, the ticks represent a minimum sequential cost any verifier must replay.
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
Bitcoin block hash B_h
|
|
269
|
+
tick 0: SHA256ᴺ(B_h) → vdf₀ → VM cycles → commit₀
|
|
270
|
+
tick 1: SHA256ᴺ(vdf₀) → vdf₁ → VM cycles → commit₁
|
|
271
|
+
…
|
|
272
|
+
Next block B_{h+1} reseeds the chain
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Trace commitment (v2)
|
|
276
|
+
|
|
277
|
+
Every VM step is recorded as a hash-chained entry:
|
|
278
|
+
`step_hash = SHA256(prev_hash ‖ pc ‖ op ‖ regs_before ‖ regs_after)`.
|
|
279
|
+
A binary Merkle tree over all step hashes produces a single root that
|
|
280
|
+
replaces `state_hash` in the ledger commitment. Any individual step can
|
|
281
|
+
be verified without replaying the full execution. The trace file is
|
|
282
|
+
the witness a ZK prover (RISC Zero, SP1, Cairo) would consume.
|
|
283
|
+
|
|
284
|
+
### Fleet Merkle root (v3)
|
|
285
|
+
|
|
286
|
+
N VMs run in parallel each tick. A binary Merkle tree over all N
|
|
287
|
+
commitments produces a single `fleet_root` — one OP_RETURN regardless
|
|
288
|
+
of fleet size.
|
|
289
|
+
|
|
290
|
+
```
|
|
291
|
+
tick N:
|
|
292
|
+
VM₀ → commitment₀ ─┐
|
|
293
|
+
VM₁ → commitment₁ ─┤ Merkle → fleet_root → SHA256(block_hash:fleet_root) → OP_RETURN
|
|
294
|
+
VM₂ → commitment₂ ─┤
|
|
295
|
+
VM₃ → commitment₃ ─┘
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## Ledger formats
|
|
299
|
+
|
|
300
|
+
**v1 entry:**
|
|
301
|
+
```json
|
|
302
|
+
{
|
|
303
|
+
"block_height": 961224,
|
|
304
|
+
"block_hash": "000000000000...",
|
|
305
|
+
"vdf_tick": 0,
|
|
306
|
+
"vm_ticks": 10,
|
|
307
|
+
"halted": false,
|
|
308
|
+
"registers": [1, 1, 1, 20, 1, 0, 0, 0],
|
|
309
|
+
"state_hash": "a3f9c2b1...",
|
|
310
|
+
"commitment": "88d6f091..."
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**v1.2 additions** (VDF active):
|
|
315
|
+
```json
|
|
316
|
+
{
|
|
317
|
+
"vdf_tick": 2,
|
|
318
|
+
"vdf_input": "prev_tick_output...",
|
|
319
|
+
"vdf_hash": "this_tick_output...",
|
|
320
|
+
"commitment": "SHA256(block_hash:vdf_hash:state_hash)"
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
**v2 additions** (trace active):
|
|
325
|
+
```json
|
|
326
|
+
{
|
|
327
|
+
"trace_root": "merkle_root_over_all_steps...",
|
|
328
|
+
"trace_steps": 42,
|
|
329
|
+
"commitment": "SHA256(block_hash:trace_root)"
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
**v3** (fleet active) replaces per-VM fields with:
|
|
334
|
+
```json
|
|
335
|
+
{
|
|
336
|
+
"fleet_size": 4,
|
|
337
|
+
"fleet_root": "merkle_root_over_vm_commitments...",
|
|
338
|
+
"commitment": "SHA256(block_hash:fleet_root)",
|
|
339
|
+
"vms": [
|
|
340
|
+
{"vm_id": 0, "program": "fibonacci", "halted": false, "registers": [...], "state_hash": "..."},
|
|
341
|
+
...
|
|
342
|
+
]
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
**ott ledger entry:**
|
|
347
|
+
```json
|
|
348
|
+
{
|
|
349
|
+
"ts": "2026-08-17T20:37:00Z",
|
|
350
|
+
"block_height": 961301,
|
|
351
|
+
"block_hash": "000000000000...",
|
|
352
|
+
"merkle_root": "b699603c...",
|
|
353
|
+
"commitment": "9dc75674...",
|
|
354
|
+
"image_count": 3
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## Tab completions
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
make completion
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
Installs Bash and Zsh completions for both `btcvm` and `ott`:
|
|
365
|
+
- `btcvm` — flags and values (`--vdf-ticks`, `--vms`, etc.)
|
|
366
|
+
- `ott add` — any file
|
|
367
|
+
- `ott verify` — filenames from the manifest
|
|
368
|
+
- `ott verify-chunk` — video names, then chunk indices from the manifest
|
|
369
|
+
|
|
370
|
+
For Zsh, add to `~/.zshrc` if not already present:
|
|
371
|
+
```zsh
|
|
372
|
+
fpath=(~/.zsh/completions $fpath)
|
|
373
|
+
autoload -Uz compinit && compinit
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
## Makefile targets
|
|
377
|
+
|
|
378
|
+
```
|
|
379
|
+
make install pip install -e .
|
|
380
|
+
make dev install with dev deps
|
|
381
|
+
make test run pytest
|
|
382
|
+
make lint ruff check
|
|
383
|
+
make fix ruff --fix
|
|
384
|
+
make run btcvm one block
|
|
385
|
+
make run-vdf btcvm with VDF sub-clock
|
|
386
|
+
make run-trace btcvm with trace Merkle
|
|
387
|
+
make run-fleet btcvm fleet of 4 VMs
|
|
388
|
+
make verify verify ledger.jsonl
|
|
389
|
+
make ott-status show archive status
|
|
390
|
+
make ott-list list archived files
|
|
391
|
+
make ott-commit commit Merkle root
|
|
392
|
+
make ott-clean remove manifest + ledger
|
|
393
|
+
make ott-repo-add update archived repo record to HEAD
|
|
394
|
+
make ott-tag [OTT_NEXT_TAG=v1.x] sign a git tag + record fingerprint in ott
|
|
395
|
+
make ott-push [OTT_NEXT_TAG=v1.x] push commits + tag, then commit ott root
|
|
396
|
+
make ott-snapshot repo-add + commit root (no tag, no push)
|
|
397
|
+
make ott-release [OTT_NEXT_TAG=v1.x] full: tag → push → commit root
|
|
398
|
+
make add FILE=… add file to ott
|
|
399
|
+
make verify-file FILE=… verify inclusion
|
|
400
|
+
make completion install shell completions
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
## Roadmap
|
|
404
|
+
|
|
405
|
+
- ✅ **v1** — Bitcoin-clocked register machine, local ledger, optional OP_RETURN
|
|
406
|
+
- ✅ **v1.1** — Ledger verification against block hashes and OP_RETURN
|
|
407
|
+
- ✅ **v1.2** — VDF sub-clock (`--vdf-ticks N`)
|
|
408
|
+
- ✅ **v2** — Trace commitment / Merkle root (`--trace`)
|
|
409
|
+
- ✅ **v3** — Fleet Merkle: N parallel VMs, single OP_RETURN (`--vms N`)
|
|
410
|
+
- ✅ **ott** — Bitcoin-anchored media archive with chunked video and inclusion proofs
|
|
411
|
+
|
|
412
|
+
## Tests
|
|
413
|
+
|
|
414
|
+
```bash
|
|
415
|
+
make test
|
|
416
|
+
# or
|
|
417
|
+
python3 -m pytest -v
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
## License
|
|
421
|
+
|
|
422
|
+
MIT
|