tappsbt

package
v0.3.0-alpha.rc2 Latest Latest
Warning

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

Go to latest
Published: Oct 14, 2023 License: MIT Imports: 23 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	PsbtKeyTypeGlobalTapIsVirtualTx    = []byte{0x70}
	PsbtKeyTypeGlobalTapChainParamsHRP = []byte{0x71}
	PsbtKeyTypeGlobalTapPsbtVersion    = []byte{0x72}

	PsbtKeyTypeInputTapPrevID                             = []byte{0x70}
	PsbtKeyTypeInputTapAnchorValue                        = []byte{0x71}
	PsbtKeyTypeInputTapAnchorPkScript                     = []byte{0x72}
	PsbtKeyTypeInputTapAnchorSigHashType                  = []byte{0x73}
	PsbtKeyTypeInputTapAnchorInternalKey                  = []byte{0x74}
	PsbtKeyTypeInputTapAnchorMerkleRoot                   = []byte{0x75}
	PsbtKeyTypeInputTapAnchorOutputBip32Derivation        = []byte{0x76}
	PsbtKeyTypeInputTapAnchorOutputTaprootBip32Derivation = []byte{0x77}
	PsbtKeyTypeInputTapAnchorTapscriptSibling             = []byte{0x78}
	PsbtKeyTypeInputTapAsset                              = []byte{0x79}
	PsbtKeyTypeInputTapAssetProof                         = []byte{0x7a}

	PsbtKeyTypeOutputTapType                               = []byte{0x70}
	PsbtKeyTypeOutputTapIsInteractive                      = []byte{0x71}
	PsbtKeyTypeOutputTapAnchorOutputIndex                  = []byte{0x72}
	PsbtKeyTypeOutputTapAnchorOutputInternalKey            = []byte{0x73}
	PsbtKeyTypeOutputTapAnchorOutputBip32Derivation        = []byte{0x74}
	PsbtKeyTypeOutputTapAnchorOutputTaprootBip32Derivation = []byte{0x75}
	PsbtKeyTypeOutputTapAsset                              = []byte{0x76}
	PsbtKeyTypeOutputTapSplitAsset                         = []byte{0x77}
	PsbtKeyTypeOutputTapAnchorTapscriptSibling             = []byte{0x78}
	PsbtKeyTypeOutputAssetVersion                          = []byte{0x79}
)

We define a set of Taproot Asset (TAP) specific global, input and output PSBT key types here that correspond to the custom types defined in the VPacket below. We start at 0x70 because that is sufficiently high to not conflict with any of the keys specified in BIP-0174. Also, 7 is leet speak for "t" as in Taproot Assets. It would perhaps make sense to wrap these values in the BIP-0174 defined proprietary types to make 100% sure that no parser removes them. But the BIP also mentions to not remove unknown keys, so we should be fine like this as well.

View Source
var (
	PsbtKeyTypeInputTapProof = []byte{0x70}

	PsbtKeyTypeOutputTapProof = []byte{0x70}
)

The following keys are used as custom fields on the BTC level anchor transaction PSBTs only. They are defined here for completeness' sake but are not directly used by the tappsbt package.

View Source
var (
	// VOutIsSplitRoot is a predicate that returns true if the virtual
	// output is a split root output.
	VOutIsSplitRoot = func(o *VOutput) bool {
		return o.Type.IsSplitRoot()
	}

	// VOutCanCarryPassive is a predicate that returns true if the virtual
	// output can carry passive assets.
	VOutCanCarryPassive = func(o *VOutput) bool {
		return o.Type.CanCarryPassive()
	}

	// VOutIsNotSplitRoot is a predicate that returns true if the virtual
	// output is NOT a split root output.
	VOutIsNotSplitRoot = func(o *VOutput) bool {
		return !o.Type.IsSplitRoot()
	}

	// VOutIsInteractive is a predicate that returns true if the virtual
	// transaction is interactive.
	VOutIsInteractive = func(o *VOutput) bool {
		return o.Interactive
	}
)
View Source
var (
	// ErrKeyNotFound is returned when a key is not found among the unknown
	// fields of a packet.
	ErrKeyNotFound = errors.New("tappsbt: key not found")
)

