taroscript

package
v0.1.1-alpha Latest Latest
Warning

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

Go to latest
Published: Nov 9, 2022 License: MIT Imports: 21 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// DummyAmtSats is the default amount of sats we'll use in Bitcoin
	// outputs embedding Taro 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
)

Variables

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

	// ErrInsufficientInputAsset is an error returned when we attempt
	// to spend to a Taro address from an input that contains
	// insufficient asset funds.
	ErrInsufficientInputAsset = errors.New(
		"send: Input asset value 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",
	)

	// ErrMissingTaroCommitment is an error returned when we attempt to
	// look up a Taro commitment in a map and the specified commitment
	// is not found.
	ErrMissingTaroCommitment = errors.New(
		"send: Taro commitment not found",
	)
)
View Source
var (
	// ErrNoInputs represents an error case where an asset undergoing a
	// state transition does not have any or a specific input required.
	ErrNoInputs = errors.New("missing asset input(s)")

	// ErrInputMismatch represents an error case where an asset's set of
	// inputs mismatch the set provided to the virtual machine.
	ErrInputMismatch = errors.New("asset input(s) mismatch")

	// ErrInvalidScriptVersion represents an error case where an asset input
	// commits to an invalid script version.
	ErrInvalidScriptVersion = errors.New("invalid script version")
)

Functions

func AreValidIndexes

func AreValidIndexes(locators SpendLocators) (bool, error)

AreValidIndexes checks a set of split locators to check for the minimum number of locators, and tests if the locators could be used for a Taro-only spend, i.e. a TX that does not need other outputs added to be valid.

func CreateSpendOutputs

func CreateSpendOutputs(addr address.Taro, locators SpendLocators,
	internalKey, scriptKey btcec.PublicKey,
	commitments SpendCommitments, pkt *psbt.Packet) error

CreateSpendOutputs updates a PSBT with outputs embedding TaroCommitments involved in an asset send. The sender must attach the Bitcoin input holding the corresponding Taro input asset to this PSBT before finalizing the TX. Locators MUST be checked beforehand.

func CreateTemplatePsbt

func CreateTemplatePsbt(locators SpendLocators) (*psbt.Packet, error)

Build a template TX with dummy outputs TODO(jhb): godoc

func InputAssetPrevOut

func InputAssetPrevOut(prevAsset asset.Asset) (*wire.TxOut, error)

InputAssetPrevOut returns a TxOut that represents the input asset in a Taro virtual TX.

func InputKeySpendSigHash

func InputKeySpendSigHash(virtualTx *wire.MsgTx, input *asset.Asset,
	idx uint32) ([]byte, error)

InputKeySpendSigHash returns the signature hash of a virtual transaction for a specific Taro input that can be spent through the key path. This is the message over which signatures are generated over.

func InputPrevOutFetcher

func InputPrevOutFetcher(prevAsset asset.Asset) (*txscript.CannedPrevOutputFetcher,
	error)

InputPrevOutFetcher returns a Taro input's `PrevOutFetcher` to be used throughout signing.

func InputScriptSpendSigHash

func InputScriptSpendSigHash(virtualTx *wire.MsgTx, input *asset.Asset,
	idx uint32, tapLeaf *txscript.TapLeaf) ([]byte, error)

InputScriptSpendSigHash returns the signature hash of a virtual transaction for a specific Taro input that can be spent through the script path. This is the message over which signatures are generated over.

func IsValidInput

func IsValidInput(input *commitment.TaroCommitment,
	addr address.Taro, inputScriptKey btcec.PublicKey,
	net address.ChainParams) (*asset.Asset, bool, error)

IsValidInput verifies that the Taro commitment of the input contains an asset that could be spent to the given Taro address.

func PayToAddrScript

func PayToAddrScript(internalKey btcec.PublicKey, sibling *chainhash.Hash,
	commitment commitment.TaroCommitment) ([]byte, error)

PayToAddrScript constructs a P2TR script that embeds a Taro commitment by tweaking the receiver key by a Tapscript tree that contains the Taro commitment root. The Taro commitment must be reconstructed by the receiver, and they also need to Tapscript sibling hash used here if present.

func PayToTaprootScript

func PayToTaprootScript(taprootKey *btcec.PublicKey) ([]byte, error)

PayToTaprootScript creates a pk script for a pay-to-taproot output key.

func SignTaprootKeySpend

func SignTaprootKeySpend(internalKey btcec.PublicKey, virtualTx *wire.MsgTx,
	inputAsset *asset.Asset, idx int,
	txSigner Signer) (*wire.TxWitness, error)

SignTaprootKeySpend computes a signature over a Taro virtual transaction spending a Taro input through the key path, following BIP 86. This signature is attached to a Taro output asset before state transition validation.

func VirtualTx

func VirtualTx(newAsset *asset.Asset, prevAssets commitment.InputSet) (
	*wire.MsgTx, mssmt.Tree, error)

VirtualTx constructs the virtual transaction that enables the movement of an asset representing an asset state transition.

func VirtualTxWithInput

func VirtualTxWithInput(virtualTx *wire.MsgTx, input *asset.Asset,
	idx uint32, witness wire.TxWitness) *wire.MsgTx

VirtualTxWithInput returns a copy of the `virtualTx` amended to include all input-specific details.

