bt

package module
v2.2.5 Latest Latest
Warning

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

Go to latest
Published: Sep 8, 2023 License: ISC Imports: 16 Imported by: 78

README

go-bt

The go-to Bitcoin Transaction (BT) GoLang library

Release Build Status Report codecov Go Sponsor Donate Mergify Status


Table of Contents


Installation

go-bt requires a supported release of Go.

go get -u github.com/libsv/go-bt/v2

Documentation

View the generated documentation

GoDoc

For more information around the technical aspects of Bitcoin, please see the updated Bitcoin Wiki


Features
  • Full featured Bitcoin transactions and transaction manipulation/functionality
  • Auto-fee calculations for change outputs
  • Transaction fee calculation and related checks
  • Interfaced signing/unlocking of transaction inputs for easy adaptation/custimisation and extendability for any use case
  • Bitcoin Transaction Script functionality
    • Bitcoin script engine (interpreter)
    • P2PKH (base58 addresses)
    • Data (OP_RETURN)
    • BIP276
Coming Soon! (18 monthsTM)
  • Complete SigHash Flag Capability
  • MultiSig functionality
Library Deployment

goreleaser for easy binary or library deployment to Github and can be installed via: brew install goreleaser.

The .goreleaser.yml file is used to configure goreleaser.

Use make release-snap to create a snapshot version of the release, and finally make release to ship to production.

Makefile Commands

View all makefile commands

make help

List of all current commands:

all                  Runs multiple commands
clean                Remove previous builds and any test cache data
clean-mods           Remove all the Go mod cache
coverage             Shows the test coverage
godocs               Sync the latest tag with GoDocs
help                 Show this help message
install              Install the application
install-go           Install the application (Using Native Go)
lint                 Run the golangci-lint application (install if not found)
release              Full production release (creates release in Github)
release              Runs common.release then runs godocs
release-snap         Test the full release (build binaries)
release-test         Full production test release (everything except deploy)
replace-version      Replaces the version in HTML/JS (pre-deploy)
tag                  Generate a new tag and push (tag version=0.0.0)
tag-remove           Remove a tag if found (tag-remove version=0.0.0)
tag-update           Update an existing tag to current commit (tag-update version=0.0.0)
test                 Runs vet, lint and ALL tests
test-ci              Runs all tests via CI (exports coverage)
test-ci-no-race      Runs all tests via CI (no race) (exports coverage)
test-ci-short        Runs unit tests via CI (exports coverage)
test-short           Runs vet, lint and tests (excludes integration tests)
uninstall            Uninstall the application (and remove files)
update-linter        Update the golangci-lint package (macOS only)
vet                  Run the Go vet application

Examples & Tests

All unit tests and examples run via Github Actions and uses Go version 1.16.x. View the configuration file.

Run all tests (including integration tests)

make test

Run tests (excluding integration tests)

make test-short

Benchmarks

Run the Go benchmarks:

make bench

Code Standards

Read more about this Go project's code standards.


Usage

View the examples


Contributing

View the contributing guidelines and please follow the code of conduct.

How can I help?

All kinds of contributions are welcome 🙌! The most basic way to show your support is to star 🌟 the project, or to raise issues 💬. You can also support this project by becoming a sponsor on GitHub 👏 or by making a bitcoin donation to ensure this journey continues indefinitely! 🚀

Stars


License

License

Documentation

Overview

Package bt provides functions needed to create and manipulate Bitcoin transactions.

Index

Constants

View Source
const (
	// MaxTxInSequenceNum is the maximum sequence number the sequence field
	// of a transaction input can be.
	MaxTxInSequenceNum uint32 = 0xffffffff

	// MaxPrevOutIndex is the maximum index the index field of a previous
	// outpoint can be.
	MaxPrevOutIndex uint32 = 0xffffffff

	// SequenceLockTimeDisabled is a flag that if set on a transaction
	// input's sequence number, the sequence number will not be interpreted
	// as a relative locktime.
	SequenceLockTimeDisabled = 1 << 31

	// SequenceLockTimeIsSeconds is a flag that if set on a transaction
	// input's sequence number, the relative locktime has units of 512
	// seconds.
	SequenceLockTimeIsSeconds = 1 << 22

	// SequenceLockTimeMask is a mask that extracts the relative locktime
	// when masked against the transaction input sequence number.
	SequenceLockTimeMask = 0x0000ffff
)
View Source
const DefaultSequenceNumber uint32 = 0xFFFFFFFF

DefaultSequenceNumber is the default starting sequence number

View Source
const (
	// DustLimit is the current minimum txo output accepted by miners.
	DustLimit = 1
)
View Source
const OrdinalsPrefix = "ord"

OrdinalsPrefix contains 'ORD' the inscription protocol prefix.

Check the docs here: https://docs.1satordinals.com/

Variables

View Source
var (
	ErrInvalidTxID       = errors.New("invalid TxID")
	ErrTxNil             = errors.New("tx is nil")
	ErrTxTooShort        = errors.New("too short to be a tx - even an empty tx has 10 bytes")
	ErrNLockTimeLength   = errors.New("nLockTime length must be 4 bytes long")
	ErrEmptyValues       = errors.New("empty value or values passed, all arguments are required and cannot be empty")
	ErrUnsupportedScript = errors.New("non-P2PKH input used in the tx - unsupported")
	ErrInvalidScriptType = errors.New("invalid script type")
	ErrNoUnlocker        = errors.New("unlocker not supplied")
)

General errors.

View Source
var (
	ErrInputNoExist  = errors.New("specified input does not exist")
	ErrInputTooShort = errors.New("input length too short")

	// You should not be able to spend an input with 0 Satoshi value.
	// Most likely the input Satoshi value is not provided.
	ErrInputSatsZero = errors.New("input satoshi value is not provided")
)

Sentinal errors reported by inputs.

View Source
var (
	ErrOutputNoExist  = errors.New("specified output does not exist")
	ErrOutputTooShort = errors.New("output length too short")
)

Sentinal errors reported by outputs.

View Source
var (
	ErrEmptyPreviousTxID     = errors.New("'PreviousTxID' not supplied")
	ErrEmptyPreviousTxScript = errors.New("'PreviousTxScript' not supplied")
)

Sentinal errors reported by signature hash.

View Source
var (
	ErrFeeQuotesNotInit = errors.New("feeQuotes have not been setup, call NewFeeQuotes")
	ErrMinerNoQuotes    = errors.New("miner has no quotes stored")
	ErrFeeTypeNotFound  = errors.New("feetype not found")
	ErrFeeQuoteNotInit  = errors.New("feeQuote has not been initialised, call NewFeeQuote()")
	ErrUnknownFeeType   = errors.New("unknown fee type")
)

Sentinel errors reported by the fees.

View Source
var (
	// ErrNoUTXO signals the UTXOGetterFunc has reached the end of its input.
	ErrNoUTXO = errors.New("no remaining utxos")

	// ErrInsufficientFunds insufficient funds provided for funding
	ErrInsufficientFunds = errors.New("insufficient funds provided")
)

Sentinel errors reported by Fund.

View Source
var (
	ErrDummyInput            = errors.New("failed to add dummy input 0")
	ErrInsufficientUTXOs     = errors.New("need at least 2 utxos")
	ErrInsufficientUTXOValue = errors.New("need at least 1 utxos which is > ordinal price")
	ErrUTXOInputMismatch     = errors.New("utxo and input mismatch")
	ErrInvalidSellOffer      = errors.New("invalid sell offer (partially signed tx)")
	ErrEmptyScripts          = errors.New("at least one of needed scripts is empty")
	ErrInsufficientFees      = errors.New("fee paid not enough with new locking script")
)

Sentinal errors reported by PSBTs.

View Source
var (
	ErrInsufficientInputs = errors.New("satoshis inputted to the tx are less than the outputted satoshis")
)

Sentinal errors reported by change.

View Source
var (
	ErrOutputsNotEmpty = errors.New("transaction outputs must be empty to avoid messing with Ordinal ordering scheme")
)

Sentinal errors reported by ordinal inscriptions.

Functions

func IsValidTxID

func IsValidTxID(txid []byte) bool

IsValidTxID will check that the txid bytes are valid.

A txid should be of 32 bytes length.

func LittleEndianBytes

func LittleEndianBytes(v uint32, l uint32) []byte

LittleEndianBytes returns a byte array in little endian from an unsigned integer of 32 bytes.

func ReverseBytes

func ReverseBytes(a []byte) []byte

ReverseBytes reverses the bytes (little endian/big endian). This is used when computing merkle trees in Bitcoin, for example.

Types

type Fee

type Fee struct {
	FeeType   FeeType `json:"-"` // standard || data
	MiningFee FeeUnit `json:"miningFee"`
	RelayFee  FeeUnit `json:"relayFee"` // Fee for retaining Tx in secondary mempool
}

Fee displays the MiningFee as well as the RelayFee for a specific FeeType, for example 'standard' or 'data' see https://github.com/bitcoin-sv-specs/brfc-misc/tree/master/feespec

type FeeQuote

type FeeQuote struct {
	// contains filtered or unexported fields
}

FeeQuote contains a thread safe map of fees for standard and data fees as well as an expiry time for a specific miner.

This can be used if you are only dealing with a single miner and know you will always be using a single miner. FeeQuote will store the fees for a single miner and can be passed to transactions to calculate fees when creating change outputs.

If you are dealing with quotes from multiple miners, use the FeeQuotes structure above.

NewFeeQuote() should be called to get a new instance of a FeeQuote.

When expiry expires ie Expired() == true then you should fetch new quotes from a MAPI server and call AddQuote with the fee information.

func NewFeeQuote

func NewFeeQuote() *FeeQuote

NewFeeQuote will set up and return a new FeeQuotes struct which contains default fees when initially setup. You would then pass this data structure to a singleton struct via injection for reading. If you are only getting quotes from one miner you can use this directly instead of using the NewFeeQuotes() method which is for storing multiple miner quotes.

fq := NewFeeQuote()

The fees have an expiry time which, when initially setup, has an expiry of now.UTC. This allows you to check for fq.Expired() and if true fetch a new set of fees from a MAPI server. This means the first check will always fetch the latest fees. If you want to just use default fees always, you can ignore the expired method and simply call the fq.Fee() method. https://github.com/bitcoin-sv-specs/brfc-merchantapi#payload

A basic example of usage is shown below:

func Fee(ft bt.FeeType) *bt.Fee{
   // you would not call this every time - this is just an example
   // you'd call this at app startup and store it / pass to a struct
   fq := NewFeeQuote()

   // fq setup with defaultFees
   if !fq.Expired() {
      // not expired, just return fee we have cached
      return fe.Fee(ft)
   }

   // cache expired, fetch new quotes
   var stdFee *bt.Fee
   var dataFee *bt.Fee

   // fetch quotes from MAPI server

   fq.AddQuote(bt.FeeTypeStandard, stdFee)
   fq.AddQuote(bt.FeeTypeData, dataFee)

   // MAPI returns a quote expiry
   exp, _ := time.Parse(time.RFC3339, resp.Quote.ExpirationTime)
   fq.UpdateExpiry(exp)
   return fe.Fee(ft)
}

It will set the expiry time to now.UTC which when expires will indicate that new quotes should be fetched from a MAPI server.

func (*FeeQuote) AddQuote

func (f *FeeQuote) AddQuote(ft FeeType, fee *Fee) *FeeQuote

AddQuote will add new set of quotes for a feetype or update an existing quote if it already exists.

func (*FeeQuote) Expired

func (f *FeeQuote) Expired() bool

Expired will return true if the expiry time is before UTC now, this means we need to fetch fresh quotes from a MAPI server.

func (*FeeQuote) Expiry

func (f *FeeQuote) Expiry() time.Time

Expiry will return the expiry timestamp for the `bt.FeeQuote` in a threadsafe manner.

func (*FeeQuote) Fee

func (f *FeeQuote) Fee(t FeeType) (*Fee, error)

Fee will return a fee by type if found, nil and an error if not.

func (*FeeQuote) MarshalJSON

func (f *FeeQuote) MarshalJSON() ([]byte, error)

MarshalJSON will convert the FeeQuote to a json object with the format as shown:

 {
	 "data": {
		 "miningFee": {
			 "satoshis": 5,
			 "bytes": 2
		 },
		 "relayFee": {
			 "satoshis": 8,
			 "bytes": 4
		 }
	 },
	 "standard": {
		 "miningFee": {
			 "satoshis": 100,
			 "bytes": 10
		 },
		 "relayFee": {
			 "satoshis": 10,
			 "bytes": 5
		 }
	 }
 }

func (*FeeQuote) UnmarshalJSON

func (f *FeeQuote) UnmarshalJSON(body []byte) error

UnmarshalJSON will convert a json encoded FeeQuote back into a fee quote type, the expected JSON format is shown above in the MarshalJSON function. If the fee type supplied is unknown an ErrUnknownFeeType will be returned.

func (*FeeQuote) UpdateExpiry

func (f *FeeQuote) UpdateExpiry(exp time.Time)

UpdateExpiry will update the expiry time of the quotes, this will be used when you fetch a fresh set of quotes from a MAPI server which should return an expiration time.

type FeeQuotes

type FeeQuotes struct {
	// contains filtered or unexported fields
}

FeeQuotes contains a list of miners and the current fees for each miner as well as their expiry.

This can be used when getting fees from multiple miners, and you want to use the cheapest for example.

Usage setup should be calling NewFeeQuotes(minerName).

func NewFeeQuotes

func NewFeeQuotes(minerName string) *FeeQuotes

NewFeeQuotes will set up default feeQuotes for the minerName supplied, ie TAAL etc.

func (*FeeQuotes) AddMiner

func (f *FeeQuotes) AddMiner(minerName string, quote *FeeQuote) *FeeQuotes

AddMiner will add a new miner to the quotes map with the provided feeQuote. If you just want to add default fees use the AddMinerWithDefault method.

func (*FeeQuotes) AddMinerWithDefault

func (f *FeeQuotes) AddMinerWithDefault(minerName string) *FeeQuotes

AddMinerWithDefault will add a new miner to the quotes map with default fees & immediate expiry.

func (*FeeQuotes) Fee

func (f *FeeQuotes) Fee(minerName string, feeType FeeType) (*Fee, error)

Fee is a convenience method for quickly getting a fee by type and miner name. If the miner has no fees an ErrMinerNoQuotes error will be returned. If the feeType cannot be found an ErrFeeTypeNotFound error will be returned.

func (*FeeQuotes) Quote

func (f *FeeQuotes) Quote(minerName string) (*FeeQuote, error)

Quote will return all fees for a miner. If no fees are found an ErrMinerNoQuotes error is returned.

func (*FeeQuotes) UpdateMinerFees

func (f *FeeQuotes) UpdateMinerFees(minerName string, feeType FeeType, fee *Fee) (*FeeQuote, error)

UpdateMinerFees a convenience method to update a fee quote from a FeeQuotes struct directly. This will update the miner feeType with the provided fee. Useful after receiving new quotes from mapi.

type FeeType

type FeeType string

FeeType is used to specify which type of fee is used depending on the type of tx data (eg: standard bytes or data bytes).

const (
	// FeeTypeStandard is the fee type for standard tx parts
	FeeTypeStandard FeeType = "standard"

	// FeeTypeData is the fee type for data tx parts
	FeeTypeData FeeType = "data"
)

type FeeUnit

type FeeUnit struct {
	Satoshis int `json:"satoshis"` // Fee in satoshis of the amount of Bytes
	Bytes    int `json:"bytes"`    // Number of bytes that the Fee covers
}

FeeUnit displays the amount of Satoshis needed for a specific amount of Bytes in a transaction see https://github.com/bitcoin-sv-specs/brfc-misc/tree/master/feespec

type Input

