Skip to content

Commit 7feb8b2

Browse files
committed
multi: upgrade new taproot TLVs to use tlv.OptionalRecordT
In this commit, we update new Taproot related TLVs (nonces, partial sig, sig with nonce, etc). Along the way we were able to get rid of some boiler plate, but most importantly, we're able to better protect against API misuse (using a nonce that isn't initialized, etc) with the new options API. In some areas this introduces a bit of extra boiler plate, and where applicable I used some new helper functions to help cut down on the noise. Note to reviewers: this is done as a single commit, as changing the API breaks all callers, so if we want things to compile it needs to be in a wumbo commit.
1 parent 6bd556d commit 7feb8b2

20 files changed

+401
-288
lines changed

channeldb/channel.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1551,7 +1551,7 @@ func (c *OpenChannel) ChanSyncMsg() (*lnwire.ChannelReestablish, error) {
15511551
// If this is a taproot channel, then we'll need to generate our next
15521552
// verification nonce to send to the remote party. They'll use this to
15531553
// sign the next update to our commitment transaction.
1554-
var nextTaprootNonce *lnwire.Musig2Nonce
1554+
var nextTaprootNonce lnwire.OptMusig2NonceTLV
15551555
if c.ChanType.IsTaproot() {
15561556
taprootRevProducer, err := DeriveMusig2Shachain(
15571557
c.RevocationProducer,
@@ -1569,7 +1569,7 @@ func (c *OpenChannel) ChanSyncMsg() (*lnwire.ChannelReestablish, error) {
15691569
"nonce: %w", err)
15701570
}
15711571

1572-
nextTaprootNonce = (*lnwire.Musig2Nonce)(&nextNonce.PubNonce)
1572+
nextTaprootNonce = lnwire.SomeMusig2Nonce(nextNonce.PubNonce)
15731573
}
15741574

15751575
return &lnwire.ChannelReestablish{

funding/manager.go

Lines changed: 63 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ var (
4848
//
4949
// NOTE: for itest, this value is changed to 10ms.
5050
checkPeerChannelReadyInterval = 1 * time.Second
51+
52+
// errNoLocalNonce is returned when a local nonce is not found in the
53+
// expected TLV.
54+
errNoLocalNonce = fmt.Errorf("local nonce not found")
55+
56+
// errNoPartialSig is returned when a partial sig is not found in the
57+
// expected TLV.
58+
errNoPartialSig = fmt.Errorf("partial sig not found")
5159
)
5260

5361
// WriteOutpoint writes an outpoint to an io.Writer. This is not the same as
@@ -1801,17 +1809,17 @@ func (f *Manager) fundeeProcessOpenChannel(peer lnpeer.Peer,
18011809
}
18021810

18031811
if resCtx.reservation.IsTaproot() {
1804-
if msg.LocalNonce == nil {
1805-
err := fmt.Errorf("local nonce not set for taproot " +
1806-
"chan")
1807-
log.Error(err)
1808-
f.failFundingFlow(
1809-
resCtx.peer, cid, err,
1810-
)
1812+
localNonce, err := msg.LocalNonce.UnwrapOrErrV(errNoLocalNonce)
1813+
if err != nil {
1814+
log.Error(errNoLocalNonce)
1815+
1816+
f.failFundingFlow(resCtx.peer, cid, errNoLocalNonce)
1817+
1818+
return
18111819
}
18121820

18131821
remoteContribution.LocalNonce = &musig2.Nonces{
1814-
PubNonce: *msg.LocalNonce,
1822+
PubNonce: localNonce,
18151823
}
18161824
}
18171825

@@ -1827,13 +1835,6 @@ func (f *Manager) fundeeProcessOpenChannel(peer lnpeer.Peer,
18271835
log.Debugf("Remote party accepted commitment constraints: %v",
18281836
spew.Sdump(remoteContribution.ChannelConfig.ChannelConstraints))
18291837

1830-
var localNonce *lnwire.Musig2Nonce
1831-
if commitType.IsTaproot() {
1832-
localNonce = (*lnwire.Musig2Nonce)(
1833-
&ourContribution.LocalNonce.PubNonce,
1834-
)
1835-
}
1836-
18371838
// With the initiator's contribution recorded, respond with our
18381839
// contribution in the next message of the workflow.
18391840
fundingAccept := lnwire.AcceptChannel{
@@ -1854,7 +1855,12 @@ func (f *Manager) fundeeProcessOpenChannel(peer lnpeer.Peer,
18541855
UpfrontShutdownScript: ourContribution.UpfrontShutdown,
18551856
ChannelType: chanType,
18561857
LeaseExpiry: msg.LeaseExpiry,
1857-
LocalNonce: localNonce,
1858+
}
1859+
1860+
if commitType.IsTaproot() {
1861+
fundingAccept.LocalNonce = lnwire.SomeMusig2Nonce(
1862+
ourContribution.LocalNonce.PubNonce,
1863+
)
18581864
}
18591865

18601866
if err := peer.SendMessage(true, &fundingAccept); err != nil {
@@ -2044,15 +2050,17 @@ func (f *Manager) funderProcessAcceptChannel(peer lnpeer.Peer,
20442050
}
20452051

20462052
if resCtx.reservation.IsTaproot() {
2047-
if msg.LocalNonce == nil {
2048-
err := fmt.Errorf("local nonce not set for taproot " +
2049-
"chan")
2050-
log.Error(err)
2051-
f.failFundingFlow(resCtx.peer, cid, err)
2053+
localNonce, err := msg.LocalNonce.UnwrapOrErrV(errNoLocalNonce)
2054+
if err != nil {
2055+
log.Error(errNoLocalNonce)
2056+
2057+
f.failFundingFlow(resCtx.peer, cid, errNoLocalNonce)
2058+
2059+
return
20522060
}
20532061

20542062
remoteContribution.LocalNonce = &musig2.Nonces{
2055-
PubNonce: *msg.LocalNonce,
2063+
PubNonce: localNonce,
20562064
}
20572065
}
20582066

@@ -2263,7 +2271,9 @@ func (f *Manager) continueFundingAccept(resCtx *reservationWithCtx,
22632271
return
22642272
}
22652273

2266-
fundingCreated.PartialSig = partialSig.ToWireSig()
2274+
fundingCreated.PartialSig = lnwire.MaybePartialSigWithNonce(
2275+
partialSig.ToWireSig(),
2276+
)
22672277
} else {
22682278
fundingCreated.CommitSig, err = lnwire.NewSigFromSignature(sig)
22692279
if err != nil {
@@ -2317,14 +2327,15 @@ func (f *Manager) fundeeProcessFundingCreated(peer lnpeer.Peer,
23172327
// our internal input.Signature type.
23182328
var commitSig input.Signature
23192329
if resCtx.reservation.IsTaproot() {
2320-
if msg.PartialSig == nil {
2321-
log.Errorf("partial sig not included: %v", err)
2330+
partialSig, err := msg.PartialSig.UnwrapOrErrV(errNoPartialSig)
2331+
if err != nil {
23222332
f.failFundingFlow(peer, cid, err)
2333+
23232334
return
23242335
}
23252336

23262337
commitSig = new(lnwallet.MusigPartialSig).FromWireSig(
2327-
msg.PartialSig,
2338+
&partialSig,
23282339
)
23292340
} else {
23302341
commitSig, err = msg.CommitSig.ToSignature()
@@ -2408,7 +2419,9 @@ func (f *Manager) fundeeProcessFundingCreated(peer lnpeer.Peer,
24082419
return
24092420
}
24102421

2411-
fundingSigned.PartialSig = partialSig.ToWireSig()
2422+
fundingSigned.PartialSig = lnwire.MaybePartialSigWithNonce(
2423+
partialSig.ToWireSig(),
2424+
)
24122425
} else {
24132426
fundingSigned.CommitSig, err = lnwire.NewSigFromSignature(sig)
24142427
if err != nil {
@@ -2565,14 +2578,15 @@ func (f *Manager) funderProcessFundingSigned(peer lnpeer.Peer,
25652578
// our internal input.Signature type.
25662579
var commitSig input.Signature
25672580
if resCtx.reservation.IsTaproot() {
2568-
if msg.PartialSig == nil {
2569-
log.Errorf("partial sig not included: %v", err)
2581+
partialSig, err := msg.PartialSig.UnwrapOrErrV(errNoPartialSig)
2582+
if err != nil {
25702583
f.failFundingFlow(peer, cid, err)
2584+
25712585
return
25722586
}
25732587

25742588
commitSig = new(lnwallet.MusigPartialSig).FromWireSig(
2575-
msg.PartialSig,
2589+
&partialSig,
25762590
)
25772591
} else {
25782592
commitSig, err = msg.CommitSig.ToSignature()
@@ -3153,8 +3167,8 @@ func (f *Manager) sendChannelReady(completeChan *channeldb.OpenChannel,
31533167
}
31543168
f.nonceMtx.Unlock()
31553169

3156-
channelReadyMsg.NextLocalNonce = (*lnwire.Musig2Nonce)(
3157-
&localNonce.PubNonce,
3170+
channelReadyMsg.NextLocalNonce = lnwire.SomeMusig2Nonce(
3171+
localNonce.PubNonce,
31583172
)
31593173
}
31603174

@@ -3824,11 +3838,9 @@ func (f *Manager) handleChannelReady(peer lnpeer.Peer, //nolint:funlen
38243838
channelReadyMsg.AliasScid = &alias
38253839

38263840
if firstVerNonce != nil {
3827-
wireNonce := (*lnwire.Musig2Nonce)(
3828-
&firstVerNonce.PubNonce,
3841+
channelReadyMsg.NextLocalNonce = lnwire.SomeMusig2Nonce( //nolint:lll
3842+
firstVerNonce.PubNonce,
38293843
)
3830-
3831-
channelReadyMsg.NextLocalNonce = wireNonce
38323844
}
38333845

38343846
err = peer.SendMessage(true, channelReadyMsg)
@@ -3873,16 +3885,21 @@ func (f *Manager) handleChannelReady(peer lnpeer.Peer, //nolint:funlen
38733885
log.Infof("ChanID(%v): applying local+remote musig2 nonces",
38743886
chanID)
38753887

3876-
if msg.NextLocalNonce == nil {
3877-
log.Errorf("remote nonces are nil")
3888+
remoteNonce, err := msg.NextLocalNonce.UnwrapOrErrV(
3889+
errNoLocalNonce,
3890+
)
3891+
if err != nil {
3892+
cid := newChanIdentifier(msg.ChanID)
3893+
f.failFundingFlow(peer, cid, err)
3894+
38783895
return
38793896
}
38803897

38813898
chanOpts = append(
38823899
chanOpts,
38833900
lnwallet.WithLocalMusigNonces(localNonce),
38843901
lnwallet.WithRemoteMusigNonces(&musig2.Nonces{
3885-
PubNonce: *msg.NextLocalNonce,
3902+
PubNonce: remoteNonce,
38863903
}),
38873904
)
38883905
}
@@ -4714,13 +4731,6 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) {
47144731
log.Infof("Starting funding workflow with %v for pending_id(%x), "+
47154732
"committype=%v", msg.Peer.Address(), chanID, commitType)
47164733

4717-
var localNonce *lnwire.Musig2Nonce
4718-
if commitType.IsTaproot() {
4719-
localNonce = (*lnwire.Musig2Nonce)(
4720-
&ourContribution.LocalNonce.PubNonce,
4721-
)
4722-
}
4723-
47244734
fundingOpen := lnwire.OpenChannel{
47254735
ChainHash: *f.cfg.Wallet.Cfg.NetParams.GenesisHash,
47264736
PendingChannelID: chanID,
@@ -4743,8 +4753,14 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) {
47434753
UpfrontShutdownScript: shutdown,
47444754
ChannelType: chanType,
47454755
LeaseExpiry: leaseExpiry,
4746-
LocalNonce: localNonce,
47474756
}
4757+
4758+
if commitType.IsTaproot() {
4759+
fundingOpen.LocalNonce = lnwire.SomeMusig2Nonce(
4760+
ourContribution.LocalNonce.PubNonce,
4761+
)
4762+
}
4763+
47484764
if err := msg.Peer.SendMessage(true, &fundingOpen); err != nil {
47494765
e := fmt.Errorf("unable to send funding request message: %v",
47504766
err)

lnwallet/chancloser/chancloser.go

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ var (
4949
// ErrInvalidShutdownScript is returned when we receive an address from
5050
// a peer that isn't either a p2wsh or p2tr address.
5151
ErrInvalidShutdownScript = fmt.Errorf("invalid shutdown script")
52+
53+
// errNoShutdownNonce is returned when a shutdown message is received
54+
// w/o a nonce for a taproot channel.
55+
errNoShutdownNonce = fmt.Errorf("shutdown nonce not populated")
5256
)
5357

5458
// closeState represents all the possible states the channel closer state
@@ -337,8 +341,8 @@ func (c *ChanCloser) initChanShutdown() (*lnwire.Shutdown, error) {
337341
return nil, err
338342
}
339343

340-
shutdown.ShutdownNonce = (*lnwire.ShutdownNonce)(
341-
&firstClosingNonce.PubNonce,
344+
shutdown.ShutdownNonce = lnwire.SomeShutdownNonce(
345+
firstClosingNonce.PubNonce,
342346
)
343347

344348
chancloserLog.Infof("Initiating shutdown w/ nonce: %v",
@@ -548,13 +552,15 @@ func (c *ChanCloser) ReceiveShutdown(msg lnwire.Shutdown) (
548552
// remote nonces so we can properly create a new musig
549553
// session for signing.
550554
if c.cfg.Channel.ChanType().IsTaproot() {
551-
if msg.ShutdownNonce == nil {
552-
return noShutdown, fmt.Errorf("shutdown " +
553-
"nonce not populated")
555+
shutdownNonce, err := msg.ShutdownNonce.UnwrapOrErrV(
556+
errNoShutdownNonce,
557+
)
558+
if err != nil {
559+
return noShutdown, err
554560
}
555561

556562
c.cfg.MusigSession.InitRemoteNonce(&musig2.Nonces{
557-
PubNonce: *msg.ShutdownNonce,
563+
PubNonce: shutdownNonce,
558564
})
559565
}
560566

@@ -594,13 +600,15 @@ func (c *ChanCloser) ReceiveShutdown(msg lnwire.Shutdown) (
594600
// local+remote nonces so we can properly create a new musig
595601
// session for signing.
596602
if c.cfg.Channel.ChanType().IsTaproot() {
597-
if msg.ShutdownNonce == nil {
598-
return noShutdown, fmt.Errorf("shutdown " +
599-
"nonce not populated")
603+
shutdownNonce, err := msg.ShutdownNonce.UnwrapOrErrV(
604+
errNoShutdownNonce,
605+
)
606+
if err != nil {
607+
return noShutdown, err
600608
}
601609

602610
c.cfg.MusigSession.InitRemoteNonce(&musig2.Nonces{
603-
PubNonce: *msg.ShutdownNonce,
611+
PubNonce: shutdownNonce,
604612
})
605613
}
606614

@@ -683,10 +691,10 @@ func (c *ChanCloser) BeginNegotiation() (fn.Option[lnwire.ClosingSigned],
683691
}
684692

685693
// ReceiveClosingSigned is a method that should be called whenever we receive a
686-
// ClosingSigned message from the wire. It may or may not return a ClosingSigned
687-
// of our own to send back to the remote.
688-
func (c *ChanCloser) ReceiveClosingSigned(msg lnwire.ClosingSigned) (
689-
fn.Option[lnwire.ClosingSigned], error) {
694+
// ClosingSigned message from the wire. It may or may not return a
695+
// ClosingSigned of our own to send back to the remote.
696+
func (c *ChanCloser) ReceiveClosingSigned( //nolint:funlen
697+
msg lnwire.ClosingSigned) (fn.Option[lnwire.ClosingSigned], error) {
690698

691699
noClosing := fn.None[lnwire.ClosingSigned]()
692700

@@ -702,7 +710,7 @@ func (c *ChanCloser) ReceiveClosingSigned(msg lnwire.ClosingSigned) (
702710
// If this is a taproot channel, then it MUST have a partial
703711
// signature set at this point.
704712
isTaproot := c.cfg.Channel.ChanType().IsTaproot()
705-
if isTaproot && msg.PartialSig == nil {
713+
if isTaproot && msg.PartialSig.IsNone() {
706714
return noClosing,
707715
fmt.Errorf("partial sig not set " +
708716
"for taproot chan")
@@ -807,12 +815,23 @@ func (c *ChanCloser) ReceiveClosingSigned(msg lnwire.ClosingSigned) (
807815
)
808816
matchingSig := c.priorFeeOffers[remoteProposedFee]
809817
if c.cfg.Channel.ChanType().IsTaproot() {
818+
localWireSig, err := matchingSig.PartialSig.UnwrapOrErrV( //nolint:lll
819+
fmt.Errorf("none local sig"),
820+
)
821+
if err != nil {
822+
return noClosing, err
823+
}
824+
remoteWireSig, err := msg.PartialSig.UnwrapOrErrV(
825+
fmt.Errorf("none remote sig"),
826+
)
827+
if err != nil {
828+
return noClosing, err
829+
}
830+
810831
muSession := c.cfg.MusigSession
811-
localSig, remoteSig, closeOpts, err =
812-
muSession.CombineClosingOpts(
813-
*matchingSig.PartialSig,
814-
*msg.PartialSig,
815-
)
832+
localSig, remoteSig, closeOpts, err = muSession.CombineClosingOpts( //nolint:lll
833+
localWireSig, remoteWireSig,
834+
)
816835
if err != nil {
817836
return noClosing, err
818837
}
@@ -952,7 +971,9 @@ func (c *ChanCloser) proposeCloseSigned(fee btcutil.Amount) (
952971
// over a partial signature which'll be combined once our offer is
953972
// accepted.
954973
if partialSig != nil {
955-
closeSignedMsg.PartialSig = &partialSig.PartialSig
974+
closeSignedMsg.PartialSig = lnwire.SomePartialSig(
975+
partialSig.PartialSig,
976+
)
956977
}
957978

958979
// We'll also save this close signed, in the case that the remote party

0 commit comments

Comments
 (0)