supplycommit

package
v0.7.0-rc1 Latest Latest
Warning

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

Go to latest
Published: Sep 12, 2025 License: MIT Imports: 36 Imported by: 0

README

Universe Supply Commitment State Machine

This package implements a state machine responsible for managing the on-chain commitment to the supply of a specific Taproot Asset (identified by its asset.Specifier, namely the group key).

Rationale and Purpose

Taproot Assets allow for issuance and transfer off-chain, but maintaining a verifiable, global view of the total supply requires an on-chain commitment mechanism. This state machine addresses that need.

Its primary purpose is to:

  1. Track Supply Changes: Receive events representing new asset mints (NewMintEvent), asset burns (NewBurnEvent), and ignored outputs (NewIgnoreEvent).

  2. Batch Updates: Collect these supply-altering events over time.

  3. Commit Periodically: On a regular trigger (CommitTickEvent), create a new cryptographic commitment (an MS-SMT root) representing the current state of the asset's supply. This involves separate sub-trees for mints, burns, and ignores, which are then committed into a single root supply tree.

  4. Anchor On-Chain: Construct, fund, sign, and broadcast a Bitcoin transaction that anchors this new supply root commitment into the blockchain. This transaction spends the previous commitment output (if one exists) and any relevant pre-commitment outputs (from minting transactions).

  5. Finalize State: Wait for the commitment transaction to confirm on-chain and then finalize the state update, making the new commitment the canonical one for the asset.

This ensures that there is a publicly verifiable, tamper-proof record reflecting the known supply changes for an asset within the Universe.

Scope

The state machine handles the lifecycle of a single supply commitment update cycle for a specific asset specifier. It manages:

  • Receiving and staging supply update events.

  • Calculating the new supply root based on staged updates and previous state.

  • Interacting with the Wallet interface to:

    • Derive keys for commitment outputs.
    • Fund the commitment transaction.
    • Sign the commitment transaction.
  • Interacting with the ChainBridge to broadcast the transaction and monitor for confirmation.

  • Persisting its state and pending updates via the StateMachineStore to ensure resilience across restarts.

It does not handle:

  • Discovering supply update events (this is done by other parts of the system feeding events into the state machine).

  • Serving supply proofs to external requesters (this is handled by the broader Universe server components).

  • Managing commitments for multiple different assets simultaneously (each asset group typically gets its own state machine instance).

State Machine Overview

The state machine transitions through several states to process supply updates and create a new on-chain commitment. It starts in an idle DefaultState. Supply updates can now be received in any state and are either bound to an active transition or stored as "dangling updates" to be bound to the next transition. When the state machine has pending updates and receives a CommitTickEvent, it triggers the commitment process, moving through states for tree creation (CommitTreeCreateState), transaction creation (CommitTxCreateState), signing (CommitTxSignState), broadcasting (CommitBroadcastState), and finally finalization (CommitFinalizeState) upon confirmation, before returning to the DefaultState.

States and Transitions
stateDiagram-v2
    direction LR
    
    [*] --> DefaultState: Initialize

    DefaultState --> UpdatesPendingState: SupplyUpdateEvent
    UpdatesPendingState --> CommitTreeCreateState: CommitTickEvent
    
    state CommitmentCycle {
        direction TB
        CommitTreeCreateState --> CommitTxCreateState: CreateTreeEvent
        CommitTxCreateState --> CommitTxSignState: CreateTxEvent
        CommitTxSignState --> CommitBroadcastState: SignTxEvent
        CommitBroadcastState --> CommitFinalizeState: ConfEvent
    }
    
    CommitFinalizeState --> DefaultState: FinalizeEvent<br/>(no dangling updates)
    CommitFinalizeState --> CommitTreeCreateState: FinalizeEvent<br/>(has dangling updates)

    %% Self-transitions
    DefaultState --> DefaultState: CommitTickEvent
    UpdatesPendingState --> UpdatesPendingState: SupplyUpdateEvent
    CommitTreeCreateState --> CommitTreeCreateState: CommitTickEvent
    CommitBroadcastState --> CommitBroadcastState: BroadcastEvent

Key State Transitions:

  1. Supply Update Handling:

    • DefaultState + SupplyUpdateEvent → UpdatesPendingState
    • UpdatesPendingState + SupplyUpdateEvent → Self (accumulates)
    • Any other state + SupplyUpdateEvent → Self (stores as dangling update)
  2. Commitment Cycle:

    • UpdatesPendingState + CommitTickEvent → CommitTreeCreateState
    • Internal events drive the cycle through creation, signing, and broadcasting
  3. Critical Optimization:

    • CommitFinalizeState checks for dangling updates:
      • If none → DefaultState (idle)
      • If present → CommitTreeCreateState (immediate new cycle)

This design ensures no supply updates are lost and allows continuous processing without returning to idle states when updates accumulate during commitment processing.

  • DefaultState: The idle state. Awaiting new supply updates or the next commitment cycle. Supply updates received here transition to UpdatesPendingState.

  • UpdatesPendingState: One or more supply updates have been received and are staged, waiting for the next commit trigger. Additional updates can be received and added to the pending set.

  • CommitTreeCreateState: Triggered by CommitTickEvent. Fetches existing sub-trees, applies pending updates (including any dangling updates), calculates the new sub-tree roots, and calculates the new root supply tree. Supply updates received during this state are stored as dangling updates.

  • CommitTxCreateState: Triggered by CreateTreeEvent. Fetches the previous commitment (if any) and unspent pre-commitments. Constructs the new commitment transaction (PSBT) spending these inputs and creating the new commitment output. Funds the PSBT using the wallet. Supply updates received during this state are stored as dangling updates.

  • CommitTxSignState: Triggered by CreateTxEvent. Signs the funded commitment PSBT using the wallet. Persists the signed transaction details and state before broadcasting. Supply updates received during this state are stored as dangling updates.

  • CommitBroadcastState: Triggered by SignTxEvent. Broadcasts the signed transaction and registers for its confirmation. Waits for the ConfEvent. Supply updates received during this state are stored as dangling updates.

  • CommitFinalizeState: Triggered by ConfEvent. The commitment transaction is confirmed. Finalizes the state transition by updating the canonical supply trees and commitment details in persistent storage. Transitions back to DefaultState. Supply updates received during this state are stored as dangling updates.

Dangling Updates

A key feature of the state machine is its ability to handle "dangling updates" - supply update events that are received when the state machine is already processing a commitment cycle (states other than DefaultState or UpdatesPendingState).

These updates are:

  • Stored separately without being immediately bound to the active transition
  • Preserved across state transitions
  • Automatically bound to the next transition when it's created
  • Ensure no supply updates are lost even if they arrive during active processing

This mechanism allows the state machine to continuously accept new supply updates without blocking or losing data, even while a commitment transaction is being created, signed, or broadcast.

Environment and Persistence

The state machine operates within an Environment that provides necessary dependencies like the Wallet, ChainBridge, CommitmentTracker, SupplyTreeView, and StateMachineStore. The StateMachineStore is crucial for persisting the current state and any pending updates or intermediate transaction data, allowing the machine to resume correctly after restarts.

Documentation

Index

Constants

View Source
const (
	// DefaultCommitConfTarget is the default confirmation target used when
	// crafting the commitment transaction. This is used in fee estimation.
	DefaultCommitConfTarget = 6
)
View Source
const (
	// DefaultTimeout is the context guard default timeout.
	DefaultTimeout = 30 * time.Second
)
View Source
const Subsystem = "SUCO"

Subsystem defines the logging code for this subsystem.

