tree

package
v0.0.0-...-241d3e1 Latest Latest
Warning

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

Go to latest
Published: Jun 6, 2025 License: MIT Imports: 20 Imported by: 8

Documentation

Index

Constants

View Source
const (
	OP_INSPECTOUTPUTSCRIPTPUBKEY = 0xd1
	OP_INSPECTOUTPUTVALUE        = 0xcf
	OP_PUSHCURRENTINPUTINDEX     = 0xcd
	OP_INSPECTINPUTVALUE         = 0xc9
	OP_SUB64                     = 0xd8
)
View Source
const ConditionWitnessKey = "condition"

Variables

View Source
var (
	COSIGNER_PSBT_KEY_PREFIX     = []byte("cosigner")
	CONDITION_WITNESS_KEY_PREFIX = []byte(ConditionWitnessKey)
	VTXO_TREE_EXPIRY_PSBT_KEY    = []byte("expiry")
	VTXO_TAPROOT_TREE_KEY        = []byte("taptree")
)
View Source
var (
	ErrParentNotFound = errors.New("parent not found")
	ErrLeafNotFound   = errors.New("leaf not found in vtxo tree")
)
View Source
var (
	ErrInvalidRoundTx             = fmt.Errorf("invalid round transaction")
	ErrInvalidRoundTxOutputs      = fmt.Errorf("invalid number of outputs in round transaction")
	ErrEmptyTree                  = fmt.Errorf("empty vtxo tree")
	ErrInvalidRootLevel           = fmt.Errorf("root level must have only one node")
	ErrNoLeaves                   = fmt.Errorf("no leaves in the tree")
	ErrNodeTxEmpty                = fmt.Errorf("node transaction is empty")
	ErrNodeTxidEmpty              = fmt.Errorf("node txid is empty")
	ErrNodeParentTxidEmpty        = fmt.Errorf("node parent txid is empty")
	ErrNodeTxidDifferent          = fmt.Errorf("node txid differs from node transaction")
	ErrNumberOfInputs             = fmt.Errorf("node transaction should have only one input")
	ErrNumberOfOutputs            = fmt.Errorf("node transaction should have only three or two outputs")
	ErrParentTxidInput            = fmt.Errorf("parent txid should be the input of the node transaction")
	ErrNumberOfChildren           = fmt.Errorf("node branch transaction should have two children")
	ErrLeafChildren               = fmt.Errorf("leaf node should have max 1 child")
	ErrInvalidChildTxid           = fmt.Errorf("invalid child txid")
	ErrInternalKey                = fmt.Errorf("invalid taproot internal key")
	ErrInvalidTaprootScript       = fmt.Errorf("invalid taproot script")
	ErrMissingCosignersPublicKeys = fmt.Errorf("missing cosigners public keys")
	ErrInvalidAmount              = fmt.Errorf("children amount is different from parent amount")
	ErrInvalidSweepSequence       = fmt.Errorf("invalid sweep sequence")
	ErrInvalidServer              = fmt.Errorf("invalid server")
	ErrMissingFeeOutput           = fmt.Errorf("missing fee output")
	ErrInvalidLeftOutput          = fmt.Errorf("invalid left output")
	ErrInvalidRightOutput         = fmt.Errorf("invalid right output")
	ErrMissingSweepTapscript      = fmt.Errorf("missing sweep tapscript")
	ErrInvalidLeaf                = fmt.Errorf("leaf node shouldn't have children")
	ErrWrongRoundTxid             = fmt.Errorf("the input of the tree root is not the round tx's shared output")
)
View Source
var (
	ErrMissingVtxoTree = errors.New("missing vtxo tree")
)
View Source
var ErrNoExitLeaf = fmt.Errorf("no exit leaf")

Functions

func AddConditionWitness

func AddConditionWitness(inIndex int, ptx *psbt.Packet, witness wire.TxWitness) error

func AddCosignerKey

func AddCosignerKey(inIndex int, ptx *psbt.Packet, key *secp256k1.PublicKey) error

func AddTaprootTree

