Skip to content

Commit

Permalink
Merge pull request #8632 from lightningnetwork/aux-leaf-signing
Browse files Browse the repository at this point in the history
[4/5]: lnwallet: add new AuxSigner interface to mirror SigPool
  • Loading branch information
guggero authored May 27, 2024
2 parents 652ff81 + ebf9856 commit 626a1b8
Show file tree
Hide file tree
Showing 13 changed files with 394 additions and 44 deletions.
4 changes: 4 additions & 0 deletions chainreg/chainregistry.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ type Config struct {
// leaves for certain custom channel types.
AuxLeafStore fn.Option[lnwallet.AuxLeafStore]

// AuxSigner is an optional signer that can be used to sign auxiliary
// leaves for certain custom channel types.
AuxSigner fn.Option[lnwallet.AuxSigner]

// BlockCache is the main cache for storing block information.
BlockCache *blockcache.BlockCache

Expand Down
12 changes: 7 additions & 5 deletions config_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,14 @@ type AuxComponents struct {
MsgRouter fn.Option[protofsm.MsgRouter]

// AuxFundingController is an optional controller that can be used to
// modify the way we handle certain custom chanenl types. It's also
// modify the way we handle certain custom channel types. It's also
// able to automatically handle new custom protocol messages related to
// the funding process.
AuxFundingController fn.Option[funding.AuxFundingController]

// AuxSigner is an optional signer that can be used to sign auxiliary
// leaves for certain custom channel types.
AuxSigner fn.Option[lnwallet.AuxSigner]
}

// DefaultWalletImpl is the default implementation of our normal, btcwallet
Expand Down Expand Up @@ -580,6 +584,7 @@ func (d *DefaultWalletImpl) BuildWalletConfig(ctx context.Context,
ChanStateDB: dbs.ChanStateDB.ChannelStateDB(),
NeutrinoCS: neutrinoCS,
AuxLeafStore: aux.AuxLeafStore,
AuxSigner: aux.AuxSigner,
ActiveNetParams: d.cfg.ActiveNetParams,
FeeURL: d.cfg.FeeURL,
Dialer: func(addr string) (net.Conn, error) {
Expand Down Expand Up @@ -732,6 +737,7 @@ func (d *DefaultWalletImpl) BuildChainControl(
NetParams: *walletConfig.NetParams,
CoinSelectionStrategy: walletConfig.CoinSelectionStrategy,
AuxLeafStore: partialChainControl.Cfg.AuxLeafStore,
AuxSigner: partialChainControl.Cfg.AuxSigner,
}

// The broadcast is already always active for neutrino nodes, so we
Expand Down Expand Up @@ -911,10 +917,6 @@ type DatabaseInstances struct {
// for native SQL queries for tables that already support it. This may
// be nil if the use-native-sql flag was not set.
NativeSQLStore *sqldb.BaseDB

// AuxLeafStore is an optional data source that can be used by custom
// channels to fetch+store various data.
AuxLeafStore fn.Option[lnwallet.AuxLeafStore]
}

// DefaultDatabaseBuilder is a type that builds the default database backends
Expand Down
10 changes: 10 additions & 0 deletions contractcourt/chain_arbitrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ type ChainArbitratorConfig struct {
// AuxLeafStore is an optional store that can be used to store auxiliary
// leaves for certain custom channel types.
AuxLeafStore fn.Option[lnwallet.AuxLeafStore]

// AuxSigner is an optional signer that can be used to sign auxiliary
// leaves for certain custom channel types.
AuxSigner fn.Option[lnwallet.AuxSigner]
}

// ChainArbitrator is a sub-system that oversees the on-chain resolution of all
Expand Down Expand Up @@ -307,6 +311,9 @@ func (a *arbChannel) NewAnchorResolutions() (*lnwallet.AnchorResolutions,
a.c.cfg.AuxLeafStore.WhenSome(func(s lnwallet.AuxLeafStore) {
chanOpts = append(chanOpts, lnwallet.WithLeafStore(s))
})
a.c.cfg.AuxSigner.WhenSome(func(s lnwallet.AuxSigner) {
chanOpts = append(chanOpts, lnwallet.WithAuxSigner(s))
})

chanMachine, err := lnwallet.NewLightningChannel(
a.c.cfg.Signer, channel, nil, chanOpts...,
Expand Down Expand Up @@ -357,6 +364,9 @@ func (a *arbChannel) ForceCloseChan() (*lnwallet.LocalForceCloseSummary, error)
a.c.cfg.AuxLeafStore.WhenSome(func(s lnwallet.AuxLeafStore) {
chanOpts = append(chanOpts, lnwallet.WithLeafStore(s))
})
a.c.cfg.AuxSigner.WhenSome(func(s lnwallet.AuxSigner) {
chanOpts = append(chanOpts, lnwallet.WithAuxSigner(s))
})

// Finally, we'll force close the channel completing
// the force close workflow.
Expand Down
7 changes: 7 additions & 0 deletions funding/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,10 @@ type Config struct {
// able to automatically handle new custom protocol messages related to
// the funding process.
AuxFundingController fn.Option[AuxFundingController]

// AuxSigner is an optional signer that can be used to sign auxiliary
// leaves for certain custom channel types.
AuxSigner fn.Option[lnwallet.AuxSigner]
}

// Manager acts as an orchestrator/bridge between the wallet's
Expand Down Expand Up @@ -1077,6 +1081,9 @@ func (f *Manager) advanceFundingState(channel *channeldb.OpenChannel,
f.cfg.AuxLeafStore.WhenSome(func(s lnwallet.AuxLeafStore) {
chanOpts = append(chanOpts, lnwallet.WithLeafStore(s))
})
f.cfg.AuxSigner.WhenSome(func(s lnwallet.AuxSigner) {
chanOpts = append(chanOpts, lnwallet.WithAuxSigner(s))
})

// We create the state-machine object which wraps the database state.
lnChannel, err := lnwallet.NewLightningChannel(
Expand Down
2 changes: 2 additions & 0 deletions htlcswitch/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -2143,6 +2143,7 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) {
CommitSig: msg.CommitSig,
HtlcSigs: msg.HtlcSigs,
PartialSig: msg.PartialSig,
AuxSigBlob: msg.ExtraData,
})
if err != nil {
// If we were unable to reconstruct their proposed
Expand Down Expand Up @@ -2556,6 +2557,7 @@ func (l *channelLink) updateCommitTx() error {
CommitSig: newCommit.CommitSig,
HtlcSigs: newCommit.HtlcSigs,
PartialSig: newCommit.PartialSig,
ExtraData: newCommit.AuxSigBlob,
}
l.cfg.Peer.SendMessage(false, commitSig)

Expand Down
149 changes: 149 additions & 0 deletions lnwallet/aux_signer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package lnwallet

import (
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/fn"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/tlv"
)

// BaseAuxJob is a struct that contains the common fields that are shared among
// the aux sign/verify jobs.
type BaseAuxJob struct {
// OutputIndex is the output index of the HTLC on the commitment
// transaction being signed.
//
// NOTE: If the output is dust from the PoV of the commitment chain,
// then this value will be -1.
OutputIndex int32

// KeyRing is the commitment key ring that contains the keys needed to
// generate the second level HTLC signatures.
KeyRing CommitmentKeyRing

// HTLC is the HTLC that is being signed or verified.
HTLC PaymentDescriptor

// Incoming is a boolean that indicates if the HTLC is incoming or
// outgoing.
Incoming bool

// CommitBlob is the commitment transaction blob that contains the aux
// information for this channel.
CommitBlob fn.Option[tlv.Blob]

// HtlcLeaf is the aux tap leaf that corresponds to the HTLC being
// signed/verified.
HtlcLeaf input.AuxTapLeaf
}

// AuxSigJob is a struct that contains all the information needed to sign an
// HTLC for custom channels.
type AuxSigJob struct {
// SignDesc is the sign desc for this HTLC.
SignDesc input.SignDescriptor

BaseAuxJob

// Resp is a channel that will be used to send the result of the sign
// job.
Resp chan AuxSigJobResp

// Cancel is a channel that should be closed if the caller wishes to
// abandon all pending sign jobs part of a single batch.
Cancel chan struct{}
}

// NewAuxSigJob creates a new AuxSigJob.
func NewAuxSigJob(sigJob SignJob, keyRing CommitmentKeyRing, incoming bool,
htlc PaymentDescriptor, commitBlob fn.Option[tlv.Blob],
htlcLeaf input.AuxTapLeaf, cancelChan chan struct{}) AuxSigJob {

return AuxSigJob{
SignDesc: sigJob.SignDesc,
BaseAuxJob: BaseAuxJob{
OutputIndex: sigJob.OutputIndex,
KeyRing: keyRing,
HTLC: htlc,
Incoming: incoming,
CommitBlob: commitBlob,
HtlcLeaf: htlcLeaf,
},
Resp: make(chan AuxSigJobResp, 1),
Cancel: cancelChan,
}
}

// AuxSigJobResp is a struct that contains the result of a sign job.
type AuxSigJobResp struct {
// SigBlob is the signature blob that was generated for the HTLC. This
// is an opaque TLV field that may contain the signature and other data.
SigBlob fn.Option[tlv.Blob]

// HtlcIndex is the index of the HTLC that was signed.
HtlcIndex uint64

// Err is the error that occurred when executing the specified
// signature job. In the case that no error occurred, this value will
// be nil.
Err error
}

// AuxVerifyJob is a struct that contains all the information needed to verify
// an HTLC for custom channels.
type AuxVerifyJob struct {
// SigBlob is the signature blob that was generated for the HTLC. This
// is an opaque TLV field that may contain the signature and other data.
SigBlob fn.Option[tlv.Blob]

BaseAuxJob

// Cancel is a channel that should be closed if the caller wishes to
// abandon the job.
Cancel chan struct{}

// ErrResp is a channel that will be used to send the result of the
// verify job.
ErrResp chan error
}

// NewAuxVerifyJob creates a new AuxVerifyJob.
func NewAuxVerifyJob(sig fn.Option[tlv.Blob], keyRing CommitmentKeyRing,
incoming bool, htlc PaymentDescriptor, commitBlob fn.Option[tlv.Blob],
htlcLeaf input.AuxTapLeaf) AuxVerifyJob {

return AuxVerifyJob{
SigBlob: sig,
BaseAuxJob: BaseAuxJob{
KeyRing: keyRing,
HTLC: htlc,
Incoming: incoming,
CommitBlob: commitBlob,
HtlcLeaf: htlcLeaf,
},
}
}

// AuxSigner is an interface that is used to sign and verify HTLCs for custom
// channels. It is similar to the existing SigPool, but uses opaque blobs to
// shuffle around signature information and other metadata.
type AuxSigner interface {
// SubmitSecondLevelSigBatch takes a batch of aux sign jobs and
// processes them asynchronously.
SubmitSecondLevelSigBatch(chanState *channeldb.OpenChannel,
commitTx *wire.MsgTx, sigJob []AuxSigJob) error

// PackSigs takes a series of aux signatures and packs them into a
// single blob that can be sent alongside the CommitSig messages.
PackSigs([]fn.Option[tlv.Blob]) (fn.Option[tlv.Blob], error)

// UnpackSigs takes a packed blob of signatures and returns the
// original signatures for each HTLC, keyed by HTLC index.
UnpackSigs(fn.Option[tlv.Blob]) ([]fn.Option[tlv.Blob], error)

// VerifySecondLevelSigs attempts to synchronously verify a batch of aux
// sig jobs.
VerifySecondLevelSigs(chanState *channeldb.OpenChannel,
commitTx *wire.MsgTx, verifyJob []AuxVerifyJob) error
}
Loading

0 comments on commit 626a1b8

Please sign in to comment.