Variables

View Source
var (
	// ErrInvalidStateTransition is returned when we receive an unexpected
	// event for a given state.
	ErrInvalidStateTransition = fmt.Errorf("invalid state transition")

	// ErrEventTimeout is returned when waiting for a synchronous event
	// times out due to context cancellation.
	ErrEventTimeout = fmt.Errorf("event processing timeout")

	// ErrNilDoneChannel is returned when attempting to wait for a
	// synchronous event that doesn't have a done channel.
	ErrNilDoneChannel = fmt.Errorf("done channel is nil")
)

AllSupplySubTrees contains all possible valid SupplySubTree values.

View Source
var (
	// ErrNoBlockInfo is returned when a root commitment is expected to have
	// block information, but it is missing.
	ErrNoBlockInfo = fmt.Errorf("no block info available")
)
View Source
var (
	// ErrSupplyNotSupported is returned when an operation that requires
	// supply commitments is attempted on an asset that does not support
	// them.
	ErrSupplyNotSupported = errors.New("asset does not support supply " +
		"commitments")
)

Functions

func CalcTotalOutstandingSupply

func CalcTotalOutstandingSupply(ctx context.Context,
	supplySubtrees SupplyTrees) fn.Result[uint64]

CalcTotalOutstandingSupply calculates the total outstanding supply from the given supply subtrees.

func CheckSupplyCommitSupport

func CheckSupplyCommitSupport(ctx context.Context, assetLookup AssetLookup,
	assetSpec asset.Specifier, locallyControlled bool) error

CheckSupplyCommitSupport verifies that the asset group for the given asset specifier supports supply commitments, and that this node can generate supply commitments for it.

func DisableLog

func DisableLog()

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

func FetchLatestAssetMetadata

func FetchLatestAssetMetadata(ctx context.Context, lookup AssetLookup,
	assetSpec asset.Specifier) (proof.MetaReveal, error)

FetchLatestAssetMetadata returns the latest asset metadata for the given asset specifier.

func IsSupplySupported

func IsSupplySupported(ctx context.Context, assetLookup AssetLookup,
	assetSpec asset.Specifier, locallyControlled bool) (bool, error)

IsSupplySupported checks whether the asset group for the given asset specifier supports supply commitments. If locallyControlled is true, then we also check that this node can generate supply commitments for it.

NOTE: This is a convenience wrapper around CheckSupplyCommitSupport.

func NewAssetLogger

func NewAssetLogger(assetSpec string) btclog.Logger

NewAssetLogger creates a new prefixed logger for a specific asset. This logger will automatically include the asset specifier in all log messages, using the format "SupplyCommit(asset): message".

func RootCommitTxOut

func RootCommitTxOut(internalKey *btcec.PublicKey,
	tapOutKey *btcec.PublicKey, supplyRootHash mssmt.NodeHash) (*wire.TxOut,
	*btcec.PublicKey, error)

RootCommitTxOut returns the transaction output that corresponds to the root commitment. This is used to create a new commitment output.

func UpdateRootSupplyTree

func UpdateRootSupplyTree(ctx context.Context, rootTree mssmt.Tree,
	subTrees SupplyTrees) (mssmt.Tree, error)

UpdateRootSupplyTree takes the given root supply tree, and updates it with the set of subtrees. It returns a new tree instance with the updated values.

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.

Types

type AssetLookup

type AssetLookup interface {
	// FetchSupplyCommitAssets fetches all assets with non-nil group keys
	// that are supply commitments enabled.
	FetchSupplyCommitAssets(ctx context.Context,
		localControlled bool) ([]btcec.PublicKey, error)

	// QueryAssetGroupByID attempts to fetch an asset group by its asset ID.
	// If the asset group cannot be found, then ErrAssetGroupUnknown is
	// returned.
	QueryAssetGroupByID(ctx context.Context,
		assetID asset.ID) (*asset.AssetGroup, error)

	// QueryAssetGroupByGroupKey fetches the asset group with a matching
	// tweaked key, including the genesis information used to create the
	// group.
	QueryAssetGroupByGroupKey(ctx context.Context,
		groupKey *btcec.PublicKey) (*asset.AssetGroup, error)

	// FetchAssetMetaForAsset attempts to fetch an asset meta based on an
	// asset ID.
	FetchAssetMetaForAsset(ctx context.Context,
		assetID asset.ID) (*proof.MetaReveal, error)

	// FetchInternalKeyLocator attempts to fetch the key locator information
	// for the given raw internal key. If the key cannot be found, then
	// ErrInternalKeyNotFound is returned.
	FetchInternalKeyLocator(ctx context.Context,
		rawKey *btcec.PublicKey) (keychain.KeyLocator, error)
}

AssetLookup is an interface that allows us to query for asset information, such as asset groups and asset metadata.

type BroadcastEvent

type BroadcastEvent struct {
	// SignedCommitPkt is the signed commitment transaction that will be
	// broadcast to the network.
	SignedCommitPkt *psbt.Packet
}

BroadcastEvent is a special event that is used to trigger the broadcasting of the commitment transaction.

type ChainProof

type ChainProof struct {
	// Header is the block header of the block that contains the supply
	// commitment transaction.
	Header wire.BlockHeader

	// BlockHeight is the block height of the block that contains the supply
	// commitment transaction.
	BlockHeight uint32

	// MerkleProof is the merkle proof that proves that the supply
	// commitment transaction is included in the block.
	MerkleProof proof.TxMerkleProof

	// TxIndex is the index of the supply commitment transaction in the
	// block.
	TxIndex uint32
}

ChainProof stores the information needed to prove that a given supply commit tx has properly been mined in the Bitcoin blockchain.

type CommitBroadcastState

type CommitBroadcastState struct {
	// SupplyTransition holds all the information about the current state
	// transition, including old/new trees and commitments.
	SupplyTransition SupplyStateTransition
}

CommitBroadcastState is the state of the state machine we'll transitions to once we've signed the transaction. In this state, we'll broadcast the transaction, then wait for a confirmation event.

State transitions:

  • BroadcastEvent -> CommitBroadcastState
  • ConfEvent -> DefaultState

func (*CommitBroadcastState) IsTerminal

func (c *CommitBroadcastState) IsTerminal() bool

IsTerminal returns true if the target state is a terminal state.

func (*CommitBroadcastState) ProcessEvent

func (c *CommitBroadcastState) ProcessEvent(event Event,
	env *Environment) (*StateTransition, error)

ProcessEvent processes incoming events for the CommitTxSignState. From here, we'll sign the transaction, then transition to the next state for broadcast.

func (*CommitBroadcastState) String

func (c *CommitBroadcastState) String() string

String returns the name of the state.

type CommitFinalizeState

type CommitFinalizeState struct {
	// SupplyTransition holds all the information about the current state
	// transition, including old/new trees and commitments.
	SupplyTransition SupplyStateTransition
}

CommitFinalizeState is the final state of the state machine. In this state we'll update the state info on disk, swap in our in-memory tree with the new we've had in memory, then transition back to the DefaultState.

State transitions:

  • ConfEvent -> DefaultState

func (*CommitFinalizeState) IsTerminal

func (c *CommitFinalizeState) IsTerminal() bool

IsTerminal returns true if the target state is a terminal state.

func (*CommitFinalizeState) ProcessEvent

func (c *CommitFinalizeState) ProcessEvent(event Event,
	env *Environment) (*StateTransition, error)

ProcessEvent processes incoming events for the CommitFinalizeState. From here, we'll finalize the supply transition by updating the state machine state on disk, and updating the supply trees.