Functions

func AddBip32Derivation

func AddBip32Derivation(derivations []*psbt.Bip32Derivation,
	target *psbt.Bip32Derivation) []*psbt.Bip32Derivation

AddBip32Derivation adds the given target BIP-0032 derivation to the list of derivations if it is not already present.

func AddOutput

func AddOutput(pkt *VPacket, amount uint64, scriptAddr asset.ScriptKey,
	outputIndex uint32, anchorInternalKey keychain.KeyDescriptor,
	assetVersion asset.Version)

AddOutput adds an interactive output to the given packet.

func AddTaprootBip32Derivation

func AddTaprootBip32Derivation(derivations []*psbt.TaprootBip32Derivation,
	target *psbt.TaprootBip32Derivation) []*psbt.TaprootBip32Derivation

AddTaprootBip32Derivation adds the given target Taproot BIP-0032 derivation to the list of derivations if it is not already present.

func Bip32DerivationFromKeyDesc

func Bip32DerivationFromKeyDesc(keyDesc keychain.KeyDescriptor,
	coinType uint32) (*psbt.Bip32Derivation, *psbt.TaprootBip32Derivation)

Bip32DerivationFromKeyDesc returns the default and Taproot BIP-0032 key derivation information from the given key descriptor information.

func FromAddresses

func FromAddresses(receiverAddrs []*address.Tap,
	firstOutputIndex uint32) (*VPacket, OutputIdxToAddr, error)

FromAddresses creates an empty virtual transaction packet from the given addresses. Because sending to an address is always non-interactive, a change output is also added to the packet.

func KeyDescFromBip32Derivation

func KeyDescFromBip32Derivation(
	bip32Derivation *psbt.Bip32Derivation) (keychain.KeyDescriptor, error)

KeyDescFromBip32Derivation attempts to extract the key descriptor from the given public key and BIP-0032 derivation information.

Types

type Anchor

type Anchor struct {
	// Value is output value of the anchor output.
	Value btcutil.Amount

	// PkScript is the output script of the anchor output.
	PkScript []byte

	// SigHashType is the signature hash type that should be used to sign
	// the anchor output spend.
	SigHashType txscript.SigHashType

	// InternalKey is the internal key of the anchor output that the input
	// is spending the asset from.
	InternalKey *btcec.PublicKey

	// MerkleRoot is the root of the tap script merkle tree that also
	// contains the Taproot Asset commitment of the anchor output.
	MerkleRoot []byte

	// TapscriptSibling is the tapscript sibling of the Taproot Asset
	// commitment.
	TapscriptSibling []byte

	// Bip32Derivation is the BIP-0032 derivation of the anchor output's
	// internal key.
	Bip32Derivation []*psbt.Bip32Derivation

	// TrBip32Derivation is the Taproot BIP-0032 derivation of the anchor
	// output's internal key.
	TrBip32Derivation []*psbt.TaprootBip32Derivation
}

Anchor is a struct that contains all the information about an anchor output.

type ErrorTestCase added in v0.3.0

type ErrorTestCase struct {
	Packet  *TestVPacket `json:"packet"`
	Error   string       `json:"error"`
	Comment string       `json:"comment"`
}

type InputCommitments

type InputCommitments = map[int]*commitment.TapCommitment

InputCommitments is a map from virtual package input index to its associated Taproot Asset commitment.

type OutputIdxToAddr added in v0.3.0

type OutputIdxToAddr map[int]address.Tap

OutputIdxToAddr is a map from a VPacket's VOutput index to its associated Tap address.

type TestAnchor added in v0.3.0

type TestAnchor struct {
	Value             int64                    `json:"value"`
	PkScript          string                   `json:"pk_script"`
	SigHashType       uint32                   `json:"sig_hash_type"`
	InternalKey       string                   `json:"internal_key"`
	MerkleRoot        string                   `json:"merkle_root"`
	TapscriptSibling  string                   `json:"tapscript_sibling"`
	Bip32Derivation   []*TestBip32Derivation   `json:"bip32_derivation"`
	TrBip32Derivation []*TestTrBip32Derivation `json:"tr_bip32_derivation"`
}

func NewTestFromAnchor added in v0.3.0

