@@ -67,14 +67,15 @@ object Helpers {
6767 private def extractShutdownScript (channelId : ByteVector32 , localFeatures : Features [InitFeature ], remoteFeatures : Features [InitFeature ], upfrontShutdownScript_opt : Option [ByteVector ]): Either [ChannelException , Option [ByteVector ]] = {
6868 val canUseUpfrontShutdownScript = Features .canUseFeature(localFeatures, remoteFeatures, Features .UpfrontShutdownScript )
6969 val canUseAnySegwit = Features .canUseFeature(localFeatures, remoteFeatures, Features .ShutdownAnySegwit )
70- extractShutdownScript(channelId, canUseUpfrontShutdownScript, canUseAnySegwit, upfrontShutdownScript_opt)
70+ val canUseOpReturn = Features .canUseFeature(localFeatures, remoteFeatures, Features .SimpleClose )
71+ extractShutdownScript(channelId, canUseUpfrontShutdownScript, canUseAnySegwit, canUseOpReturn, upfrontShutdownScript_opt)
7172 }
7273
73- private def extractShutdownScript (channelId : ByteVector32 , hasOptionUpfrontShutdownScript : Boolean , allowAnySegwit : Boolean , upfrontShutdownScript_opt : Option [ByteVector ]): Either [ChannelException , Option [ByteVector ]] = {
74+ private def extractShutdownScript (channelId : ByteVector32 , hasOptionUpfrontShutdownScript : Boolean , allowAnySegwit : Boolean , allowOpReturn : Boolean , upfrontShutdownScript_opt : Option [ByteVector ]): Either [ChannelException , Option [ByteVector ]] = {
7475 (hasOptionUpfrontShutdownScript, upfrontShutdownScript_opt) match {
7576 case (true , None ) => Left (MissingUpfrontShutdownScript (channelId))
7677 case (true , Some (script)) if script.isEmpty => Right (None ) // but the provided script can be empty
77- case (true , Some (script)) if ! Closing .MutualClose .isValidFinalScriptPubkey(script, allowAnySegwit) => Left (InvalidFinalScript (channelId))
78+ case (true , Some (script)) if ! Closing .MutualClose .isValidFinalScriptPubkey(script, allowAnySegwit, allowOpReturn ) => Left (InvalidFinalScript (channelId))
7879 case (true , Some (script)) => Right (Some (script))
7980 case (false , Some (_)) => Right (None ) // they provided a script but the feature is not active, we just ignore it
8081 case _ => Right (None )
@@ -616,13 +617,14 @@ object Helpers {
616617
617618 object MutualClose {
618619
619- def isValidFinalScriptPubkey (scriptPubKey : ByteVector , allowAnySegwit : Boolean ): Boolean = {
620+ def isValidFinalScriptPubkey (scriptPubKey : ByteVector , allowAnySegwit : Boolean , allowOpReturn : Boolean ): Boolean = {
620621 Try (Script .parse(scriptPubKey)) match {
621622 case Success (OP_DUP :: OP_HASH160 :: OP_PUSHDATA (pubkeyHash, _) :: OP_EQUALVERIFY :: OP_CHECKSIG :: Nil ) if pubkeyHash.size == 20 => true
622623 case Success (OP_HASH160 :: OP_PUSHDATA (scriptHash, _) :: OP_EQUAL :: Nil ) if scriptHash.size == 20 => true
623624 case Success (OP_0 :: OP_PUSHDATA (pubkeyHash, _) :: Nil ) if pubkeyHash.size == 20 => true
624625 case Success (OP_0 :: OP_PUSHDATA (scriptHash, _) :: Nil ) if scriptHash.size == 32 => true
625626 case Success ((OP_1 | OP_2 | OP_3 | OP_4 | OP_5 | OP_6 | OP_7 | OP_8 | OP_9 | OP_10 | OP_11 | OP_12 | OP_13 | OP_14 | OP_15 | OP_16 ) :: OP_PUSHDATA (program, _) :: Nil ) if allowAnySegwit && 2 <= program.length && program.length <= 40 => true
627+ case Success (OP_RETURN :: _) if allowOpReturn => true
626628 case _ => false
627629 }
628630 }
@@ -661,8 +663,8 @@ object Helpers {
661663
662664 def makeClosingTx (keyManager : ChannelKeyManager , commitment : FullCommitment , localScriptPubkey : ByteVector , remoteScriptPubkey : ByteVector , closingFees : ClosingFees )(implicit log : LoggingAdapter ): (ClosingTx , ClosingSigned ) = {
663665 val allowAnySegwit = Features .canUseFeature(commitment.localParams.initFeatures, commitment.remoteParams.initFeatures, Features .ShutdownAnySegwit )
664- require(isValidFinalScriptPubkey(localScriptPubkey, allowAnySegwit), " invalid localScriptPubkey" )
665- require(isValidFinalScriptPubkey(remoteScriptPubkey, allowAnySegwit), " invalid remoteScriptPubkey" )
666+ require(isValidFinalScriptPubkey(localScriptPubkey, allowAnySegwit, allowOpReturn = false ), " invalid localScriptPubkey" )
667+ require(isValidFinalScriptPubkey(remoteScriptPubkey, allowAnySegwit, allowOpReturn = false ), " invalid remoteScriptPubkey" )
666668 log.debug(" making closing tx with closing fee={} and commitments:\n {}" , closingFees.preferred, commitment.specs2String)
667669 val dustLimit = commitment.localParams.dustLimit.max(commitment.remoteParams.dustLimit)
668670 val closingTx = Transactions .makeClosingTx(commitment.commitInput, localScriptPubkey, remoteScriptPubkey, commitment.localParams.isInitiator, dustLimit, closingFees.preferred, commitment.localCommit.spec)
@@ -692,16 +694,7 @@ object Helpers {
692694 * The various dust limits are detailed in https://github.com/lightningnetwork/lightning-rfc/blob/master/03-transactions.md#dust-limits
693695 */
694696 def checkClosingDustAmounts (closingTx : ClosingTx ): Boolean = {
695- closingTx.tx.txOut.forall(txOut => {
696- Try (Script .parse(txOut.publicKeyScript)) match {
697- case Success (OP_DUP :: OP_HASH160 :: OP_PUSHDATA (pubkeyHash, _) :: OP_EQUALVERIFY :: OP_CHECKSIG :: Nil ) if pubkeyHash.size == 20 => txOut.amount >= 546 .sat
698- case Success (OP_HASH160 :: OP_PUSHDATA (scriptHash, _) :: OP_EQUAL :: Nil ) if scriptHash.size == 20 => txOut.amount >= 540 .sat
699- case Success (OP_0 :: OP_PUSHDATA (pubkeyHash, _) :: Nil ) if pubkeyHash.size == 20 => txOut.amount >= 294 .sat
700- case Success (OP_0 :: OP_PUSHDATA (scriptHash, _) :: Nil ) if scriptHash.size == 32 => txOut.amount >= 330 .sat
701- case Success ((OP_1 | OP_2 | OP_3 | OP_4 | OP_5 | OP_6 | OP_7 | OP_8 | OP_9 | OP_10 | OP_11 | OP_12 | OP_13 | OP_14 | OP_15 | OP_16 ) :: OP_PUSHDATA (program, _) :: Nil ) if 2 <= program.length && program.length <= 40 => txOut.amount >= 354 .sat
702- case _ => txOut.amount >= 546 .sat
703- }
704- })
697+ closingTx.tx.txOut.forall(txOut => txOut.amount >= Transactions .dustLimit(txOut.publicKeyScript))
705698 }
706699 }
707700
0 commit comments