func (*CommitFinalizeState) String

func (c *CommitFinalizeState) String() string

String returns the name of the state.

type CommitTickEvent

type CommitTickEvent struct {
}

CommitTickEvent is a special event that is used to trigger an update of the on-chain commitment.

type CommitTreeCreateState

type CommitTreeCreateState struct {
}

CommitTreeCreateState is the state of the state machine when we have a series of new updates to commit to the tree. In this state, we'll create a new version of the supply tree in memory, to stage before going to the next state where we'll create the txn that will be used to commit the new tree in the chain.

State transitions:

  • CreateTreeEvent -> CommitTxCreateState

TODO(roasbeef): have all states cache pending updates once started with tick?

func (*CommitTreeCreateState) IsTerminal

func (c *CommitTreeCreateState) IsTerminal() bool

IsTerminal returns true if the target state is a terminal state.

func (*CommitTreeCreateState) ProcessEvent

func (c *CommitTreeCreateState) ProcessEvent(event Event,
	env *Environment) (*StateTransition, error)

ProcessEvent processes incoming events for the CommitTreeCreateState. From this state, we'll take the set of pending changes, then create/read the components of the sub-supply trees, then use that to create the new finalized tree.

func (*CommitTreeCreateState) String

func (c *CommitTreeCreateState) String() string

String returns the name of the state.

type CommitTxCreateState

type CommitTxCreateState struct {
	// SupplyTransition holds all the information about the current state
	// transition, including old/new trees and commitments.
	SupplyTransition SupplyStateTransition
}

CommitTxCreateState is the state of the state machine we'll transition to once we've created a new supply tree in memory. In this state, we'll create the actual transaction which spends the existing pre-commitment output(s) and the current commitment output.

State transitions:

  • CommitTxCreateState -> CommitTxSignState

func (*CommitTxCreateState) IsTerminal

func (c *CommitTxCreateState) IsTerminal() bool

IsTerminal returns true if the target state is a terminal state.

func (*CommitTxCreateState) ProcessEvent

func (c *CommitTxCreateState) ProcessEvent(event Event,
	env *Environment) (*StateTransition, error)

ProcessEvent processes incoming events for the CommitTxCreateState. From here, we have the new set of updated supply trees, and also the root supply tree. We'll now create a transaction that spends any unspent pre-commitments, and the latest commitment to create a new commitment that reflects the current supply state.

func (*CommitTxCreateState) String

func (c *CommitTxCreateState) String() string

String returns the name of the state.

type CommitTxSignState

type CommitTxSignState struct {
	// SupplyTransition holds all the information about the current state
	// transition, including old/new trees and commitments.
	SupplyTransition SupplyStateTransition
}

CommitTxSignState is the state of the state machine we'll transition to once we've created the tx that commits to the latest supply tree. In this state, we'll sign the transaction and all its inputs, then write our state to disk so we'll be able to recover it on restart.

State transitions:

  • SignTxEvent -> CommitBroadcastState

func (*CommitTxSignState) IsTerminal

func (s *CommitTxSignState) IsTerminal() bool

IsTerminal returns true if the target state is a terminal state.

func (*CommitTxSignState) ProcessEvent

func (s *CommitTxSignState) ProcessEvent(event Event,
	env *Environment) (*StateTransition, error)

ProcessEvent processes incoming events for the CommitTxSignState. From here, we'll sign the transaction, then transition to the next state for broadcast.

func (*CommitTxSignState) String

func (s *CommitTxSignState) String() string

String returns the name of the state.

type CommitmentBlock

type CommitmentBlock struct {
	// Height is the block height of the block that contains the
	// commitment.
	Height uint32

	// Hash is the hash of the block that contains the commitment.
	Hash chainhash.Hash

	// TxIndex is the index of the supply commitment transaction within
	// the block.
	TxIndex uint32

	// BlockHeader is the block header of the block that contains the
	// commitment.
	BlockHeader *wire.BlockHeader

	// MerkleProof is the merkle proof that proves that the supply
	// commitment transaction is included in the block.
	MerkleProof *proof.TxMerkleProof

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

CommitmentBlock captures the finalized on-chain state of a supply commitment transaction after it has been mined. It records block-level metadata and the actual fee paid to anchor the commitment.

type CommitmentTracker

type CommitmentTracker interface {
	// UnspentPrecommits returns the set of unspent pre-commitments for a
	// given asset spec. The asset spec will only specify a group key, and
	// not also an asset ID.
	UnspentPrecommits(ctx context.Context, assetSpec asset.Specifier,
		localIssuerOnly bool) lfn.Result[PreCommits]

	// SupplyCommit returns the root commitment for a given asset spec. From
	// the PoV of the chain, this is a singleton instance.
	SupplyCommit(ctx context.Context,
		assetSpec asset.Specifier) RootCommitResp
}

CommitmentTracker is used to track the state of the pre-commitment and commitment outputs that are currently confirmed on-chain for a given asset specifier.

type ConfEvent

type ConfEvent struct {
	// BlockHeight is the height of the block in which the transaction was
	// confirmed within.
	BlockHeight uint32

	// TxIndex is the index within the block of the ultimate confirmed
	// transaction.
	TxIndex uint32

	// Tx is the transaction for which the notification was requested for.
	Tx *wire.MsgTx

	// Block is the block that contains the transaction referenced above.
	Block *wire.MsgBlock
}

ConfEvent is a special event sent once our latest commitment transaction confirms on chain.

type ConfMapper

type ConfMapper = protofsm.ConfMapper[ConfEvent]

ConfMapper is a type used to map the generic confirmation event to one specific to this package.

type Config

Config is a configuration struct that is used to initialize a new supply commit state machine.

type CreateTreeEvent

type CreateTreeEvent struct {
	// contains filtered or unexported fields
}

CreateTreeEvent is a special event that is used to trigger the creation of the supply tree.

type CreateTxEvent

type CreateTxEvent struct {
}

CreateTxEvent is a special event that is used to trigger the creation of the commitment transaction.

type DaemonAdapters

type DaemonAdapters interface {
	protofsm.DaemonAdapters

	// Start starts the daemon adapters handler service.
	Start() error

	// Stop stops the daemon adapters handler service.
	Stop() error
}

DaemonAdapters is a wrapper around the protofsm.DaemonAdapters interface with the addition of Start and Stop methods.

type DefaultState

type DefaultState struct {
}

DefaultState is the idle state of the state machine. We start in this state when there are no pending changes that need to committed.

Once we receive a new supply commit event, we'll transition to the UpdatePendingState.

  • SupplyUpdateEvent -> UpdatePendingState

State transitions:

TODO(roasbeef): transition if have items in log that are pending?

func (*DefaultState) IsTerminal

func (d *DefaultState) IsTerminal() bool

IsTerminal returns true if the target state is a terminal state.

func (*DefaultState) ProcessEvent

func (d *DefaultState) ProcessEvent(event Event,
	env *Environment) (*StateTransition, error)

ProcessEvent is used to transition from the default state to the UpdatePendingState once we receive a new request to update the current supply trees.

func (*DefaultState) String

func (d *DefaultState) String() string

String returns the name of the state.

type Environment

type Environment struct {
	// AssetSpec is the asset specifier that is used to identify the asset
	// that we're maintaining a supply commit for.
	AssetSpec asset.Specifier

	// TreeView is the interface that allows the state machine to obtain an
	// up to date snapshot of the root supply tree, and the relevant set of
	// subtrees.
	TreeView SupplyTreeView

	// Commitments is used to track the state of the pre-commitment and
	// commitment outputs that are currently confirmed on-chain.
	Commitments CommitmentTracker

	// Wallet is the main wallet interface used to managed PSBT packets.
	Wallet Wallet

	// AssetLookup is used to look up asset information such as asset groups
	// and asset metadata.
	AssetLookup AssetLookup

	// KeyRing is the main key ring interface used to manage keys.
	KeyRing KeyRing

	// Chain is our access to the current main chain.
	//
	// TODO(roasbeef): can make a slimmer version of
	Chain tapgarden.ChainBridge

	// SupplySyncer is used to insert supply commitments into the remote
	// universe server.
	SupplySyncer SupplySyncer

	// StateLog is the main state log that is used to track the state of the
	// state machine. This is used to persist the state of the state machine
	// across restarts.
	StateLog StateMachineStore

	// CommitConfTarget is the confirmation target used when crafting the
	// commitment transaction.
	CommitConfTarget uint32

	// ChainParams is the chain parameters for the chain that we're
	// operating on.
	ChainParams chaincfg.Params

	// IgnoreCheckerCache is used to invalidate the ignore cache when a new
	// supply commitment is created.
	IgnoreCheckerCache IgnoreCheckerCache

	// Log is the prefixed logger for this supply commitment state machine.
	Log btclog.Logger
}

Environment is a set of dependencies that a state machine may need to carry out the logic for a given state transition. All fields are to be considered immutable, and will be fixed for the lifetime of the state machine.

func (*Environment) Logger

func (e *Environment) Logger() btclog.Logger

Logger returns the logger for this environment. If a logger was provided in the environment configuration, it returns that logger. Otherwise, it returns the package-level logger with an asset-specific prefix.

func (*Environment) Name

func (e *Environment) Name() string

Name returns the name of the environment. This is used to uniquely identify the environment of related state machines. For this state machine, the name is based on the channel ID.

type ErrorReporter

type ErrorReporter struct {
	// contains filtered or unexported fields
}

ErrorReporter is an asset specific error reporter that can be used to report errors that occur during the operation of the asset group supply commitment state machine.

func NewErrorReporter

func NewErrorReporter(assetSpec asset.Specifier) ErrorReporter

NewErrorReporter creates a new ErrorReporter for the given asset specifier state machine.

func (*ErrorReporter) ReportError

func (r *ErrorReporter) ReportError(err error)

ReportError reports an error that occurred during the operation of the asset group supply commitment state machine.

type Event

type Event interface {
	// contains filtered or unexported methods
}

Event is a special interface used to create the equivalent of a sum-type, but using a "sealed" interface. Supply commit events can be used as input to trigger a state transition, and also as output to trigger a new set of events into the very same state machine.

func SpendMapperFunc

func SpendMapperFunc(spendEvent *chainntnfs.SpendDetail) Event

type Events

type Events interface {
}

Events is a special type constraint that enumerates all the possible protocol events. This is used mainly as type-level documentation, and may also be useful to constraint certain state transition functions.

type FetchCommitmentResp

type FetchCommitmentResp struct {
	// SupplyTree is the supply tree for an asset. The leaves of this tree
	// commit to the roots of the supply commit subtrees.
	SupplyTree mssmt.Tree

	// Subtrees maps a subtree type to its corresponding supply subtree.
	Subtrees SupplyTrees

	// ChainCommitment links the supply tree to its anchor transaction.
	ChainCommitment RootCommitment
}

FetchCommitmentResp is the response type for the FetchCommitment method.

type FetchSupplyCommitResult

type FetchSupplyCommitResult struct {
	// RootCommitment contains the commitment transaction and output data.
	RootCommitment RootCommitment

	// SupplyLeaves contains the issuance, burn, and ignore leaves.
	SupplyLeaves SupplyLeaves

	// ChainProof contains the block header and merkle proof.
	ChainProof ChainProof

	// TxChainFeesSats is the total number of satoshis in on-chain fees
	// paid by the supply commitment transaction.
	TxChainFeesSats int64

	// IssuanceSubtreeRoot is the root of the issuance tree for the asset.
	IssuanceSubtreeRoot SubtreeRootProof

	// BurnSubtreeRoot is the root of the burn tree for the asset.
	BurnSubtreeRoot SubtreeRootProof

	// IgnoreSubtreeRoot is the root of the ignore tree for the asset.
	IgnoreSubtreeRoot SubtreeRootProof

	// SpentCommitmentOutpoint is the outpoint of the previous commitment
	// that this new commitment is spending. This is None for the very
	// first supply commitment of a grouped asset.
	SpentCommitmentOutpoint fn.Option[wire.OutPoint]
}

FetchSupplyCommitResult represents the complete data returned from a FetchSupplyCommit RPC call, containing all fields from the RPC response.

type FinalizeEvent

type FinalizeEvent struct {
}

FinalizeEvent is a special event that is used to trigger the finalization of the state update.

type FsmEvent

type FsmEvent = protofsm.EmittedEvent[Event]

FsmEvent is a type alias for the event type of the supply commit state machine.

type FsmState

type FsmState = protofsm.State[Event, *Environment]

FsmState is a type alias for the state of the supply commit state machine.

type IgnoreCheckerCache

type IgnoreCheckerCache interface {
	// InvalidateCache is used to invalidate the ignore checker cache when
	// a new supply commitment is created.
	InvalidateCache(btcec.PublicKey)
}

IgnoreCheckerCache is an interface that allows the state machine to invalidate the ignore checker cache when a new supply commitment is created.

type KeyRing

type KeyRing interface {
	// DeriveNextTaprootAssetKey attempts to derive the *next* key within
	// the Taproot Asset key family.
	DeriveNextTaprootAssetKey(ctx context.Context) (keychain.KeyDescriptor,
		error)
}

KeyRing is an interface that allows the state machine to derive new keys within the keychain.

type Manager

type Manager struct {

	// ContextGuard provides a wait group and main quit channel that can be
	// used to create guarded contexts.
	*fn.ContextGuard
	// contains filtered or unexported fields
}

Manager is a manager for multiple supply commitment state machines, one for each asset group. It is responsible for starting and stopping the state machines, as well as forwarding sending events to them.

func NewManager

func NewManager(cfg ManagerCfg) *Manager

NewManager creates a new multi state machine manager.

func (*Manager) CanHandle

func (m *Manager) CanHandle(assetSpec asset.Specifier,
	msg msgmux.PeerMsg) (bool, error)

CanHandle determines if the state machine associated with the given asset specifier can handle the given message. If a state machine for the asset group does not exist, it will be created and started.

func (*Manager) CurrentState

func (m *Manager) CurrentState(assetSpec asset.Specifier) (
	protofsm.State[Event, *Environment], error)

CurrentState returns the current state of the state machine associated with the given asset specifier. If a state machine for the asset group does not exist, it will be created and started.

func (*Manager) FetchSubTrees

func (m *Manager) FetchSubTrees(ctx context.Context,
	assetSpec asset.Specifier,
	blockHeightEnd fn.Option[uint32]) (SupplyTrees, error)

FetchSubTrees returns all the sub trees for the given asset specifier.

func (*Manager) FetchSupplyLeavesByHeight

func (m *Manager) FetchSupplyLeavesByHeight(
	ctx context.Context, assetSpec asset.Specifier, startHeight,
	endHeight uint32) (SupplyLeaves, error)

FetchSupplyLeavesByHeight returns the set of supply leaves for the given asset specifier within the specified height range.

func (*Manager) Name

func (m *Manager) Name(
	assetSpec asset.Specifier) (string, error)

Name returns the name of the state machine associated with the given asset specifier. If a state machine for the asset group does not exist, it will be created and started.

func (*Manager) RegisterStateEvents

func (m *Manager) RegisterStateEvents(
	assetSpec asset.Specifier) (StateSub, error)

RegisterStateEvents registers a state event subscriber with the state machine associated with the given asset specifier. If a state machine for the asset group does not exist, it will be created and started.

func (*Manager) RemoveStateSub

func (m *Manager) RemoveStateSub(assetSpec asset.Specifier,
	sub StateSub) error

RemoveStateSub removes a state event subscriber from the state machine associated with the given asset specifier. If a state machine for the asset group does not exist, it will be created and started.

func (*Manager) SendBurnEvent

func (m *Manager) SendBurnEvent(ctx context.Context, assetSpec asset.Specifier,
	burnLeaf universe.BurnLeaf) error

SendBurnEvent sends a burn event to the supply commitment state machine.

NOTE: This implements the tapfreighter.BurnSupplyCommitter interface.

func (*Manager) SendEvent

func (m *Manager) SendEvent(ctx context.Context,
	assetSpec asset.Specifier, event Event) error

SendEvent sends an event to the state machine associated with the given asset specifier. If a state machine for the asset group does not exist, it will be created and started.

func (*Manager) SendEventSync

func (m *Manager) SendEventSync(ctx context.Context, assetSpec asset.Specifier,
	event SyncSupplyUpdateEvent) error

SendEventSync sends an event to the state machine and waits for it to be processed and written to disk. This method provides synchronous confirmation that the event has been durably persisted. If the event doesn't support synchronous processing (i.e., it's not a SupplyUpdateEvent), this method will return an error.

