Repository: bitcoin/bitcoin
File: src/rpc/output_script.cpp (C++)

Code before:
            }
        },
        RPCExamples{
            "\nCreate a multisig address from 2 public keys\n"
            + HelpExampleCli("createmultisig", "2 \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"") +
            "\nAs a JSON-RPC call\n"
            + HelpExampleRpc("createmultisig", "2, [\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\",\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\"]")
                },
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
        {
            int required = request.params[0].getInt<int>();

            // Get the public keys
            const UniValue& keys = request.params[1].get_array();
            std::vector<CPubKey> pubkeys;
            pubkeys.reserve(keys.size());
            for (unsigned int i = 0; i < keys.size(); ++i) {
                pubkeys.push_back(HexToPubKey(keys[i].get_str()));
            }

            // Get the output type
            OutputType output_type = OutputType::LEGACY;
            if (!request.params[2].isNull()) {
                std::optional<OutputType> parsed = ParseOutputType(request.params[2].get_str());
                if (!parsed) {
                    throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[2].get_str()));
                } else if (parsed.value() == OutputType::BECH32M) {
                    throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "createmultisig cannot create bech32m multisig addresses");
                }
                output_type = parsed.value();
            }

            FlatSigningProvider keystore;
            CScript inner;
            const CTxDestination dest = AddAndGetMultisigDestination(required, pubkeys, output_type, keystore, inner);

            // Make the descriptor
            std::unique_ptr<Descriptor> descriptor = InferDescriptor(GetScriptForDestination(dest), keystore);

            UniValue result(UniValue::VOBJ);
            result.pushKV("address", EncodeDestination(dest));
            result.pushKV("redeemScript", HexStr(inner));
            result.pushKV("descriptor", descriptor->ToString());

            UniValue warnings(UniValue::VARR);
            if (descriptor->GetOutputType() != output_type) {
                // Only warns if the user has explicitly chosen an address type we cannot generate
                warnings.push_back("Unable to make chosen address type, please ensure no uncompressed public keys are present.");
            }
            PushWarnings(warnings, result);


Review comment (suggestion):
nit (for safety & consistency):
```suggestion
                throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, tfm::format"Unknown address type '%s'", address_type));
```

Already done in other places like:

https://github.com/bitcoin/bitcoin/blob/b49a4f17aba76d2f2d7f1109d7e68b02303947bf/src/rpc/node.cpp#L193

Code after:
                }},
            }
        },
        RPCExamples{
            "\nCreate a multisig address from 2 public keys\n"
            + HelpExampleCli("createmultisig", "2 \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"") +
            "\nAs a JSON-RPC call\n"
            + HelpExampleRpc("createmultisig", "2, [\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\",\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\"]")
                },
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
        {
            int required = request.params[0].getInt<int>();

            // Get the public keys
            const UniValue& keys = request.params[1].get_array();
            std::vector<CPubKey> pubkeys;
            pubkeys.reserve(keys.size());
            for (unsigned int i = 0; i < keys.size(); ++i) {
                pubkeys.push_back(HexToPubKey(keys[i].get_str()));
            }

            // Get the output type
            auto address_type{self.Arg<std::string_view>("address_type")};
            auto output_type{ParseOutputType(address_type)};
            if (!output_type) {
                throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, tfm::format("Unknown address type '%s'", address_type));
            } else if (output_type.value() == OutputType::BECH32M) {
                throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "createmultisig cannot create bech32m multisig addresses");
            }

            FlatSigningProvider keystore;
            CScript inner;
            const CTxDestination dest = AddAndGetMultisigDestination(required, pubkeys, output_type.value(), keystore, inner);

            // Make the descriptor
            std::unique_ptr<Descriptor> descriptor = InferDescriptor(GetScriptForDestination(dest), keystore);

            UniValue result(UniValue::VOBJ);
            result.pushKV("address", EncodeDestination(dest));
            result.pushKV("redeemScript", HexStr(inner));
            result.pushKV("descriptor", descriptor->ToString());

            UniValue warnings(UniValue::VARR);
            if (descriptor->GetOutputType() != output_type.value()) {
                // Only warns if the user has explicitly chosen an address type we cannot generate
                warnings.push_back("Unable to make chosen address type, please ensure no uncompressed public keys are present.");
            }
            PushWarnings(warnings, result);

            return result;
        },