Skip to content

Commit 626a1b8

Browse files
authored
Merge pull request #8632 from lightningnetwork/aux-leaf-signing
[4/5]: lnwallet: add new AuxSigner interface to mirror SigPool
2 parents 652ff81 + ebf9856 commit 626a1b8

File tree

13 files changed

+394
-44
lines changed

13 files changed

+394
-44
lines changed

chainreg/chainregistry.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ type Config struct {
6868
// leaves for certain custom channel types.
6969
AuxLeafStore fn.Option[lnwallet.AuxLeafStore]
7070

71+
// AuxSigner is an optional signer that can be used to sign auxiliary
72+
// leaves for certain custom channel types.
73+
AuxSigner fn.Option[lnwallet.AuxSigner]
74+
7175
// BlockCache is the main cache for storing block information.
7276
BlockCache *blockcache.BlockCache
7377

config_builder.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,14 @@ type AuxComponents struct {
170170
MsgRouter fn.Option[protofsm.MsgRouter]
171171

172172
// AuxFundingController is an optional controller that can be used to
173-
// modify the way we handle certain custom chanenl types. It's also
173+
// modify the way we handle certain custom channel types. It's also
174174
// able to automatically handle new custom protocol messages related to
175175
// the funding process.
176176
AuxFundingController fn.Option[funding.AuxFundingController]
177+
178+
// AuxSigner is an optional signer that can be used to sign auxiliary
179+
// leaves for certain custom channel types.
180+
AuxSigner fn.Option[lnwallet.AuxSigner]
177181
}
178182

179183
// DefaultWalletImpl is the default implementation of our normal, btcwallet
@@ -580,6 +584,7 @@ func (d *DefaultWalletImpl) BuildWalletConfig(ctx context.Context,
580584
ChanStateDB: dbs.ChanStateDB.ChannelStateDB(),
581585
NeutrinoCS: neutrinoCS,
582586
AuxLeafStore: aux.AuxLeafStore,
587+
AuxSigner: aux.AuxSigner,
583588
ActiveNetParams: d.cfg.ActiveNetParams,
584589
FeeURL: d.cfg.FeeURL,
585590
Dialer: func(addr string) (net.Conn, error) {
@@ -732,6 +737,7 @@ func (d *DefaultWalletImpl) BuildChainControl(
732737
NetParams: *walletConfig.NetParams,
733738
CoinSelectionStrategy: walletConfig.CoinSelectionStrategy,
734739
AuxLeafStore: partialChainControl.Cfg.AuxLeafStore,
740+
AuxSigner: partialChainControl.Cfg.AuxSigner,
735741
}
736742

737743
// The broadcast is already always active for neutrino nodes, so we
@@ -911,10 +917,6 @@ type DatabaseInstances struct {
911917
// for native SQL queries for tables that already support it. This may
912918
// be nil if the use-native-sql flag was not set.
913919
NativeSQLStore *sqldb.BaseDB
914-
915-
// AuxLeafStore is an optional data source that can be used by custom
916-
// channels to fetch+store various data.
917-
AuxLeafStore fn.Option[lnwallet.AuxLeafStore]
918920
}
919921

920922
// DefaultDatabaseBuilder is a type that builds the default database backends

contractcourt/chain_arbitrator.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,10 @@ type ChainArbitratorConfig struct {
221221
// AuxLeafStore is an optional store that can be used to store auxiliary
222222
// leaves for certain custom channel types.
223223
AuxLeafStore fn.Option[lnwallet.AuxLeafStore]
224+
225+
// AuxSigner is an optional signer that can be used to sign auxiliary
226+
// leaves for certain custom channel types.
227+
AuxSigner fn.Option[lnwallet.AuxSigner]
224228
}
225229

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

311318
chanMachine, err := lnwallet.NewLightningChannel(
312319
a.c.cfg.Signer, channel, nil, chanOpts...,
@@ -357,6 +364,9 @@ func (a *arbChannel) ForceCloseChan() (*lnwallet.LocalForceCloseSummary, error)
357364
a.c.cfg.AuxLeafStore.WhenSome(func(s lnwallet.AuxLeafStore) {
358365
chanOpts = append(chanOpts, lnwallet.WithLeafStore(s))
359366
})
367+
a.c.cfg.AuxSigner.WhenSome(func(s lnwallet.AuxSigner) {
368+
chanOpts = append(chanOpts, lnwallet.WithAuxSigner(s))
369+
})
360370

361371
// Finally, we'll force close the channel completing
362372
// the force close workflow.

funding/manager.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,10 @@ type Config struct {
548548
// able to automatically handle new custom protocol messages related to
549549
// the funding process.
550550
AuxFundingController fn.Option[AuxFundingController]
551+
552+
// AuxSigner is an optional signer that can be used to sign auxiliary
553+
// leaves for certain custom channel types.
554+
AuxSigner fn.Option[lnwallet.AuxSigner]
551555
}
552556

553557
// Manager acts as an orchestrator/bridge between the wallet's
@@ -1077,6 +1081,9 @@ func (f *Manager) advanceFundingState(channel *channeldb.OpenChannel,
10771081
f.cfg.AuxLeafStore.WhenSome(func(s lnwallet.AuxLeafStore) {
10781082
chanOpts = append(chanOpts, lnwallet.WithLeafStore(s))
10791083
})
1084+
f.cfg.AuxSigner.WhenSome(func(s lnwallet.AuxSigner) {
1085+
chanOpts = append(chanOpts, lnwallet.WithAuxSigner(s))
1086+
})
10801087

10811088
// We create the state-machine object which wraps the database state.
10821089
lnChannel, err := lnwallet.NewLightningChannel(

htlcswitch/link.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2143,6 +2143,7 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) {
21432143
CommitSig: msg.CommitSig,
21442144
HtlcSigs: msg.HtlcSigs,
21452145
PartialSig: msg.PartialSig,
2146+
AuxSigBlob: msg.ExtraData,
21462147
})
21472148
if err != nil {
21482149
// If we were unable to reconstruct their proposed
@@ -2556,6 +2557,7 @@ func (l *channelLink) updateCommitTx() error {
25562557
CommitSig: newCommit.CommitSig,
25572558
HtlcSigs: newCommit.HtlcSigs,
25582559
PartialSig: newCommit.PartialSig,
2560+
ExtraData: newCommit.AuxSigBlob,
25592561
}
25602562
l.cfg.Peer.SendMessage(false, commitSig)
25612563

lnwallet/aux_signer.go

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package lnwallet
2+
3+
import (
4+
"github.com/btcsuite/btcd/wire"
5+
"github.com/lightningnetwork/lnd/channeldb"
6+
"github.com/lightningnetwork/lnd/fn"
7+
"github.com/lightningnetwork/lnd/input"
8+
"github.com/lightningnetwork/lnd/tlv"
9+
)
10+
11+
// BaseAuxJob is a struct that contains the common fields that are shared among
12+
// the aux sign/verify jobs.
13+
type BaseAuxJob struct {
14+
// OutputIndex is the output index of the HTLC on the commitment
15+
// transaction being signed.
16+
//
17+
// NOTE: If the output is dust from the PoV of the commitment chain,
18+
// then this value will be -1.
19+
OutputIndex int32
20+
21+
// KeyRing is the commitment key ring that contains the keys needed to
22+
// generate the second level HTLC signatures.
23+
KeyRing CommitmentKeyRing
24+
25+
// HTLC is the HTLC that is being signed or verified.
26+
HTLC PaymentDescriptor
27+
28+
// Incoming is a boolean that indicates if the HTLC is incoming or
29+
// outgoing.
30+
Incoming bool
31+
32+
// CommitBlob is the commitment transaction blob that contains the aux
33+
// information for this channel.
34+
CommitBlob fn.Option[tlv.Blob]
35+
36+
// HtlcLeaf is the aux tap leaf that corresponds to the HTLC being
37+
// signed/verified.
38+
HtlcLeaf input.AuxTapLeaf
39+
}
40+
41+
// AuxSigJob is a struct that contains all the information needed to sign an
42+
// HTLC for custom channels.
43+
type AuxSigJob struct {
44+
// SignDesc is the sign desc for this HTLC.
45+
SignDesc input.SignDescriptor
46+
47+
BaseAuxJob
48+
49+
// Resp is a channel that will be used to send the result of the sign
50+
// job.
51+
Resp chan AuxSigJobResp
52+
53+
// Cancel is a channel that should be closed if the caller wishes to
54+
// abandon all pending sign jobs part of a single batch.
55+
Cancel chan struct{}
56+
}
57+
58+
// NewAuxSigJob creates a new AuxSigJob.
59+
func NewAuxSigJob(sigJob SignJob, keyRing CommitmentKeyRing, incoming bool,
60+
htlc PaymentDescriptor, commitBlob fn.Option[tlv.Blob],
61+
htlcLeaf input.AuxTapLeaf, cancelChan chan struct{}) AuxSigJob {
62+
63+
return AuxSigJob{
64+
SignDesc: sigJob.SignDesc,
65+
BaseAuxJob: BaseAuxJob{
66+
OutputIndex: sigJob.OutputIndex,
67+
KeyRing: keyRing,
68+
HTLC: htlc,
69+
Incoming: incoming,
70+
CommitBlob: commitBlob,
71+
HtlcLeaf: htlcLeaf,
72+
},
73+
Resp: make(chan AuxSigJobResp, 1),
74+
Cancel: cancelChan,
75+
}
76+
}
77+
78+
// AuxSigJobResp is a struct that contains the result of a sign job.
79+
type AuxSigJobResp struct {
80+
// SigBlob is the signature blob that was generated for the HTLC. This
81+
// is an opaque TLV field that may contain the signature and other data.
82+
SigBlob fn.Option[tlv.Blob]
83+
84+
// HtlcIndex is the index of the HTLC that was signed.
85+
HtlcIndex uint64
86+
87+
// Err is the error that occurred when executing the specified
88+
// signature job. In the case that no error occurred, this value will
89+
// be nil.
90+
Err error
91+
}
92+
93+
// AuxVerifyJob is a struct that contains all the information needed to verify
94+
// an HTLC for custom channels.
95+
type AuxVerifyJob struct {
96+
// SigBlob is the signature blob that was generated for the HTLC. This
97+
// is an opaque TLV field that may contain the signature and other data.
98+
SigBlob fn.Option[tlv.Blob]
99+
100+
BaseAuxJob
101+
102+
// Cancel is a channel that should be closed if the caller wishes to
103+
// abandon the job.
104+
Cancel chan struct{}
105+
106+
// ErrResp is a channel that will be used to send the result of the
107+
// verify job.
108+
ErrResp chan error
109+
}
110+
111+
// NewAuxVerifyJob creates a new AuxVerifyJob.
112+
func NewAuxVerifyJob(sig fn.Option[tlv.Blob], keyRing CommitmentKeyRing,
113+
incoming bool, htlc PaymentDescriptor, commitBlob fn.Option[tlv.Blob],
114+
htlcLeaf input.AuxTapLeaf) AuxVerifyJob {
115+
116+
return AuxVerifyJob{
117+
SigBlob: sig,
118+
BaseAuxJob: BaseAuxJob{
119+
KeyRing: keyRing,
120+
HTLC: htlc,
121+
Incoming: incoming,
122+
CommitBlob: commitBlob,
123+
HtlcLeaf: htlcLeaf,
124+
},
125+
}
126+
}
127+
128+
// AuxSigner is an interface that is used to sign and verify HTLCs for custom
129+
// channels. It is similar to the existing SigPool, but uses opaque blobs to
130+
// shuffle around signature information and other metadata.
131+
type AuxSigner interface {
132+
// SubmitSecondLevelSigBatch takes a batch of aux sign jobs and
133+
// processes them asynchronously.
134+
SubmitSecondLevelSigBatch(chanState *channeldb.OpenChannel,
135+
commitTx *wire.MsgTx, sigJob []AuxSigJob) error
136+
137+
// PackSigs takes a series of aux signatures and packs them into a
138+
// single blob that can be sent alongside the CommitSig messages.
139+
PackSigs([]fn.Option[tlv.Blob]) (fn.Option[tlv.Blob], error)
140+
141+
// UnpackSigs takes a packed blob of signatures and returns the
142+
// original signatures for each HTLC, keyed by HTLC index.
143+
UnpackSigs(fn.Option[tlv.Blob]) ([]fn.Option[tlv.Blob], error)
144+
145+
// VerifySecondLevelSigs attempts to synchronously verify a batch of aux
146+
// sig jobs.
147+
VerifySecondLevelSigs(chanState *channeldb.OpenChannel,
148+
commitTx *wire.MsgTx, verifyJob []AuxVerifyJob) error
149+
}

0 commit comments

Comments
 (0)