github.com/decred/dcrlnd@v0.7.6/input/script_utils_test.go (about) 1 package input 2 3 import ( 4 "bytes" 5 "crypto/sha256" 6 "encoding/hex" 7 "fmt" 8 "testing" 9 10 "github.com/decred/dcrd/chaincfg/chainhash" 11 "github.com/decred/dcrd/dcrec/secp256k1/v4" 12 "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" 13 "github.com/decred/dcrd/dcrutil/v4" 14 "github.com/decred/dcrd/txscript/v4" 15 "github.com/decred/dcrd/wire" 16 "github.com/decred/dcrlnd/keychain" 17 "github.com/stretchr/testify/require" 18 ) 19 20 const scriptVersion uint16 = 0 21 22 func privKeyFromBytes(b []byte) (*secp256k1.PrivateKey, *secp256k1.PublicKey) { 23 priv := secp256k1.PrivKeyFromBytes(b) 24 return priv, priv.PubKey() 25 } 26 27 // assertEngineExecution executes the VM returned by the newEngine closure, 28 // asserting the result matches the validity expectation. In the case where it 29 // doesn't match the expectation, it executes the script step-by-step and 30 // prints debug information to stdout. 31 func assertEngineExecution(t *testing.T, testNum int, valid bool, 32 newEngine func() (*txscript.Engine, error)) { 33 t.Helper() 34 35 // Get a new VM to execute. 36 vm, err := newEngine() 37 if err != nil { 38 t.Fatalf("unable to create engine: %v", err) 39 } 40 41 // Execute the VM, only go on to the step-by-step execution if 42 // it doesn't validate as expected. 43 vmErr := vm.Execute() 44 if valid == (vmErr == nil) { 45 return 46 } 47 48 // Now that the execution didn't match what we expected, fetch a new VM 49 // to step through. 50 vm, err = newEngine() 51 if err != nil { 52 t.Fatalf("unable to create engine: %v", err) 53 } 54 55 // This buffer will trace execution of the Script, dumping out 56 // to stdout. 57 var debugBuf bytes.Buffer 58 59 done := false 60 for !done { 61 dis, err := vm.DisasmPC() 62 if err != nil { 63 t.Fatalf("stepping (%v)\n", err) 64 } 65 debugBuf.WriteString(fmt.Sprintf("stepping %v\n", dis)) 66 67 done, err = vm.Step() 68 if err != nil && valid { 69 fmt.Println(debugBuf.String()) 70 t.Fatalf("spend test case #%v failed, spend "+ 71 "should be valid: %v", testNum, err) 72 } else if err == nil && !valid && done { 73 fmt.Println(debugBuf.String()) 74 t.Fatalf("spend test case #%v succeed, spend "+ 75 "should be invalid: %v", testNum, err) 76 } 77 78 debugBuf.WriteString(fmt.Sprintf("Stack: %v", vm.GetStack())) 79 debugBuf.WriteString(fmt.Sprintf("AltStack: %v", vm.GetAltStack())) 80 } 81 82 // If we get to this point the unexpected case was not reached 83 // during step execution, which happens for some checks, like 84 // the clean-stack rule. 85 validity := "invalid" 86 if valid { 87 validity = "valid" 88 } 89 90 fmt.Println(debugBuf.String()) 91 t.Fatalf("%v spend test case #%v execution ended with: %v", validity, testNum, vmErr) 92 } 93 94 // TestRevocationKeyDerivation tests that given a public key, and a revocation 95 // hash, the homomorphic revocation public and private key derivation work 96 // properly. 97 func TestRevocationKeyDerivation(t *testing.T) { 98 t.Parallel() 99 100 // First, we'll generate a commitment point, and a commitment secret. 101 // These will be used to derive the ultimate revocation keys. 102 revocationPreimage := testHdSeed.CloneBytes() 103 commitSecret, commitPoint := privKeyFromBytes(revocationPreimage) 104 105 // With the commitment secrets generated, we'll now create the base 106 // keys we'll use to derive the revocation key from. 107 basePriv, basePub := privKeyFromBytes(testWalletPrivKey) 108 109 // With the point and key obtained, we can now derive the revocation 110 // key itself. 111 revocationPub := DeriveRevocationPubkey(basePub, commitPoint) 112 113 // The revocation public key derived from the original public key, and 114 // the one derived from the private key should be identical. 115 revocationPriv := DeriveRevocationPrivKey(basePriv, commitSecret) 116 if !revocationPub.IsEqual(revocationPriv.PubKey()) { 117 t.Fatalf("derived public keys don't match!") 118 } 119 } 120 121 // TestTweakKeyDerivation tests that given a public key, and commitment tweak, 122 // then we're able to properly derive a tweaked private key that corresponds to 123 // the computed tweak public key. This scenario ensure that our key derivation 124 // for any of the non revocation keys on the commitment transaction is correct. 125 func TestTweakKeyDerivation(t *testing.T) { 126 t.Parallel() 127 128 // First, we'll generate a base public key that we'll be "tweaking". 129 baseSecret := testHdSeed.CloneBytes() 130 basePriv, basePub := privKeyFromBytes(baseSecret) 131 132 // With the base key create, we'll now create a commitment point, and 133 // from that derive the bytes we'll used to tweak the base public key. 134 commitPoint := ComputeCommitmentPoint(bobsPrivKey) 135 commitTweak := SingleTweakBytes(commitPoint, basePub) 136 137 // Next, we'll modify the public key. When we apply the same operation 138 // to the private key we should get a key that matches. 139 tweakedPub := TweakPubKey(basePub, commitPoint) 140 141 // Finally, attempt to re-generate the private key that matches the 142 // tweaked public key. The derived key should match exactly. 143 derivedPriv := TweakPrivKey(basePriv, commitTweak) 144 if !derivedPriv.PubKey().IsEqual(tweakedPub) { 145 t.Fatalf("pub keys don't match") 146 } 147 } 148 149 // makeWitnessTestCase is a helper function used within test cases involving 150 // the validity of a crafted witness. This function is a wrapper function which 151 // allows constructing table-driven tests. In the case of an error while 152 // constructing the witness, the test fails fatally. 153 func makeWitnessTestCase(t *testing.T, 154 f func() (TxWitness, error)) func() TxWitness { 155 156 return func() TxWitness { 157 witness, err := f() 158 if err != nil { 159 t.Fatalf("unable to create witness test case: %v", err) 160 } 161 162 return witness 163 } 164 } 165 166 // TestHTLCSenderSpendValidation tests all possible valid+invalid redemption 167 // paths in the script used within the sender's commitment transaction for an 168 // outgoing HTLC. 169 // 170 // The following cases are exercised by this test: 171 // sender script: 172 // - receiver spends 173 // - revoke w/ sig 174 // - HTLC with invalid preimage size 175 // - HTLC with valid preimage size + sig 176 // - sender spends 177 // - invalid lock-time for CLTV 178 // - invalid sequence for CSV 179 // - valid lock-time+sequence, valid sig 180 func TestHTLCSenderSpendValidation(t *testing.T) { 181 t.Parallel() 182 183 // We generate a fake output, and the corresponding txin. This output 184 // doesn't need to exist, as we'll only be validating spending from the 185 // transaction that references this. 186 txid, err := chainhash.NewHash(testHdSeed.CloneBytes()) 187 if err != nil { 188 t.Fatalf("unable to create txid: %v", err) 189 } 190 fundingOut := &wire.OutPoint{ 191 Hash: *txid, 192 Index: 50, 193 } 194 fakeFundingTxIn := wire.NewTxIn(fundingOut, 0, nil) // TODO(decred): Need correct input value 195 196 // Next we'll the commitment secret for our commitment tx and also the 197 // revocation key that we'll use as well. 198 revokePreimage := testHdSeed.CloneBytes() 199 commitSecret, commitPoint := privKeyFromBytes(revokePreimage) 200 201 // Generate a payment preimage to be used below. 202 paymentPreimage := revokePreimage 203 paymentPreimage[0] ^= 1 204 paymentHash := sha256.Sum256(paymentPreimage) 205 206 // We'll also need some tests keys for alice and bob, and metadata of 207 // the HTLC output. 208 aliceKeyPriv, aliceKeyPub := privKeyFromBytes(testWalletPrivKey) 209 bobKeyPriv, bobKeyPub := privKeyFromBytes(bobsPrivKey) 210 paymentAmt := dcrutil.Amount(1 * 10e8) 211 212 aliceLocalKey := TweakPubKey(aliceKeyPub, commitPoint) 213 bobLocalKey := TweakPubKey(bobKeyPub, commitPoint) 214 215 // As we'll be modeling spends from Alice's commitment transaction, 216 // we'll be using Bob's base point for the revocation key. 217 revocationKey := DeriveRevocationPubkey(bobKeyPub, commitPoint) 218 219 bobCommitTweak := SingleTweakBytes(commitPoint, bobKeyPub) 220 aliceCommitTweak := SingleTweakBytes(commitPoint, aliceKeyPub) 221 222 // Finally, we'll create mock signers for both of them based on their 223 // private keys. This test simplifies a bit and uses the same key as 224 // the base point for all scripts and derivations. 225 bobSigner := &MockSigner{Privkeys: []*secp256k1.PrivateKey{bobKeyPriv}} 226 aliceSigner := &MockSigner{Privkeys: []*secp256k1.PrivateKey{aliceKeyPriv}} 227 228 var ( 229 htlcWitnessScript, htlcPkScript []byte 230 htlcOutput *wire.TxOut 231 senderCommitTx, sweepTx *wire.MsgTx 232 bobRecvrSig *ecdsa.Signature 233 bobSigHash txscript.SigHashType 234 ) 235 236 // genCommitTx generates a commitment tx where the htlc output requires 237 // confirmation to be spent according to 'confirmed'. 238 genCommitTx := func(confirmed bool) { 239 // Generate the raw HTLC redemption scripts, and its p2wsh 240 // counterpart. 241 htlcWitnessScript, err = SenderHTLCScript( 242 aliceLocalKey, bobLocalKey, revocationKey, 243 paymentHash[:], confirmed, 244 ) 245 if err != nil { 246 t.Fatalf("unable to create htlc sender script: %v", err) 247 } 248 htlcPkScript, err = ScriptHashPkScript(htlcWitnessScript) 249 if err != nil { 250 t.Fatalf("unable to create p2wsh htlc script: %v", err) 251 } 252 253 // This will be Alice's commitment transaction. In this 254 // scenario Alice is sending an HTLC to a node she has a path 255 // to (could be Bob, could be multiple hops down, it doesn't 256 // really matter). 257 htlcOutput = &wire.TxOut{ 258 Value: int64(paymentAmt), 259 PkScript: htlcPkScript, 260 Version: scriptVersion, 261 } 262 senderCommitTx = wire.NewMsgTx() 263 senderCommitTx.Version = LNTxVersion 264 senderCommitTx.AddTxIn(fakeFundingTxIn) 265 senderCommitTx.AddTxOut(htlcOutput) 266 } 267 268 // genSweepTx generates a sweep of the senderCommitTx, and sets the 269 // sequence and sighash single|anyonecanspend if confirmed is true. 270 genSweepTx := func(confirmed bool) { 271 prevOut := &wire.OutPoint{ 272 Hash: senderCommitTx.TxHash(), 273 Index: 0, 274 } 275 276 sweepTx = wire.NewMsgTx() 277 sweepTx.Version = LNTxVersion 278 279 sweepTx.AddTxIn(wire.NewTxIn(prevOut, 0, nil)) // TODO(decred) need correct input value 280 if confirmed { 281 sweepTx.TxIn[0].Sequence = LockTimeToSequence(false, 1) 282 } 283 284 sweepTx.AddTxOut( 285 &wire.TxOut{ 286 PkScript: []byte("doesn't matter"), 287 Value: 1 * 10e8, 288 }, 289 ) 290 291 bobSigHash = txscript.SigHashAll 292 if confirmed { 293 bobSigHash = txscript.SigHashSingle | txscript.SigHashAnyOneCanPay 294 } 295 296 // We'll also generate a signature on the sweep transaction above 297 // that will act as Bob's signature to Alice for the second level HTLC 298 // transaction. 299 bobSignDesc := SignDescriptor{ 300 KeyDesc: keychain.KeyDescriptor{ 301 PubKey: bobKeyPub, 302 }, 303 SingleTweak: bobCommitTweak, 304 WitnessScript: htlcWitnessScript, 305 Output: htlcOutput, 306 HashType: bobSigHash, 307 InputIndex: 0, 308 } 309 bobSig, err := bobSigner.SignOutputRaw(sweepTx, &bobSignDesc) 310 if err != nil { 311 t.Fatalf("unable to generate alice signature: %v", err) 312 } 313 314 bobRecvrSig, err = ecdsa.ParseDERSignature( 315 bobSig.Serialize(), 316 ) 317 if err != nil { 318 t.Fatalf("unable to parse signature: %v", err) 319 } 320 } 321 322 testCases := []struct { 323 witness func() TxWitness 324 valid bool 325 }{ 326 { 327 // revoke w/ sig 328 // TODO(roasbeef): test invalid revoke 329 makeWitnessTestCase(t, func() (TxWitness, error) { 330 genCommitTx(false) 331 genSweepTx(false) 332 333 signDesc := &SignDescriptor{ 334 KeyDesc: keychain.KeyDescriptor{ 335 PubKey: bobKeyPub, 336 }, 337 DoubleTweak: commitSecret, 338 WitnessScript: htlcWitnessScript, 339 Output: htlcOutput, 340 HashType: txscript.SigHashAll, 341 InputIndex: 0, 342 } 343 344 return SenderHtlcSpendRevokeWithKey(bobSigner, signDesc, 345 revocationKey, sweepTx) 346 }), 347 true, 348 }, 349 { 350 // HTLC with invalid preimage size 351 makeWitnessTestCase(t, func() (TxWitness, error) { 352 genCommitTx(false) 353 genSweepTx(false) 354 355 signDesc := &SignDescriptor{ 356 KeyDesc: keychain.KeyDescriptor{ 357 PubKey: bobKeyPub, 358 }, 359 SingleTweak: bobCommitTweak, 360 WitnessScript: htlcWitnessScript, 361 Output: htlcOutput, 362 HashType: txscript.SigHashAll, 363 InputIndex: 0, 364 } 365 366 return SenderHtlcSpendRedeem(bobSigner, signDesc, 367 sweepTx, 368 // Invalid preimage length 369 bytes.Repeat([]byte{1}, 45)) 370 }), 371 false, 372 }, 373 { 374 // HTLC with valid preimage size + sig 375 // TODO(roasbeef): invalid preimage 376 makeWitnessTestCase(t, func() (TxWitness, error) { 377 genCommitTx(false) 378 genSweepTx(false) 379 380 signDesc := &SignDescriptor{ 381 KeyDesc: keychain.KeyDescriptor{ 382 PubKey: bobKeyPub, 383 }, 384 SingleTweak: bobCommitTweak, 385 WitnessScript: htlcWitnessScript, 386 Output: htlcOutput, 387 HashType: txscript.SigHashAll, 388 InputIndex: 0, 389 } 390 391 return SenderHtlcSpendRedeem(bobSigner, signDesc, 392 sweepTx, paymentPreimage) 393 }), 394 true, 395 }, 396 { 397 // HTLC with valid preimage size + sig, and with 398 // enforced locktime in HTLC script. 399 makeWitnessTestCase(t, func() (TxWitness, error) { 400 // Make a commit tx that needs confirmation for 401 // HTLC output to be spent. 402 genCommitTx(true) 403 404 // Generate a sweep with the locktime set. 405 genSweepTx(true) 406 407 signDesc := &SignDescriptor{ 408 KeyDesc: keychain.KeyDescriptor{ 409 PubKey: bobKeyPub, 410 }, 411 SingleTweak: bobCommitTweak, 412 WitnessScript: htlcWitnessScript, 413 Output: htlcOutput, 414 HashType: txscript.SigHashAll, 415 InputIndex: 0, 416 } 417 418 return SenderHtlcSpendRedeem(bobSigner, signDesc, 419 sweepTx, paymentPreimage) 420 }), 421 true, 422 }, 423 { 424 // HTLC with valid preimage size + sig, but trying to 425 // spend CSV output without sequence set. 426 makeWitnessTestCase(t, func() (TxWitness, error) { 427 // Generate commitment tx with 1 CSV locked 428 // HTLC. 429 genCommitTx(true) 430 431 // Generate sweep tx that doesn't have locktime 432 // enabled. 433 genSweepTx(false) 434 435 signDesc := &SignDescriptor{ 436 KeyDesc: keychain.KeyDescriptor{ 437 PubKey: bobKeyPub, 438 }, 439 SingleTweak: bobCommitTweak, 440 WitnessScript: htlcWitnessScript, 441 Output: htlcOutput, 442 HashType: txscript.SigHashAll, 443 InputIndex: 0, 444 } 445 446 return SenderHtlcSpendRedeem(bobSigner, signDesc, 447 sweepTx, paymentPreimage) 448 }), 449 false, 450 }, 451 452 { 453 // valid spend to the transition the state of the HTLC 454 // output with the second level HTLC timeout 455 // transaction. 456 makeWitnessTestCase(t, func() (TxWitness, error) { 457 genCommitTx(false) 458 genSweepTx(false) 459 460 signDesc := &SignDescriptor{ 461 KeyDesc: keychain.KeyDescriptor{ 462 PubKey: aliceKeyPub, 463 }, 464 SingleTweak: aliceCommitTweak, 465 WitnessScript: htlcWitnessScript, 466 Output: htlcOutput, 467 HashType: txscript.SigHashAll, 468 InputIndex: 0, 469 } 470 471 return SenderHtlcSpendTimeout( 472 bobRecvrSig, bobSigHash, aliceSigner, 473 signDesc, sweepTx, 474 ) 475 }), 476 true, 477 }, 478 { 479 // valid spend to the transition the state of the HTLC 480 // output with the second level HTLC timeout 481 // transaction. 482 makeWitnessTestCase(t, func() (TxWitness, error) { 483 // Make a commit tx that needs confirmation for 484 // HTLC output to be spent. 485 genCommitTx(true) 486 487 // Generate a sweep with the locktime set. 488 genSweepTx(true) 489 490 signDesc := &SignDescriptor{ 491 KeyDesc: keychain.KeyDescriptor{ 492 PubKey: aliceKeyPub, 493 }, 494 SingleTweak: aliceCommitTweak, 495 WitnessScript: htlcWitnessScript, 496 Output: htlcOutput, 497 HashType: txscript.SigHashAll, 498 InputIndex: 0, 499 } 500 501 return SenderHtlcSpendTimeout( 502 bobRecvrSig, bobSigHash, aliceSigner, 503 signDesc, sweepTx, 504 ) 505 }), 506 true, 507 }, 508 { 509 // valid spend to the transition the state of the HTLC 510 // output with the second level HTLC timeout 511 // transaction. 512 makeWitnessTestCase(t, func() (TxWitness, error) { 513 // Generate commitment tx with 1 CSV locked 514 // HTLC. 515 genCommitTx(true) 516 517 // Generate sweep tx that doesn't have locktime 518 // enabled. 519 genSweepTx(false) 520 521 signDesc := &SignDescriptor{ 522 KeyDesc: keychain.KeyDescriptor{ 523 PubKey: aliceKeyPub, 524 }, 525 SingleTweak: aliceCommitTweak, 526 WitnessScript: htlcWitnessScript, 527 Output: htlcOutput, 528 HashType: txscript.SigHashAll, 529 InputIndex: 0, 530 } 531 532 return SenderHtlcSpendTimeout( 533 bobRecvrSig, bobSigHash, aliceSigner, 534 signDesc, sweepTx, 535 ) 536 }), 537 false, 538 }, 539 } 540 541 // TODO(roasbeef): set of cases to ensure able to sign w/ keypath and 542 // not 543 544 for i, testCase := range testCases { 545 sweepTx.TxIn[0].SignatureScript, err = WitnessStackToSigScript(testCase.witness()) 546 if err != nil { 547 t.Fatalf("unable to convert witness stack to sigScript: %v", err) 548 } 549 550 newEngine := func() (*txscript.Engine, error) { 551 return txscript.NewEngine(htlcPkScript, 552 sweepTx, 0, ScriptVerifyFlags, htlcOutput.Version, 553 nil) 554 } 555 556 assertEngineExecution(t, i, testCase.valid, newEngine) 557 } 558 } 559 560 // TestHTLCReceiverSpendValidation tests all possible valid+invalid redemption 561 // paths in the script used within the receiver's commitment transaction for an 562 // incoming HTLC. 563 // 564 // The following cases are exercised by this test: 565 // - receiver spends 566 // - HTLC redemption w/ invalid preimage size 567 // - HTLC redemption w/ invalid sequence 568 // - HTLC redemption w/ valid preimage size 569 // - sender spends 570 // - revoke w/ sig 571 // - refund w/ invalid lock time 572 // - refund w/ valid lock time 573 func TestHTLCReceiverSpendValidation(t *testing.T) { 574 t.Parallel() 575 576 // We generate a fake output, and the corresponding txin. This output 577 // doesn't need to exist, as we'll only be validating spending from the 578 // transaction that references this. 579 txid, err := chainhash.NewHash(testHdSeed.CloneBytes()) 580 if err != nil { 581 t.Fatalf("unable to create txid: %v", err) 582 } 583 fundingOut := &wire.OutPoint{ 584 Hash: *txid, 585 Index: 50, 586 } 587 fakeFundingTxIn := wire.NewTxIn(fundingOut, 0, nil) // TODO(decred): Need correct input value 588 589 // Next we'll the commitment secret for our commitment tx and also the 590 // revocation key that we'll use as well. 591 revokePreimage := testHdSeed.CloneBytes() 592 commitSecret, commitPoint := privKeyFromBytes(revokePreimage) 593 594 // Generate a payment preimage to be used below. 595 paymentPreimage := revokePreimage 596 paymentPreimage[0] ^= 1 597 paymentHash := sha256.Sum256(paymentPreimage) 598 599 // We'll also need some tests keys for alice and bob, and metadata of 600 // the HTLC output. 601 aliceKeyPriv, aliceKeyPub := privKeyFromBytes( 602 testWalletPrivKey) 603 bobKeyPriv, bobKeyPub := privKeyFromBytes(bobsPrivKey) 604 paymentAmt := dcrutil.Amount(1 * 10e8) 605 cltvTimeout := uint32(8) 606 607 aliceLocalKey := TweakPubKey(aliceKeyPub, commitPoint) 608 bobLocalKey := TweakPubKey(bobKeyPub, commitPoint) 609 610 // As we'll be modeling spends from Bob's commitment transaction, we'll 611 // be using Alice's base point for the revocation key. 612 revocationKey := DeriveRevocationPubkey(aliceKeyPub, commitPoint) 613 614 bobCommitTweak := SingleTweakBytes(commitPoint, bobKeyPub) 615 aliceCommitTweak := SingleTweakBytes(commitPoint, aliceKeyPub) 616 617 // Finally, we'll create mock signers for both of them based on their 618 // private keys. This test simplifies a bit and uses the same key as 619 // the base point for all scripts and derivations. 620 bobSigner := &MockSigner{Privkeys: []*secp256k1.PrivateKey{bobKeyPriv}} 621 aliceSigner := &MockSigner{Privkeys: []*secp256k1.PrivateKey{aliceKeyPriv}} 622 623 var ( 624 htlcWitnessScript, htlcPkScript []byte 625 htlcOutput *wire.TxOut 626 receiverCommitTx, sweepTx *wire.MsgTx 627 aliceSenderSig *ecdsa.Signature 628 aliceSigHash txscript.SigHashType 629 ) 630 631 genCommitTx := func(confirmed bool) { 632 // Generate the raw HTLC redemption scripts, and its p2wsh 633 // counterpart. 634 htlcWitnessScript, err = ReceiverHTLCScript( 635 cltvTimeout, aliceLocalKey, bobLocalKey, revocationKey, 636 paymentHash[:], confirmed, 637 ) 638 if err != nil { 639 t.Fatalf("unable to create htlc sender script: %v", err) 640 } 641 htlcPkScript, err = ScriptHashPkScript(htlcWitnessScript) 642 if err != nil { 643 t.Fatalf("unable to create p2wsh htlc script: %v", err) 644 } 645 646 // This will be Bob's commitment transaction. In this scenario Alice is 647 // sending an HTLC to a node she has a path to (could be Bob, could be 648 // multiple hops down, it doesn't really matter). 649 htlcOutput = &wire.TxOut{ 650 Value: int64(paymentAmt), 651 PkScript: htlcWitnessScript, 652 } 653 654 receiverCommitTx = wire.NewMsgTx() 655 receiverCommitTx.Version = LNTxVersion 656 receiverCommitTx.AddTxIn(fakeFundingTxIn) 657 receiverCommitTx.AddTxOut(htlcOutput) 658 } 659 660 genSweepTx := func(confirmed bool) { 661 prevOut := &wire.OutPoint{ 662 Hash: receiverCommitTx.TxHash(), 663 Index: 0, 664 } 665 666 sweepTx = wire.NewMsgTx() 667 sweepTx.Version = LNTxVersion 668 sweepTx.AddTxIn(&wire.TxIn{ 669 PreviousOutPoint: *prevOut, 670 }) 671 if confirmed { 672 sweepTx.TxIn[0].Sequence = LockTimeToSequence(false, 1) 673 } 674 675 sweepTx.AddTxOut( 676 &wire.TxOut{ 677 PkScript: []byte("doesn't matter"), 678 Value: 1 * 10e8, 679 }, 680 ) 681 682 aliceSigHash = txscript.SigHashAll 683 if confirmed { 684 aliceSigHash = txscript.SigHashSingle | txscript.SigHashAnyOneCanPay 685 } 686 687 // We'll also generate a signature on the sweep transaction above 688 // that will act as Alice's signature to Bob for the second level HTLC 689 // transaction. 690 aliceSignDesc := SignDescriptor{ 691 KeyDesc: keychain.KeyDescriptor{ 692 PubKey: aliceKeyPub, 693 }, 694 SingleTweak: aliceCommitTweak, 695 WitnessScript: htlcWitnessScript, 696 Output: htlcOutput, 697 HashType: aliceSigHash, 698 InputIndex: 0, 699 } 700 aliceSigBytes, err := aliceSigner.SignOutputRaw(sweepTx, &aliceSignDesc) 701 if err != nil { 702 t.Fatalf("unable to generate alice signature: %v", err) 703 } 704 705 aliceSenderSig, err = ecdsa.ParseDERSignature( 706 aliceSigBytes.Serialize(), 707 ) 708 if err != nil { 709 t.Fatalf("unable to parse signature: %v", err) 710 } 711 } 712 713 // TODO(roasbeef): modify valid to check precise script errors? 714 testCases := []struct { 715 witness func() TxWitness 716 valid bool 717 }{ 718 { 719 // HTLC redemption w/ invalid preimage size 720 makeWitnessTestCase(t, func() (TxWitness, error) { 721 genCommitTx(false) 722 genSweepTx(false) 723 724 signDesc := &SignDescriptor{ 725 KeyDesc: keychain.KeyDescriptor{ 726 PubKey: bobKeyPub, 727 }, 728 SingleTweak: bobCommitTweak, 729 WitnessScript: htlcWitnessScript, 730 Output: htlcOutput, 731 HashType: txscript.SigHashAll, 732 InputIndex: 0, 733 } 734 735 return ReceiverHtlcSpendRedeem( 736 aliceSenderSig, aliceSigHash, 737 bytes.Repeat([]byte{1}, 45), bobSigner, 738 signDesc, sweepTx, 739 ) 740 741 }), 742 false, 743 }, 744 { 745 // HTLC redemption w/ valid preimage size 746 makeWitnessTestCase(t, func() (TxWitness, error) { 747 genCommitTx(false) 748 genSweepTx(false) 749 750 signDesc := &SignDescriptor{ 751 KeyDesc: keychain.KeyDescriptor{ 752 PubKey: bobKeyPub, 753 }, 754 SingleTweak: bobCommitTweak, 755 WitnessScript: htlcWitnessScript, 756 Output: htlcOutput, 757 HashType: txscript.SigHashAll, 758 InputIndex: 0, 759 } 760 761 return ReceiverHtlcSpendRedeem( 762 aliceSenderSig, aliceSigHash, 763 paymentPreimage, bobSigner, 764 signDesc, sweepTx, 765 ) 766 }), 767 true, 768 }, 769 { 770 // revoke w/ sig 771 makeWitnessTestCase(t, func() (TxWitness, error) { 772 genCommitTx(false) 773 genSweepTx(false) 774 775 signDesc := &SignDescriptor{ 776 KeyDesc: keychain.KeyDescriptor{ 777 PubKey: aliceKeyPub, 778 }, 779 DoubleTweak: commitSecret, 780 WitnessScript: htlcWitnessScript, 781 Output: htlcOutput, 782 HashType: txscript.SigHashAll, 783 InputIndex: 0, 784 } 785 786 return ReceiverHtlcSpendRevokeWithKey(aliceSigner, 787 signDesc, revocationKey, sweepTx) 788 }), 789 true, 790 }, 791 { 792 // HTLC redemption w/ valid preimage size, and with 793 // enforced locktime in HTLC scripts. 794 makeWitnessTestCase(t, func() (TxWitness, error) { 795 // Make a commit tx that needs confirmation for 796 // HTLC output to be spent. 797 genCommitTx(true) 798 799 // Generate a sweep with the locktime set. 800 genSweepTx(true) 801 802 signDesc := &SignDescriptor{ 803 KeyDesc: keychain.KeyDescriptor{ 804 PubKey: bobKeyPub, 805 }, 806 SingleTweak: bobCommitTweak, 807 WitnessScript: htlcWitnessScript, 808 Output: htlcOutput, 809 HashType: txscript.SigHashAll, 810 InputIndex: 0, 811 } 812 813 return ReceiverHtlcSpendRedeem( 814 aliceSenderSig, aliceSigHash, 815 paymentPreimage, bobSigner, 816 signDesc, sweepTx, 817 ) 818 }), 819 true, 820 }, 821 { 822 // HTLC redemption w/ valid preimage size, but trying 823 // to spend CSV output without sequence set. 824 makeWitnessTestCase(t, func() (TxWitness, error) { 825 // Generate commitment tx with 1 CSV locked 826 // HTLC. 827 genCommitTx(true) 828 829 // Generate sweep tx that doesn't have locktime 830 // enabled. 831 genSweepTx(false) 832 833 signDesc := &SignDescriptor{ 834 KeyDesc: keychain.KeyDescriptor{ 835 PubKey: bobKeyPub, 836 }, 837 SingleTweak: bobCommitTweak, 838 WitnessScript: htlcWitnessScript, 839 Output: htlcOutput, 840 HashType: txscript.SigHashAll, 841 InputIndex: 0, 842 } 843 844 return ReceiverHtlcSpendRedeem( 845 aliceSenderSig, aliceSigHash, 846 paymentPreimage, bobSigner, signDesc, 847 sweepTx, 848 ) 849 }), 850 false, 851 }, 852 853 { 854 // refund w/ invalid lock time 855 makeWitnessTestCase(t, func() (TxWitness, error) { 856 genCommitTx(false) 857 genSweepTx(false) 858 859 signDesc := &SignDescriptor{ 860 KeyDesc: keychain.KeyDescriptor{ 861 PubKey: aliceKeyPub, 862 }, 863 SingleTweak: aliceCommitTweak, 864 WitnessScript: htlcWitnessScript, 865 Output: htlcOutput, 866 HashType: txscript.SigHashAll, 867 InputIndex: 0, 868 } 869 870 return ReceiverHtlcSpendTimeout(aliceSigner, signDesc, 871 sweepTx, int32(cltvTimeout-2)) 872 }), 873 false, 874 }, 875 { 876 // refund w/ valid lock time 877 makeWitnessTestCase(t, func() (TxWitness, error) { 878 genCommitTx(false) 879 genSweepTx(false) 880 881 signDesc := &SignDescriptor{ 882 KeyDesc: keychain.KeyDescriptor{ 883 PubKey: aliceKeyPub, 884 }, 885 SingleTweak: aliceCommitTweak, 886 WitnessScript: htlcWitnessScript, 887 Output: htlcOutput, 888 HashType: txscript.SigHashAll, 889 InputIndex: 0, 890 } 891 892 return ReceiverHtlcSpendTimeout(aliceSigner, signDesc, 893 sweepTx, int32(cltvTimeout)) 894 }), 895 true, 896 }, 897 { 898 // refund w/ valid lock time, and enforced locktime in 899 // HTLC scripts. 900 makeWitnessTestCase(t, func() (TxWitness, error) { 901 // Make a commit tx that needs confirmation for 902 // HTLC output to be spent. 903 genCommitTx(true) 904 905 // Generate a sweep with the locktime set. 906 genSweepTx(true) 907 908 signDesc := &SignDescriptor{ 909 KeyDesc: keychain.KeyDescriptor{ 910 PubKey: aliceKeyPub, 911 }, 912 SingleTweak: aliceCommitTweak, 913 WitnessScript: htlcWitnessScript, 914 Output: htlcOutput, 915 HashType: txscript.SigHashAll, 916 InputIndex: 0, 917 } 918 919 return ReceiverHtlcSpendTimeout(aliceSigner, signDesc, 920 sweepTx, int32(cltvTimeout)) 921 }), 922 true, 923 }, 924 { 925 // refund w/ valid lock time, but no sequence set in 926 // sweep tx trying to spend CSV locked HTLC output. 927 makeWitnessTestCase(t, func() (TxWitness, error) { 928 // Generate commitment tx with 1 CSV locked 929 // HTLC. 930 genCommitTx(true) 931 932 // Generate sweep tx that doesn't have locktime 933 // enabled. 934 genSweepTx(false) 935 936 signDesc := &SignDescriptor{ 937 KeyDesc: keychain.KeyDescriptor{ 938 PubKey: aliceKeyPub, 939 }, 940 SingleTweak: aliceCommitTweak, 941 WitnessScript: htlcWitnessScript, 942 Output: htlcOutput, 943 HashType: txscript.SigHashAll, 944 InputIndex: 0, 945 } 946 947 return ReceiverHtlcSpendTimeout(aliceSigner, signDesc, 948 sweepTx, int32(cltvTimeout)) 949 }), 950 false, 951 }, 952 } 953 954 for i, testCase := range testCases { 955 sweepTx.TxIn[0].SignatureScript, err = WitnessStackToSigScript(testCase.witness()) 956 if err != nil { 957 t.Fatalf("unable to convert witness stack to sigScript: %v", err) 958 } 959 960 newEngine := func() (*txscript.Engine, error) { 961 return txscript.NewEngine(htlcPkScript, 962 sweepTx, 0, ScriptVerifyFlags, scriptVersion, 963 nil) 964 } 965 966 assertEngineExecution(t, i, testCase.valid, newEngine) 967 } 968 } 969 970 // TestSecondLevelHtlcSpends tests all the possible redemption clauses from the 971 // HTLC success and timeout covenant transactions. 972 func TestSecondLevelHtlcSpends(t *testing.T) { 973 t.Parallel() 974 975 // We'll start be creating a creating a 2 DCR HTLC. 976 const htlcAmt = dcrutil.Amount(2 * 10e8) 977 978 // In all of our scenarios, the CSV timeout to claim a self output will 979 // be 5 blocks. 980 const claimDelay = 5 981 982 // First we'll set up some initial key state for Alice and Bob that 983 // will be used in the scripts we created below. 984 aliceKeyPriv, aliceKeyPub := privKeyFromBytes(testWalletPrivKey) 985 bobKeyPriv, bobKeyPub := privKeyFromBytes(bobsPrivKey) 986 987 revokePreimage := testHdSeed.CloneBytes() 988 commitSecret, commitPoint := privKeyFromBytes(revokePreimage) 989 990 // As we're modeling this as Bob sweeping the HTLC on-chain from his 991 // commitment transaction after a period of time, we'll be using a 992 // revocation key derived from Alice's base point and his secret. 993 revocationKey := DeriveRevocationPubkey(aliceKeyPub, commitPoint) 994 995 // Next, craft a fake HTLC outpoint that we'll use to generate the 996 // sweeping transaction using. 997 txid, err := chainhash.NewHash(testHdSeed.CloneBytes()) 998 if err != nil { 999 t.Fatalf("unable to create txid: %v", err) 1000 } 1001 htlcOutPoint := &wire.OutPoint{ 1002 Hash: *txid, 1003 Index: 0, 1004 } 1005 sweepTx := wire.NewMsgTx() 1006 sweepTx.Version = LNTxVersion 1007 sweepTx.AddTxIn(wire.NewTxIn(htlcOutPoint, 0, nil)) // TODO(decred): Need correct input value 1008 sweepTx.AddTxOut( 1009 &wire.TxOut{ 1010 PkScript: []byte("doesn't matter"), 1011 Value: 1 * 10e8, 1012 }, 1013 ) 1014 1015 // The delay key will be crafted using Bob's public key as the output 1016 // we created will be spending from Alice's commitment transaction. 1017 delayKey := TweakPubKey(bobKeyPub, commitPoint) 1018 1019 // The commit tweak will be required in order for Bob to derive the 1020 // proper key need to spend the output. 1021 commitTweak := SingleTweakBytes(commitPoint, bobKeyPub) 1022 1023 // Finally we'll generate the HTLC script itself that we'll be spending 1024 // from. The revocation clause can be claimed by Alice, while Bob can 1025 // sweep the output after a particular delay. 1026 htlcWitnessScript, err := SecondLevelHtlcScript(revocationKey, 1027 delayKey, claimDelay) 1028 if err != nil { 1029 t.Fatalf("unable to create htlc script: %v", err) 1030 } 1031 htlcPkScript, err := ScriptHashPkScript(htlcWitnessScript) 1032 if err != nil { 1033 t.Fatalf("unable to create htlc output: %v", err) 1034 } 1035 1036 htlcOutput := &wire.TxOut{ 1037 PkScript: htlcPkScript, 1038 Value: int64(htlcAmt), 1039 } 1040 1041 // TODO(roasbeef): make actually use timeout/success txns? 1042 1043 // Finally, we'll create mock signers for both of them based on their 1044 // private keys. This test simplifies a bit and uses the same key as 1045 // the base point for all scripts and derivations. 1046 bobSigner := &MockSigner{Privkeys: []*secp256k1.PrivateKey{bobKeyPriv}} 1047 aliceSigner := &MockSigner{Privkeys: []*secp256k1.PrivateKey{aliceKeyPriv}} 1048 1049 testCases := []struct { 1050 witness func() TxWitness 1051 valid bool 1052 }{ 1053 { 1054 // Sender of the HTLC attempts to activate the 1055 // revocation clause, but uses the wrong key (fails to 1056 // use the double tweak in this case). 1057 makeWitnessTestCase(t, func() (TxWitness, error) { 1058 signDesc := &SignDescriptor{ 1059 KeyDesc: keychain.KeyDescriptor{ 1060 PubKey: aliceKeyPub, 1061 }, 1062 WitnessScript: htlcWitnessScript, 1063 Output: htlcOutput, 1064 HashType: txscript.SigHashAll, 1065 InputIndex: 0, 1066 } 1067 1068 return HtlcSpendRevoke(aliceSigner, signDesc, 1069 sweepTx) 1070 }), 1071 false, 1072 }, 1073 { 1074 // Sender of HTLC activates the revocation clause. 1075 makeWitnessTestCase(t, func() (TxWitness, error) { 1076 signDesc := &SignDescriptor{ 1077 KeyDesc: keychain.KeyDescriptor{ 1078 PubKey: aliceKeyPub, 1079 }, 1080 DoubleTweak: commitSecret, 1081 WitnessScript: htlcWitnessScript, 1082 Output: htlcOutput, 1083 HashType: txscript.SigHashAll, 1084 InputIndex: 0, 1085 } 1086 1087 return HtlcSpendRevoke(aliceSigner, signDesc, 1088 sweepTx) 1089 }), 1090 true, 1091 }, 1092 { 1093 // Receiver of the HTLC attempts to sweep, but tries to 1094 // do so pre-maturely with a smaller CSV delay (2 1095 // blocks instead of 5 blocks). 1096 makeWitnessTestCase(t, func() (TxWitness, error) { 1097 signDesc := &SignDescriptor{ 1098 KeyDesc: keychain.KeyDescriptor{ 1099 PubKey: bobKeyPub, 1100 }, 1101 SingleTweak: commitTweak, 1102 WitnessScript: htlcWitnessScript, 1103 Output: htlcOutput, 1104 HashType: txscript.SigHashAll, 1105 InputIndex: 0, 1106 } 1107 1108 return HtlcSpendSuccess(bobSigner, signDesc, 1109 sweepTx, claimDelay-3) 1110 }), 1111 false, 1112 }, 1113 { 1114 // Receiver of the HTLC sweeps with the proper CSV 1115 // delay, but uses the wrong key (leaves off the single 1116 // tweak). 1117 makeWitnessTestCase(t, func() (TxWitness, error) { 1118 signDesc := &SignDescriptor{ 1119 KeyDesc: keychain.KeyDescriptor{ 1120 PubKey: bobKeyPub, 1121 }, 1122 WitnessScript: htlcWitnessScript, 1123 Output: htlcOutput, 1124 HashType: txscript.SigHashAll, 1125 InputIndex: 0, 1126 } 1127 1128 return HtlcSpendSuccess(bobSigner, signDesc, 1129 sweepTx, claimDelay) 1130 }), 1131 false, 1132 }, 1133 { 1134 // Receiver of the HTLC sweeps with the proper CSV 1135 // delay, and the correct key. 1136 makeWitnessTestCase(t, func() (TxWitness, error) { 1137 signDesc := &SignDescriptor{ 1138 KeyDesc: keychain.KeyDescriptor{ 1139 PubKey: bobKeyPub, 1140 }, 1141 SingleTweak: commitTweak, 1142 WitnessScript: htlcWitnessScript, 1143 Output: htlcOutput, 1144 HashType: txscript.SigHashAll, 1145 InputIndex: 0, 1146 } 1147 1148 return HtlcSpendSuccess(bobSigner, signDesc, 1149 sweepTx, claimDelay) 1150 }), 1151 true, 1152 }, 1153 } 1154 1155 for i, testCase := range testCases { 1156 sweepTx.TxIn[0].SignatureScript, err = WitnessStackToSigScript(testCase.witness()) 1157 if err != nil { 1158 t.Fatalf("unable to convert witness stack to sigScript: %v", err) 1159 } 1160 1161 newEngine := func() (*txscript.Engine, error) { 1162 return txscript.NewEngine(htlcPkScript, 1163 sweepTx, 0, ScriptVerifyFlags, scriptVersion, 1164 nil) 1165 } 1166 1167 assertEngineExecution(t, i, testCase.valid, newEngine) 1168 } 1169 } 1170 1171 // TestLeaseSecondLevelHtlcSpends tests all the possible redemption clauses from 1172 // the HTLC success and timeout covenant transactions in script enforced lease 1173 // commitments. 1174 func TestLeaseSecondLevelHtlcSpends(t *testing.T) { 1175 t.Parallel() 1176 1177 // We'll start be creating a creating a 2BTC HTLC. 1178 const htlcAmt = dcrutil.Amount(2 * 10e8) 1179 1180 // In all of our scenarios, the CSV timeout to claim a self output will 1181 // be 5 blocks. 1182 const claimDelay = 5 1183 1184 // In all of our scenarios, the CLTV timelock will expire at height 1185 // 1337. 1186 const leaseExpiry = 1337 1187 1188 // First we'll set up some initial key state for Alice and Bob that 1189 // will be used in the scripts we created below. 1190 aliceKeyPriv, aliceKeyPub := privKeyFromBytes( 1191 testWalletPrivKey, 1192 ) 1193 bobKeyPriv, bobKeyPub := privKeyFromBytes( 1194 bobsPrivKey, 1195 ) 1196 1197 revokePreimage := testHdSeed.CloneBytes() 1198 commitSecret, commitPoint := privKeyFromBytes( 1199 revokePreimage, 1200 ) 1201 1202 // As we're modeling this as Bob sweeping the HTLC on-chain from his 1203 // commitment transaction after a period of time, we'll be using a 1204 // revocation key derived from Alice's base point and his secret. 1205 revocationKey := DeriveRevocationPubkey(aliceKeyPub, commitPoint) 1206 1207 // Next, craft a fake HTLC outpoint that we'll use to generate the 1208 // sweeping transaction using. 1209 txid, err := chainhash.NewHash(testHdSeed.CloneBytes()) 1210 require.NoError(t, err) 1211 htlcOutPoint := &wire.OutPoint{ 1212 Hash: *txid, 1213 Index: 0, 1214 } 1215 sweepTx := wire.NewMsgTx() 1216 sweepTx.Version = LNTxVersion 1217 sweepTx.AddTxIn(wire.NewTxIn(htlcOutPoint, 0, nil)) 1218 sweepTx.AddTxOut( 1219 &wire.TxOut{ 1220 PkScript: []byte("doesn't matter"), 1221 Value: 1 * 10e8, 1222 }, 1223 ) 1224 1225 // The delay key will be crafted using Bob's public key as the output 1226 // we created will be spending from Alice's commitment transaction. 1227 delayKey := TweakPubKey(bobKeyPub, commitPoint) 1228 1229 // The commit tweak will be required in order for Bob to derive the 1230 // proper key need to spend the output. 1231 commitTweak := SingleTweakBytes(commitPoint, bobKeyPub) 1232 1233 // Finally we'll generate the HTLC script itself that we'll be spending 1234 // from. The revocation clause can be claimed by Alice, while Bob can 1235 // sweep the output after a particular delay. 1236 htlcWitnessScript, err := LeaseSecondLevelHtlcScript( 1237 revocationKey, delayKey, claimDelay, leaseExpiry, 1238 ) 1239 require.NoError(t, err) 1240 htlcPkScript, err := ScriptHashPkScript(htlcWitnessScript) 1241 require.NoError(t, err) 1242 1243 htlcOutput := &wire.TxOut{ 1244 PkScript: htlcPkScript, 1245 Value: int64(htlcAmt), 1246 } 1247 1248 // Finally, we'll create mock signers for both of them based on their 1249 // private keys. This test simplifies a bit and uses the same key as 1250 // the base point for all scripts and derivations. 1251 bobSigner := &MockSigner{Privkeys: []*secp256k1.PrivateKey{bobKeyPriv}} 1252 aliceSigner := &MockSigner{Privkeys: []*secp256k1.PrivateKey{aliceKeyPriv}} 1253 1254 testCases := []struct { 1255 witness func() TxWitness 1256 valid bool 1257 }{ 1258 { 1259 // Sender of the HTLC attempts to activate the 1260 // revocation clause, but uses the wrong key (fails to 1261 // use the double tweak in this case). 1262 makeWitnessTestCase(t, func() (TxWitness, error) { 1263 signDesc := &SignDescriptor{ 1264 KeyDesc: keychain.KeyDescriptor{ 1265 PubKey: aliceKeyPub, 1266 }, 1267 WitnessScript: htlcWitnessScript, 1268 Output: htlcOutput, 1269 HashType: txscript.SigHashAll, 1270 InputIndex: 0, 1271 } 1272 1273 return HtlcSpendRevoke( 1274 aliceSigner, signDesc, sweepTx, 1275 ) 1276 }), 1277 false, 1278 }, 1279 { 1280 // Sender of HTLC activates the revocation clause. 1281 makeWitnessTestCase(t, func() (TxWitness, error) { 1282 signDesc := &SignDescriptor{ 1283 KeyDesc: keychain.KeyDescriptor{ 1284 PubKey: aliceKeyPub, 1285 }, 1286 DoubleTweak: commitSecret, 1287 WitnessScript: htlcWitnessScript, 1288 Output: htlcOutput, 1289 HashType: txscript.SigHashAll, 1290 InputIndex: 0, 1291 } 1292 1293 return HtlcSpendRevoke( 1294 aliceSigner, signDesc, sweepTx, 1295 ) 1296 }), 1297 true, 1298 }, 1299 { 1300 // Receiver of the HTLC attempts to sweep, but tries to 1301 // do so pre-maturely with a smaller CSV delay (2 1302 // blocks instead of 5 blocks), even after the CLTV 1303 // timelock expires. 1304 makeWitnessTestCase(t, func() (TxWitness, error) { 1305 sweepTx.LockTime = leaseExpiry 1306 signDesc := &SignDescriptor{ 1307 KeyDesc: keychain.KeyDescriptor{ 1308 PubKey: bobKeyPub, 1309 }, 1310 SingleTweak: commitTweak, 1311 WitnessScript: htlcWitnessScript, 1312 Output: htlcOutput, 1313 HashType: txscript.SigHashAll, 1314 InputIndex: 0, 1315 } 1316 1317 return HtlcSpendSuccess( 1318 bobSigner, signDesc, sweepTx, claimDelay-3, 1319 ) 1320 }), 1321 false, 1322 }, 1323 { 1324 // Receiver of the HTLC sweeps with the proper CSV delay 1325 // and after the CLTV timelock expires, but uses the 1326 // wrong key (leaves off the single tweak). 1327 makeWitnessTestCase(t, func() (TxWitness, error) { 1328 sweepTx.LockTime = leaseExpiry 1329 signDesc := &SignDescriptor{ 1330 KeyDesc: keychain.KeyDescriptor{ 1331 PubKey: bobKeyPub, 1332 }, 1333 WitnessScript: htlcWitnessScript, 1334 Output: htlcOutput, 1335 HashType: txscript.SigHashAll, 1336 InputIndex: 0, 1337 } 1338 1339 return HtlcSpendSuccess( 1340 bobSigner, signDesc, sweepTx, claimDelay, 1341 ) 1342 }), 1343 false, 1344 }, 1345 { 1346 // Receiver of the HTLC sweeps with the proper CSV 1347 // delay, and the correct key, but before the CTLV 1348 // timelock expires. 1349 makeWitnessTestCase(t, func() (TxWitness, error) { 1350 sweepTx.LockTime = 0 1351 signDesc := &SignDescriptor{ 1352 KeyDesc: keychain.KeyDescriptor{ 1353 PubKey: bobKeyPub, 1354 }, 1355 SingleTweak: commitTweak, 1356 WitnessScript: htlcWitnessScript, 1357 Output: htlcOutput, 1358 HashType: txscript.SigHashAll, 1359 InputIndex: 0, 1360 } 1361 1362 return HtlcSpendSuccess( 1363 bobSigner, signDesc, sweepTx, claimDelay, 1364 ) 1365 }), 1366 false, 1367 }, 1368 { 1369 // Receiver of the HTLC sweeps with the proper CSV 1370 // delay, and the correct key after the CTLV timelock 1371 // expires. 1372 makeWitnessTestCase(t, func() (TxWitness, error) { 1373 sweepTx.LockTime = leaseExpiry 1374 signDesc := &SignDescriptor{ 1375 KeyDesc: keychain.KeyDescriptor{ 1376 PubKey: bobKeyPub, 1377 }, 1378 SingleTweak: commitTweak, 1379 WitnessScript: htlcWitnessScript, 1380 Output: htlcOutput, 1381 HashType: txscript.SigHashAll, 1382 InputIndex: 0, 1383 } 1384 1385 return HtlcSpendSuccess( 1386 bobSigner, signDesc, sweepTx, claimDelay, 1387 ) 1388 }), 1389 true, 1390 }, 1391 } 1392 1393 for i, testCase := range testCases { 1394 sigScript, err := WitnessStackToSigScript(testCase.witness()) 1395 require.NoError(t, err) 1396 sweepTx.TxIn[0].SignatureScript = sigScript 1397 1398 newEngine := func() (*txscript.Engine, error) { 1399 return txscript.NewEngine(htlcPkScript, 1400 sweepTx, 0, ScriptVerifyFlags, scriptVersion, 1401 nil) 1402 } 1403 1404 assertEngineExecution(t, i, testCase.valid, newEngine) 1405 } 1406 } 1407 1408 // TestLeaseCommmitSpendToSelf tests all the possible redemption clauses from 1409 // the to_self output in a script enforced lease commitment transaction. 1410 func TestLeaseCommmitSpendToSelf(t *testing.T) { 1411 t.Parallel() 1412 1413 const ( 1414 outputVal = dcrutil.Amount(2 * 10e8) 1415 csvDelay = 5 1416 leaseExpiry = 1337 1417 ) 1418 1419 // Set up some initial key state for Alice and Bob that will be used in 1420 // the scripts we created below. 1421 aliceKeyPriv, aliceKeyPub := privKeyFromBytes( 1422 testWalletPrivKey, 1423 ) 1424 bobKeyPriv, bobKeyPub := privKeyFromBytes( 1425 bobsPrivKey, 1426 ) 1427 1428 // We'll have Bob take the revocation path in some cases. 1429 revokePreimage := testHdSeed.CloneBytes() 1430 commitSecret, commitPoint := privKeyFromBytes( 1431 revokePreimage, 1432 ) 1433 revocationKey := DeriveRevocationPubkey(bobKeyPub, commitPoint) 1434 1435 // Construct the script enforced lease to_self commitment transaction 1436 // output. 1437 txid, err := chainhash.NewHash(testHdSeed.CloneBytes()) 1438 require.NoError(t, err) 1439 commitOut := &wire.OutPoint{ 1440 Hash: *txid, 1441 Index: 0, 1442 } 1443 commitScript, err := LeaseCommitScriptToSelf( 1444 aliceKeyPub, revocationKey, csvDelay, leaseExpiry, 1445 ) 1446 require.NoError(t, err) 1447 commitPkScript, err := ScriptHashPkScript(commitScript) 1448 require.NoError(t, err) 1449 1450 commitOutput := &wire.TxOut{ 1451 PkScript: commitPkScript, 1452 Value: int64(outputVal), 1453 } 1454 1455 sweepTx := wire.NewMsgTx() 1456 sweepTx.Version = LNTxVersion 1457 sweepTx.AddTxIn(wire.NewTxIn(commitOut, 0, nil)) 1458 sweepTx.AddTxOut( 1459 &wire.TxOut{ 1460 PkScript: []byte("doesn't matter"), 1461 Value: 1 * 10e8, 1462 }, 1463 ) 1464 1465 // Create mock signers for both parties to ensure signatures are 1466 // produced and verified correctly. 1467 aliceSigner := &MockSigner{Privkeys: []*secp256k1.PrivateKey{aliceKeyPriv}} 1468 bobSigner := &MockSigner{Privkeys: []*secp256k1.PrivateKey{bobKeyPriv}} 1469 1470 testCases := []struct { 1471 witness func() TxWitness 1472 valid bool 1473 }{ 1474 { 1475 // Bob can spend with his revocation key, but not 1476 // without the proper tweak. 1477 makeWitnessTestCase(t, func() (TxWitness, error) { 1478 signDesc := &SignDescriptor{ 1479 KeyDesc: keychain.KeyDescriptor{ 1480 PubKey: bobKeyPub, 1481 }, 1482 WitnessScript: commitScript, 1483 Output: commitOutput, 1484 HashType: txscript.SigHashAll, 1485 InputIndex: 0, 1486 } 1487 1488 return CommitSpendRevoke( 1489 bobSigner, signDesc, sweepTx, 1490 ) 1491 }), 1492 false, 1493 }, 1494 { 1495 // Bob can spend with his revocation key with the proper 1496 // tweak. 1497 makeWitnessTestCase(t, func() (TxWitness, error) { 1498 signDesc := &SignDescriptor{ 1499 KeyDesc: keychain.KeyDescriptor{ 1500 PubKey: bobKeyPub, 1501 }, 1502 DoubleTweak: commitSecret, 1503 WitnessScript: commitScript, 1504 Output: commitOutput, 1505 HashType: txscript.SigHashAll, 1506 InputIndex: 0, 1507 } 1508 1509 return CommitSpendRevoke( 1510 bobSigner, signDesc, sweepTx, 1511 ) 1512 }), 1513 true, 1514 }, 1515 { 1516 // Alice cannot spend with the proper key before the CSV 1517 // delay and after the CLTV timelock has expired. 1518 makeWitnessTestCase(t, func() (TxWitness, error) { 1519 sweepTx.LockTime = leaseExpiry 1520 sweepTx.TxIn[0].Sequence = LockTimeToSequence( 1521 false, csvDelay/2, 1522 ) 1523 signDesc := &SignDescriptor{ 1524 KeyDesc: keychain.KeyDescriptor{ 1525 PubKey: aliceKeyPub, 1526 }, 1527 DoubleTweak: commitSecret, 1528 WitnessScript: commitScript, 1529 Output: commitOutput, 1530 HashType: txscript.SigHashAll, 1531 InputIndex: 0, 1532 } 1533 1534 return CommitSpendTimeout( 1535 aliceSigner, signDesc, sweepTx, 1536 ) 1537 }), 1538 false, 1539 }, 1540 { 1541 // Alice cannot spend with the proper key after the CSV 1542 // delay and before the CLTV timelock has expired. 1543 makeWitnessTestCase(t, func() (TxWitness, error) { 1544 sweepTx.LockTime = 0 1545 sweepTx.TxIn[0].Sequence = LockTimeToSequence( 1546 false, csvDelay, 1547 ) 1548 signDesc := &SignDescriptor{ 1549 KeyDesc: keychain.KeyDescriptor{ 1550 PubKey: aliceKeyPub, 1551 }, 1552 DoubleTweak: commitSecret, 1553 WitnessScript: commitScript, 1554 Output: commitOutput, 1555 HashType: txscript.SigHashAll, 1556 InputIndex: 0, 1557 } 1558 1559 return CommitSpendTimeout( 1560 aliceSigner, signDesc, sweepTx, 1561 ) 1562 }), 1563 false, 1564 }, 1565 { 1566 // Alice can spend with the proper key after the CSV 1567 // delay and CLTV timelock have expired. 1568 makeWitnessTestCase(t, func() (TxWitness, error) { 1569 sweepTx.LockTime = leaseExpiry 1570 sweepTx.TxIn[0].Sequence = LockTimeToSequence( 1571 false, csvDelay, 1572 ) 1573 signDesc := &SignDescriptor{ 1574 KeyDesc: keychain.KeyDescriptor{ 1575 PubKey: aliceKeyPub, 1576 }, 1577 WitnessScript: commitScript, 1578 Output: commitOutput, 1579 HashType: txscript.SigHashAll, 1580 InputIndex: 0, 1581 } 1582 1583 return CommitSpendTimeout( 1584 aliceSigner, signDesc, sweepTx, 1585 ) 1586 }), 1587 true, 1588 }, 1589 } 1590 1591 for i, testCase := range testCases { 1592 sigScript, err := WitnessStackToSigScript(testCase.witness()) 1593 require.NoError(t, err) 1594 sweepTx.TxIn[0].SignatureScript = sigScript 1595 1596 newEngine := func() (*txscript.Engine, error) { 1597 return txscript.NewEngine(commitPkScript, 1598 sweepTx, 0, ScriptVerifyFlags, scriptVersion, 1599 nil) 1600 } 1601 1602 assertEngineExecution(t, i, testCase.valid, newEngine) 1603 } 1604 } 1605 1606 // TestCommitSpendToRemoteConfirmed checks that the delayed version of the 1607 // to_remote version can only be spent by the owner, and after one 1608 // confirmation. 1609 func TestCommitSpendToRemoteConfirmed(t *testing.T) { 1610 t.Parallel() 1611 1612 const outputVal = dcrutil.Amount(2 * 10e8) 1613 1614 aliceKeyPriv, aliceKeyPub := privKeyFromBytes(testWalletPrivKey) 1615 1616 txid, err := chainhash.NewHash(testHdSeed.CloneBytes()) 1617 if err != nil { 1618 t.Fatalf("unable to create txid: %v", err) 1619 } 1620 commitOut := &wire.OutPoint{ 1621 Hash: *txid, 1622 Index: 0, 1623 } 1624 commitScript, err := CommitScriptToRemoteConfirmed(aliceKeyPub) 1625 if err != nil { 1626 t.Fatalf("unable to create htlc script: %v", err) 1627 } 1628 commitPkScript, err := ScriptHashPkScript(commitScript) 1629 if err != nil { 1630 t.Fatalf("unable to create htlc output: %v", err) 1631 } 1632 1633 commitOutput := &wire.TxOut{ 1634 PkScript: commitPkScript, 1635 Value: int64(outputVal), 1636 Version: scriptVersion, 1637 } 1638 1639 sweepTx := wire.NewMsgTx() 1640 sweepTx.Version = LNTxVersion 1641 sweepTx.AddTxIn(wire.NewTxIn(commitOut, 0, nil)) // TODO(decred) fill correct value 1642 sweepTx.AddTxOut( 1643 &wire.TxOut{ 1644 PkScript: []byte("doesn't matter"), 1645 Value: 1 * 10e8, 1646 Version: scriptVersion, 1647 }, 1648 ) 1649 1650 aliceSigner := &MockSigner{Privkeys: []*secp256k1.PrivateKey{aliceKeyPriv}} 1651 1652 testCases := []struct { 1653 witness func() TxWitness 1654 valid bool 1655 }{ 1656 { 1657 // Alice can spend after the a CSV delay has passed. 1658 makeWitnessTestCase(t, func() (TxWitness, error) { 1659 sweepTx.TxIn[0].Sequence = LockTimeToSequence(false, 1) 1660 1661 signDesc := &SignDescriptor{ 1662 KeyDesc: keychain.KeyDescriptor{ 1663 PubKey: aliceKeyPub, 1664 }, 1665 WitnessScript: commitScript, 1666 Output: commitOutput, 1667 HashType: txscript.SigHashAll, 1668 InputIndex: 0, 1669 } 1670 1671 return CommitSpendToRemoteConfirmed(aliceSigner, signDesc, 1672 sweepTx) 1673 }), 1674 true, 1675 }, 1676 { 1677 // Alice cannot spend output without sequence set. 1678 makeWitnessTestCase(t, func() (TxWitness, error) { 1679 sweepTx.TxIn[0].Sequence = wire.MaxTxInSequenceNum 1680 1681 signDesc := &SignDescriptor{ 1682 KeyDesc: keychain.KeyDescriptor{ 1683 PubKey: aliceKeyPub, 1684 }, 1685 WitnessScript: commitScript, 1686 Output: commitOutput, 1687 HashType: txscript.SigHashAll, 1688 InputIndex: 0, 1689 } 1690 1691 return CommitSpendToRemoteConfirmed(aliceSigner, signDesc, 1692 sweepTx) 1693 }), 1694 false, 1695 }, 1696 } 1697 1698 for i, testCase := range testCases { 1699 sweepTx.TxIn[0].SignatureScript, err = WitnessStackToSigScript(testCase.witness()) 1700 if err != nil { 1701 t.Fatal(err) 1702 } 1703 1704 newEngine := func() (*txscript.Engine, error) { 1705 return txscript.NewEngine(commitPkScript, 1706 sweepTx, 0, ScriptVerifyFlags, scriptVersion, 1707 nil) 1708 } 1709 1710 assertEngineExecution(t, i, testCase.valid, newEngine) 1711 } 1712 } 1713 1714 // TestLeaseCommitSpendToRemoteConfirmed checks that the delayed version of the 1715 // to_remote version can only be spent by the owner, after one confirmation, and 1716 // after the lease expiration has been met. 1717 func TestLeaseCommitSpendToRemoteConfirmed(t *testing.T) { 1718 t.Parallel() 1719 1720 const ( 1721 outputVal = dcrutil.Amount(2 * 10e8) 1722 leaseExpiry = 1337 1723 ) 1724 1725 aliceKeyPriv, aliceKeyPub := privKeyFromBytes( 1726 testWalletPrivKey, 1727 ) 1728 1729 txid, err := chainhash.NewHash(testHdSeed.CloneBytes()) 1730 require.NoError(t, err) 1731 commitOut := &wire.OutPoint{ 1732 Hash: *txid, 1733 Index: 0, 1734 } 1735 commitScript, err := LeaseCommitScriptToRemoteConfirmed( 1736 aliceKeyPub, leaseExpiry, 1737 ) 1738 require.NoError(t, err) 1739 commitPkScript, err := ScriptHashPkScript(commitScript) 1740 require.NoError(t, err) 1741 1742 commitOutput := &wire.TxOut{ 1743 PkScript: commitPkScript, 1744 Value: int64(outputVal), 1745 } 1746 1747 sweepTx := wire.NewMsgTx() 1748 sweepTx.Version = LNTxVersion 1749 sweepTx.AddTxIn(wire.NewTxIn(commitOut, 0, nil)) 1750 sweepTx.AddTxOut( 1751 &wire.TxOut{ 1752 PkScript: []byte("doesn't matter"), 1753 Value: 1 * 10e8, 1754 }, 1755 ) 1756 1757 aliceSigner := &MockSigner{Privkeys: []*secp256k1.PrivateKey{aliceKeyPriv}} 1758 1759 testCases := []struct { 1760 witness func() TxWitness 1761 valid bool 1762 }{ 1763 { 1764 // Alice can spend after the CSV delay and CLTV timelock 1765 // has passed. 1766 makeWitnessTestCase(t, func() (TxWitness, error) { 1767 sweepTx.LockTime = leaseExpiry 1768 sweepTx.TxIn[0].Sequence = LockTimeToSequence( 1769 false, 1, 1770 ) 1771 1772 signDesc := &SignDescriptor{ 1773 KeyDesc: keychain.KeyDescriptor{ 1774 PubKey: aliceKeyPub, 1775 }, 1776 WitnessScript: commitScript, 1777 Output: commitOutput, 1778 HashType: txscript.SigHashAll, 1779 InputIndex: 0, 1780 } 1781 1782 return CommitSpendToRemoteConfirmed( 1783 aliceSigner, signDesc, sweepTx, 1784 ) 1785 }), 1786 true, 1787 }, 1788 { 1789 // Alice cannot spend output without sequence set, even 1790 // once the CLTV timelock has expired. 1791 makeWitnessTestCase(t, func() (TxWitness, error) { 1792 sweepTx.LockTime = leaseExpiry 1793 sweepTx.TxIn[0].Sequence = wire.MaxTxInSequenceNum 1794 1795 signDesc := &SignDescriptor{ 1796 KeyDesc: keychain.KeyDescriptor{ 1797 PubKey: aliceKeyPub, 1798 }, 1799 WitnessScript: commitScript, 1800 Output: commitOutput, 1801 HashType: txscript.SigHashAll, 1802 InputIndex: 0, 1803 } 1804 1805 return CommitSpendToRemoteConfirmed( 1806 aliceSigner, signDesc, sweepTx, 1807 ) 1808 }), 1809 false, 1810 }, 1811 { 1812 // Alice cannot spend output without sequence or 1813 // locktime set. 1814 makeWitnessTestCase(t, func() (TxWitness, error) { 1815 sweepTx.LockTime = 0 1816 sweepTx.TxIn[0].Sequence = wire.MaxTxInSequenceNum 1817 1818 signDesc := &SignDescriptor{ 1819 KeyDesc: keychain.KeyDescriptor{ 1820 PubKey: aliceKeyPub, 1821 }, 1822 WitnessScript: commitScript, 1823 Output: commitOutput, 1824 HashType: txscript.SigHashAll, 1825 InputIndex: 0, 1826 } 1827 1828 return CommitSpendToRemoteConfirmed( 1829 aliceSigner, signDesc, sweepTx, 1830 ) 1831 }), 1832 false, 1833 }, 1834 } 1835 1836 for i, testCase := range testCases { 1837 sigScript, err := WitnessStackToSigScript(testCase.witness()) 1838 require.NoError(t, err) 1839 sweepTx.TxIn[0].SignatureScript = sigScript 1840 1841 newEngine := func() (*txscript.Engine, error) { 1842 return txscript.NewEngine( 1843 commitPkScript, sweepTx, 0, 1844 ScriptVerifyFlags, scriptVersion, nil, 1845 ) 1846 } 1847 1848 assertEngineExecution(t, i, testCase.valid, newEngine) 1849 } 1850 } 1851 1852 // TestSpendAnchor checks that we can spend the anchors using the various spend 1853 // paths. 1854 func TestSpendAnchor(t *testing.T) { 1855 t.Parallel() 1856 1857 const anchorSize = 294 1858 1859 // First we'll set up some initial key state for Alice. 1860 aliceKeyPriv, aliceKeyPub := privKeyFromBytes(testWalletPrivKey) 1861 1862 // Create a fake anchor outpoint that we'll use to generate the 1863 // sweeping transaction. 1864 txid, err := chainhash.NewHash(testHdSeed.CloneBytes()) 1865 if err != nil { 1866 t.Fatalf("unable to create txid: %v", err) 1867 } 1868 anchorOutPoint := &wire.OutPoint{ 1869 Hash: *txid, 1870 Index: 0, 1871 } 1872 1873 sweepTx := wire.NewMsgTx() 1874 sweepTx.Version = LNTxVersion 1875 sweepTx.AddTxIn(wire.NewTxIn(anchorOutPoint, 0, nil)) // TODO(decred) Pass in correct value 1876 sweepTx.AddTxOut( 1877 &wire.TxOut{ 1878 PkScript: []byte("doesn't matter"), 1879 Value: 1 * 10e8, 1880 }, 1881 ) 1882 1883 // Generate the anchor script that can be spent by Alice immediately, 1884 // or by anyone after 16 blocks. 1885 anchorScript, err := CommitScriptAnchor(aliceKeyPub) 1886 if err != nil { 1887 t.Fatalf("unable to create htlc script: %v", err) 1888 } 1889 anchorPkScript, err := ScriptHashPkScript(anchorScript) 1890 if err != nil { 1891 t.Fatalf("unable to create htlc output: %v", err) 1892 } 1893 1894 anchorOutput := &wire.TxOut{ 1895 PkScript: anchorPkScript, 1896 Value: int64(anchorSize), 1897 } 1898 1899 // Create mock signer for Alice. 1900 aliceSigner := &MockSigner{Privkeys: []*secp256k1.PrivateKey{aliceKeyPriv}} 1901 1902 testCases := []struct { 1903 witness func() TxWitness 1904 valid bool 1905 }{ 1906 { 1907 // Alice can spend immediately. 1908 makeWitnessTestCase(t, func() (TxWitness, error) { 1909 sweepTx.TxIn[0].Sequence = wire.MaxTxInSequenceNum 1910 1911 signDesc := &SignDescriptor{ 1912 KeyDesc: keychain.KeyDescriptor{ 1913 PubKey: aliceKeyPub, 1914 }, 1915 WitnessScript: anchorScript, 1916 Output: anchorOutput, 1917 HashType: txscript.SigHashAll, 1918 InputIndex: 0, 1919 } 1920 1921 return CommitSpendAnchor(aliceSigner, signDesc, 1922 sweepTx) 1923 }), 1924 true, 1925 }, 1926 { 1927 // Anyone can spend after 16 blocks. 1928 makeWitnessTestCase(t, func() (TxWitness, error) { 1929 sweepTx.TxIn[0].Sequence = LockTimeToSequence(false, 16) 1930 return CommitSpendAnchorAnyone(anchorScript) 1931 }), 1932 true, 1933 }, 1934 { 1935 // Anyone cannot spend before 16 blocks. 1936 makeWitnessTestCase(t, func() (TxWitness, error) { 1937 sweepTx.TxIn[0].Sequence = LockTimeToSequence(false, 15) 1938 return CommitSpendAnchorAnyone(anchorScript) 1939 }), 1940 false, 1941 }, 1942 } 1943 1944 for i, testCase := range testCases { 1945 sweepTx.TxIn[0].SignatureScript, err = WitnessStackToSigScript(testCase.witness()) 1946 if err != nil { 1947 t.Fatal(err) 1948 } 1949 1950 newEngine := func() (*txscript.Engine, error) { 1951 return txscript.NewEngine(anchorPkScript, 1952 sweepTx, 0, ScriptVerifyFlags, scriptVersion, 1953 nil) 1954 } 1955 1956 assertEngineExecution(t, i, testCase.valid, newEngine) 1957 } 1958 } 1959 1960 // TestSpecificationKeyDerivation implements the test vectors provided in 1961 // BOLT-03, Appendix E. 1962 func TestSpecificationKeyDerivation(t *testing.T) { 1963 const ( 1964 baseSecretHex = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" 1965 perCommitmentSecretHex = "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100" 1966 basePointHex = "036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2" 1967 perCommitmentPointHex = "025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486" 1968 ) 1969 1970 baseSecret, err := privkeyFromHex(baseSecretHex) 1971 if err != nil { 1972 t.Fatalf("Failed to parse serialized privkey: %v", err) 1973 } 1974 perCommitmentSecret, err := privkeyFromHex(perCommitmentSecretHex) 1975 if err != nil { 1976 t.Fatalf("Failed to parse serialized privkey: %v", err) 1977 } 1978 basePoint, err := pubkeyFromHex(basePointHex) 1979 if err != nil { 1980 t.Fatalf("Failed to parse serialized pubkey: %v", err) 1981 } 1982 perCommitmentPoint, err := pubkeyFromHex(perCommitmentPointHex) 1983 if err != nil { 1984 t.Fatalf("Failed to parse serialized pubkey: %v", err) 1985 } 1986 1987 // name: derivation of key from basepoint and per_commitment_point 1988 const expectedLocalKeyHex = "0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5" 1989 actualLocalKey := TweakPubKey(basePoint, perCommitmentPoint) 1990 actualLocalKeyHex := pubkeyToHex(actualLocalKey) 1991 if actualLocalKeyHex != expectedLocalKeyHex { 1992 t.Errorf("Incorrect derivation of local public key: "+ 1993 "expected %v, got %v", expectedLocalKeyHex, actualLocalKeyHex) 1994 } 1995 1996 // name: derivation of secret key from basepoint secret and per_commitment_secret 1997 const expectedLocalPrivKeyHex = "cbced912d3b21bf196a766651e436aff192362621ce317704ea2f75d87e7be0f" 1998 tweak := SingleTweakBytes(perCommitmentPoint, basePoint) 1999 actualLocalPrivKey := TweakPrivKey(baseSecret, tweak) 2000 actualLocalPrivKeyHex := privkeyToHex(actualLocalPrivKey) 2001 if actualLocalPrivKeyHex != expectedLocalPrivKeyHex { 2002 t.Errorf("Incorrect derivation of local private key: "+ 2003 "expected %v, got %v, %v", expectedLocalPrivKeyHex, 2004 actualLocalPrivKeyHex, hex.EncodeToString(tweak)) 2005 } 2006 2007 // name: derivation of revocation key from basepoint and per_commitment_point 2008 const expectedRevocationKeyHex = "02916e326636d19c33f13e8c0c3a03dd157f332f3e99c317c141dd865eb01f8ff0" 2009 actualRevocationKey := DeriveRevocationPubkey(basePoint, perCommitmentPoint) 2010 actualRevocationKeyHex := pubkeyToHex(actualRevocationKey) 2011 if actualRevocationKeyHex != expectedRevocationKeyHex { 2012 t.Errorf("Incorrect derivation of revocation public key: "+ 2013 "expected %v, got %v", expectedRevocationKeyHex, 2014 actualRevocationKeyHex) 2015 } 2016 2017 // name: derivation of revocation secret from basepoint_secret and per_commitment_secret 2018 const expectedRevocationPrivKeyHex = "d09ffff62ddb2297ab000cc85bcb4283fdeb6aa052affbc9dddcf33b61078110" 2019 actualRevocationPrivKey := DeriveRevocationPrivKey(baseSecret, 2020 perCommitmentSecret) 2021 actualRevocationPrivKeyHex := privkeyToHex(actualRevocationPrivKey) 2022 if actualRevocationPrivKeyHex != expectedRevocationPrivKeyHex { 2023 t.Errorf("Incorrect derivation of revocation private key: "+ 2024 "expected %v, got %v", expectedRevocationPrivKeyHex, 2025 actualRevocationPrivKeyHex) 2026 } 2027 } 2028 2029 // TestReplaceReceiverHtlcSpendRedeemPreimage tests whether the corresponding 2030 // function works as intended. 2031 func TestReplaceReceiverHtlcSpendRedeemPreimage(t *testing.T) { 2032 t.Parallel() 2033 2034 // pushes generates nb data pushes of 1-byte length 2035 pushes := func(nb int) []byte { 2036 return bytes.Repeat([]byte{0x01, 0xff}, nb) 2037 } 2038 2039 tests := []struct { 2040 name string 2041 sigScript []byte 2042 preimage []byte 2043 valid bool 2044 }{ 2045 { 2046 name: "sigscript with few items fail", 2047 sigScript: pushes(3), 2048 preimage: []byte{}, 2049 valid: false, 2050 }, 2051 { 2052 name: "sigscript with many items fail", 2053 sigScript: pushes(5), 2054 preimage: []byte{}, 2055 valid: false, 2056 }, 2057 { 2058 name: "sigscript and preimage same size", 2059 sigScript: pushes(4), 2060 preimage: []byte{0xee}, 2061 valid: true, 2062 }, 2063 { 2064 name: "sigscript and preimage different sizes", 2065 sigScript: pushes(4), 2066 preimage: []byte{0xee, 0xdd}, 2067 valid: true, 2068 }, 2069 } 2070 2071 for _, tc := range tests { 2072 res, err := ReplaceReceiverHtlcSpendRedeemPreimage(tc.sigScript, tc.preimage) 2073 if err != nil && tc.valid { 2074 t.Errorf("case '%s' returned error when it should have been valid: %v", 2075 tc.name, err) 2076 continue 2077 } 2078 2079 if err == nil && !tc.valid { 2080 t.Errorf("case '%s' should have returned error but passed", tc.name) 2081 continue 2082 } 2083 2084 if err == nil { 2085 // Given we know all data pushes use 2 bytes (OP_DATA_1+0xff), we 2086 // can easily figure out where the preimage _should_ start. 2087 sigPreImage := res[5 : len(res)-2] 2088 if !bytes.Equal(sigPreImage, tc.preimage) { 2089 t.Errorf("case '%s' did not include a correct preimage: "+ 2090 "preimage: %x return: %x\n", tc.name, tc.preimage, res) 2091 } 2092 } 2093 } 2094 }