func NewTestFromAnchor(a *Anchor) *TestAnchor

func (*TestAnchor) ToAnchor added in v0.3.0

func (ta *TestAnchor) ToAnchor(t testing.TB) *Anchor

type TestBip32Derivation added in v0.3.0

type TestBip32Derivation struct {
	PubKey      string   `json:"pub_key"`
	Fingerprint uint32   `json:"fingerprint"`
	Bip32Path   []uint32 `json:"bip32_path"`
}

func NewTestFromBip32Derivation added in v0.3.0

func NewTestFromBip32Derivation(b *psbt.Bip32Derivation) *TestBip32Derivation

func (*TestBip32Derivation) ToBip32Derivation added in v0.3.0

func (td *TestBip32Derivation) ToBip32Derivation(
	t testing.TB) *psbt.Bip32Derivation

type TestTrBip32Derivation added in v0.3.0

type TestTrBip32Derivation struct {
	XOnlyPubKey string   `json:"pub_key"`
	LeafHashes  []string `json:"leaf_hashes"`
	Fingerprint uint32   `json:"fingerprint"`
	Bip32Path   []uint32 `json:"bip32_path"`
}

func NewTestFromTrBip32Derivation added in v0.3.0

func NewTestFromTrBip32Derivation(
	b *psbt.TaprootBip32Derivation) *TestTrBip32Derivation

func (*TestTrBip32Derivation) ToTrBip32Derivation added in v0.3.0

func (td *TestTrBip32Derivation) ToTrBip32Derivation(
	t testing.TB) *psbt.TaprootBip32Derivation

type TestVInput added in v0.3.0

type TestVInput struct {
	Bip32Derivation   []*TestBip32Derivation   `json:"bip32_derivation"`
	TrBip32Derivation []*TestTrBip32Derivation `json:"tr_bip32_derivation"`
	TrInternalKey     string                   `json:"tr_internal_key"`
	TrMerkleRoot      string                   `json:"tr_merkle_root"`
	PrevID            *asset.TestPrevID        `json:"prev_id"`
	Anchor            *TestAnchor              `json:"anchor"`
	Asset             *asset.TestAsset         `json:"asset"`
	Proof             string                   `json:"proof"`
}

func NewTestFromVInput added in v0.3.0

func NewTestFromVInput(t testing.TB, i *VInput) *TestVInput

func (*TestVInput) ToVInput added in v0.3.0

func (ti *TestVInput) ToVInput(t testing.TB) *VInput

type TestVOutput added in v0.3.0

type TestVOutput struct {
	Amount                        uint64                   `json:"amount"`
	Type                          uint8                    `json:"type"`
	AssetVersion                  uint32                   `json:"asset_version"`
	Interactive                   bool                     `json:"interactive"`
	AnchorOutputIndex             uint32                   `json:"anchor_output_index"`
	AnchorOutputInternalKey       string                   `json:"anchor_output_internal_key"`
	AnchorOutputBip32Derivation   []*TestBip32Derivation   `json:"anchor_output_bip32_derivation"`
	AnchorOutputTrBip32Derivation []*TestTrBip32Derivation `json:"anchor_output_tr_bip32_derivation"`
	AnchorOutputTapscriptSibling  string                   `json:"anchor_output_tapscript_sibling"`
	Asset                         *asset.TestAsset         `json:"asset"`
	SplitAsset                    *asset.TestAsset         `json:"split_asset"`
	PkScript                      string                   `json:"pk_script"`
	Bip32Derivation               []*TestBip32Derivation   `json:"bip32_derivation"`
	TrBip32Derivation             []*TestTrBip32Derivation `json:"tr_bip32_derivation"`
	TrInternalKey                 string                   `json:"tr_internal_key"`
	TrMerkleRoot                  string                   `json:"tr_merkle_root"`
}

func NewTestFromVOutput added in v0.3.0

func NewTestFromVOutput(t testing.TB, v *VOutput,
	coinType uint32) *TestVOutput

func (*TestVOutput) ToVOutput added in v0.3.0

func (to *TestVOutput) ToVOutput(t testing.TB) *VOutput

type TestVPacket added in v0.3.0

