tapsend

package
v0.4.1 Latest Latest
Warning

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

Go to latest
Published: Jul 25, 2024 License: MIT Imports: 29 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// DummyAmtSats is the default amount of sats we'll use in Bitcoin
	// outputs embedding Taproot Asset commitments. This value just needs to
	// be greater than dust, and we assume that this value is updated to
	// match the input asset bearing UTXOs before finalizing the transfer
	// TX.
	DummyAmtSats = btcutil.Amount(1_000)

	// SendConfTarget is the confirmation target we'll use to query for
	// a fee estimate.
	SendConfTarget = 6
)
View Source
const Subsystem = "SEND"

Subsystem defines the logging code for this subsystem.

Variables

View Source
var (
	// ErrInvalidCollectibleSplit is returned when a collectible is split
	// into more than two outputs.
	ErrInvalidCollectibleSplit = errors.New(
		"fund: invalid collectible split",
	)

	// ErrInvalidChangeOutputLocation is returned when the change output is
	// not at the expected location (index 0).
	ErrInvalidChangeOutputLocation = errors.New(
		"fund: invalid change output location, should be index 0",
	)

	// ErrInvalidSplitAmounts is returned when the split amounts don't add
	// up to the amount of the asset being spent.
	ErrInvalidSplitAmounts = errors.New(
		"fund: invalid split amounts, sum doesn't match input",
	)

	// ErrMissingInputAsset is an error returned when we attempt to spend
	// to a Taproot Asset address from an input that does not contain
	// the matching asset.
	ErrMissingInputAsset = errors.New(
		"send: Input does not contain requested asset",
	)

	// ErrInsufficientInputAssets is an error returned when we attempt
	// to spend to a Taproot Asset address from a set of inputs which
	// contain an insufficient amount of total funds.
	ErrInsufficientInputAssets = errors.New(
		"send: Input assets total funds is insufficient",
	)

	// ErrInvalidOutputIndexes is an error returned when we attempt to spend
	// to Bitcoin output indexes that do not start at 0 or
	// are not continuous.
	ErrInvalidOutputIndexes = errors.New(
		"send: Output indexes not starting at 0 and continuous",
	)

	// ErrMissingSplitAsset is an error returned when we attempt to look up
	// a split asset in a map and the specified asset is not found.
	ErrMissingSplitAsset = errors.New(
		"send: split asset not found",
	)

	// ErrMissingAssetCommitment is an error returned when we attempt to
	// look up an Asset commitment in a map and the specified commitment
	// is not found.
	ErrMissingAssetCommitment = errors.New(
		"send: Asset commitment not found",
	)

	// ErrMissingTapCommitment is an error returned when we attempt to look
	// up a Taproot Asset commitment in a map and the specified commitment
	// is not found.
	ErrMissingTapCommitment = errors.New(
		"send: Taproot Asset commitment not found",
	)

	// ErrInvalidAnchorOutputInfo is an error returned when the anchor output
	// information on a virtual transaction output is invalid.
	ErrInvalidAnchorOutputInfo = errors.New(
		"send: invalid anchor output info",
	)

	// ErrInvalidAnchorInputInfo is an error returned when the anchor input
	// information on a virtual transaction input is invalid.
	ErrInvalidAnchorInputInfo = errors.New(
		"send: invalid anchor input info",
	)

	// ErrAssetMissing is an error returned when an asset is missing from a
	// virtual transaction.
	ErrAssetMissing = errors.New("asset missing")

	// ErrAssetNotSigned is an error returned when an asset is not signed
	// in a virtual transaction that was already committed to an anchor
	// output.
	ErrAssetNotSigned = errors.New("asset not signed")

	// ErrNoRootLocator is an error that is returned when a split commitment
	// is created without a split root output.
	ErrNoRootLocator = errors.New(
		"cannot create split commitment without split root output",
	)
)
View Source
var (
	// GenesisDummyScript is a dummy script that we'll use to fund the
	// initial PSBT packet that'll create initial set of assets. It's the
	// same size as an encoded P2TR output and has a valid P2TR prefix.
	GenesisDummyScript = append(
		[]byte{txscript.OP_1, txscript.OP_DATA_32},
		bytes.Repeat([]byte{0x00}, 32)...,
	)
)

Functions

