github.com/decred/dcrlnd@v0.7.6/funding/commitment_type_negotiation_test.go (about) 1 package funding 2 3 import ( 4 "testing" 5 6 "github.com/decred/dcrlnd/lnwallet" 7 "github.com/decred/dcrlnd/lnwire" 8 "github.com/stretchr/testify/require" 9 ) 10 11 // TestCommitmentTypeNegotiation tests all of the possible paths of a channel 12 // commitment type negotiation. 13 func TestCommitmentTypeNegotiation(t *testing.T) { 14 t.Parallel() 15 16 testCases := []struct { 17 name string 18 mustBeExplicit bool 19 channelFeatures *lnwire.RawFeatureVector 20 localFeatures *lnwire.RawFeatureVector 21 remoteFeatures *lnwire.RawFeatureVector 22 expectsCommitType lnwallet.CommitmentType 23 expectsChanType lnwire.ChannelType 24 expectsErr error 25 }{ 26 { 27 name: "explicit missing remote negotiation feature", 28 channelFeatures: lnwire.NewRawFeatureVector( 29 lnwire.StaticRemoteKeyRequired, 30 lnwire.AnchorsZeroFeeHtlcTxRequired, 31 ), 32 localFeatures: lnwire.NewRawFeatureVector( 33 lnwire.StaticRemoteKeyOptional, 34 lnwire.AnchorsZeroFeeHtlcTxOptional, 35 lnwire.ExplicitChannelTypeOptional, 36 ), 37 remoteFeatures: lnwire.NewRawFeatureVector( 38 lnwire.StaticRemoteKeyOptional, 39 lnwire.AnchorsZeroFeeHtlcTxOptional, 40 ), 41 expectsCommitType: lnwallet.CommitmentTypeAnchorsZeroFeeHtlcTx, 42 expectsChanType: lnwire.ChannelType(*lnwire.NewRawFeatureVector( 43 lnwire.StaticRemoteKeyRequired, 44 lnwire.AnchorsZeroFeeHtlcTxRequired, 45 )), 46 expectsErr: nil, 47 }, 48 { 49 name: "local funder wants explicit, remote doesn't " + 50 "support so fall back", 51 mustBeExplicit: true, 52 channelFeatures: lnwire.NewRawFeatureVector( 53 lnwire.StaticRemoteKeyRequired, 54 lnwire.AnchorsZeroFeeHtlcTxRequired, 55 ), 56 localFeatures: lnwire.NewRawFeatureVector( 57 lnwire.StaticRemoteKeyOptional, 58 lnwire.AnchorsZeroFeeHtlcTxOptional, 59 lnwire.ExplicitChannelTypeOptional, 60 ), 61 remoteFeatures: lnwire.NewRawFeatureVector( 62 lnwire.StaticRemoteKeyOptional, 63 lnwire.AnchorsZeroFeeHtlcTxOptional, 64 ), 65 expectsErr: errUnsupportedExplicitNegotiation, 66 }, 67 { 68 name: "explicit missing remote commitment feature", 69 channelFeatures: lnwire.NewRawFeatureVector( 70 lnwire.StaticRemoteKeyRequired, 71 lnwire.AnchorsZeroFeeHtlcTxRequired, 72 ), 73 localFeatures: lnwire.NewRawFeatureVector( 74 lnwire.StaticRemoteKeyOptional, 75 lnwire.AnchorsZeroFeeHtlcTxOptional, 76 lnwire.ExplicitChannelTypeOptional, 77 ), 78 remoteFeatures: lnwire.NewRawFeatureVector( 79 lnwire.StaticRemoteKeyOptional, 80 lnwire.ExplicitChannelTypeOptional, 81 ), 82 expectsErr: errUnsupportedChannelType, 83 }, 84 { 85 name: "explicit anchors", 86 channelFeatures: lnwire.NewRawFeatureVector( 87 lnwire.StaticRemoteKeyRequired, 88 lnwire.AnchorsZeroFeeHtlcTxRequired, 89 ), 90 localFeatures: lnwire.NewRawFeatureVector( 91 lnwire.StaticRemoteKeyOptional, 92 lnwire.AnchorsZeroFeeHtlcTxOptional, 93 lnwire.ExplicitChannelTypeOptional, 94 ), 95 remoteFeatures: lnwire.NewRawFeatureVector( 96 lnwire.StaticRemoteKeyOptional, 97 lnwire.AnchorsZeroFeeHtlcTxOptional, 98 lnwire.ExplicitChannelTypeOptional, 99 ), 100 expectsCommitType: lnwallet.CommitmentTypeAnchorsZeroFeeHtlcTx, 101 expectsChanType: lnwire.ChannelType(*lnwire.NewRawFeatureVector( 102 lnwire.StaticRemoteKeyRequired, 103 lnwire.AnchorsZeroFeeHtlcTxRequired, 104 )), 105 expectsErr: nil, 106 }, 107 { 108 name: "explicit tweakless", 109 channelFeatures: lnwire.NewRawFeatureVector( 110 lnwire.StaticRemoteKeyRequired, 111 ), 112 localFeatures: lnwire.NewRawFeatureVector( 113 lnwire.StaticRemoteKeyOptional, 114 lnwire.AnchorsZeroFeeHtlcTxOptional, 115 lnwire.ExplicitChannelTypeOptional, 116 ), 117 remoteFeatures: lnwire.NewRawFeatureVector( 118 lnwire.StaticRemoteKeyOptional, 119 lnwire.AnchorsZeroFeeHtlcTxOptional, 120 lnwire.ExplicitChannelTypeOptional, 121 ), 122 expectsCommitType: lnwallet.CommitmentTypeTweakless, 123 expectsChanType: lnwire.ChannelType(*lnwire.NewRawFeatureVector( 124 lnwire.StaticRemoteKeyRequired, 125 )), 126 expectsErr: nil, 127 }, 128 { 129 name: "explicit legacy", 130 channelFeatures: lnwire.NewRawFeatureVector(), 131 localFeatures: lnwire.NewRawFeatureVector( 132 lnwire.StaticRemoteKeyOptional, 133 lnwire.AnchorsZeroFeeHtlcTxOptional, 134 lnwire.ExplicitChannelTypeOptional, 135 ), 136 remoteFeatures: lnwire.NewRawFeatureVector( 137 lnwire.StaticRemoteKeyOptional, 138 lnwire.AnchorsZeroFeeHtlcTxOptional, 139 lnwire.ExplicitChannelTypeOptional, 140 ), 141 expectsCommitType: lnwallet.CommitmentTypeLegacy, 142 expectsChanType: lnwire.ChannelType(*lnwire.NewRawFeatureVector()), 143 expectsErr: nil, 144 }, 145 // Both sides signal the explicit chan type bit, so we expect 146 // that we return the corresponding chan type feature bits, 147 // even though we didn't set an explicit channel type. 148 { 149 name: "implicit anchors", 150 channelFeatures: nil, 151 localFeatures: lnwire.NewRawFeatureVector( 152 lnwire.StaticRemoteKeyOptional, 153 lnwire.AnchorsZeroFeeHtlcTxOptional, 154 lnwire.ExplicitChannelTypeOptional, 155 ), 156 remoteFeatures: lnwire.NewRawFeatureVector( 157 lnwire.StaticRemoteKeyOptional, 158 lnwire.AnchorsZeroFeeHtlcTxOptional, 159 lnwire.ExplicitChannelTypeOptional, 160 ), 161 expectsCommitType: lnwallet.CommitmentTypeAnchorsZeroFeeHtlcTx, 162 expectsChanType: lnwire.ChannelType(*lnwire.NewRawFeatureVector( 163 lnwire.StaticRemoteKeyRequired, 164 lnwire.AnchorsZeroFeeHtlcTxRequired, 165 )), 166 expectsErr: nil, 167 }, 168 { 169 name: "implicit tweakless", 170 channelFeatures: nil, 171 localFeatures: lnwire.NewRawFeatureVector( 172 lnwire.StaticRemoteKeyOptional, 173 lnwire.AnchorsZeroFeeHtlcTxOptional, 174 ), 175 remoteFeatures: lnwire.NewRawFeatureVector( 176 lnwire.StaticRemoteKeyOptional, 177 ), 178 expectsCommitType: lnwallet.CommitmentTypeTweakless, 179 expectsChanType: lnwire.ChannelType(*lnwire.NewRawFeatureVector( 180 lnwire.StaticRemoteKeyRequired, 181 )), 182 expectsErr: nil, 183 }, 184 { 185 name: "implicit legacy", 186 channelFeatures: nil, 187 localFeatures: lnwire.NewRawFeatureVector(), 188 remoteFeatures: lnwire.NewRawFeatureVector( 189 lnwire.StaticRemoteKeyOptional, 190 lnwire.AnchorsZeroFeeHtlcTxOptional, 191 ), 192 expectsCommitType: lnwallet.CommitmentTypeLegacy, 193 expectsChanType: lnwire.ChannelType(*lnwire.NewRawFeatureVector()), 194 expectsErr: nil, 195 }, 196 } 197 198 for _, testCase := range testCases { 199 testCase := testCase 200 ok := t.Run(testCase.name, func(t *testing.T) { 201 localFeatures := lnwire.NewFeatureVector( 202 testCase.localFeatures, lnwire.Features, 203 ) 204 remoteFeatures := lnwire.NewFeatureVector( 205 testCase.remoteFeatures, lnwire.Features, 206 ) 207 208 var channelType *lnwire.ChannelType 209 if testCase.channelFeatures != nil { 210 channelType = new(lnwire.ChannelType) 211 *channelType = lnwire.ChannelType( 212 *testCase.channelFeatures, 213 ) 214 } 215 _, localChanType, localCommitType, err := negotiateCommitmentType( 216 channelType, localFeatures, remoteFeatures, 217 testCase.mustBeExplicit, 218 ) 219 require.Equal(t, testCase.expectsErr, err) 220 221 _, remoteChanType, remoteCommitType, err := negotiateCommitmentType( 222 channelType, remoteFeatures, localFeatures, 223 testCase.mustBeExplicit, 224 ) 225 require.Equal(t, testCase.expectsErr, err) 226 227 if testCase.expectsErr != nil { 228 return 229 } 230 231 require.Equal( 232 t, testCase.expectsCommitType, localCommitType, 233 testCase.name, 234 ) 235 require.Equal( 236 t, testCase.expectsCommitType, remoteCommitType, 237 testCase.name, 238 ) 239 240 require.Equal( 241 t, testCase.expectsChanType, *localChanType, 242 testCase.name, 243 ) 244 require.Equal( 245 t, testCase.expectsChanType, *remoteChanType, 246 testCase.name, 247 ) 248 }) 249 if !ok { 250 return 251 } 252 } 253 }