mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-08-31 17:51:33 +02:00
funding: fix channel type negotiation bug
The bug manifests when a nil ChannelType is passed to the funding manager in InitFundingMsg. A default value for ChannelType is selected and sent in the OpenChannel message. However, a nil ChannelType is stored in the reservation context. This causes our ChannelType checks in handleFundingAccept to be bypassed. Usually this makes us end up in the "peer unexpectedly sent explicit ChannelType" case, where we can still recover by reselecting a default ChannelType and verifying it matches the one the peer sent. But if the peer sends a nil ChannelType, we miss it. While fixing the bug, I also tried to simplify the negotiation logic, as the complexity is likely what hid the bug in the first place. Now negotiateCommitmentType only returns the ChannelType to be used in OpenChannel/AcceptChannel and the CommitmentType to pass to the wallet. It will even return a nil ChannelType when we're supposed to use implicit negotiation, so we don't need to manually set it to nil for OpenChannel and AcceptChannel.
This commit is contained in:
@@ -4493,3 +4493,62 @@ func TestCommitmentTypeFundmaxSanityCheck(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestFundingManagerNoEchoChanType tests that the funding flow is aborted if
|
||||
// the peer fails to echo back the channel type in AcceptChannel.
|
||||
func TestFundingManagerNoEchoChanType(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
alice, bob := setupFundingManagers(t)
|
||||
t.Cleanup(func() {
|
||||
tearDownFundingManagers(t, alice, bob)
|
||||
})
|
||||
|
||||
// Alice and Bob will have the same set of feature bits in our test.
|
||||
featureBits := []lnwire.FeatureBit{
|
||||
lnwire.ExplicitChannelTypeOptional,
|
||||
lnwire.StaticRemoteKeyOptional,
|
||||
lnwire.AnchorsZeroFeeHtlcTxOptional,
|
||||
}
|
||||
alice.localFeatures = featureBits
|
||||
alice.remoteFeatures = featureBits
|
||||
bob.localFeatures = featureBits
|
||||
bob.remoteFeatures = featureBits
|
||||
|
||||
expectedChanType := (*lnwire.ChannelType)(lnwire.NewRawFeatureVector(
|
||||
lnwire.StaticRemoteKeyRequired,
|
||||
lnwire.AnchorsZeroFeeHtlcTxRequired,
|
||||
))
|
||||
|
||||
// Create a funding request and start the workflow.
|
||||
updateChan := make(chan *lnrpc.OpenStatusUpdate)
|
||||
errChan := make(chan error, 1)
|
||||
initReq := &InitFundingMsg{
|
||||
Peer: bob,
|
||||
TargetPubkey: bob.privKey.PubKey(),
|
||||
ChainHash: *fundingNetParams.GenesisHash,
|
||||
LocalFundingAmt: 500000,
|
||||
Updates: updateChan,
|
||||
Err: errChan,
|
||||
}
|
||||
|
||||
alice.fundingMgr.InitFundingWorkflow(initReq)
|
||||
|
||||
// Alice should have sent the OpenChannel message to Bob.
|
||||
openChanMsg := expectOpenChannelMsg(t, alice.msgChan)
|
||||
|
||||
require.Equal(t, expectedChanType, openChanMsg.ChannelType)
|
||||
|
||||
// Let Bob handle the OpenChannel message.
|
||||
bob.fundingMgr.ProcessFundingMsg(openChanMsg, alice)
|
||||
|
||||
acceptChanMsg, _ := assertFundingMsgSent(t, bob.msgChan,
|
||||
"AcceptChannel").(*lnwire.AcceptChannel)
|
||||
|
||||
require.Equal(t, expectedChanType, acceptChanMsg.ChannelType)
|
||||
|
||||
// Drop the channel type and ensure Alice responds with an error.
|
||||
acceptChanMsg.ChannelType = nil
|
||||
alice.fundingMgr.ProcessFundingMsg(acceptChanMsg, bob)
|
||||
assertFundingMsgSent(t, alice.msgChan, "Error")
|
||||
}
|
||||
|
Reference in New Issue
Block a user