Added companion removeprunedfunds call.
This commit is contained in:
parent
7eb702954e
commit
f1bb13c93d
7 changed files with 127 additions and 0 deletions
|
@ -115,5 +115,26 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
|
||||||
assert_equal(address_info['iswatchonly'], False)
|
assert_equal(address_info['iswatchonly'], False)
|
||||||
assert_equal(address_info['ismine'], True)
|
assert_equal(address_info['ismine'], True)
|
||||||
|
|
||||||
|
#Remove transactions
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.nodes[1].removeprunedfunds(txnid1)
|
||||||
|
except JSONRPCException,e:
|
||||||
|
errorString = e.error['message']
|
||||||
|
|
||||||
|
assert('does not exist' in errorString)
|
||||||
|
|
||||||
|
balance1 = Decimal(self.nodes[1].getbalance("", 0, True))
|
||||||
|
assert_equal(balance1, Decimal('0.075'))
|
||||||
|
|
||||||
|
|
||||||
|
self.nodes[1].removeprunedfunds(txnid2)
|
||||||
|
balance2 = Decimal(self.nodes[1].getbalance("", 0, True))
|
||||||
|
assert_equal(balance2, Decimal('0.025'))
|
||||||
|
|
||||||
|
self.nodes[1].removeprunedfunds(txnid3)
|
||||||
|
balance3 = Decimal(self.nodes[1].getbalance("", 0, True))
|
||||||
|
assert_equal(balance3, Decimal('0.0'))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
ImportPrunedFundsTest ().main ()
|
ImportPrunedFundsTest ().main ()
|
||||||
|
|
|
@ -310,6 +310,44 @@ UniValue importprunedfunds(const UniValue& params, bool fHelp)
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No addresses in wallet correspond to included transaction");
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No addresses in wallet correspond to included transaction");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UniValue removeprunedfunds(const UniValue& params, bool fHelp)
|
||||||
|
{
|
||||||
|
if (!EnsureWalletIsAvailable(fHelp))
|
||||||
|
return NullUniValue;
|
||||||
|
|
||||||
|
if (fHelp || params.size() != 1)
|
||||||
|
throw runtime_error(
|
||||||
|
"removeprunedfunds \"txid\"\n"
|
||||||
|
"\nDeletes the specified transaction from the wallet. Meant for use with pruned wallets and as a companion to importprunedfunds. This will effect wallet balances.\n"
|
||||||
|
"\nArguments:\n"
|
||||||
|
"1. \"txid\" (string, required) The hex-encoded id of the transaction you are deleting\n"
|
||||||
|
"\nExamples:\n"
|
||||||
|
+ HelpExampleCli("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") +
|
||||||
|
"\nAs a JSON-RPC call\n"
|
||||||
|
+ HelpExampleRpc("removprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"")
|
||||||
|
);
|
||||||
|
|
||||||
|
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||||
|
|
||||||
|
uint256 hash;
|
||||||
|
hash.SetHex(params[0].get_str());
|
||||||
|
vector<uint256> vHash;
|
||||||
|
vHash.push_back(hash);
|
||||||
|
vector<uint256> vHashOut;
|
||||||
|
|
||||||
|
if(pwalletMain->ZapSelectTx(vHash, vHashOut) != DB_LOAD_OK) {
|
||||||
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Could not properly delete the transaction.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(vHashOut.empty()) {
|
||||||
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction does not exist in wallet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadFlushWalletDB(pwalletMain->strWalletFile);
|
||||||
|
|
||||||
|
return NullUniValue;
|
||||||
|
}
|
||||||
|
|
||||||
UniValue importpubkey(const UniValue& params, bool fHelp)
|
UniValue importpubkey(const UniValue& params, bool fHelp)
|
||||||
{
|
{
|
||||||
if (!EnsureWalletIsAvailable(fHelp))
|
if (!EnsureWalletIsAvailable(fHelp))
|
||||||
|
|
|
@ -2504,6 +2504,7 @@ extern UniValue importpubkey(const UniValue& params, bool fHelp);
|
||||||
extern UniValue dumpwallet(const UniValue& params, bool fHelp);
|
extern UniValue dumpwallet(const UniValue& params, bool fHelp);
|
||||||
extern UniValue importwallet(const UniValue& params, bool fHelp);
|
extern UniValue importwallet(const UniValue& params, bool fHelp);
|
||||||
extern UniValue importprunedfunds(const UniValue& params, bool fHelp);
|
extern UniValue importprunedfunds(const UniValue& params, bool fHelp);
|
||||||
|
extern UniValue removeprunedfunds(const UniValue& params, bool fHelp);
|
||||||
|
|
||||||
const CRPCCommand vWalletRPCCommands[] =
|
const CRPCCommand vWalletRPCCommands[] =
|
||||||
{ // category name actor (function) okSafeMode
|
{ // category name actor (function) okSafeMode
|
||||||
|
@ -2552,6 +2553,7 @@ const CRPCCommand vWalletRPCCommands[] =
|
||||||
{ "wallet", "walletlock", &walletlock, true },
|
{ "wallet", "walletlock", &walletlock, true },
|
||||||
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, true },
|
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, true },
|
||||||
{ "wallet", "walletpassphrase", &walletpassphrase, true },
|
{ "wallet", "walletpassphrase", &walletpassphrase, true },
|
||||||
|
{ "wallet", "removeprunedfunds", &removeprunedfunds, true },
|
||||||
};
|
};
|
||||||
|
|
||||||
void walletRegisterRPCCommands()
|
void walletRegisterRPCCommands()
|
||||||
|
|
|
@ -2362,6 +2362,31 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
|
||||||
return DB_LOAD_OK;
|
return DB_LOAD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DBErrors CWallet::ZapSelectTx(vector<uint256>& vHashIn, vector<uint256>& vHashOut)
|
||||||
|
{
|
||||||
|
if (!fFileBacked)
|
||||||
|
return DB_LOAD_OK;
|
||||||
|
DBErrors nZapSelectTxRet = CWalletDB(strWalletFile,"cr+").ZapSelectTx(this, vHashIn, vHashOut);
|
||||||
|
if (nZapSelectTxRet == DB_NEED_REWRITE)
|
||||||
|
{
|
||||||
|
if (CDB::Rewrite(strWalletFile, "\x04pool"))
|
||||||
|
{
|
||||||
|
LOCK(cs_wallet);
|
||||||
|
setKeyPool.clear();
|
||||||
|
// Note: can't top-up keypool here, because wallet is locked.
|
||||||
|
// User will be prompted to unlock wallet the next operation
|
||||||
|
// that requires a new key.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nZapSelectTxRet != DB_LOAD_OK)
|
||||||
|
return nZapSelectTxRet;
|
||||||
|
|
||||||
|
MarkDirty();
|
||||||
|
|
||||||
|
return DB_LOAD_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
DBErrors CWallet::ZapWalletTx(std::vector<CWalletTx>& vWtx)
|
DBErrors CWallet::ZapWalletTx(std::vector<CWalletTx>& vWtx)
|
||||||
{
|
{
|
||||||
|
|
|
@ -792,6 +792,7 @@ public:
|
||||||
|
|
||||||
DBErrors LoadWallet(bool& fFirstRunRet);
|
DBErrors LoadWallet(bool& fFirstRunRet);
|
||||||
DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);
|
DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);
|
||||||
|
DBErrors ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut);
|
||||||
|
|
||||||
bool SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& purpose);
|
bool SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& purpose);
|
||||||
|
|
||||||
|
|
|
@ -785,6 +785,45 @@ DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, vector<uint256>& vTxHash, vec
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DBErrors CWalletDB::ZapSelectTx(CWallet* pwallet, vector<uint256>& vTxHashIn, vector<uint256>& vTxHashOut)
|
||||||
|
{
|
||||||
|
// build list of wallet TXs and hashes
|
||||||
|
vector<uint256> vTxHash;
|
||||||
|
vector<CWalletTx> vWtx;
|
||||||
|
DBErrors err = FindWalletTx(pwallet, vTxHash, vWtx);
|
||||||
|
if (err != DB_LOAD_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(vTxHash.begin(), vTxHash.end());
|
||||||
|
std::sort(vTxHashIn.begin(), vTxHashIn.end());
|
||||||
|
|
||||||
|
// erase each matching wallet TX
|
||||||
|
bool delerror = false;
|
||||||
|
vector<uint256>::iterator it = vTxHashIn.begin();
|
||||||
|
BOOST_FOREACH (uint256 hash, vTxHash) {
|
||||||
|
while (it < vTxHashIn.end() && (*it) < hash) {
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
if (it == vTxHashIn.end()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if ((*it) == hash) {
|
||||||
|
pwallet->mapWallet.erase(hash);
|
||||||
|
if(!EraseTx(hash)) {
|
||||||
|
LogPrint("db", "Transaction was found for deletion but returned database error: %s\n", hash.GetHex());
|
||||||
|
delerror = true;
|
||||||
|
}
|
||||||
|
vTxHashOut.push_back(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delerror) {
|
||||||
|
return DB_CORRUPT;
|
||||||
|
}
|
||||||
|
return DB_LOAD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
DBErrors CWalletDB::ZapWalletTx(CWallet* pwallet, vector<CWalletTx>& vWtx)
|
DBErrors CWalletDB::ZapWalletTx(CWallet* pwallet, vector<CWalletTx>& vWtx)
|
||||||
{
|
{
|
||||||
// build list of wallet TXs
|
// build list of wallet TXs
|
||||||
|
|
|
@ -130,6 +130,7 @@ public:
|
||||||
DBErrors LoadWallet(CWallet* pwallet);
|
DBErrors LoadWallet(CWallet* pwallet);
|
||||||
DBErrors FindWalletTx(CWallet* pwallet, std::vector<uint256>& vTxHash, std::vector<CWalletTx>& vWtx);
|
DBErrors FindWalletTx(CWallet* pwallet, std::vector<uint256>& vTxHash, std::vector<CWalletTx>& vWtx);
|
||||||
DBErrors ZapWalletTx(CWallet* pwallet, std::vector<CWalletTx>& vWtx);
|
DBErrors ZapWalletTx(CWallet* pwallet, std::vector<CWalletTx>& vWtx);
|
||||||
|
DBErrors ZapSelectTx(CWallet* pwallet, std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut);
|
||||||
static bool Recover(CDBEnv& dbenv, const std::string& filename, bool fOnlyKeys);
|
static bool Recover(CDBEnv& dbenv, const std::string& filename, bool fOnlyKeys);
|
||||||
static bool Recover(CDBEnv& dbenv, const std::string& filename);
|
static bool Recover(CDBEnv& dbenv, const std::string& filename);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue