2019-01-16 17:47:43 +03:00
|
|
|
package input
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2017-03-16 04:56:25 +03:00
|
|
|
"crypto/sha256"
|
2017-10-02 23:20:48 +03:00
|
|
|
"encoding/hex"
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
"fmt"
|
|
|
|
"testing"
|
|
|
|
|
2018-06-05 04:34:16 +03:00
|
|
|
"github.com/btcsuite/btcd/btcec"
|
|
|
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
|
|
|
"github.com/btcsuite/btcd/txscript"
|
|
|
|
"github.com/btcsuite/btcd/wire"
|
|
|
|
"github.com/btcsuite/btcutil"
|
2018-07-18 05:20:52 +03:00
|
|
|
"github.com/lightningnetwork/lnd/keychain"
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
)
|
|
|
|
|
2020-03-06 18:11:44 +03:00
|
|
|
// assertEngineExecution executes the VM returned by the newEngine closure,
|
|
|
|
// asserting the result matches the validity expectation. In the case where it
|
|
|
|
// doesn't match the expectation, it executes the script step-by-step and
|
|
|
|
// prints debug information to stdout.
|
|
|
|
func assertEngineExecution(t *testing.T, testNum int, valid bool,
|
|
|
|
newEngine func() (*txscript.Engine, error)) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
// Get a new VM to execute.
|
|
|
|
vm, err := newEngine()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to create engine: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Execute the VM, only go on to the step-by-step execution if
|
|
|
|
// it doesn't validate as expected.
|
|
|
|
vmErr := vm.Execute()
|
|
|
|
if valid == (vmErr == nil) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now that the execution didn't match what we expected, fetch a new VM
|
|
|
|
// to step through.
|
|
|
|
vm, err = newEngine()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to create engine: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// This buffer will trace execution of the Script, dumping out
|
|
|
|
// to stdout.
|
|
|
|
var debugBuf bytes.Buffer
|
|
|
|
|
|
|
|
done := false
|
|
|
|
for !done {
|
|
|
|
dis, err := vm.DisasmPC()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("stepping (%v)\n", err)
|
|
|
|
}
|
|
|
|
debugBuf.WriteString(fmt.Sprintf("stepping %v\n", dis))
|
|
|
|
|
|
|
|
done, err = vm.Step()
|
|
|
|
if err != nil && valid {
|
|
|
|
fmt.Println(debugBuf.String())
|
|
|
|
t.Fatalf("spend test case #%v failed, spend "+
|
|
|
|
"should be valid: %v", testNum, err)
|
|
|
|
} else if err == nil && !valid && done {
|
|
|
|
fmt.Println(debugBuf.String())
|
|
|
|
t.Fatalf("spend test case #%v succeed, spend "+
|
|
|
|
"should be invalid: %v", testNum, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
debugBuf.WriteString(fmt.Sprintf("Stack: %v", vm.GetStack()))
|
|
|
|
debugBuf.WriteString(fmt.Sprintf("AltStack: %v", vm.GetAltStack()))
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we get to this point the unexpected case was not reached
|
|
|
|
// during step execution, which happens for some checks, like
|
|
|
|
// the clean-stack rule.
|
|
|
|
validity := "invalid"
|
|
|
|
if valid {
|
|
|
|
validity = "valid"
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Println(debugBuf.String())
|
|
|
|
t.Fatalf("%v spend test case #%v execution ended with: %v", validity, testNum, vmErr)
|
|
|
|
}
|
|
|
|
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
// TestRevocationKeyDerivation tests that given a public key, and a revocation
|
|
|
|
// hash, the homomorphic revocation public and private key derivation work
|
|
|
|
// properly.
|
|
|
|
func TestRevocationKeyDerivation(t *testing.T) {
|
2017-06-17 01:59:20 +03:00
|
|
|
t.Parallel()
|
|
|
|
|
2017-07-30 04:35:47 +03:00
|
|
|
// First, we'll generate a commitment point, and a commitment secret.
|
|
|
|
// These will be used to derive the ultimate revocation keys.
|
|
|
|
revocationPreimage := testHdSeed.CloneBytes()
|
|
|
|
commitSecret, commitPoint := btcec.PrivKeyFromBytes(btcec.S256(),
|
|
|
|
revocationPreimage)
|
|
|
|
|
|
|
|
// With the commitment secrets generated, we'll now create the base
|
|
|
|
// keys we'll use to derive the revocation key from.
|
|
|
|
basePriv, basePub := btcec.PrivKeyFromBytes(btcec.S256(),
|
|
|
|
testWalletPrivKey)
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
|
2017-07-30 04:35:47 +03:00
|
|
|
// With the point and key obtained, we can now derive the revocation
|
|
|
|
// key itself.
|
|
|
|
revocationPub := DeriveRevocationPubkey(basePub, commitPoint)
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
|
2017-07-30 04:35:47 +03:00
|
|
|
// The revocation public key derived from the original public key, and
|
|
|
|
// the one derived from the private key should be identical.
|
|
|
|
revocationPriv := DeriveRevocationPrivKey(basePriv, commitSecret)
|
|
|
|
if !revocationPub.IsEqual(revocationPriv.PubKey()) {
|
|
|
|
t.Fatalf("derived public keys don't match!")
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
}
|
2017-07-30 04:36:04 +03:00
|
|
|
}
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
|
2017-07-30 04:35:25 +03:00
|
|
|
// TestTweakKeyDerivation tests that given a public key, and commitment tweak,
|
|
|
|
// then we're able to properly derive a tweaked private key that corresponds to
|
|
|
|
// the computed tweak public key. This scenario ensure that our key derivation
|
|
|
|
// for any of the non revocation keys on the commitment transaction is correct.
|
|
|
|
func TestTweakKeyDerivation(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
// First, we'll generate a base public key that we'll be "tweaking".
|
|
|
|
baseSecret := testHdSeed.CloneBytes()
|
|
|
|
basePriv, basePub := btcec.PrivKeyFromBytes(btcec.S256(), baseSecret)
|
|
|
|
|
|
|
|
// With the base key create, we'll now create a commitment point, and
|
|
|
|
// from that derive the bytes we'll used to tweak the base public key.
|
|
|
|
commitPoint := ComputeCommitmentPoint(bobsPrivKey)
|
|
|
|
commitTweak := SingleTweakBytes(commitPoint, basePub)
|
|
|
|
|
|
|
|
// Next, we'll modify the public key. When we apply the same operation
|
|
|
|
// to the private key we should get a key that matches.
|
|
|
|
tweakedPub := TweakPubKey(basePub, commitPoint)
|
|
|
|
|
|
|
|
// Finally, attempt to re-generate the private key that matches the
|
|
|
|
// tweaked public key. The derived key should match exactly.
|
|
|
|
derivedPriv := TweakPrivKey(basePriv, commitTweak)
|
|
|
|
if !derivedPriv.PubKey().IsEqual(tweakedPub) {
|
|
|
|
t.Fatalf("pub keys don't match")
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-29 21:31:29 +03:00
|
|
|
// makeWitnessTestCase is a helper function used within test cases involving
|
|
|
|
// the validity of a crafted witness. This function is a wrapper function which
|
|
|
|
// allows constructing table-driven tests. In the case of an error while
|
2017-07-30 04:34:54 +03:00
|
|
|
// constructing the witness, the test fails fatally.
|
|
|
|
func makeWitnessTestCase(t *testing.T,
|
|
|
|
f func() (wire.TxWitness, error)) func() wire.TxWitness {
|
|
|
|
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
return func() wire.TxWitness {
|
|
|
|
witness, err := f()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to create witness test case: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return witness
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestHTLCSenderSpendValidation tests all possible valid+invalid redemption
|
|
|
|
// paths in the script used within the sender's commitment transaction for an
|
|
|
|
// outgoing HTLC.
|
|
|
|
//
|
|
|
|
// The following cases are exercised by this test:
|
|
|
|
// sender script:
|
2017-01-13 08:01:50 +03:00
|
|
|
// * receiver spends
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
// * revoke w/ sig
|
2017-01-13 08:01:50 +03:00
|
|
|
// * HTLC with invalid preimage size
|
|
|
|
// * HTLC with valid preimage size + sig
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
// * sender spends
|
|
|
|
// * invalid lock-time for CLTV
|
|
|
|
// * invalid sequence for CSV
|
|
|
|
// * valid lock-time+sequence, valid sig
|
|
|
|
func TestHTLCSenderSpendValidation(t *testing.T) {
|
2017-06-17 01:59:20 +03:00
|
|
|
t.Parallel()
|
|
|
|
|
2017-07-30 04:34:54 +03:00
|
|
|
// We generate a fake output, and the corresponding txin. This output
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
// doesn't need to exist, as we'll only be validating spending from the
|
|
|
|
// transaction that references this.
|
2017-07-30 04:34:54 +03:00
|
|
|
txid, err := chainhash.NewHash(testHdSeed.CloneBytes())
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to create txid: %v", err)
|
|
|
|
}
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
fundingOut := &wire.OutPoint{
|
2017-07-30 04:34:54 +03:00
|
|
|
Hash: *txid,
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
Index: 50,
|
|
|
|
}
|
|
|
|
fakeFundingTxIn := wire.NewTxIn(fundingOut, nil, nil)
|
|
|
|
|
2017-07-30 04:34:54 +03:00
|
|
|
// Next we'll the commitment secret for our commitment tx and also the
|
|
|
|
// revocation key that we'll use as well.
|
|
|
|
revokePreimage := testHdSeed.CloneBytes()
|
|
|
|
commitSecret, commitPoint := btcec.PrivKeyFromBytes(btcec.S256(),
|
|
|
|
revokePreimage)
|
|
|
|
|
|
|
|
// Generate a payment preimage to be used below.
|
|
|
|
paymentPreimage := revokePreimage
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
paymentPreimage[0] ^= 1
|
2017-03-16 04:56:25 +03:00
|
|
|
paymentHash := sha256.Sum256(paymentPreimage[:])
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
|
2017-01-13 08:01:50 +03:00
|
|
|
// We'll also need some tests keys for alice and bob, and metadata of
|
2016-06-29 21:31:29 +03:00
|
|
|
// the HTLC output.
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes(btcec.S256(),
|
|
|
|
testWalletPrivKey)
|
|
|
|
bobKeyPriv, bobKeyPub := btcec.PrivKeyFromBytes(btcec.S256(),
|
|
|
|
bobsPrivKey)
|
|
|
|
paymentAmt := btcutil.Amount(1 * 10e8)
|
2017-07-30 04:34:54 +03:00
|
|
|
|
|
|
|
aliceLocalKey := TweakPubKey(aliceKeyPub, commitPoint)
|
|
|
|
bobLocalKey := TweakPubKey(bobKeyPub, commitPoint)
|
|
|
|
|
|
|
|
// As we'll be modeling spends from Alice's commitment transaction,
|
|
|
|
// we'll be using Bob's base point for the revocation key.
|
|
|
|
revocationKey := DeriveRevocationPubkey(bobKeyPub, commitPoint)
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
|
2017-07-30 04:34:54 +03:00
|
|
|
bobCommitTweak := SingleTweakBytes(commitPoint, bobKeyPub)
|
|
|
|
aliceCommitTweak := SingleTweakBytes(commitPoint, aliceKeyPub)
|
|
|
|
|
|
|
|
// Finally, we'll create mock signers for both of them based on their
|
|
|
|
// private keys. This test simplifies a bit and uses the same key as
|
|
|
|
// the base point for all scripts and derivations.
|
2019-01-16 17:47:43 +03:00
|
|
|
bobSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{bobKeyPriv}}
|
|
|
|
aliceSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{aliceKeyPriv}}
|
2017-07-30 04:34:54 +03:00
|
|
|
|
2020-03-06 18:11:45 +03:00
|
|
|
var (
|
|
|
|
htlcWitnessScript, htlcPkScript []byte
|
|
|
|
htlcOutput *wire.TxOut
|
|
|
|
sweepTxSigHashes *txscript.TxSigHashes
|
|
|
|
senderCommitTx, sweepTx *wire.MsgTx
|
|
|
|
bobRecvrSig []byte
|
2020-03-06 18:11:47 +03:00
|
|
|
bobSigHash txscript.SigHashType
|
2020-03-06 18:11:45 +03:00
|
|
|
)
|
|
|
|
|
2020-03-06 18:11:45 +03:00
|
|
|
// genCommitTx generates a commitment tx where the htlc output requires
|
|
|
|
// confirmation to be spent according to 'confirmed'.
|
|
|
|
genCommitTx := func(confirmed bool) {
|
2020-03-06 18:11:45 +03:00
|
|
|
// Generate the raw HTLC redemption scripts, and its p2wsh
|
|
|
|
// counterpart.
|
|
|
|
htlcWitnessScript, err = SenderHTLCScript(
|
|
|
|
aliceLocalKey, bobLocalKey, revocationKey,
|
2020-03-06 18:11:45 +03:00
|
|
|
paymentHash[:], confirmed,
|
2020-03-06 18:11:45 +03:00
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to create htlc sender script: %v", err)
|
|
|
|
}
|
|
|
|
htlcPkScript, err = WitnessScriptHash(htlcWitnessScript)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to create p2wsh htlc script: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// This will be Alice's commitment transaction. In this
|
|
|
|
// scenario Alice is sending an HTLC to a node she has a path
|
|
|
|
// to (could be Bob, could be multiple hops down, it doesn't
|
|
|
|
// really matter).
|
|
|
|
htlcOutput = &wire.TxOut{
|
|
|
|
Value: int64(paymentAmt),
|
|
|
|
PkScript: htlcPkScript,
|
|
|
|
}
|
|
|
|
senderCommitTx = wire.NewMsgTx(2)
|
|
|
|
senderCommitTx.AddTxIn(fakeFundingTxIn)
|
|
|
|
senderCommitTx.AddTxOut(htlcOutput)
|
2017-07-30 04:34:54 +03:00
|
|
|
}
|
2020-03-06 18:11:45 +03:00
|
|
|
|
2020-03-06 18:11:45 +03:00
|
|
|
// genSweepTx generates a sweep of the senderCommitTx, and sets the
|
2020-03-06 18:11:47 +03:00
|
|
|
// sequence and sighash single|anyonecanspend if confirmed is true.
|
2020-03-06 18:11:45 +03:00
|
|
|
genSweepTx := func(confirmed bool) {
|
2020-03-06 18:11:45 +03:00
|
|
|
prevOut := &wire.OutPoint{
|
|
|
|
Hash: senderCommitTx.TxHash(),
|
|
|
|
Index: 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
sweepTx = wire.NewMsgTx(2)
|
|
|
|
|
|
|
|
sweepTx.AddTxIn(wire.NewTxIn(prevOut, nil, nil))
|
2020-03-06 18:11:45 +03:00
|
|
|
if confirmed {
|
|
|
|
sweepTx.TxIn[0].Sequence = LockTimeToSequence(false, 1)
|
|
|
|
}
|
2020-03-06 18:11:45 +03:00
|
|
|
|
|
|
|
sweepTx.AddTxOut(
|
|
|
|
&wire.TxOut{
|
|
|
|
PkScript: []byte("doesn't matter"),
|
|
|
|
Value: 1 * 10e8,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
sweepTxSigHashes = txscript.NewTxSigHashes(sweepTx)
|
|
|
|
|
2020-03-06 18:11:47 +03:00
|
|
|
bobSigHash = txscript.SigHashAll
|
|
|
|
if confirmed {
|
|
|
|
bobSigHash = txscript.SigHashSingle | txscript.SigHashAnyOneCanPay
|
|
|
|
}
|
|
|
|
|
2020-03-06 18:11:45 +03:00
|
|
|
// We'll also generate a signature on the sweep transaction above
|
|
|
|
// that will act as Bob's signature to Alice for the second level HTLC
|
|
|
|
// transaction.
|
|
|
|
bobSignDesc := SignDescriptor{
|
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: bobKeyPub,
|
|
|
|
},
|
|
|
|
SingleTweak: bobCommitTweak,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
2020-03-06 18:11:47 +03:00
|
|
|
HashType: bobSigHash,
|
2020-03-06 18:11:45 +03:00
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
bobRecvrSig, err = bobSigner.SignOutputRaw(sweepTx, &bobSignDesc)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to generate alice signature: %v", err)
|
|
|
|
}
|
2017-07-30 04:34:54 +03:00
|
|
|
}
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
witness func() wire.TxWitness
|
|
|
|
valid bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
// revoke w/ sig
|
|
|
|
// TODO(roasbeef): test invalid revoke
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
2020-03-06 18:11:45 +03:00
|
|
|
genCommitTx(false)
|
|
|
|
genSweepTx(false)
|
2020-03-06 18:11:45 +03:00
|
|
|
|
2017-07-30 04:34:54 +03:00
|
|
|
signDesc := &SignDescriptor{
|
2018-02-18 02:09:51 +03:00
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: bobKeyPub,
|
|
|
|
},
|
2017-07-30 04:34:54 +03:00
|
|
|
DoubleTweak: commitSecret,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
2019-01-16 17:47:43 +03:00
|
|
|
return SenderHtlcSpendRevokeWithKey(bobSigner, signDesc,
|
2017-07-30 04:34:54 +03:00
|
|
|
revocationKey, sweepTx)
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
}),
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
2017-01-13 08:01:50 +03:00
|
|
|
// HTLC with invalid preimage size
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
2020-03-06 18:11:45 +03:00
|
|
|
genCommitTx(false)
|
|
|
|
genSweepTx(false)
|
2020-03-06 18:11:45 +03:00
|
|
|
|
2017-07-30 04:34:54 +03:00
|
|
|
signDesc := &SignDescriptor{
|
2018-02-18 02:09:51 +03:00
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: bobKeyPub,
|
|
|
|
},
|
2017-07-30 04:34:54 +03:00
|
|
|
SingleTweak: bobCommitTweak,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
2018-01-17 05:38:49 +03:00
|
|
|
return SenderHtlcSpendRedeem(bobSigner, signDesc,
|
2017-07-30 04:34:54 +03:00
|
|
|
sweepTx,
|
2017-01-13 08:01:50 +03:00
|
|
|
// Invalid preimage length
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
bytes.Repeat([]byte{1}, 45))
|
|
|
|
}),
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
2017-01-13 08:01:50 +03:00
|
|
|
// HTLC with valid preimage size + sig
|
2018-02-07 06:11:11 +03:00
|
|
|
// TODO(roasbeef): invalid preimage
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
2020-03-06 18:11:45 +03:00
|
|
|
genCommitTx(false)
|
|
|
|
genSweepTx(false)
|
|
|
|
|
|
|
|
signDesc := &SignDescriptor{
|
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: bobKeyPub,
|
|
|
|
},
|
|
|
|
SingleTweak: bobCommitTweak,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
return SenderHtlcSpendRedeem(bobSigner, signDesc,
|
|
|
|
sweepTx, paymentPreimage)
|
|
|
|
}),
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// HTLC with valid preimage size + sig, and with
|
|
|
|
// enforced locktime in HTLC script.
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
|
|
|
// Make a commit tx that needs confirmation for
|
|
|
|
// HTLC output to be spent.
|
|
|
|
genCommitTx(true)
|
|
|
|
|
|
|
|
// Generate a sweep with the locktime set.
|
|
|
|
genSweepTx(true)
|
|
|
|
|
|
|
|
signDesc := &SignDescriptor{
|
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: bobKeyPub,
|
|
|
|
},
|
|
|
|
SingleTweak: bobCommitTweak,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
return SenderHtlcSpendRedeem(bobSigner, signDesc,
|
|
|
|
sweepTx, paymentPreimage)
|
|
|
|
}),
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// HTLC with valid preimage size + sig, but trying to
|
|
|
|
// spend CSV output without sequence set.
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
|
|
|
// Generate commitment tx with 1 CSV locked
|
|
|
|
// HTLC.
|
|
|
|
genCommitTx(true)
|
|
|
|
|
|
|
|
// Generate sweep tx that doesn't have locktime
|
|
|
|
// enabled.
|
|
|
|
genSweepTx(false)
|
2020-03-06 18:11:45 +03:00
|
|
|
|
2017-07-30 04:34:54 +03:00
|
|
|
signDesc := &SignDescriptor{
|
2018-02-18 02:09:51 +03:00
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: bobKeyPub,
|
|
|
|
},
|
2017-07-30 04:34:54 +03:00
|
|
|
SingleTweak: bobCommitTweak,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
2018-01-17 05:38:49 +03:00
|
|
|
return SenderHtlcSpendRedeem(bobSigner, signDesc,
|
2017-07-30 04:34:54 +03:00
|
|
|
sweepTx, paymentPreimage)
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
}),
|
2020-03-06 18:11:45 +03:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
// valid spend to the transition the state of the HTLC
|
|
|
|
// output with the second level HTLC timeout
|
|
|
|
// transaction.
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
|
|
|
genCommitTx(false)
|
|
|
|
genSweepTx(false)
|
|
|
|
|
|
|
|
signDesc := &SignDescriptor{
|
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: aliceKeyPub,
|
|
|
|
},
|
|
|
|
SingleTweak: aliceCommitTweak,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
2020-03-06 18:11:47 +03:00
|
|
|
return SenderHtlcSpendTimeout(
|
|
|
|
bobRecvrSig, bobSigHash, aliceSigner,
|
|
|
|
signDesc, sweepTx,
|
|
|
|
)
|
2020-03-06 18:11:45 +03:00
|
|
|
}),
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
2017-07-30 04:34:54 +03:00
|
|
|
// valid spend to the transition the state of the HTLC
|
|
|
|
// output with the second level HTLC timeout
|
|
|
|
// transaction.
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
2020-03-06 18:11:45 +03:00
|
|
|
// Make a commit tx that needs confirmation for
|
|
|
|
// HTLC output to be spent.
|
|
|
|
genCommitTx(true)
|
|
|
|
|
|
|
|
// Generate a sweep with the locktime set.
|
|
|
|
genSweepTx(true)
|
2020-03-06 18:11:45 +03:00
|
|
|
|
2017-07-30 04:34:54 +03:00
|
|
|
signDesc := &SignDescriptor{
|
2018-02-18 02:09:51 +03:00
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: aliceKeyPub,
|
|
|
|
},
|
2017-07-30 04:34:54 +03:00
|
|
|
SingleTweak: aliceCommitTweak,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
2020-03-06 18:11:47 +03:00
|
|
|
return SenderHtlcSpendTimeout(
|
|
|
|
bobRecvrSig, bobSigHash, aliceSigner,
|
|
|
|
signDesc, sweepTx,
|
|
|
|
)
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
}),
|
|
|
|
true,
|
|
|
|
},
|
2020-03-06 18:11:45 +03:00
|
|
|
{
|
|
|
|
// valid spend to the transition the state of the HTLC
|
|
|
|
// output with the second level HTLC timeout
|
|
|
|
// transaction.
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
|
|
|
// Generate commitment tx with 1 CSV locked
|
|
|
|
// HTLC.
|
|
|
|
genCommitTx(true)
|
|
|
|
|
|
|
|
// Generate sweep tx that doesn't have locktime
|
|
|
|
// enabled.
|
|
|
|
genSweepTx(false)
|
|
|
|
|
|
|
|
signDesc := &SignDescriptor{
|
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: aliceKeyPub,
|
|
|
|
},
|
|
|
|
SingleTweak: aliceCommitTweak,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
2020-03-06 18:11:47 +03:00
|
|
|
return SenderHtlcSpendTimeout(
|
|
|
|
bobRecvrSig, bobSigHash, aliceSigner,
|
|
|
|
signDesc, sweepTx,
|
|
|
|
)
|
2020-03-06 18:11:45 +03:00
|
|
|
}),
|
|
|
|
false,
|
|
|
|
},
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
}
|
|
|
|
|
2018-02-18 02:09:51 +03:00
|
|
|
// TODO(roasbeef): set of cases to ensure able to sign w/ keypath and
|
|
|
|
// not
|
|
|
|
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
for i, testCase := range testCases {
|
|
|
|
sweepTx.TxIn[0].Witness = testCase.witness()
|
|
|
|
|
2020-03-06 18:11:44 +03:00
|
|
|
newEngine := func() (*txscript.Engine, error) {
|
|
|
|
return txscript.NewEngine(htlcPkScript,
|
|
|
|
sweepTx, 0, txscript.StandardVerifyFlags, nil,
|
|
|
|
nil, int64(paymentAmt))
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
}
|
|
|
|
|
2020-03-06 18:11:44 +03:00
|
|
|
assertEngineExecution(t, i, testCase.valid, newEngine)
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestHTLCReceiverSpendValidation tests all possible valid+invalid redemption
|
2017-01-13 08:01:50 +03:00
|
|
|
// paths in the script used within the receiver's commitment transaction for an
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
// incoming HTLC.
|
|
|
|
//
|
|
|
|
// The following cases are exercised by this test:
|
2017-01-13 08:01:50 +03:00
|
|
|
// * receiver spends
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
// * HTLC redemption w/ invalid preimage size
|
|
|
|
// * HTLC redemption w/ invalid sequence
|
|
|
|
// * HTLC redemption w/ valid preimage size
|
|
|
|
// * sender spends
|
|
|
|
// * revoke w/ sig
|
|
|
|
// * refund w/ invalid lock time
|
|
|
|
// * refund w/ valid lock time
|
|
|
|
func TestHTLCReceiverSpendValidation(t *testing.T) {
|
2017-06-17 01:59:20 +03:00
|
|
|
t.Parallel()
|
|
|
|
|
2017-07-30 04:34:16 +03:00
|
|
|
// We generate a fake output, and the corresponding txin. This output
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
// doesn't need to exist, as we'll only be validating spending from the
|
|
|
|
// transaction that references this.
|
2017-07-30 04:34:16 +03:00
|
|
|
txid, err := chainhash.NewHash(testHdSeed.CloneBytes())
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to create txid: %v", err)
|
|
|
|
}
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
fundingOut := &wire.OutPoint{
|
2017-07-30 04:34:16 +03:00
|
|
|
Hash: *txid,
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
Index: 50,
|
|
|
|
}
|
|
|
|
fakeFundingTxIn := wire.NewTxIn(fundingOut, nil, nil)
|
|
|
|
|
2017-07-30 04:34:16 +03:00
|
|
|
// Next we'll the commitment secret for our commitment tx and also the
|
|
|
|
// revocation key that we'll use as well.
|
|
|
|
revokePreimage := testHdSeed.CloneBytes()
|
|
|
|
commitSecret, commitPoint := btcec.PrivKeyFromBytes(btcec.S256(),
|
|
|
|
revokePreimage)
|
|
|
|
|
|
|
|
// Generate a payment preimage to be used below.
|
|
|
|
paymentPreimage := revokePreimage
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
paymentPreimage[0] ^= 1
|
2017-03-16 04:56:25 +03:00
|
|
|
paymentHash := sha256.Sum256(paymentPreimage[:])
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
|
2017-01-13 08:01:50 +03:00
|
|
|
// We'll also need some tests keys for alice and bob, and metadata of
|
2016-06-29 21:31:29 +03:00
|
|
|
// the HTLC output.
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes(btcec.S256(),
|
|
|
|
testWalletPrivKey)
|
|
|
|
bobKeyPriv, bobKeyPub := btcec.PrivKeyFromBytes(btcec.S256(),
|
|
|
|
bobsPrivKey)
|
|
|
|
paymentAmt := btcutil.Amount(1 * 10e8)
|
|
|
|
cltvTimeout := uint32(8)
|
2017-07-30 04:34:16 +03:00
|
|
|
|
|
|
|
aliceLocalKey := TweakPubKey(aliceKeyPub, commitPoint)
|
|
|
|
bobLocalKey := TweakPubKey(bobKeyPub, commitPoint)
|
|
|
|
|
|
|
|
// As we'll be modeling spends from Bob's commitment transaction, we'll
|
|
|
|
// be using Alice's base point for the revocation key.
|
|
|
|
revocationKey := DeriveRevocationPubkey(aliceKeyPub, commitPoint)
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
|
2017-07-30 04:34:16 +03:00
|
|
|
bobCommitTweak := SingleTweakBytes(commitPoint, bobKeyPub)
|
|
|
|
aliceCommitTweak := SingleTweakBytes(commitPoint, aliceKeyPub)
|
|
|
|
|
|
|
|
// Finally, we'll create mock signers for both of them based on their
|
|
|
|
// private keys. This test simplifies a bit and uses the same key as
|
|
|
|
// the base point for all scripts and derivations.
|
2019-01-16 17:47:43 +03:00
|
|
|
bobSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{bobKeyPriv}}
|
|
|
|
aliceSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{aliceKeyPriv}}
|
2017-07-30 04:34:16 +03:00
|
|
|
|
2020-03-06 18:11:45 +03:00
|
|
|
var (
|
|
|
|
htlcWitnessScript, htlcPkScript []byte
|
|
|
|
htlcOutput *wire.TxOut
|
|
|
|
receiverCommitTx, sweepTx *wire.MsgTx
|
|
|
|
sweepTxSigHashes *txscript.TxSigHashes
|
|
|
|
aliceSenderSig []byte
|
2020-03-06 18:11:47 +03:00
|
|
|
aliceSigHash txscript.SigHashType
|
2020-03-06 18:11:45 +03:00
|
|
|
)
|
|
|
|
|
2020-03-06 18:11:45 +03:00
|
|
|
genCommitTx := func(confirmed bool) {
|
2020-03-06 18:11:45 +03:00
|
|
|
// Generate the raw HTLC redemption scripts, and its p2wsh
|
|
|
|
// counterpart.
|
|
|
|
htlcWitnessScript, err = ReceiverHTLCScript(
|
|
|
|
cltvTimeout, aliceLocalKey, bobLocalKey, revocationKey,
|
2020-03-06 18:11:45 +03:00
|
|
|
paymentHash[:], confirmed,
|
2020-03-06 18:11:45 +03:00
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to create htlc sender script: %v", err)
|
|
|
|
}
|
|
|
|
htlcPkScript, err = WitnessScriptHash(htlcWitnessScript)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to create p2wsh htlc script: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// This will be Bob's commitment transaction. In this scenario Alice is
|
|
|
|
// sending an HTLC to a node she has a path to (could be Bob, could be
|
|
|
|
// multiple hops down, it doesn't really matter).
|
|
|
|
htlcOutput = &wire.TxOut{
|
|
|
|
Value: int64(paymentAmt),
|
|
|
|
PkScript: htlcWitnessScript,
|
|
|
|
}
|
|
|
|
|
|
|
|
receiverCommitTx = wire.NewMsgTx(2)
|
|
|
|
receiverCommitTx.AddTxIn(fakeFundingTxIn)
|
|
|
|
receiverCommitTx.AddTxOut(htlcOutput)
|
2017-07-30 04:34:16 +03:00
|
|
|
}
|
2020-03-06 18:11:45 +03:00
|
|
|
|
2020-03-06 18:11:45 +03:00
|
|
|
genSweepTx := func(confirmed bool) {
|
2020-03-06 18:11:45 +03:00
|
|
|
prevOut := &wire.OutPoint{
|
|
|
|
Hash: receiverCommitTx.TxHash(),
|
|
|
|
Index: 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
sweepTx = wire.NewMsgTx(2)
|
|
|
|
sweepTx.AddTxIn(&wire.TxIn{
|
|
|
|
PreviousOutPoint: *prevOut,
|
|
|
|
})
|
2020-03-06 18:11:45 +03:00
|
|
|
if confirmed {
|
|
|
|
sweepTx.TxIn[0].Sequence = LockTimeToSequence(false, 1)
|
|
|
|
}
|
2020-03-06 18:11:45 +03:00
|
|
|
|
|
|
|
sweepTx.AddTxOut(
|
|
|
|
&wire.TxOut{
|
|
|
|
PkScript: []byte("doesn't matter"),
|
|
|
|
Value: 1 * 10e8,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
sweepTxSigHashes = txscript.NewTxSigHashes(sweepTx)
|
|
|
|
|
2020-03-06 18:11:47 +03:00
|
|
|
aliceSigHash = txscript.SigHashAll
|
|
|
|
if confirmed {
|
|
|
|
aliceSigHash = txscript.SigHashSingle | txscript.SigHashAnyOneCanPay
|
|
|
|
}
|
|
|
|
|
2020-03-06 18:11:45 +03:00
|
|
|
// We'll also generate a signature on the sweep transaction above
|
|
|
|
// that will act as Alice's signature to Bob for the second level HTLC
|
|
|
|
// transaction.
|
|
|
|
aliceSignDesc := SignDescriptor{
|
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: aliceKeyPub,
|
|
|
|
},
|
|
|
|
SingleTweak: aliceCommitTweak,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
2020-03-06 18:11:47 +03:00
|
|
|
HashType: aliceSigHash,
|
2020-03-06 18:11:45 +03:00
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
aliceSenderSig, err = aliceSigner.SignOutputRaw(sweepTx, &aliceSignDesc)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to generate alice signature: %v", err)
|
|
|
|
}
|
2017-07-30 04:34:16 +03:00
|
|
|
}
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
|
2017-07-30 04:34:16 +03:00
|
|
|
// TODO(roasbeef): modify valid to check precise script errors?
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
testCases := []struct {
|
|
|
|
witness func() wire.TxWitness
|
|
|
|
valid bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
// HTLC redemption w/ invalid preimage size
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
2020-03-06 18:11:45 +03:00
|
|
|
genCommitTx(false)
|
|
|
|
genSweepTx(false)
|
2020-03-06 18:11:45 +03:00
|
|
|
|
2017-07-30 04:34:16 +03:00
|
|
|
signDesc := &SignDescriptor{
|
2018-02-18 02:09:51 +03:00
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: bobKeyPub,
|
|
|
|
},
|
2017-07-30 04:34:16 +03:00
|
|
|
SingleTweak: bobCommitTweak,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
2020-03-06 18:11:47 +03:00
|
|
|
return ReceiverHtlcSpendRedeem(
|
|
|
|
aliceSenderSig, aliceSigHash,
|
2017-07-30 04:34:16 +03:00
|
|
|
bytes.Repeat([]byte{1}, 45), bobSigner,
|
2020-03-06 18:11:47 +03:00
|
|
|
signDesc, sweepTx,
|
|
|
|
)
|
2017-07-30 04:34:16 +03:00
|
|
|
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
}),
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// HTLC redemption w/ valid preimage size
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
2020-03-06 18:11:45 +03:00
|
|
|
genCommitTx(false)
|
|
|
|
genSweepTx(false)
|
2020-03-06 18:11:45 +03:00
|
|
|
|
2017-07-30 04:34:16 +03:00
|
|
|
signDesc := &SignDescriptor{
|
2018-02-18 02:09:51 +03:00
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: bobKeyPub,
|
|
|
|
},
|
2017-07-30 04:34:16 +03:00
|
|
|
SingleTweak: bobCommitTweak,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
2020-03-06 18:11:47 +03:00
|
|
|
return ReceiverHtlcSpendRedeem(
|
|
|
|
aliceSenderSig, aliceSigHash,
|
|
|
|
paymentPreimage, bobSigner,
|
|
|
|
signDesc, sweepTx,
|
|
|
|
)
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
}),
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// revoke w/ sig
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
2020-03-06 18:11:45 +03:00
|
|
|
genCommitTx(false)
|
|
|
|
genSweepTx(false)
|
2020-03-06 18:11:45 +03:00
|
|
|
|
2017-07-30 04:34:16 +03:00
|
|
|
signDesc := &SignDescriptor{
|
2018-02-18 02:09:51 +03:00
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: aliceKeyPub,
|
|
|
|
},
|
2017-07-30 04:34:16 +03:00
|
|
|
DoubleTweak: commitSecret,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
2019-01-16 17:47:43 +03:00
|
|
|
return ReceiverHtlcSpendRevokeWithKey(aliceSigner,
|
2017-07-30 04:34:16 +03:00
|
|
|
signDesc, revocationKey, sweepTx)
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
}),
|
|
|
|
true,
|
|
|
|
},
|
2020-03-06 18:11:45 +03:00
|
|
|
{
|
|
|
|
// HTLC redemption w/ valid preimage size, and with
|
|
|
|
// enforced locktime in HTLC scripts.
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
|
|
|
// Make a commit tx that needs confirmation for
|
|
|
|
// HTLC output to be spent.
|
|
|
|
genCommitTx(true)
|
|
|
|
|
|
|
|
// Generate a sweep with the locktime set.
|
|
|
|
genSweepTx(true)
|
|
|
|
|
|
|
|
signDesc := &SignDescriptor{
|
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: bobKeyPub,
|
|
|
|
},
|
|
|
|
SingleTweak: bobCommitTweak,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
2020-03-06 18:11:47 +03:00
|
|
|
return ReceiverHtlcSpendRedeem(
|
|
|
|
aliceSenderSig, aliceSigHash,
|
2020-03-06 18:11:45 +03:00
|
|
|
paymentPreimage, bobSigner,
|
2020-03-06 18:11:47 +03:00
|
|
|
signDesc, sweepTx,
|
|
|
|
)
|
2020-03-06 18:11:45 +03:00
|
|
|
}),
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// HTLC redemption w/ valid preimage size, but trying
|
|
|
|
// to spend CSV output without sequence set.
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
|
|
|
// Generate commitment tx with 1 CSV locked
|
|
|
|
// HTLC.
|
|
|
|
genCommitTx(true)
|
|
|
|
|
|
|
|
// Generate sweep tx that doesn't have locktime
|
|
|
|
// enabled.
|
|
|
|
genSweepTx(false)
|
|
|
|
|
|
|
|
signDesc := &SignDescriptor{
|
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: bobKeyPub,
|
|
|
|
},
|
|
|
|
SingleTweak: bobCommitTweak,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
2020-03-06 18:11:47 +03:00
|
|
|
return ReceiverHtlcSpendRedeem(
|
|
|
|
aliceSenderSig, aliceSigHash,
|
|
|
|
paymentPreimage, bobSigner, signDesc,
|
|
|
|
sweepTx,
|
|
|
|
)
|
2020-03-06 18:11:45 +03:00
|
|
|
}),
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
{
|
|
|
|
// refund w/ invalid lock time
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
2020-03-06 18:11:45 +03:00
|
|
|
genCommitTx(false)
|
|
|
|
genSweepTx(false)
|
2020-03-06 18:11:45 +03:00
|
|
|
|
2017-07-30 04:34:16 +03:00
|
|
|
signDesc := &SignDescriptor{
|
2018-02-18 02:09:51 +03:00
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: aliceKeyPub,
|
|
|
|
},
|
2017-07-30 04:34:16 +03:00
|
|
|
SingleTweak: aliceCommitTweak,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
2019-01-16 17:47:43 +03:00
|
|
|
return ReceiverHtlcSpendTimeout(aliceSigner, signDesc,
|
2018-01-17 05:38:49 +03:00
|
|
|
sweepTx, int32(cltvTimeout-2))
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
}),
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// refund w/ valid lock time
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
2020-03-06 18:11:45 +03:00
|
|
|
genCommitTx(false)
|
|
|
|
genSweepTx(false)
|
2020-03-06 18:11:45 +03:00
|
|
|
|
2017-07-30 04:34:16 +03:00
|
|
|
signDesc := &SignDescriptor{
|
2018-02-18 02:09:51 +03:00
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: aliceKeyPub,
|
|
|
|
},
|
2017-07-30 04:34:16 +03:00
|
|
|
SingleTweak: aliceCommitTweak,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
2019-01-16 17:47:43 +03:00
|
|
|
return ReceiverHtlcSpendTimeout(aliceSigner, signDesc,
|
2018-01-17 05:38:49 +03:00
|
|
|
sweepTx, int32(cltvTimeout))
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
}),
|
|
|
|
true,
|
|
|
|
},
|
2020-03-06 18:11:45 +03:00
|
|
|
{
|
|
|
|
// refund w/ valid lock time, and enforced locktime in
|
|
|
|
// HTLC scripts.
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
|
|
|
// Make a commit tx that needs confirmation for
|
|
|
|
// HTLC output to be spent.
|
|
|
|
genCommitTx(true)
|
|
|
|
|
|
|
|
// Generate a sweep with the locktime set.
|
|
|
|
genSweepTx(true)
|
|
|
|
|
|
|
|
signDesc := &SignDescriptor{
|
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: aliceKeyPub,
|
|
|
|
},
|
|
|
|
SingleTweak: aliceCommitTweak,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
return ReceiverHtlcSpendTimeout(aliceSigner, signDesc,
|
|
|
|
sweepTx, int32(cltvTimeout))
|
|
|
|
}),
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// refund w/ valid lock time, but no sequence set in
|
|
|
|
// sweep tx trying to spend CSV locked HTLC output.
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
|
|
|
// Generate commitment tx with 1 CSV locked
|
|
|
|
// HTLC.
|
|
|
|
genCommitTx(true)
|
|
|
|
|
|
|
|
// Generate sweep tx that doesn't have locktime
|
|
|
|
// enabled.
|
|
|
|
genSweepTx(false)
|
|
|
|
|
|
|
|
signDesc := &SignDescriptor{
|
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: aliceKeyPub,
|
|
|
|
},
|
|
|
|
SingleTweak: aliceCommitTweak,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
return ReceiverHtlcSpendTimeout(aliceSigner, signDesc,
|
|
|
|
sweepTx, int32(cltvTimeout))
|
|
|
|
}),
|
|
|
|
false,
|
|
|
|
},
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
for i, testCase := range testCases {
|
|
|
|
sweepTx.TxIn[0].Witness = testCase.witness()
|
|
|
|
|
2020-03-06 18:11:44 +03:00
|
|
|
newEngine := func() (*txscript.Engine, error) {
|
|
|
|
return txscript.NewEngine(htlcPkScript,
|
|
|
|
sweepTx, 0, txscript.StandardVerifyFlags, nil,
|
|
|
|
nil, int64(paymentAmt))
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
}
|
|
|
|
|
2020-03-06 18:11:44 +03:00
|
|
|
assertEngineExecution(t, i, testCase.valid, newEngine)
|
lnwallet: update HTLC+commitment scripts
This commit updates the previous HTLC and commitment scripts to their
current latest evolution.
The HTLC scripts have been optimized for space savings, the
functionality itself has remained relatively unchanged. A trade off was
made to add additional bytes into the sigScript in order to avoid
extraneous CHECKSIG’s. The rationale is that an extra 1-2 bytes in the
sigScript to guide execution, are worthwhile since they’re in the
witness, and witness data may be pruned in the near future.
The primary change is within the commitment transaction itself. Instead
of using revocation hashes, we now use signature based revocation. This
saves space in the Script, and optimizes away an extra hashing
operation. Elkrem/shachain is still used but, we now use the pre-images
to homomorphically derive a public key which the other party will be
able to sign with, once we disclose the pre-image itself.
Finally, we have switched to using SHA-256 everywhere uniformly for
both revocation hashes, and payment hashes. The rationale is that the
output of ripemd160 is too small for modern security margins, and that
other coins/chains are more likely to have SHA-256 implemented, than
ripemd160.
A set of tests has also been included which contain (mostly) exhaustive
tests of all possible redemption paths for both commitment and HTLC.
2016-06-27 21:33:59 +03:00
|
|
|
}
|
|
|
|
}
|
2016-11-15 05:34:59 +03:00
|
|
|
|
2017-07-30 04:32:04 +03:00
|
|
|
// TestSecondLevelHtlcSpends tests all the possible redemption clauses from the
|
|
|
|
// HTLC success and timeout covenant transactions.
|
|
|
|
func TestSecondLevelHtlcSpends(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
// We'll start be creating a creating a 2BTC HTLC.
|
|
|
|
const htlcAmt = btcutil.Amount(2 * 10e8)
|
|
|
|
|
|
|
|
// In all of our scenarios, the CSV timeout to claim a self output will
|
|
|
|
// be 5 blocks.
|
|
|
|
const claimDelay = 5
|
|
|
|
|
|
|
|
// First we'll set up some initial key state for Alice and Bob that
|
|
|
|
// will be used in the scripts we created below.
|
|
|
|
aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes(btcec.S256(),
|
|
|
|
testWalletPrivKey)
|
|
|
|
bobKeyPriv, bobKeyPub := btcec.PrivKeyFromBytes(btcec.S256(),
|
|
|
|
bobsPrivKey)
|
|
|
|
|
|
|
|
revokePreimage := testHdSeed.CloneBytes()
|
|
|
|
commitSecret, commitPoint := btcec.PrivKeyFromBytes(
|
|
|
|
btcec.S256(), revokePreimage)
|
|
|
|
|
|
|
|
// As we're modeling this as Bob sweeping the HTLC on-chain from his
|
|
|
|
// commitment transaction after a period of time, we'll be using a
|
|
|
|
// revocation key derived from Alice's base point and his secret.
|
|
|
|
revocationKey := DeriveRevocationPubkey(aliceKeyPub, commitPoint)
|
|
|
|
|
|
|
|
// Next, craft a fake HTLC outpoint that we'll use to generate the
|
|
|
|
// sweeping transaction using.
|
|
|
|
txid, err := chainhash.NewHash(testHdSeed.CloneBytes())
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to create txid: %v", err)
|
|
|
|
}
|
|
|
|
htlcOutPoint := &wire.OutPoint{
|
|
|
|
Hash: *txid,
|
|
|
|
Index: 0,
|
|
|
|
}
|
|
|
|
sweepTx := wire.NewMsgTx(2)
|
|
|
|
sweepTx.AddTxIn(wire.NewTxIn(htlcOutPoint, nil, nil))
|
|
|
|
sweepTx.AddTxOut(
|
|
|
|
&wire.TxOut{
|
|
|
|
PkScript: []byte("doesn't matter"),
|
|
|
|
Value: 1 * 10e8,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
sweepTxSigHashes := txscript.NewTxSigHashes(sweepTx)
|
|
|
|
|
|
|
|
// The delay key will be crafted using Bob's public key as the output
|
|
|
|
// we created will be spending from Alice's commitment transaction.
|
|
|
|
delayKey := TweakPubKey(bobKeyPub, commitPoint)
|
|
|
|
|
|
|
|
// The commit tweak will be required in order for Bob to derive the
|
|
|
|
// proper key need to spend the output.
|
|
|
|
commitTweak := SingleTweakBytes(commitPoint, bobKeyPub)
|
|
|
|
|
|
|
|
// Finally we'll generate the HTLC script itself that we'll be spending
|
|
|
|
// from. The revocation clause can be claimed by Alice, while Bob can
|
|
|
|
// sweep the output after a particular delay.
|
2019-01-16 17:47:43 +03:00
|
|
|
htlcWitnessScript, err := SecondLevelHtlcScript(revocationKey,
|
2017-07-30 04:32:04 +03:00
|
|
|
delayKey, claimDelay)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to create htlc script: %v", err)
|
|
|
|
}
|
2018-06-29 05:24:44 +03:00
|
|
|
htlcPkScript, err := WitnessScriptHash(htlcWitnessScript)
|
2017-07-30 04:32:04 +03:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to create htlc output: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
htlcOutput := &wire.TxOut{
|
|
|
|
PkScript: htlcPkScript,
|
|
|
|
Value: int64(htlcAmt),
|
|
|
|
}
|
|
|
|
|
2018-02-07 06:11:11 +03:00
|
|
|
// TODO(roasbeef): make actually use timeout/success txns?
|
2017-07-30 04:32:04 +03:00
|
|
|
|
|
|
|
// Finally, we'll create mock signers for both of them based on their
|
|
|
|
// private keys. This test simplifies a bit and uses the same key as
|
|
|
|
// the base point for all scripts and derivations.
|
2019-01-16 17:47:43 +03:00
|
|
|
bobSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{bobKeyPriv}}
|
|
|
|
aliceSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{aliceKeyPriv}}
|
2017-07-30 04:32:04 +03:00
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
witness func() wire.TxWitness
|
|
|
|
valid bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
// Sender of the HTLC attempts to activate the
|
|
|
|
// revocation clause, but uses the wrong key (fails to
|
|
|
|
// use the double tweak in this case).
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
|
|
|
signDesc := &SignDescriptor{
|
2018-02-18 02:09:51 +03:00
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: aliceKeyPub,
|
|
|
|
},
|
2017-07-30 04:32:04 +03:00
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
2019-01-16 17:47:43 +03:00
|
|
|
return HtlcSpendRevoke(aliceSigner, signDesc,
|
2017-07-30 04:32:04 +03:00
|
|
|
sweepTx)
|
|
|
|
}),
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// Sender of HTLC activates the revocation clause.
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
|
|
|
signDesc := &SignDescriptor{
|
2018-02-18 02:09:51 +03:00
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: aliceKeyPub,
|
|
|
|
},
|
2017-07-30 04:32:04 +03:00
|
|
|
DoubleTweak: commitSecret,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
2019-01-16 17:47:43 +03:00
|
|
|
return HtlcSpendRevoke(aliceSigner, signDesc,
|
2017-07-30 04:32:04 +03:00
|
|
|
sweepTx)
|
|
|
|
}),
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// Receiver of the HTLC attempts to sweep, but tries to
|
|
|
|
// do so pre-maturely with a smaller CSV delay (2
|
|
|
|
// blocks instead of 5 blocks).
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
|
|
|
signDesc := &SignDescriptor{
|
2018-02-18 02:09:51 +03:00
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: bobKeyPub,
|
|
|
|
},
|
2017-07-30 04:32:04 +03:00
|
|
|
SingleTweak: commitTweak,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
2019-01-16 17:47:43 +03:00
|
|
|
return HtlcSpendSuccess(bobSigner, signDesc,
|
2017-07-30 04:32:04 +03:00
|
|
|
sweepTx, claimDelay-3)
|
|
|
|
}),
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// Receiver of the HTLC sweeps with the proper CSV
|
|
|
|
// delay, but uses the wrong key (leaves off the single
|
|
|
|
// tweak).
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
|
|
|
signDesc := &SignDescriptor{
|
2018-02-18 02:09:51 +03:00
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: bobKeyPub,
|
|
|
|
},
|
2017-07-30 04:32:04 +03:00
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
2019-01-16 17:47:43 +03:00
|
|
|
return HtlcSpendSuccess(bobSigner, signDesc,
|
2017-07-30 04:32:04 +03:00
|
|
|
sweepTx, claimDelay)
|
|
|
|
}),
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// Receiver of the HTLC sweeps with the proper CSV
|
|
|
|
// delay, and the correct key.
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
|
|
|
signDesc := &SignDescriptor{
|
2018-02-18 02:09:51 +03:00
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: bobKeyPub,
|
|
|
|
},
|
2017-07-30 04:32:04 +03:00
|
|
|
SingleTweak: commitTweak,
|
|
|
|
WitnessScript: htlcWitnessScript,
|
|
|
|
Output: htlcOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
2019-01-16 17:47:43 +03:00
|
|
|
return HtlcSpendSuccess(bobSigner, signDesc,
|
2017-07-30 04:32:04 +03:00
|
|
|
sweepTx, claimDelay)
|
|
|
|
}),
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, testCase := range testCases {
|
|
|
|
sweepTx.TxIn[0].Witness = testCase.witness()
|
|
|
|
|
2020-03-06 18:11:44 +03:00
|
|
|
newEngine := func() (*txscript.Engine, error) {
|
|
|
|
return txscript.NewEngine(htlcPkScript,
|
|
|
|
sweepTx, 0, txscript.StandardVerifyFlags, nil,
|
|
|
|
nil, int64(htlcAmt))
|
2017-07-30 04:32:04 +03:00
|
|
|
}
|
|
|
|
|
2020-03-06 18:11:44 +03:00
|
|
|
assertEngineExecution(t, i, testCase.valid, newEngine)
|
2017-07-30 04:32:04 +03:00
|
|
|
}
|
2017-01-09 21:03:19 +03:00
|
|
|
}
|
|
|
|
|
2020-03-06 18:11:45 +03:00
|
|
|
// TestCommitSpendToRemoteConfirmed checks that the delayed version of the
|
|
|
|
// to_remote version can only be spent by the owner, and after one
|
|
|
|
// confirmation.
|
|
|
|
func TestCommitSpendToRemoteConfirmed(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
const outputVal = btcutil.Amount(2 * 10e8)
|
|
|
|
|
|
|
|
aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes(btcec.S256(),
|
|
|
|
testWalletPrivKey)
|
|
|
|
|
|
|
|
txid, err := chainhash.NewHash(testHdSeed.CloneBytes())
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to create txid: %v", err)
|
|
|
|
}
|
|
|
|
commitOut := &wire.OutPoint{
|
|
|
|
Hash: *txid,
|
|
|
|
Index: 0,
|
|
|
|
}
|
|
|
|
commitScript, err := CommitScriptToRemoteConfirmed(aliceKeyPub)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to create htlc script: %v", err)
|
|
|
|
}
|
|
|
|
commitPkScript, err := WitnessScriptHash(commitScript)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to create htlc output: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
commitOutput := &wire.TxOut{
|
|
|
|
PkScript: commitPkScript,
|
|
|
|
Value: int64(outputVal),
|
|
|
|
}
|
|
|
|
|
|
|
|
sweepTx := wire.NewMsgTx(2)
|
|
|
|
sweepTx.AddTxIn(wire.NewTxIn(commitOut, nil, nil))
|
|
|
|
sweepTx.AddTxOut(
|
|
|
|
&wire.TxOut{
|
|
|
|
PkScript: []byte("doesn't matter"),
|
|
|
|
Value: 1 * 10e8,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
aliceSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{aliceKeyPriv}}
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
witness func() wire.TxWitness
|
|
|
|
valid bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
// Alice can spend after the a CSV delay has passed.
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
|
|
|
sweepTx.TxIn[0].Sequence = LockTimeToSequence(false, 1)
|
|
|
|
sweepTxSigHashes := txscript.NewTxSigHashes(sweepTx)
|
|
|
|
|
|
|
|
signDesc := &SignDescriptor{
|
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: aliceKeyPub,
|
|
|
|
},
|
|
|
|
WitnessScript: commitScript,
|
|
|
|
Output: commitOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
return CommitSpendToRemoteConfirmed(aliceSigner, signDesc,
|
|
|
|
sweepTx)
|
|
|
|
}),
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// Alice cannot spend output without sequence set.
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
|
|
|
sweepTx.TxIn[0].Sequence = wire.MaxTxInSequenceNum
|
|
|
|
sweepTxSigHashes := txscript.NewTxSigHashes(sweepTx)
|
|
|
|
|
|
|
|
signDesc := &SignDescriptor{
|
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: aliceKeyPub,
|
|
|
|
},
|
|
|
|
WitnessScript: commitScript,
|
|
|
|
Output: commitOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
return CommitSpendToRemoteConfirmed(aliceSigner, signDesc,
|
|
|
|
sweepTx)
|
|
|
|
}),
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, testCase := range testCases {
|
|
|
|
sweepTx.TxIn[0].Witness = testCase.witness()
|
|
|
|
|
|
|
|
newEngine := func() (*txscript.Engine, error) {
|
|
|
|
return txscript.NewEngine(commitPkScript,
|
|
|
|
sweepTx, 0, txscript.StandardVerifyFlags, nil,
|
|
|
|
nil, int64(outputVal))
|
|
|
|
}
|
|
|
|
|
|
|
|
assertEngineExecution(t, i, testCase.valid, newEngine)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-06 18:11:46 +03:00
|
|
|
// TestSpendAnchor checks that we can spend the anchors using the various spend
|
|
|
|
// paths.
|
|
|
|
func TestSpendAnchor(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
const anchorSize = 294
|
|
|
|
|
|
|
|
// First we'll set up some initial key state for Alice.
|
|
|
|
aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes(btcec.S256(),
|
|
|
|
testWalletPrivKey)
|
|
|
|
|
|
|
|
// Create a fake anchor outpoint that we'll use to generate the
|
|
|
|
// sweeping transaction.
|
|
|
|
txid, err := chainhash.NewHash(testHdSeed.CloneBytes())
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to create txid: %v", err)
|
|
|
|
}
|
|
|
|
anchorOutPoint := &wire.OutPoint{
|
|
|
|
Hash: *txid,
|
|
|
|
Index: 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
sweepTx := wire.NewMsgTx(2)
|
|
|
|
sweepTx.AddTxIn(wire.NewTxIn(anchorOutPoint, nil, nil))
|
|
|
|
sweepTx.AddTxOut(
|
|
|
|
&wire.TxOut{
|
|
|
|
PkScript: []byte("doesn't matter"),
|
|
|
|
Value: 1 * 10e8,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
// Generate the anchor script that can be spent by Alice immediately,
|
|
|
|
// or by anyone after 16 blocks.
|
|
|
|
anchorScript, err := CommitScriptAnchor(aliceKeyPub)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to create htlc script: %v", err)
|
|
|
|
}
|
|
|
|
anchorPkScript, err := WitnessScriptHash(anchorScript)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to create htlc output: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
anchorOutput := &wire.TxOut{
|
|
|
|
PkScript: anchorPkScript,
|
|
|
|
Value: int64(anchorSize),
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create mock signer for Alice.
|
|
|
|
aliceSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{aliceKeyPriv}}
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
witness func() wire.TxWitness
|
|
|
|
valid bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
// Alice can spend immediately.
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
|
|
|
sweepTx.TxIn[0].Sequence = wire.MaxTxInSequenceNum
|
|
|
|
sweepTxSigHashes := txscript.NewTxSigHashes(sweepTx)
|
|
|
|
|
|
|
|
signDesc := &SignDescriptor{
|
|
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
|
|
PubKey: aliceKeyPub,
|
|
|
|
},
|
|
|
|
WitnessScript: anchorScript,
|
|
|
|
Output: anchorOutput,
|
|
|
|
HashType: txscript.SigHashAll,
|
|
|
|
SigHashes: sweepTxSigHashes,
|
|
|
|
InputIndex: 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
return CommitSpendAnchor(aliceSigner, signDesc,
|
|
|
|
sweepTx)
|
|
|
|
}),
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// Anyone can spend after 16 blocks.
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
|
|
|
sweepTx.TxIn[0].Sequence = LockTimeToSequence(false, 16)
|
|
|
|
return CommitSpendAnchorAnyone(anchorScript)
|
|
|
|
}),
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// Anyone cannot spend before 16 blocks.
|
|
|
|
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
|
|
|
sweepTx.TxIn[0].Sequence = LockTimeToSequence(false, 15)
|
|
|
|
return CommitSpendAnchorAnyone(anchorScript)
|
|
|
|
}),
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, testCase := range testCases {
|
|
|
|
sweepTx.TxIn[0].Witness = testCase.witness()
|
|
|
|
|
|
|
|
newEngine := func() (*txscript.Engine, error) {
|
|
|
|
return txscript.NewEngine(anchorPkScript,
|
|
|
|
sweepTx, 0, txscript.StandardVerifyFlags, nil,
|
|
|
|
nil, int64(anchorSize))
|
|
|
|
}
|
|
|
|
|
|
|
|
assertEngineExecution(t, i, testCase.valid, newEngine)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-02 23:20:48 +03:00
|
|
|
// TestSpecificationKeyDerivation implements the test vectors provided in
|
|
|
|
// BOLT-03, Appendix E.
|
|
|
|
func TestSpecificationKeyDerivation(t *testing.T) {
|
|
|
|
const (
|
|
|
|
baseSecretHex = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
|
|
|
|
perCommitmentSecretHex = "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100"
|
|
|
|
basePointHex = "036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2"
|
|
|
|
perCommitmentPointHex = "025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486"
|
|
|
|
)
|
|
|
|
|
|
|
|
baseSecret, err := privkeyFromHex(baseSecretHex)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Failed to parse serialized privkey: %v", err)
|
|
|
|
}
|
|
|
|
perCommitmentSecret, err := privkeyFromHex(perCommitmentSecretHex)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Failed to parse serialized privkey: %v", err)
|
|
|
|
}
|
|
|
|
basePoint, err := pubkeyFromHex(basePointHex)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Failed to parse serialized pubkey: %v", err)
|
|
|
|
}
|
|
|
|
perCommitmentPoint, err := pubkeyFromHex(perCommitmentPointHex)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Failed to parse serialized pubkey: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// name: derivation of key from basepoint and per_commitment_point
|
|
|
|
const expectedLocalKeyHex = "0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5"
|
|
|
|
actualLocalKey := TweakPubKey(basePoint, perCommitmentPoint)
|
|
|
|
actualLocalKeyHex := pubkeyToHex(actualLocalKey)
|
|
|
|
if actualLocalKeyHex != expectedLocalKeyHex {
|
|
|
|
t.Errorf("Incorrect derivation of local public key: "+
|
|
|
|
"expected %v, got %v", expectedLocalKeyHex, actualLocalKeyHex)
|
|
|
|
}
|
|
|
|
|
|
|
|
// name: derivation of secret key from basepoint secret and per_commitment_secret
|
|
|
|
const expectedLocalPrivKeyHex = "cbced912d3b21bf196a766651e436aff192362621ce317704ea2f75d87e7be0f"
|
|
|
|
tweak := SingleTweakBytes(perCommitmentPoint, basePoint)
|
|
|
|
actualLocalPrivKey := TweakPrivKey(baseSecret, tweak)
|
|
|
|
actualLocalPrivKeyHex := privkeyToHex(actualLocalPrivKey)
|
|
|
|
if actualLocalPrivKeyHex != expectedLocalPrivKeyHex {
|
|
|
|
t.Errorf("Incorrect derivation of local private key: "+
|
|
|
|
"expected %v, got %v, %v", expectedLocalPrivKeyHex,
|
|
|
|
actualLocalPrivKeyHex, hex.EncodeToString(tweak))
|
|
|
|
}
|
|
|
|
|
|
|
|
// name: derivation of revocation key from basepoint and per_commitment_point
|
|
|
|
const expectedRevocationKeyHex = "02916e326636d19c33f13e8c0c3a03dd157f332f3e99c317c141dd865eb01f8ff0"
|
|
|
|
actualRevocationKey := DeriveRevocationPubkey(basePoint, perCommitmentPoint)
|
|
|
|
actualRevocationKeyHex := pubkeyToHex(actualRevocationKey)
|
|
|
|
if actualRevocationKeyHex != expectedRevocationKeyHex {
|
|
|
|
t.Errorf("Incorrect derivation of revocation public key: "+
|
|
|
|
"expected %v, got %v", expectedRevocationKeyHex,
|
|
|
|
actualRevocationKeyHex)
|
|
|
|
}
|
|
|
|
|
|
|
|
// name: derivation of revocation secret from basepoint_secret and per_commitment_secret
|
|
|
|
const expectedRevocationPrivKeyHex = "d09ffff62ddb2297ab000cc85bcb4283fdeb6aa052affbc9dddcf33b61078110"
|
|
|
|
actualRevocationPrivKey := DeriveRevocationPrivKey(baseSecret,
|
|
|
|
perCommitmentSecret)
|
|
|
|
actualRevocationPrivKeyHex := privkeyToHex(actualRevocationPrivKey)
|
|
|
|
if actualRevocationPrivKeyHex != expectedRevocationPrivKeyHex {
|
|
|
|
t.Errorf("Incorrect derivation of revocation private key: "+
|
|
|
|
"expected %v, got %v", expectedRevocationPrivKeyHex,
|
|
|
|
actualRevocationPrivKeyHex)
|
|
|
|
}
|
|
|
|
}
|