or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

address.mdblocks.mdcrypto.mdindex.mdnetworks.mdpayments.mdpsbt.mdscripts.mdtransactions.mdutilities.md
tile.json

scripts.mddocs/

Script Operations

Complete script compilation, decompilation, and analysis utilities with support for script validation, ASM representation, and Bitcoin script operations including push data handling and signature validation.

Core Types

type StackElement = Buffer | number;
type Stack = StackElement[];

/** Operation codes object mapping names to opcodes */
const OPS: { [key: string]: number };

Capabilities

Script Compilation and Decompilation

Convert between human-readable and binary script formats.

/**
 * Compiles an array of chunks into a Buffer
 * @param chunks - Array of chunks or raw buffer to compile
 * @returns Compiled script Buffer
 * @throws Error if compilation fails
 */
function compile(chunks: Buffer | Stack): Buffer;

/**
 * Decompiles a script buffer into array of chunks
 * @param buffer - Script buffer or array to decompile
 * @returns Array of chunks or null if decompilation fails
 */
function decompile(buffer: Buffer | Array<number | Buffer>): Array<number | Buffer> | null;

Usage Examples:

import { script } from 'bitcoinjs-lib';

// Compile script from chunks
const chunks = [
  script.OPS.OP_DUP,
  script.OPS.OP_HASH160,
  Buffer.from('a54d79f79f1f7b7e2d3e8b4f8c7a6e9f8c7a6e9f', 'hex'),
  script.OPS.OP_EQUALVERIFY,
  script.OPS.OP_CHECKSIG
];
const compiledScript = script.compile(chunks);
console.log('P2PKH script:', compiledScript.toString('hex'));

// Decompile script to chunks
const scriptBuffer = Buffer.from('76a914a54d79f7...88ac', 'hex');
const decompiled = script.decompile(scriptBuffer);
console.log('Decompiled chunks:', decompiled);

ASM Representation

Convert scripts to and from human-readable ASM format.

/**
 * Converts chunks into ASM (Assembly) string representation
 * @param chunks - Chunks to convert or buffer to decompile first
 * @returns ASM string representation
 */
function toASM(chunks: Buffer | Array<number | Buffer>): string;

/**
 * Converts ASM string to script buffer
 * @param asm - ASM string to convert
 * @returns Compiled script buffer
 */
function fromASM(asm: string): Buffer;

Usage Examples:

import { script } from 'bitcoinjs-lib';

// Script to ASM
const p2pkhScript = Buffer.from('76a914a54d79f7...88ac', 'hex');
const asm = script.toASM(p2pkhScript);
console.log('P2PKH ASM:', asm);
// Output: "OP_DUP OP_HASH160 a54d79f79f1f7b7e2d3e8b4f8c7a6e9f8c7a6e9f OP_EQUALVERIFY OP_CHECKSIG"

// ASM to script
const asmString = 'OP_DUP OP_HASH160 a54d79f79f1f7b7e2d3e8b4f8c7a6e9f8c7a6e9f OP_EQUALVERIFY OP_CHECKSIG';
const scriptFromAsm = script.fromASM(asmString);
console.log('Script from ASM:', scriptFromAsm.toString('hex'));

// Multisig ASM
const multisigAsm = '2 03a34b... 03b45c... 03c56d... 3 OP_CHECKMULTISIG';
const multisigScript = script.fromASM(multisigAsm);

Stack Operations

Convert scripts to stack format for execution analysis.

/**
 * Converts chunks into stack of buffers
 * @param chunks - Chunks to convert or buffer to decompile first
 * @returns Stack of buffers
 */
function toStack(chunks: Buffer | Array<number | Buffer>): Buffer[];

Usage Examples:

import { script } from 'bitcoinjs-lib';

const scriptSig = Buffer.from('473044...', 'hex'); // Signature + pubkey
const stack = script.toStack(scriptSig);
console.log('Stack items:', stack.length);
console.log('Signature:', stack[0].toString('hex'));
console.log('Public key:', stack[1].toString('hex'));

Script Analysis

Analyze script properties and validation.

/**
 * Check if stack contains only push operations (no opcodes)
 * @param value - Stack to analyze
 * @returns True if contains only push operations
 */
function isPushOnly(value: Stack): boolean;

/**
 * Count non-push operations in stack
 * @param value - Stack to analyze
 * @returns Number of non-push operations
 */
function countNonPushOnlyOPs(value: Stack): number;

/**
 * Check if buffer contains canonical public key
 * @param buffer - Buffer to check
 * @returns True if canonical public key format
 */
function isCanonicalPubKey(buffer: Buffer): boolean;

/**
 * Check if hash type is valid/defined
 * @param hashType - Hash type to check
 * @returns True if valid hash type
 */
function isDefinedHashType(hashType: number): boolean;

