Skip to content

Instantly share code, notes, and snippets.

View RobinLinus's full-sized avatar
🧡
₿itcoin

Robin Linus RobinLinus

🧡
₿itcoin
View GitHub Profile
@RobinLinus
RobinLinus / layer-tree.md
Last active May 6, 2026 01:11
Layer Tree is an efficient Bitcoin L2 based on a 1-of-n trust assumption

Layer Tree protocol summary

Layer Tree is a Bitcoin L2 built around a shared pool UTXO controlled by an n-of-n MuSig key held by a set of operators. The operators may be implemented as independently attested TEEs.

Users’ balances are represented by periodically signed exit trees. Each exit tree commits to the current allocation of the pool among users. Users can transfer funds offchain, withdraw cooperatively to L1, deposit from L1, or unilaterally exit through the latest available exit tree.

The protocol fundamentally relies on a 1-of-N honest operator assumption for safety and data availability, while normal operation requires N-of-N operator cooperation.


@RobinLinus
RobinLinus / roulette.md
Last active August 18, 2026 11:22
Roulette in a Bitcoin Payment Channel

Roulette in a Bitcoin Payment Channel

A protocol sketch for a two-party roulette game between a player and a casino. It uses a revocable 2-of-2 payment channel, hash-preimage-length commitments for randomness, Taproot script paths for unilateral dispute resolution, and payout-class settlement transactions for arbitrary roulette betting patterns.

This is a design document, not production-ready consensus-critical code. Every script fragment below is pseudocode and must be compiled, simulated, and tested on regtest before use with real value.


1. Design Goals

@RobinLinus
RobinLinus / subchains.md
Last active May 5, 2026 21:16
Bitcoin Subchains via OP_CAT and the Taproot Annex

Bitcoin Subchains via OP_CAT and the Taproot Annex

Abstract

We sketch a construction for subchains: blockchains embedded inside the Bitcoin blockchain, with on-chain data availability and trust-minimized two-way pegs. The construction is similar in spirit to Ruben Somsen's spacechains [1], but lifts data availability onto Bitcoin itself and supports a STARK-verified bridge. It assumes (1) OP_CAT [2] and (2) standardness of the taproot annex [3].

Background and Assumptions

  • OP_CAT. Restoring OP_CAT [2] enables recursive covenants and, in combination with Andrew Poelstra's sighash trick [4], allows a script to introspect the transaction that contains it.
  • Taproot annex standardness. The annex is a witness field that is committed to by the BIP-341 sighash [3]. Standardness is required so transactions carrying annex data relay through the public mempool.
@RobinLinus
RobinLinus / zeroconf.md
Last active August 7, 2026 09:22
A Protocol for Zero-Confirmation Bitcoin Payments

Protocol for Zero-Confirmation Bitcoin Payments

Overview

This protocol lets a Bitcoin user make zero-confirmation payments while retaining a trustless unilateral exit path if the co-signing server disappears or refuses to cooperate.

  • The user keeps funds in a confirmed 2-of-2 multisig with a co-signing server.
  • The co-signer enforces a policy of not signing conflicting spends.
  • Recipients can accept zero-confirmation payments if they trust the co-signer's policy.
  • The user receives a pre-signed unilateral exit transaction before depositing funds.

ECDSA-HORS in Bitcoin Script

A construction for hash-based one-time signatures in Bitcoin using ECDSA key leakage as the reveal mechanism.

Overview

Classical HORS uses n hash digests as the public key and reveals t preimages to sign a message, where the message selects which t-of-n preimages to reveal. This construction replaces:

HORS ECDSA-HORS
@RobinLinus
RobinLinus / publishing-proofs.md
Last active February 20, 2026 01:39
Optimizing On-Chain Costs of Publishing Proofs for BitVM3-Style Bridges

Optimizing On-Chain Costs for Publishing Proofs in BitVM-Style Bridges

Liam Eagen came up with a clever optimization for publishing proof data in BitVM-style bridges. Instead of Lamport/Winternitz signatures, it uses adaptor signatures. The message is split into chunks (e.g., 8- or 11-bit digits), and for each digit a Schnorr signature is provided.

Naively, the unlocking script would require a separate public key for each digit. The following construction shows how to use OP_CODESEPARATOR to instead require just a single public key, regardless of the number of digits. The key idea is to use OP_CODESEPARATOR to modify the sighash so that each adaptor signature is tied to a specific digit.

@RobinLinus
RobinLinus / cat_ecc.md
Last active September 3, 2024 22:05
OP_CAT Enables Scalar Multiplication for EC Points

OP_CAT Enables Scalar Multiplication for EC Points

CAT can reduce curve point scalar multiplication to a subtraction in the scalar field.

Subtraction of field elements can probably be emulated in less than 250 (?) opcodes. For now, let's assume we had an (emulated) opcode, op_scalar_sub, for subtracting two elements of the scalar field of secp256k1.

Given secp's generator G, we want to compute for some scalar r the point R = rG

That is possible by hacking it into a Schnorr signature (R,s) for the key P = xG = 1G = G

Commit to a Bit Value using a Schnorr Signature

This is a bit commitment (e.g. for BitVM) which allows you to commit to the value of a 1-bit variable across two different UTXOs via Schnorr signatures. If Paul equivocates on the bit's value then he leaks his private key.

Surprisingly, the commitment script doesn't need to commit to anything specific. All semantics arise from the nonces in the partial signatures. That allows you to reprogram gates after compile time.

Commitment Script

The commitment script uses OP_CODESEPARATOR such that public key P can sign off on one of two execution branches in the script. Depending on which branch is signed, the script leaves 0 or 1 on the stack.

31-bit Commitment

This is a 31-bit commitment in Bitcoin Script.

OP_DUP
OP_TOALTSTACK

OP_DUP
<1073741824>
<main>
<h1>Seed Splitting</h1>
<h3>Split your BIP39 seed phrase into two of three shards.</h3>
<div class="row-reverse">
<a onclick="example()">Example</a>
</div>
<textarea id="$seedphrase" placeholder="Enter 24 word seed phrase"></textarea>
<div class="row-reverse">
<button onclick="splitSeed()">Split</button>
</div>