func AnchorOutputScript

func AnchorOutputScript(internalKey *btcec.PublicKey,
	siblingPreimage *commitment.TapscriptPreimage,
	anchorCommitment *commitment.TapCommitment) ([]byte, chainhash.Hash,
	chainhash.Hash, error)

AnchorOutputScript creates the anchor output script given an internal key, tapscript sibling and the TapCommitment. It also returns the merkle root and taproot asset root for the commitment.

func AssertAnchorTimeLocks

func AssertAnchorTimeLocks(btcPkt *psbt.Packet, vPkt *tappsbt.VPacket)

AssertAnchorTimeLocks makes sure the anchor transaction and its inputs have the correct lock time and sequence set, according to the assets being spent.

func AssertInputAnchorsEqual

func AssertInputAnchorsEqual(packets []*tappsbt.VPacket) error

AssertInputAnchorsEqual makes sure that the anchor input information for each input of the virtual packets that anchors to the same BTC level input is identical.

func AssertOutputAnchorsEqual

func AssertOutputAnchorsEqual(packets []*tappsbt.VPacket) error

AssertOutputAnchorsEqual makes sure that the anchor output information for each output of the virtual packets that anchors to the same BTC level output is identical.

func AssetFromTapCommitment

func AssetFromTapCommitment(tapCommitment *commitment.TapCommitment,
	desc *FundingDescriptor, inputScriptKey btcec.PublicKey) (*asset.Asset,
	error)

AssetFromTapCommitment uses a script key to extract an asset from a given Taproot Asset commitment.

func CreateAnchorTx

func CreateAnchorTx(vPackets []*tappsbt.VPacket) (*psbt.Packet, error)

CreateAnchorTx creates a template BTC anchor TX with dummy outputs.

func CreateDummyOutput

func CreateDummyOutput() *wire.TxOut

CreateDummyOutput creates a new Bitcoin transaction output that is later used to embed a Taproot Asset commitment.

func CreateOutputCommitments

func CreateOutputCommitments(
	packets []*tappsbt.VPacket) (tappsbt.OutputCommitments, error)

CreateOutputCommitments creates the final set of Taproot asset commitments representing the asset sends of the given packets of active and passive assets.

func CreateProofSuffix

func CreateProofSuffix(chainTx *wire.MsgTx, finalTxPacketOutputs []psbt.POutput,
	vPacket *tappsbt.VPacket, outputCommitments tappsbt.OutputCommitments,
	outIndex int, allAnchoredVPackets []*tappsbt.VPacket) (*proof.Proof,
	error)

CreateProofSuffix creates a new proof for the given virtual transaction output indicated with outIndex within vPacket. This is the final state transition that will be added to the proofs of the receiver. The proof returned will have all the Taproot Asset level proof information, but contains dummy data for the on-chain part and potentially the anchor transaction itself, if chainTx is not yet fully final. Only the outputs of chainTx need to be final and correspond to the PSBT outputs given as finalTxPacketOutputs.

func CreateProofSuffixCustom

func CreateProofSuffixCustom(finalTx *wire.MsgTx, vPacket *tappsbt.VPacket,
	outputCommitments tappsbt.OutputCommitments, outIndex int,
	allAnchoredVPackets []*tappsbt.VPacket,
	genExclusionProofs ExclusionProofGenerator) (*proof.Proof, error)

CreateProofSuffixCustom creates the new proof for the given virtual transaction output indicated with outIndex within vPacket. This is the final state transition that will be added to the proofs of the receiver. The proof returned will have all the Taproot Asset level proof information, but contains dummy data for the on-chain part and potentially the anchor transaction itself, if chainTx is not yet fully final or even nil. If chainTx is nil, it must be set on the proof later manually to make the proof valid. The exclusion proof generator function must add an exclusion proof for each P2TR on-chain output that is NOT an asset commitment (e.g. P2TR change outputs or other pure BTC P2TR outputs).

func CreateTaprootSignature

func CreateTaprootSignature(vIn *tappsbt.VInput, virtualTx *wire.MsgTx,
	idx int, txSigner tapscript.Signer) (wire.TxWitness, error)

CreateTaprootSignature creates a Taproot signature for the given asset input. Depending on the fields set in the input, this will either create a key path spend or a script path spend.

func DisableLog