func (*Manager) SendMessage

func (m *Manager) SendMessage(ctx context.Context,
	assetSpec asset.Specifier, msg msgmux.PeerMsg) (bool, error)

SendMessage sends a message to the state machine associated with the given asset specifier. If a state machine for the asset group does not exist, it will be created and started.

func (*Manager) SendMintEvent

func (m *Manager) SendMintEvent(ctx context.Context, assetSpec asset.Specifier,
	leafKey universe.UniqueLeafKey, issuanceProof universe.Leaf,
	mintBlockHeight uint32) error

SendMintEvent sends a mint event to the supply commitment state machine.

NOTE: This implements the tapgarden.MintSupplyCommitter interface.

func (*Manager) Start

func (m *Manager) Start() error

Start starts the multi state machine manager.

func (*Manager) StartSupplyPublishFlow

func (m *Manager) StartSupplyPublishFlow(ctx context.Context,
	assetSpec asset.Specifier) error

StartSupplyPublishFlow triggers the state machine to build and publish a new supply commitment if pending supply tree updates exist.

func (*Manager) Stop

func (m *Manager) Stop() error

Stop stops the multi state machine manager, which in turn stops all asset group key specific supply commitment state machines.

type ManagerCfg

type ManagerCfg struct {
	// TreeView is the interface that allows the state machine to obtain an
	// up to date snapshot of the root supply tree, and the relevant set of
	// subtrees.
	TreeView SupplyTreeView

	// Commitments is used to track the state of the pre-commitment and
	// commitment outputs that are currently confirmed on-chain.
	Commitments CommitmentTracker

	// Wallet is the interface used interact with the wallet.
	Wallet Wallet

	// AssetLookup is used to look up asset information such as asset groups
	// and asset metadata.
	AssetLookup AssetLookup

	// KeyRing is the key ring used to derive new keys.
	KeyRing KeyRing

	// Chain is our access to the current main chain.
	//
	// TODO(roasbeef): can make a slimmer version of
	Chain tapgarden.ChainBridge

	// SupplySyncer is used to insert supply commitments into the remote
	// universe server.
	SupplySyncer SupplySyncer

	// DaemonAdapters is a set of adapters that allow the state machine to
	// interact with external daemons whilst processing internal events.
	DaemonAdapters DaemonAdapters

	// StateLog is the main state log that is used to track the state of the
	// state machine. This is used to persist the state of the state machine
	// across restarts.
	StateLog StateMachineStore

	// ChainParams is the chain parameters for the chain that we're
	// operating on.
	ChainParams chaincfg.Params

	// IgnoreCheckerCache is used to invalidate the ignore cache when a new
	// supply commitment is created.
	IgnoreCheckerCache IgnoreCheckerCache
}

ManagerCfg is the configuration for the Manager. It contains all the dependencies needed to manage multiple supply commitment state machines, one for each asset group.

type NewBurnEvent

type NewBurnEvent struct {
	universe.BurnLeaf

	// Done is an optional channel that will receive an error (or nil for
	// success) when the event has been processed and written to disk.
	// If nil, the event is processed asynchronously.
	Done chan error
}

NewBurnEvent signals that a caller wishes to update the burn portion of the supply tree with a new burnt asset.

func (*NewBurnEvent) BlockHeight

func (n *NewBurnEvent) BlockHeight() uint32

BlockHeight returns the block height of the update.

func (*NewBurnEvent) Encode

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

Encode encodes the burn leaf into the passed io.Writer.

func (*NewBurnEvent) ScriptKey

func (n *NewBurnEvent) ScriptKey() asset.SerializedKey

ScriptKey returns the script key that is used to identify the target asset.

func (*NewBurnEvent) SignalDone

func (n *NewBurnEvent) SignalDone(err error)

SignalDone signals completion on the done channel if it exists. It sends the error (or nil for success) and does not block.

func (*NewBurnEvent) SupplySubTreeType

func (n *NewBurnEvent) SupplySubTreeType() SupplySubTree

SupplySubTreeType returns the type of sub-tree this update affects.

func (*NewBurnEvent) UniverseLeafKey

func (n *NewBurnEvent) UniverseLeafKey() universe.UniqueLeafKey

UniverseLeafKey returns the specific leaf key to use when inserting this update into a universe MS-SMT tree.

func (*NewBurnEvent) UniverseLeafNode

func (n *NewBurnEvent) UniverseLeafNode() (*mssmt.LeafNode, error)

UniverseLeafNode returns the leaf node to use when inserting this update into a universe MS-SMT tree.

func (*NewBurnEvent) WaitForDone

func (n *NewBurnEvent) WaitForDone(ctx context.Context) error

WaitForDone waits for the event to be processed by waiting on its done channel. This is a helper method that can be used by callers who want synchronous confirmation that their event has been persisted.

type NewIgnoreEvent

type NewIgnoreEvent struct {
	universe.SignedIgnoreTuple

	// Done is an optional channel that will receive an error (or nil for
	// success) when the event has been processed and written to disk. If
	// nil, the event is processed asynchronously.
	Done chan error
}

NewIgnoreEvent signals that a caller wishes to update the ignore portion of the supply tree with a new outpoint + script key combo.

func (*NewIgnoreEvent) BlockHeight

func (n *NewIgnoreEvent) BlockHeight() uint32

BlockHeight returns the block height of the update.

func (*NewIgnoreEvent) Encode

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

Encode encodes the ignore tuple into the passed io.Writer.

func (*NewIgnoreEvent) ScriptKey

func (n *NewIgnoreEvent) ScriptKey() asset.SerializedKey

ScriptKey returns the script key that is used to identify the target asset.

func (*NewIgnoreEvent) SignalDone

func (n *NewIgnoreEvent) SignalDone(err error)