type Input struct {
	PreviousTxSatoshis uint64
	PreviousTxScript   *bscript.Script
	UnlockingScript    *bscript.Script
	PreviousTxOutIndex uint32
	SequenceNumber     uint32
	// contains filtered or unexported fields
}

Input is a representation of a transaction input

DO NOT CHANGE ORDER - Optimised for memory via maligned

func (*Input) Bytes

func (i *Input) Bytes(clear bool) []byte

Bytes encodes the Input into a hex byte array.

func (*Input) MarshalJSON

func (i *Input) MarshalJSON() ([]byte, error)

MarshalJSON will convert an input to json, expanding upon the input struct to add additional fields.

func (*Input) PreviousTxID

func (i *Input) PreviousTxID() []byte

PreviousTxID will return the PreviousTxID if set.

func (*Input) PreviousTxIDAdd

func (i *Input) PreviousTxIDAdd(txID []byte) error

PreviousTxIDAdd will add the supplied txID bytes to the Input, if it isn't a valid transaction id an ErrInvalidTxID error will be returned.

func (*Input) PreviousTxIDAddStr

func (i *Input) PreviousTxIDAddStr(txID string) error

PreviousTxIDAddStr will validate and add the supplied txID string to the Input, if it isn't a valid transaction id an ErrInvalidTxID error will be returned.

func (*Input) PreviousTxIDStr

func (i *Input) PreviousTxIDStr() string

PreviousTxIDStr returns the Previous TxID as a hex string.

func (*Input) ReadFrom

func (i *Input) ReadFrom(r io.Reader) (int64, error)

ReadFrom reads from the `io.Reader` into the `bt.Input`.

func (*Input) ReadFromExtended

func (i *Input) ReadFromExtended(r io.Reader) (int64, error)

ReadFromExtended reads the `io.Reader` into the `bt.Input` when the reader is consuming an extended format transaction.

func (*Input) String

func (i *Input) String() string

String implements the Stringer interface and returns a string representation of a transaction input.

func (*Input) UnmarshalJSON

func (i *Input) UnmarshalJSON(b []byte) error

UnmarshalJSON will convert a JSON input to an input.

type Output

type Output struct {
	Satoshis      uint64          `json:"satoshis"`
	LockingScript *bscript.Script `json:"locking_script"`
}

Output is a representation of a transaction output

func CreateOpReturnOutput added in v2.1.1

func CreateOpReturnOutput(data [][]byte) (*Output, error)

CreateOpReturnOutput creates a new Output with OP_FALSE OP_RETURN and then uses OP_PUSHDATA format to encode the multiple byte arrays passed in.

func (*Output) Bytes

func (o *Output) Bytes() []byte

Bytes encodes the Output into a byte array.

func (*Output) BytesForSigHash

func (o *Output) BytesForSigHash() []byte

BytesForSigHash returns the proper serialisation of an output to be hashed and signed (sighash).

func (*Output) LockingScriptHexString

func (o *Output) LockingScriptHexString() string

LockingScriptHexString returns the locking script of an output encoded as a hex string.

func (*Output) MarshalJSON

func (o *Output) MarshalJSON() ([]byte, error)

MarshalJSON will serialise an output to json.

func (*Output) NodeJSON

func (o *Output) NodeJSON() interface{}

NodeJSON returns a wrapped *bt.Output for marshalling/unmarshalling into a node output format.

Marshalling usage example:

bb, err := json.Marshal(output.NodeJSON())

Unmarshalling usage example:

output := &bt.Output{}
if err := json.Unmarshal(bb, output.NodeJSON()); err != nil {}

func (*Output) ReadFrom

func (o *Output) ReadFrom(r io.Reader) (int64, error)

ReadFrom reads from the `io.Reader` into the `bt.Output`.

func (*Output) String

func (o *Output) String() string

func (*Output) UnmarshalJSON

func (o *Output) UnmarshalJSON(b []byte) error

UnmarshalJSON will convert a json serialised output to a bt Output.

type Tx

type Tx struct {
	Inputs   []*Input  `json:"inputs"`
	Outputs  []*Output `json:"outputs"`
	Version  uint32    `json:"version"`
	LockTime uint32    `json:"locktime"`
}

Tx wraps a bitcoin transaction

DO NOT CHANGE ORDER - Optimised memory via malign

func NewTx

func NewTx() *Tx

NewTx creates a new transaction object with default values.

func NewTxFromBytes

func NewTxFromBytes(b []byte) (*Tx, error)

NewTxFromBytes takes an array of bytes, constructs a Tx and returns it. This function assumes that the byte slice contains exactly 1 transaction.

func NewTxFromStream

func NewTxFromStream(b []byte) (*Tx, int, error)

NewTxFromStream takes an array of bytes and constructs a Tx from it, returning the Tx and the bytes used. Despite the name, this is not actually reading a stream in the true sense: it is a byte slice that contains many transactions one after another.

func NewTxFromString

func NewTxFromString(str string) (*Tx, error)

NewTxFromString takes a toBytesHelper string representation of a bitcoin transaction and returns a Tx object.

func (*Tx) AddHashPuzzleOutput

func (tx *Tx) AddHashPuzzleOutput(secret, publicKeyHash string, satoshis uint64) error

AddHashPuzzleOutput makes an output to a hash puzzle + PKH with a value.

func (*Tx) AddOpReturnOutput

func (tx *Tx) AddOpReturnOutput(data []byte) error

AddOpReturnOutput creates a new Output with OP_FALSE OP_RETURN and then the data passed in encoded as hex.

