| 87 | } |
| 88 | |
| 89 | static RPCMethod createmultisig() |
| 90 | { |
| 91 | return RPCMethod{ |
| 92 | "createmultisig", |
| 93 | "Creates a multi-signature address with n signatures of m keys required.\n" |
| 94 | "It returns a json object with the address and redeemScript.\n", |
| 95 | { |
| 96 | {"nrequired", RPCArg::Type::NUM, RPCArg::Optional::NO, "The number of required signatures out of the m keys."}, |
| 97 | {"keys", RPCArg::Type::ARR, RPCArg::Optional::NO, "The hex-encoded public keys.", |
| 98 | { |
| 99 | {"key", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "The hex-encoded public key"}, |
| 100 | }}, |
| 101 | {"address_type", RPCArg::Type::STR, RPCArg::Default{"legacy"}, "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."}, |
| 102 | }, |
| 103 | RPCResult{ |
| 104 | RPCResult::Type::OBJ, "", "", |
| 105 | { |
| 106 | {RPCResult::Type::STR, "address", "The value of the new multisig address."}, |
| 107 | {RPCResult::Type::STR_HEX, "redeemScript", "The string value of the hex-encoded redemption script."}, |
| 108 | {RPCResult::Type::STR, "descriptor", "The descriptor for this multisig"}, |
| 109 | {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Any warnings resulting from the creation of this multisig", |
| 110 | { |
| 111 | {RPCResult::Type::STR, "", ""}, |
| 112 | }}, |
| 113 | } |
| 114 | }, |
| 115 | RPCExamples{ |
| 116 | "\nCreate a multisig address from 2 public keys\n" |
| 117 | + HelpExampleCli("createmultisig", "2 \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"") + |
| 118 | "\nAs a JSON-RPC call\n" |
| 119 | + HelpExampleRpc("createmultisig", "2, [\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\",\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\"]") |
| 120 | }, |
| 121 | [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue |
| 122 | { |
| 123 | int required = request.params[0].getInt<int>(); |
| 124 | |
| 125 | // Get the public keys |
| 126 | const UniValue& keys = request.params[1].get_array(); |
| 127 | std::vector<CPubKey> pubkeys; |
| 128 | pubkeys.reserve(keys.size()); |
| 129 | for (unsigned int i = 0; i < keys.size(); ++i) { |
| 130 | pubkeys.push_back(HexToPubKey(keys[i].get_str())); |
| 131 | } |
| 132 | |
| 133 | // Get the output type |
| 134 | auto address_type{self.Arg<std::string_view>("address_type")}; |
| 135 | auto output_type{ParseOutputType(address_type)}; |
| 136 | if (!output_type) { |
| 137 | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, tfm::format("Unknown address type '%s'", address_type)); |
| 138 | } else if (output_type.value() == OutputType::BECH32M) { |
| 139 | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "createmultisig cannot create bech32m multisig addresses"); |
| 140 | } |
| 141 | |
| 142 | FlatSigningProvider keystore; |
| 143 | CScript inner; |
| 144 | const CTxDestination dest = AddAndGetMultisigDestination(required, pubkeys, output_type.value(), keystore, inner); |
| 145 | |
| 146 | // Make the descriptor |
nothing calls this directly
no test coverage detected