headers

package
v0.14.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 7, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package headers is a chain tracker over a header source: an overlay bridge's native /v1 routes (github.com/lightwebinc/overlay-bridge), the public WhatsOnChain API, a chaintracks v2 service, a block-headers-service, or the chaintracks server an arcade installation embeds.

It is the root of trust for every proof checked against it. A transaction is only as trustworthy as the headers its BUMP is checked against, so the question of WHO answers "what root does height N commit to" is the whole security question, not a configuration detail. A bridge that received the headers itself, off the same network that delivered the transaction, needs no further check. A source that serves header fields (every other kind) is not taken at its word: every header it answers is hashed here and must carry the work its bits claim, at or above the network's floor, so a lie costs a mined block rather than an edited response.

It speaks HTTP and imports nothing from the bridge. That is deliberate: this module has exactly one direct dependency, and an HTTP contract plus a vendored fixture is a cheaper coupling than a Go dependency on a service. The fixtures in testdata/fixtures are the bridge's own generated bytes, copied verbatim, so a change to its wire shape fails here rather than in production.

Index

Constants

View Source
const (
	Mainnet = "main"
	Testnet = "test"
	Regtest = "regtest"
)

Networks a source may be checked against. The network decides the proof-of-work floor, nothing else.

View Source
const MainnetMinDifficulty = 4e9

MainnetMinDifficulty is the lowest difficulty a mainnet header may claim.

Every mainnet block since the 2018 split has carried a difficulty between about 2.6e10 and 5.2e11 (sampled across that range in 2026). The floor sits well below the lowest of those, so a real header never trips it, and well above what anyone could mine for the price of a lie: a header at 4e9 takes about 1.7e19 hashes. Without a floor a lying source would hand back a header whose bits claim a target nobody needs to work for, and the header would pass its own proof-of-work check.

Variables

View Source
var ErrBodyTooLarge = errors.New("headers: response body exceeds the bound")

ErrBodyTooLarge refuses a response above the bound.

View Source
var ErrProofOfWork = errors.New("headers: header fails its proof of work")

ErrProofOfWork is a header that does not carry the work it claims, or claims less than its network's floor. It is the header source lying (or serving another chain), never a proof that failed: a caller must not read it as "not yet".

View Source
var ErrSource = errors.New("headers: bad header source")

ErrSource is a header source specification that cannot be used.

View Source
var ErrUnknownHeight = errors.New("headers: the source does not hold that height")

ErrUnknownHeight is a height the source does not hold yet.

Functions

This section is empty.

Types

type Client

type Client struct {
	// Base is the source's base URL, with no path suffix.
	Base string
	// Kind is the dialect Base speaks. The zero value is a bridge's /v1.
	Kind Kind
	// Network sets the proof-of-work floor for a source that serves header
	// fields: Mainnet checks MainnetMinDifficulty, anything else checks each
	// header against its own target only.
	Network string
	// MinDifficulty overrides the network's floor when positive.
	MinDifficulty float64
	// HTTP is optional.
	HTTP *http.Client
	// Timeout defaults to 10s when HTTP is nil.
	Timeout time.Duration
	// Token, when set, is sent as a bearer token on every request: a
	// block-headers-service requires one unless its operator turned
	// authentication off.
	Token string
	// contains filtered or unexported fields
}

Client reads block headers from one header source.

func New

func New(spec string) *Client

New returns a client for a header source specification (see Parse). A specification that does not parse yields a client whose every call returns the parse error, so a caller that cannot handle an error at construction still refuses rather than guessing.

func NewSource added in v0.3.0

func NewSource(spec string) (*Client, error)

NewSource returns a client for a header source specification (see Parse). A source with header fields is checked for proof of work at the floor of the network it implies; set Network after construction to check it against another.

func (*Client) CurrentHeight

func (c *Client) CurrentHeight(ctx context.Context) (uint32, error)

CurrentHeight reports the header service's tip.

Needed as well as root validation, not instead of it: a health check reports how far the header source has got, and a service that answers roots while reporting height zero is a service that has not started.

func (*Client) HeaderAt added in v0.14.0

func (c *Client) HeaderAt(ctx context.Context, height uint32) (*Header, error)

HeaderAt reads the header at height from a source that serves header fields (WhatsOnChain, chaintracks, block-headers-service, arcade) and checks it as IsValidRootForHeight does: its fields hash to its hash, the hash carries the work its bits claim, at or above the network's floor. It is how an application with no node reads a block's hash or time by height. A native source carries no header fields and is an error.

func (*Client) IsValidRootForHeight

func (c *Client) IsValidRootForHeight(ctx context.Context, root *chainhash.Hash, height uint32) (bool, error)

IsValidRootForHeight reports whether root is the merkle root committed at height.

A 404 is (false, nil): the bridge does not hold that height yet, which means the proof cannot be checked, not that anything is broken. Any OTHER non-ok status is an ERROR, and the distinction is load-bearing. Collapsing the two makes an unreachable or misconfigured header service look exactly like a forged proof, and a verifier that cannot tell those apart will either accept forgeries during an outage or reject good proofs during one, depending on which way it guessed.

type Header struct {
	Height     uint32
	Hash       chainhash.Hash
	Prev       chainhash.Hash
	MerkleRoot chainhash.Hash
	Version    uint32
	Time       uint32
	Bits       uint32
	Nonce      uint32
}

Header is a block header a source served, its proof of work checked: the fields its hash commits to, the hash, and the height the source placed it at. Time is the block's own timestamp (Unix seconds).

type Kind added in v0.3.0

type Kind int

Kind names the dialect a header source speaks.

const (
	// Native is an overlay bridge's /v1 routes: a root per height and a tip,
	// with no header fields, so no proof of work can be checked.
	Native Kind = iota
	// WhatsOnChain is the public WhatsOnChain API for one network.
	WhatsOnChain
	// Chaintracks is a chaintracks v2 service (GET /height and
	// GET /header/height/{h} under the base).
	Chaintracks
	// BlockHeadersService is a block-headers-service (bsv-blockchain)
	// API: GET /chain/tip/longest and GET /chain/header/byHeight under
	// /api/v1, with a bearer token when the service requires one.
	BlockHeadersService
	// Arcade is the chaintracks server an arcade installation embeds,
	// under /chaintracks/v2: GET /height and GET /header/height/{h}, each
	// answering the value bare rather than in a status envelope.
	Arcade
)

func Parse added in v0.3.0

func Parse(spec string) (Kind, string, string, error)

Parse reads a header source specification:

woc:main | woc:test          the public WhatsOnChain API
chaintracks:https://host/v2  a chaintracks v2 service
bhs:https://host:8080        a block-headers-service (/api/v1 is added
                             to a URL with no path); set Client.Token
                             when it requires one
arcade:https://host          an arcade installation's embedded
                             chaintracks server (/chaintracks/v2)
https://host:port            an overlay bridge's native /v1 routes

and reports the kind, the base URL and the network the kind implies ("" for a native source, which carries no header fields to check). chaintracks, bhs and arcade imply mainnet; set Client.Network for a testnet one.

func (Kind) String added in v0.3.0

func (k Kind) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL