text: // Copyright (c) 2009-2010 Satoshi Nakamoto
  // Copyright (c) 2009-2018 The Pocketcoin Core developers
  // Distributed under the MIT software license, see the accompanying
  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  
  #include <outputtype.h>
  
  #include <keystore.h>
  #include <pubkey.h>
  #include <script/script.h>
  #include <script/standard.h>
  
  #include <assert.h>
  #include <string>
  
  static const std::string OUTPUT_TYPE_STRING_LEGACY = "legacy";
  static const std::string OUTPUT_TYPE_STRING_P2SH_SEGWIT = "p2sh-segwit";
  static const std::string OUTPUT_TYPE_STRING_BECH32 = "bech32";
  
  bool ParseOutputType(const std::string& type, OutputType& output_type)
  {
      if (type == OUTPUT_TYPE_STRING_LEGACY) {
          output_type = OutputType::LEGACY;
          return true;
      } else if (type == OUTPUT_TYPE_STRING_P2SH_SEGWIT) {
          output_type = OutputType::P2SH_SEGWIT;
          return true;
      } else if (type == OUTPUT_TYPE_STRING_BECH32) {
          output_type = OutputType::BECH32;
          return true;
      }
      return false;
  }
  
  const std::string& FormatOutputType(OutputType type)
  {
      switch (type) {
      case OutputType::LEGACY: return OUTPUT_TYPE_STRING_LEGACY;
      case OutputType::P2SH_SEGWIT: return OUTPUT_TYPE_STRING_P2SH_SEGWIT;
      case OutputType::BECH32: return OUTPUT_TYPE_STRING_BECH32;
      default: assert(false);
      }
  }
  
  CTxDestination GetDestinationForKey(const CPubKey& key, OutputType type)
  {
      switch (type) {
      case OutputType::LEGACY: return key.GetID();
      case OutputType::P2SH_SEGWIT:
      case OutputType::BECH32: {
          if (!key.IsCompressed()) return key.GetID();
          CTxDestination witdest = WitnessV0KeyHash(key.GetID());
          CScript witprog = GetScriptForDestination(witdest);
          if (type == OutputType::P2SH_SEGWIT) {
              return CScriptID(witprog);
          } else {
              return witdest;
          }
      }
      default: assert(false);
      }
  }
  
  std::vector<CTxDestination> GetAllDestinationsForKey(const CPubKey& key)
  {
      CKeyID keyid = key.GetID();
      if (key.IsCompressed()) {
          CTxDestination segwit = WitnessV0KeyHash(keyid);
          CTxDestination p2sh = CScriptID(GetScriptForDestination(segwit));
          return std::vector<CTxDestination>{std::move(keyid), std::move(p2sh), std::move(segwit)};
      } else {
          return std::vector<CTxDestination>{std::move(keyid)};
      }
  }
  
  CTxDestination AddAndGetDestinationForScript(CKeyStore& keystore, const CScript& script, OutputType type)
  {
      // Add script to keystore
      keystore.AddCScript(script);
      // Note that scripts over 520 bytes are not yet supported.
      switch (type) {
      case OutputType::LEGACY:
          return CScriptID(script);
      case OutputType::P2SH_SEGWIT:
      case OutputType::BECH32: {
          CTxDestination witdest = WitnessV0ScriptHash(script);
          CScript witprog = GetScriptForDestination(witdest);
          // Check if the resulting program is solvable (i.e. doesn't use an uncompressed key)
          if (!IsSolvable(keystore, witprog)) return CScriptID(script);
          // Add the redeemscript, so that P2WSH and P2SH-P2WSH outputs are recognized as ours.
          keystore.AddCScript(witprog);
          if (type == OutputType::BECH32) {
              return witdest;
          } else {
              return CScriptID(witprog);
          }
      }
      default: assert(false);
      }
  }
  
  