func DisableLog()

DisableLog disables all library log output. Logging output is disabled by default until UseLogger is called.

func ExtractUnSpendable

func ExtractUnSpendable(c *commitment.TapCommitment) []*asset.Asset

ExtractUnSpendable extracts all tombstones and burns from the active input commitment.

func HasInput

func HasInput(tx *wire.MsgTx, outpoint wire.OutPoint) bool

HasInput returns true if the given transaction has an input that spends the given outpoint.

func LogCommitment

func LogCommitment(prefix string, idx int,
	tapCommitment *commitment.TapCommitment, internalKey *btcec.PublicKey,
	pkScript, trimmedMerkleRoot []byte)

LogCommitment logs the given Taproot Asset commitment to the log as a trace message. This is a no-op if the log level is not set to trace.

func PrepareAnchoringTemplate

func PrepareAnchoringTemplate(
	vPackets []*tappsbt.VPacket) (*psbt.Packet, error)

PrepareAnchoringTemplate creates a BTC level PSBT packet that can be used to anchor the given virtual packets. The PSBT packet is created with the necessary inputs and outputs to anchor the virtual packets, but without any signatures. The main difference to CreateAnchorTx is that this function populates the inputs with the witness UTXO and derivation path information.

func PrepareOutputAssets

func PrepareOutputAssets(ctx context.Context, vPkt *tappsbt.VPacket) error

PrepareOutputAssets prepares the assets of the given outputs depending on the amounts set on the transaction. If a split is necessary (non-interactive or partial amount send) it computes a split commitment with the given inputs and spend information. The inputs MUST be checked as valid beforehand and the change output is expected to be declared as such (and be at index 0).

func RemoveAssetsFromCommitment

func RemoveAssetsFromCommitment(c *commitment.TapCommitment,
	assets []*asset.Asset) (*commitment.TapCommitment, error)

RemoveAssetsFromCommitment removes all assets from the given commitment and only returns a tree of the remaining commitments.

func RemovePacketsFromCommitment

func RemovePacketsFromCommitment(c *commitment.TapCommitment,
	packets []*tappsbt.VPacket) (*commitment.TapCommitment, error)

RemovePacketsFromCommitment removes all assets within the virtual transactions from the given commitment.

func SignVirtualTransaction

func SignVirtualTransaction(vPkt *tappsbt.VPacket, signer tapscript.Signer,
	validator tapscript.WitnessValidator) error

SignVirtualTransaction updates the new asset (the root asset located at the change output in case of a non-interactive or partial amount send or the full asset in case of an interactive full amount send) by creating a signature over the asset transfer, verifying the transfer with the Taproot Asset VM, and attaching that signature to the new Asset.

func UpdateTaprootOutputKeys

func UpdateTaprootOutputKeys(btcPacket *psbt.Packet, vPkt *tappsbt.VPacket,
	outputCommitments tappsbt.OutputCommitments) error

UpdateTaprootOutputKeys updates a PSBT with outputs embedding TapCommitments involved in an asset send. The sender must attach the Bitcoin input holding the corresponding Taproot Asset input asset to this PSBT before finalizing the TX. Locators MUST be checked beforehand. Since this is called when the anchor transaction and all assets are final, we also make sure any time locks from the assets are properly bubbled up to the BTC level.

func UseLogger

func UseLogger(logger btclog.Logger)

UseLogger uses a specified Logger to output package logging info. This should be used in preference to SetLogWriter if the caller is also using btclog.

func ValidateAnchorInputs

func ValidateAnchorInputs(anchorPacket *psbt.Packet, packets []*tappsbt.VPacket,
	prunedAssets map[wire.OutPoint][]*asset.Asset) error

ValidateAnchorInputs checks that the anchor inputs of the virtual packets are valid and consistent with the provided BTC level PSBT packet.

func ValidateAnchorOutputs

func ValidateAnchorOutputs(anchorPacket *psbt.Packet,
	packets []*tappsbt.VPacket, updateDatabaseHints bool) error

ValidateAnchorOutputs checks that the anchor outputs of the virtual packets are valid and consistent with the provided BTC level PSBT packet. When calling this function, everything must be ready to be signed on the BTC level, meaning all asset level information must be final (including the asset signatures for ASSET_VERSION_V0 assets). If the updateDatabaseHints flag is set, the function will also make sure the extra information (merkle root and taproot asset root) is set in the PSBT packet's outputs. That info is required to create the transfer output database entry.