func (*Tx) AddOpReturnPartsOutput

func (tx *Tx) AddOpReturnPartsOutput(data [][]byte) error

AddOpReturnPartsOutput creates a new Output with OP_FALSE OP_RETURN and then uses OP_PUSHDATA format to encode the multiple byte arrays passed in.

func (*Tx) AddOutput

func (tx *Tx) AddOutput(output *Output)

AddOutput adds a new output to the transaction.

func (*Tx) AddP2PKHInputsFromTx

func (tx *Tx) AddP2PKHInputsFromTx(pvsTx *Tx, matchPK []byte) error

AddP2PKHInputsFromTx will add all Outputs of given previous transaction that match a specific public key to your transaction.

func (*Tx) AddP2PKHOutputFromAddress

func (tx *Tx) AddP2PKHOutputFromAddress(addr string, satoshis uint64) error

AddP2PKHOutputFromAddress makes an output to a PKH with a value.

func (*Tx) AddP2PKHOutputFromBip32ExtKey

func (tx *Tx) AddP2PKHOutputFromBip32ExtKey(privKey *bip32.ExtendedKey, satoshis uint64) (string, error)

AddP2PKHOutputFromBip32ExtKey generated a random P2PKH output script from a provided *bip32.ExtendedKey, and add it to the receiving tx. The derviation path used is returned.

func (*Tx) AddP2PKHOutputFromPubKeyBytes

func (tx *Tx) AddP2PKHOutputFromPubKeyBytes(publicKeyBytes []byte, satoshis uint64) error

AddP2PKHOutputFromPubKeyBytes makes an output to a PKH with a value.

func (*Tx) AddP2PKHOutputFromPubKeyHashStr

func (tx *Tx) AddP2PKHOutputFromPubKeyHashStr(publicKeyHash string, satoshis uint64) error

AddP2PKHOutputFromPubKeyHashStr makes an output to a PKH with a value.

func (*Tx) AddP2PKHOutputFromPubKeyStr

func (tx *Tx) AddP2PKHOutputFromPubKeyStr(publicKey string, satoshis uint64) error

AddP2PKHOutputFromPubKeyStr makes an output to a PKH with a value.

func (*Tx) AddP2PKHOutputFromScript

func (tx *Tx) AddP2PKHOutputFromScript(script *bscript.Script, satoshis uint64) error

AddP2PKHOutputFromScript makes an output to a P2PKH script paid to the provided locking script with a value.

func (*Tx) Bytes

func (tx *Tx) Bytes() []byte

Bytes encodes the transaction into a byte array. See https://chainquery.com/bitcoin-cli/decoderawtransaction

func (*Tx) BytesWithClearedInputs

func (tx *Tx) BytesWithClearedInputs(index int, lockingScript []byte) []byte

BytesWithClearedInputs encodes the transaction into a byte array but clears its Inputs first. This is used when signing transactions.

func (*Tx) CalcInputPreimage

func (tx *Tx) CalcInputPreimage(inputNumber uint32, sigHashFlag sighash.Flag) ([]byte, error)

CalcInputPreimage serialises the transaction based on the input index and the SIGHASH flag and returns the preimage before double hashing (SHA256d).

see https://github.com/bitcoin-sv/bitcoin-sv/blob/master/doc/abc/replay-protected-sighash.md#digest-algorithm

func (*Tx) CalcInputPreimageLegacy

func (tx *Tx) CalcInputPreimageLegacy(inputNumber uint32, shf sighash.Flag) ([]byte, error)

CalcInputPreimageLegacy serialises the transaction based on the input index and the SIGHASH flag and returns the preimage before double hashing (SHA256d), in the legacy format.

see https://wiki.bitcoinsv.io/index.php/Legacy_Sighash_Algorithm

func (*Tx) CalcInputSignatureHash

func (tx *Tx) CalcInputSignatureHash(inputNumber uint32, sigHashFlag sighash.Flag) ([]byte, error)

CalcInputSignatureHash serialised the transaction and returns the hash digest to be signed. BitCoin (SV) uses a different signature hashing algorithm after the UAHF fork for replay protection.

see https://github.com/bitcoin-sv/bitcoin-sv/blob/master/doc/abc/replay-protected-sighash.md#digest-algorithm

func (*Tx) Change

func (tx *Tx) Change(s *bscript.Script, f *FeeQuote) error

Change calculates the amount of fees needed to cover the transaction

and adds the leftover change in a new output using the script provided.

func (*Tx) ChangeToAddress

func (tx *Tx) ChangeToAddress(addr string, f *FeeQuote) error

ChangeToAddress calculates the amount of fees needed to cover the transaction and adds the leftover change in a new P2PKH output using the address provided.

func (*Tx) ChangeToExistingOutput

func (tx *Tx) ChangeToExistingOutput(index uint, f *FeeQuote) error

ChangeToExistingOutput will calculate fees and add them to an output at the index specified (0 based). If an invalid index is supplied and error is returned.

func (*Tx) Clone

func (tx *Tx) Clone() *Tx

Clone returns a clone of the tx

func (*Tx) EstimateFeesPaid

func (tx *Tx) EstimateFeesPaid(fees *FeeQuote) (*TxFees, error)

EstimateFeesPaid will estimate how big the tx will be when finalised by estimating input unlocking scripts that have not yet been filled including the individual fee types (std/data/etc.).

