spv

package
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Jul 8, 2025 License: ISC Imports: 11 Imported by: 0

Documentation

Overview

Package spv is a simple payment verification library for Bitcoin SV. It is designed to be used by applications that need to verify payments without needing to run a full node. It uses TSC formats for the extended data required to verify an inbound transaction.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNoTxInputs returns if an ancestry is attempted to be created from a transaction that has no inputs.
	ErrNoTxInputs = errors.New("provided tx has no inputs to build ancestry from")

	// ErrPaymentNotVerified returns if a transaction in the tree provided was missed during verification.
	ErrPaymentNotVerified = errors.New("a tx was missed during validation")

	// ErrTipTxConfirmed returns if the tip transaction is already confirmed.
	ErrTipTxConfirmed = errors.New("tip transaction must be unconfirmed")

	// ErrNoConfirmedTransaction returns if a path from tip to beginning/anchor contains no confirmed transaction.
	ErrNoConfirmedTransaction = errors.New("not confirmed/anchored tx(s) provided")

	// ErrTxIDMismatch returns if they key value pair of a transactions input has a mismatch in txID.
	ErrTxIDMismatch = errors.New("input and proof ID mismatch")

	// ErrNotAllInputsSupplied returns if an unconfirmed transaction in ancestry contains inputs which are not
	// present in the parent ancestor.
	ErrNotAllInputsSupplied = errors.New("a tx input missing in parent ancestor")

	// ErrNoTxInputsToVerify returns if a transaction has no inputs.
	ErrNoTxInputsToVerify = errors.New("a tx has no inputs to verify")

	// ErrNilInitialPayment returns if a transaction has no inputs.
	ErrNilInitialPayment = errors.New("initial payment cannot be nil")

	// ErrInputRefsOutOfBoundsOutput returns if a transaction has no inputs.
	ErrInputRefsOutOfBoundsOutput = errors.New("tx input index into output is out of bounds")

	// ErrNoFeeQuoteSupplied is returned when VerifyFees is enabled but no bt.FeeQuote has been supplied.
	ErrNoFeeQuoteSupplied = errors.New("no bt.FeeQuote supplied for fee validation, supply the bt.FeeQuote using VerifyFees opt")

	// ErrFeePaidNotEnough returned when not enough fees have been paid.
	ErrFeePaidNotEnough = errors.New("not enough fees paid")

	// ErrCannotCalculateFeePaid returned when fee check is enabled but the tx has no parents.
	ErrCannotCalculateFeePaid = errors.New("no parents supplied in ancestry which means we cannot valdiate " +
		"fees, either ensure parents are supplied or remove fee check")

	// ErrInvalidProof is returned if the merkle proof validation fails.
	ErrInvalidProof = errors.New("invalid merkle proof, payment invalid")

	// ErrMissingOutput is returned when checking fees if an output in a parent tx is missing.
	ErrMissingOutput = errors.New("expected output used in payment tx missing")

	// ErrProofOrInputMissing returns if a path from tip to beginning/anchor is broken.
	ErrProofOrInputMissing = errors.New("break in the ancestry missing either a parent transaction or a proof")

	// ErrTriedToParseZeroBytes returns when we attempt to parse a slice of bytes of zero length which should be a mapi response.
	ErrTriedToParseZeroBytes = errors.New("there are no mapi response bytes to parse")

	// ErrUnsupporredVersion returns if another version of the binary format is being used - since we cannot guarantee we know how to parse it.
	ErrUnsupporredVersion = errors.New("we only support version 1 of the Ancestor Binary format")

	// ErrInvalidMerkleFlags returns if a merkle proof being verified uses something other than the one currently supported.
	ErrInvalidMerkleFlags = errors.New("invalid flags used in merkle proof")

	// ErrMissingTxidInProof returns if there's a missing txid in the proof.
	ErrMissingTxidInProof = errors.New("missing txid in proof")

	// ErrMissingRootInProof returns if there's a missing root in the proof.
	ErrMissingRootInProof = errors.New("missing root in proof")

	// ErrInvalidNodes returns if there is a * on the left hand side within the node array.
	ErrInvalidNodes = errors.New("invalid nodes")
)

Functions

This section is empty.

Types

type AncestryJSON

type AncestryJSON struct {
	TxID          string                   `json:"txid,omitempty"`
	RawTx         string                   `json:"rawTx,omitempty"`
	Proof         *bc.MerkleProof          `json:"proof,omitempty"`
	MapiResponses []bc.MapiCallback        `json:"mapiResponses,omitempty"`
	Parents       map[string]*AncestryJSON `json:"parents,omitempty"`
}