func ValidateInputs

func ValidateInputs(inputCommitments tappsbt.InputCommitments,
	expectedAssetType asset.Type, desc *FundingDescriptor) (bool, error)

ValidateInputs validates a set of inputs against a funding request. It returns true if the inputs would be spent fully, otherwise false.

func ValidateVPacketVersions

func ValidateVPacketVersions(vPackets []*tappsbt.VPacket) error

ValidateVPacketVersions checks that all virtual packets are the same version.

Types

type AnchorTransaction

type AnchorTransaction struct {
	// FundedPsbt is the funded anchor TX at the state before it was signed,
	// with all the UTXO information intact for later exclusion proof
	// creation.
	FundedPsbt *FundedPsbt

	// FinalTx is the fully signed and finalized anchor TX that can be
	// broadcast to the network.
	FinalTx *wire.MsgTx

	// TargetFeeRate is the fee rate that was used to fund the anchor TX.
	TargetFeeRate chainfee.SatPerKWeight

	// ChainFees is the actual, total amount of sats paid in chain fees by
	// the anchor TX.
	ChainFees int64
}

AnchorTransaction is a type that holds all information about a BTC level anchor transaction that anchors multiple virtual asset transfer transactions.

func (*AnchorTransaction) Copy

Copy creates a deep copy of the AnchorTransaction.

type AssetGroupQuerier

type AssetGroupQuerier interface {
	// QueryAssetGroup attempts to locate the asset group information
	// (genesis + group key) associated with a given asset.
	QueryAssetGroup(context.Context, asset.ID) (*asset.AssetGroup, error)
}

AssetGroupQuerier is an interface that allows us to query for asset groups by asset ID.

type ExclusionProofGenerator

type ExclusionProofGenerator func(target *proof.BaseProofParams,
	isAnchor IsAnchor) error

ExclusionProofGenerator is a function type that can be used to generate exclusion proofs for any BTC transaction outputs that don't carry any assets. The function should add the exclusion proofs to the given target proof parameters.

type FundedPsbt

type FundedPsbt struct {
	// Pkt is the PSBT packet itself.
	Pkt *psbt.Packet

	// ChangeOutputIndex denotes which output in the PSBT packet is the
	// change output. We use this to figure out which output will store our
	// Taproot Asset commitment (the non-change output).
	ChangeOutputIndex int32

	// ChainFees is the amount in sats paid in on-chain fees for this
	// transaction.
	ChainFees int64

	// LockedUTXOs is the set of UTXOs that were locked to create the PSBT
	// packet.
	LockedUTXOs []wire.OutPoint
}

FundedPsbt represents a fully funded PSBT transaction.

func (*FundedPsbt) Copy

func (f *FundedPsbt) Copy() *FundedPsbt

Copy creates a deep copy of the FundedPsbt.

type FundingDescriptor

type FundingDescriptor struct {
	// AssetSpecifier is the asset specifier.
	AssetSpecifier asset.Specifier

	// Amount is the amount of the asset to transfer.
	Amount uint64
}

FundingDescriptor describes the information that is needed to select and verify input assets in order to send to a specific recipient. It is a subset of the information contained in a Taproot Asset address.

func DescribeAddrs

func DescribeAddrs(addrs []*address.Tap) (*FundingDescriptor, error)

DescribeAddrs extracts the recipient descriptors from a list of Taproot Asset addresses.

func DescribeRecipients

func DescribeRecipients(ctx context.Context, vPkt *tappsbt.VPacket,
	groupQuerier AssetGroupQuerier) (*FundingDescriptor, error)

DescribeRecipients extracts the recipient descriptors from a Taproot Asset PSBT.

func (*FundingDescriptor) TapCommitmentKey

func (r *FundingDescriptor) TapCommitmentKey() [32]byte

TapCommitmentKey is the key that maps to the root commitment for the asset group specified by a recipient descriptor.

type IsAnchor

type IsAnchor func(anchorOutputIndex uint32) bool

IsAnchor is a function type that can be used to determine if a given BTC transaction output at the given index is an anchor for committing assets.

Jump to

Keyboard shortcuts

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