◊ETERNALCHAIN
EngravingsDecodeAboutEngrave NowSign In
Method deep dive

Stamps (Multisig)

The most durable way to inscribe data on Bitcoin. Unprunable, permanent, and resistant to network changes.

What are Stamps?

Stamps is a protocol that embeds data inside bare 1-of-3 multisig outputs. Unlike OP_RETURN, these outputs are part of the UTXO set — the database of unspent coins that every full node must maintain. This makes Stamps inscriptions truly unprunable: no node can discard them without breaking consensus.

The data is encrypted using ARC4 (a stream cipher) with the first input’s transaction ID as the key. This isn’t for security — anyone who knows the txid can decrypt it. It’s a convention of the Stamps protocol to make the data appear random in the blockchain, reducing the chance of false pattern matches.

Encoding Pipeline

The encoding process has several stages:

1. Your message (UTF-8) "I love you forever" 2. Base64 encode "SSBsb3ZlIHlvdSBmb3JldmVy" 3. Add "stamp:" prefix "stamp:SSBsb3ZlIHlvdSBmb3JldmVy" 4. Add 2-byte big-endian length frame [0x00, 0x22, ...payload_bytes] 5. ARC4 encrypt using first input txid as key [encrypted_bytes...] 6. Split into 31-byte chunks [chunk_0, chunk_1, ...]

Multisig Output Structure

Each pair of data chunks becomes a 1-of-3 bare multisig output. The three public keys in each output serve different purposes:

OP_1 (0x51) <data_pubkey_1> 33 bytes — chunk N embedded in bytes [1..31] <data_pubkey_2> 33 bytes — chunk N+1 embedded in bytes [1..31] <keyburn_key> 33 bytes — unspendable (all 0x02 bytes) OP_3 (0x53) OP_CHECKMULTISIG (0xae) Total script size: 105 bytes per multisig output

The “data pubkeys” are crafted by embedding 31 bytes of data into positions [1..31] of a 33-byte compressed public key. Position [0] is the prefix (0x02 or 0x03) and position [32] is a nonce. The code tries different prefix/nonce combinations until the result is a valid point on the secp256k1 curve.

The keyburn key (0x020202...02) is unspendable — no one knows its private key. This ensures the 7,800 sats sent to each multisig output are permanently locked.

Transaction Structure

Input: - Server wallet UTXO (P2WPKH) Outputs: 1. Recipient address (7,800 sats dust) 2. Bare multisig (chunks 0-1) (7,800 sats dust, burned) 3. Bare multisig (chunks 2-3) (7,800 sats dust, burned) ...N multisig outputs... N+1. Change to server wallet (remaining balance)

Decoding a Stamps Inscription

// 1. Fetch the transaction const res = await fetch("https://mempool.space/api/tx/<txid>"); const tx = await res.json(); // 2. Find bare multisig outputs // Script starts with 0x51 (OP_1) and ends with 0x53ae (OP_3 OP_CHECKMULTISIG) const multisigOutputs = tx.vout.filter( (o) => o.scriptpubkey.startsWith("51") && o.scriptpubkey.endsWith("53ae") ); // 3. Extract data pubkeys (skip the keyburn key) const chunks = []; for (const out of multisigOutputs) { const script = out.scriptpubkey; let offset = 2; // skip OP_1 const keys = []; while (offset < script.length - 4) { if (script.slice(offset, offset + 2) === "21") { // OP_PUSHBYTES_33 offset += 2; keys.push(script.slice(offset, offset + 66)); offset += 66; } else break; } // First 2 keys are data keys, 3rd is keyburn for (let i = 0; i < Math.min(keys.length - 1, 2); i++) { const keyBytes = hexToBytes(keys[i]); chunks.push(keyBytes.slice(1, 32)); // strip prefix byte } } // 4. Concatenate and ARC4 decrypt const encrypted = concatBytes(chunks); const arc4Key = hexToBytes(tx.vin[0].txid); const decrypted = arc4Decrypt(arc4Key, encrypted); // 5. Parse length frame and stamp: prefix const payloadLen = (decrypted[0] << 8) | decrypted[1]; const payload = new TextDecoder().decode( decrypted.slice(2, 2 + payloadLen) ); // 6. Remove "stamp:" prefix and base64 decode const b64 = payload.slice(6); // remove "stamp:" const message = atob(b64); console.log(message); // "I love you forever"

Cost Breakdown

Estimated vsize (80-char message, 2 multisig outputs): Overhead: 11 vB P2WPKH input: 68 vB Recipient output: 31 vB 2x multisig outputs: 210 vB (105 each) Change output: 31 vB ───────────────────────────── Total: 351 vB At 10 sat/vB fee rate: Miner fee: 3,510 sats Recipient dust: 7,800 sats Multisig dust: 15,600 sats (7,800 x 2, permanently burned) Total cost: 26,910 sats (~$17.49 at $65k BTC)

Trade-offs

Advantages
Disadvantages
Unprunable — in the UTXO set
Higher cost ($25)
Truly permanent inscriptions
Burns sats in dust outputs
Cannot be censored by nodes
Adds to UTXO set bloat
Encrypted data on-chain
More complex to decode

Why “Stamps”?

The name comes from the Bitcoin Stamps protocol, which was originally designed for embedding images (like NFTs) on Bitcoin in a way that cannot be pruned. EternalChain uses the same encoding technique for text inscriptions, giving your words the same level of permanence as Bitcoin Stamps art.

Explore other methods
OP_RETURNETH CalldataETH EventSOL MemoSOL cNFT
Create Your Engraving
◊ ETERNALCHAIN — Love, immutable. © 2026·Terms of Use