func AddTaprootTree(inIndex int, ptx *psbt.Packet, leaves []string) error

AddTaprootTree adds the whole taproot tree of the VTXO to the given PSBT input. it follows the format of PSBT_OUT_TAP_TREE / BIP-371

func AddVtxoTreeExpiry

func AddVtxoTreeExpiry(inIndex int, ptx *psbt.Packet, vtxoTreeExpiry common.RelativeLocktime) error

func AggregateKeys

func AggregateKeys(
	pubkeys []*btcec.PublicKey,
	scriptRoot []byte,
) (*musig2.AggregateKey, error)

AggregateKeys is a wrapper around musig2.AggregateKeys using the given scriptRoot as taproot tweak

func BuildForfeitTx

func BuildForfeitTx(
	connectorInput, vtxoInput *wire.OutPoint,
	vtxoAmount, connectorAmount, feeAmount uint64,
	vtxoScript, connectorScript, serverScript []byte,
	txLocktime uint32,
) (*psbt.Packet, error)

func BuildRedeemTx

func BuildRedeemTx(
	vtxos []common.VtxoInput,
	outputs []*wire.TxOut,
) (string, error)

func CraftConnectorsOutput

func CraftConnectorsOutput(
	receivers []Leaf,
	feeSatsPerNode uint64,
) ([]byte, int64, error)

CraftConnectorsOutput returns the taproot script and the amount of the root shared output of a connectors tree radix is hardcoded to 4

func CraftSharedOutput

func CraftSharedOutput(
	receivers []Leaf,
	feeSatsPerNode uint64,
	sweepTapTreeRoot []byte,
) ([]byte, int64, error)

CraftSharedOutput returns the taproot script and the amount of the root shared output of a vtxo tree radix is hardcoded to 2

func ExecuteBoolScript

func ExecuteBoolScript(script []byte, witness wire.TxWitness) (bool, error)

ExecuteBoolScript run the script with the provided witness as argument the result must be a boolean value accepted by OP_IF / OP_NOTIF opcodes

func GetConditionWitness

func GetConditionWitness(in psbt.PInput) (wire.TxWitness, error)

func GetCosignerKeys

func GetCosignerKeys(in psbt.PInput) ([]*secp256k1.PublicKey, error)

func GetTaprootTree

func GetTaprootTree(in psbt.PInput) ([]string, error)

GetTaprootTree returns the taproot tree of the given PSBT input.

func GetVtxoTreeExpiry

func GetVtxoTreeExpiry(in psbt.PInput) (*common.RelativeLocktime, error)

func ReadTxWitness

func ReadTxWitness(witnessSerialized []byte) (wire.TxWitness, error)

func UnspendableKey

func UnspendableKey() *secp256k1.PublicKey

func ValidateTreeSigs

func ValidateTreeSigs(
	scriptRoot []byte,
	roundSharedOutputAmount int64,
	vtxoTree TxTree,
) error

ValidateTreeSigs iterates over the tree matrix and verify the TaprootKeySpendSig the public key is rebuilt from the keys set in the unknown field of the psbt

func ValidateVtxoTree

func ValidateVtxoTree(
	vtxoTree TxTree, roundTx string, serverPubkey *secp256k1.PublicKey, vtxoTreeExpiry common.RelativeLocktime,
) error

ValidateVtxoTree checks if the given vtxo tree is valid roundTxid & roundTxIndex & roundTxAmount are used to validate the root input outpoint serverPubkey & vtxoTreeExpiry are used to validate the sweep tapscript leaves besides that, the function validates: - the number of nodes - the number of leaves - children coherence with parent - every control block and taproot output scripts - input and output amounts

Types

type CLTVMultisigClosure

type CLTVMultisigClosure struct {
	MultisigClosure
	Locktime common.AbsoluteLocktime
}

CLTVMultisigClosure is a closure that contains a list of public keys and a CHECKLOCKTIMEVERIFY. The witness size is 64 bytes per key, admitting the sighash type is SIGHASH_DEFAULT.

func (*CLTVMultisigClosure) Decode