This is used to further bind a given witness to the "true" input it spends. We'll use the index of the serialized input to bind the prev index, which represents the "leaf index" of the virtual input MS-SMT.

Types

type MockSigner

type MockSigner struct {
	PrivKey *btcec.PrivateKey
}

func NewMockSigner

func NewMockSigner(privKey *btcec.PrivateKey) *MockSigner

func (*MockSigner) SignOutputRaw

func (m *MockSigner) SignOutputRaw(tx *wire.MsgTx,
	signDesc *input.SignDescriptor) (*schnorr.Signature, error)

SignOutputRaw creates a signature for a single input. Taken from lnd/lnwallet/btcwallet/signer:L344, SignOutputRaw

func (*MockSigner) SignVirtualTx

func (m *MockSigner) SignVirtualTx(signDesc *lndclient.SignDescriptor,
	tx *wire.MsgTx, prevOut *wire.TxOut) (*schnorr.Signature, error)

type Signer

type Signer interface {
	// SignVirtualTx generates a signature according to the passed signing
	// descriptor and TX.
	//
	// NOTE: We currently assume the signature requested is for the/ BIP 86
	// spending type.
	SignVirtualTx(signDesc *lndclient.SignDescriptor, tx *wire.MsgTx,
		prevOut *wire.TxOut) (*schnorr.Signature, error)
}

Signer is the interface used to compute the witness for a Taro virtual TX.

type SpendCommitments

type SpendCommitments = map[[32]byte]commitment.TaroCommitment

SpendCommitments stores the Taro commitment for each receiver (including the sender), which is needed to create the final PSBT for the transfer.

func CreateSpendCommitments

func CreateSpendCommitments(inputCommitment *commitment.TaroCommitment,
	prevInput asset.PrevID, spend SpendDelta, addr address.Taro,
	senderScriptKey btcec.PublicKey) (SpendCommitments, error)

CreateSpendCommitments creates the final set of TaroCommitments representing the asset send. The input TaroCommitment must become a valid change commitment by removing the input asset and adding the root split asset if present. The receiver TaroCommitment must include the output asset.

type SpendDelta

type SpendDelta struct {
	// NewAsset is the Asset that will be validated by the Taro VM.
	// In the case of an asset split, it is the root locator that also
	// contains the split commitment. Otherwise, it is the asset that will
	// be sent to the receiver.
	NewAsset asset.Asset

	// InputAssets maps asset PrevIDs to Assets being spent by the sender.
	InputAssets commitment.InputSet

	// Locators maps AssetCommitmentKeys for all receivers to splitLocators.
	// The locators are used to create split commitments, and store indexes
	// for each receiver's corresponding Bitcoin output.
	Locators SpendLocators

	// NOTE: This is nil unless the InputAsset is being split.
	SplitCommitment *commitment.SplitCommitment
}

SpendDelta stores the information needed to prepare new asset leaves or a split commitment, and validated a spend with the Taro VM. SpendDelta is also used to create the final TaroCommitments for each receiver.

func CompleteAssetSpend

func CompleteAssetSpend(internalKey btcec.PublicKey, prevInput asset.PrevID,
	delta SpendDelta, signer Signer,
	validator TxValidator) (*SpendDelta, error)

CompleteAssetSpend updates the new Asset by creating a signature over the asset transfer, verifying the transfer with the Taro VM, and attaching that signature to the new Asset.

func PrepareAssetCompleteSpend

func PrepareAssetCompleteSpend(addr address.Taro, prevInput asset.PrevID,
	delta SpendDelta) *SpendDelta

PrepareAssetCompleteSpend computes a new asset leaf for spends that fully consume the input, i.e. collectibles or an equal-valued send. Input MUST be checked as valid beforehand.

func PrepareAssetSplitSpend

func PrepareAssetSplitSpend(addr address.Taro, prevInput asset.PrevID,
	scriptKey btcec.PublicKey, delta SpendDelta) (*SpendDelta, error)

PrepareAssetSplitSpend computes a split commitment with the given input and spend information. Input MUST be checked as valid beforehand, and locators MUST be checked for validity beforehand if provided.

TODO(jhb): This assumes only 2 split outputs / 1 receiver; needs update to support multiple receivers.

func (*SpendDelta) Copy

func (s *SpendDelta) Copy() SpendDelta

Copy returns a deep copy of a SpendDelta.

type SpendLocators

type SpendLocators = map[[32]byte]commitment.SplitLocator

SpendLocators stores a split locators for each receiver, keyed by their AssetCommitmentKey. These locators are used to create split commitments and the final PSBT for the transfer. AssetCommitmentKeys are unique to each asset and each receiver due to the inclusion of the receiver's ScriptKey.

func CreateDummyLocators

func CreateDummyLocators(stateKeys [][32]byte) SpendLocators

CreateDummyLocators creates a set of split locators with continuous output indexes, starting for 0. These mock locators are used for initial split commitment validation, and are the default for the final PSBT.

type TxValidator

type TxValidator interface {
	// Execute creates an instance of the Taro VM and validates
	// an asset transfer, including the attached witnesses.
	Execute(newAsset *asset.Asset, splitAsset *commitment.SplitAsset,
		prevAssets commitment.InputSet) error
}

TxValidator is the interface used to validate an asset transfer with the Taro VM.

Jump to

Keyboard shortcuts

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