Skip to content

Commit

Permalink
Merge pull request #9032 from lightningnetwork/htlc-aux-sig-retransmi…
Browse files Browse the repository at this point in the history
…ssion

lnwallet: properly set aux HTLC blob on retransmission
  • Loading branch information
Roasbeef authored Sep 13, 2024
2 parents e78b0bb + 5058432 commit fb66bd2
Show file tree
Hide file tree
Showing 12 changed files with 643 additions and 112 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ require (
google.golang.org/protobuf v1.33.0
gopkg.in/macaroon-bakery.v2 v2.0.1
gopkg.in/macaroon.v2 v2.0.0
pgregory.net/rapid v1.1.0
)

require (
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1070,6 +1070,8 @@ modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw=
pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
Expand Down
27 changes: 21 additions & 6 deletions htlcswitch/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -2164,11 +2164,21 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) {
// We just received a new updates to our local commitment
// chain, validate this new commitment, closing the link if
// invalid.
auxSigBlob, err := msg.CustomRecords.Serialize()
if err != nil {
l.fail(
LinkFailureError{code: ErrInternalError},
"unable to serialize custom records: %v",
err,
)

return
}
err = l.channel.ReceiveNewCommitment(&lnwallet.CommitSigs{
CommitSig: msg.CommitSig,
HtlcSigs: msg.HtlcSigs,
PartialSig: msg.PartialSig,
AuxSigBlob: msg.ExtraData,
AuxSigBlob: auxSigBlob,
})
if err != nil {
// If we were unable to reconstruct their proposed
Expand Down Expand Up @@ -2577,12 +2587,17 @@ func (l *channelLink) updateCommitTx() error {
default:
}

auxBlobRecords, err := lnwire.ParseCustomRecords(newCommit.AuxSigBlob)
if err != nil {
return fmt.Errorf("error parsing aux sigs: %w", err)
}

commitSig := &lnwire.CommitSig{
ChanID: l.ChanID(),
CommitSig: newCommit.CommitSig,
HtlcSigs: newCommit.HtlcSigs,
PartialSig: newCommit.PartialSig,
ExtraData: newCommit.AuxSigBlob,
ChanID: l.ChanID(),
CommitSig: newCommit.CommitSig,
HtlcSigs: newCommit.HtlcSigs,
PartialSig: newCommit.PartialSig,
CustomRecords: auxBlobRecords,
}
l.cfg.Peer.SendMessage(false, commitSig)

Expand Down
78 changes: 65 additions & 13 deletions lnwallet/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -4028,16 +4028,20 @@ func (lc *LightningChannel) createCommitDiff(newCommit *commitment,
if err != nil {
return nil, fmt.Errorf("error packing aux sigs: %w", err)
}
auxBlobRecords, err := lnwire.ParseCustomRecords(auxSigBlob)
if err != nil {
return nil, fmt.Errorf("error parsing aux sigs: %w", err)
}

return &channeldb.CommitDiff{
Commitment: *diskCommit,
CommitSig: &lnwire.CommitSig{
ChanID: lnwire.NewChanIDFromOutPoint(
lc.channelState.FundingOutpoint,
),
CommitSig: commitSig,
HtlcSigs: htlcSigs,
ExtraData: auxSigBlob,
CommitSig: commitSig,
HtlcSigs: htlcSigs,
CustomRecords: auxBlobRecords,
},
LogUpdates: logUpdates,
OpenedCircuitKeys: openCircuitKeys,
Expand Down Expand Up @@ -4737,17 +4741,44 @@ func (lc *LightningChannel) SignNextCommitment() (*NewCommitState, error) {
// latest commitment update.
lc.remoteCommitChain.addCommitment(newCommitView)

auxSigBlob, err := commitDiff.CommitSig.CustomRecords.Serialize()
if err != nil {
return nil, fmt.Errorf("unable to serialize aux sig "+
"blob: %v", err)
}

return &NewCommitState{
CommitSigs: &CommitSigs{
CommitSig: sig,
HtlcSigs: htlcSigs,
PartialSig: lnwire.MaybePartialSigWithNonce(partialSig),
AuxSigBlob: commitDiff.CommitSig.ExtraData,
AuxSigBlob: auxSigBlob,
},
PendingHTLCs: commitDiff.Commitment.Htlcs,
}, nil
}

// resignMusigCommit is used to resign a commitment transaction for taproot
// channels when we need to retransmit a signature after a channel reestablish
// message. Taproot channels use musig2, which means we must use fresh nonces
// each time. After we receive the channel reestablish message, we learn the
// nonce we need to use for the remote party. As a result, we need to generate
// the partial signature again with the new nonce.
func (lc *LightningChannel) resignMusigCommit(commitTx *wire.MsgTx,
) (lnwire.OptPartialSigWithNonceTLV, error) {

remoteSession := lc.musigSessions.RemoteSession
musig, err := remoteSession.SignCommit(commitTx)
if err != nil {
var none lnwire.OptPartialSigWithNonceTLV
return none, err
}

partialSig := lnwire.MaybePartialSigWithNonce(musig.ToWireSig())

return partialSig, nil
}

// ProcessChanSyncMsg processes a ChannelReestablish message sent by the remote
// connection upon re establishment of our connection with them. This method
// will return a single message if we are currently out of sync, otherwise a
Expand Down Expand Up @@ -4939,13 +4970,23 @@ func (lc *LightningChannel) ProcessChanSyncMsg(
// If we signed this state, then we'll accumulate
// another update to send over.
case err == nil:
blobRecords, err := lnwire.ParseCustomRecords(
newCommit.AuxSigBlob,
)
if err != nil {
sErr := fmt.Errorf("error parsing "+
"aux sigs: %w", err)
return nil, nil, nil, sErr
}

commitSig := &lnwire.CommitSig{
ChanID: lnwire.NewChanIDFromOutPoint(
lc.channelState.FundingOutpoint,
),
CommitSig: newCommit.CommitSig,
HtlcSigs: newCommit.HtlcSigs,
PartialSig: newCommit.PartialSig,
CommitSig: newCommit.CommitSig,
HtlcSigs: newCommit.HtlcSigs,
PartialSig: newCommit.PartialSig,
CustomRecords: blobRecords,
}

updates = append(updates, commitSig)
Expand Down Expand Up @@ -5025,12 +5066,23 @@ func (lc *LightningChannel) ProcessChanSyncMsg(
commitUpdates = append(commitUpdates, logUpdate.UpdateMsg)
}

// If this is a taproot channel, then we need to regenerate the
// musig2 signature for the remote party, using their fresh
// nonce.
if lc.channelState.ChanType.IsTaproot() {
partialSig, err := lc.resignMusigCommit(
commitDiff.Commitment.CommitTx,
)
if err != nil {
return nil, nil, nil, err
}

commitDiff.CommitSig.PartialSig = partialSig
}

// With the batch of updates accumulated, we'll now re-send the
// original CommitSig message required to re-sync their remote
// commitment chain with our local version of their chain.
//
// TODO(roasbeef): need to re-sign commitment states w/
// fresh nonce
commitUpdates = append(commitUpdates, commitDiff.CommitSig)

// NOTE: If a revocation is not owed, then updates is empty.
Expand Down Expand Up @@ -5500,9 +5552,9 @@ func genHtlcSigValidationJobs(chanState *channeldb.OpenChannel,
// store in the custom records map so we can write to
// disk later.
sigType := htlcCustomSigType.TypeVal()
htlc.CustomRecords[uint64(sigType)] = auxSig.UnwrapOr(
nil,
)
auxSig.WhenSome(func(sigB tlv.Blob) {
htlc.CustomRecords[uint64(sigType)] = sigB
})

auxVerifyJobs = append(auxVerifyJobs, auxVerifyJob)
}
Expand Down
Loading

0 comments on commit fb66bd2

Please sign in to comment.