Skip to content

Commit

Permalink
Implement "protx list" RPC
Browse files Browse the repository at this point in the history
  • Loading branch information
codablock committed Aug 30, 2018
1 parent 2c17287 commit 5e3abec
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 0 deletions.
134 changes: 134 additions & 0 deletions src/rpc/rpcevo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "evo/specialtx.h"
#include "evo/providertx.h"
#include "evo/deterministicmns.h"

#ifdef ENABLE_WALLET
extern UniValue signrawtransaction(const JSONRPCRequest& request);
Expand Down Expand Up @@ -239,6 +240,136 @@ UniValue protx_register(const JSONRPCRequest& request)
return SignAndSendSpecialTx(tx);
}

void protx_list_help()
{
throw std::runtime_error(
"protx list (\"type\")\n"
"\nLists all ProTxs in your wallet or on-chain, depending on the given type. If \"type\" is not\n"
"specified, it defaults to \"wallet\". All types have the optional argument \"detailed\" which if set to\n"
"\"true\" will result in a detailed list to be returned. If set to \"false\", only the hashes of the ProTx\n"
"will be returned.\n"
"\nAvailable types:\n"
" wallet (detailed) - List only ProTx which are found in your wallet. This will also include ProTx which\n"
" failed PoSe verfication\n"
" valid (height) (detailed) - List only ProTx which are active/valid at the given chain height. If height is not\n"
" specified, it defaults to the current chain-tip\n"
" registered (height) (detaileD) - List all ProTx which are registered at the given chain height. If height is not\n"
" specified, it defaults to the current chain-tip. This will also include ProTx\n"
" which failed PoSe verification at that height\n"
);
}

static bool CheckWalletOwnsScript(const CScript& script) {
CTxDestination dest;
if (ExtractDestination(script, dest)) {
if ((boost::get<CKeyID>(&dest) && pwalletMain->HaveKey(*boost::get<CKeyID>(&dest))) || (boost::get<CScriptID>(&dest) && pwalletMain->HaveCScript(*boost::get<CScriptID>(&dest)))) {
return true;
}
}
return false;
}

UniValue BuildDMNListEntry(const CDeterministicMNCPtr& dmn, bool detailed)
{
if (!detailed)
return dmn->proTxHash.ToString();

UniValue o(UniValue::VOBJ);

dmn->ToJson(o);

int confirmations = GetUTXOConfirmations(COutPoint(dmn->proTxHash, dmn->nCollateralIndex));
o.push_back(Pair("confirmations", confirmations));

bool hasOwnerKey = pwalletMain->HaveKey(dmn->pdmnState->keyIDOwner);
bool hasOperatorKey = pwalletMain->HaveKey(dmn->pdmnState->keyIDOperator);
bool hasVotingKey = pwalletMain->HaveKey(dmn->pdmnState->keyIDVoting);

bool ownsCollateral = false;
CTransactionRef collateralTx;
uint256 tmpHashBlock;
if (GetTransaction(dmn->proTxHash, collateralTx, Params().GetConsensus(), tmpHashBlock)) {
ownsCollateral = CheckWalletOwnsScript(collateralTx->vout[dmn->nCollateralIndex].scriptPubKey);
}

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));
walletObj.push_back(Pair("ownsPayeeScript", CheckWalletOwnsScript(dmn->pdmnState->scriptPayout)));
walletObj.push_back(Pair("ownsOperatorRewardScript", CheckWalletOwnsScript(dmn->pdmnState->scriptOperatorPayout)));
o.push_back(Pair("wallet", walletObj));

return o;
}

UniValue protx_list(const JSONRPCRequest& request)
{
if (request.fHelp)
protx_list_help();

std::string type = "wallet";
if (request.params.size() > 1)
type = request.params[1].get_str();

UniValue ret(UniValue::VARR);

LOCK2(cs_main, pwalletMain->cs_wallet);

if (type == "wallet") {
if (request.params.size() > 3)
protx_list_help();

bool detailed = request.params.size() > 2 ? ParseBoolV(request.params[2], "detailed") : false;

std::vector<COutPoint> vOutpts;
pwalletMain->ListProTxCoins(vOutpts);
std::set<uint256> setOutpts;
for (const auto& outpt : vOutpts) {
setOutpts.emplace(outpt.hash);
}

for (const auto& dmn : deterministicMNManager->GetListAtChainTip().all_range()) {
if (setOutpts.count(dmn->proTxHash) ||
pwalletMain->HaveKey(dmn->pdmnState->keyIDOwner) ||
pwalletMain->HaveKey(dmn->pdmnState->keyIDOperator) ||
pwalletMain->HaveKey(dmn->pdmnState->keyIDVoting) ||
CheckWalletOwnsScript(dmn->pdmnState->scriptPayout) ||
CheckWalletOwnsScript(dmn->pdmnState->scriptOperatorPayout)) {
ret.push_back(BuildDMNListEntry(dmn, detailed));
}
}
} else if (type == "valid" || type == "registered") {
if (request.params.size() > 4)
protx_list_help();

LOCK(cs_main);

int height = request.params.size() > 2 ? ParseInt32V(request.params[2], "height") : chainActive.Height();
if (height < 1 || height > chainActive.Height())
throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid height specified");

bool detailed = request.params.size() > 3 ? ParseBoolV(request.params[3], "detailed") : false;

CDeterministicMNList mnList = deterministicMNManager->GetListForBlock(chainActive[height]->GetBlockHash());
CDeterministicMNList::range_type range;

if (type == "valid") {
range = mnList.valid_range();
} else if (type == "registered") {
range = mnList.all_range();
}
for (const auto& dmn : range) {
ret.push_back(BuildDMNListEntry(dmn, detailed));
}
} else {
throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid type specified");
}

return ret;
}

UniValue protx(const JSONRPCRequest& request)
{
if (request.params.empty()) {
Expand All @@ -250,13 +381,16 @@ UniValue protx(const JSONRPCRequest& request)
"1. \"command\" (string, required) The command to execute\n"
"\nAvailable commands:\n"
" register - Create and send ProTx to network\n"
" list - List ProTxs\n"
);
}

std::string command = request.params[0].get_str();

if (command == "register") {
return protx_register(request);
} else if (command == "list") {
return protx_list(request);
} else {
throw std::runtime_error("invalid command: " + command);
}
Expand Down
13 changes: 13 additions & 0 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4636,6 +4636,19 @@ void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
}
}

void CWallet::ListProTxCoins(std::vector<COutPoint>& vOutpts)
{
AssertLockHeld(cs_wallet);
for (const auto &o : setWalletUTXO) {
if (mapWallet.count(o.hash)) {
const auto &p = mapWallet[o.hash];
if (IsProTxCollateral(*p.tx, o.n)) {
vOutpts.emplace_back(o);
}
}
}
}

/** @} */ // end of Actions

class CAffectedKeysVisitor : public boost::static_visitor<void> {
Expand Down
1 change: 1 addition & 0 deletions src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
void UnlockCoin(const COutPoint& output);
void UnlockAllCoins();
void ListLockedCoins(std::vector<COutPoint>& vOutpts);
void ListProTxCoins(std::vector<COutPoint>& vOutpts);

/**
* keystore implementation
Expand Down

0 comments on commit 5e3abec

Please sign in to comment.