Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[4/5]: lnwallet: add new AuxSigner interface to mirror SigPool #8632

Merged
merged 3 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this here / being removed now?

Copy link
Collaborator

@guggero guggero May 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was just in the wrong place, moved it to the AuxComponents sub struct. When we just had a single aux interface it made sense here, as "store" vaguely has something to do with database. But with all the other components it made sense to move everything to its own struct.

}

// 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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be unsigned int rather than signed?

Copy link
Collaborator

@guggero guggero May 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The value comes from here: https://github.com/lightningnetwork/lnd/blob/a350ccd7/lnwallet/channel.go#L308
So it can actually be negative. Added the same comment here.


// 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 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be nice to mock this and have some minimal test coverage

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this to the tracking issue, since we currently don't have any coverage for those aux interfaces.

// 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
Loading