type TestVPacket struct {
	Inputs         []*TestVInput  `json:"inputs"`
	Outputs        []*TestVOutput `json:"outputs"`
	Version        uint8          `json:"version"`
	ChainParamsHRP string         `json:"chain_params_hrp"`
}

func NewTestFromVPacket added in v0.3.0

func NewTestFromVPacket(t testing.TB, p *VPacket) *TestVPacket

func (*TestVPacket) ToVPacket added in v0.3.0

func (tp *TestVPacket) ToVPacket(t testing.TB) *VPacket

type TestVectors added in v0.3.0

type TestVectors struct {
	ValidTestCases []*ValidTestCase `json:"valid_test_cases"`
	ErrorTestCases []*ErrorTestCase `json:"error_test_cases"`
}

type VInput

type VInput struct {
	// PInput is the embedded default PSBT input struct that is used for
	// asset related input data.
	psbt.PInput

	// PrevID is the asset previous ID of the asset being spent.
	PrevID asset.PrevID

	// Anchor contains the information about the BTC level anchor
	// transaction that committed to the asset being spent.
	Anchor Anchor
	// contains filtered or unexported fields
}

VInput represents an input to a virtual asset state transition transaction.

func (*VInput) Asset

func (i *VInput) Asset() *asset.Asset

Asset returns the input's asset that's being spent.

func (*VInput) Proof

func (i *VInput) Proof() []byte

Proof returns the proof blob that the asset being spent was committed to in the anchor transaction.

type VOutPredicate

type VOutPredicate func(*VOutput) bool

VOutPredicate is a function that can be used to filter virtual outputs.

type VOutput

type VOutput struct {
	// Amount is the amount of units of the asset that this output is
	// creating. This can be zero in case of an asset tombstone in a
	// non-interactive full value send scenario. When serialized, this will
	// be stored as the value of the wire.TxOut of the PSBT's unsigned TX.
	Amount uint64

	// AssetVersion is the version of the asset that this output should
	// create.
	AssetVersion asset.Version

	// Type indicates what type of output this is, which has an influence on
	// whether the asset is set or what witness type is expected to be
	// generated for the asset.
	Type VOutputType

	// Interactive, when set to true, indicates that the receiver of the
	// output is aware of the asset transfer and can therefore receive a
	// full value send directly and without a tombstone in the change
	// output.
	Interactive bool

	// AnchorOutputIndex indicates in which output index of the BTC
	// transaction this asset output should be committed to. Multiple asset
	// outputs can be committed to within the same BTC transaction output.
	AnchorOutputIndex uint32

	// AnchorOutputInternalKey is the internal key of the anchor output that
	// will be used to create the anchor Taproot output key to which this
	// asset output will be committed to.
	AnchorOutputInternalKey *btcec.PublicKey

	// AnchorOutputBip32Derivation is the BIP-0032 derivation of the anchor
	// output's internal key.
	AnchorOutputBip32Derivation []*psbt.Bip32Derivation

	// AnchorOutputTaprootBip32Derivation is the Taproot BIP-0032 derivation
	// of the anchor output's internal key.
	AnchorOutputTaprootBip32Derivation []*psbt.TaprootBip32Derivation

	// AnchorOutputTapscriptSibling is the preimage of the tapscript sibling
	// of the Taproot Asset commitment.
	AnchorOutputTapscriptSibling *commitment.TapscriptPreimage

	// Asset is the actual asset (including witness or split commitment
	// data) that this output will commit to on chain. This asset will be
	// included in the proof sent to the recipient of this output.
	Asset *asset.Asset

	// SplitAsset is the original split asset that was created when creating
	// the split commitment.
	//
	// NOTE: This is only set if the above Asset is the root asset of a
	// split. Compared to the root asset, this does not have a split
	// commitment root and no TX witness, but instead has the split
	// commitment set.
	SplitAsset *asset.Asset

	// ScriptKey is the new script key of the recipient of the asset. When
	// serialized, this will be stored in the TaprootInternalKey and
	// TaprootDerivationPath fields of the PSBT output.
	ScriptKey asset.ScriptKey
}

VOutput represents an output of a virtual asset state transition.

func (*VOutput) AnchorKeyToDesc

