output_script.cpp raw

   1  // Copyright (c) 2010 Satoshi Nakamoto
   2  // Copyright (c) 2009-present The Bitcoin Core developers
   3  // Distributed under the MIT software license, see the accompanying
   4  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   5  
   6  #include <key_io.h>
   7  #include <outputtype.h>
   8  #include <pubkey.h>
   9  #include <rpc/protocol.h>
  10  #include <rpc/request.h>
  11  #include <rpc/server.h>
  12  #include <rpc/util.h>
  13  #include <script/descriptor.h>
  14  #include <script/script.h>
  15  #include <script/signingprovider.h>
  16  #include <tinyformat.h>
  17  #include <univalue.h>
  18  #include <util/check.h>
  19  #include <util/strencodings.h>
  20  
  21  #include <cstdint>
  22  #include <memory>
  23  #include <optional>
  24  #include <string>
  25  #include <string_view>
  26  #include <tuple>
  27  #include <vector>
  28  
  29  static RPCMethod validateaddress()
  30  {
  31      return RPCMethod{
  32          "validateaddress",
  33          "Return information about the given bitcoin address.\n",
  34          {
  35              {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to validate"},
  36          },
  37          RPCResult{
  38              RPCResult::Type::OBJ, "", "",
  39              {
  40                  {RPCResult::Type::BOOL, "isvalid", "If the address is valid or not"},
  41                  {RPCResult::Type::STR, "address", /*optional=*/true, "The bitcoin address validated"},
  42                  {RPCResult::Type::STR_HEX, "scriptPubKey", /*optional=*/true, "The hex-encoded output script generated by the address"},
  43                  {RPCResult::Type::BOOL, "isscript", /*optional=*/true, "If the key is a script"},
  44                  {RPCResult::Type::BOOL, "iswitness", /*optional=*/true, "If the address is a witness address"},
  45                  {RPCResult::Type::NUM, "witness_version", /*optional=*/true, "The version number of the witness program"},
  46                  {RPCResult::Type::STR_HEX, "witness_program", /*optional=*/true, "The hex value of the witness program"},
  47                  {RPCResult::Type::STR, "error", /*optional=*/true, "Error message, if any"},
  48                  {RPCResult::Type::ARR, "error_locations", /*optional=*/true, "Indices of likely error locations in address, if known (e.g. Bech32 errors)",
  49                      {
  50                          {RPCResult::Type::NUM, "index", "index of a potential error"},
  51                      }},
  52              }
  53          },
  54          RPCExamples{
  55              HelpExampleCli("validateaddress", "\"" + EXAMPLE_ADDRESS[0] + "\"") +
  56              HelpExampleRpc("validateaddress", "\"" + EXAMPLE_ADDRESS[0] + "\"")
  57          },
  58          [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
  59          {
  60              std::string error_msg;
  61              std::vector<int> error_locations;
  62              CTxDestination dest = DecodeDestination(request.params[0].get_str(), error_msg, &error_locations);
  63              const bool isValid = IsValidDestination(dest);
  64              CHECK_NONFATAL(isValid == error_msg.empty());
  65  
  66              UniValue ret(UniValue::VOBJ);
  67              ret.pushKV("isvalid", isValid);
  68              if (isValid) {
  69                  std::string currentAddress = EncodeDestination(dest);
  70                  ret.pushKV("address", currentAddress);
  71  
  72                  CScript scriptPubKey = GetScriptForDestination(dest);
  73                  ret.pushKV("scriptPubKey", HexStr(scriptPubKey));
  74  
  75                  UniValue detail = DescribeAddress(dest);
  76                  ret.pushKVs(std::move(detail));
  77              } else {
  78                  UniValue error_indices(UniValue::VARR);
  79                  for (int i : error_locations) error_indices.push_back(i);
  80                  ret.pushKV("error_locations", std::move(error_indices));
  81                  ret.pushKV("error", error_msg);
  82              }
  83  
  84              return ret;
  85          },
  86      };
  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
 147              std::unique_ptr<Descriptor> descriptor = InferDescriptor(GetScriptForDestination(dest), keystore);
 148  
 149              UniValue result(UniValue::VOBJ);
 150              result.pushKV("address", EncodeDestination(dest));
 151              result.pushKV("redeemScript", HexStr(inner));
 152              result.pushKV("descriptor", descriptor->ToString());
 153  
 154              UniValue warnings(UniValue::VARR);
 155              if (descriptor->GetOutputType() != output_type.value()) {
 156                  // Only warns if the user has explicitly chosen an address type we cannot generate
 157                  warnings.push_back("Unable to make chosen address type, please ensure no uncompressed public keys are present.");
 158              }
 159              PushWarnings(warnings, result);
 160  
 161              return result;
 162          },
 163      };
 164  }
 165  
 166  static RPCMethod getdescriptorinfo()
 167  {
 168      const std::string EXAMPLE_DESCRIPTOR = "wpkh([d34db33f/84h/0h/0h]0279be667ef9dcbbac55a06295Ce870b07029Bfcdb2dce28d959f2815b16f81798)";
 169  
 170      return RPCMethod{
 171          "getdescriptorinfo",
 172          "Analyses a descriptor.\n",
 173          {
 174              {"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor."},
 175          },
 176          RPCResult{
 177              RPCResult::Type::OBJ, "", "",
 178              {
 179                  {RPCResult::Type::STR, "descriptor", "The descriptor in canonical form, without private keys. For a multipath descriptor, only the first will be returned."},
 180                  {RPCResult::Type::ARR, "multipath_expansion", /*optional=*/true, "All descriptors produced by expanding multipath derivation elements. Only if the provided descriptor specifies multipath derivation elements.",
 181                  {
 182                      {RPCResult::Type::STR, "", ""},
 183                  }},
 184                  {RPCResult::Type::STR, "checksum", "The checksum for the input descriptor"},
 185                  {RPCResult::Type::BOOL, "isrange", "Whether the descriptor is ranged"},
 186                  {RPCResult::Type::BOOL, "issolvable", "Whether the descriptor is solvable"},
 187                  {RPCResult::Type::BOOL, "hasprivatekeys", "Whether the input descriptor contained at least one private key"},
 188              }
 189          },
 190          RPCExamples{
 191              "Analyse a descriptor\n" +
 192              HelpExampleCli("getdescriptorinfo", "\"" + EXAMPLE_DESCRIPTOR + "\"") +
 193              HelpExampleRpc("getdescriptorinfo", "\"" + EXAMPLE_DESCRIPTOR + "\"")
 194          },
 195          [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
 196          {
 197              FlatSigningProvider provider;
 198              std::string error;
 199              auto descs = Parse(self.Arg<std::string_view>("descriptor"), provider, error);
 200              if (descs.empty()) {
 201                  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error);
 202              }
 203  
 204              UniValue result(UniValue::VOBJ);
 205              result.pushKV("descriptor", descs.at(0)->ToString());
 206  
 207              if (descs.size() > 1) {
 208                  UniValue multipath_descs(UniValue::VARR);
 209                  for (const auto& d : descs) {
 210                      multipath_descs.push_back(d->ToString());
 211                  }
 212                  result.pushKV("multipath_expansion", multipath_descs);
 213              }
 214  
 215              result.pushKV("checksum", GetDescriptorChecksum(request.params[0].get_str()));
 216              result.pushKV("isrange", descs.at(0)->IsRange());
 217              result.pushKV("issolvable", descs.at(0)->IsSolvable());
 218              result.pushKV("hasprivatekeys", provider.keys.size() > 0);
 219              return result;
 220          },
 221      };
 222  }
 223  
 224  static UniValue DeriveAddresses(const Descriptor* desc, int64_t range_begin, int64_t range_end, FlatSigningProvider& key_provider)
 225  {
 226      UniValue addresses(UniValue::VARR);
 227  
 228      for (int64_t i = range_begin; i <= range_end; ++i) {
 229          FlatSigningProvider provider;
 230          std::vector<CScript> scripts;
 231          if (!desc->Expand(i, key_provider, scripts, provider)) {
 232              throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot derive script without private keys");
 233          }
 234  
 235          for (const CScript& script : scripts) {
 236              CTxDestination dest;
 237              if (!ExtractDestination(script, dest)) {
 238                  // ExtractDestination no longer returns true for P2PK since it doesn't have a corresponding address
 239                  // However combo will output P2PK and should just ignore that script
 240                  if (scripts.size() > 1 && std::get_if<PubKeyDestination>(&dest)) {
 241                      continue;
 242                  }
 243                  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Descriptor does not have a corresponding address");
 244              }
 245  
 246              addresses.push_back(EncodeDestination(dest));
 247          }
 248      }
 249  
 250      // This should not be possible, but an assert seems overkill:
 251      if (addresses.empty()) {
 252          throw JSONRPCError(RPC_MISC_ERROR, "Unexpected empty result");
 253      }
 254  
 255      return addresses;
 256  }
 257  
 258  static RPCMethod deriveaddresses()
 259  {
 260      const std::string EXAMPLE_DESCRIPTOR = "wpkh([d34db33f/84h/0h/0h]xpub6DJ2dNUysrn5Vt36jH2KLBT2i1auw1tTSSomg8PhqNiUtx8QX2SvC9nrHu81fT41fvDUnhMjEzQgXnQjKEu3oaqMSzhSrHMxyyoEAmUHQbY/0/*)#cjjspncu";
 261  
 262      return RPCMethod{
 263          "deriveaddresses",
 264          "Derives one or more addresses corresponding to an output descriptor.\n"
 265           "Examples of output descriptors are:\n"
 266           "    pkh(<pubkey>)                                     P2PKH outputs for the given pubkey\n"
 267           "    wpkh(<pubkey>)                                    Native segwit P2PKH outputs for the given pubkey\n"
 268           "    sh(multi(<n>,<pubkey>,<pubkey>,...))              P2SH-multisig outputs for the given threshold and pubkeys\n"
 269           "    raw(<hex script>)                                 Outputs whose output script equals the specified hex-encoded bytes\n"
 270           "    tr(<pubkey>,multi_a(<n>,<pubkey>,<pubkey>,...))   P2TR-multisig outputs for the given threshold and pubkeys\n"
 271           "\nIn the above, <pubkey> either refers to a fixed public key in hexadecimal notation, or to an xpub/xprv optionally followed by one\n"
 272           "or more path elements separated by \"/\", where \"h\" represents a hardened child key.\n"
 273          "For more information on output descriptors, see the documentation in the doc/descriptors.md file.\n",
 274          {
 275              {"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor."},
 276              {"range", RPCArg::Type::RANGE, RPCArg::Optional::OMITTED, "If a ranged descriptor is used, this specifies the end or the range (in [begin,end] notation) to derive."},
 277          },
 278          {
 279              RPCResult{"for single derivation descriptors",
 280                  RPCResult::Type::ARR, "", "",
 281                  {
 282                      {RPCResult::Type::STR, "address", "the derived addresses"},
 283                  }
 284              },
 285              RPCResult{"for multipath descriptors",
 286                  RPCResult::Type::ARR, "", "The derived addresses for each of the multipath expansions of the descriptor, in multipath specifier order",
 287                  {
 288                      {
 289                          RPCResult::Type::ARR, "", "The derived addresses for a multipath descriptor expansion",
 290                          {
 291                              {RPCResult::Type::STR, "address", "the derived address"},
 292                          },
 293                      },
 294                  },
 295              },
 296          },
 297          RPCExamples{
 298              "First three native segwit receive addresses\n" +
 299              HelpExampleCli("deriveaddresses", "\"" + EXAMPLE_DESCRIPTOR + "\" \"[0,2]\"") +
 300              HelpExampleRpc("deriveaddresses", "\"" + EXAMPLE_DESCRIPTOR + "\", \"[0,2]\"")
 301          },
 302          [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
 303          {
 304              auto desc_str{self.Arg<std::string_view>("descriptor")};
 305  
 306              int64_t range_begin = 0;
 307              int64_t range_end = 0;
 308  
 309              if (request.params.size() >= 2 && !request.params[1].isNull()) {
 310                  std::tie(range_begin, range_end) = ParseDescriptorRange(request.params[1]);
 311              }
 312  
 313              FlatSigningProvider key_provider;
 314              std::string error;
 315              auto descs = Parse(desc_str, key_provider, error, /* require_checksum = */ true);
 316              if (descs.empty()) {
 317                  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error);
 318              }
 319              auto& desc = descs.at(0);
 320              if (!desc->IsRange() && request.params.size() > 1) {
 321                  throw JSONRPCError(RPC_INVALID_PARAMETER, "Range should not be specified for an un-ranged descriptor");
 322              }
 323  
 324              if (desc->IsRange() && request.params.size() == 1) {
 325                  throw JSONRPCError(RPC_INVALID_PARAMETER, "Range must be specified for a ranged descriptor");
 326              }
 327  
 328              UniValue addresses = DeriveAddresses(desc.get(), range_begin, range_end, key_provider);
 329  
 330              if (descs.size() == 1) {
 331                  return addresses;
 332              }
 333  
 334              UniValue ret(UniValue::VARR);
 335              ret.push_back(addresses);
 336              for (size_t i = 1; i < descs.size(); ++i) {
 337                  ret.push_back(DeriveAddresses(descs.at(i).get(), range_begin, range_end, key_provider));
 338              }
 339              return ret;
 340          },
 341      };
 342  }
 343  
 344  void RegisterOutputScriptRPCCommands(CRPCTable& t)
 345  {
 346      static const CRPCCommand commands[]{
 347          {"util", &validateaddress},
 348          {"util", &createmultisig},
 349          {"util", &deriveaddresses},
 350          {"util", &getdescriptorinfo},
 351      };
 352      for (const auto& c : commands) {
 353          t.appendCommand(c.name, &c);
 354      }
 355  }
 356