func (d *CLTVMultisigClosure) Decode(script []byte) (bool, error)

func (*CLTVMultisigClosure) Script

func (d *CLTVMultisigClosure) Script() ([]byte, error)

func (*CLTVMultisigClosure) Witness

func (f *CLTVMultisigClosure) Witness(controlBlock []byte, signatures map[string][]byte) (wire.TxWitness, error)

func (*CLTVMultisigClosure) WitnessSize

func (f *CLTVMultisigClosure) WitnessSize(extraWitnessSizes ...int) int

type CSVMultisigClosure

type CSVMultisigClosure struct {
	MultisigClosure
	Locktime common.RelativeLocktime
}

CSVMultisigClosure is a closure that contains a list of public keys and a CHECKSEQUENCEVERIFY. The witness size is 64 bytes per key, admitting the sighash type is SIGHASH_DEFAULT.

func (*CSVMultisigClosure) Decode

func (d *CSVMultisigClosure) Decode(script []byte) (bool, error)

func (*CSVMultisigClosure) Script

func (d *CSVMultisigClosure) Script() ([]byte, error)

func (*CSVMultisigClosure) Witness

func (f *CSVMultisigClosure) Witness(controlBlock []byte, signatures map[string][]byte) (wire.TxWitness, error)

func (*CSVMultisigClosure) WitnessSize

func (f *CSVMultisigClosure) WitnessSize(extraWitnessSizes ...int) int

type Closure

type Closure interface {
	Script() ([]byte, error)
	Decode(script []byte) (bool, error)
	// WitnessSize returns the size of the witness excluding the script and control block
	// extraWitnessSize is here to count the condition witness size
	// or any other witness size that can't be computed from the script
	WitnessSize(extraWitnessSize ...int) int
	Witness(controlBlock []byte, signatures map[string][]byte) (wire.TxWitness, error)
}

func DecodeClosure

func DecodeClosure(script []byte) (Closure, error)

type ConditionCSVMultisigClosure

type ConditionCSVMultisigClosure struct {
	CSVMultisigClosure
	Condition []byte
}

ConditionCSVMultisigClosure is a closure that contains a condition and a CSV multisig closure. The condition is a boolean script that is executed with the multisig witness.

func (*ConditionCSVMultisigClosure) Decode

func (f *ConditionCSVMultisigClosure) Decode(script []byte) (bool, error)

func (*ConditionCSVMultisigClosure) Script

func (f *ConditionCSVMultisigClosure) Script() ([]byte, error)

func (*ConditionCSVMultisigClosure) Witness

func (f *ConditionCSVMultisigClosure) Witness(controlBlock []byte, args map[string][]byte) (wire.TxWitness, error)

func (*ConditionCSVMultisigClosure) WitnessSize

func (f *ConditionCSVMultisigClosure) WitnessSize(conditionWitnessSizes ...int) int

type ConditionMultisigClosure

type ConditionMultisigClosure struct {
	MultisigClosure
	Condition []byte
}

ConditionMultisigClosure is a closure that contains a condition and a multisig closure. The condition is a boolean script that is executed with the multisig witness.

func (*ConditionMultisigClosure) Decode

func (f *ConditionMultisigClosure) Decode(script []byte) (bool, error)

func (*ConditionMultisigClosure) Script

func (f *ConditionMultisigClosure) Script() ([]byte, error)

func (*ConditionMultisigClosure) Witness

func (f *ConditionMultisigClosure) Witness(controlBlock []byte, args map[string][]byte) (wire.TxWitness, error)

func (*ConditionMultisigClosure) WitnessSize

func (f *ConditionMultisigClosure) WitnessSize(conditionWitnessSizes ...int) int

type CoordinatorSession

type CoordinatorSession interface {
	AddNonce(*btcec.PublicKey, TreeNonces)
	AddSignatures(*btcec.PublicKey, TreePartialSigs)
	AggregateNonces() (TreeNonces, error)
	// SignTree combines the signatures and add them to the tree's psbts
	SignTree() (TxTree, error)
}

func NewTreeCoordinatorSession

