| 134 | } |
| 135 | |
| 136 | static RPCHelpMan createmultisig() |
| 137 | { |
| 138 | return RPCHelpMan{"createmultisig", |
| 139 | "\nCreates a multi-signature address with n signature of m keys required.\n" |
| 140 | "It returns a json object with the address and redeemScript.\n", |
| 141 | { |
| 142 | {"nrequired", RPCArg::Type::NUM, RPCArg::Optional::NO, "The number of required signatures out of the n keys."}, |
| 143 | {"keys", RPCArg::Type::ARR, RPCArg::Optional::NO, "The hex-encoded public keys.", |
| 144 | { |
| 145 | {"key", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "The hex-encoded public key"}, |
| 146 | }}, |
| 147 | {"address_type", RPCArg::Type::STR, RPCArg::Default{"legacy"}, "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."}, |
| 148 | }, |
| 149 | RPCResult{ |
| 150 | RPCResult::Type::OBJ, "", "", |
| 151 | { |
| 152 | {RPCResult::Type::STR, "address", "The value of the new multisig address."}, |
| 153 | {RPCResult::Type::STR_HEX, "redeemScript", "The string value of the hex-encoded redemption script."}, |
| 154 | {RPCResult::Type::STR, "descriptor", "The descriptor for this multisig"}, |
| 155 | {RPCResult::Type::ARR, "warnings", /* optional */ true, "Any warnings resulting from the creation of this multisig", |
| 156 | { |
| 157 | {RPCResult::Type::STR, "", ""}, |
| 158 | }}, |
| 159 | } |
| 160 | }, |
| 161 | RPCExamples{ |
| 162 | "\nCreate a multisig address from 2 public keys\n" |
| 163 | + HelpExampleCli("createmultisig", "2 \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"") + |
| 164 | "\nAs a JSON-RPC call\n" |
| 165 | + HelpExampleRpc("createmultisig", "2, [\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\",\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\"]") |
| 166 | }, |
| 167 | [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue |
| 168 | { |
| 169 | int required = request.params[0].get_int(); |
| 170 | |
| 171 | // Get the public keys |
| 172 | const UniValue& keys = request.params[1].get_array(); |
| 173 | std::vector<CPubKey> pubkeys; |
| 174 | for (unsigned int i = 0; i < keys.size(); ++i) { |
| 175 | if (IsHex(keys[i].get_str()) && (keys[i].get_str().length() == 66 || keys[i].get_str().length() == 130)) { |
| 176 | pubkeys.push_back(HexToPubKey(keys[i].get_str())); |
| 177 | } else { |
| 178 | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid public key: %s\n.", keys[i].get_str())); |
| 179 | } |
| 180 | } |
| 181 | |
| 182 | // Get the output type |
| 183 | OutputType output_type = OutputType::LEGACY; |
| 184 | if (!request.params[2].isNull()) { |
| 185 | std::optional<OutputType> parsed = ParseOutputType(request.params[2].get_str()); |
| 186 | if (!parsed) { |
| 187 | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[2].get_str())); |
| 188 | } else if (parsed.value() == OutputType::BECH32M) { |
| 189 | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "createmultisig cannot create bech32m multisig addresses"); |
| 190 | } |
| 191 | output_type = parsed.value(); |
| 192 | } |
| 193 |
nothing calls this directly
no test coverage detected