github.com/decred/dcrlnd@v0.7.6/chanbackup/single_test.go (about) 1 package chanbackup 2 3 import ( 4 "bytes" 5 "math" 6 "math/rand" 7 "net" 8 "reflect" 9 "testing" 10 11 "github.com/davecgh/go-spew/spew" 12 "github.com/decred/dcrd/chaincfg/chainhash" 13 "github.com/decred/dcrd/dcrec/secp256k1/v4" 14 "github.com/decred/dcrd/wire" 15 "github.com/decred/dcrlnd/channeldb" 16 "github.com/decred/dcrlnd/keychain" 17 "github.com/decred/dcrlnd/lnwire" 18 "github.com/decred/dcrlnd/shachain" 19 ) 20 21 var ( 22 chainHash = chainhash.Hash{ 23 0xb7, 0x94, 0x38, 0x5f, 0x2d, 0x1e, 0xf7, 0xab, 24 0x4d, 0x92, 0x73, 0xd1, 0x90, 0x63, 0x81, 0xb4, 25 0x4f, 0x2f, 0x6f, 0x25, 0x18, 0xa3, 0xef, 0xb9, 26 0x64, 0x49, 0x18, 0x83, 0x31, 0x98, 0x47, 0x53, 27 } 28 29 op = wire.OutPoint{ 30 Hash: chainHash, 31 Index: 4, 32 } 33 34 addr1, _ = net.ResolveTCPAddr("tcp", "10.0.0.2:9000") 35 addr2, _ = net.ResolveTCPAddr("tcp", "10.0.0.3:9000") 36 ) 37 38 func assertSingleEqual(t *testing.T, a, b Single) { 39 t.Helper() 40 41 if a.Version != b.Version { 42 t.Fatalf("versions don't match: %v vs %v", a.Version, 43 b.Version) 44 } 45 if a.IsInitiator != b.IsInitiator { 46 t.Fatalf("initiators don't match: %v vs %v", a.IsInitiator, 47 b.IsInitiator) 48 } 49 if a.ChainHash != b.ChainHash { 50 t.Fatalf("chainhash doesn't match: %v vs %v", a.ChainHash, 51 b.ChainHash) 52 } 53 if a.FundingOutpoint != b.FundingOutpoint { 54 t.Fatalf("chan point doesn't match: %v vs %v", 55 a.FundingOutpoint, b.FundingOutpoint) 56 } 57 if a.ShortChannelID != b.ShortChannelID { 58 t.Fatalf("chan id doesn't match: %v vs %v", 59 a.ShortChannelID, b.ShortChannelID) 60 } 61 if a.Capacity != b.Capacity { 62 t.Fatalf("capacity doesn't match: %v vs %v", 63 a.Capacity, b.Capacity) 64 } 65 if !a.RemoteNodePub.IsEqual(b.RemoteNodePub) { 66 t.Fatalf("node pubs don't match %x vs %x", 67 a.RemoteNodePub.SerializeCompressed(), 68 b.RemoteNodePub.SerializeCompressed()) 69 } 70 if !reflect.DeepEqual(a.LocalChanCfg, b.LocalChanCfg) { 71 t.Fatalf("local chan config doesn't match: %v vs %v", 72 spew.Sdump(a.LocalChanCfg), 73 spew.Sdump(b.LocalChanCfg)) 74 } 75 if !reflect.DeepEqual(a.RemoteChanCfg, b.RemoteChanCfg) { 76 t.Fatalf("remote chan config doesn't match: %v vs %v", 77 spew.Sdump(a.RemoteChanCfg), 78 spew.Sdump(b.RemoteChanCfg)) 79 } 80 if !reflect.DeepEqual(a.ShaChainRootDesc, b.ShaChainRootDesc) { 81 t.Fatalf("sha chain point doesn't match: %v vs %v", 82 spew.Sdump(a.ShaChainRootDesc), 83 spew.Sdump(b.ShaChainRootDesc)) 84 } 85 86 if len(a.Addresses) != len(b.Addresses) { 87 t.Fatalf("expected %v addrs got %v", len(a.Addresses), 88 len(b.Addresses)) 89 } 90 for i := 0; i < len(a.Addresses); i++ { 91 if a.Addresses[i].String() != b.Addresses[i].String() { 92 t.Fatalf("addr mismatch: %v vs %v", 93 a.Addresses[i], b.Addresses[i]) 94 } 95 } 96 } 97 98 func genRandomOpenChannelShell() (*channeldb.OpenChannel, error) { 99 var testPriv [32]byte 100 if _, err := rand.Read(testPriv[:]); err != nil { 101 return nil, err 102 } 103 104 pub := secp256k1.PrivKeyFromBytes(testPriv[:]).PubKey() 105 106 var chanPoint wire.OutPoint 107 if _, err := rand.Read(chanPoint.Hash[:]); err != nil { 108 return nil, err 109 } 110 111 chanPoint.Index = uint32(rand.Intn(math.MaxUint16)) 112 113 var shaChainRoot [32]byte 114 if _, err := rand.Read(shaChainRoot[:]); err != nil { 115 return nil, err 116 } 117 118 shaChainProducer := shachain.NewRevocationProducer(shaChainRoot) 119 120 var isInitiator bool 121 if rand.Int63()%2 == 0 { 122 isInitiator = true 123 } 124 125 chanType := channeldb.ChannelType(rand.Intn(8)) 126 127 return &channeldb.OpenChannel{ 128 ChainHash: chainHash, 129 ChanType: chanType, 130 IsInitiator: isInitiator, 131 FundingOutpoint: chanPoint, 132 ShortChannelID: lnwire.NewShortChanIDFromInt( 133 uint64(rand.Int63()), 134 ), 135 ThawHeight: rand.Uint32(), 136 IdentityPub: pub, 137 LocalChanCfg: channeldb.ChannelConfig{ 138 ChannelConstraints: channeldb.ChannelConstraints{ 139 CsvDelay: uint16(rand.Int63()), 140 }, 141 MultiSigKey: keychain.KeyDescriptor{ 142 KeyLocator: keychain.KeyLocator{ 143 Family: keychain.KeyFamily(rand.Int63()), 144 Index: uint32(rand.Int63()), 145 }, 146 }, 147 RevocationBasePoint: keychain.KeyDescriptor{ 148 KeyLocator: keychain.KeyLocator{ 149 Family: keychain.KeyFamily(rand.Int63()), 150 Index: uint32(rand.Int63()), 151 }, 152 }, 153 PaymentBasePoint: keychain.KeyDescriptor{ 154 KeyLocator: keychain.KeyLocator{ 155 Family: keychain.KeyFamily(rand.Int63()), 156 Index: uint32(rand.Int63()), 157 }, 158 }, 159 DelayBasePoint: keychain.KeyDescriptor{ 160 KeyLocator: keychain.KeyLocator{ 161 Family: keychain.KeyFamily(rand.Int63()), 162 Index: uint32(rand.Int63()), 163 }, 164 }, 165 HtlcBasePoint: keychain.KeyDescriptor{ 166 KeyLocator: keychain.KeyLocator{ 167 Family: keychain.KeyFamily(rand.Int63()), 168 Index: uint32(rand.Int63()), 169 }, 170 }, 171 }, 172 RemoteChanCfg: channeldb.ChannelConfig{ 173 ChannelConstraints: channeldb.ChannelConstraints{ 174 CsvDelay: uint16(rand.Int63()), 175 }, 176 MultiSigKey: keychain.KeyDescriptor{ 177 PubKey: pub, 178 }, 179 RevocationBasePoint: keychain.KeyDescriptor{ 180 PubKey: pub, 181 }, 182 PaymentBasePoint: keychain.KeyDescriptor{ 183 PubKey: pub, 184 }, 185 DelayBasePoint: keychain.KeyDescriptor{ 186 PubKey: pub, 187 }, 188 HtlcBasePoint: keychain.KeyDescriptor{ 189 PubKey: pub, 190 }, 191 }, 192 RevocationProducer: shaChainProducer, 193 }, nil 194 } 195 196 // TestSinglePackUnpack tests that we're able to unpack a previously packed 197 // channel backup. 198 func TestSinglePackUnpack(t *testing.T) { 199 t.Parallel() 200 201 // Given our test pub key, we'll create an open channel shell that 202 // contains all the information we need to create a static channel 203 // backup. 204 channel, err := genRandomOpenChannelShell() 205 if err != nil { 206 t.Fatalf("unable to gen open channel: %v", err) 207 } 208 209 singleChanBackup := NewSingle(channel, []net.Addr{addr1, addr2}) 210 211 keyRing := &mockKeyRing{} 212 213 versionTestCases := []struct { 214 // version is the pack/unpack version that we should use to 215 // decode/encode the final SCB. 216 version SingleBackupVersion 217 218 // valid tests us if this test case should pass or not. 219 valid bool 220 }{ 221 // The default version, should pack/unpack with no problem. 222 { 223 version: DefaultSingleVersion, 224 valid: true, 225 }, 226 227 // The new tweakless version, should pack/unpack with no 228 // problem. 229 { 230 version: TweaklessCommitVersion, 231 valid: true, 232 }, 233 234 // The new anchor version, should pack/unpack with no 235 // problem. 236 { 237 version: AnchorsCommitVersion, 238 valid: true, 239 }, 240 241 // The new script enforced channel lease version should 242 // pack/unpack with no problem. 243 { 244 version: ScriptEnforcedLeaseVersion, 245 valid: true, 246 }, 247 248 // A non-default version, atm this should result in a failure. 249 { 250 version: 99, 251 valid: false, 252 }, 253 } 254 for i, versionCase := range versionTestCases { 255 // First, we'll re-assign SCB version to what was indicated in 256 // the test case. 257 singleChanBackup.Version = versionCase.version 258 259 var b bytes.Buffer 260 261 err := singleChanBackup.PackToWriter(&b, keyRing) 262 switch { 263 // If this is a valid test case, and we failed, then we'll 264 // return an error. 265 case err != nil && versionCase.valid: 266 t.Fatalf("#%v, unable to pack single: %v", i, err) 267 268 // If this is an invalid test case, and we passed it, then 269 // we'll return an error. 270 case err == nil && !versionCase.valid: 271 t.Fatalf("#%v got nil error for invalid pack: %v", 272 i, err) 273 } 274 275 // If this is a valid test case, then we'll continue to ensure 276 // we can unpack it, and also that if we mutate the packed 277 // version, then we trigger an error. 278 if versionCase.valid { 279 var unpackedSingle Single 280 err = unpackedSingle.UnpackFromReader(&b, keyRing) 281 if err != nil { 282 t.Fatalf("#%v unable to unpack single: %v", 283 i, err) 284 } 285 286 assertSingleEqual(t, singleChanBackup, unpackedSingle) 287 288 // If this was a valid packing attempt, then we'll test 289 // to ensure that if we mutate the version prepended to 290 // the serialization, then unpacking will fail as well. 291 var rawSingle bytes.Buffer 292 err := unpackedSingle.Serialize(&rawSingle) 293 if err != nil { 294 t.Fatalf("unable to serialize single: %v", err) 295 } 296 297 // Mutate the version byte to an unknown version. 298 rawBytes := rawSingle.Bytes() 299 rawBytes[0] = ^uint8(0) 300 301 newReader := bytes.NewReader(rawBytes) 302 err = unpackedSingle.Deserialize(newReader) 303 if err == nil { 304 t.Fatalf("#%v unpack with unknown version "+ 305 "should have failed", i) 306 } 307 } 308 } 309 } 310 311 // TestPackedSinglesUnpack tests that we're able to properly unpack a series of 312 // packed singles. 313 func TestPackedSinglesUnpack(t *testing.T) { 314 t.Parallel() 315 316 keyRing := &mockKeyRing{} 317 318 // To start, we'll create 10 new singles, and them assemble their 319 // packed forms into a slice. 320 numSingles := 10 321 packedSingles := make([][]byte, 0, numSingles) 322 unpackedSingles := make([]Single, 0, numSingles) 323 for i := 0; i < numSingles; i++ { 324 channel, err := genRandomOpenChannelShell() 325 if err != nil { 326 t.Fatalf("unable to gen channel: %v", err) 327 } 328 329 single := NewSingle(channel, nil) 330 331 var b bytes.Buffer 332 if err := single.PackToWriter(&b, keyRing); err != nil { 333 t.Fatalf("unable to pack single: %v", err) 334 } 335 336 packedSingles = append(packedSingles, b.Bytes()) 337 unpackedSingles = append(unpackedSingles, single) 338 } 339 340 // With all singles packed, we'll create the grouped type and attempt 341 // to Unpack all of them in a single go. 342 freshSingles, err := PackedSingles(packedSingles).Unpack(keyRing) 343 if err != nil { 344 t.Fatalf("unable to unpack singles: %v", err) 345 } 346 347 // The set of freshly unpacked singles should exactly match the initial 348 // set of singles that we packed before. 349 for i := 0; i < len(unpackedSingles); i++ { 350 assertSingleEqual(t, unpackedSingles[i], freshSingles[i]) 351 } 352 353 // If we mutate one of the packed singles, then the entire method 354 // should fail. 355 packedSingles[0][0] ^= 1 356 _, err = PackedSingles(packedSingles).Unpack(keyRing) 357 if err == nil { 358 t.Fatalf("unpack attempt should fail") 359 } 360 } 361 362 // TestSinglePackStaticChanBackups tests that we're able to batch pack a set of 363 // Singles, and then unpack them obtaining the same set of unpacked singles. 364 func TestSinglePackStaticChanBackups(t *testing.T) { 365 t.Parallel() 366 367 keyRing := &mockKeyRing{} 368 369 // First, we'll create a set of random single, and along the way, 370 // create a map that will let us look up each single by its chan point. 371 numSingles := 10 372 singleMap := make(map[wire.OutPoint]Single, numSingles) 373 unpackedSingles := make([]Single, 0, numSingles) 374 for i := 0; i < numSingles; i++ { 375 channel, err := genRandomOpenChannelShell() 376 if err != nil { 377 t.Fatalf("unable to gen channel: %v", err) 378 } 379 380 single := NewSingle(channel, nil) 381 382 singleMap[channel.FundingOutpoint] = single 383 unpackedSingles = append(unpackedSingles, single) 384 } 385 386 // Now that we have all of our singles are created, we'll attempt to 387 // pack them all in a single batch. 388 packedSingleMap, err := PackStaticChanBackups(unpackedSingles, keyRing) 389 if err != nil { 390 t.Fatalf("unable to pack backups: %v", err) 391 } 392 393 // With our packed singles obtained, we'll ensure that each of them 394 // match their unpacked counterparts after they themselves have been 395 // unpacked. 396 for chanPoint, single := range singleMap { 397 packedSingles, ok := packedSingleMap[chanPoint] 398 if !ok { 399 t.Fatalf("unable to find single %v", chanPoint) 400 } 401 402 var freshSingle Single 403 err := freshSingle.UnpackFromReader( 404 bytes.NewReader(packedSingles), keyRing, 405 ) 406 if err != nil { 407 t.Fatalf("unable to unpack single: %v", err) 408 } 409 410 assertSingleEqual(t, single, freshSingle) 411 } 412 413 // If we attempt to pack again, but force the key ring to fail, then 414 // the entire method should fail. 415 _, err = PackStaticChanBackups( 416 unpackedSingles, &mockKeyRing{true}, 417 ) 418 if err == nil { 419 t.Fatalf("pack attempt should fail") 420 } 421 } 422 423 // TestSingleUnconfirmedChannel tests that unconfirmed channels get serialized 424 // correctly by encoding the funding broadcast height as block height of the 425 // short channel ID. 426 func TestSingleUnconfirmedChannel(t *testing.T) { 427 t.Parallel() 428 429 var fundingBroadcastHeight = uint32(1234) 430 431 // Let's create an open channel shell that contains all the information 432 // we need to create a static channel backup but simulate an 433 // unconfirmed channel by setting the block height to 0. 434 channel, err := genRandomOpenChannelShell() 435 if err != nil { 436 t.Fatalf("unable to gen open channel: %v", err) 437 } 438 channel.ShortChannelID.BlockHeight = 0 439 channel.FundingBroadcastHeight = fundingBroadcastHeight 440 441 singleChanBackup := NewSingle(channel, []net.Addr{addr1, addr2}) 442 keyRing := &mockKeyRing{} 443 444 // Pack it and then unpack it again to make sure everything is written 445 // correctly, then check that the block height of the unpacked 446 // is the funding broadcast height we set before. 447 var b bytes.Buffer 448 if err := singleChanBackup.PackToWriter(&b, keyRing); err != nil { 449 t.Fatalf("unable to pack single: %v", err) 450 } 451 var unpackedSingle Single 452 err = unpackedSingle.UnpackFromReader(&b, keyRing) 453 if err != nil { 454 t.Fatalf("unable to unpack single: %v", err) 455 } 456 if unpackedSingle.ShortChannelID.BlockHeight != fundingBroadcastHeight { 457 t.Fatalf("invalid block height. got %d expected %d.", 458 unpackedSingle.ShortChannelID.BlockHeight, 459 fundingBroadcastHeight) 460 } 461 } 462 463 // TODO(roasbsef): fuzz parsing