// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Copyright (c) 2016-2024 The Hush developers
// Distributed under the GPLv3 software license, see the accompanying
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
/******************************************************************************
* Copyright © 2014 - 2019 The SuperNET Developers . *
* *
* See the AUTHORS , DEVELOPER - AGREEMENT and LICENSE files at *
* the top - level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing . *
* *
* Unless otherwise agreed in a custom licensing agreement , no part of the *
* SuperNET software , including this file may be copied , modified , propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "clientversion.h"
# include "init.h"
# include "key_io.h"
# include "main.h"
# include "net.h"
# include "netbase.h"
# include "rpc/server.h"
# include "timedata.h"
# include "txmempool.h"
# include "util.h"
# include "cc/eval.h"
# include "cc/CCinclude.h"
# ifdef ENABLE_WALLET
# include "wallet/wallet.h"
# include "wallet/walletdb.h"
# endif
# include <stdint.h>
# include <boost/assign/list_of.hpp>
# include <univalue.h>
# include "zcash/Address.hpp"
//#ifdef HAVE_BUILD_INFO
//#include "build.h"
//#endif
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 hush_longestchain ( ) ;
int32_t hush_notarized_height ( int32_t * prevMoMheightp , uint256 * hashp , uint256 * txidp ) ;
bool hush_txnotarizedconfirmed ( uint256 txid ) ;
uint32_t hush_chainactive_timestamp ( ) ;
int32_t hush_whoami ( char * pubkeystr , int32_t height , uint32_t timestamp ) ;
extern int32_t HUSH_LASTMINED , HUSH_LONGESTCHAIN , IS_HUSH_NOTARY , HUSH_INSYNC ;
extern char SMART_CHAIN_SYMBOL [ HUSH_SMART_CHAIN_MAXLEN ] ;
uint32_t hush_segid32 ( char * coinaddr ) ;
int64_t hush_coinsupply ( int64_t * zfundsp , int32_t height ) ;
int32_t notarizedtxid_height ( char * dest , char * txidstr , int32_t * hushnotarized_heightp ) ;
uint64_t hush_notarypayamount ( int32_t nHeight , int64_t notarycount ) ;
int32_t hush_notaries ( uint8_t pubkeys [ 64 ] [ 33 ] , int32_t height , uint32_t timestamp ) ;
extern uint16_t ASSETCHAINS_P2PPORT , ASSETCHAINS_RPCPORT ;
extern uint32_t ASSETCHAINS_CC ;
extern uint32_t ASSETCHAINS_MAGIC , ASSETCHAINS_ALGO ;
extern uint64_t ASSETCHAINS_COMMISSION , ASSETCHAINS_SUPPLY ;
extern int32_t ASSETCHAINS_SAPLING ;
extern uint64_t ASSETCHAINS_ENDSUBSIDY [ ] , ASSETCHAINS_REWARD [ ] , ASSETCHAINS_HALVING [ ] , ASSETCHAINS_DECAY [ ] , ASSETCHAINS_NOTARY_PAY [ ] ;
extern std : : string NOTARY_PUBKEY , NOTARY_ADDRESS ; extern uint8_t NOTARY_PUBKEY33 [ ] ;
//TODO: use non-staked eras
// Currently HUSH only uses block heights to define eras
int32_t getera ( int timestamp )
{
return ( 0 ) ;
}
UniValue getdragonjson ( const UniValue & params , bool fHelp , const CPubKey & mypk )
{
if ( fHelp | | params . size ( ) ! = 0 )
throw runtime_error ( " getdragonjson \n returns json for dragon, 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(dragonSeeds[i][0]);
}
// get all current notaries
for ( int8_t i = 0 ; i < NUM_HUSH_NOTARIES ; i + + ) {
UniValue notary ( UniValue : : VOBJ ) ;
notary . push_back ( notaries_list [ era ] [ i ] [ 0 ] ) ;
notaries . push_back ( notary ) ;
}
// TODO: should be a config param
int minsigs = 13 ;
int BTCminsigs = 13 ;
int dragonPort = 5555 ;
json . push_back ( Pair ( " port " , dragonPort ) ) ;
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 , const CPubKey & mypk )
{
if ( fHelp | | params . size ( ) > 1 )
throw runtime_error (
" getnotarysendmany \n "
" Returns a sendmany JSON array with all current notaries Raddress's. \n "
" \n Examples: \n "
+ HelpExampleCli ( " getnotarysendmany " , " 10 " )
+ HelpExampleRpc ( " getnotarysendmany " , " 10 " )
) ;
int amount = 0 ;
if ( params . size ( ) = = 1 ) {
amount = params [ 0 ] . get_int ( ) ;
}
//TODO: this is broke
int era = getera ( time ( NULL ) ) ;
UniValue ret ( UniValue : : VOBJ ) ;
for ( int i = 0 ; i < NUM_HUSH_NOTARIES ; i + + )
{
char Raddress [ 18 ] ; uint8_t pubkey33 [ 33 ] ;
decode_hex ( pubkey33 , 33 , ( char * ) notaries_list [ era ] [ i ] [ 1 ] ) ;
pubkey2addr ( ( char * ) Raddress , ( uint8_t * ) pubkey33 ) ;
ret . push_back ( Pair ( Raddress , amount ) ) ;
}
return ret ;
}
UniValue geterablockheights ( const UniValue & params , bool fHelp , const CPubKey & mypk )
{
if ( fHelp | | params . size ( ) ! = 0 )
throw runtime_error (
" geterablockheights \n "
" Returns a JSON object with the first block in each era. \n "
) ;
CBlockIndex * pindex ; int8_t lastera , era = 0 ; UniValue ret ( UniValue : : VOBJ ) ;
for ( size_t i = 1 ; i < chainActive . LastTip ( ) - > GetHeight ( ) ; i + + )
{
pindex = chainActive [ i ] ;
era = getera ( pindex - > nTime ) + 1 ;
if ( era > lastera )
{
char str [ 16 ] ;
sprintf ( str , " %d " , era ) ;
ret . push_back ( Pair ( str , ( int64_t ) i ) ) ;
lastera = era ;
}
}
return ( ret ) ;
}
extern int getWorkQueueDepth ( ) ;
extern int getWorkQueueMaxDepth ( ) ;
extern int getWorkQueueNumThreads ( ) ;
UniValue rpcinfo ( const UniValue & params , bool fHelp , const CPubKey & mypk )
{
UniValue result ( UniValue : : VOBJ ) ;
if ( fHelp | | params . size ( ) ! = 0 ) {
throw runtime_error (
" rpcinfo \n "
" Returns an object containing various RPC state info. \n "
) ;
}
LOCK ( cs_main ) ;
int depth = getWorkQueueDepth ( ) ;
result . push_back ( Pair ( " work_queue_depth " , depth ) ) ;
result . push_back ( Pair ( " work_queue_max_depth " , getWorkQueueMaxDepth ( ) ) ) ;
result . push_back ( Pair ( " work_queue_num_threads " , getWorkQueueNumThreads ( ) ) ) ;
return result ;
}
UniValue getinfo ( const UniValue & params , bool fHelp , const CPubKey & mypk )
{
uint256 notarized_hash , notarized_desttxid ; int32_t prevMoMheight , notarized_height , longestchain , hushnotarized_height , txid_height ;
if ( fHelp | | params . size ( ) ! = 0 )
throw runtime_error (
" getinfo \n "
" Returns an object containing various state info. \n "
" \n Result: \n "
" { \n "
" \" version \" : xxxxx, (numeric) the server version \n "
" \" protocolversion \" : xxxxx, (numeric) the protocol version \n "
" \" walletversion \" : xxxxx, (numeric) the wallet version \n "
" \" balance \" : xxxxxxx, (numeric) the total Hush balance of the wallet \n "
" \" blocks \" : xxxxxx, (numeric) the current number of blocks processed in the server \n "
" \" timeoffset \" : xxxxx, (numeric) the time offset (deprecated, always 0) \n "
" \" connections \" : xxxxx, (numeric) the number of plaintext connections \n "
" \" tls_connections \" : xxxxx, (numeric) the number of encrypted TLS (SSL) connections \n "
" \" proxy \" : \" host:port \" , (string, optional) the proxy used by the server \n "
" \" difficulty \" : xxxxxx, (numeric) the current difficulty \n "
" \" testnet \" : true|false, (boolean) if the server is using testnet or not \n "
" \" keypoololdest \" : xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool \n "
" \" keypoolsize \" : xxxx, (numeric) how many new keys are pre-generated \n "
" \" unlocked_until \" : ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked \n "
" \" paytxfee \" : x.xxxx, (numeric) the transaction fee set in " + CURRENCY_UNIT + " /kB \n "
" \" relayfee \" : x.xxxx, (numeric) minimum relay fee for non-free transactions in " + CURRENCY_UNIT + " /kB \n "
" \" errors \" : \" ... \" (string) any error messages \n "
" } \n "
" \n Examples: \n "
+ HelpExampleCli ( " getinfo " , " " )
+ HelpExampleRpc ( " getinfo " , " " )
) ;
//#ifdef ENABLE_WALLET
// LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
//#else
LOCK ( cs_main ) ;
//#endif
proxyType proxy ;
GetProxy ( NET_IPV4 , proxy ) ;
notarized_height = hush_notarized_height ( & prevMoMheight , & notarized_hash , & notarized_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 ( " synced " , HUSH_INSYNC ! = 0 ) ) ;
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 ( ) ) ) ;
if ( HUSH_NSPV_FULLNODE )
{
txid_height = notarizedtxid_height ( ( char * ) " HUSH3 " , ( char * ) notarized_desttxid . ToString ( ) . c_str ( ) , & hushnotarized_height ) ;
if ( txid_height > 0 )
obj . push_back ( Pair ( " notarizedtxid_height " , txid_height ) ) ;
else obj . push_back ( Pair ( " notarizedtxid_height " , " mempool " ) ) ;
if ( SMART_CHAIN_SYMBOL [ 0 ] ! = 0 ) {
obj . push_back ( Pair ( " HUSHnotarized_height " , hushnotarized_height ) ) ;
}
obj . push_back ( Pair ( " notarized_confirms " , txid_height < hushnotarized_height ? ( hushnotarized_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 ( ) ) ) ;
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 = HUSH_LONGESTCHAIN ) ! = 0 & & chainActive . Height ( ) > longestchain )
longestchain = chainActive . Height ( ) ;
//fprintf(stderr,"after longestchain %u\n",(uint32_t)time(NULL));
obj . push_back ( Pair ( " longestchain " , longestchain ) ) ;
if ( chainActive . LastTip ( ) ! = 0 )
obj . push_back ( Pair ( " tiptime " , ( int ) chainActive . LastTip ( ) - > nTime ) ) ;
obj . push_back ( Pair ( " difficulty " , ( double ) GetDifficulty ( ) ) ) ;
# 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 ( " sapling " , ASSETCHAINS_SAPLING ) ) ;
}
//obj.push_back(Pair("build_date", BUILD_DATE));
obj . push_back ( Pair ( " timeoffset " , 0 ) ) ;
obj . push_back ( Pair ( " connections " , ( int ) vNodes . size ( ) ) ) ;
obj . push_back ( Pair ( " tls_connections " , ( int ) std : : count_if ( vNodes . begin ( ) , vNodes . end ( ) , [ ] ( CNode * n ) { return n - > ssl ! = NULL ; } ) ) ) ;
obj . push_back ( Pair ( " proxy " , ( proxy . IsValid ( ) ? proxy . proxy . ToStringIPPort ( ) : string ( ) ) ) ) ;
obj . push_back ( Pair ( " testnet " , Params ( ) . TestnetToBeDeprecatedFieldRPC ( ) ) ) ;
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 = hush_whoami ( pubkeystr , ( int32_t ) chainActive . LastTip ( ) - > GetHeight ( ) , hush_chainactive_timestamp ( ) ) ) > = 0 ) {
obj . push_back ( Pair ( " notaryid " , notaryid ) ) ;
if ( HUSH_LASTMINED ! = 0 )
obj . push_back ( Pair ( " lastmined " , HUSH_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 " , SMART_CHAIN_SYMBOL [ 0 ] = = 0 ? " HUSH " : SMART_CHAIN_SYMBOL ) ) ;
obj . push_back ( Pair ( " p2pport " , ASSETCHAINS_P2PPORT ) ) ;
obj . push_back ( Pair ( " rpcport " , ASSETCHAINS_RPCPORT ) ) ;
if ( SMART_CHAIN_SYMBOL [ 0 ] ! = 0 )
{
//obj.push_back(Pair("name", SMART_CHAIN_SYMBOL));
obj . push_back ( Pair ( " magic " , ( int ) ASSETCHAINS_MAGIC ) ) ;
obj . push_back ( Pair ( " premine " , ASSETCHAINS_SUPPLY ) ) ;
if ( ASSETCHAINS_REWARD [ 0 ] ! = 0 | | ASSETCHAINS_LASTERA > 0 )
{
std : : string acReward = " " , acHalving = " " , acDecay = " " , acEndSubsidy = " " , acNotaryPay = " " ;
for ( int i = 0 ; i < = ASSETCHAINS_LASTERA ; i + + )
{
if ( i = = 0 )
{
acReward = std : : to_string ( ASSETCHAINS_REWARD [ i ] ) ;
acHalving = std : : to_string ( ASSETCHAINS_HALVING [ i ] ) ;
acDecay = std : : to_string ( ASSETCHAINS_DECAY [ i ] ) ;
acEndSubsidy = std : : to_string ( ASSETCHAINS_ENDSUBSIDY [ i ] ) ;
acNotaryPay = std : : to_string ( ASSETCHAINS_NOTARY_PAY [ i ] ) ;
} else {
acReward + = " , " + std : : to_string ( ASSETCHAINS_REWARD [ i ] ) ;
acHalving + = " , " + std : : to_string ( ASSETCHAINS_HALVING [ i ] ) ;
acDecay + = " , " + std : : to_string ( ASSETCHAINS_DECAY [ i ] ) ;
acEndSubsidy + = " , " + std : : to_string ( ASSETCHAINS_ENDSUBSIDY [ i ] ) ;
acNotaryPay + = " , " + std : : to_string ( ASSETCHAINS_NOTARY_PAY [ i ] ) ;
}
}
if ( ASSETCHAINS_LASTERA > 0 )
obj . push_back ( Pair ( " eras " , ( int64_t ) ( ASSETCHAINS_LASTERA + 1 ) ) ) ;
obj . push_back ( Pair ( " reward " , acReward ) ) ;
obj . push_back ( Pair ( " halving " , acHalving ) ) ;
obj . push_back ( Pair ( " decay " , acDecay ) ) ;
obj . push_back ( Pair ( " endsubsidy " , acEndSubsidy ) ) ;
obj . push_back ( Pair ( " notarypay " , acNotaryPay ) ) ;
}
if ( ASSETCHAINS_COMMISSION ! = 0 )
obj . push_back ( Pair ( " commission " , ASSETCHAINS_COMMISSION ) ) ;
if ( ASSETCHAINS_ALGO = = ASSETCHAINS_EQUIHASH ) {
uint64_t N = ASSETCHAINS_NK [ 0 ] ? ASSETCHAINS_NK [ 0 ] : 200 ;
uint64_t K = ASSETCHAINS_NK [ 1 ] ? ASSETCHAINS_NK [ 1 ] : 9 ;
std : : string equihash_algo = " equihash ( " + std : : to_string ( N ) + " , " + std : : to_string ( K ) + " ) " ;
obj . push_back ( Pair ( " algo " , equihash_algo ) ) ;
} else {
obj . push_back ( Pair ( " algo " , ASSETCHAINS_ALGORITHMS [ ASSETCHAINS_ALGO ] ) ) ;
}
}
return obj ;
}
# ifdef ENABLE_WALLET
class DescribeAddressVisitor : public boost : : static_visitor < UniValue >
{
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 ) ) ) ; // should return pubkeyhash, but not sure about compatibility impact
obj . push_back ( Pair ( " iscompressed " , vchPubKey . IsCompressed ( ) ) ) ;
}
return obj ;
}
UniValue operator ( ) ( const CPubKey & key ) const {
UniValue obj ( UniValue : : VOBJ ) ;
obj . push_back ( Pair ( " isscript " , false ) ) ;
if ( pwalletMain & & key . IsValid ( ) ) {
obj . push_back ( Pair ( " pubkey " , HexStr ( key ) ) ) ;
obj . push_back ( Pair ( " iscompressed " , key . IsCompressed ( ) ) ) ;
}
else
{
obj . push_back ( Pair ( " pubkey " , " invalid " ) ) ;
}
return obj ;
}
UniValue operator ( ) ( const CScriptID & scriptID ) const {
UniValue obj ( UniValue : : VOBJ ) ;
Return all available information via validateaddress
`"validateaddress"` omits some information, even in cases where is it available.
The primary motivation is to be able to retrieve redeemScripts, after using `"addmultisigaddress"`, when not all keys are available in the keystore, but the redeemScript actually is.
The output of `"validateaddress"` with this commit:
Keys not available:
```js
validateaddress "n4KWZKx349gdMQGgTnZ8W6WfgSwybkGSK3"
{
"isvalid": true,
"address": "n4KWZKx349gdMQGgTnZ8W6WfgSwybkGSK3",
"scriptPubKey": "76a914fa20d564550b105787f7ce3a9ad7fd9a45cd407088ac",
"ismine": false,
"iswatchonly": false,
"isscript": false
}
```
```js
validateaddress "2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK"
{
"isvalid": true,
"address": "2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK",
"scriptPubKey": "a9146769c19a16c9400b908756e19a4d2afb9e9760e187",
"ismine": false,
"iswatchonly": false,
"isscript": true
}
```
After adding the redeemScript:
```js
addmultisigaddress 2 '["02537357B156A33306A7A014A3748631C59DF405B56F11BA4AA4A3CE81501AF095","02F1FB200390E7864EF4450C07B15988179A57C3CF3A878F668E1070CB615749FE"]'
2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK
validateaddress "2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK"
{
"isvalid": true,
"address": "2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK",
"scriptPubKey": "a9146769c19a16c9400b908756e19a4d2afb9e9760e187",
"ismine": false,
"iswatchonly": false,
"isscript": true,
"script": "multisig",
"hex": "522102537357b156a33306a7a014a3748631c59df405b56f11ba4aa4a3ce81501af0952102f1fb200390e7864ef4450c07b15988179a57c3cf3a878f668e1070cb615749fe52ae",
"addresses": [
"n4KWZKx349gdMQGgTnZ8W6WfgSwybkGSK3",
"mmSKNtbYYHRrhTLKiok5TuYrGEs4Y2A4k6"
],
"sigsrequired": 2,
"account": ""
}
```
All keys available:
```js
validateaddress "n4KWZKx349gdMQGgTnZ8W6WfgSwybkGSK3"
{
"isvalid": true,
"address": "n4KWZKx349gdMQGgTnZ8W6WfgSwybkGSK3",
"scriptPubKey": "76a914fa20d564550b105787f7ce3a9ad7fd9a45cd407088ac",
"ismine": true,
"iswatchonly": false,
"isscript": false,
"pubkey": "02537357b156a33306a7a014a3748631c59df405b56f11ba4aa4a3ce81501af095",
"iscompressed": true,
"account": ""
}
```
```js
validateaddress "2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK"
{
"isvalid": true,
"address": "2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK",
"scriptPubKey": "a9146769c19a16c9400b908756e19a4d2afb9e9760e187",
"ismine": true,
"iswatchonly": false,
"isscript": true,
"script": "multisig",
"hex": "522102537357b156a33306a7a014a3748631c59df405b56f11ba4aa4a3ce81501af0952102f1fb200390e7864ef4450c07b15988179a57c3cf3a878f668e1070cb615749fe52ae",
"addresses": [
"n4KWZKx349gdMQGgTnZ8W6WfgSwybkGSK3",
"mmSKNtbYYHRrhTLKiok5TuYrGEs4Y2A4k6"
],
"sigsrequired": 2,
"account": ""
}
```
9 years ago
CScript subscript ;
obj . push_back ( Pair ( " isscript " , true ) ) ;
if ( pwalletMain & & pwalletMain - > GetCScript ( scriptID , subscript ) ) {
std : : vector < CTxDestination > 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 ) ;
for ( const CTxDestination & addr : addresses ) {
a . push_back ( EncodeDestination ( addr ) ) ;
}
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 , const CPubKey & mypk )
{
int32_t height = 0 ; int32_t currentHeight ; int64_t blocks_per_year , zf1 , zf3 , zf12 , zfunds , supply1 , supply3 , supply12 , supply = 0 ; UniValue result ( UniValue : : VOBJ ) ;
if ( fHelp | | params . size ( ) > 1 )
throw runtime_error ( " coinsupply <height> \n "
" \n Return coin supply information at a given block height. If no height is given, the current height is used. \n "
" \n Arguments: \n "
" 1. \" height \" (integer, optional) Block height \n "
" \n Result: \n "
" { \n "
" \" result \" : \" success \" , (string) If the request was successful. \n "
" \" coin \" : \" HUSH3 \" , (string) The currency symbol of the coin for asset chains, otherwise HUSH3. \n "
" \" height \" : 420, (integer) The height of this coin supply data \n "
" \" supply \" : \" 555.0 \" , (float) The transparent coin supply \n "
" \" zfunds \" : \" 0.55555 \" , (float) The shielded coin supply (in zaddrs) \n "
" \" total \" : \" 555.55555 \" , (float) The total coin supply, i.e. sum of supply + zfunds \n "
" } \n "
" \n Examples: \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 = hush_coinsupply ( & zfunds , height ) ) > 0 )
{
result . push_back ( Pair ( " result " , " success " ) ) ;
result . push_back ( Pair ( " coin " , SMART_CHAIN_SYMBOL [ 0 ] = = 0 ? " HUSH " : SMART_CHAIN_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 ) ) ) ;
if ( ASSETCHAINS_BLOCKTIME > 0 )
{
blocks_per_year = 24 * 3600 * 365 / ASSETCHAINS_BLOCKTIME ;
if ( height > blocks_per_year )
{
supply1 = hush_coinsupply ( & zf1 , height - blocks_per_year / 12 ) ;
supply3 = hush_coinsupply ( & zf3 , height - blocks_per_year / 4 ) ;
supply12 = hush_coinsupply ( & zf12 , height - blocks_per_year ) ;
if ( supply1 ! = 0 & & supply3 ! = 0 & & supply12 ! = 0 )
{
result . push_back ( Pair ( " lastmonth " , ValueFromAmount ( supply1 + zf1 ) ) ) ;
result . push_back ( Pair ( " monthcoins " , ValueFromAmount ( zfunds + supply - supply1 - zf1 ) ) ) ;
result . push_back ( Pair ( " lastquarter " , ValueFromAmount ( supply3 + zf3 ) ) ) ;
result . push_back ( Pair ( " quartercoins " , ValueFromAmount ( zfunds + supply - supply3 - zf3 ) ) ) ;
result . push_back ( Pair ( " lastyear " , ValueFromAmount ( supply12 + zf12 ) ) ) ;
result . push_back ( Pair ( " yearcoins " , ValueFromAmount ( zfunds + supply - supply12 - zf12 ) ) ) ;
result . push_back ( Pair ( " inflation " , 100. * ( ( ( double ) ( zfunds + supply ) / ( supply12 + zf12 ) ) - 1. ) ) ) ;
result . push_back ( Pair ( " blocksperyear " , ( int64_t ) blocks_per_year ) ) ;
}
}
}
} else result . push_back ( Pair ( " error " , " couldnt calculate supply " ) ) ;
} else {
result . push_back ( Pair ( " error " , " invalid height " ) ) ;
}
return ( result ) ;
}
UniValue validateaddress ( const UniValue & params , bool fHelp , const CPubKey & mypk )
{
if ( fHelp | | params . size ( ) ! = 1 )
throw runtime_error (
" validateaddress \" addr \" \n "
" \n Return information about the given Hush or Hush Arrakis Chain (HAC) address. \n "
" \n Arguments: \n "
" 1. \" addr \" (string, required) The address to validate \n "
" \n Result: \n "
" { \n "
" \" isvalid \" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned. \n "
" \" address \" : \" addr \" , (string) The Hush or HSC 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 "
" \n Examples: \n "
+ HelpExampleCli ( " validateaddress " , " \" RTZMZHDFSTFQst8XmX2dR4DaH87cEUlulz \" " )
+ HelpExampleRpc ( " validateaddress " , " \" RTZMZHDFSTFQst8XmX2dR4DaH87cEUlulz \" " )
) ;
# ifdef ENABLE_WALLET
LOCK2 ( cs_main , pwalletMain ? & pwalletMain - > cs_wallet : NULL ) ;
# else
LOCK ( cs_main ) ;
# endif
CTxDestination dest = DecodeDestination ( params [ 0 ] . get_str ( ) ) ;
bool isValid = IsValidDestination ( dest ) ;
UniValue ret ( UniValue : : VOBJ ) ;
ret . push_back ( Pair ( " isvalid " , isValid ) ) ;
if ( isValid )
{
std : : string currentAddress = EncodeDestination ( dest ) ;
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 ) hush_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 ) ) ;
Return all available information via validateaddress
`"validateaddress"` omits some information, even in cases where is it available.
The primary motivation is to be able to retrieve redeemScripts, after using `"addmultisigaddress"`, when not all keys are available in the keystore, but the redeemScript actually is.
The output of `"validateaddress"` with this commit:
Keys not available:
```js
validateaddress "n4KWZKx349gdMQGgTnZ8W6WfgSwybkGSK3"
{
"isvalid": true,
"address": "n4KWZKx349gdMQGgTnZ8W6WfgSwybkGSK3",
"scriptPubKey": "76a914fa20d564550b105787f7ce3a9ad7fd9a45cd407088ac",
"ismine": false,
"iswatchonly": false,
"isscript": false
}
```
```js
validateaddress "2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK"
{
"isvalid": true,
"address": "2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK",
"scriptPubKey": "a9146769c19a16c9400b908756e19a4d2afb9e9760e187",
"ismine": false,
"iswatchonly": false,
"isscript": true
}
```
After adding the redeemScript:
```js
addmultisigaddress 2 '["02537357B156A33306A7A014A3748631C59DF405B56F11BA4AA4A3CE81501AF095","02F1FB200390E7864EF4450C07B15988179A57C3CF3A878F668E1070CB615749FE"]'
2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK
validateaddress "2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK"
{
"isvalid": true,
"address": "2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK",
"scriptPubKey": "a9146769c19a16c9400b908756e19a4d2afb9e9760e187",
"ismine": false,
"iswatchonly": false,
"isscript": true,
"script": "multisig",
"hex": "522102537357b156a33306a7a014a3748631c59df405b56f11ba4aa4a3ce81501af0952102f1fb200390e7864ef4450c07b15988179a57c3cf3a878f668e1070cb615749fe52ae",
"addresses": [
"n4KWZKx349gdMQGgTnZ8W6WfgSwybkGSK3",
"mmSKNtbYYHRrhTLKiok5TuYrGEs4Y2A4k6"
],
"sigsrequired": 2,
"account": ""
}
```
All keys available:
```js
validateaddress "n4KWZKx349gdMQGgTnZ8W6WfgSwybkGSK3"
{
"isvalid": true,
"address": "n4KWZKx349gdMQGgTnZ8W6WfgSwybkGSK3",
"scriptPubKey": "76a914fa20d564550b105787f7ce3a9ad7fd9a45cd407088ac",
"ismine": true,
"iswatchonly": false,
"isscript": false,
"pubkey": "02537357b156a33306a7a014a3748631c59df405b56f11ba4aa4a3ce81501af095",
"iscompressed": true,
"account": ""
}
```
```js
validateaddress "2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK"
{
"isvalid": true,
"address": "2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK",
"scriptPubKey": "a9146769c19a16c9400b908756e19a4d2afb9e9760e187",
"ismine": true,
"iswatchonly": false,
"isscript": true,
"script": "multisig",
"hex": "522102537357b156a33306a7a014a3748631c59df405b56f11ba4aa4a3ce81501af0952102f1fb200390e7864ef4450c07b15988179a57c3cf3a878f668e1070cb615749fe52ae",
"addresses": [
"n4KWZKx349gdMQGgTnZ8W6WfgSwybkGSK3",
"mmSKNtbYYHRrhTLKiok5TuYrGEs4Y2A4k6"
],
"sigsrequired": 2,
"account": ""
}
```
9 years ago
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 , const CPubKey & mypk )
{
if ( fHelp | | params . size ( ) ! = 1 )
throw runtime_error (
" z_validateaddress \" zaddr \" \n "
" \n Return information about the given z address. \n "
" \n Arguments: \n "
" 1. \" zaddr \" (string, required) The z address to validate \n "
" \n Result: \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 "
" \" type \" : \" xxxx \" , (string) \" sapling \" \n "
" \" ismine \" : true|false, (boolean) If the address is yours or not \n "
" \" diversifier \" : \" hex \" , (string) [sapling] The hex value of the diversifier, d \n "
" \" diversifiedtransmissionkey \" : \" hex \" , (string) [sapling] The hex value of pk_d \n "
" } \n "
" \n Examples: \n "
+ HelpExampleCli ( " z_validateaddress " , " \" zs1z7rejlpsa98s2rrrfkwmaxu53e4ue0ulcrw0h4x5g8jl04tak0d3mm47vdtahatqrlkngh9slya \" " )
+ HelpExampleRpc ( " z_validateaddress " , " \" zs1z7rejlpsa98s2rrrfkwmaxu53e4ue0ulcrw0h4x5g8jl04tak0d3mm47vdtahatqrlkngh9slya \" " )
) ;
# ifdef ENABLE_WALLET
LOCK2 ( cs_main , pwalletMain - > cs_wallet ) ;
# else
LOCK ( cs_main ) ;
# endif
string strAddress = params [ 0 ] . get_str ( ) ;
auto address = DecodePaymentAddress ( strAddress ) ;
bool isValid = IsValidPaymentAddress ( address ) ;
UniValue ret ( UniValue : : VOBJ ) ;
ret . push_back ( Pair ( " isvalid " , isValid ) ) ;
auto zaddr = boost : : get < libzcash : : SaplingPaymentAddress > ( & address ) ;
if ( isValid & & ( zaddr ! = nullptr ) )
{
ret . push_back ( Pair ( " address " , strAddress ) ) ;
UniValue obj ( UniValue : : VOBJ ) ;
obj . push_back ( Pair ( " type " , " sapling " ) ) ;
obj . push_back ( Pair ( " diversifier " , HexStr ( zaddr - > d ) ) ) ;
obj . push_back ( Pair ( " diversifiedtransmissionkey " , zaddr - > pk_d . GetHex ( ) ) ) ;
# ifdef ENABLE_WALLET
if ( pwalletMain ) {
libzcash : : SaplingIncomingViewingKey ivk ;
libzcash : : SaplingFullViewingKey fvk ;
bool isMine = pwalletMain - > GetSaplingIncomingViewingKey ( * zaddr , ivk ) & &
pwalletMain - > GetSaplingFullViewingKey ( ivk , fvk ) & &
pwalletMain - > HaveSaplingSpendingKey ( fvk ) ;
obj . push_back ( Pair ( " ismine " , isMine ) ) ;
}
# endif
ret . pushKVs ( obj ) ;
}
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 \n Reduce the number " ) ;
std : : vector < CPubKey > 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:
CTxDestination dest = DecodeDestination ( ks ) ;
if ( pwalletMain & & IsValidDestination ( dest ) ) {
const CKeyID * keyID = boost : : get < CKeyID > ( & dest ) ;
if ( ! keyID ) {
throw std : : runtime_error ( strprintf ( " %s does not refer to a key " , ks ) ) ;
}
CPubKey vchPubKey ;
if ( ! pwalletMain - > GetPubKey ( * keyID , vchPubKey ) ) {
throw std : : 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 , const CPubKey & mypk )
{
if ( fHelp | | params . size ( ) < 2 | | params . size ( ) > 2 )
{
string msg = " createmultisig nrequired [ \" key \" ,...] \n "
" \n Creates a multi-signature address with n signature of m keys required. \n "
" It returns a json object with the address and redeemScript. \n "
" \n Arguments: \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 Hush addresses or hex-encoded public keys \n "
" [ \n "
" \" key \" (string) Hush address or hex-encoded public key \n "
" ,... \n "
" ] \n "
" \n Result: \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 "
" \n Examples: \n "
" \n Create a multisig address from 2 addresses \n "
+ HelpExampleCli ( " createmultisig " , " 2 \" [ \\ \" RTZMZHDFSTFQst8XmX2dR4DaH87cEUs3gC \\ \" , \\ \" RNKiEBduBru6Siv1cZRVhp4fkZNyPska6z \\ \" ] \" " ) +
" \n As 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 ) ;
UniValue result ( UniValue : : VOBJ ) ;
result . push_back ( Pair ( " address " , EncodeDestination ( innerID ) ) ) ;
result . push_back ( Pair ( " redeemScript " , HexStr ( inner . begin ( ) , inner . end ( ) ) ) ) ;
return result ;
}
UniValue verifymessage ( const UniValue & params , bool fHelp , const CPubKey & mypk )
{
if ( fHelp | | params . size ( ) ! = 3 )
throw runtime_error (
" verifymessage \" hushaddress \" \" signature \" \" message \" \n "
" \n Verify a signed message \n "
" \n Arguments: \n "
" 1. \" hushaddress \" (string, required) The Hush 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 "
" \n Result: \n "
" true|false (boolean) If the signature is verified or not. \n "
" \n Examples: \n "
" \n Unlock the wallet for 30 seconds \n "
+ HelpExampleCli ( " walletpassphrase " , " \" mypassphrase \" 30 " ) +
" \n Create the signature \n "
+ HelpExampleCli ( " signmessage " , " \" RNKiEBduBru6Siv1cZRVhp4fkZNyPska6z \" \" my message \" " ) +
" \n Verify the signature \n "
+ HelpExampleCli ( " verifymessage " , " \" RNKiEBduBru6Siv1cZRVhp4fkZNyPska6z \" \" signature \" \" my message \" " ) +
" \n As 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 ( ) ;
CTxDestination destination = DecodeDestination ( strAddress ) ;
if ( ! IsValidDestination ( destination ) ) {
throw JSONRPCError ( RPC_TYPE_ERROR , " Invalid address " ) ;
}
const CKeyID * keyID = boost : : get < CKeyID > ( & destination ) ;
if ( ! keyID ) {
throw JSONRPCError ( RPC_TYPE_ERROR , " Address does not refer to key " ) ;
}
bool fInvalid = false ;
vector < unsigned char > 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 , const CPubKey & mypk )
{
if ( fHelp | | params . size ( ) ! = 1 )
throw runtime_error (
" setmocktime timestamp \n "
" \n Set the local time to given timestamp (-regtest only) \n "
" \n Arguments: \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 if ( type = = 3 ) {
address = CBitcoinAddress ( CKeyID ( hash ) ) . ToString ( ) ;
} else {
return false ;
}
return true ;
}
bool getAddressesFromParams ( const UniValue & params , std : : vector < std : : pair < uint160 , int > > & addresses )
{
bool ccVout = false ;
if ( params . size ( ) = = 2 )
ccVout = true ;
if ( params [ 0 ] . isStr ( ) ) {
CBitcoinAddress address ( params [ 0 ] . get_str ( ) ) ;
uint160 hashBytes ;
int type = 0 ;
if ( ! address . GetIndexKey ( hashBytes , type , ccVout ) ) {
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 < UniValue > values = addressValues . getValues ( ) ;
for ( std : : vector < UniValue > : : iterator it = values . begin ( ) ; it ! = values . end ( ) ; + + it ) {
CBitcoinAddress address ( it - > get_str ( ) ) ;
uint160 hashBytes ;
int type = 0 ;
if ( ! address . GetIndexKey ( hashBytes , type , ccVout ) ) {
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 < CAddressUnspentKey , CAddressUnspentValue > a ,
std : : pair < CAddressUnspentKey , CAddressUnspentValue > b ) {
return a . second . blockHeight < b . second . blockHeight ;
}
bool timestampSort ( std : : pair < CMempoolAddressDeltaKey , CMempoolAddressDelta > a ,
std : : pair < CMempoolAddressDeltaKey , CMempoolAddressDelta > b ) {
return a . second . time < b . second . time ;
}
UniValue getaddressmempool ( const UniValue & params , bool fHelp , const CPubKey & mypk )
{
if ( fHelp | | params . size ( ) > 2 | | params . size ( ) = = 0 )
throw runtime_error (
" getaddressmempool \n "
" \n Returns all mempool deltas for an address (requires addressindex to be enabled). \n "
" \n Arguments: \n "
" { \n "
" \" addresses \" \n "
" [ \n "
" \" address \" (string) The base58check encoded address \n "
" ,... \n "
" ] \n "
" } \n "
" \n CCvout (optional) Return CCvouts instead of normal vouts \n "
" \n Result: \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 "
" \n Examples: \n "
+ HelpExampleCli ( " getaddressmempool " , " '{ \" addresses \" : [ \" RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87 \" ]}' (ccvout) " )
+ HelpExampleRpc ( " getaddressmempool " , " { \" addresses \" : [ \" RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87 \" ]} (ccvout) " )
) ;
std : : vector < std : : pair < uint160 , int > > addresses ;
if ( ! getAddressesFromParams ( params , addresses ) ) {
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Invalid address " ) ;
}
std : : vector < std : : pair < CMempoolAddressDeltaKey , CMempoolAddressDelta > > 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 < std : : pair < CMempoolAddressDeltaKey , CMempoolAddressDelta > > : : 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 , const CPubKey & mypk )
{
if ( fHelp | | params . size ( ) > 2 | | params . size ( ) = = 0 )
throw runtime_error (
" getaddressutxos \n "
" \n Returns all unspent outputs for an address (requires addressindex to be enabled). \n "
" \n Arguments: \n "
" { \n "
" \" addresses \" \n "
" [ \n "
" \" address \" (string) The base58check encoded address \n "
" ,... \n "
" ], \n "
" \" chainInfo \" (boolean) Include chain info with results \n "
" } \n "
" \n CCvout (optional) Return CCvouts instead of normal vouts \n "
" \n Result \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 "
" \n Examples: \n "
+ HelpExampleCli ( " getaddressutxos " , " '{ \" addresses \" : [ \" RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87 \" ]}' (ccvout) " )
+ HelpExampleRpc ( " getaddressutxos " , " { \" addresses \" : [ \" RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87 \" ]} (ccvout) " )
) ;
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 < std : : pair < uint160 , int > > addresses ;
if ( ! getAddressesFromParams ( params , addresses ) ) {
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Invalid address " ) ;
}
std : : vector < std : : pair < CAddressUnspentKey , CAddressUnspentValue > > unspentOutputs ;
for ( std : : vector < std : : pair < uint160 , int > > : : 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 < std : : pair < CAddressUnspentKey , CAddressUnspentValue > > : : 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 , const CPubKey & mypk )
{
if ( fHelp | | params . size ( ) > 2 | | params . size ( ) = = 0 | | ! params [ 0 ] . isObject ( ) )
throw runtime_error (
" getaddressdeltas \n "
" \n Returns all changes for an address (requires addressindex to be enabled). \n "
" \n Arguments: \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 "
" \n CCvout (optional) Return CCvouts instead of normal vouts \n "
" \n Result: \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 "
" \n Examples: \n "
+ HelpExampleCli ( " getaddressdeltas " , " '{ \" addresses \" : [ \" RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87 \" ]}' (ccvout) " )
+ HelpExampleRpc ( " getaddressdeltas " , " { \" addresses \" : [ \" RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87 \" ]} (ccvout) " )
) ;
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 < std : : pair < uint160 , int > > addresses ;
if ( ! getAddressesFromParams ( params , addresses ) ) {
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Invalid address " ) ;
}
std : : vector < std : : pair < CAddressIndexKey , CAmount > > addressIndex ;
for ( std : : vector < std : : pair < uint160 , int > > : : 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 < std : : pair < CAddressIndexKey , CAmount > > : : 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 ;
}
}
CAmount checkburnaddress ( CAmount & received , int64_t & nNotaryPay , int32_t & height , std : : string sAddress )
{
CBitcoinAddress address ( sAddress ) ;
uint160 hashBytes ; int type = 0 ; CAmount balance = 0 ;
if ( address . GetIndexKey ( hashBytes , type , false ) )
{
std : : vector < std : : pair < CAddressIndexKey , CAmount > > addressIndex ;
if ( GetAddressIndex ( hashBytes , type , addressIndex ) )
{
for ( std : : vector < std : : pair < CAddressIndexKey , CAmount > > : : const_iterator it = addressIndex . begin ( ) ; it ! = addressIndex . end ( ) ; it + + )
{
if ( it - > second > 0 )
received + = it - > second ;
balance + = it - > second ;
}
// Get notary pay from current chain tip
CBlockIndex * pindex = chainActive . LastTip ( ) ;
nNotaryPay = pindex - > nNotaryPay ;
height = pindex - > GetHeight ( ) ;
}
}
return balance ;
}
UniValue checknotarization ( const UniValue & params , bool fHelp , const CPubKey & mypk )
{
if ( fHelp | | params . size ( ) ! = 0 )
throw runtime_error (
" checknotarization \n "
" \n Returns true if burn address balance is greater than total notary pay. (requires addressindex to be enabled). \n "
) ;
UniValue result ( UniValue : : VOBJ ) ; CAmount balance = 0 , received = 0 ; int64_t nNotaryPay = 0 ; int32_t height ;
// helper to test burn address's
/*uint8_t priv[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t pub [ 33 ] = { 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ;
char coinaddr [ 64 ] ; uint8_t buf33 [ 33 ] ;
//pubkey2addr(coinaddr, pub);
priv2addr ( coinaddr , buf33 , priv ) ;
fprintf ( stderr , " what.%s \n " , coinaddr ) ;
result . push_back ( Pair ( " address " , coinaddr ) ) ;
return result ;
*/
if ( ASSETCHAINS_NOTARY_PAY [ 0 ] = = 0 )
throw runtime_error ( " only works for ac_notarypay chains " ) ;
// pubkey 020000000000000000000000000000000
balance = checkburnaddress ( received , nNotaryPay , height , " REDVp3ox1pbcWYCzySadfHhk8UU3HM4k5x " ) ;
if ( nNotaryPay > = balance | | received ! = balance )
return false ;
return true ;
}
UniValue getnotarypayinfo ( const UniValue & params , bool fHelp , const CPubKey & mypk )
{
if ( fHelp | | params . size ( ) ! = 0 )
throw runtime_error (
" getnotarypayinfo \n "
" \n Returns infomation about ac_notaypay status (requires addressindex to be enabled). \n "
" \n Result: \n "
" { \n "
" \" height \" (number) The current block height \n "
" \" balance \" (number) The current balance of the burn address \n "
" \" spent \" (bool) true if coins have been spent from the burn address \n "
" \" Total_NotaryPay \" (number) Total amount paid to notaries \n "
" \" Estimated_Notarizations_Left \" (number) the estimated amount of notarizations left before the balance is consumed \n "
" \" Estimated_Days_Left \" (number) the estimated amount of days the current balance will last \n "
" \" Estimated_Height \" (number) the estimated block height funds will run out \n "
" } \n "
) ;
if ( ASSETCHAINS_NOTARY_PAY [ 0 ] = = 0 )
throw runtime_error ( " only works for ac_notarypay chains " ) ;
UniValue result ( UniValue : : VOBJ ) ; CAmount balance = 0 , received = 0 ; int64_t TotalNotaryPay = 0 , NotaryPay , notaleft = 0 , daysleft = 0 , notarycount ; int32_t height , endheight = 0 ; uint8_t notarypubkeys [ 64 ] [ 33 ] = { 0 } ;
// pubkey 020000000000000000000000000000000
balance = checkburnaddress ( received , TotalNotaryPay , height , " REDVp3ox1pbcWYCzySadfHhk8UU3HM4k5x " ) ;
notarycount = hush_notaries ( notarypubkeys , height , chainActive [ height ] - > GetBlockTime ( ) ) ;
NotaryPay = hush_notarypayamount ( height , notarycount ) * notarycount ;
bool spent = ( received ! = balance ) ;
if ( ! spent )
{
notaleft = ( ( int64_t ) balance - TotalNotaryPay ) / NotaryPay ;
daysleft = ( ( ( ASSETCHAINS_BLOCKTIME * 5 ) * notaleft ) / 3600 ) / 24 ;
endheight = ( notaleft * 5 ) + height ;
}
result . push_back ( Pair ( " height " , height ) ) ;
result . push_back ( Pair ( " balance " , ValueFromAmount ( balance ) ) ) ;
result . push_back ( Pair ( " spent " , spent ) ) ;
result . push_back ( Pair ( " Total_NotaryPay " , ValueFromAmount ( TotalNotaryPay ) ) ) ;
result . push_back ( Pair ( " Estimated_Notarizations_Left " , notaleft ) ) ;
result . push_back ( Pair ( " Estimated_Days_Left " , daysleft ) ) ;
result . push_back ( Pair ( " Estimated_Height " , endheight ) ) ;
return result ;
}
UniValue getaddressbalance ( const UniValue & params , bool fHelp , const CPubKey & mypk )
{
if ( fHelp | | params . size ( ) > 2 | | params . size ( ) = = 0 )
throw runtime_error (
" getaddressbalance \n "
" \n Returns the balance for an address(es) (requires addressindex to be enabled). \n "
" \n Arguments: \n "
" { \n "
" \" addresses \" \n "
" [ \n "
" \" address \" (string) The base58check encoded address \n "
" ,... \n "
" ] \n "
" } \n "
" \n CCvout (optional) Return CCvouts instead of normal vouts \n "
" \n Result: \n "
" { \n "
" \" balance \" (string) The current balance in satoshis \n "
" \" received \" (string) The total number of satoshis received (including change) \n "
" } \n "
" \n Examples: \n "
+ HelpExampleCli ( " getaddressbalance " , " '{ \" addresses \" : [ \" RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87 \" ]}' (ccvout) " )
+ HelpExampleRpc ( " getaddressbalance " , " { \" addresses \" : [ \" RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87 \" ]} (ccvout) " )
) ;
std : : vector < std : : pair < uint160 , int > > addresses ;
if ( ! getAddressesFromParams ( params , addresses ) ) {
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Invalid address " ) ;
}
std : : vector < std : : pair < CAddressIndexKey , CAmount > > addressIndex ;
for ( std : : vector < std : : pair < uint160 , int > > : : 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 < std : : pair < CAddressIndexKey , CAmount > > : : 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 hush_snapshot ( int top ) ;
UniValue getsnapshot ( const UniValue & params , bool fHelp , const CPubKey & mypk )
{
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 )
{
if ( HUSH_SNAPSHOT_INTERVAL = = 0 )
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid parameter, top must be a positive integer " ) ;
else
top = - 1 ;
}
}
if ( fHelp | | params . size ( ) > 1 )
{
throw runtime_error (
" getsnapshot \n "
" \n Returns a snapshot of (address,amount) pairs at current height (requires addressindex to be enabled). \n "
" \n Arguments: \n "
" \" top \" (number, optional) Only return this many addresses, i.e. top N richlist \n "
" \n Result: \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 snapshot finished, \n "
" \" start_time \" : 1531982752, (number) Unix epoch time snapshot started \n "
" \" end_time \" : 1531982752 (number) Unix epoch time snapshot finished \n "
" } \n "
" \n Examples: \n "
+ HelpExampleCli ( " getsnapshot " , " " )
+ HelpExampleRpc ( " getsnapshot " , " 1000 " )
) ;
}
result = hush_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 , const CPubKey & mypk )
{
if ( fHelp | | params . size ( ) > 2 | | params . size ( ) < 1 )
throw runtime_error (
" getaddresstxids (ccvout) \n "
" \n Returns the txids for an address(es) (requires addressindex to be enabled). \n "
" \n Arguments: \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 "
" \n CCvout (optional) Return CCvouts instead of normal vouts \n "
" \n Result: \n "
" [ \n "
" \" transactionid \" (string) The transaction id \n "
" ,... \n "
" ] \n "
" \n Examples: \n "
+ HelpExampleCli ( " getaddresstxids " , " '{ \" addresses \" : [ \" RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87 \" ]}' (ccvout) " )
+ HelpExampleRpc ( " getaddresstxids " , " { \" addresses \" : [ \" RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87 \" ]} (ccvout) " )
) ;
std : : vector < std : : pair < uint160 , int > > 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 < std : : pair < CAddressIndexKey , CAmount > > addressIndex ;
for ( std : : vector < std : : pair < uint160 , int > > : : 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 < std : : pair < int , std : : string > > txids ;
UniValue result ( UniValue : : VARR ) ;
for ( std : : vector < std : : pair < CAddressIndexKey , CAmount > > : : 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 < std : : pair < int , std : : string > > : : const_iterator it = txids . begin ( ) ; it ! = txids . end ( ) ; it + + ) {
result . push_back ( it - > second ) ;
}
}
return result ;
}
UniValue getspentinfo ( const UniValue & params , bool fHelp , const CPubKey & mypk )
{
if ( fHelp | | params . size ( ) ! = 1 | | ! params [ 0 ] . isObject ( ) )
throw runtime_error (
" getspentinfo \n "
" \n Returns the txid and index where an output is spent. \n "
" \n Arguments: \n "
" { \n "
" \" txid \" (string) The hex string of the txid \n "
" \" index \" (number) The start block height \n "
" } \n "
" \n Result: \n "
" { \n "
" \" txid \" (string) The transaction id \n "
" \" index \" (number) The spending input index \n "
" ,... \n "
" } \n "
" \n Examples: \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 ;
}
UniValue txnotarizedconfirmed ( const UniValue & params , bool fHelp , const CPubKey & mypk )
{
bool notarizedconfirmed ; uint256 txid ;
if ( fHelp | | params . size ( ) < 1 | | params . size ( ) > 1 )
{
string msg = " txnotarizedconfirmed txid \n "
" \n Returns true if transaction is notarized on chain that has dPoW or if confirmation number is greater than 60 on chain that does not have dPoW. \n "
" \n Arguments: \n "
" 1. txid (string, required) Transaction id. \n "
" \n Result: \n "
" { \n "
" true, (bool) The value the check. \n "
" } \n "
;
throw runtime_error ( msg ) ;
}
txid = uint256S ( ( char * ) params [ 0 ] . get_str ( ) . c_str ( ) ) ;
notarizedconfirmed = hush_txnotarizedconfirmed ( txid ) ;
UniValue result ( UniValue : : VOBJ ) ;
result . push_back ( Pair ( " result " , notarizedconfirmed ) ) ;
return result ;
}
static const CRPCCommand commands [ ] =
{ // category name actor (function) okSafeMode
// --------------------- ------------------------ ----------------------- ----------
{ " control " , " getinfo " , & getinfo , true } , /* uses wallet if enabled */
{ " util " , " validateaddress " , & validateaddress , true } , /* uses wallet if enabled */
{ " util " , " z_validateaddress " , & z_validateaddress , true } , /* uses wallet if enabled */
{ " util " , " createmultisig " , & createmultisig , true } ,
{ " util " , " verifymessage " , & verifymessage , true } ,
{ " util " , " rpcinfo " , & rpcinfo , true } ,
/* Not shown in help */
{ " hidden " , " setmocktime " , & setmocktime , true } ,
} ;
void RegisterMiscRPCCommands ( CRPCTable & tableRPC )
{
for ( unsigned int vcidx = 0 ; vcidx < ARRAYLEN ( commands ) ; vcidx + + )
tableRPC . appendCommand ( commands [ vcidx ] . name , & commands [ vcidx ] ) ;
}