func NewTreeCoordinatorSession(
	roundSharedOutputAmount int64,
	vtxoTree TxTree,
	scriptRoot []byte,
) (CoordinatorSession, error)

type IntentMessage

type IntentMessage struct {
	// InputTapTrees is the list of taproot trees associated with the spent inputs
	// the index of the taproot tree in the list corresponds to the index of the input + 1
	// (we ignore the first bip322 input, as it is duplicate of the second one)
	InputTapTrees []string `json:"input_tap_trees"`
	// OnchainOutputIndexes specifies what are the outputs in the proof tx
	// that should be considered as onchain by the Ark operator
	OnchainOutputIndexes []int `json:"onchain_output_indexes"`
	// ValidAt is the timestamp (in seconds) at which the proof should be considered valid
	// if set to 0, the proof will be considered valid indefinitely or until ExpireAt is reached
	ValidAt int64 `json:"valid_at"`
	// ExpireAt is the timestamp (in seconds) at which the proof should be considered invalid
	// if set to 0, the proof will be considered valid indefinitely
	ExpireAt int64 `json:"expire_at"`
	// Musig2Data contains the related information about the vtxo tree signing
	// if the outputs are not registered in the proof or all the outputs are onchain, this field is not required
	Musig2Data *Musig2 `json:"musig2_data"`
}

func (*IntentMessage) Decode

func (m *IntentMessage) Decode(data string) error

func (IntentMessage) Encode

func (m IntentMessage) Encode() (string, error)

type Leaf

type Leaf struct {
	Script     string
	Amount     uint64
	Musig2Data *Musig2
}

Leaf is the output leaf of a TxTree

type MultisigClosure

type MultisigClosure struct {
	PubKeys []*secp256k1.PublicKey
	Type    MultisigType
}

MultisigClosure is a closure that contains a list of public keys and a CHECKSIG for each key. The witness size is 64 bytes per key, admitting the sighash type is SIGHASH_DEFAULT.

func (*MultisigClosure) Decode

func (f *MultisigClosure) Decode(script []byte) (bool, error)

func (*MultisigClosure) Script

func (f *MultisigClosure) Script() ([]byte, error)

func (*MultisigClosure) Witness

func (f *MultisigClosure) Witness(controlBlock []byte, signatures map[string][]byte) (wire.TxWitness, error)

func (*MultisigClosure) WitnessSize

func (f *MultisigClosure) WitnessSize(_ ...int) int

type MultisigType

type MultisigType int
const (
	MultisigTypeChecksig MultisigType = iota
	MultisigTypeChecksigAdd
)

type Musig2

type Musig2 struct {
	CosignersPublicKeys []string    `json:"cosigners_public_keys"`
	SigningType         SigningType `json:"signing_type"`
}

type Musig2Nonce

type Musig2Nonce struct {
	PubNonce [66]byte
}

func (*Musig2Nonce) Decode

func (n *Musig2Nonce) Decode(r io.Reader) error

func (*Musig2Nonce) Encode

func (n *Musig2Nonce) Encode(w io.Writer) error

type Node

type Node struct {
	Txid       string
	Tx         string
	ParentTxid string
	Leaf       bool
}

Node is a struct embedding the transaction and the parent txid of a vtxo tree node

type SignerSession

type SignerSession interface {
	Init(scriptRoot []byte, rootSharedOutputAmount int64, vtxoTree TxTree) error
	GetPublicKey() string
	GetNonces() (TreeNonces, error) // generate tree nonces for this session
	SetAggregatedNonces(TreeNonces) // set the aggregated nonces
	Sign() (TreePartialSigs, error) // sign the tree
}

func NewTreeSignerSession

func NewTreeSignerSession(signer *btcec.PrivateKey) SignerSession

type SigningType

type SigningType uint8
const (
	// SignAll makes the signer sign all the branches
	SignAll SigningType = iota
	// SignBranch makes the signer sign only its own branch
	SignBranch
)

type TapTree

type TapTree []string

TapTree is a wrapper around a list of tapscripts it is used to encode and decode the taproot tree in a way that is compatible with the PSBT_OUT_TAP_TREE field / BIP-371