func (*Tx) EstimateIsFeePaidEnough

func (tx *Tx) EstimateIsFeePaidEnough(fees *FeeQuote) (bool, error)

EstimateIsFeePaidEnough will calculate the fees that this transaction is paying including the individual fee types (std/data/etc.), and will add 107 bytes to the unlocking script of any unsigned inputs (only P2PKH for now) found to give a final size estimate of the tx size for fee calculation.

func (*Tx) EstimateSize

func (tx *Tx) EstimateSize() (int, error)

EstimateSize will return the size of tx in bytes and will add 107 bytes to the unlocking script of any unsigned inputs (only P2PKH for now) found to give a final size estimate of the tx size.

func (*Tx) EstimateSizeWithTypes

func (tx *Tx) EstimateSizeWithTypes() (*TxSize, error)

EstimateSizeWithTypes will return the size of tx in bytes, including the different data types (std/data/etc.), and will add 107 bytes to the unlocking script of any unsigned inputs (only P2PKH for now) found to give a final size estimate of the tx size.

func (*Tx) ExtendedBytes

func (tx *Tx) ExtendedBytes() []byte

ExtendedBytes outputs the transaction into a byte array in extended format (with PreviousTxSatoshis and PreviousTXScript included)

func (*Tx) FillAllInputs

func (tx *Tx) FillAllInputs(ctx context.Context, ug UnlockerGetter) error

FillAllInputs is used to sign all inputs. It takes an UnlockerGetter interface as a parameter so that different unlocking implementations can be used to sign the transaction - for example local/external signing, or P2PKH/contract signing.

Given this signs inputs and outputs, sighash `ALL|FORKID` is used.

func (*Tx) FillInput

func (tx *Tx) FillInput(ctx context.Context, unlocker Unlocker, params UnlockerParams) error

FillInput is used to unlock the transaction at a specific input index. It takes an Unlocker interface as a parameter so that different unlocking implementations can be used to unlock the transaction - for example local or external unlocking (hardware wallet), or signature / non-signature based.

func (*Tx) From

func (tx *Tx) From(prevTxID string, vout uint32, prevTxLockingScript string, satoshis uint64) error

From adds a new input to the transaction from the specified UTXO fields, using the default finalised sequence number (0xFFFFFFFF). If you want a different nSeq, change it manually afterwards.

func (*Tx) FromUTXOs

func (tx *Tx) FromUTXOs(utxos ...*UTXO) error

FromUTXOs adds a new input to the transaction from the specified *bt.UTXO fields, using the default finalised sequence number (0xFFFFFFFF). If you want a different nSeq, change it manually afterwards.

func (*Tx) Fund

func (tx *Tx) Fund(ctx context.Context, fq *FeeQuote, next UTXOGetterFunc) error

Fund continuously calls the provided bt.UTXOGetterFunc, adding each returned input as an input via tx.From(...), until it is estimated that inputs cover the outputs + fees.

After completion, the receiver is ready for `Change(...)` to be called, and then be signed. Note, this function works under the assumption that receiver *bt.Tx already has all the outputs which need covered.

If insufficient utxos are provided from the UTXOGetterFunc, a bt.ErrInsufficientFunds is returned.

Example usage:

if err := tx.Fund(ctx, bt.NewFeeQuote(), func(ctx context.Context, deficit satoshis) ([]*bt.UTXO, error) {
    utxos := make([]*bt.UTXO, 0)
    for _, f := range funds {
        deficit -= satoshis
        utxos := append(utxos, &bt.UTXO{
            TxID: f.TxID,
            Vout: f.Vout,
            LockingScript: f.Script,
            Satoshis: f.Satoshis,
        })
        if deficit == 0 {
            return utxos, nil
        }
    }
    return nil, bt.ErrNoUTXO
}); err != nil {
    if errors.Is(err, bt.ErrInsufficientFunds) { /* handle */ }
    return err
}

func (*Tx) HasDataOutputs

func (tx *Tx) HasDataOutputs() bool

HasDataOutputs returns true if the transaction has at least one data (OP_RETURN) output in it.

func (*Tx) InputCount

func (tx *Tx) InputCount() int

InputCount returns the number of transaction Inputs.

func (*Tx) InputIdx

func (tx *Tx) InputIdx(i int) *Input

InputIdx will return the input at the specified index.

This will consume an overflow error and simply return nil if the input isn't found at the index.

func (*Tx) Inscribe added in v2.2.0

func (tx *Tx) Inscribe(ia *bscript.InscriptionArgs) error

Inscribe adds an output to the transaction with an inscription.

func (*Tx) InscribeSpecificOrdinal added in v2.2.0

func (tx *Tx) InscribeSpecificOrdinal(ia *bscript.InscriptionArgs, inputIdx uint32, satoshiIdx uint64,
	extraOutputScript *bscript.Script) error

InscribeSpecificOrdinal gives you the functionality to choose a specific ordinal from the inputs to inscribe.

You need to provide the input and Satoshi range indices in order to specify the ordinal you would like to inscribe, along with the change addresses to be used for the rest of the Satoshis.

One output will be created with the extra Satoshis and then another output will be created with 1 Satoshi with the inscription in it.

func (*Tx) InsertInputUnlockingScript

func (tx *Tx) InsertInputUnlockingScript(index uint32, s *bscript.Script) error

InsertInputUnlockingScript applies a script to the transaction at a specific index in unlocking script field.

