SPV Verification

Complete examples for Simplified Payment Verification (SPV) using merkle proofs.

Overview

This code feature demonstrates Simplified Payment Verification (SPV), which allows lightweight clients to verify that a transaction is included in a block without downloading the entire blockchain. SPV uses merkle proofs to cryptographically prove transaction inclusion with minimal data.

Related SDK Components:

Basic Merkle Proof Verification

import { MerkleProof, Transaction, Hash } from '@bsv/sdk'

/**
 * Basic SPV Verification
 *
 * Verify transaction inclusion using merkle proofs
 */
class BasicSPVVerification {
  /**
   * Verify a transaction is included in a block
   */
  verifyTransactionInclusion(
    txid: string,
    merkleProof: {
      index: number
      txOrId: string
      target: string
      nodes: string[]
    },
    blockHeader: {
      version: number
      prevBlockHash: string
      merkleRoot: string
      time: number
      bits: number
      nonce: number
    }
  ): boolean {
    try {
      // Create MerkleProof instance
      const proof = MerkleProof.fromHex(this.serializeMerkleProof(merkleProof))

      // Verify the proof
      const isValid = proof.verify(
        txid,
        Buffer.from(blockHeader.merkleRoot, 'hex')
      )

      return isValid
    } catch (error) {
      console.error('Verification failed:', error)
      return false
    }
  }

  /**
   * Serialize merkle proof to hex
   */
  private serializeMerkleProof(proof: {
    index: number
    txOrId: string
    target: string
    nodes: string[]
  }): string {
    // Implementation depends on SDK's MerkleProof format
    // This is a simplified example
    return JSON.stringify(proof)
  }

  /**
   * Calculate merkle root from transaction and proof
   */
  calculateMerkleRoot(txid: string, proof: string[]): string {
    let hash = Buffer.from(txid, 'hex')

    for (const node of proof) {
      const nodeBuffer = Buffer.from(node, 'hex')

      // Concatenate and hash
      const combined = Buffer.concat([hash, nodeBuffer])
      hash = Hash.sha256(Hash.sha256(combined))
    }

    return hash.toString('hex')
  }

  /**
   * Verify merkle root matches block header
   */
  verifyMerkleRoot(
    calculatedRoot: string,
    blockHeaderRoot: string
  ): boolean {
    return calculatedRoot === blockHeaderRoot
  }
}

/**
 * Usage Example
 */
async function basicSPVExample() {
  const spv = new BasicSPVVerification()

  // Transaction ID to verify
  const txid = 'abc123...'

  // Merkle proof (typically obtained from a block explorer or node)
  const merkleProof = {
    index: 0,
    txOrId: txid,
    target: 'merkle-root-hash...',
    nodes: [
      'hash1...',
      'hash2...',
      'hash3...'
    ]
  }

  // Block header (from chain)
  const blockHeader = {
    version: 1,
    prevBlockHash: 'prev-hash...',
    merkleRoot: 'merkle-root-hash...',
    time: 1234567890,
    bits: 0x1d00ffff,
    nonce: 12345
  }

  // Verify transaction inclusion
  const isValid = spv.verifyTransactionInclusion(
    txid,
    merkleProof,
    blockHeader
  )

  console.log('Transaction verified:', isValid)
}

SPV Proof Construction and Verification

Lightweight SPV Client

Advanced SPV Patterns

See Also

SDK Components:

Learning Paths:

Last updated