Documentation
¶
Overview ¶
Package chainbackends provides concrete implementations of the chainsource.ChainBackend interface.
The ChainBackend interface is defined in the chainsource package and provides a blockchain data abstraction layer for the Ark actor system. This package contains pluggable backend implementations that can be used depending on deployment requirements.
Available Backends ¶
LNDBackend: Full-node backend that wraps lnd's chain notification and fee estimation interfaces. Suitable for production deployments where lnd is available. Provides real-time notifications via lnd's chainntnfs package.
Usage ¶
Backends are instantiated and passed to the ChainSource actor during initialization. For in-process lnd:
backend := chainbackends.NewLNDBackend( notifier, feeEstimator, broadcaster, ) chainSource := chainsource.NewChainSourceActor( backend, system, ctx, )
For remote lnd via lndclient:
backend := chainbackends.NewLNDBackendFromLndClient(lndServices) chainSource := chainsource.NewChainSourceActor( backend, system, ctx, )
Architecture ¶
The separation between interface (chainsource) and implementations (chainbackends) provides several benefits:
- Pluggability: Easy to swap backends without changing actor code
- Testing: Mock backends can be created for testing
- Dependencies: The actor system doesn't depend on lnd or HTTP libraries
- Extensibility: New backends can be added without modifying core code
Implementation Requirements ¶
Backend implementations must:
- Implement all methods of chainsource.ChainBackend
- Be safe for concurrent use
- Handle context cancellation properly
- Clean up resources in Stop()
- Document any limitations or unsupported operations
Backend Selection Criteria ¶
LNDBackend is recommended when:
- Running a full node with lnd
- Real-time notifications are required
- Low latency is critical
- Full Bitcoin protocol support is needed
Index ¶
- Constants
- func WalkPackageTxErrors(err error, fn func(*PackageTxError))
- type LNDBackend
- func (b *LNDBackend) BestBlock(ctx context.Context) (int32, chainhash.Hash, error)
- func (b *LNDBackend) BroadcastTx(ctx context.Context, tx *wire.MsgTx, label string) error
- func (b *LNDBackend) EstimateFee(ctx context.Context, targetConf uint32) (btcutil.Amount, error)
- func (b *LNDBackend) RegisterBlocks(ctx context.Context) (*chainsource.BlockRegistration, error)
- func (b *LNDBackend) RegisterConf(ctx context.Context, txid *chainhash.Hash, pkScript []byte, numConfs uint32, ...) (*chainsource.ConfRegistration, error)
- func (b *LNDBackend) RegisterSpend(ctx context.Context, outpoint *wire.OutPoint, pkScript []byte, ...) (*chainsource.SpendRegistration, error)
- func (b *LNDBackend) SetPackageSubmitter(packageSubmitter PackageSubmitter)
- func (b *LNDBackend) Start() error
- func (b *LNDBackend) Stop() error
- func (b *LNDBackend) SubmitPackage(ctx context.Context, parents []*wire.MsgTx, child *wire.MsgTx) error
- func (b *LNDBackend) TestMempoolAccept(_ context.Context, _ ...*wire.MsgTx) ([]chainsource.MempoolAcceptResult, error)
- type LNDBackendFromLndClientConfig
- type LndClientChainNotifier
- func (n *LndClientChainNotifier) RegisterBlockEpochNtfn(bestBlock *chainntnfs.BlockEpoch) (*chainntnfs.BlockEpochEvent, error)
- func (n *LndClientChainNotifier) RegisterConfirmationsNtfn(txid *chainhash.Hash, pkScript []byte, numConfs, heightHint uint32, ...) (*chainntnfs.ConfirmationEvent, error)
- func (n *LndClientChainNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, pkScript []byte, heightHint uint32) (*chainntnfs.SpendEvent, error)
- func (n *LndClientChainNotifier) Start() error
- func (n *LndClientChainNotifier) Started() bool
- func (n *LndClientChainNotifier) Stop() error
- type LndClientChainNotifierConfig
- type LndClientFeeEstimator
- type LndClientTxBroadcaster
- type PackageSubmitter
- type PackageTxError
- type TxBroadcaster
Constants ¶
const ( // Subsystem defines the logging subsystem code for the chainbackends // package. Subsystem = "CBKD" // LndClientSubsystem defines the logging subsystem code for the // lndclient adapter components. LndClientSubsystem = "LNDC" )
Variables ¶
This section is empty.
Functions ¶
func WalkPackageTxErrors ¶
func WalkPackageTxErrors(err error, fn func(*PackageTxError))
WalkPackageTxErrors invokes `fn` for every `*PackageTxError` reachable from `err` by walking both the `Unwrap() error` and `Unwrap() []error` shapes. It is safe to call with `nil`.
Used by callers (e.g. `txconfirm.isParentKnownChildFailed`) that need to inspect every per-tx entry in a joined `SubmitPackage` error. `errors.As` alone only surfaces the first match, which is insufficient when distinct classifications must be observed for the parent and the child.
Implementation note: this walks the error tree directly rather than using `errors.As(&pte)`, because `errors.As` short-circuits on the first match and would miss sibling per-tx entries — the whole point of the walker. The lint disables below are intentional for that reason.
Types ¶
type LNDBackend ¶
type LNDBackend struct {
// Log is an optional logger for this backend. If None, the backend
// falls back to extracting a logger from context.
Log fn.Option[btclog.Logger]
// contains filtered or unexported fields
}
LNDBackend implements the chainsource.ChainBackend interface by wrapping lnd's chain notification and fee estimation interfaces. This backend provides full-node functionality and is suitable for production deployments where lnd is available.
The backend delegates all operations to the underlying lnd components: chainntnfs for notifications and chainfee for fee estimation.
func NewLNDBackend ¶
func NewLNDBackend(notifier chainntnfs.ChainNotifier, feeEstimator chainfee.Estimator, broadcaster TxBroadcaster) *LNDBackend
NewLNDBackend creates a new LNDBackend instance with the given lnd components. All parameters must be non-nil.
func NewLNDBackendFromLndClient ¶
func NewLNDBackendFromLndClient(cfg LNDBackendFromLndClientConfig) (*LNDBackend, error)
NewLNDBackendFromLndClient creates a new LNDBackend using lndclient services. This is a convenience function for creating a backend from a remote lnd connection. The config must include LND; use WithLogger() to inject a specific logger.
func (*LNDBackend) BestBlock ¶
BestBlock returns the current best block height and hash from lnd's view of the blockchain. We register for a single block notification to get the current tip.
func (*LNDBackend) BroadcastTx ¶
BroadcastTx broadcasts a transaction to the network using the configured broadcaster.
func (*LNDBackend) EstimateFee ¶
EstimateFee returns the estimated fee rate in satoshis per vbyte for the given confirmation target. The fee estimator will provide the rate needed to confirm within the target number of blocks.
func (*LNDBackend) RegisterBlocks ¶
func (b *LNDBackend) RegisterBlocks(ctx context.Context) ( *chainsource.BlockRegistration, error)
RegisterBlocks registers for new block notifications using lnd's chain notifier. The registration returns a BlockRegistration with a channel for receiving block events.
func (*LNDBackend) RegisterConf ¶
func (b *LNDBackend) RegisterConf(ctx context.Context, txid *chainhash.Hash, pkScript []byte, numConfs uint32, heightHint uint32, includeBlock bool) (*chainsource.ConfRegistration, error)
RegisterConf registers for confirmation notifications using lnd's chain notifier. The registration returns a ConfRegistration with channels for receiving confirmation events.
func (*LNDBackend) RegisterSpend ¶
func (b *LNDBackend) RegisterSpend(ctx context.Context, outpoint *wire.OutPoint, pkScript []byte, heightHint uint32) (*chainsource.SpendRegistration, error)
RegisterSpend registers for spend notifications using lnd's chain notifier. The registration returns a SpendRegistration with channels for receiving spend events.
func (*LNDBackend) SetPackageSubmitter ¶
func (b *LNDBackend) SetPackageSubmitter(packageSubmitter PackageSubmitter)
SetPackageSubmitter attaches optional package relay support to the backend.
func (*LNDBackend) Start ¶
func (b *LNDBackend) Start() error
Start initializes the LND backend by starting the notifier and fee estimator.
func (*LNDBackend) Stop ¶
func (b *LNDBackend) Stop() error
Stop shuts down the LND backend by stopping the notifier and fee estimator.
func (*LNDBackend) SubmitPackage ¶
func (b *LNDBackend) SubmitPackage(ctx context.Context, parents []*wire.MsgTx, child *wire.MsgTx) error
SubmitPackage submits a parent+child package through the configured PackageSubmitter. This is required for v3 package relay when a fee-paying child must accompany otherwise non-relayable parents.
func (*LNDBackend) TestMempoolAccept ¶
func (b *LNDBackend) TestMempoolAccept(_ context.Context, _ ...*wire.MsgTx) ( []chainsource.MempoolAcceptResult, error)
TestMempoolAccept tests whether one or more transactions would be accepted by the mempool. LND's WalletController does not expose a testmempoolaccept equivalent, so every call returns "not supported" here — callers that treat preflight as best-effort should log and continue.
type LNDBackendFromLndClientConfig ¶
type LNDBackendFromLndClientConfig struct {
// LND is the lndclient services connection.
LND *lndclient.LndServices
// Log is an optional logger for the backend components. If None, the
// backend falls back to extracting a logger from context or uses
// btclog.Disabled.
Log fn.Option[btclog.Logger]
// PackageSubmitter is an optional package submitter for atomic
// parent+child package submission. When nil, SubmitPackage
// returns an "unsupported" error. Typically backed by a direct
// bitcoind RPC client.
PackageSubmitter PackageSubmitter
}
LNDBackendFromLndClientConfig holds configuration for creating an LNDBackend from lndclient services.
func (LNDBackendFromLndClientConfig) WithLogger ¶
func (c LNDBackendFromLndClientConfig) WithLogger( log btclog.Logger) LNDBackendFromLndClientConfig
WithLogger returns a new config with the given logger set.
type LndClientChainNotifier ¶
type LndClientChainNotifier struct {
// contains filtered or unexported fields
}
LndClientChainNotifier implements chainntnfs.ChainNotifier using lndclient. This adapter bridges the lndclient.ChainNotifierClient interface to the chainntnfs.ChainNotifier interface expected by LNDBackend.
func NewLndClientChainNotifier ¶
func NewLndClientChainNotifier( cfg LndClientChainNotifierConfig) *LndClientChainNotifier
NewLndClientChainNotifier creates a new chain notifier backed by lndclient. The config must include LND; use WithLogger() to inject a specific logger.
func (*LndClientChainNotifier) RegisterBlockEpochNtfn ¶
func (n *LndClientChainNotifier) RegisterBlockEpochNtfn( bestBlock *chainntnfs.BlockEpoch) (*chainntnfs.BlockEpochEvent, error)
RegisterBlockEpochNtfn registers for block epoch notifications using lndclient's ChainNotifier.
func (*LndClientChainNotifier) RegisterConfirmationsNtfn ¶
func (n *LndClientChainNotifier) RegisterConfirmationsNtfn(txid *chainhash.Hash, pkScript []byte, numConfs, heightHint uint32, opts ...chainntnfs.NotifierOption) (*chainntnfs.ConfirmationEvent, error)
RegisterConfirmationsNtfn registers for confirmation notifications using lndclient's ChainNotifier.
func (*LndClientChainNotifier) RegisterSpendNtfn ¶
func (n *LndClientChainNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, pkScript []byte, heightHint uint32) (*chainntnfs.SpendEvent, error)
RegisterSpendNtfn registers for spend notifications using lndclient's ChainNotifier.
func (*LndClientChainNotifier) Start ¶
func (n *LndClientChainNotifier) Start() error
Start is a no-op for lndclient-backed notifiers since the connection is already established.
func (*LndClientChainNotifier) Started ¶
func (n *LndClientChainNotifier) Started() bool
Started returns true since lndclient connections are always ready.
func (*LndClientChainNotifier) Stop ¶
func (n *LndClientChainNotifier) Stop() error
Stop is a no-op for lndclient-backed notifiers.
type LndClientChainNotifierConfig ¶
type LndClientChainNotifierConfig struct {
// LND is the lndclient services connection.
LND *lndclient.LndServices
// Log is an optional logger for this notifier. If None, the notifier
// falls back to extracting a logger from context via
// LoggerFromContext, or uses btclog.Disabled if no logger is found.
Log fn.Option[btclog.Logger]
}
LndClientChainNotifierConfig holds configuration for LndClientChainNotifier.
func (LndClientChainNotifierConfig) WithLogger ¶
func (c LndClientChainNotifierConfig) WithLogger( log btclog.Logger) LndClientChainNotifierConfig
WithLogger returns a new config with the given logger set.
type LndClientFeeEstimator ¶
type LndClientFeeEstimator = chainfees.WalletKitEstimator
LndClientFeeEstimator implements chainfee.Estimator using lndclient.
func NewLndClientFeeEstimator ¶
func NewLndClientFeeEstimator(walletKit lndclient.WalletKitClient) ( *LndClientFeeEstimator, error)
NewLndClientFeeEstimator creates a new fee estimator backed by lndclient. It uses last-good fallback semantics: a WalletKit error returns the last successful rate (or the relay floor before any success) rather than propagating the error, so a transient WalletKit outage does not abort fee estimation on the standalone LND backend path.
type LndClientTxBroadcaster ¶
type LndClientTxBroadcaster struct {
// contains filtered or unexported fields
}
LndClientTxBroadcaster implements TxBroadcaster using lndclient.WalletKitClient.
func NewLndClientTxBroadcaster ¶
func NewLndClientTxBroadcaster( walletKit lndclient.WalletKitClient) *LndClientTxBroadcaster
NewLndClientTxBroadcaster creates a new broadcaster backed by lndclient.
func (*LndClientTxBroadcaster) PublishTransaction ¶
func (b *LndClientTxBroadcaster) PublishTransaction(ctx context.Context, tx *wire.MsgTx, label string) error
PublishTransaction broadcasts the given transaction to the network via lnd.
type PackageSubmitter ¶
type PackageSubmitter interface {
// SubmitPackage submits the package. The maxFeeRate parameter is
// optional and nil leaves the node default unchanged. The context
// controls cancellation/timeout for the underlying RPC.
SubmitPackage(ctx context.Context, parents []*wire.MsgTx,
child *wire.MsgTx,
maxFeeRate *float64) (*btcjson.SubmitPackageResult, error)
}
PackageSubmitter atomically submits parent+child transaction packages. Bitcoind-backed implementations can satisfy this interface to expose v3 package relay through the LND chain backend.
type PackageTxError ¶
type PackageTxError struct {
// Wtxid is the witness txid that bitcoind / btcd echoed for this
// per-tx package result.
Wtxid string
// Txid is the legacy (non-witness) txid associated with this entry.
Txid chainhash.Hash
// Reason is the raw reject reason as emitted by the chain backend
// before normalisation. Kept for diagnostics; do not rely on it for
// classification — use `errors.Is` against the unwrapped sentinel
// instead.
Reason string
// contains filtered or unexported fields
}
PackageTxError is one per-tx result error from a `SubmitPackage` response. It preserves the original wtxid / txid / reject reason for diagnostics, and unwraps to a chain-backend sentinel mapped via `rpcclient.MapRPCErr` so callers can `errors.Is` against typed sentinels (e.g. `rpcclient.ErrTxAlreadyKnown`, `rpcclient.ErrInsufficientFee`) instead of substring-matching the raw bitcoind / btcd reject string.
func NewPackageTxError ¶
func NewPackageTxError(wtxid string, txid chainhash.Hash, reason string) *PackageTxError
NewPackageTxError builds a `PackageTxError` from a per-tx package result. The mapped sentinel is computed eagerly via `rpcclient.MapRPCErr` so the caller side can rely on `errors.Is` without re-parsing the reason.
func (*PackageTxError) Error ¶
func (e *PackageTxError) Error() string
Error implements the `error` interface and preserves the legacy "wtxid=<wtxid> txid=<txid>: <reason>" diagnostic shape that joined error messages used to carry, so log output and existing string-matching fallbacks (e.g. `rejecting replacement` heuristics) keep working until they are migrated to typed checks.
func (*PackageTxError) Unwrap ¶
func (e *PackageTxError) Unwrap() error
Unwrap surfaces the mapped chain sentinel so callers can write `errors.Is(err, rpcclient.ErrTxAlreadyKnown)` instead of substring-matching the raw reason.
type TxBroadcaster ¶
type TxBroadcaster interface {
// PublishTransaction broadcasts the given transaction to the network.
// The label parameter is optional and may be used for wallet tracking.
PublishTransaction(ctx context.Context, tx *wire.MsgTx,
label string) error
}
TxBroadcaster is a minimal interface for broadcasting transactions. This allows LNDBackend to work with both lnwallet.WalletController (in-process lnd) and lndclient wrappers (remote lnd via gRPC).
Directories
¶
| Path | Synopsis |
|---|---|
|
Package bitcoindrpc provides a direct-to-bitcoind JSON-RPC implementation of chainbackends.PackageSubmitter, used by the production daemon (and by integration tests) when the LND v3 submitpackage path is not available.
|
Package bitcoindrpc provides a direct-to-bitcoind JSON-RPC implementation of chainbackends.PackageSubmitter, used by the production daemon (and by integration tests) when the LND v3 submitpackage path is not available. |
|
Package lndsubmitter provides a chainbackends.PackageSubmitter backed by lnd's WalletKit.SubmitPackage RPC.
|
Package lndsubmitter provides a chainbackends.PackageSubmitter backed by lnd's WalletKit.SubmitPackage RPC. |