func (*Tx) IsCoinbase

func (tx *Tx) IsCoinbase() bool

IsCoinbase determines if this transaction is a coinbase by checking if the tx input is a standard coinbase input.

func (*Tx) IsFeePaidEnough

func (tx *Tx) IsFeePaidEnough(fees *FeeQuote) (bool, error)

IsFeePaidEnough will calculate the fees that this transaction is paying including the individual fee types (std/data/etc.).

func (*Tx) MarshalJSON

func (tx *Tx) MarshalJSON() ([]byte, error)

MarshalJSON will serialise a transaction to json.

func (*Tx) NodeJSON

func (tx *Tx) NodeJSON() interface{}

NodeJSON returns a wrapped *bt.Tx for marshalling/unmarshalling into a node tx format.

Marshalling usage example:

bb, err := json.Marshal(tx.NodeJSON())

Unmarshalling usage example:

tx := bt.NewTx()
if err := json.Unmarshal(bb, tx.NodeJSON()); err != nil {}

func (*Tx) OutputCount

func (tx *Tx) OutputCount() int

OutputCount returns the number of transaction Inputs.

func (*Tx) OutputIdx

func (tx *Tx) OutputIdx(i int) *Output

OutputIdx will return the output at the specified index.

This will consume an overflow error and simply return nil if the output isn't found at the index.

func (*Tx) OutputsHash

func (tx *Tx) OutputsHash(n int32) []byte

OutputsHash returns a bytes slice of the requested output, used for generating the txs signature hash. If n is -1, it will create the byte slice from all outputs.

func (*Tx) PayTo

func (tx *Tx) PayTo(script *bscript.Script, satoshis uint64) error

PayTo creates a new P2PKH output from a BitCoin address (base58) and the satoshis amount and adds that to the transaction.

func (*Tx) PayToAddress

func (tx *Tx) PayToAddress(addr string, satoshis uint64) error

PayToAddress creates a new P2PKH output from a BitCoin address (base58) and the satoshis amount and adds that to the transaction.

func (*Tx) PreviousOutHash

func (tx *Tx) PreviousOutHash() []byte

PreviousOutHash returns a byte slice of inputs outpoints, for creating a signature hash

func (*Tx) ReadFrom

func (tx *Tx) ReadFrom(r io.Reader) (int64, error)

ReadFrom reads from the `io.Reader` into the `bt.Tx`.

func (*Tx) SequenceHash

func (tx *Tx) SequenceHash() []byte

SequenceHash returns a byte slice of inputs SequenceNumber, for creating a signature hash

func (*Tx) Size

func (tx *Tx) Size() int

Size will return the size of tx in bytes.

func (*Tx) SizeWithTypes

func (tx *Tx) SizeWithTypes() *TxSize

SizeWithTypes will return the size of tx in bytes and include the different data types (std/data/etc.).

func (*Tx) String

func (tx *Tx) String() string

String encodes the transaction into a hex string.

func (*Tx) TotalInputSatoshis

func (tx *Tx) TotalInputSatoshis() (total uint64)

TotalInputSatoshis returns the total Satoshis inputted to the transaction.

func (*Tx) TotalOutputSatoshis

func (tx *Tx) TotalOutputSatoshis() (total uint64)

TotalOutputSatoshis returns the total Satoshis outputted from the transaction.

func (*Tx) TxID

func (tx *Tx) TxID() string

TxID returns the transaction ID of the transaction (which is also the transaction hash).

func (*Tx) TxIDBytes

func (tx *Tx) TxIDBytes() []byte

TxIDBytes returns the transaction ID of the transaction as bytes (which is also the transaction hash).

func (*Tx) UnmarshalJSON

func (tx *Tx) UnmarshalJSON(b []byte) error

UnmarshalJSON will unmarshall a transaction that has been marshalled with this library.

type TxFees

type TxFees struct {
	// TotalFeePaid is the total amount of fees this tx will pay.
	TotalFeePaid uint64
	// StdFeePaid is the amount of fee to cover the standard inputs and outputs etc.
	StdFeePaid uint64
	// DataFeePaid is the amount of fee to cover the op_return data outputs.
	DataFeePaid uint64
}

TxFees is returned when CalculateFee is called and contains a breakdown of the fees including the total and the size breakdown of the tx in bytes.

type TxSize

type TxSize struct {
	// TotalBytes are the amount of bytes for the entire tx.
	TotalBytes uint64
	// TotalStdBytes are the amount of bytes for the tx minus the data bytes.
	TotalStdBytes uint64
	// TotalDataBytes is the size in bytes of the op_return / data outputs.
	TotalDataBytes uint64
}

TxSize contains the size breakdown of a transaction including the breakdown of data bytes vs standard bytes. This information can be used when calculating fees.

type Txs

type Txs []*Tx

Txs a collection of *bt.Tx.

func (*Txs) NodeJSON

func (tt *Txs) NodeJSON() interface{}

NodeJSON returns a wrapped bt.Txs for marshalling/unmarshalling into a node tx format.

Marshalling usage example:

bb, err := json.Marshal(txs.NodeJSON())

Unmarshalling usage example:

var txs bt.Txs
if err := json.Unmarshal(bb, txs.NodeJSON()); err != nil {}

func (*Txs) ReadFrom

func (tt *Txs) ReadFrom(r io.Reader) (int64, error)