/**
 * Check if buffer contains canonical script signature
 * @param buffer - Buffer to check
 * @returns True if canonical signature format
 */
function isCanonicalScriptSignature(buffer: Buffer): boolean;

Usage Examples:

import { script } from 'bitcoinjs-lib';

// Analyze P2PKH scriptSig (should be push-only)
const p2pkhScriptSig = [
  Buffer.from('3044...', 'hex'), // signature
  Buffer.from('03a34b...', 'hex') // pubkey
];
console.log('Is push only:', script.isPushOnly(p2pkhScriptSig)); // true
console.log('Non-push ops:', script.countNonPushOnlyOPs(p2pkhScriptSig)); // 0

// Analyze public key
const pubkey = Buffer.from('03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd', 'hex');
console.log('Is canonical pubkey:', script.isCanonicalPubKey(pubkey)); // true

// Check signature
const signature = Buffer.from('3044...01', 'hex'); // DER + SIGHASH_ALL
console.log('Is canonical signature:', script.isCanonicalScriptSignature(signature));

// Check hash type
console.log('Valid hash type:', script.isDefinedHashType(0x01)); // true
console.log('Invalid hash type:', script.isDefinedHashType(0xFF)); // false

Script Number Operations

Handle Bitcoin script number encoding and decoding.

const number: {
  /**
   * Decode script number from buffer
   * @param buffer - Buffer containing script number
   * @param maxLength - Maximum length of script number (default: 4)
   * @param minimal - Whether encoding should be minimal (default: true)
   * @returns Decoded number
   * @throws TypeError if number overflows or isn't minimal
   */
  decode(buffer: Buffer, maxLength?: number, minimal?: boolean): number;
  
  /**
   * Encode number into script number buffer
   * @param _number - Number to encode
   * @returns Encoded number as buffer
   */
  encode(_number: number): Buffer;
};

Usage Examples:

import { script } from 'bitcoinjs-lib';

// Encode numbers for scripts
const encoded1 = script.number.encode(1);
const encoded42 = script.number.encode(42);
const encodedNeg1 = script.number.encode(-1);

console.log('Encoded 1:', encoded1.toString('hex')); // '01'
console.log('Encoded 42:', encoded42.toString('hex')); // '2a'
console.log('Encoded -1:', encodedNeg1.toString('hex')); // '81'

// Decode script numbers
const decoded1 = script.number.decode(Buffer.from('01', 'hex'));
const decoded42 = script.number.decode(Buffer.from('2a', 'hex'));
const decodedNeg1 = script.number.decode(Buffer.from('81', 'hex'));

console.log('Decoded:', decoded1, decoded42, decodedNeg1); // 1, 42, -1

// Handle OP_1 through OP_16 (special encoding)
const op2Chunks = [script.OPS.OP_2]; // Represents number 2
const op2Script = script.compile(op2Chunks);
console.log('OP_2 script:', op2Script.toString('hex')); // '52'

Script Signature Operations

Handle Bitcoin script signature encoding and decoding.

const signature: {
  /**
   * Decode script signature buffer
   * @param buffer - Buffer containing signature and hash type
   * @returns Object with signature and hash type
   * @throws Error if hash type is invalid
   */
  decode(buffer: Buffer): { signature: Buffer; hashType: number };
  
  /**
   * Encode signature and hash type into buffer
   * @param signature - DER-encoded signature
   * @param hashType - Signature hash type
   * @returns Encoded signature buffer
   * @throws Error if hash type is invalid
   */
  encode(signature: Buffer, hashType: number): Buffer;
};

Usage Examples:

import { script, Transaction } from 'bitcoinjs-lib';

// Encode signature with hash type
const derSig = Buffer.from('3044...', 'hex'); // DER signature
const hashType = Transaction.SIGHASH_ALL;
const encodedSig = script.signature.encode(derSig, hashType);
console.log('Encoded signature:', encodedSig.toString('hex'));

// Decode signature from scriptSig
const scriptSigBuffer = Buffer.from('473044...01', 'hex');
const decoded = script.signature.decode(scriptSigBuffer);
console.log('DER signature:', decoded.signature.toString('hex'));
console.log('Hash type:', decoded.hashType); // 1 (SIGHASH_ALL)

// Handle different hash types
const sighashNone = script.signature.encode(derSig, Transaction.SIGHASH_NONE);
const sighashSingle = script.signature.encode(derSig, Transaction.SIGHASH_SINGLE);
const sighashAnyoneCanPay = script.signature.encode(derSig, Transaction.SIGHASH_ANYONECANPAY);

Operation Codes

Access Bitcoin operation codes and their reverse mappings.