AncestryJSON is a struct that contains all information needed for a transaction to be verified. this contains all ancestors for the transaction allowing proofs, etc. to be verified.

This is the JSON format of the Ancestry but in a nested format (in comparison) with the flat structure that the TSC uses. This allows verification to become a lot easier and use a recursive function.

func (*AncestryJSON) Bytes

func (e *AncestryJSON) Bytes() ([]byte, error)

Bytes take a TxAncestry struct and returns the serialized binary format.

func (*AncestryJSON) HasParents

func (e *AncestryJSON) HasParents() bool

HasParents returns true if this ancestry has immediate parents.

func (*AncestryJSON) IsAnchored

func (e *AncestryJSON) IsAnchored() bool

IsAnchored returns true if the ancestry has a merkle proof.

func (*AncestryJSON) ParentTx

func (e *AncestryJSON) ParentTx(txID string) (*bt.Tx, error)

ParentTx will return a parent if found and convert the rawTx to a bt.TX, otherwise an ErrNotAllInputsSupplied error is returned.

type Envelope

type Envelope struct {
	TxID          string               `json:"txid,omitempty"`
	RawTx         string               `json:"rawTx,omitempty"`
	Proof         *bc.MerkleProof      `json:"proof,omitempty"`
	MapiResponses []bc.MapiCallback    `json:"mapiResponses,omitempty"`
	Parents       map[string]*Envelope `json:"parents,omitempty"`
}

Envelope is a struct that contains all information needed for a transaction to be verified.

spec at https://tsc.bitcoinassociation.net/standards/spv-envelope/

func NewCrunchyNutEnvelopeFromBytes

func NewCrunchyNutEnvelopeFromBytes(b []byte) (*Envelope, error)

NewCrunchyNutEnvelopeFromBytes will encode a spv envelope byte slice into the Envelope structure.

func NewSpecialKEnvelopeFromBytes

func NewSpecialKEnvelopeFromBytes(b []byte) (*Envelope, error)

NewSpecialKEnvelopeFromBytes will encode a spv envelope byte slice into the Envelope structure.

func (*Envelope) CrunchyNutBytes

func (e *Envelope) CrunchyNutBytes() (*[]byte, error)

CrunchyNutBytes takes a spvEnvelope struct and returns a pointer to the serialized bytes.

func (*Envelope) HasParents

func (e *Envelope) HasParents() bool

HasParents returns true if this envelope has immediate parents.

func (*Envelope) IsAnchored

func (e *Envelope) IsAnchored() bool

IsAnchored returns true if the envelope is the anchor tx.

func (*Envelope) ParentTX

func (e *Envelope) ParentTX(txID string) (*bt.Tx, error)

ParentTX will return a parent if found and convert the rawTx to a bt.TX, otherwise an ErrNotAllInputsSupplied error is returned.

func (*Envelope) SpecialKBytes

func (e *Envelope) SpecialKBytes() (*[]byte, error)

SpecialKBytes takes a spvEnvelope struct and returns a pointer to the serialized bytes.

type MerkleProofStore

type MerkleProofStore interface {
	MerkleProof(ctx context.Context, txID string) (*bc.MerkleProof, error)
}

MerkleProofStore interfaces a Merkle Proof store.

type MerkleProofValidation

type MerkleProofValidation struct {
	TxID         string
	Valid        bool
	IsLastInTree bool
}

MerkleProofValidation is a wrapper for the response of a validation operation.

type MerkleProofVerifier

type MerkleProofVerifier interface {
	VerifyMerkleProof(ctx context.Context, b []byte) (*MerkleProofValidation, error)
	VerifyMerkleProofJSON(ctx context.Context, p *bc.MerkleProof) (bool, bool, error)
}

MerkleProofVerifier interfaces the verification of Merkle Proofs.

func NewMerkleProofVerifier

func NewMerkleProofVerifier(bhc bc.BlockHeaderChain) (MerkleProofVerifier, error)

NewMerkleProofVerifier creates a new spv.MerkleProofVerifier with the bc.BlockHeaderChain provided. If no BlockHeaderChain implementation is provided, the setup will return an error.

type Payment

type Payment struct {
	PaymentTx *bt.Tx
	Ancestry  []byte
}

Payment is a payment and its ancestry.

type PaymentVerifier

type PaymentVerifier interface {
	VerifyPayment(ctx context.Context, p *Payment, opts ...VerifyOpt) error
	MerkleProofVerifier
}

A PaymentVerifier is an interface used to complete Simple Payment Verification (SPV) in conjunction with a Merkle Proof.

