lnwallet: coalesce different supported output scripts into single method

This commit is contained in:
Wilmer Paulino 2021-07-14 17:06:13 -07:00 committed by Olaoluwa Osuntokun
parent 652f841738
commit 01e9bb2bff
No known key found for this signature in database
GPG Key ID: 3BBD59E99B280306
4 changed files with 88 additions and 70 deletions

View File

@ -372,19 +372,14 @@ func (c *chainWatcher) handleUnknownLocalState(
// Next, we'll derive our script that includes the revocation base for
// the remote party allowing them to claim this output before the CSV
// delay if we breach.
localScript, err := input.CommitScriptToSelf(
uint32(c.cfg.chanState.LocalChanCfg.CsvDelay),
localScript, err := lnwallet.CommitScriptToSelf(
commitKeyRing.ToLocalKey, commitKeyRing.RevocationKey,
uint32(c.cfg.chanState.LocalChanCfg.CsvDelay),
)
if err != nil {
return false, err
}
localPkScript, err := input.WitnessScriptHash(localScript)
if err != nil {
return false, err
}
// With all our scripts assembled, we'll examine the outputs of the
// commitment transaction to determine if this is a local force close
// or not.
@ -393,7 +388,7 @@ func (c *chainWatcher) handleUnknownLocalState(
pkScript := output.PkScript
switch {
case bytes.Equal(localPkScript, pkScript):
case bytes.Equal(localScript.PkScript, pkScript):
ourCommit = true
case bytes.Equal(remoteScript.PkScript, pkScript):

View File

@ -2315,16 +2315,12 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
// number so we can have the proper witness script to sign and include
// within the final witness.
theirDelay := uint32(chanState.RemoteChanCfg.CsvDelay)
theirPkScript, err := input.CommitScriptToSelf(
theirDelay, keyRing.ToLocalKey, keyRing.RevocationKey,
theirScript, err := CommitScriptToSelf(
keyRing.ToLocalKey, keyRing.RevocationKey, theirDelay,
)
if err != nil {
return nil, err
}
theirWitnessHash, err := input.WitnessScriptHash(theirPkScript)
if err != nil {
return nil, err
}
// Since it is the remote breach we are reconstructing, the output going
// to us will be a to-remote script with our local params.
@ -2347,7 +2343,7 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
switch {
case bytes.Equal(txOut.PkScript, ourScript.PkScript):
ourOutpoint.Index = uint32(i)
case bytes.Equal(txOut.PkScript, theirWitnessHash):
case bytes.Equal(txOut.PkScript, theirScript.PkScript):
theirOutpoint.Index = uint32(i)
}
}
@ -2385,9 +2381,9 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
theirSignDesc = &input.SignDescriptor{
KeyDesc: chanState.LocalChanCfg.RevocationBasePoint,
DoubleTweak: commitmentSecret,
WitnessScript: theirPkScript,
WitnessScript: theirScript.WitnessScript,
Output: &wire.TxOut{
PkScript: theirWitnessHash,
PkScript: theirScript.PkScript,
Value: int64(theirAmt),
},
HashType: txscript.SigHashAll,
@ -2413,7 +2409,7 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
// as we'll need it if we're revoking an HTLC output on the
// remote commitment transaction, and *they* go to the second
// level.
secondLevelWitnessScript, err := input.SecondLevelHtlcScript(
secondLevelScript, err := SecondLevelHtlcScript(
keyRing.RevocationKey, keyRing.ToLocalKey, theirDelay,
)
if err != nil {
@ -2448,7 +2444,7 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
Hash: commitHash,
Index: uint32(htlc.OutputIndex),
},
SecondLevelWitnessScript: secondLevelWitnessScript,
SecondLevelWitnessScript: secondLevelScript.WitnessScript,
IsIncoming: htlc.Incoming,
})
}
@ -5904,16 +5900,12 @@ func newOutgoingHtlcResolution(signer input.Signer,
// Finally, we'll generate the script output that the timeout
// transaction creates so we can generate the signDesc required to
// complete the claim process after a delay period.
htlcSweepScript, err := input.SecondLevelHtlcScript(
htlcSweepScript, err := SecondLevelHtlcScript(
keyRing.RevocationKey, keyRing.ToLocalKey, csvDelay,
)
if err != nil {
return nil, err
}
htlcSweepScriptHash, err := input.WitnessScriptHash(htlcSweepScript)
if err != nil {
return nil, err
}
localDelayTweak := input.SingleTweakBytes(
keyRing.CommitPoint, localChanCfg.DelayBasePoint.PubKey,
@ -5930,9 +5922,9 @@ func newOutgoingHtlcResolution(signer input.Signer,
SweepSignDesc: input.SignDescriptor{
KeyDesc: localChanCfg.DelayBasePoint,
SingleTweak: localDelayTweak,
WitnessScript: htlcSweepScript,
WitnessScript: htlcSweepScript.WitnessScript,
Output: &wire.TxOut{
PkScript: htlcSweepScriptHash,
PkScript: htlcSweepScript.PkScript,
Value: int64(secondLevelOutputAmt),
},
HashType: txscript.SigHashAll,
@ -6043,16 +6035,12 @@ func newIncomingHtlcResolution(signer input.Signer,
// Finally, we'll generate the script that the second-level transaction
// creates so we can generate the proper signDesc to sweep it after the
// CSV delay has passed.
htlcSweepScript, err := input.SecondLevelHtlcScript(
htlcSweepScript, err := SecondLevelHtlcScript(
keyRing.RevocationKey, keyRing.ToLocalKey, csvDelay,
)
if err != nil {
return nil, err
}
htlcSweepScriptHash, err := input.WitnessScriptHash(htlcSweepScript)
if err != nil {
return nil, err
}
localDelayTweak := input.SingleTweakBytes(
keyRing.CommitPoint, localChanCfg.DelayBasePoint.PubKey,
@ -6068,9 +6056,9 @@ func newIncomingHtlcResolution(signer input.Signer,
SweepSignDesc: input.SignDescriptor{
KeyDesc: localChanCfg.DelayBasePoint,
SingleTweak: localDelayTweak,
WitnessScript: htlcSweepScript,
WitnessScript: htlcSweepScript.WitnessScript,
Output: &wire.TxOut{
PkScript: htlcSweepScriptHash,
PkScript: htlcSweepScript.PkScript,
Value: int64(secondLevelOutputAmt),
},
HashType: txscript.SigHashAll,
@ -6293,16 +6281,12 @@ func NewLocalForceCloseSummary(chanState *channeldb.OpenChannel,
&chanState.LocalChanCfg, &chanState.RemoteChanCfg,
)
selfScript, err := input.CommitScriptToSelf(
csvTimeout, keyRing.ToLocalKey, keyRing.RevocationKey,
toLocalScript, err := CommitScriptToSelf(
keyRing.ToLocalKey, keyRing.RevocationKey, csvTimeout,
)
if err != nil {
return nil, err
}
payToUsScriptHash, err := input.WitnessScriptHash(selfScript)
if err != nil {
return nil, err
}
// Locate the output index of the delayed commitment output back to us.
// We'll return the details of this output to the caller so they can
@ -6312,7 +6296,7 @@ func NewLocalForceCloseSummary(chanState *channeldb.OpenChannel,
delayOut *wire.TxOut
)
for i, txOut := range commitTx.TxOut {
if !bytes.Equal(payToUsScriptHash, txOut.PkScript) {
if !bytes.Equal(toLocalScript.PkScript, txOut.PkScript) {
continue
}
@ -6338,7 +6322,7 @@ func NewLocalForceCloseSummary(chanState *channeldb.OpenChannel,
SelfOutputSignDesc: input.SignDescriptor{
KeyDesc: chanState.LocalChanCfg.DelayBasePoint,
SingleTweak: keyRing.LocalCommitKeyTweak,
WitnessScript: selfScript,
WitnessScript: toLocalScript.WitnessScript,
Output: &wire.TxOut{
PkScript: delayOut.PkScript,
Value: localBalance,

View File

@ -190,10 +190,34 @@ type ScriptInfo struct {
WitnessScript []byte
}
// CommitScriptToRemote creates the script that will pay to the non-owner of
// the commitment transaction, adding a delay to the script based on the
// channel type. The second return value is the CSV deleay of the output
// script, what must be satisfied in order to spend the output.
// CommitScriptToSelf constructs the public key script for the output on the
// commitment transaction paying to the "owner" of said commitment transaction.
// If the other party learns of the preimage to the revocation hash, then they
// can claim all the settled funds in the channel, plus the unsettled funds.
func CommitScriptToSelf(selfKey, revokeKey *btcec.PublicKey, csvDelay uint32) (
*ScriptInfo, error) {
toLocalRedeemScript, err := input.CommitScriptToSelf(
csvDelay, selfKey, revokeKey,
)
if err != nil {
return nil, err
}
toLocalScriptHash, err := input.WitnessScriptHash(toLocalRedeemScript)
if err != nil {
return nil, err
}
return &ScriptInfo{
PkScript: toLocalScriptHash,
WitnessScript: toLocalRedeemScript,
}, nil
}
// CommitScriptToRemote derives the appropriate to_remote script based on the
// channel's commitment type. The second return value is the CSV delay of the
// output script, what must be satisfied in order to spend the output.
func CommitScriptToRemote(chanType channeldb.ChannelType,
key *btcec.PublicKey) (*ScriptInfo, uint32, error) {
@ -268,6 +292,32 @@ func HtlcSecondLevelInputSequence(chanType channeldb.ChannelType) uint32 {
return 0
}
// SecondLevelHtlcScript derives the appropriate second level HTLC script based
// on the channel's commitment type. It is the uniform script that's used as the
// output for the second-level HTLC transactions. The second level transaction
// act as a sort of covenant, ensuring that a 2-of-2 multi-sig output can only
// be spent in a particular way, and to a particular output.
func SecondLevelHtlcScript(revocationKey, delayKey *btcec.PublicKey,
csvDelay uint32) (*ScriptInfo, error) {
witnessScript, err := input.SecondLevelHtlcScript(
revocationKey, delayKey, csvDelay,
)
if err != nil {
return nil, err
}
pkScript, err := input.WitnessScriptHash(witnessScript)
if err != nil {
return nil, err
}
return &ScriptInfo{
PkScript: pkScript,
WitnessScript: witnessScript,
}, nil
}
// CommitWeight returns the base commitment weight before adding HTLCs.
func CommitWeight(chanType channeldb.ChannelType) int64 {
// If this commitment has anchors, it will be slightly heavier.
@ -622,15 +672,9 @@ func CreateCommitTx(chanType channeldb.ChannelType,
// output after a relative block delay, or the remote node can claim
// the funds with the revocation key if we broadcast a revoked
// commitment transaction.
toLocalRedeemScript, err := input.CommitScriptToSelf(
uint32(localChanCfg.CsvDelay), keyRing.ToLocalKey,
keyRing.RevocationKey,
)
if err != nil {
return nil, err
}
toLocalScriptHash, err := input.WitnessScriptHash(
toLocalRedeemScript,
toLocalScript, err := CommitScriptToSelf(
keyRing.ToLocalKey, keyRing.RevocationKey,
uint32(localChanCfg.CsvDelay),
)
if err != nil {
return nil, err
@ -654,7 +698,7 @@ func CreateCommitTx(chanType channeldb.ChannelType,
localOutput := amountToLocal >= localChanCfg.DustLimit
if localOutput {
commitTx.AddTxOut(&wire.TxOut{
PkScript: toLocalScriptHash,
PkScript: toLocalScript.PkScript,
Value: int64(amountToLocal),
})
}

View File

@ -8,7 +8,6 @@ import (
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/input"
)
const (
@ -65,12 +64,9 @@ func CreateHtlcSuccessTx(chanType channeldb.ChannelType,
// Next, we'll generate the script used as the output for all second
// level HTLC which forces a covenant w.r.t what can be done with all
// HTLC outputs.
witnessScript, err := input.SecondLevelHtlcScript(revocationKey, delayKey,
csvDelay)
if err != nil {
return nil, err
}
pkScript, err := input.WitnessScriptHash(witnessScript)
script, err := SecondLevelHtlcScript(
revocationKey, delayKey, csvDelay,
)
if err != nil {
return nil, err
}
@ -79,7 +75,7 @@ func CreateHtlcSuccessTx(chanType channeldb.ChannelType,
// required fees), paying to the timeout script.
successTx.AddTxOut(&wire.TxOut{
Value: int64(htlcAmt),
PkScript: pkScript,
PkScript: script.PkScript,
})
return successTx, nil
@ -117,6 +113,8 @@ func CreateHtlcTimeoutTx(chanType channeldb.ChannelType,
// sequence number based on the channel type.
txin := &wire.TxIn{
PreviousOutPoint: htlcOutput,
SignatureScript: []byte{},
Witness: [][]byte{},
Sequence: HtlcSecondLevelInputSequence(chanType),
}
timeoutTx.AddTxIn(txin)
@ -124,12 +122,9 @@ func CreateHtlcTimeoutTx(chanType channeldb.ChannelType,
// Next, we'll generate the script used as the output for all second
// level HTLC which forces a covenant w.r.t what can be done with all
// HTLC outputs.
witnessScript, err := input.SecondLevelHtlcScript(revocationKey, delayKey,
csvDelay)
if err != nil {
return nil, err
}
pkScript, err := input.WitnessScriptHash(witnessScript)
script, err := SecondLevelHtlcScript(
revocationKey, delayKey, csvDelay,
)
if err != nil {
return nil, err
}
@ -138,7 +133,7 @@ func CreateHtlcTimeoutTx(chanType channeldb.ChannelType,
// required fees), paying to the regular second level HTLC script.
timeoutTx.AddTxOut(&wire.TxOut{
Value: int64(htlcAmt),
PkScript: pkScript,
PkScript: script.PkScript,
})
return timeoutTx, nil