2019-01-29 15:53:14 +01:00
// Copyright (c) 2018-2019 The Dash Core developers
2018-02-13 13:36:59 +01:00
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
# include "base58.h"
# include "consensus/validation.h"
# include "core_io.h"
# include "init.h"
# include "messagesigner.h"
# include "rpc/server.h"
# include "utilmoneystr.h"
# include "validation.h"
# ifdef ENABLE_WALLET
2018-12-28 10:24:48 +01:00
# include "wallet/coincontrol.h"
2018-02-13 13:36:59 +01:00
# include "wallet/wallet.h"
2019-01-25 17:52:27 +01:00
# include "wallet/rpcwallet.h"
2018-02-13 13:36:59 +01:00
# endif //ENABLE_WALLET
# include "netbase.h"
# include "evo/specialtx.h"
# include "evo/providertx.h"
2018-03-03 21:48:00 +01:00
# include "evo/deterministicmns.h"
2018-04-09 14:49:34 +02:00
# include "evo/simplifiedmns.h"
2018-02-13 13:36:59 +01:00
2018-10-21 21:45:16 +02:00
# include "bls/bls.h"
2018-02-13 13:36:59 +01:00
# ifdef ENABLE_WALLET
extern UniValue signrawtransaction ( const JSONRPCRequest & request ) ;
extern UniValue sendrawtransaction ( const JSONRPCRequest & request ) ;
# endif //ENABLE_WALLET
2019-01-29 15:54:01 +01:00
std : : string GetHelpString ( int nParamNum , std : : string strParamName )
{
static const std : : map < std : : string , std : : string > mapParamHelp = {
{ " collateralAddress " ,
" %d. \" collateralAddress \" (string, required) The dash address to send the collateral to. \n "
} ,
{ " collateralHash " ,
" %d. \" collateralHash \" (string, required) The collateral transaction hash. \n "
} ,
{ " collateralIndex " ,
" %d. collateralIndex (numeric, required) The collateral transaction output index. \n "
} ,
{ " feeSourceAddress " ,
" %d. \" feeSourceAddress \" (string, optional) If specified wallet will only use coins from this address to fund ProTx. \n "
" If not specified, payoutAddress is the one that is going to be used. \n "
" The private key belonging to this address must be known in your wallet. \n "
} ,
{ " fundAddress " ,
" %d. \" fundAddress \" (string, optional) If specified wallet will only use coins from this address to fund ProTx. \n "
" If not specified, payoutAddress is the one that is going to be used. \n "
" The private key belonging to this address must be known in your wallet. \n "
} ,
{ " ipAndPort " ,
" %d. \" ipAndPort \" (string, required) IP and port in the form \" IP:PORT \" . \n "
" Must be unique on the network. Can be set to 0, which will require a ProUpServTx afterwards. \n "
} ,
{ " operatorKey " ,
" %d. \" operatorKey \" (string, required) The operator private key belonging to the \n "
" registered operator public key. \n "
} ,
2019-02-04 10:52:24 +01:00
{ " operatorPayoutAddress " ,
" %d. \" operatorPayoutAddress \" (string, optional) The address used for operator reward payments. \n "
" Only allowed when the ProRegTx had a non-zero operatorReward value. \n "
" If set to an empty string, the currently active payout address is reused. \n "
} ,
2019-01-29 15:54:01 +01:00
{ " operatorPubKey " ,
" %d. \" operatorPubKey \" (string, required) The operator BLS public key. The private key does not have to be known. \n "
" It has to match the private key which is later used when operating the masternode. \n "
} ,
{ " operatorReward " ,
" %d. \" operatorReward \" (numeric, required) The fraction in %% to share with the operator. The value must be \n "
" between 0.00 and 100.00. \n "
} ,
{ " ownerAddress " ,
" %d. \" ownerAddress \" (string, required) The dash address to use for payee updates and proposal voting. \n "
" The private key belonging to this address must be known in your wallet. The address must \n "
" be unused and must differ from the collateralAddress \n "
} ,
{ " payoutAddress " ,
" %d. \" payoutAddress \" (string, required) The dash address to use for masternode reward payments. \n "
} ,
{ " proTxHash " ,
" %d. \" proTxHash \" (string, required) The hash of the initial ProRegTx. \n "
} ,
{ " reason " ,
" %d. reason (numeric, optional) The reason for masternode service revocation. \n "
} ,
{ " votingAddress " ,
" %d. \" votingAddress \" (string, required) The voting key address. The private key does not have to be known by your wallet. \n "
" It has to match the private key which is later used when voting on proposals. \n "
" If set to an empty string, ownerAddress will be used. \n "
} ,
} ;
auto it = mapParamHelp . find ( strParamName ) ;
if ( it = = mapParamHelp . end ( ) )
throw std : : runtime_error ( strprintf ( " FIXME: WRONG PARAM NAME %s! " , strParamName ) ) ;
return strprintf ( it - > second , nParamNum ) ;
}
2018-02-13 13:36:59 +01:00
// Allows to specify Dash address or priv key. In case of Dash address, the priv key is taken from the wallet
2018-12-29 21:15:02 +01:00
static CKey ParsePrivKey ( CWallet * pwallet , const std : : string & strKeyOrAddress , bool allowAddresses = true ) {
2018-02-13 13:36:59 +01:00
CBitcoinAddress address ;
if ( allowAddresses & & address . SetString ( strKeyOrAddress ) & & address . IsValid ( ) ) {
# ifdef ENABLE_WALLET
2018-12-29 21:15:02 +01:00
if ( ! pwallet ) {
2018-11-29 09:12:41 +01:00
throw std : : runtime_error ( " addresses not supported when wallet is disabled " ) ;
}
2019-04-25 17:37:08 +02:00
EnsureWalletIsUnlocked ( pwallet ) ;
2018-02-13 13:36:59 +01:00
CKeyID keyId ;
CKey key ;
2018-12-29 21:15:02 +01:00
if ( ! address . GetKeyID ( keyId ) | | ! pwallet - > GetKey ( keyId , key ) )
2018-02-13 13:36:59 +01:00
throw std : : runtime_error ( strprintf ( " non-wallet or invalid address %s " , strKeyOrAddress ) ) ;
return key ;
# else //ENABLE_WALLET
throw std : : runtime_error ( " addresses not supported in no-wallet builds " ) ;
# endif //ENABLE_WALLET
}
CBitcoinSecret secret ;
2018-10-26 07:03:14 +02:00
if ( ! secret . SetString ( strKeyOrAddress ) | | ! secret . IsValid ( ) ) {
2018-02-13 13:36:59 +01:00
throw std : : runtime_error ( strprintf ( " invalid priv-key/address %s " , strKeyOrAddress ) ) ;
2018-10-26 07:03:14 +02:00
}
2018-02-13 13:36:59 +01:00
return secret . GetKey ( ) ;
}
static CKeyID ParsePubKeyIDFromAddress ( const std : : string & strAddress , const std : : string & paramName )
{
CBitcoinAddress address ( strAddress ) ;
CKeyID keyID ;
2018-10-26 07:03:14 +02:00
if ( ! address . IsValid ( ) | | ! address . GetKeyID ( keyID ) ) {
2018-02-13 13:36:59 +01:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , strprintf ( " %s must be a valid P2PKH address, not %s " , paramName , strAddress ) ) ;
2018-10-26 07:03:14 +02:00
}
2018-02-13 13:36:59 +01:00
return keyID ;
}
2018-10-21 21:45:16 +02:00
static CBLSPublicKey ParseBLSPubKey ( const std : : string & hexKey , const std : : string & paramName )
{
CBLSPublicKey pubKey ;
2019-04-30 14:48:21 +02:00
if ( ! pubKey . SetHexStr ( hexKey ) ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , strprintf ( " %s must be a valid BLS public key, not %s " , paramName , hexKey ) ) ;
2018-10-21 21:45:16 +02:00
}
return pubKey ;
}
static CBLSSecretKey ParseBLSSecretKey ( const std : : string & hexKey , const std : : string & paramName )
{
CBLSSecretKey secKey ;
2019-04-30 14:48:21 +02:00
if ( ! secKey . SetHexStr ( hexKey ) ) {
2018-10-21 21:45:16 +02:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , strprintf ( " %s must be a valid BLS secret key " , paramName ) ) ;
}
return secKey ;
}
2018-02-13 13:36:59 +01:00
# ifdef ENABLE_WALLET
template < typename SpecialTxPayload >
2018-12-31 03:37:40 +01:00
static void FundSpecialTx ( CWallet * pwallet , CMutableTransaction & tx , const SpecialTxPayload & payload , const CTxDestination & fundDest )
2018-02-13 13:36:59 +01:00
{
2018-12-31 03:37:40 +01:00
assert ( pwallet ! = NULL ) ;
LOCK2 ( cs_main , pwallet - > cs_wallet ) ;
2018-12-28 10:24:48 +01:00
CTxDestination nodest = CNoDestination ( ) ;
if ( fundDest = = nodest ) {
throw JSONRPCError ( RPC_INTERNAL_ERROR , " No source of funds specified " ) ;
}
2018-02-13 13:36:59 +01:00
CDataStream ds ( SER_NETWORK , PROTOCOL_VERSION ) ;
ds < < payload ;
tx . vExtraPayload . assign ( ds . begin ( ) , ds . end ( ) ) ;
static CTxOut dummyTxOut ( 0 , CScript ( ) < < OP_RETURN ) ;
2018-12-28 10:24:48 +01:00
std : : vector < CRecipient > vecSend ;
2018-02-13 13:36:59 +01:00
bool dummyTxOutAdded = false ;
2018-12-28 10:24:48 +01:00
2018-02-13 13:36:59 +01:00
if ( tx . vout . empty ( ) ) {
2018-12-28 10:24:48 +01:00
// add dummy txout as CreateTransaction requires at least one recipient
2018-02-13 13:36:59 +01:00
tx . vout . emplace_back ( dummyTxOut ) ;
dummyTxOutAdded = true ;
}
2018-12-28 10:24:48 +01:00
for ( const auto & txOut : tx . vout ) {
CRecipient recipient = { txOut . scriptPubKey , txOut . nValue , false } ;
vecSend . push_back ( recipient ) ;
}
CCoinControl coinControl ;
coinControl . destChange = fundDest ;
coinControl . fRequireAllInputs = false ;
std : : vector < COutput > vecOutputs ;
2018-12-31 03:37:40 +01:00
pwallet - > AvailableCoins ( vecOutputs ) ;
2018-12-28 10:24:48 +01:00
for ( const auto & out : vecOutputs ) {
CTxDestination txDest ;
if ( ExtractDestination ( out . tx - > tx - > vout [ out . i ] . scriptPubKey , txDest ) & & txDest = = fundDest ) {
coinControl . Select ( COutPoint ( out . tx - > tx - > GetHash ( ) , out . i ) ) ;
}
}
if ( ! coinControl . HasSelected ( ) ) {
throw JSONRPCError ( RPC_INTERNAL_ERROR , " No funds at specified address " ) ;
}
CWalletTx wtx ;
2019-04-25 17:37:08 +02:00
CReserveKey reservekey ( pwallet ) ;
2018-02-13 13:36:59 +01:00
CAmount nFee ;
int nChangePos = - 1 ;
std : : string strFailReason ;
2018-12-28 10:24:48 +01:00
2018-12-29 21:15:02 +01:00
if ( ! pwallet - > CreateTransaction ( vecSend , wtx , reservekey , nFee , nChangePos , strFailReason , & coinControl , false , ALL_COINS , false , tx . vExtraPayload . size ( ) ) ) {
2018-02-13 13:36:59 +01:00
throw JSONRPCError ( RPC_INTERNAL_ERROR , strFailReason ) ;
2018-10-26 07:03:14 +02:00
}
2018-02-13 13:36:59 +01:00
2018-12-28 10:24:48 +01:00
tx . vin = wtx . tx - > vin ;
tx . vout = wtx . tx - > vout ;
2018-02-13 13:36:59 +01:00
if ( dummyTxOutAdded & & tx . vout . size ( ) > 1 ) {
2018-12-28 10:24:48 +01:00
// CreateTransaction added a change output, so we don't need the dummy txout anymore.
// Removing it results in slight overpayment of fees, but we ignore this for now (as it's a very low amount).
2018-02-13 13:36:59 +01:00
auto it = std : : find ( tx . vout . begin ( ) , tx . vout . end ( ) , dummyTxOut ) ;
assert ( it ! = tx . vout . end ( ) ) ;
tx . vout . erase ( it ) ;
}
}
template < typename SpecialTxPayload >
2018-10-25 16:29:50 +02:00
static void UpdateSpecialTxInputsHash ( const CMutableTransaction & tx , SpecialTxPayload & payload )
2018-02-13 13:36:59 +01:00
{
payload . inputsHash = CalcTxInputsHash ( tx ) ;
2018-10-25 16:29:50 +02:00
}
template < typename SpecialTxPayload >
2018-11-01 22:57:10 +01:00
static void SignSpecialTxPayloadByHash ( const CMutableTransaction & tx , SpecialTxPayload & payload , const CKey & key )
2018-10-25 16:29:50 +02:00
{
UpdateSpecialTxInputsHash ( tx , payload ) ;
2018-02-13 13:36:59 +01:00
payload . vchSig . clear ( ) ;
uint256 hash = : : SerializeHash ( payload ) ;
if ( ! CHashSigner : : SignHash ( hash , key , payload . vchSig ) ) {
throw JSONRPCError ( RPC_INTERNAL_ERROR , " failed to sign special tx " ) ;
}
}
2018-10-21 21:45:16 +02:00
template < typename SpecialTxPayload >
2018-11-01 22:57:10 +01:00
static void SignSpecialTxPayloadByString ( const CMutableTransaction & tx , SpecialTxPayload & payload , const CKey & key )
{
UpdateSpecialTxInputsHash ( tx , payload ) ;
payload . vchSig . clear ( ) ;
std : : string m = payload . MakeSignString ( ) ;
if ( ! CMessageSigner : : SignMessage ( m , payload . vchSig , key ) ) {
throw JSONRPCError ( RPC_INTERNAL_ERROR , " failed to sign special tx " ) ;
}
}
template < typename SpecialTxPayload >
static void SignSpecialTxPayloadByHash ( const CMutableTransaction & tx , SpecialTxPayload & payload , const CBLSSecretKey & key )
2018-10-21 21:45:16 +02:00
{
2018-10-25 16:29:50 +02:00
UpdateSpecialTxInputsHash ( tx , payload ) ;
2018-10-21 21:45:16 +02:00
uint256 hash = : : SerializeHash ( payload ) ;
payload . sig = key . Sign ( hash ) ;
}
2018-02-13 13:36:59 +01:00
static std : : string SignAndSendSpecialTx ( const CMutableTransaction & tx )
{
LOCK ( cs_main ) ;
2018-10-25 16:29:50 +02:00
2018-02-13 13:36:59 +01:00
CValidationState state ;
2018-10-26 07:03:14 +02:00
if ( ! CheckSpecialTx ( tx , chainActive . Tip ( ) , state ) ) {
2018-02-13 13:36:59 +01:00
throw std : : runtime_error ( FormatStateMessage ( state ) ) ;
2018-10-26 07:03:14 +02:00
}
2018-02-13 13:36:59 +01:00
CDataStream ds ( SER_NETWORK , PROTOCOL_VERSION ) ;
ds < < tx ;
2019-04-04 06:39:28 +02:00
JSONRPCRequest signRequest ;
signRequest . params . setArray ( ) ;
signRequest . params . push_back ( HexStr ( ds . begin ( ) , ds . end ( ) ) ) ;
UniValue signResult = signrawtransaction ( signRequest ) ;
2018-02-13 13:36:59 +01:00
JSONRPCRequest sendRequest ;
sendRequest . params . setArray ( ) ;
sendRequest . params . push_back ( signResult [ " hex " ] . get_str ( ) ) ;
return sendrawtransaction ( sendRequest ) . get_str ( ) ;
}
2019-04-25 17:37:08 +02:00
void protx_register_fund_help ( CWallet * const pwallet )
2018-02-13 13:36:59 +01:00
{
throw std : : runtime_error (
2019-01-11 11:05:58 +01:00
" protx register_fund \" collateralAddress \" \" ipAndPort \" \" ownerAddress \" \" operatorPubKey \" \" votingAddress \" operatorReward \" payoutAddress \" ( \" fundAddress \" ) \n "
2018-10-25 16:29:50 +02:00
" \n Creates, funds and sends a ProTx to the network. The resulting transaction will move 1000 Dash \n "
2018-02-13 13:36:59 +01:00
" to the address specified by collateralAddress and will then function as the collateral of your \n "
" masternode. \n "
" A few of the limitations you see in the arguments are temporary and might be lifted after DIP3 \n "
" is fully deployed. \n "
2019-04-25 17:37:08 +02:00
+ HelpRequiringPassphrase ( pwallet ) + " \n "
2018-02-13 13:36:59 +01:00
" \n Arguments: \n "
2019-01-29 15:54:01 +01:00
+ GetHelpString ( 1 , " collateralAddress " )
+ GetHelpString ( 2 , " ipAndPort " )
+ GetHelpString ( 3 , " ownerAddress " )
+ GetHelpString ( 4 , " operatorPubKey " )
+ GetHelpString ( 5 , " votingAddress " )
+ GetHelpString ( 6 , " operatorReward " )
+ GetHelpString ( 7 , " payoutAddress " )
+ GetHelpString ( 8 , " fundAddress " ) +
" \n Result: \n "
" \" txid \" (string) The transaction id. \n "
2018-02-13 13:36:59 +01:00
" \n Examples: \n "
2018-11-01 22:57:10 +01:00
+ HelpExampleCli ( " protx " , " register_fund \" XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb \" \" 1.2.3.4:1234 \" \" Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr \" \" 93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4 \" \" Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr \" 0 \" XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb \" " )
2018-10-25 16:29:50 +02:00
) ;
}
2019-04-25 17:37:08 +02:00
void protx_register_help ( CWallet * const pwallet )
2018-10-25 16:29:50 +02:00
{
throw std : : runtime_error (
2019-01-11 11:05:58 +01:00
" protx register \" collateralHash \" collateralIndex \" ipAndPort \" \" ownerAddress \" \" operatorPubKey \" \" votingAddress \" operatorReward \" payoutAddress \" ( \" feeSourceAddress \" ) \n "
2018-11-01 22:57:10 +01:00
" \n Same as \" protx register_fund \" , but with an externally referenced collateral. \n "
2018-10-25 16:29:50 +02:00
" The collateral is specified through \" collateralHash \" and \" collateralIndex \" and must be an unspent \n "
2019-01-29 15:54:01 +01:00
" transaction output spendable by this wallet. It must also not be used by any other masternode. \n "
2019-04-25 17:37:08 +02:00
+ HelpRequiringPassphrase ( pwallet ) + " \n "
2018-10-25 16:29:50 +02:00
" \n Arguments: \n "
2019-01-29 15:54:01 +01:00
+ GetHelpString ( 1 , " collateralHash " )
+ GetHelpString ( 2 , " collateralIndex " )
+ GetHelpString ( 3 , " ipAndPort " )
+ GetHelpString ( 4 , " ownerAddress " )
+ GetHelpString ( 5 , " operatorPubKey " )
+ GetHelpString ( 6 , " votingAddress " )
+ GetHelpString ( 7 , " operatorReward " )
+ GetHelpString ( 8 , " payoutAddress " )
+ GetHelpString ( 9 , " feeSourceAddress " ) +
" \n Result: \n "
" \" txid \" (string) The transaction id. \n "
2018-10-25 16:29:50 +02:00
" \n Examples: \n "
2018-11-08 18:03:50 +01:00
+ HelpExampleCli ( " protx " , " register \" 0123456701234567012345670123456701234567012345670123456701234567 \" 0 \" 1.2.3.4:1234 \" \" Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr \" \" 93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4 \" \" Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr \" 0 \" XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb \" " )
2018-02-13 13:36:59 +01:00
) ;
}
2018-11-01 22:57:10 +01:00
void protx_register_prepare_help ( )
{
throw std : : runtime_error (
2019-01-11 11:05:58 +01:00
" protx register_prepare \" collateralHash \" collateralIndex \" ipAndPort \" \" ownerAddress \" \" operatorPubKey \" \" votingAddress \" operatorReward \" payoutAddress \" ( \" feeSourceAddress \" ) \n "
2018-11-01 22:57:10 +01:00
" \n Creates an unsigned ProTx and returns it. The ProTx must be signed externally with the collateral \n "
" key and then passed to \" protx register_submit \" . The prepared transaction will also contain inputs \n "
" and outputs to cover fees. \n "
" \n Arguments: \n "
2019-01-29 15:54:01 +01:00
+ GetHelpString ( 1 , " collateralHash " )
+ GetHelpString ( 2 , " collateralIndex " )
+ GetHelpString ( 3 , " ipAndPort " )
+ GetHelpString ( 4 , " ownerAddress " )
+ GetHelpString ( 5 , " operatorPubKey " )
+ GetHelpString ( 6 , " votingAddress " )
+ GetHelpString ( 7 , " operatorReward " )
+ GetHelpString ( 8 , " payoutAddress " )
+ GetHelpString ( 9 , " feeSourceAddress " ) +
2018-11-01 22:57:10 +01:00
" \n Result: \n "
2019-01-29 15:54:01 +01:00
" { (json object) \n "
" \" tx \" : (string) The serialized ProTx in hex format. \n "
" \" collateralAddress \" : (string) The collateral address. \n "
" \" signMessage \" : (string) The string message that needs to be signed with \n "
" the collateral key. \n "
2018-11-01 22:57:10 +01:00
" } \n "
" \n Examples: \n "
2018-11-08 18:03:50 +01:00
+ HelpExampleCli ( " protx " , " register_prepare \" 0123456701234567012345670123456701234567012345670123456701234567 \" 0 \" 1.2.3.4:1234 \" \" Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr \" \" 93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4 \" \" Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr \" 0 \" XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb \" " )
2018-11-01 22:57:10 +01:00
) ;
}
2019-04-25 17:37:08 +02:00
void protx_register_submit_help ( CWallet * const pwallet )
2018-11-01 22:57:10 +01:00
{
throw std : : runtime_error (
" protx register_submit \" tx \" \" sig \" \n "
" \n Submits the specified ProTx to the network. This command will also sign the inputs of the transaction \n "
" which were previously added by \" protx register_prepare \" to cover transaction fees \n "
2019-04-25 17:37:08 +02:00
+ HelpRequiringPassphrase ( pwallet ) + " \n "
2018-11-01 22:57:10 +01:00
" \n Arguments: \n "
2018-11-08 18:03:50 +01:00
" 1. \" tx \" (string, required) The serialized transaction previously returned by \" protx register_prepare \" \n "
2018-11-01 22:57:10 +01:00
" 2. \" sig \" (string, required) The signature signed with the collateral key. Must be in base64 format. \n "
2019-01-29 15:54:01 +01:00
" \n Result: \n "
" \" txid \" (string) The transaction id. \n "
2018-11-01 22:57:10 +01:00
" \n Examples: \n "
+ HelpExampleCli ( " protx " , " register_submit \" tx \" \" sig \" " )
) ;
}
// handles register, register_prepare and register_fund in one method
2018-02-13 13:36:59 +01:00
UniValue protx_register ( const JSONRPCRequest & request )
{
2018-12-29 21:15:02 +01:00
CWallet * const pwallet = GetWalletForJSONRPCRequest ( request ) ;
2018-11-01 22:57:10 +01:00
bool isExternalRegister = request . params [ 0 ] . get_str ( ) = = " register " ;
bool isFundRegister = request . params [ 0 ] . get_str ( ) = = " register_fund " ;
bool isPrepareRegister = request . params [ 0 ] . get_str ( ) = = " register_prepare " ;
2018-02-13 13:36:59 +01:00
2018-12-28 10:24:48 +01:00
if ( isFundRegister & & ( request . fHelp | | ( request . params . size ( ) ! = 8 & & request . params . size ( ) ! = 9 ) ) ) {
2019-04-25 17:37:08 +02:00
protx_register_fund_help ( pwallet ) ;
2018-12-28 10:24:48 +01:00
} else if ( isExternalRegister & & ( request . fHelp | | ( request . params . size ( ) ! = 9 & & request . params . size ( ) ! = 10 ) ) ) {
2019-04-25 17:37:08 +02:00
protx_register_help ( pwallet ) ;
2018-12-28 10:24:48 +01:00
} else if ( isPrepareRegister & & ( request . fHelp | | ( request . params . size ( ) ! = 9 & & request . params . size ( ) ! = 10 ) ) ) {
2018-11-01 22:57:10 +01:00
protx_register_prepare_help ( ) ;
2018-10-25 16:29:50 +02:00
}
2018-02-13 13:36:59 +01:00
2019-04-25 17:37:08 +02:00
if ( ! EnsureWalletIsAvailable ( pwallet , request . fHelp ) )
return NullUniValue ;
if ( isExternalRegister | | isFundRegister ) {
EnsureWalletIsUnlocked ( pwallet ) ;
}
2018-10-25 16:29:50 +02:00
size_t paramIdx = 1 ;
2018-02-13 13:36:59 +01:00
2018-10-25 16:29:50 +02:00
CAmount collateralAmount = 1000 * COIN ;
2018-02-13 13:36:59 +01:00
CMutableTransaction tx ;
tx . nVersion = 3 ;
tx . nType = TRANSACTION_PROVIDER_REGISTER ;
CProRegTx ptx ;
ptx . nVersion = CProRegTx : : CURRENT_VERSION ;
2018-10-25 16:29:50 +02:00
if ( isFundRegister ) {
CBitcoinAddress collateralAddress ( request . params [ paramIdx ] . get_str ( ) ) ;
2018-10-26 07:03:14 +02:00
if ( ! collateralAddress . IsValid ( ) ) {
2018-10-25 16:29:50 +02:00
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , strprintf ( " invalid collaterall address: %s " , request . params [ paramIdx ] . get_str ( ) ) ) ;
2018-10-26 07:03:14 +02:00
}
2018-10-25 16:29:50 +02:00
CScript collateralScript = GetScriptForDestination ( collateralAddress . Get ( ) ) ;
CTxOut collateralTxOut ( collateralAmount , collateralScript ) ;
tx . vout . emplace_back ( collateralTxOut ) ;
paramIdx + + ;
} else {
uint256 collateralHash = ParseHashV ( request . params [ paramIdx ] , " collateralHash " ) ;
int32_t collateralIndex = ParseInt32V ( request . params [ paramIdx + 1 ] , " collateralIndex " ) ;
if ( collateralHash . IsNull ( ) | | collateralIndex < 0 ) {
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , strprintf ( " invalid hash or index: %s-%d " , collateralHash . ToString ( ) , collateralIndex ) ) ;
}
ptx . collateralOutpoint = COutPoint ( collateralHash , ( uint32_t ) collateralIndex ) ;
paramIdx + = 2 ;
// TODO unlock on failure
2018-12-29 21:15:02 +01:00
LOCK ( pwallet - > cs_wallet ) ;
pwallet - > LockCoin ( ptx . collateralOutpoint ) ;
2018-10-25 16:29:50 +02:00
}
2019-01-12 14:17:16 +01:00
if ( request . params [ paramIdx ] . get_str ( ) ! = " " ) {
2018-10-26 07:03:14 +02:00
if ( ! Lookup ( request . params [ paramIdx ] . get_str ( ) . c_str ( ) , ptx . addr , Params ( ) . GetDefaultPort ( ) , false ) ) {
2018-10-25 16:29:50 +02:00
throw std : : runtime_error ( strprintf ( " invalid network address %s " , request . params [ paramIdx ] . get_str ( ) ) ) ;
2018-10-26 07:03:14 +02:00
}
2018-02-13 13:36:59 +01:00
}
2018-12-29 21:15:02 +01:00
CKey keyOwner = ParsePrivKey ( pwallet , request . params [ paramIdx + 1 ] . get_str ( ) , true ) ;
2018-10-25 16:29:50 +02:00
CBLSPublicKey pubKeyOperator = ParseBLSPubKey ( request . params [ paramIdx + 2 ] . get_str ( ) , " operator BLS address " ) ;
2018-02-13 13:36:59 +01:00
CKeyID keyIDVoting = keyOwner . GetPubKey ( ) . GetID ( ) ;
2019-01-12 14:17:16 +01:00
if ( request . params [ paramIdx + 3 ] . get_str ( ) ! = " " ) {
2018-10-25 16:29:50 +02:00
keyIDVoting = ParsePubKeyIDFromAddress ( request . params [ paramIdx + 3 ] . get_str ( ) , " voting address " ) ;
2018-02-13 13:36:59 +01:00
}
2018-11-21 08:04:42 +01:00
int64_t operatorReward ;
if ( ! ParseFixedPoint ( request . params [ paramIdx + 4 ] . getValStr ( ) , 2 , & operatorReward ) ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " operatorReward must be a number " ) ;
}
if ( operatorReward < 0 | | operatorReward > 10000 ) {
2018-11-01 22:58:36 +01:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " operatorReward must be between 0.00 and 100.00 " ) ;
2018-10-26 07:03:14 +02:00
}
2018-11-21 08:04:42 +01:00
ptx . nOperatorReward = operatorReward ;
2018-02-13 13:36:59 +01:00
2018-10-25 16:29:50 +02:00
CBitcoinAddress payoutAddress ( request . params [ paramIdx + 5 ] . get_str ( ) ) ;
2018-10-26 07:03:14 +02:00
if ( ! payoutAddress . IsValid ( ) ) {
2018-10-25 16:29:50 +02:00
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , strprintf ( " invalid payout address: %s " , request . params [ paramIdx + 5 ] . get_str ( ) ) ) ;
2018-10-26 07:03:14 +02:00
}
2018-02-13 13:36:59 +01:00
ptx . keyIDOwner = keyOwner . GetPubKey ( ) . GetID ( ) ;
2018-10-21 21:45:16 +02:00
ptx . pubKeyOperator = pubKeyOperator ;
2018-02-13 13:36:59 +01:00
ptx . keyIDVoting = keyIDVoting ;
ptx . scriptPayout = GetScriptForDestination ( payoutAddress . Get ( ) ) ;
2018-10-25 16:29:50 +02:00
if ( ! isFundRegister ) {
// make sure fee calculation works
ptx . vchSig . resize ( 65 ) ;
}
2018-12-28 10:24:48 +01:00
CBitcoinAddress fundAddress = payoutAddress ;
if ( request . params . size ( ) > paramIdx + 6 ) {
fundAddress = CBitcoinAddress ( request . params [ paramIdx + 6 ] . get_str ( ) ) ;
if ( ! fundAddress . IsValid ( ) )
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , std : : string ( " Invalid Dash address: " ) + request . params [ paramIdx + 6 ] . get_str ( ) ) ;
}
2018-12-31 03:37:40 +01:00
FundSpecialTx ( pwallet , tx , ptx , fundAddress . Get ( ) ) ;
2018-11-01 22:57:10 +01:00
UpdateSpecialTxInputsHash ( tx , ptx ) ;
2018-02-13 13:36:59 +01:00
2018-10-25 16:29:50 +02:00
if ( isFundRegister ) {
uint32_t collateralIndex = ( uint32_t ) - 1 ;
for ( uint32_t i = 0 ; i < tx . vout . size ( ) ; i + + ) {
if ( tx . vout [ i ] . nValue = = collateralAmount ) {
collateralIndex = i ;
break ;
}
2018-02-13 13:36:59 +01:00
}
2018-10-25 16:29:50 +02:00
assert ( collateralIndex ! = ( uint32_t ) - 1 ) ;
ptx . collateralOutpoint . n = collateralIndex ;
2018-02-13 13:36:59 +01:00
2018-11-01 22:57:10 +01:00
SetTxPayload ( tx , ptx ) ;
return SignAndSendSpecialTx ( tx ) ;
2018-10-25 16:29:50 +02:00
} else {
2018-11-01 22:57:10 +01:00
// referencing external collateral
2018-10-25 16:29:50 +02:00
Coin coin ;
if ( ! GetUTXOCoin ( ptx . collateralOutpoint , coin ) ) {
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , strprintf ( " collateral not found: %s " , ptx . collateralOutpoint . ToStringShort ( ) ) ) ;
}
CTxDestination txDest ;
CKeyID keyID ;
if ( ! ExtractDestination ( coin . out . scriptPubKey , txDest ) | | ! CBitcoinAddress ( txDest ) . GetKeyID ( keyID ) ) {
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , strprintf ( " collateral type not supported: %s " , ptx . collateralOutpoint . ToStringShort ( ) ) ) ;
}
2018-11-01 22:57:10 +01:00
if ( isPrepareRegister ) {
// external signing with collateral key
ptx . vchSig . clear ( ) ;
SetTxPayload ( tx , ptx ) ;
UniValue ret ( UniValue : : VOBJ ) ;
ret . push_back ( Pair ( " tx " , EncodeHexTx ( tx ) ) ) ;
ret . push_back ( Pair ( " collateralAddress " , CBitcoinAddress ( txDest ) . ToString ( ) ) ) ;
ret . push_back ( Pair ( " signMessage " , ptx . MakeSignString ( ) ) ) ;
return ret ;
} else {
// lets prove we own the collateral
CKey key ;
2018-12-29 21:15:02 +01:00
if ( ! pwallet - > GetKey ( keyID , key ) ) {
2018-11-01 22:57:10 +01:00
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , strprintf ( " collateral key not in wallet: %s " , CBitcoinAddress ( keyID ) . ToString ( ) ) ) ;
}
SignSpecialTxPayloadByString ( tx , ptx , key ) ;
SetTxPayload ( tx , ptx ) ;
return SignAndSendSpecialTx ( tx ) ;
2018-10-25 16:29:50 +02:00
}
}
2018-11-01 22:57:10 +01:00
}
UniValue protx_register_submit ( const JSONRPCRequest & request )
{
2019-04-25 17:37:08 +02:00
CWallet * const pwallet = GetWalletForJSONRPCRequest ( request ) ;
2018-11-01 22:57:10 +01:00
if ( request . fHelp | | request . params . size ( ) ! = 3 ) {
2019-04-25 17:37:08 +02:00
protx_register_submit_help ( pwallet ) ;
2018-11-01 22:57:10 +01:00
}
2018-02-13 13:36:59 +01:00
2019-04-25 17:37:08 +02:00
if ( ! EnsureWalletIsAvailable ( pwallet , request . fHelp ) )
return NullUniValue ;
EnsureWalletIsUnlocked ( pwallet ) ;
2018-11-01 22:57:10 +01:00
CMutableTransaction tx ;
if ( ! DecodeHexTx ( tx , request . params [ 1 ] . get_str ( ) ) ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " transaction not deserializable " ) ;
}
if ( tx . nType ! = TRANSACTION_PROVIDER_REGISTER ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " transaction not a ProRegTx " ) ;
}
CProRegTx ptx ;
if ( ! GetTxPayload ( tx , ptx ) ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " transaction payload not deserializable " ) ;
}
if ( ! ptx . vchSig . empty ( ) ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " payload signature not empty " ) ;
}
ptx . vchSig = DecodeBase64 ( request . params [ 2 ] . get_str ( ) . c_str ( ) ) ;
SetTxPayload ( tx , ptx ) ;
2018-02-13 13:36:59 +01:00
return SignAndSendSpecialTx ( tx ) ;
}
2019-04-25 17:37:08 +02:00
void protx_update_service_help ( CWallet * const pwallet )
2018-03-14 08:57:08 +01:00
{
throw std : : runtime_error (
2018-12-28 10:24:48 +01:00
" protx update_service \" proTxHash \" \" ipAndPort \" \" operatorKey \" ( \" operatorPayoutAddress \" \" feeSourceAddress \" ) \n "
2018-10-23 13:15:38 +02:00
" \n Creates and sends a ProUpServTx to the network. This will update the IP address \n "
2018-12-19 09:11:38 +01:00
" of a masternode. \n "
2018-03-14 08:57:08 +01:00
" If this is done for a masternode that got PoSe-banned, the ProUpServTx will also revive this masternode. \n "
2019-04-25 17:37:08 +02:00
+ HelpRequiringPassphrase ( pwallet ) + " \n "
2018-03-14 08:57:08 +01:00
" \n Arguments: \n "
2019-01-29 15:54:01 +01:00
+ GetHelpString ( 1 , " proTxHash " )
+ GetHelpString ( 2 , " ipAndPort " )
+ GetHelpString ( 3 , " operatorKey " )
+ GetHelpString ( 4 , " operatorPayoutAddress " )
+ GetHelpString ( 5 , " feeSourceAddress " ) +
" \n Result: \n "
" \" txid \" (string) The transaction id. \n "
2018-03-14 08:57:08 +01:00
" \n Examples: \n "
2018-10-23 13:15:38 +02:00
+ HelpExampleCli ( " protx " , " update_service \" 0123456701234567012345670123456701234567012345670123456701234567 \" \" 1.2.3.4:1234 \" 5a2e15982e62f1e0b7cf9783c64cf7e3af3f90a52d6c40f6f95d624c0b1621cd " )
2018-03-14 08:57:08 +01:00
) ;
}
UniValue protx_update_service ( const JSONRPCRequest & request )
{
2018-12-31 03:37:40 +01:00
CWallet * const pwallet = GetWalletForJSONRPCRequest ( request ) ;
2018-12-28 10:24:48 +01:00
if ( request . fHelp | | ( request . params . size ( ) < 4 | | request . params . size ( ) > 6 ) )
2019-04-25 17:37:08 +02:00
protx_update_service_help ( pwallet ) ;
if ( ! EnsureWalletIsAvailable ( pwallet , request . fHelp ) )
return NullUniValue ;
EnsureWalletIsUnlocked ( pwallet ) ;
2018-03-14 08:57:08 +01:00
CProUpServTx ptx ;
ptx . nVersion = CProRegTx : : CURRENT_VERSION ;
ptx . proTxHash = ParseHashV ( request . params [ 1 ] , " proTxHash " ) ;
if ( ! Lookup ( request . params [ 2 ] . get_str ( ) . c_str ( ) , ptx . addr , Params ( ) . GetDefaultPort ( ) , false ) ) {
2018-11-22 06:05:20 +01:00
throw std : : runtime_error ( strprintf ( " invalid network address %s " , request . params [ 2 ] . get_str ( ) ) ) ;
2018-03-14 08:57:08 +01:00
}
2018-10-23 13:15:38 +02:00
CBLSSecretKey keyOperator = ParseBLSSecretKey ( request . params [ 3 ] . get_str ( ) , " operatorKey " ) ;
2018-10-21 21:45:16 +02:00
2018-03-14 08:57:08 +01:00
auto dmn = deterministicMNManager - > GetListAtChainTip ( ) . GetMN ( ptx . proTxHash ) ;
if ( ! dmn ) {
throw std : : runtime_error ( strprintf ( " masternode with proTxHash %s not found " , ptx . proTxHash . ToString ( ) ) ) ;
}
2018-10-21 21:45:16 +02:00
if ( keyOperator . GetPublicKey ( ) ! = dmn - > pdmnState - > pubKeyOperator ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , strprintf ( " the operator key does not belong to the registered public key " ) ) ;
2018-03-14 08:57:08 +01:00
}
CMutableTransaction tx ;
tx . nVersion = 3 ;
tx . nType = TRANSACTION_PROVIDER_UPDATE_SERVICE ;
2018-12-28 10:24:48 +01:00
// param operatorPayoutAddress
if ( request . params . size ( ) > = 5 ) {
2019-01-12 14:17:16 +01:00
if ( request . params [ 4 ] . get_str ( ) . empty ( ) ) {
2018-12-28 10:24:48 +01:00
ptx . scriptOperatorPayout = dmn - > pdmnState - > scriptOperatorPayout ;
} else {
CBitcoinAddress payoutAddress ( request . params [ 4 ] . get_str ( ) ) ;
if ( ! payoutAddress . IsValid ( ) ) {
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , strprintf ( " invalid operator payout address: %s " , request . params [ 4 ] . get_str ( ) ) ) ;
}
ptx . scriptOperatorPayout = GetScriptForDestination ( payoutAddress . Get ( ) ) ;
}
} else {
ptx . scriptOperatorPayout = dmn - > pdmnState - > scriptOperatorPayout ;
}
CTxDestination feeSource ;
// param feeSourceAddress
if ( request . params . size ( ) > = 6 ) {
CBitcoinAddress feeSourceAddress = CBitcoinAddress ( request . params [ 5 ] . get_str ( ) ) ;
if ( ! feeSourceAddress . IsValid ( ) )
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , std : : string ( " Invalid Dash address: " ) + request . params [ 5 ] . get_str ( ) ) ;
feeSource = feeSourceAddress . Get ( ) ;
} else {
if ( ptx . scriptOperatorPayout ! = CScript ( ) ) {
// use operator reward address as default source for fees
ExtractDestination ( ptx . scriptOperatorPayout , feeSource ) ;
} else {
// use payout address as default source for fees
ExtractDestination ( dmn - > pdmnState - > scriptPayout , feeSource ) ;
}
}
2018-12-31 03:37:40 +01:00
FundSpecialTx ( pwallet , tx , ptx , feeSource ) ;
2018-12-28 10:24:48 +01:00
2018-11-01 22:57:10 +01:00
SignSpecialTxPayloadByHash ( tx , ptx , keyOperator ) ;
2018-03-14 08:57:08 +01:00
SetTxPayload ( tx , ptx ) ;
return SignAndSendSpecialTx ( tx ) ;
}
2019-04-25 17:37:08 +02:00
void protx_update_registrar_help ( CWallet * const pwallet )
2018-03-19 09:46:08 +01:00
{
throw std : : runtime_error (
2019-01-11 11:05:58 +01:00
" protx update_registrar \" proTxHash \" \" operatorPubKey \" \" votingAddress \" \" payoutAddress \" ( \" feeSourceAddress \" ) \n "
2018-03-19 09:46:08 +01:00
" \n Creates and sends a ProUpRegTx to the network. This will update the operator key, voting key and payout \n "
" address of the masternode specified by \" proTxHash \" . \n "
" The owner key of the masternode must be known to your wallet. \n "
2019-04-25 17:37:08 +02:00
+ HelpRequiringPassphrase ( pwallet ) + " \n "
2018-03-19 09:46:08 +01:00
" \n Arguments: \n "
2019-01-29 15:54:01 +01:00
+ GetHelpString ( 1 , " proTxHash " )
+ GetHelpString ( 2 , " operatorPubKey " )
+ GetHelpString ( 3 , " votingAddress " )
+ GetHelpString ( 4 , " payoutAddress " )
+ GetHelpString ( 5 , " feeSourceAddress " ) +
" \n Result: \n "
" \" txid \" (string) The transaction id. \n "
2018-03-19 09:46:08 +01:00
" \n Examples: \n "
2018-10-26 07:03:14 +02:00
+ HelpExampleCli ( " protx " , " update_registrar \" 0123456701234567012345670123456701234567012345670123456701234567 \" \" 982eb34b7c7f614f29e5c665bc3605f1beeef85e3395ca12d3be49d2868ecfea5566f11cedfad30c51b2403f2ad95b67 \" \" XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG \" " )
2018-03-19 09:46:08 +01:00
) ;
}
UniValue protx_update_registrar ( const JSONRPCRequest & request )
{
2018-12-29 21:15:02 +01:00
CWallet * const pwallet = GetWalletForJSONRPCRequest ( request ) ;
2018-12-28 10:24:48 +01:00
if ( request . fHelp | | ( request . params . size ( ) ! = 5 & & request . params . size ( ) ! = 6 ) ) {
2019-04-25 17:37:08 +02:00
protx_update_registrar_help ( pwallet ) ;
2018-10-26 07:03:14 +02:00
}
2018-03-19 09:46:08 +01:00
2019-04-25 17:37:08 +02:00
if ( ! EnsureWalletIsAvailable ( pwallet , request . fHelp ) )
return NullUniValue ;
EnsureWalletIsUnlocked ( pwallet ) ;
2018-03-19 09:46:08 +01:00
CProUpRegTx ptx ;
ptx . nVersion = CProRegTx : : CURRENT_VERSION ;
ptx . proTxHash = ParseHashV ( request . params [ 1 ] , " proTxHash " ) ;
auto dmn = deterministicMNManager - > GetListAtChainTip ( ) . GetMN ( ptx . proTxHash ) ;
if ( ! dmn ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , strprintf ( " masternode %s not found " , ptx . proTxHash . ToString ( ) ) ) ;
}
2018-10-21 21:45:16 +02:00
ptx . pubKeyOperator = dmn - > pdmnState - > pubKeyOperator ;
2018-03-19 09:46:08 +01:00
ptx . keyIDVoting = dmn - > pdmnState - > keyIDVoting ;
ptx . scriptPayout = dmn - > pdmnState - > scriptPayout ;
2019-01-12 14:17:16 +01:00
if ( request . params [ 2 ] . get_str ( ) ! = " " ) {
2018-10-21 21:45:16 +02:00
ptx . pubKeyOperator = ParseBLSPubKey ( request . params [ 2 ] . get_str ( ) , " operator BLS address " ) ;
2018-03-19 09:46:08 +01:00
}
2019-01-12 14:17:16 +01:00
if ( request . params [ 3 ] . get_str ( ) ! = " " ) {
2019-03-07 14:29:24 +01:00
ptx . keyIDVoting = ParsePubKeyIDFromAddress ( request . params [ 3 ] . get_str ( ) , " voting address " ) ;
2018-03-19 09:46:08 +01:00
}
CBitcoinAddress payoutAddress ( request . params [ 4 ] . get_str ( ) ) ;
2018-10-26 07:03:14 +02:00
if ( ! payoutAddress . IsValid ( ) ) {
2018-03-19 09:46:08 +01:00
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , strprintf ( " invalid payout address: %s " , request . params [ 4 ] . get_str ( ) ) ) ;
2018-10-26 07:03:14 +02:00
}
2018-03-19 09:46:08 +01:00
ptx . scriptPayout = GetScriptForDestination ( payoutAddress . Get ( ) ) ;
CKey keyOwner ;
2019-04-25 17:37:08 +02:00
if ( ! pwallet - > GetKey ( dmn - > pdmnState - > keyIDOwner , keyOwner ) ) {
2019-01-11 11:05:58 +01:00
throw std : : runtime_error ( strprintf ( " Private key for owner address %s not found in your wallet " , CBitcoinAddress ( dmn - > pdmnState - > keyIDOwner ) . ToString ( ) ) ) ;
2018-03-19 09:46:08 +01:00
}
CMutableTransaction tx ;
tx . nVersion = 3 ;
tx . nType = TRANSACTION_PROVIDER_UPDATE_REGISTRAR ;
2018-11-15 08:05:38 +01:00
// make sure we get anough fees added
ptx . vchSig . resize ( 65 ) ;
2018-12-28 10:24:48 +01:00
CBitcoinAddress feeSourceAddress = payoutAddress ;
if ( request . params . size ( ) > 5 ) {
feeSourceAddress = CBitcoinAddress ( request . params [ 5 ] . get_str ( ) ) ;
if ( ! feeSourceAddress . IsValid ( ) )
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , std : : string ( " Invalid Dash address: " ) + request . params [ 5 ] . get_str ( ) ) ;
}
2018-12-31 03:37:40 +01:00
FundSpecialTx ( pwallet , tx , ptx , feeSourceAddress . Get ( ) ) ;
2018-11-01 22:57:10 +01:00
SignSpecialTxPayloadByHash ( tx , ptx , keyOwner ) ;
2018-03-19 09:46:08 +01:00
SetTxPayload ( tx , ptx ) ;
return SignAndSendSpecialTx ( tx ) ;
}
2019-04-25 17:37:08 +02:00
void protx_revoke_help ( CWallet * const pwallet )
2018-03-19 12:45:15 +01:00
{
throw std : : runtime_error (
2018-12-28 10:24:48 +01:00
" protx revoke \" proTxHash \" \" operatorKey \" ( reason \" feeSourceAddress \" ) \n "
2018-03-19 12:45:15 +01:00
" \n Creates and sends a ProUpRevTx to the network. This will revoke the operator key of the masternode and \n "
2018-10-23 13:15:38 +02:00
" put it into the PoSe-banned state. It will also set the service field of the masternode \n "
2018-03-19 12:45:15 +01:00
" to zero. Use this in case your operator key got compromised or you want to stop providing your service \n "
" to the masternode owner. \n "
2019-04-25 17:37:08 +02:00
+ HelpRequiringPassphrase ( pwallet ) + " \n "
2018-03-19 12:45:15 +01:00
" \n Arguments: \n "
2019-01-29 15:54:01 +01:00
+ GetHelpString ( 1 , " proTxHash " )
+ GetHelpString ( 2 , " operatorKey " )
+ GetHelpString ( 3 , " reason " )
+ GetHelpString ( 4 , " feeSourceAddress " ) +
" \n Result: \n "
" \" txid \" (string) The transaction id. \n "
2018-03-19 12:45:15 +01:00
" \n Examples: \n "
2018-10-21 21:45:16 +02:00
+ HelpExampleCli ( " protx " , " revoke \" 0123456701234567012345670123456701234567012345670123456701234567 \" \" 072f36a77261cdd5d64c32d97bac417540eddca1d5612f416feb07ff75a8e240 \" " )
2018-03-19 12:45:15 +01:00
) ;
}
UniValue protx_revoke ( const JSONRPCRequest & request )
{
2018-12-31 03:37:40 +01:00
CWallet * const pwallet = GetWalletForJSONRPCRequest ( request ) ;
2018-12-28 10:24:48 +01:00
if ( request . fHelp | | ( request . params . size ( ) < 3 | | request . params . size ( ) > 5 ) ) {
2019-04-25 17:37:08 +02:00
protx_revoke_help ( pwallet ) ;
2018-10-26 07:03:14 +02:00
}
2018-03-19 12:45:15 +01:00
2019-04-25 17:37:08 +02:00
if ( ! EnsureWalletIsAvailable ( pwallet , request . fHelp ) )
return NullUniValue ;
EnsureWalletIsUnlocked ( pwallet ) ;
2018-03-19 12:45:15 +01:00
CProUpRevTx ptx ;
ptx . nVersion = CProRegTx : : CURRENT_VERSION ;
ptx . proTxHash = ParseHashV ( request . params [ 1 ] , " proTxHash " ) ;
2018-10-21 21:45:16 +02:00
CBLSSecretKey keyOperator = ParseBLSSecretKey ( request . params [ 2 ] . get_str ( ) , " operatorKey " ) ;
if ( request . params . size ( ) > 3 ) {
int32_t nReason = ParseInt32V ( request . params [ 3 ] , " reason " ) ;
2019-03-21 21:46:30 +01:00
if ( nReason < 0 | | nReason > CProUpRevTx : : REASON_LAST ) {
2018-03-19 12:45:15 +01:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , strprintf ( " invalid reason %d, must be between 0 and %d " , nReason , CProUpRevTx : : REASON_LAST ) ) ;
2018-10-26 07:03:14 +02:00
}
2018-03-19 12:45:15 +01:00
ptx . nReason = ( uint16_t ) nReason ;
}
auto dmn = deterministicMNManager - > GetListAtChainTip ( ) . GetMN ( ptx . proTxHash ) ;
if ( ! dmn ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , strprintf ( " masternode %s not found " , ptx . proTxHash . ToString ( ) ) ) ;
}
2018-10-21 21:45:16 +02:00
if ( keyOperator . GetPublicKey ( ) ! = dmn - > pdmnState - > pubKeyOperator ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , strprintf ( " the operator key does not belong to the registered public key " ) ) ;
2018-03-19 12:45:15 +01:00
}
CMutableTransaction tx ;
tx . nVersion = 3 ;
tx . nType = TRANSACTION_PROVIDER_UPDATE_REVOKE ;
2018-12-28 10:24:48 +01:00
if ( request . params . size ( ) > 4 ) {
CBitcoinAddress feeSourceAddress = CBitcoinAddress ( request . params [ 4 ] . get_str ( ) ) ;
if ( ! feeSourceAddress . IsValid ( ) )
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , std : : string ( " Invalid Dash address: " ) + request . params [ 4 ] . get_str ( ) ) ;
2018-12-31 03:37:40 +01:00
FundSpecialTx ( pwallet , tx , ptx , feeSourceAddress . Get ( ) ) ;
2018-12-28 10:24:48 +01:00
} else if ( dmn - > pdmnState - > scriptOperatorPayout ! = CScript ( ) ) {
// Using funds from previousely specified operator payout address
CTxDestination txDest ;
ExtractDestination ( dmn - > pdmnState - > scriptOperatorPayout , txDest ) ;
2018-12-31 03:37:40 +01:00
FundSpecialTx ( pwallet , tx , ptx , txDest ) ;
2018-12-28 10:24:48 +01:00
} else if ( dmn - > pdmnState - > scriptPayout ! = CScript ( ) ) {
// Using funds from previousely specified masternode payout address
CTxDestination txDest ;
ExtractDestination ( dmn - > pdmnState - > scriptPayout , txDest ) ;
2018-12-31 03:37:40 +01:00
FundSpecialTx ( pwallet , tx , ptx , txDest ) ;
2018-12-28 10:24:48 +01:00
} else {
throw JSONRPCError ( RPC_INTERNAL_ERROR , " No payout or fee source addresses found, can't revoke " ) ;
}
2018-11-01 22:57:10 +01:00
SignSpecialTxPayloadByHash ( tx , ptx , keyOperator ) ;
2018-03-19 12:45:15 +01:00
SetTxPayload ( tx , ptx ) ;
return SignAndSendSpecialTx ( tx ) ;
}
2018-11-29 19:51:31 +01:00
# endif //ENABLE_WALLET
2018-03-19 12:45:15 +01:00
2018-03-03 21:48:00 +01:00
void protx_list_help ( )
{
throw std : : runtime_error (
2018-12-17 07:06:45 +01:00
" protx list ( \" type \" \" detailed \" \" height \" ) \n "
" \n Lists all ProTxs in your wallet or on-chain, depending on the given type. \n "
" If \" type \" is not specified, it defaults to \" registered \" . \n "
" If \" detailed \" is not specified, it defaults to \" false \" and only the hashes of the ProTx will be returned. \n "
" If \" height \" is not specified, it defaults to the current chain-tip. \n "
2018-03-03 21:48:00 +01:00
" \n Available types: \n "
2018-12-17 07:06:45 +01:00
" registered - List all ProTx which are registered at the given chain height. \n "
" This will also include ProTx which failed PoSe verfication. \n "
" valid - List only ProTx which are active/valid at the given chain height. \n "
2018-11-29 19:51:31 +01:00
# ifdef ENABLE_WALLET
2018-12-17 07:06:45 +01:00
" wallet - List only ProTx which are found in your wallet at the given chain height. \n "
" This will also include ProTx which failed PoSe verfication. \n "
2018-11-29 19:51:31 +01:00
# endif
2018-03-03 21:48:00 +01:00
) ;
}
2018-12-29 21:15:02 +01:00
static bool CheckWalletOwnsKey ( CWallet * pwallet , const CKeyID & keyID ) {
2018-11-29 19:51:31 +01:00
# ifndef ENABLE_WALLET
return false ;
# else
2018-12-29 21:15:02 +01:00
if ( ! pwallet ) {
2018-11-29 19:51:31 +01:00
return false ;
}
2018-12-29 21:15:02 +01:00
return pwallet - > HaveKey ( keyID ) ;
2018-11-29 19:51:31 +01:00
# endif
}
2018-12-29 21:15:02 +01:00
static bool CheckWalletOwnsScript ( CWallet * pwallet , const CScript & script ) {
2018-11-29 19:51:31 +01:00
# ifndef ENABLE_WALLET
return false ;
# else
2018-12-29 21:15:02 +01:00
if ( ! pwallet ) {
2018-11-29 09:12:41 +01:00
return false ;
}
2018-03-03 21:48:00 +01:00
CTxDestination dest ;
if ( ExtractDestination ( script , dest ) ) {
2018-12-29 21:15:02 +01:00
if ( ( boost : : get < CKeyID > ( & dest ) & & pwallet - > HaveKey ( * boost : : get < CKeyID > ( & dest ) ) ) | | ( boost : : get < CScriptID > ( & dest ) & & pwallet - > HaveCScript ( * boost : : get < CScriptID > ( & dest ) ) ) ) {
2018-03-03 21:48:00 +01:00
return true ;
}
}
return false ;
2018-11-29 19:51:31 +01:00
# endif
2018-03-03 21:48:00 +01:00
}
2018-12-29 21:15:02 +01:00
UniValue BuildDMNListEntry ( CWallet * pwallet , const CDeterministicMNCPtr & dmn , bool detailed )
2018-03-03 21:48:00 +01:00
{
2018-10-26 07:03:14 +02:00
if ( ! detailed ) {
2018-03-03 21:48:00 +01:00
return dmn - > proTxHash . ToString ( ) ;
2018-10-26 07:03:14 +02:00
}
2018-03-03 21:48:00 +01:00
UniValue o ( UniValue : : VOBJ ) ;
dmn - > ToJson ( o ) ;
2018-10-25 16:29:50 +02:00
int confirmations = GetUTXOConfirmations ( dmn - > collateralOutpoint ) ;
2018-03-03 21:48:00 +01:00
o . push_back ( Pair ( " confirmations " , confirmations ) ) ;
2018-12-29 21:15:02 +01:00
bool hasOwnerKey = CheckWalletOwnsKey ( pwallet , dmn - > pdmnState - > keyIDOwner ) ;
2018-11-29 19:51:31 +01:00
bool hasOperatorKey = false ; //CheckWalletOwnsKey(dmn->pdmnState->keyIDOperator);
2018-12-29 21:15:02 +01:00
bool hasVotingKey = CheckWalletOwnsKey ( pwallet , dmn - > pdmnState - > keyIDVoting ) ;
2018-03-03 21:48:00 +01:00
bool ownsCollateral = false ;
CTransactionRef collateralTx ;
uint256 tmpHashBlock ;
2018-10-25 16:29:50 +02:00
if ( GetTransaction ( dmn - > collateralOutpoint . hash , collateralTx , Params ( ) . GetConsensus ( ) , tmpHashBlock ) ) {
2018-12-29 21:15:02 +01:00
ownsCollateral = CheckWalletOwnsScript ( pwallet , collateralTx - > vout [ dmn - > collateralOutpoint . n ] . scriptPubKey ) ;
2018-03-03 21:48:00 +01:00
}
UniValue walletObj ( UniValue : : VOBJ ) ;
walletObj . push_back ( Pair ( " hasOwnerKey " , hasOwnerKey ) ) ;
walletObj . push_back ( Pair ( " hasOperatorKey " , hasOperatorKey ) ) ;
walletObj . push_back ( Pair ( " hasVotingKey " , hasVotingKey ) ) ;
walletObj . push_back ( Pair ( " ownsCollateral " , ownsCollateral ) ) ;
2018-12-29 21:15:02 +01:00
walletObj . push_back ( Pair ( " ownsPayeeScript " , CheckWalletOwnsScript ( pwallet , dmn - > pdmnState - > scriptPayout ) ) ) ;
walletObj . push_back ( Pair ( " ownsOperatorRewardScript " , CheckWalletOwnsScript ( pwallet , dmn - > pdmnState - > scriptOperatorPayout ) ) ) ;
2018-03-03 21:48:00 +01:00
o . push_back ( Pair ( " wallet " , walletObj ) ) ;
return o ;
}
UniValue protx_list ( const JSONRPCRequest & request )
{
2018-10-26 07:03:14 +02:00
if ( request . fHelp ) {
2018-03-03 21:48:00 +01:00
protx_list_help ( ) ;
2018-10-26 07:03:14 +02:00
}
2018-03-03 21:48:00 +01:00
2018-11-29 19:51:31 +01:00
# ifdef ENABLE_WALLET
2019-01-25 17:52:27 +01:00
CWallet * const pwallet = GetWalletForJSONRPCRequest ( request ) ;
2018-11-29 19:51:31 +01:00
# else
2019-01-25 17:52:27 +01:00
CWallet * const pwallet = nullptr ;
2018-11-29 19:51:31 +01:00
# endif
2018-11-29 13:31:37 +01:00
std : : string type = " registered " ;
2018-10-26 07:03:14 +02:00
if ( request . params . size ( ) > 1 ) {
2018-03-03 21:48:00 +01:00
type = request . params [ 1 ] . get_str ( ) ;
2018-10-26 07:03:14 +02:00
}
2018-03-03 21:48:00 +01:00
UniValue ret ( UniValue : : VARR ) ;
2018-11-29 09:12:41 +01:00
LOCK ( cs_main ) ;
2018-03-03 21:48:00 +01:00
if ( type = = " wallet " ) {
2019-01-25 17:52:27 +01:00
if ( ! pwallet ) {
2018-11-29 09:12:41 +01:00
throw std : : runtime_error ( " \" protx list wallet \" not supported when wallet is disabled " ) ;
}
2018-11-29 19:51:31 +01:00
# ifdef ENABLE_WALLET
2018-12-29 21:15:02 +01:00
LOCK2 ( cs_main , pwallet - > cs_wallet ) ;
2018-11-29 09:12:41 +01:00
2018-10-26 07:03:14 +02:00
if ( request . params . size ( ) > 3 ) {
2018-03-03 21:48:00 +01:00
protx_list_help ( ) ;
2018-10-26 07:03:14 +02:00
}
2018-03-03 21:48:00 +01:00
bool detailed = request . params . size ( ) > 2 ? ParseBoolV ( request . params [ 2 ] , " detailed " ) : false ;
2018-12-17 07:06:45 +01:00
int height = request . params . size ( ) > 3 ? ParseInt32V ( request . params [ 3 ] , " height " ) : chainActive . Height ( ) ;
if ( height < 1 | | height > chainActive . Height ( ) ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " invalid height specified " ) ;
}
2018-03-03 21:48:00 +01:00
std : : vector < COutPoint > vOutpts ;
2018-12-29 21:15:02 +01:00
pwallet - > ListProTxCoins ( vOutpts ) ;
2018-10-25 16:29:50 +02:00
std : : set < COutPoint > setOutpts ;
2018-03-03 21:48:00 +01:00
for ( const auto & outpt : vOutpts ) {
2018-10-25 16:29:50 +02:00
setOutpts . emplace ( outpt ) ;
2018-03-03 21:48:00 +01:00
}
2018-12-17 07:06:45 +01:00
CDeterministicMNList mnList = deterministicMNManager - > GetListForBlock ( chainActive [ height ] - > GetBlockHash ( ) ) ;
mnList . ForEachMN ( false , [ & ] ( const CDeterministicMNCPtr & dmn ) {
2018-10-25 16:29:50 +02:00
if ( setOutpts . count ( dmn - > collateralOutpoint ) | |
2018-12-31 03:37:40 +01:00
CheckWalletOwnsKey ( pwallet , dmn - > pdmnState - > keyIDOwner ) | |
CheckWalletOwnsKey ( pwallet , dmn - > pdmnState - > keyIDVoting ) | |
2018-12-29 21:15:02 +01:00
CheckWalletOwnsScript ( pwallet , dmn - > pdmnState - > scriptPayout ) | |
CheckWalletOwnsScript ( pwallet , dmn - > pdmnState - > scriptOperatorPayout ) ) {
ret . push_back ( BuildDMNListEntry ( pwallet , dmn , detailed ) ) ;
2018-03-03 21:48:00 +01:00
}
2018-10-02 11:03:05 +02:00
} ) ;
2018-11-29 19:51:31 +01:00
# endif
2018-03-03 21:48:00 +01:00
} else if ( type = = " valid " | | type = = " registered " ) {
2018-10-26 07:03:14 +02:00
if ( request . params . size ( ) > 4 ) {
2018-03-03 21:48:00 +01:00
protx_list_help ( ) ;
2018-10-26 07:03:14 +02:00
}
2018-03-03 21:48:00 +01:00
LOCK ( cs_main ) ;
2018-12-17 07:06:45 +01:00
bool detailed = request . params . size ( ) > 2 ? ParseBoolV ( request . params [ 2 ] , " detailed " ) : false ;
int height = request . params . size ( ) > 3 ? ParseInt32V ( request . params [ 3 ] , " height " ) : chainActive . Height ( ) ;
2018-10-26 07:03:14 +02:00
if ( height < 1 | | height > chainActive . Height ( ) ) {
2018-03-03 21:48:00 +01:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " invalid height specified " ) ;
2018-10-26 07:03:14 +02:00
}
2018-03-03 21:48:00 +01:00
CDeterministicMNList mnList = deterministicMNManager - > GetListForBlock ( chainActive [ height ] - > GetBlockHash ( ) ) ;
2018-10-02 11:03:05 +02:00
bool onlyValid = type = = " valid " ;
mnList . ForEachMN ( onlyValid , [ & ] ( const CDeterministicMNCPtr & dmn ) {
2018-12-29 21:15:02 +01:00
ret . push_back ( BuildDMNListEntry ( pwallet , dmn , detailed ) ) ;
2018-10-02 11:03:05 +02:00
} ) ;
2018-03-03 21:48:00 +01:00
} else {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " invalid type specified " ) ;
}
return ret ;
}
2018-10-25 16:29:50 +02:00
void protx_info_help ( )
{
throw std : : runtime_error (
" protx info \" proTxHash \" \n "
" \n Returns detailed information about a deterministic masternode. \n "
" \n Arguments: \n "
2019-01-29 15:54:01 +01:00
+ GetHelpString ( 1 , " proTxHash " ) +
" \n Result: \n "
" { (json object) Details about a specific deterministic masternode \n "
" } \n "
" \n Examples: \n "
+ HelpExampleCli ( " protx " , " info \" 0123456701234567012345670123456701234567012345670123456701234567 \" " )
2018-10-25 16:29:50 +02:00
) ;
}
UniValue protx_info ( const JSONRPCRequest & request )
{
2018-10-26 07:03:14 +02:00
if ( request . fHelp | | request . params . size ( ) ! = 2 ) {
2018-10-25 16:29:50 +02:00
protx_info_help ( ) ;
2018-10-26 07:03:14 +02:00
}
2018-10-25 16:29:50 +02:00
2019-01-25 17:52:27 +01:00
# ifdef ENABLE_WALLET
CWallet * const pwallet = GetWalletForJSONRPCRequest ( request ) ;
# else
CWallet * const pwallet = nullptr ;
# endif
2018-10-25 16:29:50 +02:00
uint256 proTxHash = ParseHashV ( request . params [ 1 ] , " proTxHash " ) ;
auto mnList = deterministicMNManager - > GetListAtChainTip ( ) ;
auto dmn = mnList . GetMN ( proTxHash ) ;
if ( ! dmn ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , strprintf ( " %s not found " , proTxHash . ToString ( ) ) ) ;
}
2018-12-29 21:15:02 +01:00
return BuildDMNListEntry ( pwallet , dmn , true ) ;
2018-10-25 16:29:50 +02:00
}
2018-04-09 14:49:34 +02:00
void protx_diff_help ( )
{
throw std : : runtime_error (
" protx diff \" baseBlock \" \" block \" \n "
" \n Calculates a diff between two deterministic masternode lists. The result also contains proof data. \n "
2018-11-02 09:18:05 +01:00
" \n Arguments: \n "
" 1. \" baseBlock \" (numeric, required) The starting block height. \n "
" 2. \" block \" (numeric, required) The ending block height. \n "
2018-04-09 14:49:34 +02:00
) ;
}
static uint256 ParseBlock ( const UniValue & v , std : : string strName )
{
AssertLockHeld ( cs_main ) ;
try {
return ParseHashV ( v , strName ) ;
} catch ( . . . ) {
int h = ParseInt32V ( v , strName ) ;
if ( h < 1 | | h > chainActive . Height ( ) )
throw std : : runtime_error ( strprintf ( " %s must be a block hash or chain height and not %s " , strName , v . getValStr ( ) ) ) ;
return * chainActive [ h ] - > phashBlock ;
}
}
UniValue protx_diff ( const JSONRPCRequest & request )
{
2018-10-26 07:03:14 +02:00
if ( request . fHelp | | request . params . size ( ) ! = 3 ) {
2018-04-09 14:49:34 +02:00
protx_diff_help ( ) ;
2018-10-26 07:03:14 +02:00
}
2018-04-09 14:49:34 +02:00
LOCK ( cs_main ) ;
uint256 baseBlockHash = ParseBlock ( request . params [ 1 ] , " baseBlock " ) ;
uint256 blockHash = ParseBlock ( request . params [ 2 ] , " block " ) ;
CSimplifiedMNListDiff mnListDiff ;
std : : string strError ;
if ( ! BuildSimplifiedMNListDiff ( baseBlockHash , blockHash , mnListDiff , strError ) ) {
throw std : : runtime_error ( strError ) ;
}
UniValue ret ;
mnListDiff . ToJson ( ret ) ;
return ret ;
}
2018-11-05 10:28:38 +01:00
[[ noreturn ]] void protx_help ( )
{
throw std : : runtime_error (
" protx \" command \" ... \n "
" Set of commands to execute ProTx related actions. \n "
" To get help on individual commands, use \" help protx command \" . \n "
" \n Arguments: \n "
" 1. \" command \" (string, required) The command to execute \n "
" \n Available commands: \n "
2018-11-29 19:51:31 +01:00
# ifdef ENABLE_WALLET
2018-11-05 10:28:38 +01:00
" register - Create and send ProTx to network \n "
" register_fund - Fund, create and send ProTx to network \n "
" register_prepare - Create an unsigned ProTx \n "
" register_submit - Sign and submit a ProTx \n "
2018-11-29 19:51:31 +01:00
# endif
2018-11-05 10:28:38 +01:00
" list - List ProTxs \n "
" info - Return information about a ProTx \n "
2018-11-29 19:51:31 +01:00
# ifdef ENABLE_WALLET
2018-11-05 10:28:38 +01:00
" update_service - Create and send ProUpServTx to network \n "
" update_registrar - Create and send ProUpRegTx to network \n "
" revoke - Create and send ProUpRevTx to network \n "
2018-11-29 19:51:31 +01:00
# endif
2018-11-05 10:28:38 +01:00
" diff - Calculate a diff and a proof between two masternode lists \n "
) ;
}
2018-04-09 14:49:34 +02:00
2018-02-13 13:36:59 +01:00
UniValue protx ( const JSONRPCRequest & request )
{
2018-11-09 07:48:26 +01:00
if ( request . fHelp & & request . params . empty ( ) ) {
2018-11-05 10:28:38 +01:00
protx_help ( ) ;
2018-02-13 13:36:59 +01:00
}
2018-11-13 13:23:52 +01:00
std : : string command ;
if ( request . params . size ( ) > = 1 ) {
command = request . params [ 0 ] . get_str ( ) ;
}
2018-02-13 13:36:59 +01:00
2018-11-29 19:51:31 +01:00
# ifdef ENABLE_WALLET
2018-11-01 22:57:10 +01:00
if ( command = = " register " | | command = = " register_fund " | | command = = " register_prepare " ) {
2018-02-13 13:36:59 +01:00
return protx_register ( request ) ;
2019-04-25 17:37:08 +02:00
} else if ( command = = " register_submit " ) {
2018-11-01 22:57:10 +01:00
return protx_register_submit ( request ) ;
2018-03-14 08:57:08 +01:00
} else if ( command = = " update_service " ) {
return protx_update_service ( request ) ;
2018-03-19 09:46:08 +01:00
} else if ( command = = " update_registrar " ) {
return protx_update_registrar ( request ) ;
2018-03-19 12:45:15 +01:00
} else if ( command = = " revoke " ) {
return protx_revoke ( request ) ;
2018-11-29 19:51:31 +01:00
} else
# endif
if ( command = = " list " ) {
return protx_list ( request ) ;
} else if ( command = = " info " ) {
return protx_info ( request ) ;
2018-04-09 14:49:34 +02:00
} else if ( command = = " diff " ) {
return protx_diff ( request ) ;
2018-02-13 13:36:59 +01:00
} else {
2018-11-05 10:28:38 +01:00
protx_help ( ) ;
2018-02-13 13:36:59 +01:00
}
}
2018-11-01 22:57:43 +01:00
void bls_generate_help ( )
{
throw std : : runtime_error (
" bls generate \n "
" \n Returns a BLS secret/public key pair. \n "
" \n Result: \n "
" { \n "
" \" secret \" : \" xxxx \" , (string) BLS secret key \n "
" \" public \" : \" xxxx \" , (string) BLS public key \n "
" } \n "
" \n Examples: \n "
+ HelpExampleCli ( " bls generate " , " " )
) ;
}
2018-10-21 21:45:16 +02:00
UniValue bls_generate ( const JSONRPCRequest & request )
{
2018-11-01 22:57:43 +01:00
if ( request . fHelp | | request . params . size ( ) ! = 1 ) {
bls_generate_help ( ) ;
}
2018-10-21 21:45:16 +02:00
CBLSSecretKey sk ;
sk . MakeNewKey ( ) ;
UniValue ret ( UniValue : : VOBJ ) ;
ret . push_back ( Pair ( " secret " , sk . ToString ( ) ) ) ;
ret . push_back ( Pair ( " public " , sk . GetPublicKey ( ) . ToString ( ) ) ) ;
return ret ;
}
2019-04-08 07:06:54 +02:00
void bls_fromsecret_help ( )
{
throw std : : runtime_error (
" bls fromsecret \" secret \" \n "
" \n Parses a BLS secret key and returns the secret/public key pair. \n "
" \n Arguments: \n "
" 1. \" secret \" (string, required) The BLS secret key \n "
" \n Result: \n "
" { \n "
" \" secret \" : \" xxxx \" , (string) BLS secret key \n "
" \" public \" : \" xxxx \" , (string) BLS public key \n "
" } \n "
" \n Examples: \n "
+ HelpExampleCli ( " bls fromsecret " , " 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f " )
) ;
}
UniValue bls_fromsecret ( const JSONRPCRequest & request )
{
if ( request . fHelp | | request . params . size ( ) ! = 2 ) {
bls_fromsecret_help ( ) ;
}
CBLSSecretKey sk ;
if ( ! sk . SetHexStr ( request . params [ 1 ] . get_str ( ) ) ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , strprintf ( " Secret key must be a valid hex string of length %d " , sk . SerSize * 2 ) ) ;
}
UniValue ret ( UniValue : : VOBJ ) ;
ret . push_back ( Pair ( " secret " , sk . ToString ( ) ) ) ;
ret . push_back ( Pair ( " public " , sk . GetPublicKey ( ) . ToString ( ) ) ) ;
return ret ;
}
2018-11-05 10:28:38 +01:00
[[ noreturn ]] void bls_help ( )
2018-11-01 22:57:43 +01:00
{
throw std : : runtime_error (
" bls \" command \" ... \n "
" Set of commands to execute BLS related actions. \n "
" To get help on individual commands, use \" help bls command \" . \n "
" \n Arguments: \n "
" 1. \" command \" (string, required) The command to execute \n "
" \n Available commands: \n "
" generate - Create a BLS secret/public key pair \n "
2019-04-08 07:06:54 +02:00
" fromsecret - Parse a BLS secret key and return the secret/public key pair \n "
2018-11-01 22:57:43 +01:00
) ;
}
2018-10-21 21:45:16 +02:00
UniValue _bls ( const JSONRPCRequest & request )
{
2018-11-13 13:23:52 +01:00
if ( request . fHelp & & request . params . empty ( ) ) {
2018-11-01 22:57:43 +01:00
bls_help ( ) ;
2018-10-21 21:45:16 +02:00
}
2018-11-13 13:23:52 +01:00
std : : string command ;
if ( request . params . size ( ) > = 1 ) {
command = request . params [ 0 ] . get_str ( ) ;
}
2018-10-21 21:45:16 +02:00
if ( command = = " generate " ) {
return bls_generate ( request ) ;
2019-04-08 07:06:54 +02:00
} else if ( command = = " fromsecret " ) {
return bls_fromsecret ( request ) ;
2018-10-21 21:45:16 +02:00
} else {
2018-11-01 22:57:43 +01:00
bls_help ( ) ;
2018-10-21 21:45:16 +02:00
}
}
2018-02-13 13:36:59 +01:00
static const CRPCCommand commands [ ] =
{ // category name actor (function) okSafeMode
// --------------------- ------------------------ ----------------------- ----------
2018-10-21 21:45:16 +02:00
{ " evo " , " bls " , & _bls , false , { } } ,
2018-02-13 13:36:59 +01:00
{ " evo " , " protx " , & protx , false , { } } ,
} ;
void RegisterEvoRPCCommands ( CRPCTable & tableRPC )
{
2018-10-26 07:03:14 +02:00
for ( unsigned int vcidx = 0 ; vcidx < ARRAYLEN ( commands ) ; vcidx + + ) {
2018-02-13 13:36:59 +01:00
tableRPC . appendCommand ( commands [ vcidx ] . name , & commands [ vcidx ] ) ;
2018-10-26 07:03:14 +02:00
}
2018-02-13 13:36:59 +01:00
}