The implementation of bc.BlockHeaderChain, which is supplied, will depend on the client you are using; some may return a HeaderJSON response, others may return the blockhash.

func NewPaymentVerifier

func NewPaymentVerifier(bhc bc.BlockHeaderChain, opts ...VerifyOpt) (PaymentVerifier, error)

NewPaymentVerifier creates a new spv.PaymentVerifier with the bc.BlockHeaderChain provided. If no BlockHeaderChain implementation is provided, the setup will return an error.

opts control the global behavior of the verifier, and all options are enabled by default, they are: - ancestry verification (proofs checked etc.) - fees checked, ensuring the root tx covers enough fees - script verification which checks the script is correct (not currently implemented).

type TSCAncestriesJSON

type TSCAncestriesJSON []TSCAncestryJSON

TSCAncestriesJSON spec at https://tsc.bitcoinassociation.net/standards/transaction-ancestors/ eventually.

func NewAncestryJSONFromBytes

func NewAncestryJSONFromBytes(b []byte) (TSCAncestriesJSON, error)

NewAncestryJSONFromBytes is a way to create the JSON format for Ancestry from the binary format.

func (TSCAncestriesJSON) Bytes

func (j TSCAncestriesJSON) Bytes() ([]byte, error)

Bytes take an AncestryJSON and return the serialized bytes.

type TSCAncestryJSON

type TSCAncestryJSON struct {
	RawTx         string             `json:"rawtx,omitempty"`
	Proof         *bc.MerkleProof    `json:"proof,omitempty"`
	MapiResponses []*bc.MapiCallback `json:"mapiResponses,omitempty"`
}

TSCAncestryJSON is one of the serial objects within the overall list of ancestors.

This JSON structure follows the TSC definition even though the other JSON structure used in ancestry_json.go is more useful for verification.

type TxAncestryCreator

type TxAncestryCreator interface {
	CreateTxAncestry(ctx context.Context, tx *bt.Tx) (*AncestryJSON, error)
}

An TxAncestryCreator is an interface used to build the spv.TxAncestry data type for Simple Payment Verification (SPV).

The implementation of an spv.TxStore and spv.MerkleProofStore which is supplied will depend on the client you are using.

func NewEnvelopeCreator

func NewEnvelopeCreator(txc TxStore, mpc MerkleProofStore) (TxAncestryCreator, error)

NewEnvelopeCreator creates a new spv.Creator with the provided spv.TxStore and tx.MerkleProofStore. If either implementation is not provided, the setup will return an error.

type TxStore

type TxStore interface {
	Tx(ctx context.Context, txID string) (*bt.Tx, error)
}

TxStore interfaces the a tx store.

type VerifyOpt

type VerifyOpt func(opts *verifyOptions)

VerifyOpt defines a functional option used to modify the behavior of the payment verifier.

func NoVerifyFees

func NoVerifyFees() VerifyOpt

NoVerifyFees will switch off transaction fee verification and rely on mAPI / node verification when the transaction is broadcast.

func NoVerifyProofs

func NoVerifyProofs() VerifyOpt

NoVerifyProofs will switch off ancestry proof verification and rely on mAPI/node verification when the tx is broadcast.

func NoVerifySPV

func NoVerifySPV() VerifyOpt

NoVerifySPV will turn off any spv validation for merkle proofs and script validation. This is a helper method that is equivalent to NoVerifyProofs && NoVerifyScripts.

func NoVerifyScript

func NoVerifyScript() VerifyOpt

NoVerifyScript will switch off script verification and rely on mAPI / node verification when the tx is broadcast.

func VerifyFees

func VerifyFees(fees *bt.FeeQuote) VerifyOpt

VerifyFees will make the verifier check the transaction fees of the supplied transaction are enough based on the feeQuote provided.

It is recommended to provide a fresh fee quote when calling the VerifyPayment method rather than loading fees when calling NewPaymentVerifier as fees can go out of date over the lifetime of the application and you may be supplying different feeQuotes to different consumers.

func VerifyProofs

func VerifyProofs() VerifyOpt

VerifyProofs will make the verifier validate the ancestry merkle proofs for each parent transaction.

func VerifySPV

func VerifySPV() VerifyOpt

VerifySPV will turn on spv validation for merkle proofs and script validation. This is a helper method that is equivalent to VerifyProofs && VerifyScripts.

func VerifyScript

func VerifyScript() VerifyOpt

VerifyScript will ensure the scripts provided in the transaction are valid.

Jump to

Keyboard shortcuts

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