mirror of
https://github.com/dogecoin/dogecoin.git
synced 2026-01-31 10:30:52 +00:00
Add height to importpubkey for rescan
This adds two helper functions. One function gets a height parameter from the incoming RPC request. The other performs the scanning. We can use both functions for reducing code in other RPC calls that can/should take height parameters and perform rescanning.
This commit is contained in:
parent
6686083a14
commit
7a00fb1b18
@ -20,7 +20,7 @@ happened previously.
|
||||
|
||||
from test_framework.authproxy import JSONRPCException
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import (start_nodes, connect_nodes, sync_blocks, assert_equal, set_node_times)
|
||||
from test_framework.util import (start_nodes, connect_nodes, sync_blocks, assert_equal, set_node_times, sync_mempools)
|
||||
from decimal import Decimal
|
||||
|
||||
import collections
|
||||
@ -127,10 +127,19 @@ class ImportRescanTest(BitcoinTestFramework):
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args)
|
||||
for i in range(1, self.num_nodes):
|
||||
connect_nodes(self.nodes[i], 0)
|
||||
self.sync_recipient_nodes()
|
||||
|
||||
def sync_recipient_nodes(self):
|
||||
syncable = self.nodes[:2]
|
||||
sync_blocks(syncable)
|
||||
sync_mempools(syncable)
|
||||
|
||||
def run_test(self):
|
||||
self.test_argument_validation()
|
||||
self.test_import_types()
|
||||
self.test_rescan_from_height()
|
||||
|
||||
def test_import_types(self):
|
||||
# Create one transaction on node 0 with a unique amount and label for
|
||||
# each possible type of wallet import RPC.
|
||||
|
||||
@ -202,6 +211,54 @@ class ImportRescanTest(BitcoinTestFramework):
|
||||
except JSONRPCException as e:
|
||||
assert("Block height out of range" in e.error["message"])
|
||||
|
||||
try:
|
||||
node.importpubkey("")
|
||||
except JSONRPCException as e:
|
||||
assert("Pubkey must be a hex string" in e.error["message"])
|
||||
|
||||
try:
|
||||
node.importpubkey("abcdef")
|
||||
except JSONRPCException as e:
|
||||
assert("Pubkey is not a valid public key" in e.error["message"])
|
||||
|
||||
try:
|
||||
address = self.nodes[1].getnewaddress()
|
||||
pubkey = self.nodes[1].validateaddress(address)["pubkey"]
|
||||
node.importpubkey(pubkey, "", True, node.getblockcount() + 1)
|
||||
except JSONRPCException as e:
|
||||
assert("Block height out of range" in e.error["message"])
|
||||
|
||||
def test_rescan_from_height(self):
|
||||
# this height is before sending anything to the new address
|
||||
orig_height = self.nodes[0].getblockcount()
|
||||
|
||||
address = self.nodes[0].getnewaddress()
|
||||
pubkey = self.nodes[0].validateaddress(address)["pubkey"]
|
||||
self.nodes[0].sendtoaddress(address, 100)
|
||||
|
||||
# generate two blocks
|
||||
# the first contains the tx that sends these koinu
|
||||
# the second is after it
|
||||
self.nodes[0].generate(2)
|
||||
new_height = self.nodes[0].getblockcount()
|
||||
|
||||
self.sync_recipient_nodes()
|
||||
|
||||
# no rescan, no funds seen for this pubkey
|
||||
self.nodes[1].importpubkey(pubkey, "newpubkey", False)
|
||||
balance = self.nodes[1].getbalance("newpubkey", 0, True)
|
||||
assert_equal(balance, Decimal("0"))
|
||||
|
||||
# rescan at the block *after* the tx, no funds seen for this pubkey
|
||||
self.nodes[2].importpubkey(pubkey, "newpubkey", True, new_height)
|
||||
balance = self.nodes[2].getbalance("newpubkey", 0, True)
|
||||
assert_equal(balance, Decimal("0"))
|
||||
|
||||
# rescan at the block *before* the tx, funds seen for this pubkey
|
||||
self.nodes[3].importpubkey(pubkey, "newpubkey", True, orig_height)
|
||||
balance = self.nodes[3].getbalance("newpubkey", 0, True)
|
||||
assert_equal(balance, Decimal("100"))
|
||||
|
||||
def try_rpc(func, *args, **kwargs):
|
||||
try:
|
||||
return func(*args, **kwargs), None
|
||||
|
||||
@ -107,6 +107,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
||||
{ "importaddress", 2, "rescan" },
|
||||
{ "importaddress", 3, "p2sh" },
|
||||
{ "importpubkey", 2, "rescan" },
|
||||
{ "importpubkey", 3, "height" },
|
||||
{ "importmulti", 0, "requests" },
|
||||
{ "importmulti", 1, "options" },
|
||||
{ "verifychain", 0, "checklevel" },
|
||||
|
||||
@ -35,6 +35,8 @@ using namespace std;
|
||||
|
||||
void EnsureWalletIsUnlocked();
|
||||
bool EnsureWalletIsAvailable(bool avoidException);
|
||||
uint32_t getHeightParamFromRequest(const JSONRPCRequest& request, size_t pos);
|
||||
void attemptRescanFromHeight(uint32_t nHeight);
|
||||
|
||||
std::string static EncodeDumpTime(int64_t nTime) {
|
||||
return DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", nTime);
|
||||
@ -151,29 +153,42 @@ UniValue importprivkey(const JSONRPCRequest& request)
|
||||
if (!pwalletMain->AddKeyPubKey(key, pubkey))
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
|
||||
|
||||
|
||||
if (fRescan) {
|
||||
CBlockIndex* pblockindex = chainActive.Genesis();
|
||||
|
||||
if (request.params.size() > 3) {
|
||||
int nHeight = request.params[3].get_int();
|
||||
|
||||
if (nHeight < 0 || nHeight > chainActive.Height())
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
|
||||
|
||||
pblockindex = chainActive[nHeight];
|
||||
} else {
|
||||
// we have no implicit first height for a key, so we need to scan the whole chain
|
||||
pwalletMain->UpdateTimeFirstKey(1);
|
||||
}
|
||||
|
||||
pwalletMain->ScanForWalletTransactions(pblockindex, true);
|
||||
const uint32_t nHeight = getHeightParamFromRequest(request, 3);
|
||||
attemptRescanFromHeight(nHeight);
|
||||
}
|
||||
}
|
||||
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
uint32_t getHeightParamFromRequest(const JSONRPCRequest& request, const size_t pos)
|
||||
{
|
||||
if (request.params.size() <= pos)
|
||||
return 1;
|
||||
|
||||
const int nHeight = request.params[pos].get_int();
|
||||
|
||||
if (nHeight < 0 || nHeight > chainActive.Height())
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
|
||||
|
||||
return nHeight;
|
||||
}
|
||||
|
||||
void attemptRescanFromHeight(const uint32_t nHeight)
|
||||
{
|
||||
CBlockIndex* pblockindex = chainActive.Genesis();
|
||||
|
||||
// we have no implicit first height for a key, so we need to scan the whole chain
|
||||
if (nHeight <= 1)
|
||||
pwalletMain->UpdateTimeFirstKey(1);
|
||||
else
|
||||
pblockindex = chainActive[nHeight];
|
||||
|
||||
pwalletMain->ScanForWalletTransactions(pblockindex, true);
|
||||
pwalletMain->ReacceptWalletTransactions();
|
||||
}
|
||||
|
||||
void ImportAddress(const CBitcoinAddress& address, const string& strLabel);
|
||||
void ImportScript(const CScript& script, const string& strLabel, bool isRedeemScript)
|
||||
{
|
||||
@ -382,10 +397,13 @@ UniValue importpubkey(const JSONRPCRequest& request)
|
||||
"1. \"pubkey\" (string, required) The hex-encoded public key\n"
|
||||
"2. \"label\" (string, optional, default=\"\") An optional label\n"
|
||||
"3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
|
||||
"4. height (numeric, optional, default=1) If rescanning, the block height from which to start\n"
|
||||
"\nNote: This call can take minutes to complete if rescan is true.\n"
|
||||
"\nExamples:\n"
|
||||
"\nImport a public key with rescan\n"
|
||||
+ HelpExampleCli("importpubkey", "\"mypubkey\"") +
|
||||
"\nImport a public key with rescan from a specific height\n"
|
||||
+ HelpExampleCli("importpubkey", "\"mypubkey\" true 123654") +
|
||||
"\nImport using a label without rescan\n"
|
||||
+ HelpExampleCli("importpubkey", "\"mypubkey\" \"testing\" false") +
|
||||
"\nAs a JSON-RPC call\n"
|
||||
@ -417,10 +435,9 @@ UniValue importpubkey(const JSONRPCRequest& request)
|
||||
ImportAddress(CBitcoinAddress(pubKey.GetID()), strLabel);
|
||||
ImportScript(GetScriptForRawPubKey(pubKey), strLabel, false);
|
||||
|
||||
if (fRescan)
|
||||
{
|
||||
pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true);
|
||||
pwalletMain->ReacceptWalletTransactions();
|
||||
if (fRescan) {
|
||||
const uint32_t nHeight = getHeightParamFromRequest(request, 3);
|
||||
attemptRescanFromHeight(nHeight);
|
||||
}
|
||||
|
||||
return NullUniValue;
|
||||
|
||||
@ -3248,7 +3248,7 @@ static const CRPCCommand commands[] =
|
||||
{ "wallet", "importwallet", &importwallet, true, {"filename"} },
|
||||
{ "wallet", "importaddress", &importaddress, true, {"address","label","rescan","p2sh"} },
|
||||
{ "wallet", "importprunedfunds", &importprunedfunds, true, {"rawtransaction","txoutproof"} },
|
||||
{ "wallet", "importpubkey", &importpubkey, true, {"pubkey","label","rescan"} },
|
||||
{ "wallet", "importpubkey", &importpubkey, true, {"pubkey","label","rescan", "height"} },
|
||||
{ "wallet", "keypoolrefill", &keypoolrefill, true, {"newsize"} },
|
||||
{ "wallet", "listaccounts", &listaccounts, false, {"minconf","include_watchonly"} },
|
||||
{ "wallet", "listaddressgroupings", &listaddressgroupings, false, {} },
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user