ts-sdk

Transaction Verification

Understanding how to verify Bitcoin transactions using the BSV TypeScript SDK.

What is Transaction Verification?

Transaction verification ensures that Bitcoin transactions are valid and can be trusted:

import { Transaction } from '@bsv/sdk'

// Verify a transaction
const isValid = await transaction.verify(chainTracker, {
  merkleProof: proof,
  blockHeader: header
})

Verification Levels

Basic Validation

Check transaction structure and format:

Script Execution

Verify that unlocking scripts satisfy locking scripts:

SPV Verification

Confirm transaction inclusion in the blockchain:

SDK Verification Methods

Transaction.verify()

Complete transaction verification:

const result = await transaction.verify(chainTracker, {
  merkleProof: merkleProof,
  blockHeader: blockHeader,
  maxMemoryLimit: 100000000
})

Script Verification

Verify individual scripts:

const isValid = unlockingScript.verify(
  lockingScript,
  transaction,
  inputIndex
)

Signature Verification

Check digital signatures:

const publicKey = PrivateKey.fromWif(wif).toPublicKey()
const isValid = publicKey.verify(messageHash, signature)

Verification Options

Memory Limits

Control script execution memory usage:

const options = {
  maxMemoryLimit: 50000000 // 50MB limit
}

Scripts-Only Mode

Skip SPV verification for performance:

const options = {
  scriptsOnly: true
}

Custom Chain Tracker

Use specific data sources:

const customTracker = new WhatsOnChain('testnet')
const isValid = await transaction.verify(customTracker)

BEEF Verification

BEEF format includes verification data:

// BEEF transactions include proofs
const beefTx = Transaction.fromHexBEEF(beefData)

// Verify using included proofs
const isValid = await beefTx.verify(chainTracker)

Error Handling

Common verification failures:

try {
  const isValid = await transaction.verify(chainTracker)
  if (!isValid) {
    console.log('Transaction verification failed')
  }
} catch (error) {
  console.error('Verification error:', error.message)
}

Performance Considerations

Batch Verification

Verify multiple transactions efficiently:

const results = await Promise.all(
  transactions.map(tx => tx.verify(chainTracker))
)

Caching

Cache verification results:

const verificationCache = new Map()

if (!verificationCache.has(txid)) {
  const result = await transaction.verify(chainTracker)
  verificationCache.set(txid, result)
}

Security Best Practices

Always Verify

Multiple Sources

Resource Limits

Common Use Cases

Payment Verification

// Verify received payment
const payment = Transaction.fromHex(paymentHex)
const isValid = await payment.verify(chainTracker)

if (isValid) {
  // Process confirmed payment
}

Historical Transaction Audit

// Verify old transactions
for (const txHex of historicalTransactions) {
  const tx = Transaction.fromHex(txHex)
  const result = await tx.verify(chainTracker)
  console.log(`Transaction ${tx.id()}: ${result ? 'Valid' : 'Invalid'}`)
}

Integration Patterns

Wallet Integration

// Wallets typically handle verification
const wallet = new WalletClient()
const action = await wallet.createAction({
  outputs: [/* outputs */]
})
// Wallet verifies before broadcasting

Application Verification

// Applications verify received transactions
async function processIncomingTransaction(txHex: string) {
  const tx = Transaction.fromHex(txHex)
  
  if (await tx.verify(chainTracker)) {
    // Process verified transaction
    await handleValidTransaction(tx)
  } else {
    // Reject invalid transaction
    throw new Error('Invalid transaction received')
  }
}

Next Steps