SignalDone signals completion on the done channel if it exists. It sends the error (or nil for success) and does not block.

func (*NewIgnoreEvent) SupplySubTreeType

func (n *NewIgnoreEvent) SupplySubTreeType() SupplySubTree

SupplySubTreeType returns the type of sub-tree this update affects.

func (*NewIgnoreEvent) UniverseLeafKey

func (n *NewIgnoreEvent) UniverseLeafKey() universe.UniqueLeafKey

UniverseLeafKey returns the specific leaf key to use when inserting this update into a universe MS-SMT tree.

func (*NewIgnoreEvent) UniverseLeafNode

func (n *NewIgnoreEvent) UniverseLeafNode() (*mssmt.LeafNode, error)

UniverseLeafNode returns the leaf node to use when inserting this update into a universe MS-SMT tree.

func (*NewIgnoreEvent) WaitForDone

func (n *NewIgnoreEvent) WaitForDone(ctx context.Context) error

WaitForDone waits for the event to be processed by waiting on its done channel. This is a helper method that can be used by callers who want synchronous confirmation that their event has been persisted.

type NewMintEvent

type NewMintEvent struct {
	// LeafKey is the universe leaf key for the asset issuance or spend.
	LeafKey universe.UniqueLeafKey

	// IssuanceProof is the universe leaf for the issuance.
	IssuanceProof universe.Leaf

	// MintHeight is the height of the block that contains the mint.
	MintHeight uint32

	// Done is an optional channel that will receive an error (or nil for
	// success) when the event has been processed and written to disk.
	// If nil, the event is processed asynchronously.
	Done chan error
}

NewMintEvent signals that a caller wishes to update the mint portion of the supply tree with a new minted asset.

func (*NewMintEvent) BlockHeight

func (n *NewMintEvent) BlockHeight() uint32

BlockHeight returns the block height of the update.

func (*NewMintEvent) Decode

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

Decode decodes the mint event from the passed io.Reader.

func (*NewMintEvent) Encode

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

Encode encodes the mint event into the passed io.Writer.

func (*NewMintEvent) ScriptKey

func (n *NewMintEvent) ScriptKey() asset.SerializedKey

ScriptKey returns the script key that is used to identify the target asset.

func (*NewMintEvent) SignalDone

func (n *NewMintEvent) SignalDone(err error)

SignalDone signals completion on the done channel if it exists. It sends the error (or nil for success) and does not block.

func (*NewMintEvent) SupplySubTreeType

func (n *NewMintEvent) SupplySubTreeType() SupplySubTree

SupplySubTreeType returns the type of sub-tree this update affects.

func (*NewMintEvent) UniverseLeafKey

func (n *NewMintEvent) UniverseLeafKey() universe.UniqueLeafKey

UniverseLeafKey returns the specific leaf key to use when inserting this update into a universe MS-SMT tree.

func (*NewMintEvent) UniverseLeafNode

func (n *NewMintEvent) UniverseLeafNode() (*mssmt.LeafNode, error)

UniverseLeafNode returns the leaf node to use when inserting this update into a universe MS-SMT tree.

func (*NewMintEvent) WaitForDone

func (n *NewMintEvent) WaitForDone(ctx context.Context) error

WaitForDone waits for the event to be processed by waiting on its done channel. This is a helper method that can be used by callers who want synchronous confirmation that their event has been persisted.

type PreCommitment

type PreCommitment struct {
	// BlockHeight is the block height of the transaction that contains the
	// pre-commitment.
	BlockHeight uint32

	// MintingTxn is the minting transaction itself that created the pre
	// commitment.
	MintingTxn *wire.MsgTx

	// OutIdx specifies the index of the pre-commitment output within the
	// batch mint anchor transaction.
	OutIdx uint32

	// InternalKey is the Taproot internal public key associated with the
	// pre-commitment output.
	InternalKey keychain.KeyDescriptor

	// GroupPubKey is the asset group public key associated with this
	// pre-commitment output.
	GroupPubKey btcec.PublicKey
}

PreCommitment is a struct that represents a pre-commitment to an asset commitment. A pre-commitment is an extra transaction that exists in the same on-chain transaction as a new issuance event.

func (*PreCommitment) OutPoint

func (p *PreCommitment) OutPoint() wire.OutPoint

OutPoint returns the outpoint that corresponds to the pre-commitment output. This is the output that is spent by the supply commitment anchoring transaction.

func (*PreCommitment) TxIn

func (p *PreCommitment) TxIn() *wire.TxIn

TxIn returns the transaction input that corresponds to the pre-commitment.

type PreCommits

type PreCommits = []PreCommitment

PreCommits is a slice of pre-commitments.

type RootCommitResp

type RootCommitResp = lfn.Result[lfn.Option[RootCommitment]]

RootCommitResp is the response type for the root commitment. It captures the fact that there may not be a root commitment yet for a given asset.

type RootCommitment

type RootCommitment struct {
	// Txn is the transaction that created the root commitment.
	Txn *wire.MsgTx

	// TxOutIdx is the index of the output in the transaction where the
	// commitment resides.
	TxOutIdx uint32

	// InternalKey is the internal key used to create the commitment output.
	InternalKey keychain.KeyDescriptor

	// Output key is the taproot output key used to create the commitment
	// output.
	OutputKey *btcec.PublicKey

	// SupplyRoot is the root of the supply tree that contains the set of
	// sub-commitments. The sum value of this tree is the outstanding supply
	// value.
	SupplyRoot *mssmt.BranchNode

	// CommitmentBlock is the block that contains the commitment to the
	// asset supply. This may be None if the commitment has not yet
	// been mined.
	CommitmentBlock fn.Option[CommitmentBlock]

	// SpentCommitment is the outpoint of the previous root commitment that
	// this root commitment is spending. This will be None if this is the
	// first root commitment for the asset.
	SpentCommitment fn.Option[wire.OutPoint]
}

RootCommitment is the root commitment that contains the commitment to the the sub-supply trees for a given asset.

func (*RootCommitment) CommitPoint

func (r *RootCommitment) CommitPoint() wire.OutPoint

CommitPoint returns the outpoint that corresponds to the root commitment.

func (*RootCommitment) TapscriptRoot

func (r *RootCommitment) TapscriptRoot() ([]byte, error)

TapscriptRoot returns the tapscript root hash that commits to the supply root. This is tweaked with the internal key to derive the output key.

func (*RootCommitment) TxIn

func (r *RootCommitment) TxIn() *wire.TxIn

TxIn returns the transaction input that corresponds to the root commitment. This is used to spend the old commitment output, and create a new one.

func (*RootCommitment) TxOut

func (r *RootCommitment) TxOut() (*wire.TxOut, error)

TxOut returns the transaction output that corresponds to the root commitment. This is used to create a new commitment output.

TODO(roasbeef): expand, add support for tapscript as well

func (*RootCommitment) VerifyChainAnchor

func (r *RootCommitment) VerifyChainAnchor(merkleVerifier proof.MerkleVerifier,
	headerVerifier proof.HeaderVerifier) error

VerifyChainAnchor checks that the on-chain information is correct.

type SignTxEvent

type SignTxEvent struct {
	// CommitPkt is the unsigned transaction that will be used to commit to
	// the new supply tree.
	CommitPkt *tapsend.FundedPsbt

	// NewSupplyCommit is the new supply commitment that that will be
	// created by the above commit pkt.
	NewSupplyCommit RootCommitment
}

SignTxEvent is a special event that is used to trigger the signing of the commitment transaction.

type SpendEvent

