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

blocks.mddocs/

Block Operations

Bitcoin block parsing, validation, and Merkle root calculation with support for witness commitments, proof-of-work validation, and block serialization for all Bitcoin block formats.

Capabilities

Block Class

Core block functionality with comprehensive methods for block creation, parsing, and validation.

class Block {
  /** Block version */
  version: number;
  /** Previous block hash */
  prevHash?: Buffer;
  /** Merkle root of transactions */
  merkleRoot?: Buffer;
  /** Block timestamp (Unix timestamp) */
  timestamp: number;
  /** Witness commitment (BIP 141) */
  witnessCommit?: Buffer;
  /** Difficulty bits */
  bits: number;
  /** Proof-of-work nonce */
  nonce: number;
  /** Block transactions */
  transactions?: Transaction[];
}

Block Creation and Parsing

Create blocks from various sources including buffers and hex strings.

/**
 * Create block from buffer
 * @param buffer - Raw block buffer
 * @returns Parsed Block object
 */
static fromBuffer(buffer: Buffer): Block;

/**
 * Create block from hex string
 * @param hex - Hex-encoded block string
 * @returns Parsed Block object
 */
static fromHex(hex: string): Block;

Usage Examples:

import { Block } from 'bitcoinjs-lib';

// Parse block from hex
const blockHex = '01000000...';
const block = Block.fromHex(blockHex);

console.log('Block version:', block.version);
console.log('Previous hash:', block.prevHash?.toString('hex'));
console.log('Timestamp:', new Date(block.timestamp * 1000));
console.log('Transaction count:', block.transactions?.length);

// Parse from buffer
const blockBuffer = Buffer.from(blockHex, 'hex');
const block2 = Block.fromBuffer(blockBuffer);

Static Utility Methods

Utility methods for block-related calculations.

/**
 * Calculate target from difficulty bits
 * @param bits - Difficulty bits from block header
 * @returns Target as 32-byte buffer
 */
static calculateTarget(bits: number): Buffer;

/**
 * Calculate Merkle root from transactions
 * @param transactions - Array of transactions
 * @param forWitness - Calculate witness commitment Merkle root
 * @returns Merkle root as 32-byte buffer
 */
static calculateMerkleRoot(transactions: Transaction[], forWitness?: boolean): Buffer;

Usage Examples:

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

// Calculate target from difficulty bits
const difficultyBits = 0x1d00ffff; // Example difficulty
const target = Block.calculateTarget(difficultyBits);
console.log('Target:', target.toString('hex'));

// Calculate Merkle root
const transactions = [
  Transaction.fromHex('01000000...'),
  Transaction.fromHex('01000000...'),
  // ... more transactions
];
const merkleRoot = Block.calculateMerkleRoot(transactions);
console.log('Merkle root:', merkleRoot.toString('hex'));

// Calculate witness Merkle root
const witnessMerkleRoot = Block.calculateMerkleRoot(transactions, true);
console.log('Witness Merkle root:', witnessMerkleRoot.toString('hex'));

Block Properties and Metadata

Retrieve block properties and metadata.

/**
 * Get witness commitment from coinbase transaction
 * @returns Witness commitment or null if not present
 */
getWitnessCommit(): Buffer | null;

/**
 * Check if block has witness commitment
 * @returns True if block has witness commitment
 */
hasWitnessCommit(): boolean;

/**
 * Check if block has witness data in any transaction
 * @returns True if any transaction has witness data
 */
hasWitness(): boolean;

/**
 * Calculate block weight (BIP 141)
 * @returns Block weight in weight units
 */
weight(): number;

/**
 * Calculate block byte length
 * @param headersOnly - Calculate only header length
 * @param allowWitness - Include witness data in calculation
 * @returns Byte length
 */
byteLength(headersOnly?: boolean, allowWitness?: boolean): number;

/**
 * Get block timestamp as Date object
 * @returns Block timestamp as Date
 */
getUTCDate(): Date;

Usage Examples:

const block = Block.fromHex('01000000...');

// Check witness support
console.log('Has witness commit:', block.hasWitnessCommit());
console.log('Has witness data:', block.hasWitness());

// Get witness commitment
const witnessCommit = block.getWitnessCommit();
if (witnessCommit) {
  console.log('Witness commitment:', witnessCommit.toString('hex'));
}

// Size and weight calculations
console.log('Block weight:', block.weight());
console.log('Block size:', block.byteLength());
console.log('Header only size:', block.byteLength(true));

// Timestamp
console.log('Block time:', block.getUTCDate().toISOString());

Block Hashing

Generate block hashes and identifiers.

/**
 * Get block hash (double SHA256 of header)
 * @returns Block hash as 32-byte buffer
 */
getHash(): Buffer;

/**
 * Get block ID (hex-encoded reversed hash)
 * @returns Block ID string
 */
getId(): string;

Usage Examples:

const block = Block.fromHex('01000000...');

// Get block hash and ID
const blockHash = block.getHash();
const blockId = block.getId();

console.log('Block hash:', blockHash.toString('hex'));
console.log('Block ID:', blockId);

// Verify hash matches expected format
console.log('Hash is 32 bytes:', blockHash.length === 32);
console.log('ID is 64 char hex:', blockId.length === 64);

Block Serialization

Convert blocks to various formats for storage and transmission.

/**
 * Serialize block to buffer
 * @param headersOnly - Serialize only block header
 * @returns Serialized block buffer
 */
toBuffer(headersOnly?: boolean): Buffer;

/**
 * Serialize block to hex string
 * @param headersOnly - Serialize only block header
 * @returns Hex-encoded block
 */
toHex(headersOnly?: boolean): string;

Usage Examples:

const block = Block.fromHex('01000000...');

