github.com/decred/dcrlnd@v0.7.6/peer/brontide_test.go (about) 1 package peer 2 3 import ( 4 "bytes" 5 "io/ioutil" 6 "testing" 7 "time" 8 9 "github.com/decred/dcrd/chaincfg/v3" 10 "github.com/decred/dcrd/dcrec/secp256k1/v4" 11 "github.com/decred/dcrd/dcrutil/v4" 12 "github.com/decred/dcrd/txscript/v4/stdaddr" 13 "github.com/decred/dcrd/wire" 14 "github.com/decred/dcrlnd/chainntnfs" 15 "github.com/decred/dcrlnd/channeldb" 16 "github.com/decred/dcrlnd/contractcourt" 17 "github.com/decred/dcrlnd/htlcswitch" 18 "github.com/decred/dcrlnd/input" 19 "github.com/decred/dcrlnd/lntest/mock" 20 "github.com/decred/dcrlnd/lnwallet/chancloser" 21 "github.com/decred/dcrlnd/lnwire" 22 "github.com/decred/dcrlnd/pool" 23 "github.com/stretchr/testify/assert" 24 "github.com/stretchr/testify/require" 25 ) 26 27 var ( 28 // p2SHAddress is a valid pay to script hash address. 29 p2SHAddress = "TcrypGAcGCRVXrES7hWqVZb5oLJKCZEtoL1" 30 31 // p2pkhAddress is a valid pay to public key hash address. 32 p2PKHAddress = "TsYJk2CWpEjcwgHMcJjva3sDCKZgCMFQvj2" 33 ) 34 35 // TestPeerChannelClosureAcceptFeeResponder tests the shutdown responder's 36 // behavior if we can agree on the fee immediately. 37 func TestPeerChannelClosureAcceptFeeResponder(t *testing.T) { 38 t.Parallel() 39 40 notifier := &mock.ChainNotifier{ 41 SpendChan: make(chan *chainntnfs.SpendDetail), 42 EpochChan: make(chan *chainntnfs.BlockEpoch), 43 ConfChan: make(chan *chainntnfs.TxConfirmation), 44 } 45 broadcastTxChan := make(chan *wire.MsgTx) 46 47 mockSwitch := &mockMessageSwitch{} 48 49 alicePeer, bobChan, cleanUp, err := createTestPeer( 50 notifier, broadcastTxChan, noUpdate, mockSwitch, 51 ) 52 if err != nil { 53 t.Fatalf("unable to create test channels: %v", err) 54 } 55 defer cleanUp() 56 57 chanID := lnwire.NewChanIDFromOutPoint(bobChan.ChannelPoint()) 58 59 mockLink := newMockUpdateHandler(chanID) 60 mockSwitch.links = append(mockSwitch.links, mockLink) 61 62 // We send a shutdown request to Alice. She will now be the responding 63 // node in this shutdown procedure. We first expect Alice to answer 64 // this shutdown request with a Shutdown message. 65 alicePeer.chanCloseMsgs <- &closeMsg{ 66 cid: chanID, 67 msg: lnwire.NewShutdown(chanID, dummyDeliveryScript), 68 } 69 70 var msg lnwire.Message 71 select { 72 case outMsg := <-alicePeer.outgoingQueue: 73 msg = outMsg.msg 74 case <-time.After(timeout): 75 t.Fatalf("did not receive shutdown message") 76 } 77 78 shutdownMsg, ok := msg.(*lnwire.Shutdown) 79 if !ok { 80 t.Fatalf("expected Shutdown message, got %T", msg) 81 } 82 83 respDeliveryScript := shutdownMsg.Address 84 85 // Alice will then send a ClosingSigned message, indicating her proposed 86 // closing transaction fee. Alice sends the ClosingSigned message as she is 87 // the initiator of the channel. 88 select { 89 case outMsg := <-alicePeer.outgoingQueue: 90 msg = outMsg.msg 91 case <-time.After(timeout): 92 t.Fatalf("did not receive ClosingSigned message") 93 } 94 95 respClosingSigned, ok := msg.(*lnwire.ClosingSigned) 96 if !ok { 97 t.Fatalf("expected ClosingSigned message, got %T", msg) 98 } 99 100 // We accept the fee, and send a ClosingSigned with the same fee back, 101 // so she knows we agreed. 102 aliceFee := respClosingSigned.FeeAtoms 103 bobSig, _, _, err := bobChan.CreateCloseProposal( 104 aliceFee, dummyDeliveryScript, respDeliveryScript, 105 ) 106 if err != nil { 107 t.Fatalf("error creating close proposal: %v", err) 108 } 109 110 parsedSig, err := lnwire.NewSigFromSignature(bobSig) 111 if err != nil { 112 t.Fatalf("error parsing signature: %v", err) 113 } 114 closingSigned := lnwire.NewClosingSigned(chanID, aliceFee, parsedSig) 115 alicePeer.chanCloseMsgs <- &closeMsg{ 116 cid: chanID, 117 msg: closingSigned, 118 } 119 120 // Alice should now see that we agreed on the fee, and should broadcast the 121 // closing transaction. 122 select { 123 case <-broadcastTxChan: 124 case <-time.After(timeout): 125 t.Fatalf("closing tx not broadcast") 126 } 127 128 // Need to pull the remaining message off of Alice's outgoing queue. 129 select { 130 case outMsg := <-alicePeer.outgoingQueue: 131 msg = outMsg.msg 132 case <-time.After(timeout): 133 t.Fatalf("did not receive ClosingSigned message") 134 } 135 if _, ok := msg.(*lnwire.ClosingSigned); !ok { 136 t.Fatalf("expected ClosingSigned message, got %T", msg) 137 } 138 139 // Alice should be waiting in a goroutine for a confirmation. 140 notifier.ConfChan <- &chainntnfs.TxConfirmation{} 141 } 142 143 // TestPeerChannelClosureAcceptFeeInitiator tests the shutdown initiator's 144 // behavior if we can agree on the fee immediately. 145 func TestPeerChannelClosureAcceptFeeInitiator(t *testing.T) { 146 t.Parallel() 147 148 notifier := &mock.ChainNotifier{ 149 SpendChan: make(chan *chainntnfs.SpendDetail), 150 EpochChan: make(chan *chainntnfs.BlockEpoch), 151 ConfChan: make(chan *chainntnfs.TxConfirmation), 152 } 153 broadcastTxChan := make(chan *wire.MsgTx) 154 155 mockSwitch := &mockMessageSwitch{} 156 157 alicePeer, bobChan, cleanUp, err := createTestPeer( 158 notifier, broadcastTxChan, noUpdate, mockSwitch, 159 ) 160 if err != nil { 161 t.Fatalf("unable to create test channels: %v", err) 162 } 163 defer cleanUp() 164 165 chanID := lnwire.NewChanIDFromOutPoint(bobChan.ChannelPoint()) 166 mockLink := newMockUpdateHandler(chanID) 167 mockSwitch.links = append(mockSwitch.links, mockLink) 168 169 // We make Alice send a shutdown request. 170 updateChan := make(chan interface{}, 1) 171 errChan := make(chan error, 1) 172 closeCommand := &htlcswitch.ChanClose{ 173 CloseType: contractcourt.CloseRegular, 174 ChanPoint: bobChan.ChannelPoint(), 175 Updates: updateChan, 176 TargetFeePerKB: 12500, 177 Err: errChan, 178 } 179 alicePeer.localCloseChanReqs <- closeCommand 180 181 // We can now pull a Shutdown message off of Alice's outgoingQueue. 182 var msg lnwire.Message 183 select { 184 case outMsg := <-alicePeer.outgoingQueue: 185 msg = outMsg.msg 186 case <-time.After(timeout): 187 t.Fatalf("did not receive shutdown request") 188 } 189 190 shutdownMsg, ok := msg.(*lnwire.Shutdown) 191 if !ok { 192 t.Fatalf("expected Shutdown message, got %T", msg) 193 } 194 195 aliceDeliveryScript := shutdownMsg.Address 196 197 // Bob will respond with his own Shutdown message. 198 alicePeer.chanCloseMsgs <- &closeMsg{ 199 cid: chanID, 200 msg: lnwire.NewShutdown(chanID, 201 dummyDeliveryScript), 202 } 203 204 // Alice will reply with a ClosingSigned here. 205 select { 206 case outMsg := <-alicePeer.outgoingQueue: 207 msg = outMsg.msg 208 case <-time.After(timeout): 209 t.Fatalf("did not receive closing signed message") 210 } 211 closingSignedMsg, ok := msg.(*lnwire.ClosingSigned) 212 if !ok { 213 t.Fatalf("expected to receive closing signed message, got %T", msg) 214 } 215 216 // Bob should reply with the exact same fee in his next ClosingSigned 217 // message. 218 bobFee := closingSignedMsg.FeeAtoms 219 bobSig, _, _, err := bobChan.CreateCloseProposal( 220 bobFee, dummyDeliveryScript, aliceDeliveryScript, 221 ) 222 if err != nil { 223 t.Fatalf("unable to create close proposal: %v", err) 224 } 225 parsedSig, err := lnwire.NewSigFromSignature(bobSig) 226 if err != nil { 227 t.Fatalf("unable to parse signature: %v", err) 228 } 229 230 closingSigned := lnwire.NewClosingSigned(shutdownMsg.ChannelID, 231 bobFee, parsedSig) 232 alicePeer.chanCloseMsgs <- &closeMsg{ 233 cid: chanID, 234 msg: closingSigned, 235 } 236 237 // Alice should accept Bob's fee, broadcast the cooperative close tx, and 238 // send a ClosingSigned message back to Bob. 239 240 // Alice should now broadcast the closing transaction. 241 select { 242 case <-broadcastTxChan: 243 case <-time.After(timeout): 244 t.Fatalf("closing tx not broadcast") 245 } 246 247 // Alice should respond with the ClosingSigned they both agreed upon. 248 select { 249 case outMsg := <-alicePeer.outgoingQueue: 250 msg = outMsg.msg 251 case <-time.After(timeout): 252 t.Fatalf("did not receive closing signed message") 253 } 254 255 closingSignedMsg, ok = msg.(*lnwire.ClosingSigned) 256 if !ok { 257 t.Fatalf("expected ClosingSigned message, got %T", msg) 258 } 259 260 if closingSignedMsg.FeeAtoms != bobFee { 261 t.Fatalf("expected ClosingSigned fee to be %v, instead got %v", 262 bobFee, closingSignedMsg.FeeAtoms) 263 } 264 265 // Alice should be waiting on a single confirmation for the coop close tx. 266 notifier.ConfChan <- &chainntnfs.TxConfirmation{} 267 } 268 269 // TestPeerChannelClosureFeeNegotiationsResponder tests the shutdown 270 // responder's behavior in the case where we must do several rounds of fee 271 // negotiation before we agree on a fee. 272 func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) { 273 t.Parallel() 274 275 notifier := &mock.ChainNotifier{ 276 SpendChan: make(chan *chainntnfs.SpendDetail), 277 EpochChan: make(chan *chainntnfs.BlockEpoch), 278 ConfChan: make(chan *chainntnfs.TxConfirmation), 279 } 280 broadcastTxChan := make(chan *wire.MsgTx) 281 282 mockSwitch := &mockMessageSwitch{} 283 284 alicePeer, bobChan, cleanUp, err := createTestPeer( 285 notifier, broadcastTxChan, noUpdate, mockSwitch, 286 ) 287 if err != nil { 288 t.Fatalf("unable to create test channels: %v", err) 289 } 290 defer cleanUp() 291 292 chanID := lnwire.NewChanIDFromOutPoint(bobChan.ChannelPoint()) 293 294 mockLink := newMockUpdateHandler(chanID) 295 mockSwitch.links = append(mockSwitch.links, mockLink) 296 297 // Bob sends a shutdown request to Alice. She will now be the responding 298 // node in this shutdown procedure. We first expect Alice to answer this 299 // Shutdown request with a Shutdown message. 300 alicePeer.chanCloseMsgs <- &closeMsg{ 301 cid: chanID, 302 msg: lnwire.NewShutdown(chanID, 303 dummyDeliveryScript), 304 } 305 306 var msg lnwire.Message 307 select { 308 case outMsg := <-alicePeer.outgoingQueue: 309 msg = outMsg.msg 310 case <-time.After(timeout): 311 t.Fatalf("did not receive shutdown message") 312 } 313 314 shutdownMsg, ok := msg.(*lnwire.Shutdown) 315 if !ok { 316 t.Fatalf("expected Shutdown message, got %T", msg) 317 } 318 319 aliceDeliveryScript := shutdownMsg.Address 320 321 // As Alice is the channel initiator, she will send her ClosingSigned 322 // message. 323 select { 324 case outMsg := <-alicePeer.outgoingQueue: 325 msg = outMsg.msg 326 case <-time.After(timeout): 327 t.Fatalf("did not receive closing signed message") 328 } 329 330 aliceClosingSigned, ok := msg.(*lnwire.ClosingSigned) 331 if !ok { 332 t.Fatalf("expected ClosingSigned message, got %T", msg) 333 } 334 335 // Bob doesn't agree with the fee and will send one back that's 2.5x. 336 preferredRespFee := aliceClosingSigned.FeeAtoms 337 increasedFee := dcrutil.Amount(float64(preferredRespFee) * 2.5) 338 bobSig, _, _, err := bobChan.CreateCloseProposal( 339 increasedFee, dummyDeliveryScript, aliceDeliveryScript, 340 ) 341 if err != nil { 342 t.Fatalf("error creating close proposal: %v", err) 343 } 344 345 parsedSig, err := lnwire.NewSigFromSignature(bobSig) 346 if err != nil { 347 t.Fatalf("error parsing signature: %v", err) 348 } 349 closingSigned := lnwire.NewClosingSigned(chanID, increasedFee, parsedSig) 350 alicePeer.chanCloseMsgs <- &closeMsg{ 351 cid: chanID, 352 msg: closingSigned, 353 } 354 355 // Alice will now see the new fee we propose, but with current settings it 356 // won't accept it immediately as it differs too much by its ideal fee. We 357 // should get a new proposal back, which should have the average fee rate 358 // proposed. 359 select { 360 case outMsg := <-alicePeer.outgoingQueue: 361 msg = outMsg.msg 362 case <-time.After(timeout): 363 t.Fatalf("did not receive closing signed message") 364 } 365 366 aliceClosingSigned, ok = msg.(*lnwire.ClosingSigned) 367 if !ok { 368 t.Fatalf("expected ClosingSigned message, got %T", msg) 369 } 370 371 // The fee sent by Alice should be less than the fee Bob just sent as 372 // Alice should attempt to compromise. 373 aliceFee := aliceClosingSigned.FeeAtoms 374 if aliceFee > increasedFee { 375 t.Fatalf("new fee should be less than our fee: new=%v, "+ 376 "prior=%v", aliceFee, increasedFee) 377 } 378 lastFeeResponder := aliceFee 379 380 // We try negotiating a 2.1x fee, which should also be rejected. 381 increasedFee = dcrutil.Amount(float64(preferredRespFee) * 2.1) 382 bobSig, _, _, err = bobChan.CreateCloseProposal( 383 increasedFee, dummyDeliveryScript, aliceDeliveryScript, 384 ) 385 if err != nil { 386 t.Fatalf("error creating close proposal: %v", err) 387 } 388 389 parsedSig, err = lnwire.NewSigFromSignature(bobSig) 390 if err != nil { 391 t.Fatalf("error parsing signature: %v", err) 392 } 393 closingSigned = lnwire.NewClosingSigned(chanID, increasedFee, parsedSig) 394 alicePeer.chanCloseMsgs <- &closeMsg{ 395 cid: chanID, 396 msg: closingSigned, 397 } 398 399 // Bob's latest proposal still won't be accepted and Alice should send over 400 // a new ClosingSigned message. It should be the average of what Bob and 401 // Alice each proposed last time. 402 select { 403 case outMsg := <-alicePeer.outgoingQueue: 404 msg = outMsg.msg 405 case <-time.After(timeout): 406 t.Fatalf("did not receive closing signed message") 407 } 408 409 aliceClosingSigned, ok = msg.(*lnwire.ClosingSigned) 410 if !ok { 411 t.Fatalf("expected ClosingSigned message, got %T", msg) 412 } 413 414 // Alice should inch towards Bob's fee, in order to compromise. 415 // Additionally, this fee should be less than the fee Bob sent before. 416 aliceFee = aliceClosingSigned.FeeAtoms 417 if aliceFee < lastFeeResponder { 418 t.Fatalf("new fee should be greater than prior: new=%v, "+ 419 "prior=%v", aliceFee, lastFeeResponder) 420 } 421 if aliceFee > increasedFee { 422 t.Fatalf("new fee should be less than Bob's fee: new=%v, "+ 423 "prior=%v", aliceFee, increasedFee) 424 } 425 426 // Finally, Bob will accept the fee by echoing back the same fee that Alice 427 // just sent over. 428 bobSig, _, _, err = bobChan.CreateCloseProposal( 429 aliceFee, dummyDeliveryScript, aliceDeliveryScript, 430 ) 431 if err != nil { 432 t.Fatalf("error creating close proposal: %v", err) 433 } 434 435 parsedSig, err = lnwire.NewSigFromSignature(bobSig) 436 if err != nil { 437 t.Fatalf("error parsing signature: %v", err) 438 } 439 closingSigned = lnwire.NewClosingSigned(chanID, aliceFee, parsedSig) 440 alicePeer.chanCloseMsgs <- &closeMsg{ 441 cid: chanID, 442 msg: closingSigned, 443 } 444 445 // Alice will now see that Bob agreed on the fee, and broadcast the coop 446 // close transaction. 447 select { 448 case <-broadcastTxChan: 449 case <-time.After(timeout): 450 t.Fatalf("closing tx not broadcast") 451 } 452 453 // Alice should respond with the ClosingSigned they both agreed upon. 454 select { 455 case outMsg := <-alicePeer.outgoingQueue: 456 msg = outMsg.msg 457 case <-time.After(timeout): 458 t.Fatalf("did not receive closing signed message") 459 } 460 if _, ok := msg.(*lnwire.ClosingSigned); !ok { 461 t.Fatalf("expected to receive closing signed message, got %T", msg) 462 } 463 464 // Alice should be waiting on a single confirmation for the coop close tx. 465 notifier.ConfChan <- &chainntnfs.TxConfirmation{} 466 } 467 468 // TestPeerChannelClosureFeeNegotiationsInitiator tests the shutdown 469 // initiator's behavior in the case where we must do several rounds of fee 470 // negotiation before we agree on a fee. 471 func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) { 472 t.Parallel() 473 474 notifier := &mock.ChainNotifier{ 475 SpendChan: make(chan *chainntnfs.SpendDetail), 476 EpochChan: make(chan *chainntnfs.BlockEpoch), 477 ConfChan: make(chan *chainntnfs.TxConfirmation), 478 } 479 broadcastTxChan := make(chan *wire.MsgTx) 480 481 mockSwitch := &mockMessageSwitch{} 482 483 alicePeer, bobChan, cleanUp, err := createTestPeer( 484 notifier, broadcastTxChan, noUpdate, mockSwitch, 485 ) 486 if err != nil { 487 t.Fatalf("unable to create test channels: %v", err) 488 } 489 defer cleanUp() 490 491 chanID := lnwire.NewChanIDFromOutPoint(bobChan.ChannelPoint()) 492 mockLink := newMockUpdateHandler(chanID) 493 mockSwitch.links = append(mockSwitch.links, mockLink) 494 495 // We make the initiator send a shutdown request. 496 updateChan := make(chan interface{}, 1) 497 errChan := make(chan error, 1) 498 closeCommand := &htlcswitch.ChanClose{ 499 CloseType: contractcourt.CloseRegular, 500 ChanPoint: bobChan.ChannelPoint(), 501 Updates: updateChan, 502 TargetFeePerKB: 12500, 503 Err: errChan, 504 } 505 506 alicePeer.localCloseChanReqs <- closeCommand 507 508 // Alice should now send a Shutdown request to Bob. 509 var msg lnwire.Message 510 select { 511 case outMsg := <-alicePeer.outgoingQueue: 512 msg = outMsg.msg 513 case <-time.After(timeout): 514 t.Fatalf("did not receive shutdown request") 515 } 516 517 shutdownMsg, ok := msg.(*lnwire.Shutdown) 518 if !ok { 519 t.Fatalf("expected Shutdown message, got %T", msg) 520 } 521 522 aliceDeliveryScript := shutdownMsg.Address 523 524 // Bob will answer the Shutdown message with his own Shutdown. 525 respShutdown := lnwire.NewShutdown(chanID, dummyDeliveryScript) 526 alicePeer.chanCloseMsgs <- &closeMsg{ 527 cid: chanID, 528 msg: respShutdown, 529 } 530 531 // Alice should now respond with a ClosingSigned message with her ideal 532 // fee rate. 533 select { 534 case outMsg := <-alicePeer.outgoingQueue: 535 msg = outMsg.msg 536 case <-time.After(timeout): 537 t.Fatalf("did not receive closing signed") 538 } 539 closingSignedMsg, ok := msg.(*lnwire.ClosingSigned) 540 if !ok { 541 t.Fatalf("expected ClosingSigned message, got %T", msg) 542 } 543 544 idealFeeRate := closingSignedMsg.FeeAtoms 545 lastReceivedFee := idealFeeRate 546 547 increasedFee := dcrutil.Amount(float64(idealFeeRate) * 2.1) 548 lastSentFee := increasedFee 549 550 bobSig, _, _, err := bobChan.CreateCloseProposal( 551 increasedFee, dummyDeliveryScript, aliceDeliveryScript, 552 ) 553 if err != nil { 554 t.Fatalf("error creating close proposal: %v", err) 555 } 556 557 parsedSig, err := lnwire.NewSigFromSignature(bobSig) 558 if err != nil { 559 t.Fatalf("unable to parse signature: %v", err) 560 } 561 562 closingSigned := lnwire.NewClosingSigned(chanID, increasedFee, parsedSig) 563 alicePeer.chanCloseMsgs <- &closeMsg{ 564 cid: chanID, 565 msg: closingSigned, 566 } 567 568 // It still won't be accepted, and we should get a new proposal, the 569 // average of what we proposed, and what they proposed last time. 570 select { 571 case outMsg := <-alicePeer.outgoingQueue: 572 msg = outMsg.msg 573 case <-time.After(timeout): 574 t.Fatalf("did not receive closing signed") 575 } 576 closingSignedMsg, ok = msg.(*lnwire.ClosingSigned) 577 if !ok { 578 t.Fatalf("expected ClosingSigned message, got %T", msg) 579 } 580 581 aliceFee := closingSignedMsg.FeeAtoms 582 if aliceFee < lastReceivedFee { 583 t.Fatalf("new fee should be greater than prior: new=%v, old=%v", 584 aliceFee, lastReceivedFee) 585 } 586 if aliceFee > lastSentFee { 587 t.Fatalf("new fee should be less than our fee: new=%v, old=%v", 588 aliceFee, lastSentFee) 589 } 590 591 lastReceivedFee = aliceFee 592 593 // We'll try negotiating a 1.5x fee, which should also be rejected. 594 increasedFee = dcrutil.Amount(float64(idealFeeRate) * 1.5) 595 lastSentFee = increasedFee 596 597 bobSig, _, _, err = bobChan.CreateCloseProposal( 598 increasedFee, dummyDeliveryScript, aliceDeliveryScript, 599 ) 600 if err != nil { 601 t.Fatalf("error creating close proposal: %v", err) 602 } 603 604 parsedSig, err = lnwire.NewSigFromSignature(bobSig) 605 if err != nil { 606 t.Fatalf("error parsing signature: %v", err) 607 } 608 609 closingSigned = lnwire.NewClosingSigned(chanID, increasedFee, parsedSig) 610 alicePeer.chanCloseMsgs <- &closeMsg{ 611 cid: chanID, 612 msg: closingSigned, 613 } 614 615 // Alice won't accept Bob's new proposal, and Bob should receive a new 616 // proposal which is the average of what Bob proposed and Alice proposed 617 // last time. 618 select { 619 case outMsg := <-alicePeer.outgoingQueue: 620 msg = outMsg.msg 621 case <-time.After(timeout): 622 t.Fatalf("did not receive closing signed") 623 } 624 closingSignedMsg, ok = msg.(*lnwire.ClosingSigned) 625 if !ok { 626 t.Fatalf("expected ClosingSigned message, got %T", msg) 627 } 628 629 aliceFee = closingSignedMsg.FeeAtoms 630 if aliceFee < lastReceivedFee { 631 t.Fatalf("new fee should be greater than prior: new=%v, old=%v", 632 aliceFee, lastReceivedFee) 633 } 634 if aliceFee > lastSentFee { 635 t.Fatalf("new fee should be less than Bob's fee: new=%v, old=%v", 636 aliceFee, lastSentFee) 637 } 638 639 // Bob will now accept their fee by sending back a ClosingSigned message 640 // with an identical fee. 641 bobSig, _, _, err = bobChan.CreateCloseProposal( 642 aliceFee, dummyDeliveryScript, aliceDeliveryScript, 643 ) 644 if err != nil { 645 t.Fatalf("error creating close proposal: %v", err) 646 } 647 648 parsedSig, err = lnwire.NewSigFromSignature(bobSig) 649 if err != nil { 650 t.Fatalf("error parsing signature: %v", err) 651 } 652 closingSigned = lnwire.NewClosingSigned(chanID, aliceFee, parsedSig) 653 alicePeer.chanCloseMsgs <- &closeMsg{ 654 cid: chanID, 655 msg: closingSigned, 656 } 657 658 // Wait for closing tx to be broadcasted. 659 select { 660 case <-broadcastTxChan: 661 case <-time.After(timeout): 662 t.Fatalf("closing tx not broadcast") 663 } 664 665 // Alice should respond with the ClosingSigned they both agreed upon. 666 select { 667 case outMsg := <-alicePeer.outgoingQueue: 668 msg = outMsg.msg 669 case <-time.After(timeout): 670 t.Fatalf("did not receive closing signed message") 671 } 672 if _, ok := msg.(*lnwire.ClosingSigned); !ok { 673 t.Fatalf("expected to receive closing signed message, got %T", msg) 674 } 675 676 // Alice should be waiting on a single confirmation for the coop close tx. 677 notifier.ConfChan <- &chainntnfs.TxConfirmation{} 678 } 679 680 // TestChooseDeliveryScript tests that chooseDeliveryScript correctly errors 681 // when upfront and user set scripts that do not match are provided, allows 682 // matching values and returns appropriate values in the case where one or none 683 // are set. 684 func TestChooseDeliveryScript(t *testing.T) { 685 // generate non-zero scripts for testing. 686 script1 := genScript(t, p2SHAddress) 687 script2 := genScript(t, p2PKHAddress) 688 689 tests := []struct { 690 name string 691 userScript lnwire.DeliveryAddress 692 shutdownScript lnwire.DeliveryAddress 693 expectedScript lnwire.DeliveryAddress 694 expectedError error 695 }{ 696 { 697 name: "Neither set", 698 userScript: nil, 699 shutdownScript: nil, 700 expectedScript: nil, 701 expectedError: nil, 702 }, 703 { 704 name: "Both set and equal", 705 userScript: script1, 706 shutdownScript: script1, 707 expectedScript: script1, 708 expectedError: nil, 709 }, 710 { 711 name: "Both set and not equal", 712 userScript: script1, 713 shutdownScript: script2, 714 expectedScript: nil, 715 expectedError: chancloser.ErrUpfrontShutdownScriptMismatch, 716 }, 717 { 718 name: "Only upfront script", 719 userScript: nil, 720 shutdownScript: script1, 721 expectedScript: script1, 722 expectedError: nil, 723 }, 724 { 725 name: "Only user script", 726 userScript: script2, 727 shutdownScript: nil, 728 expectedScript: script2, 729 expectedError: nil, 730 }, 731 } 732 733 for _, test := range tests { 734 test := test 735 736 t.Run(test.name, func(t *testing.T) { 737 script, err := chooseDeliveryScript( 738 test.shutdownScript, test.userScript, 739 ) 740 if err != test.expectedError { 741 t.Fatalf("Expected: %v, got: %v", test.expectedError, err) 742 } 743 744 if !bytes.Equal(script, test.expectedScript) { 745 t.Fatalf("Expected: %x, got: %x", test.expectedScript, script) 746 } 747 }) 748 } 749 } 750 751 // TestCustomShutdownScript tests that the delivery script of a shutdown 752 // message can be set to a specified address. It checks that setting a close 753 // script fails for channels which have an upfront shutdown script already set. 754 func TestCustomShutdownScript(t *testing.T) { 755 script := genScript(t, p2SHAddress) 756 757 // setShutdown is a function which sets the upfront shutdown address for 758 // the local channel. 759 setShutdown := func(a, b *channeldb.OpenChannel) { 760 a.LocalShutdownScript = script 761 b.RemoteShutdownScript = script 762 } 763 764 tests := []struct { 765 name string 766 767 // update is a function used to set values on the channel set up for the 768 // test. It is used to set values for upfront shutdown addresses. 769 update func(a, b *channeldb.OpenChannel) 770 771 // userCloseScript is the address specified by the user. 772 userCloseScript lnwire.DeliveryAddress 773 774 // expectedScript is the address we expect to be set on the shutdown 775 // message. 776 expectedScript lnwire.DeliveryAddress 777 778 // expectedError is the error we expect, if any. 779 expectedError error 780 }{ 781 { 782 name: "User set script", 783 update: noUpdate, 784 userCloseScript: script, 785 expectedScript: script, 786 }, 787 { 788 name: "No user set script", 789 update: noUpdate, 790 }, 791 { 792 name: "Shutdown set, no user script", 793 update: setShutdown, 794 expectedScript: script, 795 }, 796 { 797 name: "Shutdown set, user script matches", 798 update: setShutdown, 799 userCloseScript: script, 800 expectedScript: script, 801 }, 802 { 803 name: "Shutdown set, user script different", 804 update: setShutdown, 805 userCloseScript: []byte("different addr"), 806 expectedError: chancloser.ErrUpfrontShutdownScriptMismatch, 807 }, 808 } 809 810 for _, test := range tests { 811 test := test 812 813 t.Run(test.name, func(t *testing.T) { 814 notifier := &mock.ChainNotifier{ 815 SpendChan: make(chan *chainntnfs.SpendDetail), 816 EpochChan: make(chan *chainntnfs.BlockEpoch), 817 ConfChan: make(chan *chainntnfs.TxConfirmation), 818 } 819 broadcastTxChan := make(chan *wire.MsgTx) 820 821 mockSwitch := &mockMessageSwitch{} 822 823 // Open a channel. 824 alicePeer, bobChan, cleanUp, err := createTestPeer( 825 notifier, broadcastTxChan, test.update, 826 mockSwitch, 827 ) 828 if err != nil { 829 t.Fatalf("unable to create test channels: %v", err) 830 } 831 defer cleanUp() 832 833 chanPoint := bobChan.ChannelPoint() 834 chanID := lnwire.NewChanIDFromOutPoint(chanPoint) 835 mockLink := newMockUpdateHandler(chanID) 836 mockSwitch.links = append(mockSwitch.links, mockLink) 837 838 // Request initiator to cooperatively close the channel, with 839 // a specified delivery address. 840 updateChan := make(chan interface{}, 1) 841 errChan := make(chan error, 1) 842 closeCommand := htlcswitch.ChanClose{ 843 CloseType: contractcourt.CloseRegular, 844 ChanPoint: chanPoint, 845 Updates: updateChan, 846 TargetFeePerKB: 12500, 847 DeliveryScript: test.userCloseScript, 848 Err: errChan, 849 } 850 851 // Send the close command for the correct channel and check that a 852 // shutdown message is sent. 853 alicePeer.localCloseChanReqs <- &closeCommand 854 855 var msg lnwire.Message 856 select { 857 case outMsg := <-alicePeer.outgoingQueue: 858 msg = outMsg.msg 859 case <-time.After(timeout): 860 t.Fatalf("did not receive shutdown message") 861 case err := <-errChan: 862 // Fail if we do not expect an error. 863 if err != test.expectedError { 864 t.Fatalf("error closing channel: %v", err) 865 } 866 867 // Terminate the test early if have received an error, no 868 // further action is expected. 869 return 870 } 871 872 // Check that we have received a shutdown message. 873 shutdownMsg, ok := msg.(*lnwire.Shutdown) 874 if !ok { 875 t.Fatalf("expected shutdown message, got %T", msg) 876 } 877 878 // If the test has not specified an expected address, do not check 879 // whether the shutdown address matches. This covers the case where 880 // we epect shutdown to a random address and cannot match it. 881 if len(test.expectedScript) == 0 { 882 return 883 } 884 885 // Check that the Shutdown message includes the expected delivery 886 // script. 887 if !bytes.Equal(test.expectedScript, shutdownMsg.Address) { 888 t.Fatalf("expected delivery script: %x, got: %x", 889 test.expectedScript, shutdownMsg.Address) 890 } 891 }) 892 } 893 } 894 895 // TestStaticRemoteDowngrade tests that we downgrade our static remote feature 896 // bit to optional if we have legacy channels with a peer. This ensures that 897 // we can stay connected to peers that don't support the feature bit that we 898 // have channels with. 899 func TestStaticRemoteDowngrade(t *testing.T) { 900 t.Parallel() 901 902 var ( 903 // We set the same legacy feature bits for all tests, since 904 // these are not relevant to our test scenario 905 rawLegacy = lnwire.NewRawFeatureVector( 906 lnwire.UpfrontShutdownScriptOptional, 907 ) 908 legacy = lnwire.NewFeatureVector(rawLegacy, nil) 909 910 legacyCombinedOptional = lnwire.NewRawFeatureVector( 911 lnwire.UpfrontShutdownScriptOptional, 912 lnwire.StaticRemoteKeyOptional, 913 ) 914 915 rawFeatureOptional = lnwire.NewRawFeatureVector( 916 lnwire.StaticRemoteKeyOptional, 917 ) 918 919 featureOptional = lnwire.NewFeatureVector( 920 rawFeatureOptional, nil, 921 ) 922 923 rawFeatureRequired = lnwire.NewRawFeatureVector( 924 lnwire.StaticRemoteKeyRequired, 925 ) 926 927 featureRequired = lnwire.NewFeatureVector( 928 rawFeatureRequired, nil, 929 ) 930 ) 931 932 tests := []struct { 933 name string 934 legacy bool 935 features *lnwire.FeatureVector 936 expectedInit *lnwire.Init 937 }{ 938 { 939 name: "no legacy channel, static optional", 940 legacy: false, 941 features: featureOptional, 942 expectedInit: &lnwire.Init{ 943 GlobalFeatures: rawLegacy, 944 Features: rawFeatureOptional, 945 }, 946 }, 947 { 948 name: "legacy channel, static optional", 949 legacy: true, 950 features: featureOptional, 951 expectedInit: &lnwire.Init{ 952 GlobalFeatures: rawLegacy, 953 Features: rawFeatureOptional, 954 }, 955 }, 956 { 957 name: "no legacy channel, static required", 958 legacy: false, 959 features: featureRequired, 960 expectedInit: &lnwire.Init{ 961 GlobalFeatures: rawLegacy, 962 Features: rawFeatureRequired, 963 }, 964 }, 965 966 // In this case we need to flip our required bit to optional, 967 // this should also propagate to the legacy set of feature bits 968 // so we have proper consistency: a bit isn't set to optional 969 // in one field and required in the other. 970 { 971 name: "legacy channel, static required", 972 legacy: true, 973 features: featureRequired, 974 expectedInit: &lnwire.Init{ 975 GlobalFeatures: legacyCombinedOptional, 976 Features: rawFeatureOptional, 977 }, 978 }, 979 } 980 981 for _, test := range tests { 982 test := test 983 984 t.Run(test.name, func(t *testing.T) { 985 writeBufferPool := pool.NewWriteBuffer( 986 pool.DefaultWriteBufferGCInterval, 987 pool.DefaultWriteBufferExpiryInterval, 988 ) 989 990 writePool := pool.NewWrite( 991 writeBufferPool, 1, timeout, 992 ) 993 require.NoError(t, writePool.Start()) 994 995 mockConn := newMockConn(t, 1) 996 997 p := Brontide{ 998 cfg: Config{ 999 LegacyFeatures: legacy, 1000 Features: test.features, 1001 Conn: mockConn, 1002 WritePool: writePool, 1003 PongBuf: make([]byte, lnwire.MaxPongBytes), 1004 }, 1005 } 1006 1007 var b bytes.Buffer 1008 _, err := lnwire.WriteMessage(&b, test.expectedInit, 0) 1009 require.NoError(t, err) 1010 1011 // Send our init message, assert that we write our expected message 1012 // and shutdown our write pool. 1013 require.NoError(t, p.sendInitMsg(test.legacy)) 1014 mockConn.assertWrite(b.Bytes()) 1015 require.NoError(t, writePool.Stop()) 1016 }) 1017 } 1018 } 1019 1020 // genScript creates a script paying out to the address provided, which must 1021 // be a valid address. 1022 func genScript(t *testing.T, address string) lnwire.DeliveryAddress { 1023 // Generate an address which can be used for testing. 1024 deliveryAddr, err := stdaddr.DecodeAddress( 1025 address, 1026 chaincfg.TestNet3Params(), 1027 ) 1028 if err != nil { 1029 t.Fatalf("invalid delivery address: %v", err) 1030 } 1031 1032 script, err := input.PayToAddrScript(deliveryAddr) 1033 if err != nil { 1034 t.Fatalf("cannot create script: %v", err) 1035 } 1036 1037 return script 1038 } 1039 1040 // TestPeerCustomMessage tests custom message exchange between peers. 1041 func TestPeerCustomMessage(t *testing.T) { 1042 t.Parallel() 1043 1044 // Set up node Alice. 1045 alicePath, err := ioutil.TempDir("", "alicedb") 1046 require.NoError(t, err) 1047 1048 dbAlice, err := channeldb.Open(alicePath) 1049 require.NoError(t, err) 1050 1051 aliceKey, err := secp256k1.GeneratePrivateKey() 1052 require.NoError(t, err) 1053 1054 writeBufferPool := pool.NewWriteBuffer( 1055 pool.DefaultWriteBufferGCInterval, 1056 pool.DefaultWriteBufferExpiryInterval, 1057 ) 1058 1059 writePool := pool.NewWrite( 1060 writeBufferPool, 1, timeout, 1061 ) 1062 require.NoError(t, writePool.Start()) 1063 1064 readBufferPool := pool.NewReadBuffer( 1065 pool.DefaultReadBufferGCInterval, 1066 pool.DefaultReadBufferExpiryInterval, 1067 ) 1068 1069 readPool := pool.NewRead( 1070 readBufferPool, 1, timeout, 1071 ) 1072 require.NoError(t, readPool.Start()) 1073 1074 mockConn := newMockConn(t, 1) 1075 1076 receivedCustomChan := make(chan *customMsg) 1077 1078 remoteKey := [33]byte{8} 1079 1080 notifier := &mock.ChainNotifier{ 1081 SpendChan: make(chan *chainntnfs.SpendDetail), 1082 EpochChan: make(chan *chainntnfs.BlockEpoch), 1083 ConfChan: make(chan *chainntnfs.TxConfirmation), 1084 } 1085 1086 alicePeer := NewBrontide(Config{ 1087 PubKeyBytes: remoteKey, 1088 ChannelDB: dbAlice.ChannelStateDB(), 1089 Addr: &lnwire.NetAddress{ 1090 IdentityKey: aliceKey.PubKey(), 1091 }, 1092 PrunePersistentPeerConnection: func([33]byte) {}, 1093 Features: lnwire.EmptyFeatureVector(), 1094 LegacyFeatures: lnwire.EmptyFeatureVector(), 1095 WritePool: writePool, 1096 ReadPool: readPool, 1097 Conn: mockConn, 1098 ChainNotifier: notifier, 1099 HandleCustomMessage: func( 1100 peer [33]byte, msg *lnwire.Custom) error { 1101 1102 receivedCustomChan <- &customMsg{ 1103 peer: peer, 1104 msg: *msg, 1105 } 1106 return nil 1107 }, 1108 PongBuf: make([]byte, lnwire.MaxPongBytes), 1109 }) 1110 1111 // Set up the init sequence. 1112 go func() { 1113 // Read init message. 1114 <-mockConn.writtenMessages 1115 1116 // Write the init reply message. 1117 initReplyMsg := lnwire.NewInitMessage( 1118 lnwire.NewRawFeatureVector( 1119 lnwire.DataLossProtectRequired, 1120 ), 1121 lnwire.NewRawFeatureVector(), 1122 ) 1123 var b bytes.Buffer 1124 _, err = lnwire.WriteMessage(&b, initReplyMsg, 0) 1125 assert.NoError(t, err) 1126 1127 mockConn.readMessages <- b.Bytes() 1128 }() 1129 1130 // Start the peer. 1131 require.NoError(t, alicePeer.Start()) 1132 1133 // Send a custom message. 1134 customMsg, err := lnwire.NewCustom( 1135 lnwire.MessageType(40000), []byte{1, 2, 3}, 1136 ) 1137 require.NoError(t, err) 1138 1139 require.NoError(t, alicePeer.SendMessageLazy(false, customMsg)) 1140 1141 // Verify that it is passed down to the noise layer correctly. 1142 writtenMsg := <-mockConn.writtenMessages 1143 require.Equal(t, []byte{0x9c, 0x40, 0x1, 0x2, 0x3}, writtenMsg) 1144 1145 // Receive a custom message. 1146 receivedCustomMsg, err := lnwire.NewCustom( 1147 lnwire.MessageType(40001), []byte{4, 5, 6}, 1148 ) 1149 require.NoError(t, err) 1150 1151 receivedData := []byte{0x9c, 0x41, 0x4, 0x5, 0x6} 1152 mockConn.readMessages <- receivedData 1153 1154 // Verify that it is propagated up to the custom message handler. 1155 receivedCustom := <-receivedCustomChan 1156 require.Equal(t, remoteKey, receivedCustom.peer) 1157 require.Equal(t, receivedCustomMsg, &receivedCustom.msg) 1158 }