cleanwallettransactions
This commit is contained in:
@@ -364,16 +364,16 @@ static const CRPCCommand vRPCCommands[] =
|
|||||||
|
|
||||||
// auction
|
// auction
|
||||||
{ "auction", "auctionaddress", &auctionaddress, true },
|
{ "auction", "auctionaddress", &auctionaddress, true },
|
||||||
|
|
||||||
// lotto
|
// lotto
|
||||||
{ "lotto", "lottoaddress", &lottoaddress, true },
|
{ "lotto", "lottoaddress", &lottoaddress, true },
|
||||||
|
|
||||||
// fsm
|
// fsm
|
||||||
{ "FSM", "FSMaddress", &FSMaddress, true },
|
{ "FSM", "FSMaddress", &FSMaddress, true },
|
||||||
{ "FSM", "FSMcreate", &FSMcreate, true },
|
{ "FSM", "FSMcreate", &FSMcreate, true },
|
||||||
{ "FSM", "FSMlist", &FSMlist, true },
|
{ "FSM", "FSMlist", &FSMlist, true },
|
||||||
{ "FSM", "FSMinfo", &FSMinfo, true },
|
{ "FSM", "FSMinfo", &FSMinfo, true },
|
||||||
|
|
||||||
// rewards
|
// rewards
|
||||||
{ "rewards", "rewardslist", &rewardslist, true },
|
{ "rewards", "rewardslist", &rewardslist, true },
|
||||||
{ "rewards", "rewardsinfo", &rewardsinfo, true },
|
{ "rewards", "rewardsinfo", &rewardsinfo, true },
|
||||||
@@ -382,7 +382,7 @@ static const CRPCCommand vRPCCommands[] =
|
|||||||
{ "rewards", "rewardslock", &rewardslock, true },
|
{ "rewards", "rewardslock", &rewardslock, true },
|
||||||
{ "rewards", "rewardsunlock", &rewardsunlock, true },
|
{ "rewards", "rewardsunlock", &rewardsunlock, true },
|
||||||
{ "rewards", "rewardsaddress", &rewardsaddress, true },
|
{ "rewards", "rewardsaddress", &rewardsaddress, true },
|
||||||
|
|
||||||
// faucet
|
// faucet
|
||||||
{ "faucet", "faucetinfo", &faucetinfo, true },
|
{ "faucet", "faucetinfo", &faucetinfo, true },
|
||||||
{ "faucet", "faucetfund", &faucetfund, true },
|
{ "faucet", "faucetfund", &faucetfund, true },
|
||||||
@@ -399,7 +399,7 @@ static const CRPCCommand vRPCCommands[] =
|
|||||||
{ "channels", "channelspayment", &channelspayment, true },
|
{ "channels", "channelspayment", &channelspayment, true },
|
||||||
{ "channels", "channelsclose", &channelsclose, true },
|
{ "channels", "channelsclose", &channelsclose, true },
|
||||||
{ "channels", "channelsrefund", &channelsrefund, true },
|
{ "channels", "channelsrefund", &channelsrefund, true },
|
||||||
|
|
||||||
// Oracles
|
// Oracles
|
||||||
{ "oracles", "oraclesaddress", &oraclesaddress, true },
|
{ "oracles", "oraclesaddress", &oraclesaddress, true },
|
||||||
{ "oracles", "oracleslist", &oracleslist, true },
|
{ "oracles", "oracleslist", &oracleslist, true },
|
||||||
@@ -508,6 +508,7 @@ static const CRPCCommand vRPCCommands[] =
|
|||||||
{ "wallet", "getaccountaddress", &getaccountaddress, true },
|
{ "wallet", "getaccountaddress", &getaccountaddress, true },
|
||||||
{ "wallet", "getaccount", &getaccount, true },
|
{ "wallet", "getaccount", &getaccount, true },
|
||||||
{ "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true },
|
{ "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true },
|
||||||
|
{ "wallet", "cleanwallettransactions", &cleanwallettransactions, false },
|
||||||
{ "wallet", "getbalance", &getbalance, false },
|
{ "wallet", "getbalance", &getbalance, false },
|
||||||
{ "wallet", "getbalance64", &getbalance64, false },
|
{ "wallet", "getbalance64", &getbalance64, false },
|
||||||
{ "wallet", "getnewaddress", &getnewaddress, true },
|
{ "wallet", "getnewaddress", &getnewaddress, true },
|
||||||
|
|||||||
@@ -317,6 +317,7 @@ extern UniValue signmessage(const UniValue& params, bool fHelp);
|
|||||||
extern UniValue verifymessage(const UniValue& params, bool fHelp);
|
extern UniValue verifymessage(const UniValue& params, bool fHelp);
|
||||||
extern UniValue getreceivedbyaddress(const UniValue& params, bool fHelp);
|
extern UniValue getreceivedbyaddress(const UniValue& params, bool fHelp);
|
||||||
extern UniValue getreceivedbyaccount(const UniValue& params, bool fHelp);
|
extern UniValue getreceivedbyaccount(const UniValue& params, bool fHelp);
|
||||||
|
extern UniValue cleanwallettransactions(const UniValue& params, bool fHelp);
|
||||||
extern UniValue getbalance(const UniValue& params, bool fHelp);
|
extern UniValue getbalance(const UniValue& params, bool fHelp);
|
||||||
extern UniValue getbalance64(const UniValue& params, bool fHelp);
|
extern UniValue getbalance64(const UniValue& params, bool fHelp);
|
||||||
extern UniValue getunconfirmedbalance(const UniValue& params, bool fHelp);
|
extern UniValue getunconfirmedbalance(const UniValue& params, bool fHelp);
|
||||||
|
|||||||
@@ -1015,6 +1015,108 @@ CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminef
|
|||||||
return GetAccountBalance(walletdb, strAccount, nMinDepth, filter);
|
return GetAccountBalance(walletdb, strAccount, nMinDepth, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UniValue cleanwallettransactions(const UniValue& params, bool fHelp)
|
||||||
|
{
|
||||||
|
if (!EnsureWalletIsAvailable(fHelp))
|
||||||
|
return NullUniValue;
|
||||||
|
|
||||||
|
if (fHelp || params.size() > 1 )
|
||||||
|
throw runtime_error(
|
||||||
|
"cleanwallettransactions \"txid\"\n"
|
||||||
|
"\nRemove all txs that are spent. You can clear all txs bar one, by specifiying a txid.\n"
|
||||||
|
"\nPlease backup your wallet.dat before running this command.\n"
|
||||||
|
"\nArguments:\n"
|
||||||
|
"1. \"txid\" (string, optional) The transaction id to keep.\n"
|
||||||
|
"\nResult:\n"
|
||||||
|
"{\n"
|
||||||
|
" \"total_transactons\" : n, (numeric) Transactions in wallet of " + strprintf("%s",komodo_chainname()) + "\n"
|
||||||
|
" \"remaining_transactons\" : n, (numeric) Transactions in wallet after clean.\n"
|
||||||
|
" \"removed_transactons\" : n, (numeric) The number of transactions removed.\n"
|
||||||
|
"}\n"
|
||||||
|
"\nExamples:\n"
|
||||||
|
+ HelpExampleCli("cleanwallettransactions", "")
|
||||||
|
+ HelpExampleCli("cleanwallettransactions","\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
|
||||||
|
+ HelpExampleRpc("cleanwallettransactions", "")
|
||||||
|
+ HelpExampleRpc("cleanwallettransactions","\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
|
||||||
|
);
|
||||||
|
|
||||||
|
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||||
|
UniValue ret(UniValue::VOBJ);
|
||||||
|
uint256 exception; int32_t txs = pwalletMain->mapWallet.size();
|
||||||
|
std::vector<uint256> TxToRemove;
|
||||||
|
if (params.size() == 1)
|
||||||
|
{
|
||||||
|
exception.SetHex(params[0].get_str());
|
||||||
|
uint256 tmp_hash; CTransaction tmp_tx;
|
||||||
|
if (GetTransaction(exception,tmp_tx,tmp_hash,false))
|
||||||
|
{
|
||||||
|
if ( !pwalletMain->IsMine(tmp_tx) )
|
||||||
|
{
|
||||||
|
throw runtime_error("\nThe transaction is not yours!\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||||
|
{
|
||||||
|
const CWalletTx& wtx = (*it).second;
|
||||||
|
if ( wtx.GetHash() != exception )
|
||||||
|
{
|
||||||
|
TxToRemove.push_back(wtx.GetHash());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw runtime_error("\nThe transaction could not be found!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// get all locked utxos to relock them later.
|
||||||
|
vector<COutPoint> vLockedUTXO;
|
||||||
|
pwalletMain->ListLockedCoins(vLockedUTXO);
|
||||||
|
// unlock all coins so that the following call containes all utxos.
|
||||||
|
pwalletMain->UnlockAllCoins();
|
||||||
|
// listunspent call... this gets us all the txids that are unspent, we search this list for the oldest tx,
|
||||||
|
vector<COutput> vecOutputs;
|
||||||
|
assert(pwalletMain != NULL);
|
||||||
|
pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
|
||||||
|
int32_t oldestTxDepth = 0;
|
||||||
|
BOOST_FOREACH(const COutput& out, vecOutputs)
|
||||||
|
{
|
||||||
|
if ( out.nDepth > oldestTxDepth )
|
||||||
|
oldestTxDepth = out.nDepth;
|
||||||
|
}
|
||||||
|
oldestTxDepth = oldestTxDepth + 1; // add extra block just for safety.
|
||||||
|
// lock all the previouly locked coins.
|
||||||
|
BOOST_FOREACH(COutPoint &outpt, vLockedUTXO) {
|
||||||
|
pwalletMain->LockCoin(outpt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// then add all txs in the wallet before this block to the list to remove.
|
||||||
|
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||||
|
{
|
||||||
|
const CWalletTx& wtx = (*it).second;
|
||||||
|
if (wtx.GetDepthInMainChain() > oldestTxDepth)
|
||||||
|
TxToRemove.push_back(wtx.GetHash());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// erase txs
|
||||||
|
BOOST_FOREACH (uint256& hash, TxToRemove)
|
||||||
|
{
|
||||||
|
pwalletMain->EraseFromWallet(hash);
|
||||||
|
LogPrintf("Erased %s from wallet.\n",hash.ToString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// build return JSON for stats.
|
||||||
|
int remaining = pwalletMain->mapWallet.size();
|
||||||
|
ret.push_back(Pair("total_transactons", (int)txs));
|
||||||
|
ret.push_back(Pair("remaining_transactons", (int)remaining));
|
||||||
|
ret.push_back(Pair("removed_transactions", (int)(txs-remaining)));
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
UniValue getbalance(const UniValue& params, bool fHelp)
|
UniValue getbalance(const UniValue& params, bool fHelp)
|
||||||
{
|
{
|
||||||
@@ -1674,7 +1776,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
|
|||||||
if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY))
|
if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY))
|
||||||
entry.push_back(Pair("involvesWatchonly", true));
|
entry.push_back(Pair("involvesWatchonly", true));
|
||||||
entry.push_back(Pair("account", account));
|
entry.push_back(Pair("account", account));
|
||||||
|
|
||||||
CTxDestination dest;
|
CTxDestination dest;
|
||||||
if (CScriptExt::ExtractVoutDestination(wtx, r.vout, dest))
|
if (CScriptExt::ExtractVoutDestination(wtx, r.vout, dest))
|
||||||
MaybePushAddress(entry, dest);
|
MaybePushAddress(entry, dest);
|
||||||
@@ -2920,11 +3022,11 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
|
|||||||
// User did not provide zaddrs, so use default i.e. all addresses
|
// User did not provide zaddrs, so use default i.e. all addresses
|
||||||
std::set<libzcash::SproutPaymentAddress> sproutzaddrs = {};
|
std::set<libzcash::SproutPaymentAddress> sproutzaddrs = {};
|
||||||
pwalletMain->GetSproutPaymentAddresses(sproutzaddrs);
|
pwalletMain->GetSproutPaymentAddresses(sproutzaddrs);
|
||||||
|
|
||||||
// Sapling support
|
// Sapling support
|
||||||
std::set<libzcash::SaplingPaymentAddress> saplingzaddrs = {};
|
std::set<libzcash::SaplingPaymentAddress> saplingzaddrs = {};
|
||||||
pwalletMain->GetSaplingPaymentAddresses(saplingzaddrs);
|
pwalletMain->GetSaplingPaymentAddresses(saplingzaddrs);
|
||||||
|
|
||||||
zaddrs.insert(sproutzaddrs.begin(), sproutzaddrs.end());
|
zaddrs.insert(sproutzaddrs.begin(), sproutzaddrs.end());
|
||||||
zaddrs.insert(saplingzaddrs.begin(), saplingzaddrs.end());
|
zaddrs.insert(saplingzaddrs.begin(), saplingzaddrs.end());
|
||||||
}
|
}
|
||||||
@@ -2936,7 +3038,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
|
|||||||
std::vector<SaplingNoteEntry> saplingEntries;
|
std::vector<SaplingNoteEntry> saplingEntries;
|
||||||
pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs, nMinDepth, nMaxDepth, true, !fIncludeWatchonly, false);
|
pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs, nMinDepth, nMaxDepth, true, !fIncludeWatchonly, false);
|
||||||
std::set<std::pair<PaymentAddress, uint256>> nullifierSet = pwalletMain->GetNullifiersForAddresses(zaddrs);
|
std::set<std::pair<PaymentAddress, uint256>> nullifierSet = pwalletMain->GetNullifiersForAddresses(zaddrs);
|
||||||
|
|
||||||
for (auto & entry : sproutEntries) {
|
for (auto & entry : sproutEntries) {
|
||||||
UniValue obj(UniValue::VOBJ);
|
UniValue obj(UniValue::VOBJ);
|
||||||
obj.push_back(Pair("txid", entry.jsop.hash.ToString()));
|
obj.push_back(Pair("txid", entry.jsop.hash.ToString()));
|
||||||
@@ -2954,7 +3056,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
|
|||||||
}
|
}
|
||||||
results.push_back(obj);
|
results.push_back(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto & entry : saplingEntries) {
|
for (auto & entry : saplingEntries) {
|
||||||
UniValue obj(UniValue::VOBJ);
|
UniValue obj(UniValue::VOBJ);
|
||||||
obj.push_back(Pair("txid", entry.op.hash.ToString()));
|
obj.push_back(Pair("txid", entry.op.hash.ToString()));
|
||||||
@@ -4115,7 +4217,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
|
|||||||
}
|
}
|
||||||
if ( toSapling && ASSETCHAINS_SYMBOL[0] == 0 )
|
if ( toSapling && ASSETCHAINS_SYMBOL[0] == 0 )
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER,"Sprout usage will expire soon");
|
throw JSONRPCError(RPC_INVALID_PARAMETER,"Sprout usage will expire soon");
|
||||||
|
|
||||||
// If we are sending from a shielded address, all recipient
|
// If we are sending from a shielded address, all recipient
|
||||||
// shielded addresses must be of the same type.
|
// shielded addresses must be of the same type.
|
||||||
if ((fromSprout && toSapling) || (fromSapling && toSprout)) {
|
if ((fromSprout && toSapling) || (fromSapling && toSprout)) {
|
||||||
@@ -4534,14 +4636,14 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
if (!EnsureWalletIsAvailable(fHelp))
|
if (!EnsureWalletIsAvailable(fHelp))
|
||||||
return NullUniValue;
|
return NullUniValue;
|
||||||
|
|
||||||
string enableArg = "zmergetoaddress";
|
string enableArg = "zmergetoaddress";
|
||||||
auto fEnableMergeToAddress = fExperimentalMode && GetBoolArg("-" + enableArg, true);
|
auto fEnableMergeToAddress = fExperimentalMode && GetBoolArg("-" + enableArg, true);
|
||||||
std::string strDisabledMsg = "";
|
std::string strDisabledMsg = "";
|
||||||
if (!fEnableMergeToAddress) {
|
if (!fEnableMergeToAddress) {
|
||||||
strDisabledMsg = experimentalDisabledHelpMsg("z_mergetoaddress", enableArg);
|
strDisabledMsg = experimentalDisabledHelpMsg("z_mergetoaddress", enableArg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fHelp || params.size() < 2 || params.size() > 6)
|
if (fHelp || params.size() < 2 || params.size() > 6)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"z_mergetoaddress [\"fromaddress\", ... ] \"toaddress\" ( fee ) ( transparent_limit ) ( shielded_limit ) ( memo )\n"
|
"z_mergetoaddress [\"fromaddress\", ... ] \"toaddress\" ( fee ) ( transparent_limit ) ( shielded_limit ) ( memo )\n"
|
||||||
@@ -4590,33 +4692,33 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||||||
+ HelpExampleCli("z_mergetoaddress", "'[\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"]' ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf")
|
+ HelpExampleCli("z_mergetoaddress", "'[\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"]' ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf")
|
||||||
+ HelpExampleRpc("z_mergetoaddress", "[\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"], \"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\"")
|
+ HelpExampleRpc("z_mergetoaddress", "[\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"], \"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\"")
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!fEnableMergeToAddress) {
|
if (!fEnableMergeToAddress) {
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, "Error: z_mergetoaddress is disabled.");
|
throw JSONRPCError(RPC_WALLET_ERROR, "Error: z_mergetoaddress is disabled.");
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||||
|
|
||||||
bool useAnyUTXO = false;
|
bool useAnyUTXO = false;
|
||||||
bool useAnySprout = false;
|
bool useAnySprout = false;
|
||||||
bool useAnySapling = false;
|
bool useAnySapling = false;
|
||||||
std::set<CTxDestination> taddrs = {};
|
std::set<CTxDestination> taddrs = {};
|
||||||
std::set<libzcash::PaymentAddress> zaddrs = {};
|
std::set<libzcash::PaymentAddress> zaddrs = {};
|
||||||
|
|
||||||
UniValue addresses = params[0].get_array();
|
UniValue addresses = params[0].get_array();
|
||||||
if (addresses.size()==0)
|
if (addresses.size()==0)
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, fromaddresses array is empty.");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, fromaddresses array is empty.");
|
||||||
|
|
||||||
// Keep track of addresses to spot duplicates
|
// Keep track of addresses to spot duplicates
|
||||||
std::set<std::string> setAddress;
|
std::set<std::string> setAddress;
|
||||||
|
|
||||||
// Sources
|
// Sources
|
||||||
for (const UniValue& o : addresses.getValues()) {
|
for (const UniValue& o : addresses.getValues()) {
|
||||||
if (!o.isStr())
|
if (!o.isStr())
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected string");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected string");
|
||||||
|
|
||||||
std::string address = o.get_str();
|
std::string address = o.get_str();
|
||||||
|
|
||||||
if (address == "ANY_TADDR") {
|
if (address == "ANY_TADDR") {
|
||||||
useAnyUTXO = true;
|
useAnyUTXO = true;
|
||||||
} else if (address == "ANY_SPROUT") {
|
} else if (address == "ANY_SPROUT") {
|
||||||
@@ -4636,23 +4738,23 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setAddress.count(address))
|
if (setAddress.count(address))
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ") + address);
|
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ") + address);
|
||||||
setAddress.insert(address);
|
setAddress.insert(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useAnyUTXO && taddrs.size() > 0) {
|
if (useAnyUTXO && taddrs.size() > 0) {
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify specific t-addrs when using \"ANY_TADDR\"");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify specific t-addrs when using \"ANY_TADDR\"");
|
||||||
}
|
}
|
||||||
if ((useAnySprout || useAnySapling) && zaddrs.size() > 0) {
|
if ((useAnySprout || useAnySapling) && zaddrs.size() > 0) {
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify specific z-addrs when using \"ANY_SPROUT\" or \"ANY_SAPLING\"");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify specific z-addrs when using \"ANY_SPROUT\" or \"ANY_SAPLING\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
const int nextBlockHeight = chainActive.Height() + 1;
|
const int nextBlockHeight = chainActive.Height() + 1;
|
||||||
const bool overwinterActive = NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER);
|
const bool overwinterActive = NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER);
|
||||||
const bool saplingActive = NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING);
|
const bool saplingActive = NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING);
|
||||||
|
|
||||||
// Validate the destination address
|
// Validate the destination address
|
||||||
auto destaddress = params[1].get_str();
|
auto destaddress = params[1].get_str();
|
||||||
bool isToSproutZaddr = false;
|
bool isToSproutZaddr = false;
|
||||||
@@ -4674,7 +4776,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
|
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert fee from currency format to zatoshis
|
// Convert fee from currency format to zatoshis
|
||||||
CAmount nFee = SHIELD_COINBASE_DEFAULT_MINERS_FEE;
|
CAmount nFee = SHIELD_COINBASE_DEFAULT_MINERS_FEE;
|
||||||
if (params.size() > 2) {
|
if (params.size() > 2) {
|
||||||
@@ -4684,7 +4786,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||||||
nFee = AmountFromValue( params[2] );
|
nFee = AmountFromValue( params[2] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int nUTXOLimit = MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT;
|
int nUTXOLimit = MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT;
|
||||||
if (params.size() > 3) {
|
if (params.size() > 3) {
|
||||||
nUTXOLimit = params[3].get_int();
|
nUTXOLimit = params[3].get_int();
|
||||||
@@ -4692,7 +4794,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of UTXOs cannot be negative");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of UTXOs cannot be negative");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int sproutNoteLimit = MERGE_TO_ADDRESS_DEFAULT_SPROUT_LIMIT;
|
int sproutNoteLimit = MERGE_TO_ADDRESS_DEFAULT_SPROUT_LIMIT;
|
||||||
int saplingNoteLimit = MERGE_TO_ADDRESS_DEFAULT_SAPLING_LIMIT;
|
int saplingNoteLimit = MERGE_TO_ADDRESS_DEFAULT_SAPLING_LIMIT;
|
||||||
if (params.size() > 4) {
|
if (params.size() > 4) {
|
||||||
@@ -4703,7 +4805,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||||||
sproutNoteLimit = nNoteLimit;
|
sproutNoteLimit = nNoteLimit;
|
||||||
saplingNoteLimit = nNoteLimit;
|
saplingNoteLimit = nNoteLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string memo;
|
std::string memo;
|
||||||
if (params.size() > 5) {
|
if (params.size() > 5) {
|
||||||
memo = params[5].get_str();
|
memo = params[5].get_str();
|
||||||
@@ -4716,9 +4818,9 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, size of memo is larger than maximum allowed %d", ZC_MEMO_SIZE ));
|
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, size of memo is larger than maximum allowed %d", ZC_MEMO_SIZE ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MergeToAddressRecipient recipient(destaddress, memo);
|
MergeToAddressRecipient recipient(destaddress, memo);
|
||||||
|
|
||||||
// Prepare to get UTXOs and notes
|
// Prepare to get UTXOs and notes
|
||||||
std::vector<MergeToAddressInputUTXO> utxoInputs;
|
std::vector<MergeToAddressInputUTXO> utxoInputs;
|
||||||
std::vector<MergeToAddressInputSproutNote> sproutNoteInputs;
|
std::vector<MergeToAddressInputSproutNote> sproutNoteInputs;
|
||||||
@@ -4732,7 +4834,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||||||
bool maxedOutUTXOsFlag = false;
|
bool maxedOutUTXOsFlag = false;
|
||||||
bool maxedOutNotesFlag = false;
|
bool maxedOutNotesFlag = false;
|
||||||
size_t mempoolLimit = (nUTXOLimit != 0) ? nUTXOLimit : (overwinterActive ? 0 : (size_t)GetArg("-mempooltxinputlimit", 0));
|
size_t mempoolLimit = (nUTXOLimit != 0) ? nUTXOLimit : (overwinterActive ? 0 : (size_t)GetArg("-mempooltxinputlimit", 0));
|
||||||
|
|
||||||
unsigned int max_tx_size = saplingActive ? MAX_TX_SIZE_AFTER_SAPLING : MAX_TX_SIZE_BEFORE_SAPLING;
|
unsigned int max_tx_size = saplingActive ? MAX_TX_SIZE_AFTER_SAPLING : MAX_TX_SIZE_BEFORE_SAPLING;
|
||||||
size_t estimatedTxSize = 200; // tx overhead + wiggle room
|
size_t estimatedTxSize = 200; // tx overhead + wiggle room
|
||||||
if (isToSproutZaddr) {
|
if (isToSproutZaddr) {
|
||||||
@@ -4740,20 +4842,20 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||||||
} else if (isToSaplingZaddr) {
|
} else if (isToSaplingZaddr) {
|
||||||
estimatedTxSize += OUTPUTDESCRIPTION_SIZE;
|
estimatedTxSize += OUTPUTDESCRIPTION_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useAnyUTXO || taddrs.size() > 0) {
|
if (useAnyUTXO || taddrs.size() > 0) {
|
||||||
// Get available utxos
|
// Get available utxos
|
||||||
vector<COutput> vecOutputs;
|
vector<COutput> vecOutputs;
|
||||||
pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, false);
|
pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, false);
|
||||||
|
|
||||||
// Find unspent utxos and update estimated size
|
// Find unspent utxos and update estimated size
|
||||||
for (const COutput& out : vecOutputs) {
|
for (const COutput& out : vecOutputs) {
|
||||||
if (!out.fSpendable) {
|
if (!out.fSpendable) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
CScript scriptPubKey = out.tx->vout[out.i].scriptPubKey;
|
CScript scriptPubKey = out.tx->vout[out.i].scriptPubKey;
|
||||||
|
|
||||||
CTxDestination address;
|
CTxDestination address;
|
||||||
if (!ExtractDestination(scriptPubKey, address)) {
|
if (!ExtractDestination(scriptPubKey, address)) {
|
||||||
continue;
|
continue;
|
||||||
@@ -4762,10 +4864,10 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||||||
if (taddrs.size() > 0 && !taddrs.count(address)) {
|
if (taddrs.size() > 0 && !taddrs.count(address)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
utxoCounter++;
|
utxoCounter++;
|
||||||
CAmount nValue = out.tx->vout[out.i].nValue;
|
CAmount nValue = out.tx->vout[out.i].nValue;
|
||||||
|
|
||||||
if (!maxedOutUTXOsFlag) {
|
if (!maxedOutUTXOsFlag) {
|
||||||
size_t increase = (boost::get<CScriptID>(&address) != nullptr) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE;
|
size_t increase = (boost::get<CScriptID>(&address) != nullptr) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE;
|
||||||
if (estimatedTxSize + increase >= max_tx_size ||
|
if (estimatedTxSize + increase >= max_tx_size ||
|
||||||
@@ -4779,19 +4881,19 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||||||
mergedUTXOValue += nValue;
|
mergedUTXOValue += nValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxedOutUTXOsFlag) {
|
if (maxedOutUTXOsFlag) {
|
||||||
remainingUTXOValue += nValue;
|
remainingUTXOValue += nValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useAnySprout || useAnySapling || zaddrs.size() > 0) {
|
if (useAnySprout || useAnySapling || zaddrs.size() > 0) {
|
||||||
// Get available notes
|
// Get available notes
|
||||||
std::vector<CSproutNotePlaintextEntry> sproutEntries;
|
std::vector<CSproutNotePlaintextEntry> sproutEntries;
|
||||||
std::vector<SaplingNoteEntry> saplingEntries;
|
std::vector<SaplingNoteEntry> saplingEntries;
|
||||||
pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs);
|
pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs);
|
||||||
|
|
||||||
// If Sapling is not active, do not allow sending from a sapling addresses.
|
// If Sapling is not active, do not allow sending from a sapling addresses.
|
||||||
if (!saplingActive && saplingEntries.size() > 0) {
|
if (!saplingActive && saplingEntries.size() > 0) {
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated");
|
||||||
@@ -4808,12 +4910,12 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||||||
RPC_INVALID_PARAMETER,
|
RPC_INVALID_PARAMETER,
|
||||||
"Cannot send between Sprout and Sapling addresses using z_mergetoaddress");
|
"Cannot send between Sprout and Sapling addresses using z_mergetoaddress");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find unspent notes and update estimated size
|
// Find unspent notes and update estimated size
|
||||||
for (const CSproutNotePlaintextEntry& entry : sproutEntries) {
|
for (const CSproutNotePlaintextEntry& entry : sproutEntries) {
|
||||||
noteCounter++;
|
noteCounter++;
|
||||||
CAmount nValue = entry.plaintext.value();
|
CAmount nValue = entry.plaintext.value();
|
||||||
|
|
||||||
if (!maxedOutNotesFlag) {
|
if (!maxedOutNotesFlag) {
|
||||||
// If we haven't added any notes yet and the merge is to a
|
// If we haven't added any notes yet and the merge is to a
|
||||||
// z-address, we have already accounted for the first JoinSplit.
|
// z-address, we have already accounted for the first JoinSplit.
|
||||||
@@ -4831,12 +4933,12 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||||||
mergedNoteValue += nValue;
|
mergedNoteValue += nValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxedOutNotesFlag) {
|
if (maxedOutNotesFlag) {
|
||||||
remainingNoteValue += nValue;
|
remainingNoteValue += nValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const SaplingNoteEntry& entry : saplingEntries) {
|
for (const SaplingNoteEntry& entry : saplingEntries) {
|
||||||
noteCounter++;
|
noteCounter++;
|
||||||
CAmount nValue = entry.note.value();
|
CAmount nValue = entry.note.value();
|
||||||
@@ -4856,20 +4958,20 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||||||
mergedNoteValue += nValue;
|
mergedNoteValue += nValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxedOutNotesFlag) {
|
if (maxedOutNotesFlag) {
|
||||||
remainingNoteValue += nValue;
|
remainingNoteValue += nValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t numUtxos = utxoInputs.size();
|
size_t numUtxos = utxoInputs.size();
|
||||||
size_t numNotes = sproutNoteInputs.size() + saplingNoteInputs.size();
|
size_t numNotes = sproutNoteInputs.size() + saplingNoteInputs.size();
|
||||||
|
|
||||||
if (numUtxos == 0 && numNotes == 0) {
|
if (numUtxos == 0 && numNotes == 0) {
|
||||||
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Could not find any funds to merge.");
|
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Could not find any funds to merge.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanity check: Don't do anything if:
|
// Sanity check: Don't do anything if:
|
||||||
// - We only have one from address
|
// - We only have one from address
|
||||||
// - It's equal to toaddress
|
// - It's equal to toaddress
|
||||||
@@ -4877,26 +4979,26 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||||||
if (setAddress.size() == 1 && setAddress.count(destaddress) && (numUtxos + numNotes) == 1) {
|
if (setAddress.size() == 1 && setAddress.count(destaddress) && (numUtxos + numNotes) == 1) {
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Destination address is also the only source address, and all its funds are already merged.");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Destination address is also the only source address, and all its funds are already merged.");
|
||||||
}
|
}
|
||||||
|
|
||||||
CAmount mergedValue = mergedUTXOValue + mergedNoteValue;
|
CAmount mergedValue = mergedUTXOValue + mergedNoteValue;
|
||||||
if (mergedValue < nFee) {
|
if (mergedValue < nFee) {
|
||||||
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS,
|
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS,
|
||||||
strprintf("Insufficient funds, have %s, which is less than miners fee %s",
|
strprintf("Insufficient funds, have %s, which is less than miners fee %s",
|
||||||
FormatMoney(mergedValue), FormatMoney(nFee)));
|
FormatMoney(mergedValue), FormatMoney(nFee)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the user specified fee is sane (if too high, it can result in error -25 absurd fee)
|
// Check that the user specified fee is sane (if too high, it can result in error -25 absurd fee)
|
||||||
CAmount netAmount = mergedValue - nFee;
|
CAmount netAmount = mergedValue - nFee;
|
||||||
if (nFee > netAmount) {
|
if (nFee > netAmount) {
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the net amount to be shielded %s", FormatMoney(nFee), FormatMoney(netAmount)));
|
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the net amount to be shielded %s", FormatMoney(nFee), FormatMoney(netAmount)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep record of parameters in context object
|
// Keep record of parameters in context object
|
||||||
UniValue contextInfo(UniValue::VOBJ);
|
UniValue contextInfo(UniValue::VOBJ);
|
||||||
contextInfo.push_back(Pair("fromaddresses", params[0]));
|
contextInfo.push_back(Pair("fromaddresses", params[0]));
|
||||||
contextInfo.push_back(Pair("toaddress", params[1]));
|
contextInfo.push_back(Pair("toaddress", params[1]));
|
||||||
contextInfo.push_back(Pair("fee", ValueFromAmount(nFee)));
|
contextInfo.push_back(Pair("fee", ValueFromAmount(nFee)));
|
||||||
|
|
||||||
// Contextual transaction we will build on
|
// Contextual transaction we will build on
|
||||||
CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(
|
CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(
|
||||||
Params().GetConsensus(),
|
Params().GetConsensus(),
|
||||||
@@ -4905,7 +5007,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||||||
if (contextualTx.nVersion == 1 && isSproutShielded) {
|
if (contextualTx.nVersion == 1 && isSproutShielded) {
|
||||||
contextualTx.nVersion = 2; // Tx format should support vjoinsplit
|
contextualTx.nVersion = 2; // Tx format should support vjoinsplit
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builder (used if Sapling addresses are involved)
|
// Builder (used if Sapling addresses are involved)
|
||||||
boost::optional<TransactionBuilder> builder;
|
boost::optional<TransactionBuilder> builder;
|
||||||
if (isToSaplingZaddr || saplingNoteInputs.size() > 0) {
|
if (isToSaplingZaddr || saplingNoteInputs.size() > 0) {
|
||||||
@@ -4917,7 +5019,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||||||
new AsyncRPCOperation_mergetoaddress(builder, contextualTx, utxoInputs, sproutNoteInputs, saplingNoteInputs, recipient, nFee, contextInfo) );
|
new AsyncRPCOperation_mergetoaddress(builder, contextualTx, utxoInputs, sproutNoteInputs, saplingNoteInputs, recipient, nFee, contextInfo) );
|
||||||
q->addOperation(operation);
|
q->addOperation(operation);
|
||||||
AsyncRPCOperationId operationId = operation->getId();
|
AsyncRPCOperationId operationId = operation->getId();
|
||||||
|
|
||||||
// Return continuation information
|
// Return continuation information
|
||||||
UniValue o(UniValue::VOBJ);
|
UniValue o(UniValue::VOBJ);
|
||||||
o.push_back(Pair("remainingUTXOs", static_cast<uint64_t>(utxoCounter - numUtxos)));
|
o.push_back(Pair("remainingUTXOs", static_cast<uint64_t>(utxoCounter - numUtxos)));
|
||||||
@@ -6018,7 +6120,7 @@ UniValue gatewaysbind(const UniValue& params, bool fHelp)
|
|||||||
if ( params.size() < 6+i+1 )
|
if ( params.size() < 6+i+1 )
|
||||||
throw runtime_error("not enough parameters for N pubkeys\n");
|
throw runtime_error("not enough parameters for N pubkeys\n");
|
||||||
pubkey = ParseHex(params[6+i].get_str().c_str());
|
pubkey = ParseHex(params[6+i].get_str().c_str());
|
||||||
if (pubkey.size()!= 33)
|
if (pubkey.size()!= 33)
|
||||||
throw runtime_error("invalid destination pubkey");
|
throw runtime_error("invalid destination pubkey");
|
||||||
pubkeys.push_back(pubkey2pk(pubkey));
|
pubkeys.push_back(pubkey2pk(pubkey));
|
||||||
}
|
}
|
||||||
@@ -6052,8 +6154,8 @@ UniValue gatewaysdeposit(const UniValue& params, bool fHelp)
|
|||||||
amount = atof((char *)params[8].get_str().c_str()) * COIN + 0.00000000499999;
|
amount = atof((char *)params[8].get_str().c_str()) * COIN + 0.00000000499999;
|
||||||
if ( amount <= 0 || claimvout < 0 )
|
if ( amount <= 0 || claimvout < 0 )
|
||||||
throw runtime_error("invalid param: amount, numpks or claimvout\n");
|
throw runtime_error("invalid param: amount, numpks or claimvout\n");
|
||||||
if (destpub.size()!= 33)
|
if (destpub.size()!= 33)
|
||||||
throw runtime_error("invalid destination pubkey");
|
throw runtime_error("invalid destination pubkey");
|
||||||
hex = GatewaysDeposit(0,bindtxid,height,coin,cointxid,claimvout,deposithex,proof,pubkey2pk(destpub),amount);
|
hex = GatewaysDeposit(0,bindtxid,height,coin,cointxid,claimvout,deposithex,proof,pubkey2pk(destpub),amount);
|
||||||
|
|
||||||
RETURN_IF_ERROR(CCerror);
|
RETURN_IF_ERROR(CCerror);
|
||||||
@@ -6078,9 +6180,9 @@ UniValue gatewaysclaim(const UniValue& params, bool fHelp)
|
|||||||
coin = params[1].get_str();
|
coin = params[1].get_str();
|
||||||
deposittxid = Parseuint256((char *)params[2].get_str().c_str());
|
deposittxid = Parseuint256((char *)params[2].get_str().c_str());
|
||||||
destpub = ParseHex(params[3].get_str());
|
destpub = ParseHex(params[3].get_str());
|
||||||
amount = atof((char *)params[4].get_str().c_str()) * COIN + 0.00000000499999;
|
amount = atof((char *)params[4].get_str().c_str()) * COIN + 0.00000000499999;
|
||||||
if (destpub.size()!= 33)
|
if (destpub.size()!= 33)
|
||||||
throw runtime_error("invalid destination pubkey");
|
throw runtime_error("invalid destination pubkey");
|
||||||
hex = GatewaysClaim(0,bindtxid,coin,deposittxid,pubkey2pk(destpub),amount);
|
hex = GatewaysClaim(0,bindtxid,coin,deposittxid,pubkey2pk(destpub),amount);
|
||||||
RETURN_IF_ERROR(CCerror);
|
RETURN_IF_ERROR(CCerror);
|
||||||
if ( hex.size() > 0 )
|
if ( hex.size() > 0 )
|
||||||
@@ -6103,9 +6205,9 @@ UniValue gatewayswithdraw(const UniValue& params, bool fHelp)
|
|||||||
bindtxid = Parseuint256((char *)params[0].get_str().c_str());
|
bindtxid = Parseuint256((char *)params[0].get_str().c_str());
|
||||||
coin = params[1].get_str();
|
coin = params[1].get_str();
|
||||||
withdrawpub = ParseHex(params[2].get_str());
|
withdrawpub = ParseHex(params[2].get_str());
|
||||||
amount = atof((char *)params[3].get_str().c_str()) * COIN + 0.00000000499999;
|
amount = atof((char *)params[3].get_str().c_str()) * COIN + 0.00000000499999;
|
||||||
if (withdrawpub.size()!= 33)
|
if (withdrawpub.size()!= 33)
|
||||||
throw runtime_error("invalid destination pubkey");
|
throw runtime_error("invalid destination pubkey");
|
||||||
hex = GatewaysWithdraw(0,bindtxid,coin,pubkey2pk(withdrawpub),amount);
|
hex = GatewaysWithdraw(0,bindtxid,coin,pubkey2pk(withdrawpub),amount);
|
||||||
RETURN_IF_ERROR(CCerror);
|
RETURN_IF_ERROR(CCerror);
|
||||||
if ( hex.size() > 0 )
|
if ( hex.size() > 0 )
|
||||||
@@ -6124,7 +6226,7 @@ UniValue gatewayspartialsign(const UniValue& params, bool fHelp)
|
|||||||
if ( ensure_CCrequirements() < 0 )
|
if ( ensure_CCrequirements() < 0 )
|
||||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||||
const CKeyStore& keystore = *pwalletMain;
|
const CKeyStore& keystore = *pwalletMain;
|
||||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||||
txid = Parseuint256((char *)params[0].get_str().c_str());
|
txid = Parseuint256((char *)params[0].get_str().c_str());
|
||||||
coin = params[1].get_str();
|
coin = params[1].get_str();
|
||||||
parthex = params[2].get_str();
|
parthex = params[2].get_str();
|
||||||
@@ -6169,7 +6271,7 @@ UniValue gatewaysmarkdone(const UniValue& params, bool fHelp)
|
|||||||
const CKeyStore& keystore = *pwalletMain;
|
const CKeyStore& keystore = *pwalletMain;
|
||||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||||
completetxid = Parseuint256((char *)params[0].get_str().c_str());
|
completetxid = Parseuint256((char *)params[0].get_str().c_str());
|
||||||
coin = params[1].get_str();
|
coin = params[1].get_str();
|
||||||
hex = GatewaysMarkDone(0,completetxid,coin);
|
hex = GatewaysMarkDone(0,completetxid,coin);
|
||||||
RETURN_IF_ERROR(CCerror);
|
RETURN_IF_ERROR(CCerror);
|
||||||
if ( hex.size() > 0 )
|
if ( hex.size() > 0 )
|
||||||
@@ -7173,7 +7275,7 @@ UniValue tokenfillask(const UniValue& params, bool fHelp)
|
|||||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||||
tokenid = Parseuint256((char *)params[0].get_str().c_str());
|
tokenid = Parseuint256((char *)params[0].get_str().c_str());
|
||||||
asktxid = Parseuint256((char *)params[1].get_str().c_str());
|
asktxid = Parseuint256((char *)params[1].get_str().c_str());
|
||||||
//fillunits = atol(params[2].get_str().c_str());
|
//fillunits = atol(params[2].get_str().c_str());
|
||||||
fillunits = atoll(params[2].get_str().c_str()); // dimxy changed to prevent loss of significance
|
fillunits = atoll(params[2].get_str().c_str()); // dimxy changed to prevent loss of significance
|
||||||
if ( fillunits <= 0 )
|
if ( fillunits <= 0 )
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user