lnwallet+htlcswitch: add NewCommitState struct, modify send/recv sig to accept
In this commit, we add a new NewCommitState struct. This preps us for the future change wherein a partial signature is also added to the mix. All related tests and type signatures have also been updated accordingly.
This commit is contained in:
9 files changed
+342
-322
No files matched your search
+54
-24
@@ -3716,6 +3716,30 @@ func (lc *LightningChannel) validateCommitmentSanity(theirLogCounter,
|
||||
return nil
|
||||
}
|
||||
|
||||
// CommitSig holds the set of related signatures for a new commitment
|
||||
// transaction state.
|
||||
type CommitSigs struct {
|
||||
// CommitSig is the normal commitment signature. This will only be a
|
||||
// non-zero commitment signature for taproot channels.
|
||||
CommitSig lnwire.Sig
|
||||
|
||||
// HtlcSigs is the set of signatures for all HTLCs in the commitment
|
||||
// transaction. Depending on the channel type, these will either be
|
||||
// ECDSA or Schnorr signatures.
|
||||
HtlcSigs []lnwire.Sig
|
||||
}
|
||||
|
||||
// NewCommitState wraps the various signatures needed to properly
|
||||
// propose/accept a new commitment state. This includes the signer's nonce for
|
||||
// musig2 channels.
|
||||
type NewCommitState struct {
|
||||
*CommitSigs
|
||||
|
||||
// PendingHTLCs is the set of new/pending HTLCs produced by this
|
||||
// commitment state.
|
||||
PendingHTLCs []channeldb.HTLC
|
||||
}
|
||||
|
||||
// SignNextCommitment signs a new commitment which includes any previous
|
||||
// unsettled HTLCs, any new HTLCs, and any modifications to prior HTLCs
|
||||
// committed in previous commitment updates. Signing a new commitment
|
||||
@@ -3727,8 +3751,7 @@ func (lc *LightningChannel) validateCommitmentSanity(theirLogCounter,
|
||||
// any). The HTLC signatures are sorted according to the BIP 69 order of the
|
||||
// HTLC's on the commitment transaction. Finally, the new set of pending HTLCs
|
||||
// for the remote party's commitment are also returned.
|
||||
func (lc *LightningChannel) SignNextCommitment() (lnwire.Sig, []lnwire.Sig,
|
||||
[]channeldb.HTLC, error) {
|
||||
func (lc *LightningChannel) SignNextCommitment() (*NewCommitState, error) {
|
||||
|
||||
lc.Lock()
|
||||
defer lc.Unlock()
|
||||
@@ -3755,7 +3778,7 @@ func (lc *LightningChannel) SignNextCommitment() (lnwire.Sig, []lnwire.Sig,
|
||||
if unacked || commitPoint == nil {
|
||||
lc.log.Tracef("waiting for remote ack=%v, nil "+
|
||||
"RemoteNextRevocation: %v", unacked, commitPoint == nil)
|
||||
return sig, htlcSigs, nil, ErrNoWindow
|
||||
return nil, ErrNoWindow
|
||||
}
|
||||
|
||||
// Determine the last update on the remote log that has been locked in.
|
||||
@@ -3770,7 +3793,7 @@ func (lc *LightningChannel) SignNextCommitment() (lnwire.Sig, []lnwire.Sig,
|
||||
remoteACKedIndex, lc.localUpdateLog.logIndex, true, nil, nil,
|
||||
)
|
||||
if err != nil {
|
||||
return sig, htlcSigs, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Grab the next commitment point for the remote party. This will be
|
||||
@@ -3793,7 +3816,7 @@ func (lc *LightningChannel) SignNextCommitment() (lnwire.Sig, []lnwire.Sig,
|
||||
remoteACKedIndex, remoteHtlcIndex, keyRing,
|
||||
)
|
||||
if err != nil {
|
||||
return sig, htlcSigs, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lc.log.Tracef("extending remote chain to height %v, "+
|
||||
@@ -3824,7 +3847,7 @@ func (lc *LightningChannel) SignNextCommitment() (lnwire.Sig, []lnwire.Sig,
|
||||
&lc.channelState.RemoteChanCfg, newCommitView,
|
||||
)
|
||||
if err != nil {
|
||||
return sig, htlcSigs, nil, err
|
||||
return nil, err
|
||||
}
|
||||
lc.sigPool.SubmitSignBatch(sigBatch)
|
||||
|
||||
@@ -3835,12 +3858,12 @@ func (lc *LightningChannel) SignNextCommitment() (lnwire.Sig, []lnwire.Sig,
|
||||
rawSig, err := lc.Signer.SignOutputRaw(newCommitView.txn, lc.signDesc)
|
||||
if err != nil {
|
||||
close(cancelChan)
|
||||
return sig, htlcSigs, nil, err
|
||||
return nil, err
|
||||
}
|
||||
sig, err = lnwire.NewSigFromSignature(rawSig)
|
||||
if err != nil {
|
||||
close(cancelChan)
|
||||
return sig, htlcSigs, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We'll need to send over the signatures to the remote party in the
|
||||
@@ -3860,7 +3883,7 @@ func (lc *LightningChannel) SignNextCommitment() (lnwire.Sig, []lnwire.Sig,
|
||||
// jobs.
|
||||
if jobResp.Err != nil {
|
||||
close(cancelChan)
|
||||
return sig, htlcSigs, nil, jobResp.Err
|
||||
return nil, jobResp.Err
|
||||
}
|
||||
|
||||
htlcSigs = append(htlcSigs, jobResp.Sig)
|
||||
@@ -3871,11 +3894,11 @@ func (lc *LightningChannel) SignNextCommitment() (lnwire.Sig, []lnwire.Sig,
|
||||
// can retransmit it if necessary.
|
||||
commitDiff, err := lc.createCommitDiff(newCommitView, sig, htlcSigs)
|
||||
if err != nil {
|
||||
return sig, htlcSigs, nil, err
|
||||
return nil, err
|
||||
}
|
||||
err = lc.channelState.AppendRemoteCommitChain(commitDiff)
|
||||
if err != nil {
|
||||
return sig, htlcSigs, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO(roasbeef): check that one eclair bug
|
||||
@@ -3886,7 +3909,13 @@ func (lc *LightningChannel) SignNextCommitment() (lnwire.Sig, []lnwire.Sig,
|
||||
// latest commitment update.
|
||||
lc.remoteCommitChain.addCommitment(newCommitView)
|
||||
|
||||
return sig, htlcSigs, commitDiff.Commitment.Htlcs, nil
|
||||
return &NewCommitState{
|
||||
CommitSigs: &CommitSigs{
|
||||
CommitSig: sig,
|
||||
HtlcSigs: htlcSigs,
|
||||
},
|
||||
PendingHTLCs: commitDiff.Commitment.Htlcs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ProcessChanSyncMsg processes a ChannelReestablish message sent by the remote
|
||||
@@ -4044,19 +4073,21 @@ func (lc *LightningChannel) ProcessChanSyncMsg(
|
||||
// revocation, but also initiate a state transition to re-sync
|
||||
// them.
|
||||
if lc.OweCommitment() {
|
||||
commitSig, htlcSigs, _, err := lc.SignNextCommitment()
|
||||
newCommit, err := lc.SignNextCommitment()
|
||||
switch {
|
||||
|
||||
// If we signed this state, then we'll accumulate
|
||||
// another update to send over.
|
||||
case err == nil:
|
||||
updates = append(updates, &lnwire.CommitSig{
|
||||
commitSig := &lnwire.CommitSig{
|
||||
ChanID: lnwire.NewChanIDFromOutPoint(
|
||||
&lc.channelState.FundingOutpoint,
|
||||
),
|
||||
CommitSig: commitSig,
|
||||
HtlcSigs: htlcSigs,
|
||||
})
|
||||
CommitSig: newCommit.CommitSig,
|
||||
HtlcSigs: newCommit.HtlcSigs,
|
||||
}
|
||||
|
||||
updates = append(updates, commitSig)
|
||||
|
||||
// If we get a failure due to not knowing their next
|
||||
// point, then this is fine as they'll either send
|
||||
@@ -4535,8 +4566,7 @@ var _ error = (*InvalidCommitSigError)(nil)
|
||||
// to our local commitment chain. Once we send a revocation for our prior
|
||||
// state, then this newly added commitment becomes our current accepted channel
|
||||
// state.
|
||||
func (lc *LightningChannel) ReceiveNewCommitment(commitSig lnwire.Sig,
|
||||
htlcSigs []lnwire.Sig) error {
|
||||
func (lc *LightningChannel) ReceiveNewCommitment(commitSigs *CommitSigs) error {
|
||||
|
||||
lc.Lock()
|
||||
defer lc.Unlock()
|
||||
@@ -4631,7 +4661,7 @@ func (lc *LightningChannel) ReceiveNewCommitment(commitSig lnwire.Sig,
|
||||
leaseExpiry = lc.channelState.ThawHeight
|
||||
}
|
||||
verifyJobs, err := genHtlcSigValidationJobs(
|
||||
localCommitmentView, keyRing, htlcSigs,
|
||||
localCommitmentView, keyRing, commitSigs.HtlcSigs,
|
||||
lc.channelState.ChanType, lc.channelState.IsInitiator,
|
||||
leaseExpiry, &lc.channelState.LocalChanCfg,
|
||||
&lc.channelState.RemoteChanCfg,
|
||||
@@ -4648,7 +4678,7 @@ func (lc *LightningChannel) ReceiveNewCommitment(commitSig lnwire.Sig,
|
||||
// signature.
|
||||
verifyKey := lc.channelState.RemoteChanCfg.MultiSigKey.PubKey
|
||||
|
||||
cSig, err := commitSig.ToSignature()
|
||||
cSig, err := commitSigs.CommitSig.ToSignature()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -4663,7 +4693,7 @@ func (lc *LightningChannel) ReceiveNewCommitment(commitSig lnwire.Sig,
|
||||
localCommitTx.Serialize(&txBytes)
|
||||
return &InvalidCommitSigError{
|
||||
commitHeight: nextHeight,
|
||||
commitSig: commitSig.ToSignatureBytes(),
|
||||
commitSig: commitSigs.CommitSig.ToSignatureBytes(),
|
||||
sigHash: sigHash,
|
||||
commitTx: txBytes.Bytes(),
|
||||
}
|
||||
@@ -4703,7 +4733,7 @@ func (lc *LightningChannel) ReceiveNewCommitment(commitSig lnwire.Sig,
|
||||
|
||||
// The signature checks out, so we can now add the new commitment to
|
||||
// our local commitment chain.
|
||||
localCommitmentView.sig = commitSig.ToSignatureBytes()
|
||||
localCommitmentView.sig = commitSigs.CommitSig.ToSignatureBytes()
|
||||
lc.localCommitChain.addCommitment(localCommitmentView)
|
||||
|
||||
return nil
|
||||
@@ -5721,7 +5751,7 @@ func (lc *LightningChannel) RemoteUpfrontShutdownScript() lnwire.DeliveryAddress
|
||||
// AbsoluteThawHeight determines a frozen channel's absolute thaw height. If
|
||||
// the channel is not frozen, then 0 is returned.
|
||||
//
|
||||
// An error is returned if the channel is penidng, or is an unconfirmed zero
|
||||
// An error is returned if the channel is pending, or is an unconfirmed zero
|
||||
// conf channel.
|
||||
func (lc *LightningChannel) AbsoluteThawHeight() (uint32, error) {
|
||||
return lc.channelState.AbsoluteThawHeight()
|
||||
|
||||
+223
-206
File diff suppressed because it is too large.
Load diff
@@ -495,11 +495,12 @@ func calcStaticFee(chanType channeldb.ChannelType, numHTLCs int) btcutil.Amount
|
||||
// pending updates. This method is useful when testing interactions between two
|
||||
// live state machines.
|
||||
func ForceStateTransition(chanA, chanB *LightningChannel) error {
|
||||
aliceSig, aliceHtlcSigs, _, err := chanA.SignNextCommitment()
|
||||
aliceNewCommit, err := chanA.SignNextCommitment()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = chanB.ReceiveNewCommitment(aliceSig, aliceHtlcSigs); err != nil {
|
||||
err = chanB.ReceiveNewCommitment(aliceNewCommit.CommitSigs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -507,7 +508,7 @@ func ForceStateTransition(chanA, chanB *LightningChannel) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bobSig, bobHtlcSigs, _, err := chanB.SignNextCommitment()
|
||||
bobNewCommit, err := chanB.SignNextCommitment()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -515,7 +516,7 @@ func ForceStateTransition(chanA, chanB *LightningChannel) error {
|
||||
if _, _, _, _, err := chanA.ReceiveRevocation(bobRevocation); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := chanA.ReceiveNewCommitment(bobSig, bobHtlcSigs); err != nil {
|
||||
if err := chanA.ReceiveNewCommitment(bobNewCommit.CommitSigs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -356,10 +356,10 @@ func testVectors(t *testing.T, chanType channeldb.ChannelType, test testCase) {
|
||||
|
||||
// Execute commit dance to arrive at the point where the local node has
|
||||
// received the test commitment and the remote signature.
|
||||
localSig, localHtlcSigs, _, err := localChannel.SignNextCommitment()
|
||||
localNewCommit, err := localChannel.SignNextCommitment()
|
||||
require.NoError(t, err, "local unable to sign commitment")
|
||||
|
||||
err = remoteChannel.ReceiveNewCommitment(localSig, localHtlcSigs)
|
||||
err = remoteChannel.ReceiveNewCommitment(localNewCommit.CommitSigs)
|
||||
require.NoError(t, err)
|
||||
|
||||
revMsg, _, _, err := remoteChannel.RevokeCurrentCommitment()
|
||||
@@ -368,18 +368,22 @@ func testVectors(t *testing.T, chanType channeldb.ChannelType, test testCase) {
|
||||
_, _, _, _, err = localChannel.ReceiveRevocation(revMsg)
|
||||
require.NoError(t, err)
|
||||
|
||||
remoteSig, remoteHtlcSigs, _, err := remoteChannel.SignNextCommitment()
|
||||
remoteNewCommit, err := remoteChannel.SignNextCommitment()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, test.RemoteSigHex,
|
||||
hex.EncodeToString(remoteSig.ToSignatureBytes()))
|
||||
require.Equal(
|
||||
t, test.RemoteSigHex,
|
||||
hex.EncodeToString(remoteNewCommit.CommitSig.ToSignatureBytes()),
|
||||
)
|
||||
|
||||
for i, sig := range remoteHtlcSigs {
|
||||
require.Equal(t, test.HtlcDescs[i].RemoteSigHex,
|
||||
hex.EncodeToString(sig.ToSignatureBytes()))
|
||||
for i, sig := range remoteNewCommit.HtlcSigs {
|
||||
require.Equal(
|
||||
t, test.HtlcDescs[i].RemoteSigHex,
|
||||
hex.EncodeToString(sig.ToSignatureBytes()),
|
||||
)
|
||||
}
|
||||
|
||||
err = localChannel.ReceiveNewCommitment(remoteSig, remoteHtlcSigs)
|
||||
err = localChannel.ReceiveNewCommitment(remoteNewCommit.CommitSigs)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, _, err = localChannel.RevokeCurrentCommitment()
|
||||
|
||||
Reference in new issue
Block a user