func (o *VOutput) AnchorKeyToDesc() (keychain.KeyDescriptor, error)

AnchorKeyToDesc attempts to extract the key descriptor of the anchor output from the anchor output BIP-0032 derivation information.

func (*VOutput) SetAnchorInternalKey

func (o *VOutput) SetAnchorInternalKey(keyDesc keychain.KeyDescriptor,
	coinType uint32)

SetAnchorInternalKey sets the internal key and derivation path of the anchor output based on the given key descriptor and coin type.

func (*VOutput) SplitLocator

func (o *VOutput) SplitLocator(assetID asset.ID) commitment.SplitLocator

SplitLocator creates a split locator from the output. The asset ID is passed in for cases in which the asset is not yet set on the output.

type VOutputType

type VOutputType uint8

VOutputType represents the type of virtual output.

const (
	// TypeSimple is a plain full-value or split output that is not a split
	// root and does not carry passive assets. In case of a split, the asset
	// of this output has a split commitment.
	TypeSimple VOutputType = 0

	// TypeSplitRoot is a split root output that carries the change from a
	// split or a tombstone from a non-interactive full value send output.
	// In either case, the asset of this output has a tx witness.
	TypeSplitRoot VOutputType = 1

	// TypePassiveAssetsOnly indicates that this output only carries passive
	// assets and therefore the asset in this output is nil. The passive
	// assets themselves are signed in their own virtual transactions and
	// are not present in this packet.
	TypePassiveAssetsOnly VOutputType = 2

	// TypePassiveSplitRoot is a split root output that carries the change
	// from a split or a tombstone from a non-interactive full value send
	// output, as well as passive assets.
	TypePassiveSplitRoot VOutputType = 3

	// TypeSimplePassiveAssets is a plain full-value interactive send output
	// that also carries passive assets. This is a special case where we
	// send the full value of a single asset in a commitment to a new script
	// key, but also carry passive assets in the same output. This is useful
	// for key rotation (send-to-self) scenarios or asset burns where we
	// burn the full supply of a single asset within a commitment.
	TypeSimplePassiveAssets VOutputType = 4
)

func (VOutputType) CanBeInteractive

func (t VOutputType) CanBeInteractive() bool

CanBeInteractive returns true if the output type is compatible with being an interactive send.

func (VOutputType) CanCarryPassive

func (t VOutputType) CanCarryPassive() bool

CanCarryPassive returns true if the output type is compatible with carrying passive assets.

func (VOutputType) IsSplitRoot

func (t VOutputType) IsSplitRoot() bool

IsSplitRoot returns true if the output type is a split root, indicating that the asset has a tx witness instead of a split witness.

func (VOutputType) String

func (t VOutputType) String() string

String returns a human-readable string representation of the output type.

type VPacket

type VPacket struct {
	// Inputs is the list of asset inputs that are being spent.
	Inputs []*VInput

	// Outputs is the list of new asset outputs that are created by the
	// virtual transaction.
	Outputs []*VOutput

	// ChainParams are the Taproot Asset chain parameters that are used to
	// encode and decode certain contents of the virtual packet.
	ChainParams *address.ChainParams

	// Version is the version of the virtual transaction. This is currently
	// unused but can be used to signal a new version of the virtual PSBT
	// format in the future.
	Version uint8
}

VPacket is a PSBT extension packet for a virtual transaction. It represents the virtual asset state transition as it will be validated by the Taproot Asset VM. Some elements within the virtual packet may refer to on-chain elements (such as the anchor BTC transaction that was used to anchor the input that is spent). But in general a virtual transaction does NOT directly map onto a BTC transaction. It is entirely possible that multiple virtual transactions will be merged into a single BTC transaction. Thus, each asset state transfer is represented in a virtual TX and multiple asset state transfers can be anchored within a single BTC transaction.

NOTE: A virtual transaction only carries the asset state transition for a single asset ID. If multiple inputs are given, they must all belong to the same asset ID (which means those asset UTXOs are being merged and possibly split again in this virtual transaction). Therefore, if an anchor output carries commitments for multiple assets, a virtual transaction needs to be created, signed and then anchored for each asset ID separately.