type SpendEvent struct {
	// Tx is the spending transaction that has been confirmed.
	Tx *wire.MsgTx

	// BlockHeight is the height of the block that confirmed the
	// transaction.
	BlockHeight uint32
}

SpendEvent is sent in response to an intent be notified of a spend of an outpoint.

type SpendMapper

type SpendMapper = protofsm.SpendMapper[Event]

SpendMapper is a type used to map the generic spend event to one specific to this package.

type State

type State interface {

	// IsTerminal returns true if the target state is a terminal state.
	IsTerminal() bool

	// ProcessEvent takes a supply event event, and implements a state
	// transition for the state.
	//
	// nolint:lll
	ProcessEvent(Event, *Environment) (*StateTransition, error)

	// String returns the name of the state.
	String() string
	// contains filtered or unexported methods
}

State is our sum-type ish interface that represents the current universe commitment state.

type StateMachine

type StateMachine = protofsm.StateMachine[Event, *Environment]

StateMachine is a state machine that handles creating and updating the on-chain universe supply commitment for a given asset.

type StateMachineStore

type StateMachineStore interface {
	// InsertPendingUpdate attempts to insert a new pending update into the
	// update log of the target supply commit state machine. If the state
	// machine doesn't yet exist, then it will be created at the
	// UpdatesPendingState. If the state machine exists, but is in a
	// different state then UpdatesPendingState, then an error will be
	// returned.
	//
	// This method will also create a new pending SupplyStateTransition.
	InsertPendingUpdate(context.Context, asset.Specifier,
		SupplyUpdateEvent) error

	// InsertSignedCommitTx will associated a new signed commitment
	// anchor transaction with the current active supply commitment state
	// transition. This'll update the existing funded txn with a signed
	// copy. Finally the state of the  supply commit state transition will
	// transition to CommitBroadcastState.
	InsertSignedCommitTx(context.Context, asset.Specifier,
		SupplyCommitTxn) error

	// CommitState is used to commit the state of the state machine to then
	// disk.
	CommitState(context.Context, asset.Specifier, State) error

	// FetchState attempts to fetch the state of the state machine for the
	// target asset specifier. If the state machine doesn't exist, then an
	// error will be returned.
	//
	// TODO(roasbeef): also have it return the next event if exists?
	FetchState(context.Context, asset.Specifier) (State,
		lfn.Option[SupplyStateTransition], error)

	// ApplyStateTransition is used to apply a new state transition to the
	// target state machine. Once the transition has been applied, the state
	// machine will transition back to the default state.
	//
	// To apply a state transition, the following operations must be carried
	// out:
	//   * Insert the set of PendingUpdates into their respective sub supply
	//   trees.
	//   * Insert the new supply try leaves into the universe supply root.
	//   * Update the current supply commitment with the target chain
	//     transaction (output index, etc).
	//   * Update the block height and merkle proof information.
	//   * Update the internal key and output key of the commitment
	//     transaction.
	//   * Update the target state machine to the Default state.
	//   * Mark the target state transition as finalized.
	ApplyStateTransition(context.Context, asset.Specifier,
		SupplyStateTransition) error

	// FreezePendingTransition marks the current pending transition for a
	// group key as frozen.
	FreezePendingTransition(context.Context, asset.Specifier) error

	// BindDanglingUpdatesToTransition finds any supply update events for
	// the given asset specifier that are not yet associated with a
	// transition, creates a new transition for them, and links them. It
	// returns the list of events that were bound. If no dangling events are
	// found, it returns an empty slice and no error.
	BindDanglingUpdatesToTransition(context.Context,
		asset.Specifier) ([]SupplyUpdateEvent, error)
}

StateMachineStore is an interface that allows the state machine to persist its state across restarts. This is used to track the state of the state machine, and the set of pending updates that are being applied to the commitment.

type StateSub

StateSub is a type alias for the state subscriber of the supply commit state machine.

type StateTransition

type StateTransition = protofsm.StateTransition[Event, *Environment]

StateTransition is the StateTransition type specific to the supply commit state machine.

type SubtreeRootProof

type SubtreeRootProof struct {
	// Type indicates the type of the supply commit subtree.
	Type SupplySubTree

	// RootNode is the root node of the supply commit subtree.
	RootNode mssmt.BranchNode

	// SupplyTreeLeafKey locates the subtree leaf node in the supply commit
	// tree.
	SupplyTreeLeafKey universe.UniverseKey

	// SupplyTreeInclusionProof proves inclusion of the subtree root in the
	// supply tree.
	SupplyTreeInclusionProof mssmt.Proof
}

SubtreeRootProof represents the root of a supply commit subtree with its main supply tree inclusion proof.

type SupplyCommitTxn

type SupplyCommitTxn struct {
	// Txn is the transaction that creates the supply commitment.
	Txn *wire.MsgTx

	// InternalKey is the internal key descriptor used for the commitment
	// output. This preserves the full key derivation information.
	InternalKey keychain.KeyDescriptor

	// OutputKey is the taproot output key used for the commitment output.
	OutputKey *btcec.PublicKey

	// OutputIndex is the index of the commitment output within the Txn.
	OutputIndex uint32
}

SupplyCommitTxn encapsulates the details of the transaction that creates a new supply commitment on chain.

type SupplyLeaves

type SupplyLeaves struct {
	// IssuanceLeafEntries is a slice of issuance leaves.
	IssuanceLeafEntries []NewMintEvent

	// BurnLeafEntries is a slice of burn leaves.
	BurnLeafEntries []NewBurnEvent

	// IgnoreLeafEntries is a slice of ignore leaves.
	IgnoreLeafEntries []NewIgnoreEvent
}

SupplyLeaves is the response type for fetching the supply leaves for a given asset specifier.

func NewSupplyLeavesFromEvents

func NewSupplyLeavesFromEvents(events []SupplyUpdateEvent) (SupplyLeaves,
	error)

NewSupplyLeavesFromEvents creates a SupplyLeaves instance from a slice of SupplyUpdateEvent instances.

func (SupplyLeaves) AllUpdates

func (s SupplyLeaves) AllUpdates() []SupplyUpdateEvent

AllUpdates returns a slice of all supply update events contained within the SupplyLeaves instance. This includes mints, burns, and ignores.

func (SupplyLeaves) ValidateBlockHeights

func (s SupplyLeaves) ValidateBlockHeights() error

ValidateBlockHeights ensures that all supply leaves have a non-zero block height.

type SupplyStateTransition

type SupplyStateTransition struct {
	// OldCommitment is the old commitment that is being spent. This is used
	// to create the new commitment output (by spending this input).
	OldCommitment lfn.Option[RootCommitment]

	// UnspentPreCommits is the set of unspent pre-commitments that are
	// unspent. These will also be used as input into the new commit txn.
	UnspentPreCommits []PreCommitment

	// PendingUpdates is the set of new updates that are being added to the
	// commitment. These are the new mints, burns, or ignores.
	PendingUpdates []SupplyUpdateEvent

	// NewCommitment is the new commitment that is being created.
	//
	// TODO(roasbeef): opt? may not exist before pending updates added
	NewCommitment RootCommitment

	// ChainProof is the chain proof that proves that the new commitment has
	// been mined in the Bitcoin blockchain. If None, then the commitment
	// has not yet been mined.
	ChainProof lfn.Option[ChainProof]
}

SupplyStateTransition represents a new pending supply commitment.

type SupplySubTree

type SupplySubTree uint8

SupplySubTree is an enum that represents the different types of supply sub trees within the main supply tree. The sub trees are used to track how the supply shifts in response to: mints, burns, and ignores.

