UHRP — Universal Hash Resolution Protocol

UHRP (BRC-26) enables content-addressed file storage on BSV. Files are identified and retrieved by their SHA-256 hash, not by path. A UHRP server stores files and publishes availability advertisements on the overlay network (tm_uhrp topic). Clients discover storage locations and verify file integrity by hash.

At a glance

FieldValue
FormatOpenAPI 3.1
Version1.0.0
Statusstable
Implementations@bsv/overlay-topics (tm_uhrp topic manager)

What problem this solves

Permanent, hash-addressed file storage. Traditional URLs break when servers move. UHRP uses SHA-256 hash as permanent file ID: uhrp://abc123... always refers to the same content. Any server can host the file; clients verify integrity by hashing the retrieved data.

Decentralized availability. Files are mirrored across multiple UHRP servers. Clients query the overlay network (ls_uhrp lookup service) to find all hosts with a given hash, then download from any available server. No single point of failure.

Peer discovery via overlay. UHRP servers publish availability advertisements to the overlay's tm_uhrp topic. These advertisements record file hash, size, expiry, and download URLs. The ls_uhrp lookup service indexes these advertisements, enabling instant discovery.

Protocol overview

Three-phase flow (upload → advertise → retrieve):

Phase 1 — Upload File

  1. Client → UHRP Server POST /upload

    • File binary data (raw bytes)
    • Server computes SHA-256 hash
    • Returns: UHRP URL (uhrp://hash...) and metadata
  2. UHRP Server stores file and generates advertisement

Phase 2 — Publish to Overlay

  1. UHRP Server → Overlay (via POST /submit)
    • PushDrop transaction tagged with tm_uhrp topic
    • Advertisement contains: hash, file size, download URL, expiry timestamp
    • Overlay records admission; ls_uhrp lookup service indexes it

Phase 3 — Retrieve File

  1. Client → Overlay POST /lookup

    • Query: { service: "ls_uhrp", query: { hash: "abc123..." } }
    • Lookup service returns: array of servers hosting the file
  2. Client → UHRP Server GET /{hash}

    • Downloads file from any available server
    • Verifies SHA-256 matches requested hash
    • Rejects file if hash doesn't match

Key types / endpoints

MethodPathPurposeRequestResponse
POST/uploadUpload fileBinary file data{ hash, uhrpUrl, size, expiryTimestamp }
GET/{hash}Download file(none)Binary file data + Content-Hash header
HEAD/{hash}Check availability(none)200 OK + Content-Hash header
GET/info/{hash}Get metadata(none){ hash, size, expiryTimestamp, hosts: [...] }

Overlay integration:

  • tm_uhrp topic manager — Validates UHRP advertisements
  • ls_uhrp lookup service — Queries for files by hash; returns host list

Example: Upload and retrieve file

typescript
import { StorageUploader, StorageDownloader, WalletClient } from '@bsv/sdk'

// 1. Upload file to UHRP server
const wallet = new WalletClient('auto', 'example.com')
const uploader = new StorageUploader({
  storageURL: 'https://uhrp-storage.example.com',
  wallet
})

const file = new TextEncoder().encode('Hello, UHRP!')
const result = await uploader.publishFile({
  file: { data: file, type: 'text/plain' },
  retentionPeriod: 7
})

console.log('File stored at:', result.uhrpURL)  // uhrp://abc123...

// 2. Publish advertisement to overlay (server does this automatically)
// UHRP server issues a PushDrop transaction to tm_uhrp topic

// 3. Retrieve file later (from any server)
const downloader = new StorageDownloader()
const retrieved = await downloader.download(result.uhrpURL)

// 4. StorageDownloader verifies the content hash before returning data
console.log(new TextDecoder().decode(retrieved.data))

Example: Query overlay for file locations

typescript
import { LookupResolver } from '@bsv/sdk'

const lookupResolver = new LookupResolver({
  hostOverrides: {
    ls_uhrp: ['https://overlay.example.com']
  }
})

// 1. Find all servers hosting a file
const locations = await lookupResolver.query({
  service: 'ls_uhrp',
  query: { uhrpUrl: 'uhrp://abc123...' }
})

if (locations.type !== 'output-list') {
  throw new Error('UHRP lookup must return an output list')
}

// StorageDownloader resolves the same output list and decodes the
// hosted file URLs from the UHRP advertisement outputs.
console.log('Advertisement outputs:', locations.outputs)

Conformance vectors

UHRP conformance is tested in conformance/vectors/storage/uhrp/:

  • File upload and hash computation
  • SHA-256 hash verification on download
  • Advertisement publication and overlay indexing
  • Lookup service correctness (returns all hosts for a hash)
  • Expiry timestamp handling

Implementations in ts-stack

PackageNotes
@bsv/overlay-topicsUHRPTopicManager (validates advertisements), createUHRPLookupService (indexes hashes)
@bsv/sdkStorageUploader, StorageDownloader, and LookupResolver client classes
  • Overlay HTTP — Overlay network where UHRP advertisements are published
  • BRC-26 — Full UHRP specification

Spec artifact

uhrp-http.yaml