TODO(guggero): Actually support merging multiple virtual transactions into a single BTC transaction.

func ForInteractiveSend

func ForInteractiveSend(id asset.ID, amount uint64, scriptAddr asset.ScriptKey,
	outputIndex uint32, anchorInternalKey keychain.KeyDescriptor,
	assetVersion asset.Version,
	chainParams *address.ChainParams) *VPacket

ForInteractiveSend creates a virtual transaction packet for sending an output to a receiver in an interactive manner. Only one, interactive output is created. If the amount is not the full input amount, a change output will be added by the funding API.

func NewFromPsbt

func NewFromPsbt(packet *psbt.Packet) (*VPacket, error)

NewFromPsbt returns a new instance of a VPacket struct created by reading the custom fields on the given PSBT packet.

func NewFromRawBytes

func NewFromRawBytes(r io.Reader, b64 bool) (*VPacket, error)

NewFromRawBytes returns a new instance of a VPacket struct created by reading from a byte slice. If the format is invalid, an error is returned. If the argument b64 is true, the passed byte slice is decoded from base64 encoding before processing.

func OwnershipProofPacket

func OwnershipProofPacket(ownedAsset *asset.Asset,
	chainParams *address.ChainParams) *VPacket

OwnershipProofPacket creates a virtual transaction packet that is used to prove ownership of an asset. It creates a 1-in-1-out transaction that spends the owned asset to the NUMS key. The witness is created over an empty previous outpoint, so it can never be used in an actual state transition.

func RandPacket

func RandPacket(t testing.TB) *VPacket

RandPacket generates a random virtual packet for testing purposes.

func (*VPacket) B64Encode

func (p *VPacket) B64Encode() (string, error)

B64Encode returns the base64 encoding of the serialization of the current virtual packet, or an error if the encoding fails.

func (*VPacket) EncodeAsPsbt

func (p *VPacket) EncodeAsPsbt() (*psbt.Packet, error)

EncodeAsPsbt returns the PSBT encoding of the current virtual packet, or an error if the encoding fails.

func (*VPacket) FirstInteractiveOutput

func (p *VPacket) FirstInteractiveOutput() (*VOutput, error)

FirstInteractiveOutput returns the first interactive output in the virtual transaction.

func (*VPacket) FirstNonSplitRootOutput

func (p *VPacket) FirstNonSplitRootOutput() (*VOutput, error)

FirstNonSplitRootOutput returns the first non-change output in the virtual transaction.

func (*VPacket) HasInteractiveOutput

func (p *VPacket) HasInteractiveOutput() bool

HasInteractiveOutput determines if this virtual transaction has an interactive output.

func (*VPacket) HasSplitCommitment

func (p *VPacket) HasSplitCommitment() (bool, error)

HasSplitCommitment determines if this transaction results in an asset split. This is either the case if the value of the input asset is split or if one of the outputs is non-interactive (in which case we need to have a zero value tombstone asset in the change output).

func (*VPacket) HasSplitRootOutput

func (p *VPacket) HasSplitRootOutput() bool

HasSplitRootOutput determines if this virtual transaction has a split root output.

func (*VPacket) PassiveAssetsOutput added in v0.3.0

func (p *VPacket) PassiveAssetsOutput() (*VOutput, error)

PassiveAssetsOutput returns the output in the virtual transaction that can carry passive assets, or an error if there is none or more than one.

func (*VPacket) Serialize

func (p *VPacket) Serialize(w io.Writer) error

Serialize creates a binary serialization of the referenced VPacket struct with lexicographical ordering (by key) of the subsections.

func (*VPacket) SetInputAsset

func (p *VPacket) SetInputAsset(index int, a *asset.Asset, proof []byte)

SetInputAsset sets the input asset that is being spent.

func (*VPacket) SplitRootOutput

func (p *VPacket) SplitRootOutput() (*VOutput, error)

SplitRootOutput returns the split root output in the virtual transaction, or an error if there is none or more than one.

type ValidTestCase added in v0.3.0

type ValidTestCase struct {
	Packet   *TestVPacket `json:"packet"`
	Expected string       `json:"expected"`
	Comment  string       `json:"comment"`
}

Jump to

Keyboard shortcuts

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