github.com/decred/dcrlnd@v0.7.6/lnwallet/transactions_test.go (about) 1 package lnwallet 2 3 import ( 4 "bytes" 5 "crypto/rand" 6 "encoding/binary" 7 "encoding/hex" 8 "encoding/json" 9 "fmt" 10 "io" 11 "io/ioutil" 12 "net" 13 "os" 14 "sort" 15 "testing" 16 "time" 17 18 "github.com/decred/dcrd/blockchain/stake/v5" 19 "github.com/decred/dcrd/blockchain/standalone/v2" 20 "github.com/decred/dcrd/chaincfg/chainhash" 21 "github.com/decred/dcrd/chaincfg/v3" 22 "github.com/decred/dcrd/dcrec/secp256k1/v4" 23 "github.com/decred/dcrd/dcrutil/v4" 24 "github.com/decred/dcrd/txscript/v4" 25 "github.com/decred/dcrd/wire" 26 "github.com/decred/dcrlnd/channeldb" 27 "github.com/decred/dcrlnd/input" 28 "github.com/decred/dcrlnd/keychain" 29 "github.com/decred/dcrlnd/lntypes" 30 "github.com/decred/dcrlnd/lnwallet/chainfee" 31 "github.com/decred/dcrlnd/lnwire" 32 "github.com/decred/dcrlnd/shachain" 33 "github.com/stretchr/testify/require" 34 ) 35 36 /** 37 * This file implements that different types of transactions used in the 38 * lightning protocol are created correctly. To do so, the tests use the test 39 * vectors defined in Appendix B & C of BOLT 03. 40 */ 41 42 // testContext contains the test parameters defined in Appendix B & C of the 43 // BOLT 03 spec. 44 type testContext struct { 45 localFundingPrivkey *secp256k1.PrivateKey 46 localPaymentBasepointSecret *secp256k1.PrivateKey 47 localDelayedPaymentBasepointSecret *secp256k1.PrivateKey 48 remoteFundingPrivkey *secp256k1.PrivateKey 49 remoteRevocationBasepointSecret *secp256k1.PrivateKey 50 remotePaymentBasepointSecret *secp256k1.PrivateKey 51 52 localPerCommitSecret lntypes.Hash 53 54 fundingTx *dcrutil.Tx 55 56 localCsvDelay uint16 57 fundingAmount dcrutil.Amount 58 dustLimit dcrutil.Amount 59 commitHeight uint64 60 61 t *testing.T 62 params *chaincfg.Params 63 } 64 65 // newTestContext populates a new testContext struct with the constant 66 // parameters defined in the BOLT 03 spec. 67 func newTestContext(t *testing.T) (tc *testContext) { 68 tc = new(testContext) 69 70 priv := func(v string) *secp256k1.PrivateKey { 71 k, err := privkeyFromHex(v) 72 require.NoError(t, err) 73 74 return k 75 } 76 77 tc.remoteFundingPrivkey = priv("1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e13") 78 tc.remoteRevocationBasepointSecret = priv("2222222222222222222222222222222222222222222222222222222222222222") 79 tc.remotePaymentBasepointSecret = priv("4444444444444444444444444444444444444444444444444444444444444444") 80 tc.localPaymentBasepointSecret = priv("1111111111111111111111111111111111111111111111111111111111111111") 81 tc.localDelayedPaymentBasepointSecret = priv("3333333333333333333333333333333333333333333333333333333333333333") 82 tc.localFundingPrivkey = priv("30ff4956bbdd3222d44cc5e8a1261dab1e07957bdac5ae88fe3261ef321f3749") 83 84 var err error 85 tc.localPerCommitSecret, err = lntypes.MakeHashFromStr("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100") 86 require.NoError(t, err) 87 88 const fundingTxHex = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff0100a0724e18090000000017a9142451a686d349c5ce6f72373ed59a841192d794418700000000000000000100e057eb481b000000000000ffffffff0800002f646372642f" 89 90 tc.fundingTx, err = txFromHex(fundingTxHex) 91 92 require.NoError(t, err) 93 94 tc.localCsvDelay = 144 95 tc.fundingAmount = 10000000 96 tc.dustLimit = 546 97 98 tc.params = chaincfg.RegNetParams() 99 tc.commitHeight = 42 100 tc.t = t 101 102 return tc 103 } 104 105 var testHtlcs = []struct { 106 incoming bool 107 amount lnwire.MilliAtom 108 expiry uint32 109 preimage string 110 }{ 111 { 112 incoming: true, 113 amount: 1000000, 114 expiry: 500, 115 preimage: "0000000000000000000000000000000000000000000000000000000000000000", 116 }, 117 { 118 incoming: true, 119 amount: 2000000, 120 expiry: 501, 121 preimage: "0101010101010101010101010101010101010101010101010101010101010101", 122 }, 123 { 124 incoming: false, 125 amount: 2000000, 126 expiry: 502, 127 preimage: "0202020202020202020202020202020202020202020202020202020202020202", 128 }, 129 { 130 incoming: false, 131 amount: 3000000, 132 expiry: 503, 133 preimage: "0303030303030303030303030303030303030303030303030303030303030303", 134 }, 135 { 136 incoming: true, 137 amount: 4000000, 138 expiry: 504, 139 preimage: "0404040404040404040404040404040404040404040404040404040404040404", 140 }, 141 } 142 143 // htlcDesc is a description used to construct each HTLC in each test case. 144 type htlcDesc struct { 145 RemoteSigHex string 146 ResolutionTxHex string 147 } 148 149 type testCase struct { 150 Name string 151 LocalBalance lnwire.MilliAtom 152 RemoteBalance lnwire.MilliAtom 153 FeePerKB dcrutil.Amount 154 155 // UseTestHtlcs defined whether the fixed set of test htlc should be 156 // added to the channel before checking the commitment assertions. 157 UseTestHtlcs bool 158 159 HtlcDescs []htlcDesc 160 ExpectedCommitmentTxHex string 161 RemoteSigHex string 162 } 163 164 // TestCommitmentAndHTLCTransactions checks the test vectors specified in BOLT 165 // 03, Appendix C. This deterministically generates commitment and second level 166 // HTLC transactions and checks that they match the expected values. 167 func TestCommitmentAndHTLCTransactions(t *testing.T) { 168 // These tests are based on the original Bitcoin LN ones and thus use 169 // fees lower than the current fee floor. Thus we disable checking the 170 // fee floor for these tests. 171 disableFeeFloorCheck = true 172 defer func() { 173 disableFeeFloorCheck = false 174 }() 175 176 vectorSets := []struct { 177 name string 178 jsonFile string 179 chanType channeldb.ChannelType 180 }{ 181 { 182 name: "legacy", 183 chanType: channeldb.SingleFunderBit, 184 jsonFile: "test_vectors_legacy.json", 185 }, 186 { 187 name: "anchors", 188 chanType: channeldb.SingleFunderTweaklessBit | channeldb.AnchorOutputsBit, 189 jsonFile: "test_vectors_anchors.json", 190 }, 191 } 192 193 for _, set := range vectorSets { 194 set := set 195 196 var testCases []testCase 197 198 jsonText, err := ioutil.ReadFile(set.jsonFile) 199 require.NoError(t, err) 200 201 err = json.Unmarshal(jsonText, &testCases) 202 require.NoError(t, err) 203 204 t.Run(set.name, func(t *testing.T) { 205 for _, test := range testCases { 206 test := test 207 208 t.Run(test.Name, func(t *testing.T) { 209 testVectors(t, set.chanType, test) 210 }) 211 } 212 }) 213 } 214 } 215 216 // addTestHtlcs adds the test vector htlcs to the update logs of the local and 217 // remote node. 218 func addTestHtlcs(t *testing.T, remote, 219 local *LightningChannel) map[[20]byte]lntypes.Preimage { 220 221 hash160map := make(map[[20]byte]lntypes.Preimage) 222 for _, htlc := range testHtlcs { 223 preimage, err := lntypes.MakePreimageFromStr(htlc.preimage) 224 require.NoError(t, err) 225 226 hash := preimage.Hash() 227 228 // Store ripemd160 hash of the payment hash to later identify 229 // resolutions. 230 var hash160 [20]byte 231 copy(hash160[:], input.Ripemd160H(hash[:])) 232 hash160map[hash160] = preimage 233 234 // Add htlc to the channel. 235 chanID := lnwire.NewChanIDFromOutPoint(remote.ChanPoint) 236 237 msg := &lnwire.UpdateAddHTLC{ 238 Amount: htlc.amount, 239 ChanID: chanID, 240 Expiry: htlc.expiry, 241 PaymentHash: hash, 242 } 243 if htlc.incoming { 244 htlcID, err := remote.AddHTLC(msg, nil) 245 require.NoError(t, err, "unable to add htlc") 246 247 msg.ID = htlcID 248 _, err = local.ReceiveHTLC(msg) 249 require.NoError(t, err, "unable to recv htlc") 250 } else { 251 htlcID, err := local.AddHTLC(msg, nil) 252 require.NoError(t, err, "unable to add htlc") 253 254 msg.ID = htlcID 255 _, err = remote.ReceiveHTLC(msg) 256 require.NoError(t, err, "unable to recv htlc") 257 } 258 } 259 260 return hash160map 261 } 262 263 // testVectors executes a commit dance to end up with the commitment transaction 264 // that is described in the test vectors and then asserts that all values are 265 // correct. 266 func testVectors(t *testing.T, chanType channeldb.ChannelType, test testCase) { 267 tc := newTestContext(t) 268 269 // Balances in the test vectors are before subtraction of in-flight 270 // htlcs. Convert to spendable balances. 271 remoteBalance := test.RemoteBalance 272 localBalance := test.LocalBalance 273 274 if test.UseTestHtlcs { 275 for _, htlc := range testHtlcs { 276 if htlc.incoming { 277 remoteBalance += htlc.amount 278 } else { 279 localBalance += htlc.amount 280 } 281 } 282 } 283 284 // Set up a test channel on which the test commitment transaction is 285 // going to be produced. 286 remoteChannel, localChannel, cleanUp := createTestChannelsForVectors( 287 tc, 288 chanType, test.FeePerKB, 289 remoteBalance.ToAtoms(), 290 localBalance.ToAtoms(), 291 ) 292 defer cleanUp() 293 294 // Add htlcs (if any) to the update logs of both sides and save a hash 295 // map that allows us to identify the htlcs in the scripts later on and 296 // retrieve the corresponding preimage. 297 var hash160map map[[20]byte]lntypes.Preimage 298 if test.UseTestHtlcs { 299 hash160map = addTestHtlcs(t, remoteChannel, localChannel) 300 } 301 302 // Execute commit dance to arrive at the point where the local node has 303 // received the test commitment and the remote signature. 304 localSig, localHtlcSigs, _, err := localChannel.SignNextCommitment() 305 require.NoError(t, err, "local unable to sign commitment") 306 307 err = remoteChannel.ReceiveNewCommitment(localSig, localHtlcSigs) 308 require.NoError(t, err) 309 310 revMsg, _, err := remoteChannel.RevokeCurrentCommitment() 311 require.NoError(t, err) 312 313 _, _, _, _, err = localChannel.ReceiveRevocation(revMsg) 314 require.NoError(t, err) 315 316 remoteSig, remoteHtlcSigs, _, err := remoteChannel.SignNextCommitment() 317 require.NoError(t, err) 318 319 err = localChannel.ReceiveNewCommitment(remoteSig, remoteHtlcSigs) 320 require.NoError(t, err) 321 322 _, _, err = localChannel.RevokeCurrentCommitment() 323 require.NoError(t, err) 324 325 // Now the local node force closes the channel so that we can inspect 326 // its state. 327 forceCloseSum, err := localChannel.ForceClose() 328 require.NoError(t, err) 329 330 // Uncomment the following line to debug the generated commitment tx. 331 // t.Logf("XXXX %d %s\n%s", test.FeePerKB, test.Name, spew.Sdump(forceCloseSum.CloseTx)) 332 333 err = checkSignedCommitmentTxSanity(forceCloseSum.CloseTx, tc.fundingTx.MsgTx().TxOut[0], tc.params) 334 require.NoError(t, err) 335 336 err = checkSignedCommitmentTxSanity(forceCloseSum.CloseTx, tc.fundingTx.MsgTx().TxOut[0], tc.params) 337 require.NoError(t, err) 338 339 // Start verifying the signatures match. 340 require.Equal(t, test.RemoteSigHex, hex.EncodeToString(remoteSig.ToSignatureBytes()), 341 "commit tx remote sig incorrect") 342 require.Equal(t, len(remoteHtlcSigs), len(test.HtlcDescs), 343 "wrong number of htlc sigs") 344 for i, sig := range remoteHtlcSigs { 345 require.Equal(t, test.HtlcDescs[i].RemoteSigHex, hex.EncodeToString(sig.ToSignatureBytes()), 346 "remote HTLC sig %d incorrect", i) 347 } 348 349 // Assert that the commitment transaction itself is as expected. 350 var txBytes bytes.Buffer 351 require.NoError(t, forceCloseSum.CloseTx.Serialize(&txBytes)) 352 require.Equal(t, test.ExpectedCommitmentTxHex, hex.EncodeToString(txBytes.Bytes()), 353 "commitment tx hex incorrect") 354 355 // Obtain the second level transactions that the local node's channel 356 // state machine has produced. Store them in a map indexed by commit tx 357 // output index. Also complete the second level transaction with the 358 // preimage. This is normally done later in the contract resolver. 359 secondLevelTxes := map[uint32]*wire.MsgTx{} 360 storeTx := func(index uint32, tx *wire.MsgTx) { 361 // Prevent overwrites. 362 _, exists := secondLevelTxes[index] 363 require.False(t, exists) 364 365 secondLevelTxes[index] = tx 366 } 367 368 for _, r := range forceCloseSum.HtlcResolutions.IncomingHTLCs { 369 successTx := r.SignedSuccessTx 370 witnessStack, err := input.SigScriptToWitnessStack(successTx.TxIn[0].SignatureScript) 371 require.NoError(t, err) 372 witnessScript := witnessStack[3] 373 var hash160 [20]byte 374 copy(hash160[:], witnessScript[70:70+20]) 375 preimage, ok := hash160map[hash160] 376 require.True(t, ok, "Could not find preimage for hash %x", hash160) 377 witnessStack[2] = preimage[:] 378 successTx.TxIn[0].SignatureScript, err = input.WitnessStackToSigScript(witnessStack) 379 require.NoError(t, err) 380 storeTx(r.HtlcPoint().Index, successTx) 381 } 382 for _, r := range forceCloseSum.HtlcResolutions.OutgoingHTLCs { 383 storeTx(r.HtlcPoint().Index, r.SignedTimeoutTx) 384 } 385 386 // Create a list of second level transactions ordered by commit tx 387 // output index. 388 var keys []uint32 389 for k := range secondLevelTxes { 390 keys = append(keys, k) 391 } 392 sort.Slice(keys, func(a, b int) bool { 393 return keys[a] < keys[b] 394 }) 395 396 // Assert that this list matches the test vectors. 397 failed := false 398 for i, idx := range keys { 399 tx := secondLevelTxes[idx] 400 var b bytes.Buffer 401 err := tx.Serialize(&b) 402 require.NoError(t, err) 403 404 err = checkSignedCommitmentSpendingTxSanity(tx, forceCloseSum.CloseTx, 405 tc.params) 406 require.NoError(t, err) 407 408 require.Equal( 409 t, 410 test.HtlcDescs[i].ResolutionTxHex, 411 hex.EncodeToString(b.Bytes()), 412 "second level tx %d incorrect", i, 413 ) 414 } 415 if failed { 416 t.Fatalf("failed") 417 } 418 } 419 420 func TestCommitTxStateHint(t *testing.T) { 421 t.Parallel() 422 423 stateHintTests := []struct { 424 name string 425 from uint64 426 to uint64 427 inputs int 428 shouldFail bool 429 }{ 430 { 431 name: "states 0 to 1000", 432 from: 0, 433 to: 1000, 434 inputs: 1, 435 shouldFail: false, 436 }, 437 { 438 name: "states 'maxStateHint-1000' to 'maxStateHint'", 439 from: maxStateHint - 1000, 440 to: maxStateHint, 441 inputs: 1, 442 shouldFail: false, 443 }, 444 { 445 name: "state 'maxStateHint+1'", 446 from: maxStateHint + 1, 447 to: maxStateHint + 10, 448 inputs: 1, 449 shouldFail: true, 450 }, 451 { 452 name: "commit transaction with two inputs", 453 inputs: 2, 454 shouldFail: true, 455 }, 456 } 457 458 var obfuscator [StateHintSize]byte 459 copy(obfuscator[:], testHdSeed[:StateHintSize]) 460 timeYesterday := uint32(time.Now().Unix() - 24*60*60) 461 462 for _, test := range stateHintTests { 463 commitTx := wire.NewMsgTx() 464 commitTx.Version = input.LNTxVersion 465 466 // Add supplied number of inputs to the commitment transaction. 467 for i := 0; i < test.inputs; i++ { 468 commitTx.AddTxIn(&wire.TxIn{}) 469 } 470 471 for i := test.from; i <= test.to; i++ { 472 stateNum := i 473 474 err := SetStateNumHint(commitTx, stateNum, obfuscator) 475 if err != nil && !test.shouldFail { 476 t.Fatalf("unable to set state num %v: %v", i, err) 477 } else if err == nil && test.shouldFail { 478 t.Fatalf("Failed(%v): test should fail but did not", test.name) 479 } 480 481 locktime := commitTx.LockTime 482 sequence := commitTx.TxIn[0].Sequence 483 484 // Locktime should not be less than 500,000,000 and not larger 485 // than the time 24 hours ago. One day should provide a good 486 // enough buffer for the tests. 487 if locktime < 5e8 || locktime > timeYesterday { 488 if !test.shouldFail { 489 t.Fatalf("The value of locktime (%v) may cause the commitment "+ 490 "transaction to be unspendable", locktime) 491 } 492 } 493 494 if sequence&wire.SequenceLockTimeDisabled == 0 { 495 if !test.shouldFail { 496 t.Fatalf("Sequence locktime is NOT disabled when it should be") 497 } 498 } 499 500 extractedStateNum := GetStateNumHint(commitTx, obfuscator) 501 if extractedStateNum != stateNum && !test.shouldFail { 502 t.Fatalf("state number mismatched, expected %v, got %v", 503 stateNum, extractedStateNum) 504 } else if extractedStateNum == stateNum && test.shouldFail { 505 t.Fatalf("Failed(%v): test should fail but did not", test.name) 506 } 507 } 508 t.Logf("Passed: %v", test.name) 509 } 510 } 511 512 // testSpendValidation ensures that we're able to spend all outputs in the 513 // commitment transaction that we create. 514 func testSpendValidation(t *testing.T, tweakless bool) { 515 // We generate a fake output, and the corresponding txin. This output 516 // doesn't need to exist, as we'll only be validating spending from the 517 // transaction that references this. 518 txid, err := chainhash.NewHash(testHdSeed.CloneBytes()) 519 if err != nil { 520 t.Fatalf("unable to create txid: %v", err) 521 } 522 fundingOut := &wire.OutPoint{ 523 Hash: *txid, 524 Index: 50, 525 Tree: wire.TxTreeRegular, 526 } 527 528 const channelBalance = dcrutil.Amount(1 * 10e8) 529 const csvTimeout = 5 530 fakeFundingTxIn := wire.NewTxIn(fundingOut, int64(channelBalance), nil) 531 532 // We also set up set some resources for the commitment transaction. 533 // Each side currently has 1 DCR within the channel, with a total 534 // channel capacity of 2 DCR. 535 aliceKeyPriv, aliceKeyPub := privKeyFromBytes(testWalletPrivKey) 536 bobKeyPriv, bobKeyPub := privKeyFromBytes(bobsPrivKey) 537 538 revocationPreimage := testHdSeed.CloneBytes() 539 commitSecret, commitPoint := privKeyFromBytes(revocationPreimage) 540 revokePubKey := input.DeriveRevocationPubkey(bobKeyPub, commitPoint) 541 542 aliceDelayKey := input.TweakPubKey(aliceKeyPub, commitPoint) 543 544 // Bob will have the channel "force closed" on him, so for the sake of 545 // our commitments, if it's tweakless, his key will just be his regular 546 // pubkey. 547 bobPayKey := input.TweakPubKey(bobKeyPub, commitPoint) 548 channelType := channeldb.SingleFunderBit 549 if tweakless { 550 bobPayKey = bobKeyPub 551 channelType = channeldb.SingleFunderTweaklessBit 552 } 553 554 remoteCommitTweak := input.SingleTweakBytes(commitPoint, aliceKeyPub) 555 localCommitTweak := input.SingleTweakBytes(commitPoint, bobKeyPub) 556 557 aliceSelfOutputSigner := &input.MockSigner{ 558 Privkeys: []*secp256k1.PrivateKey{aliceKeyPriv}, 559 } 560 561 // Calculate the dust limit we'll use for the test. 562 dustLimit := DustLimitForSize(input.P2PKHPkScriptSize) 563 564 aliceChanCfg := &channeldb.ChannelConfig{ 565 ChannelConstraints: channeldb.ChannelConstraints{ 566 DustLimit: dustLimit, 567 CsvDelay: csvTimeout, 568 }, 569 } 570 571 bobChanCfg := &channeldb.ChannelConfig{ 572 ChannelConstraints: channeldb.ChannelConstraints{ 573 DustLimit: dustLimit, 574 CsvDelay: csvTimeout, 575 }, 576 } 577 578 // With all the test data set up, we create the commitment transaction. 579 // We only focus on a single party's transactions, as the scripts are 580 // identical with the roles reversed. 581 // 582 // This is Alice's commitment transaction, so she must wait a CSV delay 583 // of 5 blocks before sweeping the output, while bob can spend 584 // immediately with either the revocation key, or his regular key. 585 keyRing := &CommitmentKeyRing{ 586 ToLocalKey: aliceDelayKey, 587 RevocationKey: revokePubKey, 588 ToRemoteKey: bobPayKey, 589 } 590 commitmentTx, err := CreateCommitTx( 591 channelType, *fakeFundingTxIn, keyRing, aliceChanCfg, 592 bobChanCfg, channelBalance, channelBalance, 0, true, 0, 593 ) 594 if err != nil { 595 t.Fatalf("unable to create commitment transaction: %v", nil) 596 } 597 598 delayOutput := commitmentTx.TxOut[0] 599 regularOutput := commitmentTx.TxOut[1] 600 601 // We're testing an uncooperative close, output sweep, so construct a 602 // transaction which sweeps the funds to a random address. 603 targetOutput, err := input.CommitScriptUnencumbered(aliceKeyPub) 604 if err != nil { 605 t.Fatalf("unable to create target output: %v", err) 606 } 607 sweepTx := wire.NewMsgTx() 608 sweepTx.Version = input.LNTxVersion 609 sweepTx.AddTxIn(wire.NewTxIn(&wire.OutPoint{ 610 Hash: commitmentTx.TxHash(), 611 Index: 0, 612 }, delayOutput.Value, nil)) 613 sweepTx.AddTxOut(&wire.TxOut{ 614 PkScript: targetOutput, 615 Value: 0.5 * 10e8, 616 }) 617 618 // First, we'll test spending with Alice's key after the timeout. 619 delayScript, err := input.CommitScriptToSelf( 620 csvTimeout, aliceDelayKey, revokePubKey, 621 ) 622 if err != nil { 623 t.Fatalf("unable to generate alice delay script: %v", err) 624 } 625 sweepTx.TxIn[0].Sequence = input.LockTimeToSequence(false, csvTimeout) 626 signDesc := &input.SignDescriptor{ 627 WitnessScript: delayScript, 628 KeyDesc: keychain.KeyDescriptor{ 629 PubKey: aliceKeyPub, 630 }, 631 SingleTweak: remoteCommitTweak, 632 Output: &wire.TxOut{ 633 Value: int64(channelBalance), 634 }, 635 HashType: txscript.SigHashAll, 636 InputIndex: 0, 637 } 638 aliceWitnessSpend, err := input.CommitSpendTimeout( 639 aliceSelfOutputSigner, signDesc, sweepTx, 640 ) 641 if err != nil { 642 t.Fatalf("unable to generate delay commit spend witness: %v", err) 643 } 644 sweepTx.TxIn[0].SignatureScript, err = input.WitnessStackToSigScript(aliceWitnessSpend) 645 if err != nil { 646 t.Fatalf("unable to convert witness stack to sigScript: %v", err) 647 } 648 649 vm, err := txscript.NewEngine(delayOutput.PkScript, 650 sweepTx, 0, input.ScriptVerifyFlags, delayOutput.Version, nil) 651 if err != nil { 652 t.Fatalf("unable to create engine: %v", err) 653 } 654 if err := vm.Execute(); err != nil { 655 t.Fatalf("spend from delay output is invalid: %v", err) 656 } 657 658 localSigner := &input.MockSigner{Privkeys: []*secp256k1.PrivateKey{bobKeyPriv}} 659 660 // Next, we'll test bob spending with the derived revocation key to 661 // simulate the scenario when Alice broadcasts this commitment 662 // transaction after it's been revoked. 663 signDesc = &input.SignDescriptor{ 664 KeyDesc: keychain.KeyDescriptor{ 665 PubKey: bobKeyPub, 666 }, 667 DoubleTweak: commitSecret, 668 WitnessScript: delayScript, 669 Output: &wire.TxOut{ 670 Value: int64(channelBalance), 671 }, 672 HashType: txscript.SigHashAll, 673 InputIndex: 0, 674 } 675 bobWitnessSpend, err := input.CommitSpendRevoke(localSigner, signDesc, 676 sweepTx) 677 if err != nil { 678 t.Fatalf("unable to generate revocation witness: %v", err) 679 } 680 sweepTx.TxIn[0].SignatureScript, err = input.WitnessStackToSigScript(bobWitnessSpend) 681 if err != nil { 682 t.Fatalf("unable to convert witness stack to sigScript: %v", err) 683 } 684 685 vm, err = txscript.NewEngine(delayOutput.PkScript, 686 sweepTx, 0, input.ScriptVerifyFlags, delayOutput.Version, nil) 687 if err != nil { 688 t.Fatalf("unable to create engine: %v", err) 689 } 690 if err := vm.Execute(); err != nil { 691 t.Fatalf("revocation spend is invalid: %v", err) 692 } 693 694 // In order to test the final scenario, we modify the TxIn of the sweep 695 // transaction to instead point to the regular output (non delay) 696 // within the commitment transaction. 697 sweepTx.TxIn[0] = &wire.TxIn{ 698 PreviousOutPoint: wire.OutPoint{ 699 Hash: commitmentTx.TxHash(), 700 Index: 1, 701 }, 702 } 703 704 // Finally, we test bob sweeping his output as normal in the case that 705 // Alice broadcasts this commitment transaction. 706 bobScriptP2PKH, err := input.CommitScriptUnencumbered(bobPayKey) 707 if err != nil { 708 t.Fatalf("unable to create bob p2wkh script: %v", err) 709 } 710 signDesc = &input.SignDescriptor{ 711 KeyDesc: keychain.KeyDescriptor{ 712 PubKey: bobKeyPub, 713 }, 714 WitnessScript: bobScriptP2PKH, 715 Output: &wire.TxOut{ 716 Value: int64(channelBalance), 717 PkScript: bobScriptP2PKH, 718 }, 719 HashType: txscript.SigHashAll, 720 InputIndex: 0, 721 } 722 if !tweakless { 723 signDesc.SingleTweak = localCommitTweak 724 } 725 bobRegularSpend, err := input.CommitSpendNoDelay( 726 localSigner, signDesc, sweepTx, tweakless, 727 ) 728 if err != nil { 729 t.Fatalf("unable to create bob regular spend: %v", err) 730 } 731 sweepTx.TxIn[0].SignatureScript, err = input.WitnessStackToSigScript(bobRegularSpend) 732 if err != nil { 733 t.Fatalf("unable to convert witness stack to sigScript: %v", err) 734 } 735 736 vm, err = txscript.NewEngine(regularOutput.PkScript, 737 sweepTx, 0, input.ScriptVerifyFlags, regularOutput.Version, nil) 738 if err != nil { 739 t.Fatalf("unable to create engine: %v", err) 740 } 741 if err := vm.Execute(); err != nil { 742 t.Fatalf("bob p2wkh spend is invalid: %v", err) 743 } 744 } 745 746 // TestCommitmentSpendValidation test the spendability of both outputs within 747 // the commitment transaction. 748 // 749 // The following spending cases are covered by this test: 750 // - Alice's spend from the delayed output on her commitment transaction. 751 // - Bob's spend from Alice's delayed output when she broadcasts a revoked 752 // commitment transaction. 753 // - Bob's spend from his unencumbered output within Alice's commitment 754 // transaction. 755 func TestCommitmentSpendValidation(t *testing.T) { 756 t.Parallel() 757 758 // In the modern network, all channels use the new tweakless format, 759 // but we also need to support older nodes that want to open channels 760 // with the legacy format, so we'll test spending in both scenarios. 761 for _, tweakless := range []bool{true, false} { 762 tweakless := tweakless 763 t.Run(fmt.Sprintf("tweak=%v", tweakless), func(t *testing.T) { 764 testSpendValidation(t, tweakless) 765 }) 766 } 767 } 768 769 type mockProducer struct { 770 secret shachain.ShaHash 771 } 772 773 func (p *mockProducer) AtIndex(uint64) (*shachain.ShaHash, error) { 774 return &p.secret, nil 775 } 776 777 func (p *mockProducer) Encode(w io.Writer) error { 778 _, err := w.Write(p.secret[:]) 779 return err 780 } 781 782 // createTestChannelsForVectors creates two LightningChannel instances for the 783 // test channel that is used to verify the test vectors. 784 func createTestChannelsForVectors(tc *testContext, chanType channeldb.ChannelType, 785 feeRate dcrutil.Amount, remoteBalance, localBalance dcrutil.Amount) ( 786 *LightningChannel, *LightningChannel, func()) { 787 788 t := tc.t 789 790 prevOut := &wire.OutPoint{ 791 Hash: *tc.fundingTx.Hash(), 792 Index: 0, 793 } 794 795 fundingTxIn := wire.NewTxIn(prevOut, 0, nil) 796 797 // Generate random some keys that don't actually matter but need to be 798 // set. 799 var ( 800 remoteDummy1, remoteDummy2 *secp256k1.PrivateKey 801 localDummy2, localDummy1 *secp256k1.PrivateKey 802 ) 803 generateKeys := []**secp256k1.PrivateKey{ 804 &remoteDummy1, &remoteDummy2, &localDummy1, &localDummy2, 805 } 806 for _, keyRef := range generateKeys { 807 privkey, err := secp256k1.GeneratePrivateKey() 808 require.NoError(t, err) 809 *keyRef = privkey 810 } 811 812 // Define channel configurations. 813 remoteCfg := channeldb.ChannelConfig{ 814 ChannelConstraints: channeldb.ChannelConstraints{ 815 DustLimit: tc.dustLimit, 816 MaxPendingAmount: lnwire.NewMAtomsFromAtoms( 817 tc.fundingAmount, 818 ), 819 ChanReserve: 0, 820 MinHTLC: 0, 821 MaxAcceptedHtlcs: input.MaxHTLCNumber / 2, 822 CsvDelay: tc.localCsvDelay, 823 }, 824 MultiSigKey: keychain.KeyDescriptor{ 825 PubKey: tc.remoteFundingPrivkey.PubKey(), 826 }, 827 PaymentBasePoint: keychain.KeyDescriptor{ 828 PubKey: tc.remotePaymentBasepointSecret.PubKey(), 829 }, 830 HtlcBasePoint: keychain.KeyDescriptor{ 831 PubKey: tc.remotePaymentBasepointSecret.PubKey(), 832 }, 833 DelayBasePoint: keychain.KeyDescriptor{ 834 PubKey: remoteDummy1.PubKey(), 835 }, 836 RevocationBasePoint: keychain.KeyDescriptor{ 837 PubKey: tc.remoteRevocationBasepointSecret.PubKey(), 838 }, 839 } 840 localCfg := channeldb.ChannelConfig{ 841 ChannelConstraints: channeldb.ChannelConstraints{ 842 DustLimit: tc.dustLimit, 843 MaxPendingAmount: lnwire.NewMAtomsFromAtoms( 844 tc.fundingAmount, 845 ), 846 ChanReserve: 0, 847 MinHTLC: 0, 848 MaxAcceptedHtlcs: input.MaxHTLCNumber / 2, 849 CsvDelay: tc.localCsvDelay, 850 }, 851 MultiSigKey: keychain.KeyDescriptor{ 852 PubKey: tc.localFundingPrivkey.PubKey(), 853 }, 854 PaymentBasePoint: keychain.KeyDescriptor{ 855 PubKey: tc.localPaymentBasepointSecret.PubKey(), 856 }, 857 HtlcBasePoint: keychain.KeyDescriptor{ 858 PubKey: tc.localPaymentBasepointSecret.PubKey(), 859 }, 860 DelayBasePoint: keychain.KeyDescriptor{ 861 PubKey: tc.localDelayedPaymentBasepointSecret.PubKey(), 862 }, 863 RevocationBasePoint: keychain.KeyDescriptor{ 864 PubKey: localDummy1.PubKey(), 865 }, 866 } 867 868 // Create mock producers to force usage of the test vector commitment 869 // point. 870 remotePreimageProducer := &mockProducer{ 871 secret: shachain.ShaHash(tc.localPerCommitSecret), 872 } 873 remoteCommitPoint := input.ComputeCommitmentPoint( 874 tc.localPerCommitSecret[:], 875 ) 876 877 localPreimageProducer := &mockProducer{ 878 secret: shachain.ShaHash(tc.localPerCommitSecret), 879 } 880 localCommitPoint := input.ComputeCommitmentPoint( 881 tc.localPerCommitSecret[:], 882 ) 883 884 // Create temporary databases. 885 remotePath, err := ioutil.TempDir("", "remotedb") 886 require.NoError(t, err) 887 888 dbRemote, err := channeldb.Open(remotePath) 889 require.NoError(t, err) 890 891 localPath, err := ioutil.TempDir("", "localdb") 892 require.NoError(t, err) 893 894 dbLocal, err := channeldb.Open(localPath) 895 require.NoError(t, err) 896 897 // Create the initial commitment transactions for the channel. 898 feePerKB := chainfee.AtomPerKByte(feeRate) 899 commitSize := input.CommitmentTxSize 900 if chanType.HasAnchors() { 901 commitSize = input.CommitmentWithAnchorsTxSize 902 } 903 commitFee := feePerKB.FeeForSize(commitSize) 904 905 var anchorAmt dcrutil.Amount 906 if chanType.HasAnchors() { 907 anchorAmt = 2 * anchorSize 908 } 909 910 remoteCommitTx, localCommitTx, err := CreateCommitmentTxns( 911 remoteBalance, localBalance-commitFee, 912 &remoteCfg, &localCfg, remoteCommitPoint, 913 localCommitPoint, *fundingTxIn, chanType, true, 0, tc.params, 914 ) 915 require.NoError(t, err) 916 917 // Set up the full channel state. 918 919 // Subtract one because extra sig exchange will take place during setup 920 // to get to the right test point. 921 var commitHeight = tc.commitHeight - 1 922 923 remoteCommit := channeldb.ChannelCommitment{ 924 CommitHeight: commitHeight, 925 LocalBalance: lnwire.NewMAtomsFromAtoms(remoteBalance), 926 RemoteBalance: lnwire.NewMAtomsFromAtoms(localBalance - commitFee - anchorAmt), 927 CommitFee: commitFee, 928 FeePerKB: dcrutil.Amount(feePerKB), 929 CommitTx: remoteCommitTx, 930 CommitSig: testSigBytes, 931 } 932 localCommit := channeldb.ChannelCommitment{ 933 CommitHeight: commitHeight, 934 LocalBalance: lnwire.NewMAtomsFromAtoms(localBalance - commitFee - anchorAmt), 935 RemoteBalance: lnwire.NewMAtomsFromAtoms(remoteBalance), 936 CommitFee: commitFee, 937 FeePerKB: dcrutil.Amount(feePerKB), 938 CommitTx: localCommitTx, 939 CommitSig: testSigBytes, 940 } 941 942 var chanIDBytes [8]byte 943 _, err = io.ReadFull(rand.Reader, chanIDBytes[:]) 944 require.NoError(t, err) 945 946 shortChanID := lnwire.NewShortChanIDFromInt( 947 binary.BigEndian.Uint64(chanIDBytes[:]), 948 ) 949 950 remoteChannelState := &channeldb.OpenChannel{ 951 LocalChanCfg: remoteCfg, 952 RemoteChanCfg: localCfg, 953 IdentityPub: remoteDummy2.PubKey(), 954 FundingOutpoint: *prevOut, 955 ShortChannelID: shortChanID, 956 ChanType: chanType, 957 IsInitiator: false, 958 Capacity: tc.fundingAmount, 959 RemoteCurrentRevocation: localCommitPoint, 960 RevocationProducer: remotePreimageProducer, 961 RevocationStore: shachain.NewRevocationStore(), 962 LocalCommitment: remoteCommit, 963 RemoteCommitment: remoteCommit, 964 Db: dbRemote.ChannelStateDB(), 965 Packager: channeldb.NewChannelPackager(shortChanID), 966 FundingTxn: tc.fundingTx.MsgTx(), 967 } 968 localChannelState := &channeldb.OpenChannel{ 969 LocalChanCfg: localCfg, 970 RemoteChanCfg: remoteCfg, 971 IdentityPub: localDummy2.PubKey(), 972 FundingOutpoint: *prevOut, 973 ShortChannelID: shortChanID, 974 ChanType: chanType, 975 IsInitiator: true, 976 Capacity: tc.fundingAmount, 977 RemoteCurrentRevocation: remoteCommitPoint, 978 RevocationProducer: localPreimageProducer, 979 RevocationStore: shachain.NewRevocationStore(), 980 LocalCommitment: localCommit, 981 RemoteCommitment: localCommit, 982 Db: dbLocal.ChannelStateDB(), 983 Packager: channeldb.NewChannelPackager(shortChanID), 984 FundingTxn: tc.fundingTx.MsgTx(), 985 } 986 987 // Create mock signers that can sign for the keys that are used. 988 localSigner := &input.MockSigner{Privkeys: []*secp256k1.PrivateKey{ 989 tc.localPaymentBasepointSecret, tc.localDelayedPaymentBasepointSecret, 990 tc.localFundingPrivkey, localDummy1, localDummy2, 991 }} 992 993 remoteSigner := &input.MockSigner{Privkeys: []*secp256k1.PrivateKey{ 994 tc.remoteFundingPrivkey, tc.remoteRevocationBasepointSecret, 995 tc.remotePaymentBasepointSecret, remoteDummy1, remoteDummy2, 996 }} 997 998 remotePool := NewSigPool(1, remoteSigner) 999 channelRemote, err := NewLightningChannel( 1000 remoteSigner, remoteChannelState, remotePool, tc.params, 1001 ) 1002 require.NoError(t, err) 1003 require.NoError(t, remotePool.Start()) 1004 1005 localPool := NewSigPool(1, localSigner) 1006 channelLocal, err := NewLightningChannel( 1007 localSigner, localChannelState, localPool, tc.params, 1008 ) 1009 require.NoError(t, err) 1010 require.NoError(t, localPool.Start()) 1011 1012 // Create state hunt obfuscator for the commitment transaction. 1013 obfuscator := createStateHintObfuscator(remoteChannelState) 1014 err = SetStateNumHint( 1015 remoteCommitTx, commitHeight, obfuscator, 1016 ) 1017 require.NoError(t, err) 1018 1019 err = SetStateNumHint( 1020 localCommitTx, commitHeight, obfuscator, 1021 ) 1022 require.NoError(t, err) 1023 1024 // Initialize the database. 1025 addr := &net.TCPAddr{ 1026 IP: net.ParseIP("127.0.0.1"), 1027 Port: 18556, 1028 } 1029 require.NoError(t, channelRemote.channelState.SyncPending(addr, 101)) 1030 1031 addr = &net.TCPAddr{ 1032 IP: net.ParseIP("127.0.0.1"), 1033 Port: 18555, 1034 } 1035 require.NoError(t, channelLocal.channelState.SyncPending(addr, 101)) 1036 1037 // Now that the channel are open, simulate the start of a session by 1038 // having local and remote extend their revocation windows to each other. 1039 err = initRevocationWindows(channelRemote, channelLocal) 1040 require.NoError(t, err) 1041 1042 // Return a clean up function that stops goroutines and removes the test 1043 // databases. 1044 cleanUpFunc := func() { 1045 dbLocal.Close() 1046 dbRemote.Close() 1047 1048 os.RemoveAll(localPath) 1049 os.RemoveAll(remotePath) 1050 1051 require.NoError(t, remotePool.Stop()) 1052 require.NoError(t, localPool.Stop()) 1053 } 1054 1055 return channelRemote, channelLocal, cleanUpFunc 1056 } 1057 1058 // checkLnTransactionSanity checks whether an ln transaction (funding, 1059 // commitment, etc) is reasonably sane according to consensus and standardness 1060 // checks that don't require a full backing blockchain to verify. 1061 func checkLnTransactionSanity(tx *wire.MsgTx, utxos map[wire.OutPoint]*wire.TxOut, netParams *chaincfg.Params) error { 1062 err := standalone.CheckTransactionSanity(tx, uint64(netParams.MaxTxSize)) 1063 if err != nil { 1064 return fmt.Errorf("error checking tx sanity: %v", err) 1065 } 1066 1067 var inputSum int64 1068 var outputSum int64 1069 1070 txType := stake.DetermineTxType(tx) 1071 if txType != stake.TxTypeRegular { 1072 return fmt.Errorf("transaction is not of the regular type") 1073 } 1074 if tx.Expiry != wire.NoExpiryValue { 1075 return fmt.Errorf("expiry for the tx is not %d", wire.NoExpiryValue) 1076 } 1077 if tx.Version != input.LNTxVersion { 1078 return fmt.Errorf("tx version (%d) different than expected (%d)", 1079 tx.Version, input.LNTxVersion) 1080 } 1081 for i, out := range tx.TxOut { 1082 if out.Version != scriptVersion { 1083 return fmt.Errorf("output %d of tx does not use the "+ 1084 "default script version (found %d)", i, out.Version) 1085 } 1086 1087 outputSum += out.Value 1088 } 1089 for i, in := range tx.TxIn { 1090 utxo, hasUtxo := utxos[in.PreviousOutPoint] 1091 if !hasUtxo { 1092 return fmt.Errorf("utxo for input %d (%s) of tx not provided", i, 1093 in.PreviousOutPoint) 1094 } 1095 1096 engine, err := txscript.NewEngine(utxo.PkScript, tx, i, 1097 input.ScriptVerifyFlags, utxo.Version, nil) 1098 if err != nil { 1099 return fmt.Errorf("error creating engine to process input %d: %v", 1100 i, err) 1101 } 1102 1103 err = engine.Execute() 1104 if err != nil { 1105 return fmt.Errorf("error executing script of input %d: %v", i, err) 1106 } 1107 1108 inputSum += utxo.Value 1109 } 1110 1111 if (outputSum > inputSum) || (outputSum < 0) { 1112 return fmt.Errorf("sum of output amounts > sum of input amounts") 1113 } 1114 1115 return nil 1116 } 1117 1118 // checkSignedCommitmentTxSanity checks whether a commitment transaction is 1119 // reasonably sane according to consensus and standardness checks that don't 1120 // require a full backing blockchain to verify. 1121 // 1122 // It assumes the commit transaction input previous outpoint is correctly 1123 // pointing to the passed fundingTxOut. 1124 func checkSignedCommitmentTxSanity(commitTx *wire.MsgTx, fundingTxOut *wire.TxOut, netParams *chaincfg.Params) error { 1125 1126 if len(commitTx.TxIn) != 1 { 1127 return fmt.Errorf("commit transaction has invalid number of inputs") 1128 } 1129 1130 utxos := make(map[wire.OutPoint]*wire.TxOut, 1) 1131 utxos[commitTx.TxIn[0].PreviousOutPoint] = fundingTxOut 1132 1133 return checkLnTransactionSanity(commitTx, utxos, netParams) 1134 } 1135 1136 // checkSignedCommitmentSpendingTxSanity checks whether a transaction spending 1137 // from a commitment transaction (eg: an htlc resolution transaction or a breach 1138 // remedy transaction ) is reasonably sane according to consensus and 1139 // standardness checks that don't require a full backing blockchain to verify. 1140 // 1141 // This assumes the commitment transaction is sane (ie 1142 // checkSignedCommitmentTxSanity returns nil). 1143 func checkSignedCommitmentSpendingTxSanity(spendTx, commitTx *wire.MsgTx, netParams *chaincfg.Params) error { 1144 1145 commitTxHash := commitTx.TxHash() 1146 countCommitOuts := uint32(len(commitTx.TxOut)) 1147 1148 utxos := make(map[wire.OutPoint]*wire.TxOut, len(spendTx.TxIn)) 1149 for i, in := range spendTx.TxIn { 1150 outp := in.PreviousOutPoint 1151 if (outp.Hash != commitTxHash) || (outp.Index >= countCommitOuts) || 1152 (outp.Tree != wire.TxTreeRegular) { 1153 1154 return fmt.Errorf("input %d of spender tx does not spend from "+ 1155 "commit tx", i) 1156 } 1157 utxos[outp] = commitTx.TxOut[outp.Index] 1158 } 1159 1160 return checkLnTransactionSanity(spendTx, utxos, netParams) 1161 }