/** Operation codes mapping names to numbers */
const OPS: {
  // Push data
  OP_0: 0;
  OP_PUSHDATA1: 76;
  OP_PUSHDATA2: 77;
  OP_PUSHDATA4: 78;
  OP_1NEGATE: 79;
  OP_1: 81;
  OP_2: 82;
  // ... (all other opcodes)
  OP_CHECKSIG: 172;
  OP_CHECKSIGVERIFY: 173;
  OP_CHECKMULTISIG: 174;
  OP_CHECKMULTISIGVERIFY: 175;
  // ... etc
};

/** Reverse mapping from opcode numbers to names */
const REVERSE_OPS: { [key: number]: string };

Usage Examples:

import { script } from 'bitcoinjs-lib';

// Use opcodes in scripts
const p2pkhTemplate = [
  script.OPS.OP_DUP,
  script.OPS.OP_HASH160,
  // 20-byte pubkey hash goes here
  script.OPS.OP_EQUALVERIFY,
  script.OPS.OP_CHECKSIG
];

// Numbers for multisig
const multisig2of3 = [
  script.OPS.OP_2, // m = 2
  // pubkeys go here
  script.OPS.OP_3, // n = 3
  script.OPS.OP_CHECKMULTISIG
];

// Check specific opcodes
console.log('OP_CHECKSIG:', script.OPS.OP_CHECKSIG); // 172
console.log('OP_RETURN:', script.OPS.OP_RETURN); // 106

// Reverse lookup
console.log('Opcode 172:', script.REVERSE_OPS[172]); // 'OP_CHECKSIG'

Advanced Usage

Custom Script Creation

Build complex scripts programmatically:

import { script, crypto } from 'bitcoinjs-lib';

// Create P2PKH script
function createP2PKH(pubkeyHash: Buffer): Buffer {
  return script.compile([
    script.OPS.OP_DUP,
    script.OPS.OP_HASH160,
    pubkeyHash,
    script.OPS.OP_EQUALVERIFY,
    script.OPS.OP_CHECKSIG
  ]);
}

// Create multisig script
function createMultisig(m: number, pubkeys: Buffer[]): Buffer {
  const chunks = [
    script.OPS[`OP_${m}` as keyof typeof script.OPS],
    ...pubkeys,
    script.OPS[`OP_${pubkeys.length}` as keyof typeof script.OPS],
    script.OPS.OP_CHECKMULTISIG
  ];
  return script.compile(chunks);
}

// Create timelock script
function createTimelock(locktime: number, pubkeyHash: Buffer): Buffer {
  return script.compile([
    script.number.encode(locktime),
    script.OPS.OP_CHECKLOCKTIMEVERIFY,
    script.OPS.OP_DROP,
    script.OPS.OP_DUP,
    script.OPS.OP_HASH160,
    pubkeyHash,
    script.OPS.OP_EQUALVERIFY,
    script.OPS.OP_CHECKSIG
  ]);
}

Script Analysis and Debugging

Analyze scripts for debugging and understanding:

import { script } from 'bitcoinjs-lib';

function analyzeScript(scriptBuffer: Buffer): void {
  console.log('Raw script:', scriptBuffer.toString('hex'));
  
  const chunks = script.decompile(scriptBuffer);
  if (!chunks) {
    console.log('Failed to decompile script');
    return;
  }
  
  console.log('ASM:', script.toASM(scriptBuffer));
  console.log('Chunks:', chunks.length);
  console.log('Is push only:', script.isPushOnly(chunks));
  console.log('Non-push ops:', script.countNonPushOnlyOPs(chunks));
  
  // Analyze each chunk
  chunks.forEach((chunk, i) => {
    if (Buffer.isBuffer(chunk)) {
      console.log(`Chunk ${i}: DATA(${chunk.length}) ${chunk.toString('hex')}`);
    } else {
      const opName = script.REVERSE_OPS[chunk] || `UNKNOWN(${chunk})`;
      console.log(`Chunk ${i}: ${opName}`);
    }
  });
}

// Analyze different script types
const p2pkhScript = Buffer.from('76a914...88ac', 'hex');
analyzeScript(p2pkhScript);

Witness Script Handling

Handle witness scripts for SegWit transactions:

import { script } from 'bitcoinjs-lib';

// Witness script for P2WSH
const witnessScript = script.compile([
  script.OPS.OP_2,
  Buffer.from('03a34b...', 'hex'),
  Buffer.from('03b45c...', 'hex'),
  Buffer.from('03c56d...', 'hex'),
  script.OPS.OP_3,
  script.OPS.OP_CHECKMULTISIG
]);

console.log('Witness script:', witnessScript.toString('hex'));
console.log('Witness script ASM:', script.toASM(witnessScript));

// Create P2WSH output script
const witnessScriptHash = crypto.sha256(witnessScript);
const p2wshOutput = script.compile([script.OPS.OP_0, witnessScriptHash]);
console.log('P2WSH output:', p2wshOutput.toString('hex'));

Types

type StackElement = Buffer | number;
type Stack = StackElement[];

interface ScriptSignature {
  signature: Buffer;
  hashType: number;
}