func DecodeTapTree

func DecodeTapTree(data []byte) (TapTree, error)

func (TapTree) Encode

func (t TapTree) Encode() ([]byte, error)

type TapscriptsVtxoScript

type TapscriptsVtxoScript struct {
	Closures []Closure
}

func NewDefaultVtxoScript

func NewDefaultVtxoScript(owner, server *secp256k1.PublicKey, exitDelay common.RelativeLocktime) *TapscriptsVtxoScript

func (*TapscriptsVtxoScript) Decode

func (v *TapscriptsVtxoScript) Decode(scripts []string) error

func (*TapscriptsVtxoScript) Encode

func (v *TapscriptsVtxoScript) Encode() ([]string, error)

func (*TapscriptsVtxoScript) ExitClosures

func (v *TapscriptsVtxoScript) ExitClosures() []Closure

func (*TapscriptsVtxoScript) ForfeitClosures

func (v *TapscriptsVtxoScript) ForfeitClosures() []Closure

func (*TapscriptsVtxoScript) SmallestExitDelay

func (v *TapscriptsVtxoScript) SmallestExitDelay() (*common.RelativeLocktime, error)

func (*TapscriptsVtxoScript) TapTree

func (v *TapscriptsVtxoScript) TapTree() (*secp256k1.PublicKey, bitcoinTapTree, error)

func (*TapscriptsVtxoScript) Validate

func (v *TapscriptsVtxoScript) Validate(server *secp256k1.PublicKey, minLocktime common.RelativeLocktime) error

type TreeNonces

type TreeNonces [][]*Musig2Nonce // public nonces only

func DecodeNonces

func DecodeNonces(r io.Reader) (TreeNonces, error)

func (TreeNonces) Encode

func (n TreeNonces) Encode(w io.Writer) error

type TreePartialSigs

type TreePartialSigs [][]*musig2.PartialSignature

func DecodeSignatures

func DecodeSignatures(r io.Reader) (TreePartialSigs, error)

func (TreePartialSigs) Encode

func (s TreePartialSigs) Encode(w io.Writer) error

type TxTree

type TxTree [][]Node

TxTree is reprensented as a matrix of TreeNode struct the first level of the matrix is the root of the tree

func BuildConnectorsTree

func BuildConnectorsTree(
	initialInput *wire.OutPoint,
	receivers []Leaf,
	feeSatsPerNode uint64,
) (TxTree, error)

BuildConnectorsTree creates all the tree's transactions and returns the vtxo tree radix is hardcoded to 4

func BuildVtxoTree

func BuildVtxoTree(
	initialInput *wire.OutPoint,
	receivers []Leaf,
	feeSatsPerNode uint64,
	sweepTapTreeRoot []byte,
	vtxoTreeExpiry common.RelativeLocktime,
) (TxTree, error)

BuildVtxoTree creates all the tree's transactions and returns the vtxo tree radix is hardcoded to 2

func (TxTree) Branch

func (c TxTree) Branch(leafTxid string) ([]Node, error)

Branch returns the branch of the given leaf's txid from root to leaf in the order of the vtxo tree

func (TxTree) Children

func (c TxTree) Children(nodeTxid string) []Node

Children returns all the nodes that have the given node as parent

func (TxTree) Leaves

func (c TxTree) Leaves() []Node

Leaves returns the leaves of the vtxo tree

func (TxTree) NumberOfNodes

func (c TxTree) NumberOfNodes() int

NumberOfNodes returns the total number of pset in the vtxo tree

func (TxTree) Root

func (c TxTree) Root() (Node, error)

Root returns the root node of the vtxo tree

func (TxTree) Validate

func (c TxTree) Validate(getTxID func(string) string) error

Validate checks if the tree is coherent

type VtxoScript

type VtxoScript common.VtxoScript[bitcoinTapTree, Closure]

func ParseVtxoScript

func ParseVtxoScript(scripts []string) (VtxoScript, error)

Jump to

Keyboard shortcuts

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