// Serialize full block
const fullBlockHex = block.toHex();
const fullBlockBuffer = block.toBuffer();

// Serialize header only (80 bytes)
const headerHex = block.toHex(true);
const headerBuffer = block.toBuffer(true);

console.log('Full block size:', fullBlockBuffer.length);
console.log('Header size:', headerBuffer.length); // Should be 80
console.log('Header hex:', headerHex);

Block Validation

Validate block integrity and proof-of-work.

/**
 * Check transaction Merkle roots
 * @returns True if Merkle roots are valid
 */
checkTxRoots(): boolean;

/**
 * Check proof-of-work
 * @returns True if proof-of-work is valid
 */
checkProofOfWork(): boolean;

Usage Examples:

const block = Block.fromHex('01000000...');

// Validate block
const validMerkleRoots = block.checkTxRoots();
const validProofOfWork = block.checkProofOfWork();

console.log('Valid Merkle roots:', validMerkleRoots);
console.log('Valid proof-of-work:', validProofOfWork);

if (validMerkleRoots && validProofOfWork) {
  console.log('Block is valid');
} else {
  console.log('Block validation failed');
}

// Check individual components
if (!validMerkleRoots) {
  console.log('Merkle root mismatch');
  console.log('Calculated:', Block.calculateMerkleRoot(block.transactions!).toString('hex'));
  console.log('In header:', block.merkleRoot?.toString('hex'));
}

if (!validProofOfWork) {
  console.log('Proof-of-work insufficient');
  const target = Block.calculateTarget(block.bits);
  const hash = block.getHash();
  console.log('Block hash:', hash.toString('hex'));
  console.log('Target:', target.toString('hex'));
}

Advanced Usage

Block Header Analysis

Analyze block header components:

import { Block } from 'bitcoinjs-lib';

function analyzeBlockHeader(block: Block): void {
  console.log('=== Block Header Analysis ===');
  console.log('Version:', block.version);
  console.log('Previous hash:', block.prevHash?.toString('hex'));
  console.log('Merkle root:', block.merkleRoot?.toString('hex'));
  console.log('Timestamp:', block.timestamp, '(' + block.getUTCDate().toISOString() + ')');
  console.log('Bits:', '0x' + block.bits.toString(16));
  console.log('Nonce:', block.nonce);
  
  // Calculate difficulty
  const target = Block.calculateTarget(block.bits);
  const maxTarget = Block.calculateTarget(0x1d00ffff); // Bitcoin's max target
  const difficulty = parseInt(maxTarget.toString('hex'), 16) / parseInt(target.toString('hex'), 16);
  console.log('Difficulty:', difficulty.toFixed(2));
  
  // Check proof-of-work
  const blockHash = block.getHash();
  const hashBigInt = BigInt('0x' + blockHash.toString('hex'));
  const targetBigInt = BigInt('0x' + target.toString('hex'));
  console.log('Hash < Target:', hashBigInt < targetBigInt);
}

const block = Block.fromHex('01000000...');
analyzeBlockHeader(block);

Merkle Tree Operations

Work with Merkle trees for transaction verification:

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

function buildMerkleTree(hashes: Buffer[]): Buffer[] {
  if (hashes.length === 0) return [];
  if (hashes.length === 1) return hashes;
  
  const tree = [...hashes];
  let level = hashes;
  
  while (level.length > 1) {
    const nextLevel: Buffer[] = [];
    
    for (let i = 0; i < level.length; i += 2) {
      const left = level[i];
      const right = level[i + 1] || left; // Duplicate last hash if odd number
      const combined = Buffer.concat([left, right]);
      const hash = crypto.hash256(combined);
      nextLevel.push(hash);
      tree.push(hash);
    }
    
    level = nextLevel;
  }
  
  return tree;
}

// Build Merkle tree from transaction hashes
const txHashes = block.transactions!.map(tx => tx.getHash());
const merkleTree = buildMerkleTree(txHashes);
const merkleRoot = merkleTree[merkleTree.length - 1];

console.log('Calculated Merkle root:', merkleRoot.toString('hex'));
console.log('Block Merkle root:', block.merkleRoot?.toString('hex'));
console.log('Roots match:', merkleRoot.equals(block.merkleRoot!));

Genesis Block

Work with the Bitcoin genesis block:

import { Block } from 'bitcoinjs-lib';

// Bitcoin genesis block
const genesisBlockHex = '0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c';
const genesisBlock = Block.fromHex(genesisBlockHex);

console.log('Genesis block ID:', genesisBlock.getId());
// Expected: '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f'

console.log('Genesis timestamp:', genesisBlock.getUTCDate().toISOString());
// Expected: '2009-01-03T18:15:05.000Z'

console.log('Genesis is valid:', genesisBlock.checkProofOfWork());

Witness Commitment Verification

Verify witness commitments in SegWit blocks:

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

function verifyWitnessCommitment(block: Block): boolean {
  if (!block.hasWitnessCommit() || !block.transactions) {
    return false;
  }
  
  // Calculate witness Merkle root
  const witnessMerkleRoot = Block.calculateMerkleRoot(block.transactions, true);
  
  // Get witness commitment from coinbase
  const witnessCommit = block.getWitnessCommit();
  if (!witnessCommit) return false;
  
  // Witness commitment should be hash256(witnessMerkleRoot + witnessReservedValue)
  // For simplicity, we'll just check if witness commitment exists and format is correct
  return witnessCommit.length === 32;
}

const segwitBlock = Block.fromHex('20000000...'); // SegWit block
console.log('Valid witness commitment:', verifyWitnessCommitment(segwitBlock));

Types

interface Transaction {
  getHash(forWitness?: boolean): Buffer;
  hasWitnesses(): boolean;
  // ... other transaction properties
}