const (

	// MintTreeType is the sub tree that tracks mints.
	MintTreeType SupplySubTree = iota

	// BurnTreeType is the sub tree that tracks burns.
	BurnTreeType

	// IgnoreTreeType is the sub tree that tracks ignores.
	IgnoreTreeType
)

func NewSubtreeTypeFromStr

func NewSubtreeTypeFromStr(s string) (SupplySubTree, error)

NewSubtreeTypeFromStr returns the SupplySubTree type from a string.

func (SupplySubTree) String

func (s SupplySubTree) String() string

String returns the string representation of the supply sub tree.

func (SupplySubTree) ToUniverseProofType

func (s SupplySubTree) ToUniverseProofType() (universe.ProofType, error)

ToUniverseProofType converts the supply subtree type to the corresponding universe proof type.

func (SupplySubTree) UniverseKey

func (s SupplySubTree) UniverseKey() [32]byte

UniverseKey is the key used to identify the universe in the supply tree. This is scoped to a root supply tree for a given asset specifier.

type SupplySyncer

type SupplySyncer interface {
	// PushSupplyCommitment pushes a supply commitment to the remote
	// universe server. This function should block until the sync insertion
	// is complete.
	//
	// Returns a map of per-server errors keyed by server host string and
	// an internal error. If all pushes succeed, both return values are nil.
	// If some pushes fail, the map contains only the failed servers and
	// their corresponding errors. If there's an internal/system error that
	// prevents the operation from proceeding, it's returned as the second
	// value.
	PushSupplyCommitment(ctx context.Context, assetSpec asset.Specifier,
		commitment RootCommitment, updateLeaves SupplyLeaves,
		chainProof ChainProof,
		canonicalUniverses []url.URL) (map[string]error, error)
}

SupplySyncer is an interface that allows the state machine to insert supply commitments into the remote universe server.

type SupplyTreeView

type SupplyTreeView interface {
	// FetchSubTree returns the sub tree for the given asset spec. This
	// instance returned should be a copy, as mutations make take place in
	// the tree.
	FetchSubTree(ctx context.Context, assetSpec asset.Specifier,
		treeType SupplySubTree) lfn.Result[mssmt.Tree]

	// FetchSubTrees returns all the subtrees for the given asset spec.
	FetchSubTrees(ctx context.Context,
		assetSpec asset.Specifier,
		blockHeightEnd fn.Option[uint32]) lfn.Result[SupplyTrees]

	// FetchRootSupplyTree returns the root supply tree which contains a
	// commitment to each of the sub trees.
	FetchRootSupplyTree(ctx context.Context,
		assetSpec asset.Specifier) lfn.Result[mssmt.Tree]

	// FetchSupplyLeavesByHeight returns the set of supply leaves for the
	// given asset specifier within the specified height range.
	FetchSupplyLeavesByHeight(ctx context.Context,
		assetSpec asset.Specifier, startHeight,
		endHeight uint32) lfn.Result[SupplyLeaves]
}

SupplyTreeView is an interface that allows the state machine to obtain an up to date snapshot of the root supply tree, as the sub trees (ignore, burn, mint) committed in the main supply tree.

type SupplyTrees

type SupplyTrees map[SupplySubTree]mssmt.Tree

SupplyTrees is a map of the different supply sub trees. The keys are the sub trees, and the values are the actual trees.

func ApplyTreeUpdates

func ApplyTreeUpdates(supplyTrees SupplyTrees,
	pendingUpdates []SupplyUpdateEvent) (SupplyTrees, error)

ApplyTreeUpdates takes the set of pending updates, and applies them to the given supply trees. It returns a new map containing the updated trees.

func (SupplyTrees) FetchOrCreate

func (s SupplyTrees) FetchOrCreate(treeType SupplySubTree) mssmt.Tree

FetchOrCreate fetches the sub tree for the given asset spec. If the sub tree doesn't exist, it will be created and returned.

type SupplyUpdateEvent

type SupplyUpdateEvent interface {
	Event

	// ScriptKey returns the script key that is used to identify the target
	// asset.
	ScriptKey() asset.SerializedKey

	// SupplySubTreeType returns the type of sub-tree this update affects.
	SupplySubTreeType() SupplySubTree

	// UniverseLeafKey returns the specific leaf key to use when inserting
	// this update into a universe supply MS-SMT tree.
	UniverseLeafKey() universe.UniqueLeafKey

	// UniverseLeafNode returns the leaf node to use when inserting this
	// update into a universe supply MS-SMT tree.
	UniverseLeafNode() (*mssmt.LeafNode, error)

	// BlockHeight returns the block height of the update.
	BlockHeight() uint32

	// Encode encodes the event into the passed io.Writer.
	Encode(io.Writer) error
}

SupplyUpdateEvent is a special interface used to create the equivalent of a sum-type, but using a "sealed" interface. This is a super set of the normal event, to identify events that are used to update the supply tree.

type SyncSupplyUpdateEvent

type SyncSupplyUpdateEvent interface {
	SupplyUpdateEvent

	// SignalDone signals completion on the done channel if it exists.
	// It sends the error (or nil for success) and does not block.
	SignalDone(error)

	// WaitForDone waits for the event to be processed by waiting on its
	// done channel. This is a helper method that can be used by callers who
	// want synchronous confirmation that their event has been persisted.
	WaitForDone(context.Context) error
}

SyncSupplyUpdateEvent is an interface that extends SupplyUpdateEvent with the ability to signal completion when the event has been processed.

type UpdatesPendingState

type UpdatesPendingState struct {
	// contains filtered or unexported fields
}

UpdatesPendingState is the state of the state machine when we have. From this state, we can queue/accept new supply commit events. Periodically, we'll rely on a new incoming Commit event, that'll be used as a trigger to progress the state machine to the next state.

Upon restart, we'll start in this state if we already have pending items in the update/staging log.

State transitions:

  • SupplyUpdateEvent -> UpdatePendingState
  • CommitTickEvent -> CommmitTreeCreate

func (*UpdatesPendingState) IsTerminal

func (u *UpdatesPendingState) IsTerminal() bool

IsTerminal returns true if the target state is a terminal state.

func (*UpdatesPendingState) ProcessEvent

func (u *UpdatesPendingState) ProcessEvent(event Event, env *Environment) (
	*StateTransition, error)

ProcessEvent processes incoming events for the UpdatesPendingState. From here, we'll either be staging new events, or we'll attempt to start the commitment update process once a new commitment is received.

func (*UpdatesPendingState) String

func (u *UpdatesPendingState) String() string

String returns the name of the state.

type Wallet

type Wallet interface {
	// FundPsbt attaches enough inputs to the target PSBT packet for it to
	// be valid.
	FundPsbt(ctx context.Context, packet *psbt.Packet, minConfs uint32,
		feeRate chainfee.SatPerKWeight,
		changeIdx int32) (*tapsend.FundedPsbt, error)

	// SignPsbt fully signs the target PSBT packet.
	SignPsbt(context.Context, *psbt.Packet) (*psbt.Packet, error)

	// ImportTaprootOutput imports a new taproot output key into the wallet.
	ImportTaprootOutput(context.Context, *btcec.PublicKey) (btcutil.Address,
		error)

	// UnlockInput unlocks the set of target inputs after a batch or send
	// transaction is abandoned.
	UnlockInput(context.Context, wire.OutPoint) error
}

Wallet the main wallet interface used to managed PSBT packets, and import taproot output keys into the wallet.

Jump to

Keyboard shortcuts

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