ReadFrom txs from a block in a `bt.Txs`. This assumes a preceding varint detailing the total number of txs that the reader will provide.

type UTXO

type UTXO struct {
	TxID           []byte          `json:"txid"`
	Vout           uint32          `json:"vout"`
	LockingScript  *bscript.Script `json:"locking_script"`
	Satoshis       uint64          `json:"satoshis"`
	SequenceNumber uint32          `json:"sequence_number"`
	Unlocker       *Unlocker       `json:"-"`
}

UTXO an unspent transaction output, used for creating inputs

func (*UTXO) LockingScriptHexString

func (u *UTXO) LockingScriptHexString() string

LockingScriptHexString retur nthe locking script in hex format.

func (*UTXO) MarshalJSON

func (u *UTXO) MarshalJSON() ([]byte, error)

MarshalJSON will serialise a utxo to json.

func (*UTXO) NodeJSON

func (u *UTXO) NodeJSON() interface{}

NodeJSON returns a wrapped *bt.UTXO for marshalling/unmarshalling into a node utxo format.

Marshalling usage example:

bb, err := json.Marshal(utxo.NodeJSON())

Unmarshalling usage example:

utxo := &bt.UTXO{}
if err := json.Unmarshal(bb, utxo.NodeJSON()); err != nil {}

func (*UTXO) TxIDStr

func (u *UTXO) TxIDStr() string

TxIDStr return the tx id as a string.

func (*UTXO) UnmarshalJSON

func (u *UTXO) UnmarshalJSON(body []byte) error

UnmarshalJSON will convert a json serialised utxo to a bt.UTXO.

type UTXOGetterFunc

type UTXOGetterFunc func(ctx context.Context, deficit uint64) ([]*UTXO, error)

UTXOGetterFunc is used for tx.Fund(...). It provides the amount of satoshis required for funding as `deficit`, and expects []*bt.UTXO to be returned containing utxos of which *bt.Input's can be built. If the returned []*bt.UTXO does not cover the deficit after fee recalculation, then this UTXOGetterFunc is called again, with the newly calculated deficit passed in.

It is expected that bt.ErrNoUTXO will be returned once the utxo source is depleted.

type UTXOs

type UTXOs []*UTXO

UTXOs a collection of *bt.UTXO.

func (*UTXOs) NodeJSON

func (u *UTXOs) NodeJSON() interface{}

NodeJSON returns a wrapped bt.UTXOs for marshalling/unmarshalling into a node utxo format.

Marshalling usage example:

bb, err := json.Marshal(utxos.NodeJSON())

Unmarshalling usage example:

var txs bt.UTXOs
if err := json.Unmarshal(bb, utxos.NodeJSON()); err != nil {}

type Unlocker

type Unlocker interface {
	UnlockingScript(ctx context.Context, tx *Tx, up UnlockerParams) (uscript *bscript.Script, err error)
}

Unlocker interface to allow custom implementations of different unlocking mechanisms. Implement the Unlocker function as shown in LocalUnlocker, for example.

type UnlockerGetter

type UnlockerGetter interface {
	Unlocker(ctx context.Context, lockingScript *bscript.Script) (Unlocker, error)
}

UnlockerGetter interfaces getting an unlocker for a given output/locking script.

type UnlockerParams

type UnlockerParams struct {
	// InputIdx the input to be unlocked. [DEFAULT 0]
	InputIdx uint32
	// SigHashFlags the be applied [DEFAULT ALL|FORKID]
	SigHashFlags sighash.Flag
}

UnlockerParams params used for unlocking an input with a `bt.Unlocker`.

type VarInt

type VarInt uint64

VarInt (variable integer) is a field used in transaction data to indicate the number of upcoming fields, or the length of an upcoming field. See http://learnmeabitcoin.com/glossary/varint

func NewVarIntFromBytes

func NewVarIntFromBytes(bb []byte) (VarInt, int)

NewVarIntFromBytes takes a byte array in VarInt format and returns the decoded unsigned integer value of the length, and it's size in bytes. See http://learnmeabitcoin.com/glossary/varint

func (VarInt) Bytes

func (v VarInt) Bytes() []byte

Bytes takes the underlying unsigned integer and returns a byte array in VarInt format. See http://learnmeabitcoin.com/glossary/varint

func (VarInt) Length

func (v VarInt) Length() int

Length return the length of the underlying byte representation of the `bt.VarInt`.

func (*VarInt) ReadFrom

func (v *VarInt) ReadFrom(r io.Reader) (int64, error)

ReadFrom reads the next varint from the io.Reader and assigned it to itself.

func (VarInt) UpperLimitInc

func (v VarInt) UpperLimitInc() int

UpperLimitInc returns true if a number is at the upper limit of a VarInt and will result in a VarInt length change if incremented. The value returned will indicate how many bytes will be increase if the length in incremented. -1 will be returned when the upper limit of VarInt is reached.

Directories

Path Synopsis
Package bscript comment
Package bscript comment
interpreter
Package interpreter implements the bitcoin transaction script language.
Package interpreter implements the bitcoin transaction script language.
interpreter/debug
Package debug comment
Package debug comment
interpreter/errs
Package errs comment
Package errs comment
interpreter/scriptflag
Package scriptflag comment
Package scriptflag comment
examples
Package sighash comment
Package sighash comment
testing
data
Package data comment
Package data comment
Package unlocker comment
Package unlocker comment

Jump to

Keyboard shortcuts

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