From 6b8d3d392ad0dac9b71f0d229448eb0020f9d01a Mon Sep 17 00:00:00 2001 From: blackjok3rtt <30971146+blackjok3rtt@users.noreply.github.com> Date: Wed, 5 Dec 2018 20:13:30 +0800 Subject: [PATCH] Delete rpcmisc.cpp --- src/rpcmisc.cpp | 1300 ----------------------------------------------- 1 file changed, 1300 deletions(-) delete mode 100644 src/rpcmisc.cpp diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp deleted file mode 100644 index 4f436f41a..000000000 --- a/src/rpcmisc.cpp +++ /dev/null @@ -1,1300 +0,0 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "base58.h" -#include "clientversion.h" -#include "init.h" -#include "main.h" -#include "net.h" -#include "netbase.h" -#include "rpcserver.h" -#include "timedata.h" -#include "txmempool.h" -#include "util.h" -#include "notaries_staked.h" -#ifdef ENABLE_WALLET -#include "wallet/wallet.h" -#include "wallet/walletdb.h" -#endif - -#include - -#include - -#include - -#include "zcash/Address.hpp" - -using namespace std; - -/** - * @note Do not add or change anything in the information returned by this - * method. `getinfo` exists for backwards-compatibility only. It combines - * information from wildly different sources in the program, which is a mess, - * and is thus planned to be deprecated eventually. - * - * Based on the source of the information, new information should be added to: - * - `getblockchaininfo`, - * - `getnetworkinfo` or - * - `getwalletinfo` - * - * Or alternatively, create a specific query method for the information. - **/ - -int32_t Jumblr_depositaddradd(char *depositaddr); -int32_t Jumblr_secretaddradd(char *secretaddr); -uint64_t komodo_interestsum(); -int32_t komodo_longestchain(); -int32_t komodo_notarized_height(int32_t *prevhtp,uint256 *hashp,uint256 *txidp); -uint32_t komodo_chainactive_timestamp(); -int32_t komodo_whoami(char *pubkeystr,int32_t height,uint32_t timestamp); -extern uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; -extern int32_t KOMODO_LASTMINED,JUMBLR_PAUSE,KOMODO_LONGESTCHAIN,IS_STAKED_NOTARY,IS_KOMODO_NOTARY,STAKED_ERA; -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -uint32_t komodo_segid32(char *coinaddr); -int64_t komodo_coinsupply(int64_t *zfundsp,int32_t height); -int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp); -int8_t StakedNotaryID(std::string ¬aryname, char *Raddress); -#define KOMODO_VERSION "0.2.1" -extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; -extern uint32_t ASSETCHAINS_CC; -extern uint32_t ASSETCHAINS_MAGIC; -extern uint64_t ASSETCHAINS_ENDSUBSIDY,ASSETCHAINS_REWARD,ASSETCHAINS_HALVING,ASSETCHAINS_DECAY,ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED,ASSETCHAINS_SUPPLY; -extern std::string NOTARY_PUBKEY,NOTARY_ADDRESS; extern uint8_t NOTARY_PUBKEY33[]; - -int32_t getera(int now) -{ - for (int32_t i = 0; i < NUM_STAKED_ERAS; i++) { - if ( now <= STAKED_NOTARIES_TIMESTAMP[i] ) { - return(i); - } - } -} - -UniValue getiguanajson(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error("getiguanajson\nreturns json for iguana, for the current ERA."); - - UniValue json(UniValue::VOBJ); - UniValue seeds(UniValue::VARR); - UniValue notaries(UniValue::VARR); - // get the current era, use local time for now. - // should ideally take blocktime of last known block? - int now = time(NULL); - int32_t era = getera(now); - - // loop over seeds array and push back to json array for seeds - for (int8_t i = 0; i < 8; i++) { - seeds.push_back(iguanaSeeds[i][0]); - } - - // loop over era's notaries and push back each pair to the notary array - for (int8_t i = 0; i < num_notaries_STAKED[era]; i++) { - UniValue notary(UniValue::VOBJ); - notary.push_back(Pair(notaries_STAKED[era][i][0],notaries_STAKED[era][i][1])); - notaries.push_back(notary); - } - - // get the min sigs .. this always rounds UP so mine sigs in iguana is +1 min sigs in komodod, due to some rounding error. - int minsigs; - if ( num_notaries_STAKED[era]/5 > overrideMinSigs ) - minsigs = (num_notaries_STAKED[era] / 5) + 1; - else - minsigs = overrideMinSigs; - - json.push_back(Pair("port",iguanaPort)); - json.push_back(Pair("BTCminsigs",BTCminsigs)); - json.push_back(Pair("minsigs",minsigs)); - json.push_back(Pair("seeds", seeds)); - json.push_back(Pair("notaries",notaries)); - return json; -} - -UniValue getnotarysendmany(const UniValue& params, bool fHelp) -{ - int era = getera(time(NULL)); - - UniValue ret(UniValue::VOBJ); - for (int i = 0; ics_wallet : NULL); -//#else - LOCK(cs_main); -//#endif - - proxyType proxy; - GetProxy(NET_IPV4, proxy); - notarized_height = komodo_notarized_height(&prevMoMheight,¬arized_hash,¬arized_desttxid); - //fprintf(stderr,"after notarized_height %u\n",(uint32_t)time(NULL)); - - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("version", CLIENT_VERSION)); - obj.push_back(Pair("protocolversion", PROTOCOL_VERSION)); - obj.push_back(Pair("KMDversion", KOMODO_VERSION)); - obj.push_back(Pair("notarized", notarized_height)); - obj.push_back(Pair("prevMoMheight", prevMoMheight)); - obj.push_back(Pair("notarizedhash", notarized_hash.ToString())); - obj.push_back(Pair("notarizedtxid", notarized_desttxid.ToString())); - txid_height = notarizedtxid_height(ASSETCHAINS_SYMBOL[0] != 0 ? (char *)"KMD" : (char *)"BTC",(char *)notarized_desttxid.ToString().c_str(),&kmdnotarized_height); - if ( txid_height > 0 ) - obj.push_back(Pair("notarizedtxid_height", txid_height)); - else obj.push_back(Pair("notarizedtxid_height", "mempool")); - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - obj.push_back(Pair("KMDnotarized_height", kmdnotarized_height)); - obj.push_back(Pair("notarized_confirms", txid_height < kmdnotarized_height ? (kmdnotarized_height - txid_height + 1) : 0)); - //fprintf(stderr,"after notarized_confirms %u\n",(uint32_t)time(NULL)); -#ifdef ENABLE_WALLET - if (pwalletMain) { - obj.push_back(Pair("walletversion", pwalletMain->GetVersion())); - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - { - obj.push_back(Pair("interest", ValueFromAmount(KOMODO_INTERESTSUM))); - obj.push_back(Pair("balance", ValueFromAmount(KOMODO_WALLETBALANCE))); //pwalletMain->GetBalance() - } - else - { - obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance()))); // - } - } -#endif - //fprintf(stderr,"after wallet %u\n",(uint32_t)time(NULL)); - obj.push_back(Pair("blocks", (int)chainActive.Height())); - if ( (longestchain= KOMODO_LONGESTCHAIN) != 0 && chainActive.Height() > longestchain ) - longestchain = chainActive.Height(); - //fprintf(stderr,"after longestchain %u\n",(uint32_t)time(NULL)); - obj.push_back(Pair("longestchain", longestchain)); - obj.push_back(Pair("timeoffset", GetTimeOffset())); - if ( chainActive.LastTip() != 0 ) - obj.push_back(Pair("tiptime", (int)chainActive.LastTip()->nTime)); - obj.push_back(Pair("connections", (int)vNodes.size())); - obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string()))); - obj.push_back(Pair("difficulty", (double)GetDifficulty())); - obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC())); -#ifdef ENABLE_WALLET - if (pwalletMain) { - obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime())); - obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize())); - } - if (pwalletMain && pwalletMain->IsCrypted()) - obj.push_back(Pair("unlocked_until", nWalletUnlockTime)); - obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK()))); -#endif - obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()))); - obj.push_back(Pair("errors", GetWarnings("statusbar"))); - if ( NOTARY_PUBKEY33[0] != 0 ) { - char pubkeystr[65]; int32_t notaryid; std::string notaryname; - if ( (notaryid= StakedNotaryID(notaryname, (char *)NOTARY_ADDRESS.c_str())) != -1 ) { - obj.push_back(Pair("notaryid", notaryid)); - obj.push_back(Pair("notaryname", notaryname)); - } else if( (notaryid= komodo_whoami(pubkeystr,(int32_t)chainActive.LastTip()->nHeight,komodo_chainactive_timestamp())) >= 0 ) { - obj.push_back(Pair("notaryid", notaryid)); - if ( KOMODO_LASTMINED != 0 ) - obj.push_back(Pair("lastmined", KOMODO_LASTMINED)); - } - obj.push_back(Pair("pubkey", NOTARY_PUBKEY)); - } - if ( ASSETCHAINS_CC != 0 ) - obj.push_back(Pair("CCid", (int)ASSETCHAINS_CC)); - obj.push_back(Pair("name", ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL)); - obj.push_back(Pair("p2pport", ASSETCHAINS_P2PPORT)); - obj.push_back(Pair("rpcport", ASSETCHAINS_RPCPORT)); - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - { - if ( is_STAKED(ASSETCHAINS_SYMBOL) != 0 ) - obj.push_back(Pair("StakedEra", STAKED_ERA)); - //obj.push_back(Pair("name", ASSETCHAINS_SYMBOL)); - obj.push_back(Pair("magic", (int)ASSETCHAINS_MAGIC)); - if ( ASSETCHAINS_SUPPLY != 0 ) - obj.push_back(Pair("premine", ASSETCHAINS_SUPPLY)); - if ( ASSETCHAINS_REWARD != 0 ) - obj.push_back(Pair("reward", ASSETCHAINS_REWARD)); - if ( ASSETCHAINS_HALVING != 0 ) - obj.push_back(Pair("halving", ASSETCHAINS_HALVING)); - if ( ASSETCHAINS_DECAY != 0 ) - obj.push_back(Pair("decay", ASSETCHAINS_DECAY)); - if ( ASSETCHAINS_ENDSUBSIDY != 0 ) - obj.push_back(Pair("endsubsidy", ASSETCHAINS_ENDSUBSIDY)); - if ( ASSETCHAINS_COMMISSION != 0 ) - obj.push_back(Pair("commission", ASSETCHAINS_COMMISSION)); - if ( ASSETCHAINS_STAKED != 0 ) - obj.push_back(Pair("staked", ASSETCHAINS_STAKED)); - } - return obj; -} - -#ifdef ENABLE_WALLET -class DescribeAddressVisitor : public boost::static_visitor -{ -public: - UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); } - - UniValue operator()(const CKeyID &keyID) const { - UniValue obj(UniValue::VOBJ); - CPubKey vchPubKey; - obj.push_back(Pair("isscript", false)); - if (pwalletMain && pwalletMain->GetPubKey(keyID, vchPubKey)) { - obj.push_back(Pair("pubkey", HexStr(vchPubKey))); - obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed())); - } - return obj; - } - - UniValue operator()(const CScriptID &scriptID) const { - UniValue obj(UniValue::VOBJ); - CScript subscript; - obj.push_back(Pair("isscript", true)); - if (pwalletMain && pwalletMain->GetCScript(scriptID, subscript)) { - std::vector addresses; - txnouttype whichType; - int nRequired; - ExtractDestinations(subscript, whichType, addresses, nRequired); - obj.push_back(Pair("script", GetTxnOutputType(whichType))); - obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end()))); - UniValue a(UniValue::VARR); - BOOST_FOREACH(const CTxDestination& addr, addresses) - a.push_back(CBitcoinAddress(addr).ToString()); - obj.push_back(Pair("addresses", a)); - if (whichType == TX_MULTISIG) - obj.push_back(Pair("sigsrequired", nRequired)); - } - return obj; - } -}; -#endif - -UniValue coinsupply(const UniValue& params, bool fHelp) -{ - int32_t height = 0; int32_t currentHeight; int64_t zfunds,supply = 0; UniValue result(UniValue::VOBJ); - if (fHelp || params.size() > 1) - throw runtime_error("coinsupply \n" - "\nReturn coin supply information at a given block height. If no height is given, the current height is used.\n" - "\nArguments:\n" - "1. \"height\" (integer, optional) Block height\n" - "\nResult:\n" - "{\n" - " \"result\" : \"success\", (string) If the request was successful.\n" - " \"coin\" : \"KMD\", (string) The currency symbol of the coin for asset chains, otherwise KMD.\n" - " \"height\" : 420, (integer) The height of this coin supply data\n" - " \"supply\" : \"777.0\", (float) The transparent coin supply\n" - " \"zfunds\" : \"0.777\", (float) The shielded coin supply (in zaddrs)\n" - " \"total\" : \"777.777\", (float) The total coin supply, i.e. sum of supply + zfunds\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("coinsupply", "420") - + HelpExampleRpc("coinsupply", "420") - ); - if ( params.size() == 0 ) - height = chainActive.Height(); - else height = atoi(params[0].get_str()); - currentHeight = chainActive.Height(); - - if (height >= 0 && height <= currentHeight) { - if ( (supply= komodo_coinsupply(&zfunds,height)) > 0 ) - { - result.push_back(Pair("result", "success")); - result.push_back(Pair("coin", ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL)); - result.push_back(Pair("height", (int)height)); - result.push_back(Pair("supply", ValueFromAmount(supply))); - result.push_back(Pair("zfunds", ValueFromAmount(zfunds))); - result.push_back(Pair("total", ValueFromAmount(zfunds + supply))); - } else result.push_back(Pair("error", "couldnt calculate supply")); - } else { - result.push_back(Pair("error", "invalid height")); - } - return(result); -} - -UniValue jumblr_deposit(const UniValue& params, bool fHelp) -{ - int32_t retval; UniValue result(UniValue::VOBJ); - if (fHelp || params.size() != 1) - throw runtime_error("jumblr_deposit \"depositaddress\"\n"); - CBitcoinAddress address(params[0].get_str()); - bool isValid = address.IsValid(); - if ( isValid != 0 ) - { - string addr = params[0].get_str(); - if ( (retval= Jumblr_depositaddradd((char *)addr.c_str())) >= 0 ) - { - result.push_back(Pair("result", retval)); - JUMBLR_PAUSE = 0; - } - else result.push_back(Pair("error", retval)); - } else result.push_back(Pair("error", "invalid address")); - return(result); -} - -UniValue jumblr_secret(const UniValue& params, bool fHelp) -{ - int32_t retval; UniValue result(UniValue::VOBJ); - if (fHelp || params.size() != 1) - throw runtime_error("jumblr_secret \"secretaddress\"\n"); - CBitcoinAddress address(params[0].get_str()); - bool isValid = address.IsValid(); - if ( isValid != 0 ) - { - string addr = params[0].get_str(); - retval = Jumblr_secretaddradd((char *)addr.c_str()); - result.push_back(Pair("result", "success")); - result.push_back(Pair("num", retval)); - JUMBLR_PAUSE = 0; - } else result.push_back(Pair("error", "invalid address")); - return(result); -} - -UniValue jumblr_pause(const UniValue& params, bool fHelp) -{ - int32_t retval; UniValue result(UniValue::VOBJ); - if (fHelp ) - throw runtime_error("jumblr_pause\n"); - JUMBLR_PAUSE = 1; - result.push_back(Pair("result", "paused")); - return(result); -} - -UniValue jumblr_resume(const UniValue& params, bool fHelp) -{ - int32_t retval; UniValue result(UniValue::VOBJ); - if (fHelp ) - throw runtime_error("jumblr_resume\n"); - JUMBLR_PAUSE = 0; - result.push_back(Pair("result", "resumed")); - return(result); -} - -UniValue validateaddress(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "validateaddress \"komodoaddress\"\n" - "\nReturn information about the given Komodo address.\n" - "\nArguments:\n" - "1. \"komodoaddress\" (string, required) The Komodo address to validate\n" - "\nResult:\n" - "{\n" - " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n" - " \"address\" : \"komodoaddress\", (string) The Komodo address validated\n" - " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n" - " \"ismine\" : true|false, (boolean) If the address is yours or not\n" - " \"isscript\" : true|false, (boolean) If the key is a script\n" - " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n" - " \"iscompressed\" : true|false, (boolean) If the address is compressed\n" - " \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("validateaddress", "\"RTZMZHDFSTFQst8XmX2dR4DaH87cEUs3gC\"") - + HelpExampleRpc("validateaddress", "\"RTZMZHDFSTFQst8XmX2dR4DaH87cEUs3gC\"") - ); - -#ifdef ENABLE_WALLET - LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL); -#else - LOCK(cs_main); -#endif - - CBitcoinAddress address(params[0].get_str()); - bool isValid = address.IsValid(); - - UniValue ret(UniValue::VOBJ); - ret.push_back(Pair("isvalid", isValid)); - if (isValid) - { - CTxDestination dest = address.Get(); - string currentAddress = address.ToString(); - ret.push_back(Pair("address", currentAddress)); - - CScript scriptPubKey = GetScriptForDestination(dest); - ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()))); - ret.push_back(Pair("segid", (int32_t)komodo_segid32((char *)params[0].get_str().c_str()) & 0x3f)); -#ifdef ENABLE_WALLET - isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO; - ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false)); - ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false)); - UniValue detail = boost::apply_visitor(DescribeAddressVisitor(), dest); - ret.pushKVs(detail); - if (pwalletMain && pwalletMain->mapAddressBook.count(dest)) - ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name)); -#endif - } - return ret; -} - - -UniValue z_validateaddress(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "z_validateaddress \"zaddr\"\n" - "\nReturn information about the given z address.\n" - "\nArguments:\n" - "1. \"zaddr\" (string, required) The z address to validate\n" - "\nResult:\n" - "{\n" - " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n" - " \"address\" : \"zaddr\", (string) The z address validated\n" - " \"ismine\" : true|false, (boolean) If the address is yours or not\n" - " \"payingkey\" : \"hex\", (string) The hex value of the paying key, a_pk\n" - " \"transmissionkey\" : \"hex\", (string) The hex value of the transmission key, pk_enc\n" - - "}\n" - "\nExamples:\n" - + HelpExampleCli("z_validateaddress", "\"zcWsmqT4X2V4jgxbgiCzyrAfRT1vi1F4sn7M5Pkh66izzw8Uk7LBGAH3DtcSMJeUb2pi3W4SQF8LMKkU2cUuVP68yAGcomL\"") - + HelpExampleRpc("z_validateaddress", "\"zcWsmqT4X2V4jgxbgiCzyrAfRT1vi1F4sn7M5Pkh66izzw8Uk7LBGAH3DtcSMJeUb2pi3W4SQF8LMKkU2cUuVP68yAGcomL\"") - ); - - -#ifdef ENABLE_WALLET - LOCK2(cs_main, pwalletMain->cs_wallet); -#else - LOCK(cs_main); -#endif - - bool isValid = false; - bool isMine = false; - std::string payingKey, transmissionKey; - - string strAddress = params[0].get_str(); - try { - CZCPaymentAddress address(strAddress); - libzcash::PaymentAddress addr = address.Get(); - -#ifdef ENABLE_WALLET - isMine = pwalletMain->HaveSpendingKey(addr); -#endif - payingKey = addr.a_pk.GetHex(); - transmissionKey = addr.pk_enc.GetHex(); - isValid = true; - } catch (std::runtime_error e) { - // address is invalid, nop here as isValid is false. - } - - UniValue ret(UniValue::VOBJ); - ret.push_back(Pair("isvalid", isValid)); - if (isValid) - { - ret.push_back(Pair("address", strAddress)); - ret.push_back(Pair("payingkey", payingKey)); - ret.push_back(Pair("transmissionkey", transmissionKey)); -#ifdef ENABLE_WALLET - ret.push_back(Pair("ismine", isMine)); -#endif - } - return ret; -} - - -/** - * Used by addmultisigaddress / createmultisig: - */ -CScript _createmultisig_redeemScript(const UniValue& params) -{ - int nRequired = params[0].get_int(); - const UniValue& keys = params[1].get_array(); - - // Gather public keys - if (nRequired < 1) - throw runtime_error("a multisignature address must require at least one key to redeem"); - if ((int)keys.size() < nRequired) - throw runtime_error( - strprintf("not enough keys supplied " - "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired)); - if (keys.size() > 16) - throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number"); - std::vector pubkeys; - pubkeys.resize(keys.size()); - for (unsigned int i = 0; i < keys.size(); i++) - { - const std::string& ks = keys[i].get_str(); -#ifdef ENABLE_WALLET - // Case 1: Bitcoin address and we have full public key: - CBitcoinAddress address(ks); - if (pwalletMain && address.IsValid()) - { - CKeyID keyID; - if (!address.GetKeyID(keyID)) - throw runtime_error( - strprintf("%s does not refer to a key",ks)); - CPubKey vchPubKey; - if (!pwalletMain->GetPubKey(keyID, vchPubKey)) - throw runtime_error( - strprintf("no full public key for address %s",ks)); - if (!vchPubKey.IsFullyValid()) - throw runtime_error(" Invalid public key: "+ks); - pubkeys[i] = vchPubKey; - } - - // Case 2: hex public key - else -#endif - if (IsHex(ks)) - { - CPubKey vchPubKey(ParseHex(ks)); - if (!vchPubKey.IsFullyValid()) - throw runtime_error(" Invalid public key: "+ks); - pubkeys[i] = vchPubKey; - } - else - { - throw runtime_error(" Invalid public key: "+ks); - } - } - CScript result = GetScriptForMultisig(nRequired, pubkeys); - - if (result.size() > MAX_SCRIPT_ELEMENT_SIZE) - throw runtime_error( - strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE)); - - return result; -} - -UniValue createmultisig(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() < 2 || params.size() > 2) - { - string msg = "createmultisig nrequired [\"key\",...]\n" - "\nCreates a multi-signature address with n signature of m keys required.\n" - "It returns a json object with the address and redeemScript.\n" - - "\nArguments:\n" - "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n" - "2. \"keys\" (string, required) A json array of keys which are Komodo addresses or hex-encoded public keys\n" - " [\n" - " \"key\" (string) Komodo address or hex-encoded public key\n" - " ,...\n" - " ]\n" - - "\nResult:\n" - "{\n" - " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n" - " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n" - "}\n" - - "\nExamples:\n" - "\nCreate a multisig address from 2 addresses\n" - + HelpExampleCli("createmultisig", "2 \"[\\\"RTZMZHDFSTFQst8XmX2dR4DaH87cEUs3gC\\\",\\\"RNKiEBduBru6Siv1cZRVhp4fkZNyPska6z\\\"]\"") + - "\nAs a json rpc call\n" - + HelpExampleRpc("createmultisig", "2, \"[\\\"RTZMZHDFSTFQst8XmX2dR4DaH87cEUs3gC\\\",\\\"RNKiEBduBru6Siv1cZRVhp4fkZNyPska6z\\\"]\"") - ; - throw runtime_error(msg); - } - - // Construct using pay-to-script-hash: - CScript inner = _createmultisig_redeemScript(params); - CScriptID innerID(inner); - CBitcoinAddress address(innerID); - - UniValue result(UniValue::VOBJ); - result.push_back(Pair("address", address.ToString())); - result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end()))); - - return result; -} - -UniValue verifymessage(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 3) - throw runtime_error( - "verifymessage \"komodoaddress\" \"signature\" \"message\"\n" - "\nVerify a signed message\n" - "\nArguments:\n" - "1. \"komodoaddress\" (string, required) The Komodo address to use for the signature.\n" - "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n" - "3. \"message\" (string, required) The message that was signed.\n" - "\nResult:\n" - "true|false (boolean) If the signature is verified or not.\n" - "\nExamples:\n" - "\nUnlock the wallet for 30 seconds\n" - + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") + - "\nCreate the signature\n" - + HelpExampleCli("signmessage", "\"RNKiEBduBru6Siv1cZRVhp4fkZNyPska6z\" \"my message\"") + - "\nVerify the signature\n" - + HelpExampleCli("verifymessage", "\"RNKiEBduBru6Siv1cZRVhp4fkZNyPska6z\" \"signature\" \"my message\"") + - "\nAs json rpc\n" - + HelpExampleRpc("verifymessage", "\"RNKiEBduBru6Siv1cZRVhp4fkZNyPska6z\", \"signature\", \"my message\"") - ); - - LOCK(cs_main); - - string strAddress = params[0].get_str(); - string strSign = params[1].get_str(); - string strMessage = params[2].get_str(); - - CBitcoinAddress addr(strAddress); - if (!addr.IsValid()) - throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address"); - - CKeyID keyID; - if (!addr.GetKeyID(keyID)) - throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key"); - - bool fInvalid = false; - vector vchSig = DecodeBase64(strSign.c_str(), &fInvalid); - - if (fInvalid) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding"); - - CHashWriter ss(SER_GETHASH, 0); - ss << strMessageMagic; - ss << strMessage; - - CPubKey pubkey; - if (!pubkey.RecoverCompact(ss.GetHash(), vchSig)) - return false; - - return (pubkey.GetID() == keyID); -} - -UniValue setmocktime(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "setmocktime timestamp\n" - "\nSet the local time to given timestamp (-regtest only)\n" - "\nArguments:\n" - "1. timestamp (integer, required) Unix seconds-since-epoch timestamp\n" - " Pass 0 to go back to using the system time." - ); - - if (!Params().MineBlocksOnDemand()) - throw runtime_error("setmocktime for regression testing (-regtest mode) only"); - - // cs_vNodes is locked and node send/receive times are updated - // atomically with the time change to prevent peers from being - // disconnected because we think we haven't communicated with them - // in a long time. - LOCK2(cs_main, cs_vNodes); - - RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)); - SetMockTime(params[0].get_int64()); - - uint64_t t = GetTime(); - BOOST_FOREACH(CNode* pnode, vNodes) { - pnode->nLastSend = pnode->nLastRecv = t; - } - - return NullUniValue; -} - -bool getAddressFromIndex(const int &type, const uint160 &hash, std::string &address) -{ - if (type == 2) { - address = CBitcoinAddress(CScriptID(hash)).ToString(); - } else if (type == 1) { - address = CBitcoinAddress(CKeyID(hash)).ToString(); - } - else { - return false; - } - return true; -} - -bool getAddressesFromParams(const UniValue& params, std::vector > &addresses) -{ - if (params[0].isStr()) { - CBitcoinAddress address(params[0].get_str()); - uint160 hashBytes; - int type = 0; - if (!address.GetIndexKey(hashBytes, type)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); - } - addresses.push_back(std::make_pair(hashBytes, type)); - } else if (params[0].isObject()) { - - UniValue addressValues = find_value(params[0].get_obj(), "addresses"); - if (!addressValues.isArray()) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Addresses is expected to be an array"); - } - - std::vector values = addressValues.getValues(); - - for (std::vector::iterator it = values.begin(); it != values.end(); ++it) { - - CBitcoinAddress address(it->get_str()); - uint160 hashBytes; - int type = 0; - if (!address.GetIndexKey(hashBytes, type)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid addresses"); - } - addresses.push_back(std::make_pair(hashBytes, type)); - } - } else { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid addresse"); - } - - return true; -} - -bool heightSort(std::pair a, - std::pair b) { - return a.second.blockHeight < b.second.blockHeight; -} - -bool timestampSort(std::pair a, - std::pair b) { - return a.second.time < b.second.time; -} - -UniValue getaddressmempool(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "getaddressmempool\n" - "\nReturns all mempool deltas for an address (requires addressindex to be enabled).\n" - "\nArguments:\n" - "{\n" - " \"addresses\"\n" - " [\n" - " \"address\" (string) The base58check encoded address\n" - " ,...\n" - " ]\n" - "}\n" - "\nResult:\n" - "[\n" - " {\n" - " \"address\" (string) The base58check encoded address\n" - " \"txid\" (string) The related txid\n" - " \"index\" (number) The related input or output index\n" - " \"satoshis\" (number) The difference of satoshis\n" - " \"timestamp\" (number) The time the transaction entered the mempool (seconds)\n" - " \"prevtxid\" (string) The previous txid (if spending)\n" - " \"prevout\" (string) The previous transaction output index (if spending)\n" - " }\n" - "]\n" - "\nExamples:\n" - + HelpExampleCli("getaddressmempool", "'{\"addresses\": [\"RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87\"]}'") - + HelpExampleRpc("getaddressmempool", "{\"addresses\": [\"RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87\"]}") - ); - - std::vector > addresses; - - if (!getAddressesFromParams(params, addresses)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); - } - - std::vector > indexes; - - if (!mempool.getAddressIndex(addresses, indexes)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address"); - } - - std::sort(indexes.begin(), indexes.end(), timestampSort); - - UniValue result(UniValue::VARR); - - for (std::vector >::iterator it = indexes.begin(); - it != indexes.end(); it++) { - - std::string address; - if (!getAddressFromIndex(it->first.type, it->first.addressBytes, address)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown address type"); - } - - UniValue delta(UniValue::VOBJ); - delta.push_back(Pair("address", address)); - delta.push_back(Pair("txid", it->first.txhash.GetHex())); - delta.push_back(Pair("index", (int)it->first.index)); - delta.push_back(Pair("satoshis", it->second.amount)); - delta.push_back(Pair("timestamp", it->second.time)); - if (it->second.amount < 0) { - delta.push_back(Pair("prevtxid", it->second.prevhash.GetHex())); - delta.push_back(Pair("prevout", (int)it->second.prevout)); - } - result.push_back(delta); - } - - return result; -} - -UniValue getaddressutxos(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "getaddressutxos\n" - "\nReturns all unspent outputs for an address (requires addressindex to be enabled).\n" - "\nArguments:\n" - "{\n" - " \"addresses\"\n" - " [\n" - " \"address\" (string) The base58check encoded address\n" - " ,...\n" - " ],\n" - " \"chainInfo\" (boolean) Include chain info with results\n" - "}\n" - "\nResult\n" - "[\n" - " {\n" - " \"address\" (string) The address base58check encoded\n" - " \"txid\" (string) The output txid\n" - " \"height\" (number) The block height\n" - " \"outputIndex\" (number) The output index\n" - " \"script\" (strin) The script hex encoded\n" - " \"satoshis\" (number) The number of satoshis of the output\n" - " }\n" - "]\n" - "\nExamples:\n" - + HelpExampleCli("getaddressutxos", "'{\"addresses\": [\"RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87\"]}'") - + HelpExampleRpc("getaddressutxos", "{\"addresses\": [\"RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87\"]}") - ); - - bool includeChainInfo = false; - if (params[0].isObject()) { - UniValue chainInfo = find_value(params[0].get_obj(), "chainInfo"); - if (chainInfo.isBool()) { - includeChainInfo = chainInfo.get_bool(); - } - } - - std::vector > addresses; - - if (!getAddressesFromParams(params, addresses)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); - } - - std::vector > unspentOutputs; - - for (std::vector >::iterator it = addresses.begin(); it != addresses.end(); it++) { - if (!GetAddressUnspent((*it).first, (*it).second, unspentOutputs)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address"); - } - } - - std::sort(unspentOutputs.begin(), unspentOutputs.end(), heightSort); - - UniValue utxos(UniValue::VARR); - - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { - UniValue output(UniValue::VOBJ); - std::string address; - if (!getAddressFromIndex(it->first.type, it->first.hashBytes, address)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown address type"); - } - - output.push_back(Pair("address", address)); - output.push_back(Pair("txid", it->first.txhash.GetHex())); - output.push_back(Pair("outputIndex", (int)it->first.index)); - output.push_back(Pair("script", HexStr(it->second.script.begin(), it->second.script.end()))); - output.push_back(Pair("satoshis", it->second.satoshis)); - output.push_back(Pair("height", it->second.blockHeight)); - utxos.push_back(output); - } - - if (includeChainInfo) { - UniValue result(UniValue::VOBJ); - result.push_back(Pair("utxos", utxos)); - - LOCK(cs_main); - result.push_back(Pair("hash", chainActive.LastTip()->GetBlockHash().GetHex())); - result.push_back(Pair("height", (int)chainActive.Height())); - return result; - } else { - return utxos; - } -} - -UniValue getaddressdeltas(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1 || !params[0].isObject()) - throw runtime_error( - "getaddressdeltas\n" - "\nReturns all changes for an address (requires addressindex to be enabled).\n" - "\nArguments:\n" - "{\n" - " \"addresses\"\n" - " [\n" - " \"address\" (string) The base58check encoded address\n" - " ,...\n" - " ]\n" - " \"start\" (number) The start block height\n" - " \"end\" (number) The end block height\n" - " \"chainInfo\" (boolean) Include chain info in results, only applies if start and end specified\n" - "}\n" - "\nResult:\n" - "[\n" - " {\n" - " \"satoshis\" (number) The difference of satoshis\n" - " \"txid\" (string) The related txid\n" - " \"index\" (number) The related input or output index\n" - " \"height\" (number) The block height\n" - " \"address\" (string) The base58check encoded address\n" - " }\n" - "]\n" - "\nExamples:\n" - + HelpExampleCli("getaddressdeltas", "'{\"addresses\": [\"RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87\"]}'") - + HelpExampleRpc("getaddressdeltas", "{\"addresses\": [\"RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87\"]}") - ); - - - UniValue startValue = find_value(params[0].get_obj(), "start"); - UniValue endValue = find_value(params[0].get_obj(), "end"); - - UniValue chainInfo = find_value(params[0].get_obj(), "chainInfo"); - bool includeChainInfo = false; - if (chainInfo.isBool()) { - includeChainInfo = chainInfo.get_bool(); - } - - int start = 0; - int end = 0; - - if (startValue.isNum() && endValue.isNum()) { - start = startValue.get_int(); - end = endValue.get_int(); - if (start <= 0 || end <= 0) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Start and end is expected to be greater than zero"); - } - if (end < start) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "End value is expected to be greater than start"); - } - } - - std::vector > addresses; - - if (!getAddressesFromParams(params, addresses)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); - } - - std::vector > addressIndex; - - for (std::vector >::iterator it = addresses.begin(); it != addresses.end(); it++) { - if (start > 0 && end > 0) { - if (!GetAddressIndex((*it).first, (*it).second, addressIndex, start, end)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address"); - } - } else { - if (!GetAddressIndex((*it).first, (*it).second, addressIndex)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address"); - } - } - } - - UniValue deltas(UniValue::VARR); - - for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) { - std::string address; - if (!getAddressFromIndex(it->first.type, it->first.hashBytes, address)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown address type"); - } - - UniValue delta(UniValue::VOBJ); - delta.push_back(Pair("satoshis", it->second)); - delta.push_back(Pair("txid", it->first.txhash.GetHex())); - delta.push_back(Pair("index", (int)it->first.index)); - delta.push_back(Pair("blockindex", (int)it->first.txindex)); - delta.push_back(Pair("height", it->first.blockHeight)); - delta.push_back(Pair("address", address)); - deltas.push_back(delta); - } - - UniValue result(UniValue::VOBJ); - - if (includeChainInfo && start > 0 && end > 0) { - LOCK(cs_main); - - if (start > chainActive.Height() || end > chainActive.Height()) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Start or end is outside chain range"); - } - - CBlockIndex* startIndex = chainActive[start]; - CBlockIndex* endIndex = chainActive[end]; - - UniValue startInfo(UniValue::VOBJ); - UniValue endInfo(UniValue::VOBJ); - - startInfo.push_back(Pair("hash", startIndex->GetBlockHash().GetHex())); - startInfo.push_back(Pair("height", start)); - - endInfo.push_back(Pair("hash", endIndex->GetBlockHash().GetHex())); - endInfo.push_back(Pair("height", end)); - - result.push_back(Pair("deltas", deltas)); - result.push_back(Pair("start", startInfo)); - result.push_back(Pair("end", endInfo)); - - return result; - } else { - return deltas; - } -} - -UniValue getaddressbalance(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "getaddressbalance\n" - "\nReturns the balance for an address(es) (requires addressindex to be enabled).\n" - "\nArguments:\n" - "{\n" - " \"addresses\"\n" - " [\n" - " \"address\" (string) The base58check encoded address\n" - " ,...\n" - " ]\n" - "}\n" - "\nResult:\n" - "{\n" - " \"balance\" (string) The current balance in satoshis\n" - " \"received\" (string) The total number of satoshis received (including change)\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("getaddressbalance", "'{\"addresses\": [\"RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87\"]}'") - + HelpExampleRpc("getaddressbalance", "{\"addresses\": [\"RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87\"]}") - ); - - std::vector > addresses; - - if (!getAddressesFromParams(params, addresses)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); - } - - std::vector > addressIndex; - - for (std::vector >::iterator it = addresses.begin(); it != addresses.end(); it++) { - if (!GetAddressIndex((*it).first, (*it).second, addressIndex)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address"); - } - } - - CAmount balance = 0; - CAmount received = 0; - - for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) { - if (it->second > 0) { - received += it->second; - } - balance += it->second; - } - - UniValue result(UniValue::VOBJ); - result.push_back(Pair("balance", balance)); - result.push_back(Pair("received", received)); - - return result; - -} - -UniValue komodo_snapshot(int top); - -UniValue getsnapshot(const UniValue& params, bool fHelp) -{ - UniValue result(UniValue::VOBJ); int64_t total; int32_t top = 0; - - if (params.size() > 0 && !params[0].isNull()) { - top = atoi(params[0].get_str().c_str()); - if (top <= 0) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, top must be a positive integer"); - } - - if ( fHelp || params.size() > 1) - { - throw runtime_error( - "getsnapshot\n" - "\nReturns a snapshot of (address,amount) pairs at current height (requires addressindex to be enabled).\n" - "\nArguments:\n" - " \"top\" (number, optional) Only return this many addresses, i.e. top N richlist\n" - "\nResult:\n" - "{\n" - " \"addresses\": [\n" - " {\n" - " \"addr\": \"RMEBhzvATA8mrfVK82E5TgPzzjtaggRGN3\",\n" - " \"amount\": \"100.0\"\n" - " },\n" - " {\n" - " \"addr\": \"RqEBhzvATAJmrfVL82E57gPzzjtaggR777\",\n" - " \"amount\": \"23.45\"\n" - " }\n" - " ],\n" - " \"total\": 123.45 (numeric) Total amount in snapshot\n" - " \"average\": 61.7, (numeric) Average amount in each address \n" - " \"utxos\": 14, (number) Total number of UTXOs in snapshot\n" - " \"total_addresses\": 2, (number) Total number of addresses in snapshot,\n" - " \"start_height\": 91, (number) Block height snapshot began\n" - " \"ending_height\": 91 (number) Block height snapsho finished,\n" - " \"start_time\": 1531982752, (number) Unix epoch time snapshot started\n" - " \"end_time\": 1531982752 (number) Unix epoch time snapshot finished\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("getsnapshot","") - + HelpExampleRpc("getsnapshot", "1000") - ); - } - result = komodo_snapshot(top); - if ( result.size() > 0 ) { - result.push_back(Pair("end_time", (int) time(NULL))); - } else { - result.push_back(Pair("error", "no addressindex")); - } - return(result); -} - -UniValue getaddresstxids(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "getaddresstxids\n" - "\nReturns the txids for an address(es) (requires addressindex to be enabled).\n" - "\nArguments:\n" - "{\n" - " \"addresses\"\n" - " [\n" - " \"address\" (string) The base58check encoded address\n" - " ,...\n" - " ]\n" - " \"start\" (number) The start block height\n" - " \"end\" (number) The end block height\n" - "}\n" - "\nResult:\n" - "[\n" - " \"transactionid\" (string) The transaction id\n" - " ,...\n" - "]\n" - "\nExamples:\n" - + HelpExampleCli("getaddresstxids", "'{\"addresses\": [\"RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87\"]}'") - + HelpExampleRpc("getaddresstxids", "{\"addresses\": [\"RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87\"]}") - ); - - std::vector > addresses; - - if (!getAddressesFromParams(params, addresses)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); - } - - int start = 0; - int end = 0; - if (params[0].isObject()) { - UniValue startValue = find_value(params[0].get_obj(), "start"); - UniValue endValue = find_value(params[0].get_obj(), "end"); - if (startValue.isNum() && endValue.isNum()) { - start = startValue.get_int(); - end = endValue.get_int(); - } - } - - std::vector > addressIndex; - - for (std::vector >::iterator it = addresses.begin(); it != addresses.end(); it++) { - if (start > 0 && end > 0) { - if (!GetAddressIndex((*it).first, (*it).second, addressIndex, start, end)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address"); - } - } else { - if (!GetAddressIndex((*it).first, (*it).second, addressIndex)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address"); - } - } - } - - std::set > txids; - UniValue result(UniValue::VARR); - - for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) { - int height = it->first.blockHeight; - std::string txid = it->first.txhash.GetHex(); - - if (addresses.size() > 1) { - txids.insert(std::make_pair(height, txid)); - } else { - if (txids.insert(std::make_pair(height, txid)).second) { - result.push_back(txid); - } - } - } - - if (addresses.size() > 1) { - for (std::set >::const_iterator it=txids.begin(); it!=txids.end(); it++) { - result.push_back(it->second); - } - } - - return result; - -} - -UniValue getspentinfo(const UniValue& params, bool fHelp) -{ - - if (fHelp || params.size() != 1 || !params[0].isObject()) - throw runtime_error( - "getspentinfo\n" - "\nReturns the txid and index where an output is spent.\n" - "\nArguments:\n" - "{\n" - " \"txid\" (string) The hex string of the txid\n" - " \"index\" (number) The start block height\n" - "}\n" - "\nResult:\n" - "{\n" - " \"txid\" (string) The transaction id\n" - " \"index\" (number) The spending input index\n" - " ,...\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("getspentinfo", "'{\"txid\": \"0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9\", \"index\": 0}'") - + HelpExampleRpc("getspentinfo", "{\"txid\": \"0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9\", \"index\": 0}") - ); - - UniValue txidValue = find_value(params[0].get_obj(), "txid"); - UniValue indexValue = find_value(params[0].get_obj(), "index"); - - if (!txidValue.isStr() || !indexValue.isNum()) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid txid or index"); - } - - uint256 txid = ParseHashV(txidValue, "txid"); - int outputIndex = indexValue.get_int(); - - CSpentIndexKey key(txid, outputIndex); - CSpentIndexValue value; - - if (!GetSpentIndex(key, value)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to get spent info"); - } - - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("txid", value.txid.GetHex())); - obj.push_back(Pair("index", (int)value.inputIndex)); - obj.push_back(Pair("height", value.blockHeight)); - - return obj; -}