Documentation
¶
Index ¶
- Constants
- func BuildBatchOutput(vtxos []VTXODescriptor, operatorMuSigKey *btcec.PublicKey, ...) (*wire.TxOut, error)
- func BuildConnectorOutput(numConnectors int, dustAmount btcutil.Amount, connectorAddr btcaddr.Address) (*wire.TxOut, error)
- func ComputeFinalKey(cosigners []*btcec.PublicKey, sweepTapscriptRoot []byte) (*btcec.PublicKey, error)
- func ContainsCosigner(cosigners []*btcec.PublicKey, targetKey *btcec.PublicKey) bool
- func Materialize(ctx context.Context, root *Node, rootParams MaterializeParams, ...) error
- func NewBranchSweepSpendInfo(internalKey, sweepKey *btcec.PublicKey, csvDelay uint32) (*arkscript.SpendInfo, error)
- func UniqueCosigners(cosigners []*btcec.PublicKey) []*btcec.PublicKey
- func ValidateConnectorDescriptor(conn ConnectorDescriptor) error
- func ValidateVTXODescriptors(vtxos []VTXODescriptor) error
- type BTCMaterializer
- type ConnectorDescriptor
- type LeafDescriptor
- type MaterializeParams
- type Materializer
- type Musig2PubNonce
- type Node
- func (n *Node) AddSignature(sig *schnorr.Signature)
- func (n *Node) Depth() int
- func (n *Node) ExtractPathForCoSigners(targetKeys ...*btcec.PublicKey) (*Node, bool)
- func (n *Node) ExtractPathForIndices(targetIndices ...int) (*Node, error)
- func (n *Node) ForEach(callback func(*Node) error) error
- func (n *Node) ForEachLeaf(callback func(*Node) error) error
- func (n *Node) GetLeafForCoSigner(targetKey *btcec.PublicKey) *Node
- func (n *Node) GetLeafNodes() []*Node
- func (n *Node) GetNonAnchorOutpoint() (*wire.OutPoint, error)
- func (n *Node) IsLeaf() bool
- func (n *Node) LeavesIter() iter.Seq[*Node]
- func (n *Node) NewSignerSession(signerKey *keychain.KeyDescriptor, signer input.MuSig2Signer, ...) (*input.MuSig2SessionInfo, error)
- func (n *Node) NewTxSignerSession(signer input.MuSig2Signer, sweepTapscriptRoot []byte, ...) (*TxSignerSession, error)
- func (n *Node) NodesIter() iter.Seq[*Node]
- func (n *Node) NumTx() int
- func (n *Node) PrettyPrint() string
- func (n *Node) PrevOutputFetcher(initialPrevOut *wire.TxOut) (txscript.PrevOutputFetcher, error)
- func (n *Node) SetChildren(children map[uint32]*Node)
- func (n *Node) SigHash(prevOutFetcher txscript.PrevOutputFetcher) ([]byte, error)
- func (n *Node) TXID() (chainhash.Hash, error)
- func (n *Node) ToSignedTx() (*wire.MsgTx, error)
- func (n *Node) ToTx() (*wire.MsgTx, error)
- func (n *Node) Verify() error
- func (n *Node) VerifySigned(prevOutFetcher txscript.PrevOutputFetcher) error
- type PartitionWeightFunc
- type Queue
- type ScriptLookup
- type SignerSession
- func (s *SignerSession) Cleanup() error
- func (s *SignerSession) GetNonces() map[TxID]Musig2PubNonce
- func (s *SignerSession) PubKey() *btcec.PublicKey
- func (s *SignerSession) RegisterAggNonces(nonceSet map[TxID]Musig2PubNonce) error
- func (s *SignerSession) Signatures(cleanup bool) (map[TxID]*musig2.PartialSignature, error)
- type Structure
- type StructureConfig
- type Tree
- func BuildConnectorTree(batchOutpoint wire.OutPoint, batchOutput *wire.TxOut, ...) (*Tree, error)
- func BuildVTXOTree(batchOutpoint wire.OutPoint, batchOutput *wire.TxOut, vtxos []VTXODescriptor, ...) (*Tree, error)
- func NewTree(rootOutpoint wire.OutPoint, rootOutput *wire.TxOut, leaves []LeafDescriptor, ...) (*Tree, error)
- func NewTreeWithConfig(rootOutpoint wire.OutPoint, rootOutput *wire.TxOut, leaves []LeafDescriptor, ...) (*Tree, error)
- func (t *Tree) Depth() int
- func (t *Tree) ExtractPathForCoSigners(targetKeys ...*btcec.PublicKey) (*Tree, error)
- func (t *Tree) ExtractPathForIndices(leafIndices ...int) (*Tree, error)
- func (t *Tree) ExtractTxids() ([]TxidEntry, error)
- func (t *Tree) NewTreeSignerSession(wallet input.MuSig2Signer, signerKey *keychain.KeyDescriptor) (*SignerSession, error)
- func (t *Tree) NumLeaves() int
- func (t *Tree) NumTx() int
- func (t *Tree) PrettyPrint() string
- func (t *Tree) SubmitTreeSigs(sigs map[TxID]*schnorr.Signature) error
- func (t *Tree) ValidateAnchors() error
- func (t *Tree) ValidateAndSubmitSignatures(signatures map[chainhash.Hash][]byte) error
- func (t *Tree) ValidatePath(signingKey *btcec.PublicKey, expectedLeaf LeafDescriptor, ...) (*Tree, error)
- func (t *Tree) Verify() error
- func (t *Tree) VerifySigned() error
- func (t *Tree) VerifyVTXOPath(coSignerKey *btcec.PublicKey, expectedVTXOScript []byte) error
- type TreeAssembler
- type TreeBuildConfig
- type TreeConfig
- type TxID
- type TxSignerSession
- type TxidEntry
- type VTXODescriptor
Constants ¶
const (
// DefaultRadix is the default branching factor for tree construction.
DefaultRadix = 2
)
const NumLeafOutputs = 2
NumLeafOutputs is the number of outputs in a leaf node transaction. Leaf nodes always have exactly 2 outputs:
- For VTXO tree leaves: [VTXO output, anchor output]
- For connector tree leaves: [dust connector output, anchor output]
Variables ¶
This section is empty.
Functions ¶
func BuildBatchOutput ¶
func BuildBatchOutput(vtxos []VTXODescriptor, operatorMuSigKey *btcec.PublicKey, sweepKey *btcec.PublicKey, sweepDelay uint32) (*wire.TxOut, error)
BuildBatchOutput computes the pkscript and output amount for a batch output in the commitment transaction. This output will be spent by the root of the VTXO tree.
The output has two spend paths:
- Collaborative keyspend path: MuSig2 aggregation of operator + all client cosigners, tweaked with the sweep tapscript root.
- CSV timeout script path: Allows operator to sweep after batch expiry.
Since all transactions in the VTXT include ephemeral anchor outputs, the total amount is simply the sum of all VTXO amounts.
func BuildConnectorOutput ¶
func BuildConnectorOutput(numConnectors int, dustAmount btcutil.Amount, connectorAddr btcaddr.Address) (*wire.TxOut, error)
BuildConnectorOutput computes the pkscript and output amount for a connector output in the commitment transaction. This output will be spent by the root of the connector tree.
The total amount is numConnectors * dustAmount since each connector leaf receives the dust amount.
func ComputeFinalKey ¶
func ComputeFinalKey(cosigners []*btcec.PublicKey, sweepTapscriptRoot []byte) (*btcec.PublicKey, error)
ComputeFinalKey computes the final aggregated public key for signing. This is a helper function that aggregates the cosigners and applies the taproot tweak with the given sweep tapscript root. It handles both single-key and multi-key cases.
func ContainsCosigner ¶
ContainsCosigner checks if a target key is present in the cosigners list.
func Materialize ¶
func Materialize(ctx context.Context, root *Node, rootParams MaterializeParams, mat Materializer) error
Materialize walks the tree top-down iteratively and materializes each node using the provided Materializer. This is pass 2 of the two-pass tree construction.
The function uses an explicit stack for depth-first traversal, avoiding recursion to prevent stack overflow for deep trees.
func NewBranchSweepSpendInfo ¶
func NewBranchSweepSpendInfo(internalKey, sweepKey *btcec.PublicKey, csvDelay uint32) (*arkscript.SpendInfo, error)
NewBranchSweepSpendInfo derives the spend information for the operator's sweep path that is committed to in branch transactions. The internalKey parameter must be the pre-tweaked MuSig2 aggregate key for the branch output.
func UniqueCosigners ¶
UniqueCosigners removes duplicate cosigner keys while preserving order.
func ValidateConnectorDescriptor ¶
func ValidateConnectorDescriptor(conn ConnectorDescriptor) error
ValidateConnectorDescriptor validates a connector descriptor ensuring it is suitable for connector tree construction.
func ValidateVTXODescriptors ¶
func ValidateVTXODescriptors(vtxos []VTXODescriptor) error
ValidateVTXODescriptors validates a slice of VTXO descriptors ensuring they meet all requirements for tree construction.
Types ¶
type BTCMaterializer ¶
type BTCMaterializer struct {
// OperatorKey is the operator's public key.
OperatorKey *btcec.PublicKey
// SweepTapscriptRoot is the tapscript root for the sweep script.
SweepTapscriptRoot []byte
// LeafScriptFn returns the output script for leaf nodes. This is
// populated during structure building and used here during
// materialization.
LeafScriptFn ScriptLookup
}
BTCMaterializer builds simple BTC tree transactions. It implements the Materializer interface for BTC-only trees.
func NewBTCMaterializer ¶
func NewBTCMaterializer(operatorKey *btcec.PublicKey, sweepTapscriptRoot []byte, leafScriptFn ScriptLookup) *BTCMaterializer
NewBTCMaterializer creates a new BTC materializer. The leafScriptFn parameter provides leaf output scripts populated during structure building.
func (*BTCMaterializer) MaterializeNode ¶
func (m *BTCMaterializer) MaterializeNode(_ context.Context, node *Node, params MaterializeParams) (map[uint32]MaterializeParams, error)
MaterializeNode fills in transaction data for a single node. For BTC trees, this involves computing the final key and building outputs.
NOTE: BTC trees use Node.Amount (set during structure building) for output values.
type ConnectorDescriptor ¶
type ConnectorDescriptor struct {
// PkScript is the P2TR script for each connector leaf output. All
// connector leaves in the tree will use this same script.
PkScript []byte
// NumLeaves is the number of identical connector leaves to create in
// the tree. Each leaf will have the same PkScript and Amount.
NumLeaves int
// Amount is the value (in satoshis) for each individual connector
// leaf. The total output amount will be NumLeaves * Amount.
Amount btcutil.Amount
}
ConnectorDescriptor defines the specification for a connector tree. Connector trees are used for forfeit transactions and have identical leaves, all signed by the operator only.
func (ConnectorDescriptor) ToLeafDescriptors ¶
func (c ConnectorDescriptor) ToLeafDescriptors( operatorKey *btcec.PublicKey, ) []LeafDescriptor
ToLeafDescriptors expands a connector descriptor into identical leaves using the provided operator key as cosigner.
type LeafDescriptor ¶
type LeafDescriptor struct {
// PkScript is the public key script for the leaf output. This is
// typically a taproot script that includes both keyspend and
// scriptspend paths.
PkScript []byte
// Amount is the value of the leaf output in satoshis.
Amount btcutil.Amount
// CoSignerKey is the public key of the leaf owner who must participate
// in signing this leaf's transaction along with the operator.
CoSignerKey *btcec.PublicKey
}
LeafDescriptor is a generic descriptor for a leaf output in a transaction tree. It is agnostic to whether the leaf represents a VTXO or connector.
type MaterializeParams ¶
MaterializeParams contains the parameters for materializing a single node.
type Materializer ¶
type Materializer interface {
// MaterializeNode fills in Input, Outputs, FinalKey, and OutputsMeta
// for a single node. Returns child params for each child index.
MaterializeNode(ctx context.Context, node *Node,
params MaterializeParams) (map[uint32]MaterializeParams, error)
}
Materializer fills in transaction data for a tree structure. Different implementations handle BTC-only vs Asset trees.
type Musig2PubNonce ¶
type Musig2PubNonce [musig2.PubNonceSize]byte
Musig2PubNonce is a public nonce for MuSig2 signing.
type Node ¶
type Node struct {
// Input is the single outpoint this transaction spends.
Input wire.OutPoint
// Outputs are all the outputs created by this transaction.
// - For VTXO tree leaves: [VTXO output, anchor output]
// - For connector tree leaves: [dust connector output, anchor output]
// - For branches: [child1 output, child2 output, ..., anchor output]
Outputs []*wire.TxOut
// CoSigners is the set of public keys that must participate in
// MuSig2 signing for this transaction's input (keyspend path).
CoSigners []*btcec.PublicKey
// Children maps output index to child Node.
// Empty for leaf nodes.
Children map[uint32]*Node
// Amount is the total BTC value for this node. For leaf nodes, this
// is the leaf's BTC amount. For branch nodes, this is the sum of all
// descendant leaf amounts (subtree total). This is set during
// structure building and used during materialization to determine
// output values.
Amount btcutil.Amount
// Signature is the final aggregated MuSig2 signature for the input.
// This is populated after signing is complete.
Signature *schnorr.Signature
// FinalKey is the final aggregated public key (after taproot tweak)
// that must sign this node's input. This is cached to avoid repeated
// MuSig2 aggregations during signature verification.
FinalKey *btcec.PublicKey
}
Node represents a single transaction in a virtual transaction tree.
func NewBranchNode ¶
func NewBranchNode(input wire.OutPoint, groups [][]LeafDescriptor, operatorKey *btcec.PublicKey, sweepTapscriptRoot []byte) (*Node, error)
NewBranchNode creates a branch node with outputs for each group of leaves.
func NewLeafNode ¶
func NewLeafNode(input wire.OutPoint, leaf LeafDescriptor, operatorKey *btcec.PublicKey, sweepTapscriptRoot []byte) (*Node, error)
NewLeafNode creates a leaf node (transaction with leaf output).
func (*Node) AddSignature ¶
AddSignature sets the signature for this node's transaction.
func (*Node) Depth ¶
Depth returns the maximum depth of the tree. A single node (leaf) has depth 1, a node with children has depth 1 + max depth of children.
func (*Node) ExtractPathForCoSigners ¶
ExtractPathForCoSigners takes a Node and extracts the path that is relevant for one or more cosigners. It returns a new Node that contains only the nodes and children where any of the provided cosigner keys are present in the CoSigners list from root to leaf. The boolean return value indicates whether any matching cosigners were found in this subtree.
func (*Node) ExtractPathForIndices ¶
ExtractPathForIndices extracts the minimal subtree containing paths to all specified leaf indices. Accepts one or more indices as variadic parameters. This is useful when a client has multiple leaves in the same tree (e.g., multiple connector leaves for multiple forfeit requests).
IMPORTANT: Indices are relative to the current tree structure. After extraction, leaves in the returned subtree will be renumbered starting from 0. This means ExtractPathForIndices is NOT idempotent - calling it twice with the same indices will fail on the second call since the leaf positions have changed. If you need stable identifiers across extractions, use ExtractPathForCoSigners instead.
func (*Node) ForEach ¶
ForEach traverses the tree and applies the given callback function to each node. The traversal is done in depth-first order (pre-order: current node, then children). If the callback returns an error, traversal stops and the error is returned.
func (*Node) ForEachLeaf ¶
ForEachLeaf traverses the tree and applies the given callback function to each leaf node only. If the callback returns an error, traversal stops and the error is returned.
func (*Node) GetLeafForCoSigner ¶
GetLeafForCoSigner returns the leaf Node for a specific cosigner. Returns nil if no leaf is found for the cosigner.
func (*Node) GetLeafNodes ¶
GetLeafNodes returns all leaf nodes from this tree.
func (*Node) GetNonAnchorOutpoint ¶
GetNonAnchorOutpoint returns the outpoint for the non-anchor output of this leaf node. Leaf nodes have exactly 2 outputs: one VTXO/connector output and one anchor output. This method returns the outpoint for the non-anchor output by checking which output is not the anchor script.
func (*Node) LeavesIter ¶
LeavesIter returns an iterator over all leaf nodes in the tree.
func (*Node) NewSignerSession ¶
func (n *Node) NewSignerSession(signerKey *keychain.KeyDescriptor, signer input.MuSig2Signer, sweepTapscriptRoot []byte) ( *input.MuSig2SessionInfo, error)
NewSignerSession creates a new MuSig2 signing session for this node.
func (*Node) NewTxSignerSession ¶
func (n *Node) NewTxSignerSession(signer input.MuSig2Signer, sweepTapscriptRoot []byte, signerKey *keychain.KeyDescriptor, fetcher txscript.PrevOutputFetcher) (*TxSignerSession, error)
NewTxSignerSession creates a new signing session for a single transaction in a virtual transaction tree. The point of the session is to facilitate the MuSig2 signing process for a specific transaction. Each transaction has signs the key-spend path of the previous transaction. The parameters are:
- signer: The MuSig2Signer interface to use creating the session and signing.
- sweepTapscriptRoot: The tapscript root used for tweaking the keyspend path.
- signerKey: The key descriptor of the signer.
- fetcher: The PrevOutputFetcher to retrieve the output being spent by this node's transaction.
func (*Node) NodesIter ¶
NodesIter returns an iterator over all nodes in the tree in depth-first pre-order (current node, then children).
func (*Node) NumTx ¶
NumTx returns the total number of transactions in the tree. Each Node represents one transaction, so this counts all nodes in the tree.
func (*Node) PrettyPrint ¶
PrettyPrint returns a human-readable string representation of the tree structure with transaction IDs, amounts, and cosigner information.
func (*Node) PrevOutputFetcher ¶
PrevOutputFetcher creates a PrevOutputFetcher that can provide transaction outputs for all transactions in the tree, starting with the initial previous output that the root transaction spends.
func (*Node) SetChildren ¶
SetChildren sets the children map for this node, replacing any existing children. This is a convenience method for constructing trees.
func (*Node) SigHash ¶
func (n *Node) SigHash(prevOutFetcher txscript.PrevOutputFetcher) ([]byte, error)
SigHash computes the signature hash for this node's transaction.
func (*Node) ToSignedTx ¶
ToSignedTx converts the Node into its signed wire.MsgTx representation. This requires that the node has a signature set.
func (*Node) VerifySigned ¶
func (n *Node) VerifySigned(prevOutFetcher txscript.PrevOutputFetcher) error
VerifySigned verifies that all nodes in the tree have valid signatures.
type PartitionWeightFunc ¶
type PartitionWeightFunc func(LeafDescriptor) int64
PartitionWeightFunc returns the weight used to balance leaves during tree construction. When nil, leaves are partitioned purely by count.
func WeightByBtcAmount ¶
func WeightByBtcAmount() PartitionWeightFunc
WeightByBtcAmount is a partition function that simply prefers the BTC amount.
type Queue ¶
type Queue[T any] struct { // contains filtered or unexported fields }
Queue implements a generic FIFO queue with amortized O(1) Enqueue and Dequeue operations. The zero value is ready to use.
This is a simple slice-based implementation suitable for BFS traversal and other scenarios where elements are added to the back and removed from the front in order.
func NewQueue ¶
NewQueue creates a new empty queue with optional initial capacity. If no capacity is specified, the queue starts with zero capacity and grows as needed.
func (*Queue[T]) Clear ¶
func (q *Queue[T]) Clear()
Clear removes all items from the queue, resetting it to empty. The underlying capacity is preserved.
func (*Queue[T]) Dequeue ¶
Dequeue removes and returns the item at the front of the queue. Returns the item and true if successful, or the zero value and false if the queue is empty.
Note: This implementation does not shrink the underlying slice, so memory usage grows with the maximum queue size reached during the queue's lifetime. For most use cases (like BFS traversal), this is acceptable.
func (*Queue[T]) Enqueue ¶
func (q *Queue[T]) Enqueue(item T)
Enqueue adds an item to the back of the queue. This operation has amortized O(1) complexity due to the underlying slice's growth strategy.
type ScriptLookup ¶
ScriptLookup returns the output script (pkscript) for a leaf node. Returns nil if the node is not a leaf or has no script.
func ScriptLookupFromMap ¶
func ScriptLookupFromMap(leafScripts map[*Node][]byte) ScriptLookup
ScriptLookupFromMap creates a ScriptLookup from a map of node pointers to pkscripts. This is the standard way to provide leaf scripts for BTC tree materialization while keeping the shared Node type asset-agnostic and branch nodes untouched.
type SignerSession ¶
type SignerSession struct {
// contains filtered or unexported fields
}
SignerSession manages signing for all transactions in a client's path in a tree for a given signing key. It automatically extracts the signer's path and creates TxSignerSession for each transaction in that path. If a client has multiple vtxo's in the tree, they will have a SignerSession for each vtxo's signing key.
func NewSignerSession ¶
func NewSignerSession(signer input.MuSig2Signer, signerKey *keychain.KeyDescriptor, sweepTapscriptRoot []byte, prevOuts txscript.PrevOutputFetcher, tree *Node) (*SignerSession, error)
NewSignerSession creates a new signing session for a tree. It automatically extracts the path for the given signer and creates sessions for each transaction in that path.
func (*SignerSession) Cleanup ¶
func (s *SignerSession) Cleanup() error
Cleanup removes every underlying MuSig2 session. It is safe to call Cleanup more than once, including after a partially successful signing attempt.
func (*SignerSession) GetNonces ¶
func (s *SignerSession) GetNonces() map[TxID]Musig2PubNonce
GetNonces returns nonces for all transactions in the signer's path. This is used after all signers have shared their public nonces and the aggregated nonce has been computed for each transaction.
func (*SignerSession) PubKey ¶
func (s *SignerSession) PubKey() *btcec.PublicKey
PubKey returns the signer's public key.
func (*SignerSession) RegisterAggNonces ¶
func (s *SignerSession) RegisterAggNonces( nonceSet map[TxID]Musig2PubNonce) error
RegisterAggNonces registers the aggregated nonce for each transaction in the signer's path.
func (*SignerSession) Signatures ¶
func (s *SignerSession) Signatures(cleanup bool) ( map[TxID]*musig2.PartialSignature, error)
Signatures generates partial signatures for all transactions in the signer's path. If cleanup is true, the signing sessions are cleaned up after signing. This is used in the second round of MuSig2 signing where each signer generates their partial signatures.
type Structure ¶
type Structure struct {
// Root is the root node of the tree structure.
Root *Node
// LeafScriptMap maps leaf node pointers to their output scripts
// (pkscript). This is populated during structure building and used by
// the BTC materializer. We keep BTC leaf data out of Node to keep the
// shared structure asset-agnostic and avoid touching branch nodes.
LeafScriptMap map[*Node][]byte
}
Structure contains the outputs from BuildStructure.
func BuildStructure ¶
func BuildStructure(leaves []LeafDescriptor, cfg StructureConfig) (*Structure, error)
BuildStructure builds the tree structure bottom-up from leaf descriptors. This is pass 1 of the two-pass tree construction. It creates the tree shape, computes cosigners and internal keys - but does NOT build transactions or proofs.
The returned Structure contains:
- Root: The root node with CoSigners and Children populated
- LeafScriptMap: Map of leaf nodes to output scripts (for BTC trees only)
The following Node fields are NOT set (filled in by Materialize):
- Input (zero outpoint)
- Outputs (nil)
- FinalKey
- Signature
type StructureConfig ¶
type StructureConfig struct {
// OperatorKey is the operator's public key (included in all cosigner
// sets).
OperatorKey *btcec.PublicKey
// Radix is the maximum number of children per branch node.
Radix int
// WeightFn determines how leaves are weighted for partitioning.
// If nil, defaults to WeightByBtcAmount().
WeightFn PartitionWeightFunc
}
StructureConfig contains configuration for building tree structure.
type Tree ¶
type Tree struct {
// Root is the root transaction that spends the batch output.
Root *Node
// BatchOutpoint is the outpoint in the commitment transaction
// that the root transaction spends.
BatchOutpoint wire.OutPoint
// BatchOutput is the actual output at BatchOutpoint.
// Used for verification and signing.
BatchOutput *wire.TxOut
// SweepTapscriptRoot is the tapscript root hash used for tweaking
// branch outputs. This is the script from UnilateralCSVTimeoutTapLeaf.
// For VTXO trees, this is the operator's sweep script.
// For connector trees, this is nil (no sweep script).
SweepTapscriptRoot []byte
}
Tree wraps a Node with additional context needed for operations.
**Cache-aliasing invariant.** A *Tree value is treated as effectively immutable once it has been published from a builder or resolver. Multiple downstream consumers may share the same *Tree pointer through caches and ancestry-fragment slices (see `indexer.lineageResolver.treeByKey` and `indexer.cloneLineage`), and silently mutating a shared tree's nodes or roots would corrupt every aliasing reader. Callers that need to transform a tree must clone it first; in-place mutation of a published *Tree is a bug.
func BuildConnectorTree ¶
func BuildConnectorTree(batchOutpoint wire.OutPoint, batchOutput *wire.TxOut, connector ConnectorDescriptor, operatorKey *btcec.PublicKey, radix int) (*Tree, error)
BuildConnectorTree constructs a connector tree from a connector descriptor using a two-phase approach (structure building + materialization). Unlike VTXO trees, connector trees have identical leaves (same script, same amount) and are signed only by the operator. This is used for forfeit transaction inputs.
func BuildVTXOTree ¶
func BuildVTXOTree(batchOutpoint wire.OutPoint, batchOutput *wire.TxOut, vtxos []VTXODescriptor, operatorCoSignKey *btcec.PublicKey, sweepKey *btcec.PublicKey, sweepDelay uint32, radix int) (*Tree, error)
BuildVTXOTree constructs a complete transaction tree from VTXO descriptors using a two-phase approach (structure building + materialization). It returns a Tree with all transactions fully constructed and linked.
func NewTree ¶
func NewTree(rootOutpoint wire.OutPoint, rootOutput *wire.TxOut, leaves []LeafDescriptor, operatorKey *btcec.PublicKey, sweepTapscriptRoot []byte, radix int) (*Tree, error)
NewTree constructs a transaction tree from the given leaves using BFS. The radix parameter controls the branching factor - each branch node will have up to 'radix' children. A radix of 2 creates a binary tree, radix of 4 creates a quad-tree, etc. Higher radix values reduce tree depth but increase transaction size.
func NewTreeWithConfig ¶
func NewTreeWithConfig(rootOutpoint wire.OutPoint, rootOutput *wire.TxOut, leaves []LeafDescriptor, operatorKey *btcec.PublicKey, sweepTapscriptRoot []byte, cfg TreeBuildConfig) (*Tree, error)
NewTreeWithConfig constructs a transaction tree from the given leaves using the two-pass approach with the provided configuration.
func (*Tree) ExtractPathForCoSigners ¶
ExtractPathForCoSigners extracts the path relevant for one or more cosigners and returns a new Tree containing only the nodes where any of the provided cosigner keys are present. This is useful when a client has multiple VTXOs with different keys in the same tree.
func (*Tree) ExtractPathForIndices ¶
ExtractPathForIndices extracts a minimal subtree containing all the paths to the specified leaf indices. Accepts one or more indices as variadic parameters. The returned tree will contain only the nodes necessary to reach all target leaves.
IMPORTANT: Indices are relative to the current tree structure. After extraction, leaves in the returned subtree will be renumbered starting from 0. This means ExtractPathForIndices is NOT idempotent - calling it twice with the same indices will fail on the second call since the leaf positions have changed. If you need stable identifiers across extractions, use ExtractPathForCoSigners instead.
func (*Tree) ExtractTxids ¶
ExtractTxids walks the tree using BFS and returns all transaction IDs with their tree level and output index. This is useful for building indexes that map txids to trees for efficient lookup when chain events occur.
func (*Tree) NewTreeSignerSession ¶
func (t *Tree) NewTreeSignerSession(wallet input.MuSig2Signer, signerKey *keychain.KeyDescriptor) (*SignerSession, error)
NewTreeSignerSession creates a TreeSignerSession for this tree. This is a convenience wrapper that sets up the session with the tree's context.
func (*Tree) PrettyPrint ¶
PrettyPrint returns a human-readable string representation of the full tree.
func (*Tree) SubmitTreeSigs ¶
SubmitTreeSigs stores signatures in the tree nodes. This method does NOT validate the signatures cryptographically - it only stores them. Use VerifySigned after calling this method to validate signatures.
func (*Tree) ValidateAnchors ¶
ValidateAnchors validates that all transactions in the tree have valid ephemeral anchor outputs for CPFP fee bumping (BIP 431).
Without valid anchors, the client cannot broadcast the VTXT chain for unilateral exit, resulting in fund loss.
func (*Tree) ValidateAndSubmitSignatures ¶
ValidateAndSubmitSignatures validates and submits the complete VTXT signatures to the tree. This must be called BEFORE the client signs the boarding UTXO input.
The signatures are provided as a map from transaction ID to raw signature bytes. Each entry corresponds to a transaction in the VTXT.
The client MUST NOT sign the boarding UTXO until the VTXT is fully signed and validated. Otherwise, the operator could include the boarding UTXO in a commitment tx without providing valid VTXOs.
func (*Tree) ValidatePath ¶
func (t *Tree) ValidatePath(signingKey *btcec.PublicKey, expectedLeaf LeafDescriptor, operatorKey *btcec.PublicKey) (*Tree, error)
ValidatePath validates the tree path from the batch output to the client's VTXO for a given signing key. Each signing key maps to exactly one VTXO, providing a unique identifier for the VTXO and keeping MuSig2 signing simple.
The client MUST validate the complete path before signing the boarding UTXO. This ensures they can recover their funds even if the operator disappears.
Returns the extracted client sub-tree on success.
func (*Tree) Verify ¶
Verify recursively verifies that the tree structure is consistent. It checks that each child's input correctly references the parent's transaction at the expected output index.
func (*Tree) VerifySigned ¶
VerifySigned verifies that all nodes in the tree have valid signatures.
func (*Tree) VerifyVTXOPath ¶
VerifyVTXOPath verifies that the tree contains a valid path to a VTXO for the given cosigner and that the leaf VTXO script matches the expected script. This is used by clients to verify they received the correct VTXO path.
type TreeAssembler ¶
type TreeAssembler struct {
// contains filtered or unexported fields
}
TreeAssembler builds a BTC-only tree using the two-pass approach: structure building (pass 1) followed by materialization (pass 2).
func NewTreeAssembler ¶
func NewTreeAssembler(cfg TreeConfig) *TreeAssembler
NewTreeAssembler constructs an assembler with the given configuration.
func (*TreeAssembler) BuildTree ¶
func (a *TreeAssembler) BuildTree(rootInput wire.OutPoint, rootOutput *wire.TxOut, leaves []LeafDescriptor) (*Tree, error)
BuildTree assembles a BTC-only tree using a two-pass approach:
Pass 1 (bottom-up): Build tree structure from leaf descriptors, computing cosigners at each level. No transactions are built yet.
Pass 2 (top-down): Materialize transactions starting from the root, filling in Input, Outputs, and FinalKey as we traverse down the tree.
Parameters:
- rootInput: The outpoint being spent by the root transaction
- rootOutput: The output being spent (provides BTC value)
- leaves: Leaf descriptors defining the tree leaves
Returns the assembled tree.
type TreeBuildConfig ¶
type TreeBuildConfig struct {
// Radix is the branching factor of the tree.
Radix int
// WeightFunc optionally overrides how leaves are balanced into groups.
// When nil, leaves are distributed using WeightByBtcAmount().
WeightFunc PartitionWeightFunc
}
TreeBuildConfig configures tree construction.
type TreeConfig ¶
type TreeConfig struct {
// OperatorKey is the operator's public key (included in all cosigner
// sets).
OperatorKey *btcec.PublicKey
// SweepTapscriptRoot is the tapscript root used for the sweep script.
// This provides the unilateral exit path for tree outputs.
SweepTapscriptRoot []byte
// Radix is the maximum number of children per branch node. If zero,
// defaults to 2.
Radix int
// WeightFn determines how leaves are weighted for partitioning.
// If nil, defaults to WeightByBtcAmount().
WeightFn PartitionWeightFunc
}
TreeConfig carries the parameters needed to build a BTC-only tree.
type TxID ¶
TxID is a type alias for chainhash.Hash, used as a key for maps that index by transaction ID. Using the raw hash type instead of strings improves type safety and avoids unnecessary string conversions.
type TxSignerSession ¶
type TxSignerSession struct {
// contains filtered or unexported fields
}
TxSignerSession manages signing for a single transaction on the client or operator side. It uses lnd's MuSig2Signer interface.
SECURITY: Each TxSignerSession automatically generates fresh nonces via lnd's MuSig2 implementation. Do NOT reuse a TxSignerSession for signing multiple transactions or re-signing the same transaction, as this would constitute nonce reuse and leak the private key.
func (*TxSignerSession) Cleanup ¶
func (s *TxSignerSession) Cleanup() error
Cleanup removes the underlying MuSig2 session. It is safe to call Cleanup more than once after it succeeds. A failed cleanup remains retryable because a remote signer may recover from a transient transport error.
func (*TxSignerSession) GetNonce ¶
func (s *TxSignerSession) GetNonce() Musig2PubNonce
GetNonce returns the public nonce for this signing session.
func (*TxSignerSession) RegisterAggNonce ¶
func (s *TxSignerSession) RegisterAggNonce( aggNonce [musig2.PubNonceSize]byte) error
RegisterAggNonce registers the aggregated nonce for this signing session.
func (*TxSignerSession) Sign ¶
func (s *TxSignerSession) Sign(cleanup bool) (*musig2.PartialSignature, error)
Sign generates the partial signature for this transaction. If cleanup is true, the signing session is cleaned up after signing.
type TxidEntry ¶
type TxidEntry struct {
// Txid is the transaction hash for this tree node.
Txid chainhash.Hash
// TreeLevel is the depth of this node (0 = root, increasing toward
// leaves).
TreeLevel int
// OutputIndex is which output of the parent transaction this node
// spends.
OutputIndex uint32
}
TxidEntry holds information about a single transaction in a tree, including its txid, level in the tree, and which parent output it spends.
type VTXODescriptor ¶
type VTXODescriptor struct {
// PolicyTemplate is the semantic arkscript policy that compiles to
// PkScript. This is the authoritative policy representation for
// persistence and higher-layer validation.
PolicyTemplate []byte
// PkScript is the P2TR script for the VTXO output. This is typically
// generated using arkscript.VTXOTapKey which creates a taproot script
// with both keyspend (collaborative) and scriptspend (timeout) paths.
PkScript []byte
// Amount is the value of this VTXO in satoshis.
Amount btcutil.Amount
// CoSignerKey is the owner-side public key that participates in the
// collaborative spend path for this leaf. This is a tree-construction
// signer role, not local wallet ownership metadata.
CoSignerKey *btcec.PublicKey
}
VTXODescriptor defines the tree-construction inputs for a single VTXO leaf. It carries the compiled output script and the owner-side collaborative signer needed by the generic tree builder, while keeping local wallet ownership metadata out of the tree layer.
func NewVTXODescriptor ¶
func NewVTXODescriptor(amount btcutil.Amount, ownerKey *btcec.PublicKey, operatorKey *btcec.PublicKey, exitDelay uint32) (*VTXODescriptor, error)
NewVTXODescriptor constructs a VTXODescriptor by building the VTXO taproot script using arkscript. This helper builds the standard Ark VTXO shape, encoding the owner/operator policy while preserving only the owner-side collaborative signer that the tree builder needs.
func (VTXODescriptor) ToLeafDescriptor ¶
func (v VTXODescriptor) ToLeafDescriptor() LeafDescriptor
ToLeafDescriptor converts a VTXODescriptor to a generic LeafDescriptor.