input+lnwallet: Add scripts for CSV delayed HTLC outputs
We also increase the witness size for these types to account for the 3 extra bytes. The size won't be correct in all cases, but it is just an upper bound in any case.
This commit is contained in:
parent
b25f2fa94b
commit
8c0deb81c2
@ -150,6 +150,9 @@ func Ripemd160H(d []byte) []byte {
|
|||||||
// * The receiver of the HTLC sweeping all the funds in the case that a
|
// * The receiver of the HTLC sweeping all the funds in the case that a
|
||||||
// revoked commitment transaction bearing this HTLC was broadcast.
|
// revoked commitment transaction bearing this HTLC was broadcast.
|
||||||
//
|
//
|
||||||
|
// If confirmedSpend=true, a 1 OP_CSV check will be added to the non-revocation
|
||||||
|
// cases, to allow sweeping only after confirmation.
|
||||||
|
//
|
||||||
// Possible Input Scripts:
|
// Possible Input Scripts:
|
||||||
// SENDR: <0> <sendr sig> <recvr sig> <0> (spend using HTLC timeout transaction)
|
// SENDR: <0> <sendr sig> <recvr sig> <0> (spend using HTLC timeout transaction)
|
||||||
// RECVR: <recvr sig> <preimage>
|
// RECVR: <recvr sig> <preimage>
|
||||||
@ -168,9 +171,11 @@ func Ripemd160H(d []byte) []byte {
|
|||||||
// OP_HASH160 <ripemd160(payment hash)> OP_EQUALVERIFY
|
// OP_HASH160 <ripemd160(payment hash)> OP_EQUALVERIFY
|
||||||
// OP_CHECKSIG
|
// OP_CHECKSIG
|
||||||
// OP_ENDIF
|
// OP_ENDIF
|
||||||
|
// [1 OP_CHECKSEQUENCEVERIFY OP_DROP] <- if allowing confirmed spend only.
|
||||||
// OP_ENDIF
|
// OP_ENDIF
|
||||||
func SenderHTLCScript(senderHtlcKey, receiverHtlcKey,
|
func SenderHTLCScript(senderHtlcKey, receiverHtlcKey,
|
||||||
revocationKey *btcec.PublicKey, paymentHash []byte) ([]byte, error) {
|
revocationKey *btcec.PublicKey, paymentHash []byte,
|
||||||
|
confirmedSpend bool) ([]byte, error) {
|
||||||
|
|
||||||
builder := txscript.NewScriptBuilder()
|
builder := txscript.NewScriptBuilder()
|
||||||
|
|
||||||
@ -243,6 +248,14 @@ func SenderHTLCScript(senderHtlcKey, receiverHtlcKey,
|
|||||||
// Close out the OP_IF statement above.
|
// Close out the OP_IF statement above.
|
||||||
builder.AddOp(txscript.OP_ENDIF)
|
builder.AddOp(txscript.OP_ENDIF)
|
||||||
|
|
||||||
|
// Add 1 block CSV delay if a confirmation is required for the
|
||||||
|
// non-revocation clauses.
|
||||||
|
if confirmedSpend {
|
||||||
|
builder.AddOp(txscript.OP_1)
|
||||||
|
builder.AddOp(txscript.OP_CHECKSEQUENCEVERIFY)
|
||||||
|
builder.AddOp(txscript.OP_DROP)
|
||||||
|
}
|
||||||
|
|
||||||
// Close out the OP_IF statement at the top of the script.
|
// Close out the OP_IF statement at the top of the script.
|
||||||
builder.AddOp(txscript.OP_ENDIF)
|
builder.AddOp(txscript.OP_ENDIF)
|
||||||
|
|
||||||
@ -362,6 +375,9 @@ func SenderHtlcSpendTimeout(receiverSig []byte, signer Signer,
|
|||||||
// * The sender of the HTLC sweeps the HTLC on-chain after the timeout period
|
// * The sender of the HTLC sweeps the HTLC on-chain after the timeout period
|
||||||
// of the HTLC has passed.
|
// of the HTLC has passed.
|
||||||
//
|
//
|
||||||
|
// If confirmedSpend=true, a 1 OP_CSV check will be added to the non-revocation
|
||||||
|
// cases, to allow sweeping only after confirmation.
|
||||||
|
//
|
||||||
// Possible Input Scripts:
|
// Possible Input Scripts:
|
||||||
// RECVR: <0> <sender sig> <recvr sig> <preimage> (spend using HTLC success transaction)
|
// RECVR: <0> <sender sig> <recvr sig> <preimage> (spend using HTLC success transaction)
|
||||||
// REVOK: <sig> <key>
|
// REVOK: <sig> <key>
|
||||||
@ -381,10 +397,11 @@ func SenderHtlcSpendTimeout(receiverSig []byte, signer Signer,
|
|||||||
// OP_DROP <cltv expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
|
// OP_DROP <cltv expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
|
||||||
// OP_CHECKSIG
|
// OP_CHECKSIG
|
||||||
// OP_ENDIF
|
// OP_ENDIF
|
||||||
|
// [1 OP_CHECKSEQUENCEVERIFY OP_DROP] <- if allowing confirmed spend only.
|
||||||
// OP_ENDIF
|
// OP_ENDIF
|
||||||
func ReceiverHTLCScript(cltvExpiry uint32, senderHtlcKey,
|
func ReceiverHTLCScript(cltvExpiry uint32, senderHtlcKey,
|
||||||
receiverHtlcKey, revocationKey *btcec.PublicKey,
|
receiverHtlcKey, revocationKey *btcec.PublicKey,
|
||||||
paymentHash []byte) ([]byte, error) {
|
paymentHash []byte, confirmedSpend bool) ([]byte, error) {
|
||||||
|
|
||||||
builder := txscript.NewScriptBuilder()
|
builder := txscript.NewScriptBuilder()
|
||||||
|
|
||||||
@ -467,6 +484,14 @@ func ReceiverHTLCScript(cltvExpiry uint32, senderHtlcKey,
|
|||||||
// Close out the inner if statement.
|
// Close out the inner if statement.
|
||||||
builder.AddOp(txscript.OP_ENDIF)
|
builder.AddOp(txscript.OP_ENDIF)
|
||||||
|
|
||||||
|
// Add 1 block CSV delay for non-revocation clauses if confirmation is
|
||||||
|
// required.
|
||||||
|
if confirmedSpend {
|
||||||
|
builder.AddOp(txscript.OP_1)
|
||||||
|
builder.AddOp(txscript.OP_CHECKSEQUENCEVERIFY)
|
||||||
|
builder.AddOp(txscript.OP_DROP)
|
||||||
|
}
|
||||||
|
|
||||||
// Close out the outer if statement.
|
// Close out the outer if statement.
|
||||||
builder.AddOp(txscript.OP_ENDIF)
|
builder.AddOp(txscript.OP_ENDIF)
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ func TestHTLCSenderSpendValidation(t *testing.T) {
|
|||||||
// counterpart.
|
// counterpart.
|
||||||
htlcWitnessScript, err = SenderHTLCScript(
|
htlcWitnessScript, err = SenderHTLCScript(
|
||||||
aliceLocalKey, bobLocalKey, revocationKey,
|
aliceLocalKey, bobLocalKey, revocationKey,
|
||||||
paymentHash[:],
|
paymentHash[:], false,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create htlc sender script: %v", err)
|
t.Fatalf("unable to create htlc sender script: %v", err)
|
||||||
@ -496,7 +496,7 @@ func TestHTLCReceiverSpendValidation(t *testing.T) {
|
|||||||
// counterpart.
|
// counterpart.
|
||||||
htlcWitnessScript, err = ReceiverHTLCScript(
|
htlcWitnessScript, err = ReceiverHTLCScript(
|
||||||
cltvTimeout, aliceLocalKey, bobLocalKey, revocationKey,
|
cltvTimeout, aliceLocalKey, bobLocalKey, revocationKey,
|
||||||
paymentHash[:],
|
paymentHash[:], false,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create htlc sender script: %v", err)
|
t.Fatalf("unable to create htlc sender script: %v", err)
|
||||||
|
@ -213,7 +213,7 @@ const (
|
|||||||
// - witness_script (to_local_script)
|
// - witness_script (to_local_script)
|
||||||
ToLocalPenaltyWitnessSize = 1 + 1 + 73 + 1 + 1 + ToLocalScriptSize
|
ToLocalPenaltyWitnessSize = 1 + 1 + 73 + 1 + 1 + ToLocalScriptSize
|
||||||
|
|
||||||
// AcceptedHtlcScriptSize 139 bytes
|
// AcceptedHtlcScriptSize 142 bytes
|
||||||
// - OP_DUP: 1 byte
|
// - OP_DUP: 1 byte
|
||||||
// - OP_HASH160: 1 byte
|
// - OP_HASH160: 1 byte
|
||||||
// - OP_DATA: 1 byte (RIPEMD160(SHA256(revocationkey)) length)
|
// - OP_DATA: 1 byte (RIPEMD160(SHA256(revocationkey)) length)
|
||||||
@ -247,11 +247,14 @@ const (
|
|||||||
// - OP_DROP: 1 byte
|
// - OP_DROP: 1 byte
|
||||||
// - OP_CHECKSIG: 1 byte
|
// - OP_CHECKSIG: 1 byte
|
||||||
// - OP_ENDIF: 1 byte
|
// - OP_ENDIF: 1 byte
|
||||||
|
// - OP_1: 1 byte // These 3 extra bytes are used for both confirmed and regular
|
||||||
|
// - OP_CSV: 1 byte // HTLC script types. The size won't be correct in all cases,
|
||||||
|
// - OP_DROP: 1 byte // but it is just an upper bound used for fee estimation in any case.
|
||||||
// - OP_ENDIF: 1 byte
|
// - OP_ENDIF: 1 byte
|
||||||
AcceptedHtlcScriptSize = 3*1 + 20 + 5*1 + 33 + 7*1 + 20 + 4*1 +
|
AcceptedHtlcScriptSize = 3*1 + 20 + 5*1 + 33 + 7*1 + 20 + 4*1 +
|
||||||
33 + 5*1 + 4 + 5*1
|
33 + 5*1 + 4 + 8*1
|
||||||
|
|
||||||
// AcceptedHtlcTimeoutWitnessSize 216
|
// AcceptedHtlcTimeoutWitnessSize 219
|
||||||
// - number_of_witness_elements: 1 byte
|
// - number_of_witness_elements: 1 byte
|
||||||
// - sender_sig_length: 1 byte
|
// - sender_sig_length: 1 byte
|
||||||
// - sender_sig: 73 bytes
|
// - sender_sig: 73 bytes
|
||||||
@ -260,7 +263,7 @@ const (
|
|||||||
// - witness_script: (accepted_htlc_script)
|
// - witness_script: (accepted_htlc_script)
|
||||||
AcceptedHtlcTimeoutWitnessSize = 1 + 1 + 73 + 1 + 1 + AcceptedHtlcScriptSize
|
AcceptedHtlcTimeoutWitnessSize = 1 + 1 + 73 + 1 + 1 + AcceptedHtlcScriptSize
|
||||||
|
|
||||||
// AcceptedHtlcPenaltyWitnessSize 249 bytes
|
// AcceptedHtlcPenaltyWitnessSize 252 bytes
|
||||||
// - number_of_witness_elements: 1 byte
|
// - number_of_witness_elements: 1 byte
|
||||||
// - revocation_sig_length: 1 byte
|
// - revocation_sig_length: 1 byte
|
||||||
// - revocation_sig: 73 bytes
|
// - revocation_sig: 73 bytes
|
||||||
@ -270,7 +273,7 @@ const (
|
|||||||
// - witness_script (accepted_htlc_script)
|
// - witness_script (accepted_htlc_script)
|
||||||
AcceptedHtlcPenaltyWitnessSize = 1 + 1 + 73 + 1 + 33 + 1 + AcceptedHtlcScriptSize
|
AcceptedHtlcPenaltyWitnessSize = 1 + 1 + 73 + 1 + 33 + 1 + AcceptedHtlcScriptSize
|
||||||
|
|
||||||
// OfferedHtlcScriptSize 133 bytes
|
// OfferedHtlcScriptSize 136 bytes
|
||||||
// - OP_DUP: 1 byte
|
// - OP_DUP: 1 byte
|
||||||
// - OP_HASH160: 1 byte
|
// - OP_HASH160: 1 byte
|
||||||
// - OP_DATA: 1 byte (RIPEMD160(SHA256(revocationkey)) length)
|
// - OP_DATA: 1 byte (RIPEMD160(SHA256(revocationkey)) length)
|
||||||
@ -301,10 +304,13 @@ const (
|
|||||||
// - OP_EQUALVERIFY: 1 byte
|
// - OP_EQUALVERIFY: 1 byte
|
||||||
// - OP_CHECKSIG: 1 byte
|
// - OP_CHECKSIG: 1 byte
|
||||||
// - OP_ENDIF: 1 byte
|
// - OP_ENDIF: 1 byte
|
||||||
|
// - OP_1: 1 byte
|
||||||
|
// - OP_CSV: 1 byte
|
||||||
|
// - OP_DROP: 1 byte
|
||||||
// - OP_ENDIF: 1 byte
|
// - OP_ENDIF: 1 byte
|
||||||
OfferedHtlcScriptSize = 3*1 + 20 + 5*1 + 33 + 10*1 + 33 + 5*1 + 20 + 4*1
|
OfferedHtlcScriptSize = 3*1 + 20 + 5*1 + 33 + 10*1 + 33 + 5*1 + 20 + 7*1
|
||||||
|
|
||||||
// OfferedHtlcSuccessWitnessSize 317 bytes
|
// OfferedHtlcSuccessWitnessSize 320 bytes
|
||||||
// - number_of_witness_elements: 1 byte
|
// - number_of_witness_elements: 1 byte
|
||||||
// - nil_length: 1 byte
|
// - nil_length: 1 byte
|
||||||
// - receiver_sig_length: 1 byte
|
// - receiver_sig_length: 1 byte
|
||||||
@ -317,7 +323,7 @@ const (
|
|||||||
// - witness_script (offered_htlc_script)
|
// - witness_script (offered_htlc_script)
|
||||||
OfferedHtlcSuccessWitnessSize = 1 + 1 + 1 + 73 + 1 + 73 + 1 + 32 + 1 + OfferedHtlcScriptSize
|
OfferedHtlcSuccessWitnessSize = 1 + 1 + 1 + 73 + 1 + 73 + 1 + 32 + 1 + OfferedHtlcScriptSize
|
||||||
|
|
||||||
// OfferedHtlcPenaltyWitnessSize 243 bytes
|
// OfferedHtlcPenaltyWitnessSize 246 bytes
|
||||||
// - number_of_witness_elements: 1 byte
|
// - number_of_witness_elements: 1 byte
|
||||||
// - revocation_sig_length: 1 byte
|
// - revocation_sig_length: 1 byte
|
||||||
// - revocation_sig: 73 bytes
|
// - revocation_sig: 73 bytes
|
||||||
|
@ -510,28 +510,28 @@ func genHtlcScript(chanType channeldb.ChannelType, isIncoming, ourCommit bool,
|
|||||||
case isIncoming && ourCommit:
|
case isIncoming && ourCommit:
|
||||||
witnessScript, err = input.ReceiverHTLCScript(timeout,
|
witnessScript, err = input.ReceiverHTLCScript(timeout,
|
||||||
keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey,
|
keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey,
|
||||||
keyRing.RevocationKey, rHash[:])
|
keyRing.RevocationKey, rHash[:], false)
|
||||||
|
|
||||||
// We're being paid via an HTLC by the remote party, and the HTLC is
|
// We're being paid via an HTLC by the remote party, and the HTLC is
|
||||||
// being added to their commitment transaction, so we use the sender's
|
// being added to their commitment transaction, so we use the sender's
|
||||||
// version of the HTLC script.
|
// version of the HTLC script.
|
||||||
case isIncoming && !ourCommit:
|
case isIncoming && !ourCommit:
|
||||||
witnessScript, err = input.SenderHTLCScript(keyRing.RemoteHtlcKey,
|
witnessScript, err = input.SenderHTLCScript(keyRing.RemoteHtlcKey,
|
||||||
keyRing.LocalHtlcKey, keyRing.RevocationKey, rHash[:])
|
keyRing.LocalHtlcKey, keyRing.RevocationKey, rHash[:], false)
|
||||||
|
|
||||||
// We're sending an HTLC which is being added to our commitment
|
// We're sending an HTLC which is being added to our commitment
|
||||||
// transaction. Therefore, we need to use the sender's version of the
|
// transaction. Therefore, we need to use the sender's version of the
|
||||||
// HTLC script.
|
// HTLC script.
|
||||||
case !isIncoming && ourCommit:
|
case !isIncoming && ourCommit:
|
||||||
witnessScript, err = input.SenderHTLCScript(keyRing.LocalHtlcKey,
|
witnessScript, err = input.SenderHTLCScript(keyRing.LocalHtlcKey,
|
||||||
keyRing.RemoteHtlcKey, keyRing.RevocationKey, rHash[:])
|
keyRing.RemoteHtlcKey, keyRing.RevocationKey, rHash[:], false)
|
||||||
|
|
||||||
// Finally, we're paying the remote party via an HTLC, which is being
|
// Finally, we're paying the remote party via an HTLC, which is being
|
||||||
// added to their commitment transaction. Therefore, we use the
|
// added to their commitment transaction. Therefore, we use the
|
||||||
// receiver's version of the HTLC script.
|
// receiver's version of the HTLC script.
|
||||||
case !isIncoming && !ourCommit:
|
case !isIncoming && !ourCommit:
|
||||||
witnessScript, err = input.ReceiverHTLCScript(timeout, keyRing.LocalHtlcKey,
|
witnessScript, err = input.ReceiverHTLCScript(timeout, keyRing.LocalHtlcKey,
|
||||||
keyRing.RemoteHtlcKey, keyRing.RevocationKey, rHash[:])
|
keyRing.RemoteHtlcKey, keyRing.RevocationKey, rHash[:], false)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@ -14,7 +14,7 @@ var (
|
|||||||
input.HtlcOfferedRemoteTimeout,
|
input.HtlcOfferedRemoteTimeout,
|
||||||
input.WitnessKeyHash,
|
input.WitnessKeyHash,
|
||||||
}
|
}
|
||||||
expectedWeight = int64(1459)
|
expectedWeight = int64(1462)
|
||||||
expectedSummary = "1 CommitmentTimeLock, 1 " +
|
expectedSummary = "1 CommitmentTimeLock, 1 " +
|
||||||
"HtlcAcceptedSuccessSecondLevel, 1 HtlcOfferedRemoteTimeout, " +
|
"HtlcAcceptedSuccessSecondLevel, 1 HtlcOfferedRemoteTimeout, " +
|
||||||
"1 WitnessKeyHash"
|
"1 WitnessKeyHash"
|
||||||
|
Loading…
Reference in New Issue
Block a user