@@ -552,8 +552,10 @@ static RPCHelpMan decodescript()
552
552
{RPCResult::Type::STR, " asm" , " Script public key" },
553
553
{RPCResult::Type::STR, " type" , " The output type (e.g. " + GetAllOutputTypes () + " )" },
554
554
{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)" ,
557
559
{
558
560
{RPCResult::Type::STR, " asm" , " String representation of the script public key" },
559
561
{RPCResult::Type::STR_HEX, " hex" , " Hex string of the script public key" },
@@ -584,22 +586,68 @@ static RPCHelpMan decodescript()
584
586
std::vector<std::vector<unsigned char >> solutions_data;
585
587
const TxoutType which_type{Solver (script, solutions_data)};
586
588
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) {
590
620
r.pushKV (" p2sh" , EncodeDestination (ScriptHash (script)));
591
621
// P2SH and witness programs cannot be wrapped in P2WSH, if this script
592
622
// 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:
594
627
// Uncompressed pubkeys cannot be used with segwit checksigs.
595
628
// If the script contains an uncompressed pubkey, skip encoding of a segwit program.
596
- if ((which_type == TxoutType::PUBKEY) || (which_type == TxoutType::MULTISIG)) {
597
629
for (const auto & solution : solutions_data) {
598
630
if ((solution.size () != 1 ) && !CPubKey (solution).IsCompressed ()) {
599
- return r ;
631
+ return false ;
600
632
}
601
633
}
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) {
603
651
UniValue sr (UniValue::VOBJ);
604
652
CScript segwitScr;
605
653
if (which_type == TxoutType::PUBKEY) {
@@ -608,7 +656,6 @@ static RPCHelpMan decodescript()
608
656
segwitScr = GetScriptForDestination (WitnessV0KeyHash (uint160{solutions_data[0 ]}));
609
657
} else {
610
658
// Scripts that are not fit for P2WPKH are encoded as P2WSH.
611
- // Newer segwit program versions should be considered when then become available.
612
659
segwitScr = GetScriptForDestination (WitnessV0ScriptHash (script));
613
660
}
614
661
ScriptPubKeyToUniv (segwitScr, sr, /* include_hex */ true );
0 commit comments