lnwallet+funding: sanitize upfront_shutdown_script

Otherwise, we would get non-standard txn's and fail to broadcast
them when cooperatively closing a channel. This wouldn't affect
funds security as no HTLCs would be active to steal. This is just
a safety measure as we should only generate standard txn's.
This commit is contained in:
eugene committed 2021-06-11 10:46:21 -04:00
1 parent 42099ef5e1
commit 6d04f11f94
2 files changed
+199

No files matched your search

+45
View File
@@ -12,6 +12,7 @@ import (
"github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
@@ -1255,6 +1256,16 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
pendingReservation.Lock()
defer pendingReservation.Unlock()
// If UpfrontShutdownScript is set, validate that it is a valid script.
shutdown := req.contribution.UpfrontShutdown
if len(shutdown) > 0 {
// Validate the shutdown script.
if !validateUpfrontShutdown(shutdown, &l.Cfg.NetParams) {
req.err <- fmt.Errorf("invalid shutdown script")
return
}
}
// Some temporary variables to cut down on the resolution verbosity.
pendingReservation.theirContribution = req.contribution
theirContribution := req.contribution
@@ -1561,6 +1572,17 @@ func (l *LightningWallet) handleSingleContribution(req *addSingleContributionMsg
// TODO(roasbeef): verify sanity of remote party's parameters, fail if
// disagree
// Validate that the remote's UpfrontShutdownScript is a valid script
// if it's set.
shutdown := req.contribution.UpfrontShutdown
if len(shutdown) > 0 {
// Validate the shutdown script.
if !validateUpfrontShutdown(shutdown, &l.Cfg.NetParams) {
req.err <- fmt.Errorf("invalid shutdown script")
return
}
}
// Simply record the counterparty's contribution into the pending
// reservation data as they'll be solely funding the channel entirely.
pendingReservation.theirContribution = req.contribution
@@ -2132,3 +2154,26 @@ func (s *shimKeyRing) DeriveNextKey(keyFam keychain.KeyFamily) (keychain.KeyDesc
return *fundingKeys.LocalKey, nil
}
// validateUpfrontShutdown checks whether the provided upfront_shutdown_script
// is of a valid type that we accept.
func validateUpfrontShutdown(shutdown lnwire.DeliveryAddress,
params *chaincfg.Params) bool {
// We don't need to worry about a large UpfrontShutdownScript since it
// was already checked in lnwire when decoding from the wire.
scriptClass, _, _, _ := txscript.ExtractPkScriptAddrs(shutdown, params)
switch scriptClass {
case txscript.PubKeyHashTy,
txscript.WitnessV0PubKeyHashTy,
txscript.ScriptHashTy,
txscript.WitnessV0ScriptHashTy:
// The above four types are permitted according to BOLT#02.
// Everything else is disallowed.
return true
default:
return false
}
}