@@ -552,8 +552,10 @@ static RPCHelpMan decodescript()
552552 {RPCResult::Type::STR, " asm" , " Script public key" },
553553 {RPCResult::Type::STR, " type" , " The output type (e.g. " + GetAllOutputTypes () + " )" },
554554 {RPCResult::Type::STR, " address" , /* optional */ true , " The Bitcoin address (only if a well-defined address exists)" },
555- {RPCResult::Type::STR, " p2sh" , /* optional */ true , " address of P2SH script wrapping this redeem script (not returned if the script is already a P2SH)" },
556- {RPCResult::Type::OBJ, " segwit" , /* optional */ true , " Result of a witness script public key wrapping this redeem script (not returned if the script is a P2SH or witness)" ,
555+ {RPCResult::Type::STR, " p2sh" , /* optional=*/ true ,
556+ " address of P2SH script wrapping this redeem script (not returned for types that should not be wrapped)" },
557+ {RPCResult::Type::OBJ, " segwit" , /* optional=*/ true ,
558+ " Result of a witness script public key wrapping this redeem script (not returned for types that should not be wrapped)" ,
557559 {
558560 {RPCResult::Type::STR, " asm" , " String representation of the script public key" },
559561 {RPCResult::Type::STR_HEX, " hex" , " Hex string of the script public key" },
@@ -584,22 +586,68 @@ static RPCHelpMan decodescript()
584586 std::vector<std::vector<unsigned char >> solutions_data;
585587 const TxoutType which_type{Solver (script, solutions_data)};
586588
587- if (which_type != TxoutType::SCRIPTHASH) {
588- // P2SH cannot be wrapped in a P2SH. If this script is already a P2SH,
589- // don't return the address for a P2SH of the P2SH.
589+ const bool can_wrap{[&] {
590+ switch (which_type) {
591+ case TxoutType::MULTISIG:
592+ case TxoutType::NONSTANDARD:
593+ case TxoutType::PUBKEY:
594+ case TxoutType::PUBKEYHASH:
595+ case TxoutType::WITNESS_V0_KEYHASH:
596+ case TxoutType::WITNESS_V0_SCRIPTHASH:
597+ // Can be wrapped if the checks below pass
598+ break ;
599+ case TxoutType::NULL_DATA:
600+ case TxoutType::SCRIPTHASH:
601+ case TxoutType::WITNESS_UNKNOWN:
602+ case TxoutType::WITNESS_V1_TAPROOT:
603+ // Should not be wrapped
604+ return false ;
605+ } // no default case, so the compiler can warn about missing cases
606+ if (!script.HasValidOps () || script.IsUnspendable ()) {
607+ return false ;
608+ }
609+ for (CScript::const_iterator it{script.begin ()}; it != script.end ();) {
610+ opcodetype op;
611+ CHECK_NONFATAL (script.GetOp (it, op));
612+ if (op == OP_CHECKSIGADD || IsOpSuccess (op)) {
613+ return false ;
614+ }
615+ }
616+ return true ;
617+ }()};
618+
619+ if (can_wrap) {
590620 r.pushKV (" p2sh" , EncodeDestination (ScriptHash (script)));
591621 // P2SH and witness programs cannot be wrapped in P2WSH, if this script
592622 // is a witness program, don't return addresses for a segwit programs.
593- if (which_type == TxoutType::PUBKEY || which_type == TxoutType::PUBKEYHASH || which_type == TxoutType::MULTISIG || which_type == TxoutType::NONSTANDARD) {
623+ const bool can_wrap_P2WSH{[&] {
624+ switch (which_type) {
625+ case TxoutType::MULTISIG:
626+ case TxoutType::PUBKEY:
594627 // Uncompressed pubkeys cannot be used with segwit checksigs.
595628 // If the script contains an uncompressed pubkey, skip encoding of a segwit program.
596- if ((which_type == TxoutType::PUBKEY) || (which_type == TxoutType::MULTISIG)) {
597629 for (const auto & solution : solutions_data) {
598630 if ((solution.size () != 1 ) && !CPubKey (solution).IsCompressed ()) {
599- return r ;
631+ return false ;
600632 }
601633 }
602- }
634+ return true ;
635+ case TxoutType::NONSTANDARD:
636+ case TxoutType::PUBKEYHASH:
637+ // Can be P2WSH wrapped
638+ return true ;
639+ case TxoutType::NULL_DATA:
640+ case TxoutType::SCRIPTHASH:
641+ case TxoutType::WITNESS_UNKNOWN:
642+ case TxoutType::WITNESS_V0_KEYHASH:
643+ case TxoutType::WITNESS_V0_SCRIPTHASH:
644+ case TxoutType::WITNESS_V1_TAPROOT:
645+ // Should not be wrapped
646+ return false ;
647+ } // no default case, so the compiler can warn about missing cases
648+ CHECK_NONFATAL (false );
649+ }()};
650+ if (can_wrap_P2WSH) {
603651 UniValue sr (UniValue::VOBJ);
604652 CScript segwitScr;
605653 if (which_type == TxoutType::PUBKEY) {
@@ -608,7 +656,6 @@ static RPCHelpMan decodescript()
608656 segwitScr = GetScriptForDestination (WitnessV0KeyHash (uint160{solutions_data[0 ]}));
609657 } else {
610658 // Scripts that are not fit for P2WPKH are encoded as P2WSH.
611- // Newer segwit program versions should be considered when then become available.
612659 segwitScr = GetScriptForDestination (WitnessV0ScriptHash (script));
613660 }
614661 ScriptPubKeyToUniv (segwitScr, sr, /* include_hex */ true );
0 commit comments