From ca56a420eeb7a0b771ddcd7d061e44ac03b91764 Mon Sep 17 00:00:00 2001 From: Roy Lee Date: Tue, 25 Oct 2022 22:12:38 -0700 Subject: [PATCH] rpc: implement rescanblockchain --- internal/rpchelp/helpdescs_en_US.go | 9 ++++++ internal/rpchelp/methods.go | 1 + rpc/legacyrpc/methods.go | 44 +++++++++++++++++++++++++++++ rpc/legacyrpc/rpcserverhelp.go | 3 +- 4 files changed, 56 insertions(+), 1 deletion(-) diff --git a/internal/rpchelp/helpdescs_en_US.go b/internal/rpchelp/helpdescs_en_US.go index c1b19af..536505b 100644 --- a/internal/rpchelp/helpdescs_en_US.go +++ b/internal/rpchelp/helpdescs_en_US.go @@ -348,6 +348,15 @@ var helpDescsEnUS = map[string]string{ "renameaccount-oldaccount": "The old account name to rename.", "renameaccount-newaccount": "The new name for the account.", + // RescanBlockchainCmd help. + "rescanblockchain--synopsis": "Renames an account.", + "rescanblockchain-startheight": "Block height where the rescan should start.", + "rescanblockchain-stopheight": "The last block height that should be scanned. If none is provided it will rescan up to the tip at return time of this call.", + + // RescanblockchainResult help. + "rescanblockchainresult-start_height": "The block height where the rescan started (the requested height or 0)", + "rescanblockchainresult-stop_height": "The height of the last rescanned block.", + // SendFromCmd help. "sendfrom--synopsis": "Authors, signs, and sends a transaction that outputs some amount to a payment address.\n" + "A change output is automatically included to send extra output value back to the original account.", diff --git a/internal/rpchelp/methods.go b/internal/rpchelp/methods.go index a5aaaa5..e4362c5 100644 --- a/internal/rpchelp/methods.go +++ b/internal/rpchelp/methods.go @@ -70,6 +70,7 @@ var Methods = []struct { {"listaddresstransactions", returnsLTRArray}, {"listalltransactions", returnsLTRArray}, {"renameaccount", nil}, + {"rescanblockchain", []interface{}{(*btcjson.RescanBlockchainResult)(nil)}}, {"walletislocked", returnsBool}, } diff --git a/rpc/legacyrpc/methods.go b/rpc/legacyrpc/methods.go index 7ebbc02..8fb2751 100644 --- a/rpc/legacyrpc/methods.go +++ b/rpc/legacyrpc/methods.go @@ -102,6 +102,7 @@ var rpcHandlers = map[string]struct { "listunspent": {handler: listUnspent}, "lockunspent": {handler: lockUnspent}, "sendfrom": {handlerWithChain: sendFrom}, + "rescanblockchain": {handlerWithChain: rescanBlockchain}, "sendmany": {handler: sendMany}, "sendtoaddress": {handler: sendToAddress}, "settxfee": {handler: setTxFee}, @@ -1585,6 +1586,49 @@ func makeOutputs(pairs map[string]btcutil.Amount, chainParams *chaincfg.Params) return outputs, nil } +// rescanBlockchain handles a rescanblockhain RPC request. +func rescanBlockchain(icmd interface{}, w *wallet.Wallet, + chainClient *chain.RPCClient) (interface{}, error) { + + cmd := icmd.(*btcjson.RescanBlockchainCmd) + + _, bestHeight, err := chainClient.GetBestBlock() + if err != nil { + return nil, err + } + + startHeight := *cmd.StartHeight + if startHeight < 0 || startHeight > bestHeight { + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidParameter, + Message: "Invalid start height", + } + } + + // Scan to the best block if no stopHeight is specified. + stopHeight := bestHeight + if cmd.StopHeight != nil { + stopHeight = *cmd.StopHeight + } + if stopHeight < 0 || stopHeight > bestHeight { + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidParameter, + Message: "Invalid stop height", + } + } + + startHeight, stopHeight, err = w.RescanBlockchain(chainClient, + startHeight, stopHeight) + if err != nil { + return nil, fmt.Errorf("rescanblockchain: %w", err) + } + ret := btcjson.RescanBlockchainResult{ + StartHeight: startHeight, + StoptHeight: stopHeight, + } + return ret, nil +} + // sendPairs creates and sends payment transactions. // It returns the transaction hash in string format upon success // All errors are returned in btcjson.RPCError format diff --git a/rpc/legacyrpc/rpcserverhelp.go b/rpc/legacyrpc/rpcserverhelp.go index e652433..2a40f14 100644 --- a/rpc/legacyrpc/rpcserverhelp.go +++ b/rpc/legacyrpc/rpcserverhelp.go @@ -48,6 +48,7 @@ func helpDescsEnUS() map[string]string { "listaddresstransactions": "listaddresstransactions [\"address\",...] (account=\"default\")\n\nReturns a JSON array of objects containing verbose details for wallet transactions pertaining some addresses.\n\nArguments:\n1. addresses (array of string, required) Addresses to filter transaction results by.\n2. account (string, optional, default=\"default\") Account to filter transactions results by. Defaults to 'default'.\n\nResult:\n[{\n \"abandoned\": true|false, (boolean) Unset.\n \"account\": \"value\", (string) The account name associated with the transaction.\n \"address\": \"value\", (string) Payment address for a transaction output.\n \"amount\": n.nnn, (numeric) The value of the transaction output valued in LBC.\n \"bip125-replaceable\": \"value\", (string) Unset.\n \"blockhash\": \"value\", (string) The hash of the block this transaction is mined in, or the empty string if unmined.\n \"blockheight\": n, (numeric) The block height containing the transaction.\n \"blockindex\": n, (numeric) Unset.\n \"blocktime\": n, (numeric) The Unix time of the block header this transaction is mined in, or 0 if unmined.\n \"category\": \"value\", (string) The kind of transaction: \"send\" for sent transactions, \"immature\" for immature coinbase outputs, \"generate\" for mature coinbase outputs, or \"recv\" for all other received outputs. Note: A single output may be included multiple times under different categories\n \"confirmations\": n, (numeric) The number of block confirmations of the transaction.\n \"fee\": n.nnn, (numeric) The total input value minus the total output value for sent transactions.\n \"generated\": true|false, (boolean) Whether the transaction output is a coinbase output.\n \"involveswatchonly\": true|false, (boolean) Unset.\n \"label\": \"value\", (string) A comment for the address/transaction, if any.\n \"time\": n, (numeric) The earliest Unix time this transaction was known to exist.\n \"timereceived\": n, (numeric) The earliest Unix time this transaction was known to exist.\n \"trusted\": true|false, (boolean) Unset.\n \"txid\": \"value\", (string) The hash of the transaction.\n \"vout\": n, (numeric) The transaction output index.\n \"walletconflicts\": [\"value\",...], (array of string) Unset.\n \"comment\": \"value\", (string) Unset.\n \"otheraccount\": \"value\", (string) Unset.\n},...]\n", "listalltransactions": "listalltransactions (account=\"default\")\n\nReturns a JSON array of objects in the same format as 'listtransactions' without limiting the number of returned objects.\n\nArguments:\n1. account (string, optional, default=\"default\") Account to filter transactions results by. Defaults to 'default'.\n\nResult:\n[{\n \"abandoned\": true|false, (boolean) Unset.\n \"account\": \"value\", (string) The account name associated with the transaction.\n \"address\": \"value\", (string) Payment address for a transaction output.\n \"amount\": n.nnn, (numeric) The value of the transaction output valued in LBC.\n \"bip125-replaceable\": \"value\", (string) Unset.\n \"blockhash\": \"value\", (string) The hash of the block this transaction is mined in, or the empty string if unmined.\n \"blockheight\": n, (numeric) The block height containing the transaction.\n \"blockindex\": n, (numeric) Unset.\n \"blocktime\": n, (numeric) The Unix time of the block header this transaction is mined in, or 0 if unmined.\n \"category\": \"value\", (string) The kind of transaction: \"send\" for sent transactions, \"immature\" for immature coinbase outputs, \"generate\" for mature coinbase outputs, or \"recv\" for all other received outputs. Note: A single output may be included multiple times under different categories\n \"confirmations\": n, (numeric) The number of block confirmations of the transaction.\n \"fee\": n.nnn, (numeric) The total input value minus the total output value for sent transactions.\n \"generated\": true|false, (boolean) Whether the transaction output is a coinbase output.\n \"involveswatchonly\": true|false, (boolean) Unset.\n \"label\": \"value\", (string) A comment for the address/transaction, if any.\n \"time\": n, (numeric) The earliest Unix time this transaction was known to exist.\n \"timereceived\": n, (numeric) The earliest Unix time this transaction was known to exist.\n \"trusted\": true|false, (boolean) Unset.\n \"txid\": \"value\", (string) The hash of the transaction.\n \"vout\": n, (numeric) The transaction output index.\n \"walletconflicts\": [\"value\",...], (array of string) Unset.\n \"comment\": \"value\", (string) Unset.\n \"otheraccount\": \"value\", (string) Unset.\n},...]\n", "renameaccount": "renameaccount \"oldaccount\" \"newaccount\"\n\nRenames an account.\n\nArguments:\n1. oldaccount (string, required) The old account name to rename.\n2. newaccount (string, required) The new name for the account.\n\nResult:\nNothing\n", + "rescanblockchain": "rescanblockchain (startheight=0 stopheight)\n\nRenames an account.\n\nArguments:\n1. startheight (numeric, optional, default=0) Block height where the rescan should start.\n2. stopheight (numeric, optional) The last block height that should be scanned. If none is provided it will rescan up to the tip at return time of this call.\n\nResult:\n{\n \"start_height\": n, (numeric) The block height where the rescan started (the requested height or 0)\n \"stop_height\": n, (numeric) The height of the last rescanned block.\n} \n", "walletislocked": "walletislocked\n\nReturns whether or not the wallet is locked.\n\nArguments:\nNone\n\nResult:\ntrue|false (boolean) Whether the wallet is locked.\n", } } @@ -56,4 +57,4 @@ var localeHelpDescs = map[string]func() map[string]string{ "en_US": helpDescsEnUS, } -var requestUsages = "addmultisigaddress nrequired [\"key\",...] (\"account\")\ncreatemultisig nrequired [\"key\",...]\ndumpprivkey \"address\"\ngetaccount \"address\"\ngetaccountaddress (account=\"default\" addresstype=\"legacy\")\ngetaddressesbyaccount (account=\"default\" addresstype=\"*\")\ngetaddressinfo \"address\"\ngetbalance (account=\"default\" minconf=1 addresstype=\"*\")\ngetbestblockhash\ngetblockcount\ngetinfo\ngetnewaddress (account=\"default\" addresstype=\"legacy\")\ngetrawchangeaddress (account=\"default\" addresstype=\"legacy\")\ngetreceivedbyaccount (account=\"default\" minconf=1)\ngetreceivedbyaddress \"address\" (minconf=1)\ngettransaction \"txid\" (includewatchonly=false)\nhelp (\"command\")\nimportprivkey \"privkey\" (\"label\" rescan=true)\nkeypoolrefill (newsize=100)\nlistaccounts (minconf=1 addresstype=\"*\")\nlistlockunspent\nlistreceivedbyaccount (minconf=1 includeempty=false includewatchonly=false)\nlistreceivedbyaddress (minconf=1 includeempty=false includewatchonly=false)\nlistsinceblock (\"blockhash\" targetconfirmations=1 includewatchonly=false)\nlisttransactions (account=\"default\" count=10 from=0 includewatchonly=false)\nlistunspent (minconf=1 maxconf=9999999 [\"address\",...])\nlockunspent unlock [{\"txid\":\"value\",\"vout\":n},...]\nsendfrom \"fromaccount\" \"toaddress\" amount (minconf=1 addresstype=\"*\" \"comment\" \"commentto\")\nsendmany \"fromaccount\" {\"address\":amount,...} (minconf=1 addresstype=\"*\" \"comment\")\nsendtoaddress \"address\" amount (addresstype=\"*\" \"comment\" \"commentto\")\nsettxfee amount\nsignmessage \"address\" \"message\"\nsignrawtransaction \"rawtx\" ([{\"txid\":\"value\",\"vout\":n,\"scriptpubkey\":\"value\",\"redeemscript\":\"value\"},...] [\"privkey\",...] flags=\"ALL\")\nvalidateaddress \"address\"\nverifymessage \"address\" \"signature\" \"message\"\nwalletlock\nwalletpassphrase \"passphrase\" timeout\nwalletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\ncreatenewaccount \"account\"\ngetbestblock\ngetunconfirmedbalance (account=\"default\")\nlistaddresstransactions [\"address\",...] (account=\"default\")\nlistalltransactions (account=\"default\")\nrenameaccount \"oldaccount\" \"newaccount\"\nwalletislocked" +var requestUsages = "addmultisigaddress nrequired [\"key\",...] (\"account\")\ncreatemultisig nrequired [\"key\",...]\ndumpprivkey \"address\"\ngetaccount \"address\"\ngetaccountaddress (account=\"default\" addresstype=\"legacy\")\ngetaddressesbyaccount (account=\"default\" addresstype=\"*\")\ngetaddressinfo \"address\"\ngetbalance (account=\"default\" minconf=1 addresstype=\"*\")\ngetbestblockhash\ngetblockcount\ngetinfo\ngetnewaddress (account=\"default\" addresstype=\"legacy\")\ngetrawchangeaddress (account=\"default\" addresstype=\"legacy\")\ngetreceivedbyaccount (account=\"default\" minconf=1)\ngetreceivedbyaddress \"address\" (minconf=1)\ngettransaction \"txid\" (includewatchonly=false)\nhelp (\"command\")\nimportprivkey \"privkey\" (\"label\" rescan=true)\nkeypoolrefill (newsize=100)\nlistaccounts (minconf=1 addresstype=\"*\")\nlistlockunspent\nlistreceivedbyaccount (minconf=1 includeempty=false includewatchonly=false)\nlistreceivedbyaddress (minconf=1 includeempty=false includewatchonly=false)\nlistsinceblock (\"blockhash\" targetconfirmations=1 includewatchonly=false)\nlisttransactions (account=\"default\" count=10 from=0 includewatchonly=false)\nlistunspent (minconf=1 maxconf=9999999 [\"address\",...])\nlockunspent unlock [{\"txid\":\"value\",\"vout\":n},...]\nsendfrom \"fromaccount\" \"toaddress\" amount (minconf=1 addresstype=\"*\" \"comment\" \"commentto\")\nsendmany \"fromaccount\" {\"address\":amount,...} (minconf=1 addresstype=\"*\" \"comment\")\nsendtoaddress \"address\" amount (addresstype=\"*\" \"comment\" \"commentto\")\nsettxfee amount\nsignmessage \"address\" \"message\"\nsignrawtransaction \"rawtx\" ([{\"txid\":\"value\",\"vout\":n,\"scriptpubkey\":\"value\",\"redeemscript\":\"value\"},...] [\"privkey\",...] flags=\"ALL\")\nvalidateaddress \"address\"\nverifymessage \"address\" \"signature\" \"message\"\nwalletlock\nwalletpassphrase \"passphrase\" timeout\nwalletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\ncreatenewaccount \"account\"\ngetbestblock\ngetunconfirmedbalance (account=\"default\")\nlistaddresstransactions [\"address\",...] (account=\"default\")\nlistalltransactions (account=\"default\")\nrenameaccount \"oldaccount\" \"newaccount\"\nrescanblockchain (startheight=0 stopheight)\nwalletislocked"