Skip to content

Commit

Permalink
rpc: implement syncstatus JSON-RPC method
Browse files Browse the repository at this point in the history
  • Loading branch information
itswisdomagain authored Apr 15, 2021
1 parent 8ea3da5 commit f7d0826
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 8 deletions.
54 changes: 53 additions & 1 deletion internal/rpc/jsonrpc/methods.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) 2013-2016 The btcsuite developers
// Copyright (c) 2015-2020 The Decred developers
// Copyright (c) 2015-2021 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

Expand Down Expand Up @@ -150,6 +150,7 @@ var handlers = map[string]handler{
"signrawtransactions": {fn: (*Server).signRawTransactions},
"stakepooluserinfo": {fn: (*Server).stakePoolUserInfo},
"sweepaccount": {fn: (*Server).sweepAccount},
"syncstatus": {fn: (*Server).syncStatus},
"ticketinfo": {fn: (*Server).ticketInfo},
"ticketsforaddress": {fn: (*Server).ticketsForAddress},
"treasurypolicy": {fn: (*Server).treasuryPolicy},
Expand Down Expand Up @@ -1223,6 +1224,57 @@ func difficultyRatio(bits uint32, params *chaincfg.Params) float64 {
return ratio
}

// syncStatus handles a syncstatus request.
func (s *Server) syncStatus(ctx context.Context, icmd interface{}) (interface{}, error) {
w, ok := s.walletLoader.LoadedWallet()
if !ok {
return nil, errUnloadedWallet
}
n, err := w.NetworkBackend()
if err != nil {
return nil, err
}

walletBestHash, walletBestHeight := w.MainChainTip(ctx)
bestBlock, err := w.BlockInfo(ctx, wallet.NewBlockIdentifierFromHash(&walletBestHash))
if err != nil {
return nil, err
}
_24HoursAgo := time.Now().UTC().Add(-24 * time.Hour).Unix()
walletBestBlockTooOld := bestBlock.Timestamp < _24HoursAgo

var synced bool
var targetHeight int32

if syncer, ok := n.(*spv.Syncer); ok {
synced = syncer.Synced()
targetHeight = syncer.EstimateMainChainTip()
} else if rpc, ok := n.(*dcrd.RPC); ok {
var chainInfo *dcrdtypes.GetBlockChainInfoResult
err := rpc.Call(ctx, "getblockchaininfo", &chainInfo)
if err != nil {
return nil, err
}
synced = chainInfo.Headers == int64(walletBestHeight)
targetHeight = int32(chainInfo.Headers)
}

var headersFetchProgress float32
blocksToFetch := targetHeight - walletBestHeight
if blocksToFetch <= 0 {
headersFetchProgress = 1
} else {
totalHeadersToFetch := targetHeight - w.InitialHeight()
headersFetchProgress = 1 - (float32(blocksToFetch) / float32(totalHeadersToFetch))
}

return &types.SyncStatusResult{
Synced: synced,
InitialBlockDownload: walletBestBlockTooOld,
HeadersFetchProgress: headersFetchProgress,
}, nil
}

// getInfo handles a getinfo request by returning a structure containing
// information about the current state of the wallet.
func (s *Server) getInfo(ctx context.Context, icmd interface{}) (interface{}, error) {
Expand Down
3 changes: 2 additions & 1 deletion internal/rpc/jsonrpc/rpcserverhelp.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ func helpDescsEnUS() map[string]string {
"signrawtransactions": "signrawtransactions [\"rawtx\",...] (send=true)\n\nSigns transaction inputs using private keys from this wallet and request for a list of transactions.\n\n\nArguments:\n1. rawtxs (array of string, required) A list of transactions to sign (and optionally send).\n2. send (boolean, optional, default=true) Set true to send the transactions after signing.\n\nResult:\n{\n \"results\": [{ (array of object) Returned values from the signrawtransactions command.\n \"signingresult\": { (object) Success or failure of signing.\n \"hex\": \"value\", (string) The resulting transaction encoded as a hexadecimal string\n \"complete\": true|false, (boolean) Whether all input signatures have been created\n \"errors\": [{ (array of object) Script verification errors (if exists)\n \"txid\": \"value\", (string) The transaction hash of the referenced previous output\n \"vout\": n, (numeric) The output index of the referenced previous output\n \"scriptSig\": \"value\", (string) The hex-encoded signature script\n \"sequence\": n, (numeric) Script sequence number\n \"error\": \"value\", (string) Verification or signing error related to the input\n },...], \n }, \n \"sent\": true|false, (boolean) Tells if the transaction was sent.\n \"txhash\": \"value\", (string) The hash of the signed tx.\n },...], \n} \n",
"stakepooluserinfo": "stakepooluserinfo \"user\"\n\nGet user info for stakepool\n\nArguments:\n1. user (string, required) The id of the user to be looked up\n\nResult:\n{\n \"tickets\": [{ (array of object) A list of valid tickets that the user has added\n \"status\": \"value\", (string) The current status of the added ticket\n \"ticket\": \"value\", (string) The hash of the added ticket\n \"ticketheight\": n, (numeric) The height in which the ticket was added\n \"spentby\": \"value\", (string) The vote in which the ticket was spent\n \"spentbyheight\": n, (numeric) The height in which the ticket was spent\n },...], \n \"invalid\": [\"value\",...], (array of string) A list of invalid tickets that the user has added\n} \n",
"sweepaccount": "sweepaccount \"sourceaccount\" \"destinationaddress\" (requiredconfirmations feeperkb)\n\nMoves as much value as possible in a transaction from an account.\n\n\nArguments:\n1. sourceaccount (string, required) The account to be swept.\n2. destinationaddress (string, required) The destination address to pay to.\n3. requiredconfirmations (numeric, optional) The minimum utxo confirmation requirement (optional).\n4. feeperkb (numeric, optional) The minimum relay fee policy (optional).\n\nResult:\n{\n \"unsignedtransaction\": \"value\", (string) The hex encoded string of the unsigned transaction.\n \"totalpreviousoutputamount\": n.nnn, (numeric) The total transaction input amount.\n \"totaloutputamount\": n.nnn, (numeric) The total transaction output amount.\n \"estimatedsignedsize\": n, (numeric) The estimated size of the transaction when signed.\n} \n",
"syncstatus": "syncstatus\n\nReturns information about this wallet's synchronization to the network.\n\nArguments:\nNone\n\nResult:\n{\n \"synced\": true|false, (boolean) Whether or not the wallet is fully caught up to the network.\n \"initialblockdownload\": true|false, (boolean) Best guess of whether this wallet is in the initial block download mode used to catch up the blockchain when it is far behind.\n \"headersfetchprogress\": n.nnn, (numeric) Estimated progress of the headers fetching stage of the current sync process.\n} \n",
"ticketinfo": "ticketinfo (startheight=0)\n\nReturns details of each wallet ticket transaction\n\nArguments:\n1. startheight (numeric, optional, default=0) Specify the starting block height to scan from\n\nResult:\n[{\n \"hash\": \"value\", (string) Transaction hash of the ticket\n \"cost\": n.nnn, (numeric) Amount paid to purchase the ticket; this may be greater than the ticket price at time of purchase\n \"votingaddress\": \"value\", (string) Address of 0th output, which describes the requirements to spend the ticket\n \"status\": \"value\", (string) Description of ticket status (unknown, unmined, immature, mature, live, voted, missed, expired, unspent, revoked)\n \"blockhash\": \"value\", (string) Hash of block ticket is mined in\n \"blockheight\": n, (numeric) Height of block ticket is mined in\n \"vote\": \"value\", (string) Transaction hash of vote which spends the ticket\n \"revocation\": \"value\", (string) Transaction hash of revocation which spends the ticket\n \"choices\": [{ (array of object) Vote preferences set for the ticket\n \"agendaid\": \"value\", (string) The ID for the agenda the choice concerns\n \"agendadescription\": \"value\", (string) A description of the agenda the choice concerns\n \"choiceid\": \"value\", (string) The ID of the current choice for this agenda\n \"choicedescription\": \"value\", (string) A description of the current choice for this agenda\n },...], \n},...]\n",
"ticketsforaddress": "ticketsforaddress \"address\"\n\nRequest all the tickets for an address.\n\nArguments:\n1. address (string, required) Address to look for.\n\nResult:\ntrue|false (boolean) Tickets owned by the specified address.\n",
"treasurypolicy": "treasurypolicy (\"key\")\n\nReturn voting policies for treasury spend transactions by key\n\nArguments:\n1. key (string, optional) Return the policy for a particular key\n\nResult (no key provided):\n[{\n \"key\": \"value\", (string) Treasury key associated with a policy\n \"policy\": \"value\", (string) Voting policy description (abstain, yes, or no)\n},...]\n\nResult (key specified):\n{\n \"key\": \"value\", (string) Treasury key associated with a policy\n \"policy\": \"value\", (string) Voting policy description (abstain, yes, or no)\n} \n",
Expand All @@ -106,4 +107,4 @@ var localeHelpDescs = map[string]func() map[string]string{
"en_US": helpDescsEnUS,
}

var requestUsages = "abandontransaction \"hash\"\naccountaddressindex \"account\" branch\naccountsyncaddressindex \"account\" branch index\naccountunlocked \"account\"\naddmultisigaddress nrequired [\"key\",...] (\"account\")\naddtransaction \"blockhash\" \"transaction\"\nauditreuse (since)\nconsolidate inputs (\"account\" \"address\")\ncreatemultisig nrequired [\"key\",...]\ncreatenewaccount \"account\"\ncreaterawtransaction [{\"amount\":n.nnn,\"txid\":\"value\",\"vout\":n,\"tree\":n},...] {\"address\":amount,...} (locktime expiry)\ncreatesignature \"address\" inputindex hashtype \"previouspkscript\" \"serializedtransaction\"\ndiscoverusage (\"startblock\" discoveraccounts gaplimit)\ndumpprivkey \"address\"\nfundrawtransaction \"hexstring\" \"fundaccount\" ({\"changeaddress\":changeaddress,\"feerate\":feerate,\"conftarget\":conftarget})\ngeneratevote \"blockhash\" height \"tickethash\" votebits \"votebitsext\"\ngetaccount \"address\"\ngetaccountaddress \"account\"\ngetaddressesbyaccount \"account\"\ngetbalance (\"account\" minconf=1)\ngetbestblock\ngetbestblockhash\ngetblockcount\ngetblockhash index\ngetcoinjoinsbyacct\ngetinfo\ngetmasterpubkey (\"account\")\ngetmultisigoutinfo \"hash\" index\ngetnewaddress (\"account\" \"gappolicy\")\ngetpeerinfo\ngetrawchangeaddress (\"account\")\ngetreceivedbyaccount \"account\" (minconf=1)\ngetreceivedbyaddress \"address\" (minconf=1)\ngetstakeinfo\ngettickets includeimmature\ngettransaction \"txid\" (includewatchonly=false)\ngetunconfirmedbalance (\"account\")\ngetvotechoices (\"tickethash\")\ngetwalletfee\nhelp (\"command\")\nimportcfiltersv2 startheight [\"filter\",...]\nimportprivkey \"privkey\" (\"label\" rescan=true scanfrom)\nimportscript \"hex\" (rescan=true scanfrom)\nimportxpub \"name\" \"xpub\"\nlistaccounts (minconf=1)\nlistaddresstransactions [\"address\",...] (\"account\")\nlistalltransactions (\"account\")\nlistlockunspent (\"account\")\nlistreceivedbyaccount (minconf=1 includeempty=false includewatchonly=false)\nlistreceivedbyaddress (minconf=1 includeempty=false includewatchonly=false)\nlistsinceblock (\"blockhash\" targetconfirmations=1 includewatchonly=false)\nlisttransactions (\"account\" count=10 from=0 includewatchonly=false)\nlistunspent (minconf=1 maxconf=9999999 [\"address\",...] \"account\")\nlockaccount \"account\"\nlockunspent unlock [{\"amount\":n.nnn,\"txid\":\"value\",\"vout\":n,\"tree\":n},...]\nmixaccount\nmixoutput \"outpoint\"\npurchaseticket \"fromaccount\" spendlimit (minconf=1 \"ticketaddress\" numtickets=1 \"pooladdress\" poolfees expiry \"comment\" dontsigntx)\nredeemmultisigout \"hash\" index tree (\"address\")\nredeemmultisigouts \"fromscraddress\" (\"toaddress\" number)\nrenameaccount \"oldaccount\" \"newaccount\"\nrescanwallet (beginheight=0)\nrevoketickets\nsendfrom \"fromaccount\" \"toaddress\" amount (minconf=1 \"comment\" \"commentto\")\nsendfromtreasury \"key\" amounts\nsendmany \"fromaccount\" {\"address\":amount,...} (minconf=1 \"comment\")\nsendrawtransaction \"hextx\" (allowhighfees=false)\nsendtoaddress \"address\" amount (\"comment\" \"commentto\")\nsendtomultisig \"fromaccount\" amount [\"pubkey\",...] (nrequired=1 minconf=1 \"comment\")\nsendtotreasury amount\nsetaccountpassphrase \"account\" \"passphrase\"\nsettreasurypolicy \"key\" \"policy\"\nsettspendpolicy \"hash\" \"policy\"\nsettxfee amount\nsetvotechoice \"agendaid\" \"choiceid\" (\"tickethash\")\nsignmessage \"address\" \"message\"\nsignrawtransaction \"rawtx\" ([{\"txid\":\"value\",\"vout\":n,\"tree\":n,\"scriptpubkey\":\"value\",\"redeemscript\":\"value\"},...] [\"privkey\",...] flags=\"ALL\")\nsignrawtransactions [\"rawtx\",...] (send=true)\nstakepooluserinfo \"user\"\nsweepaccount \"sourceaccount\" \"destinationaddress\" (requiredconfirmations feeperkb)\nticketinfo (startheight=0)\nticketsforaddress \"address\"\ntreasurypolicy (\"key\")\ntspendpolicy (\"hash\")\nunlockaccount \"account\" \"passphrase\"\nvalidateaddress \"address\"\nvalidatepredcp0005cf\nverifymessage \"address\" \"signature\" \"message\"\nversion\nwalletinfo\nwalletislocked\nwalletlock\nwalletpassphrase \"passphrase\" timeout\nwalletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\nwalletpubpassphrasechange \"oldpassphrase\" \"newpassphrase\""
var requestUsages = "abandontransaction \"hash\"\naccountaddressindex \"account\" branch\naccountsyncaddressindex \"account\" branch index\naccountunlocked \"account\"\naddmultisigaddress nrequired [\"key\",...] (\"account\")\naddtransaction \"blockhash\" \"transaction\"\nauditreuse (since)\nconsolidate inputs (\"account\" \"address\")\ncreatemultisig nrequired [\"key\",...]\ncreatenewaccount \"account\"\ncreaterawtransaction [{\"amount\":n.nnn,\"txid\":\"value\",\"vout\":n,\"tree\":n},...] {\"address\":amount,...} (locktime expiry)\ncreatesignature \"address\" inputindex hashtype \"previouspkscript\" \"serializedtransaction\"\ndiscoverusage (\"startblock\" discoveraccounts gaplimit)\ndumpprivkey \"address\"\nfundrawtransaction \"hexstring\" \"fundaccount\" ({\"changeaddress\":changeaddress,\"feerate\":feerate,\"conftarget\":conftarget})\ngeneratevote \"blockhash\" height \"tickethash\" votebits \"votebitsext\"\ngetaccount \"address\"\ngetaccountaddress \"account\"\ngetaddressesbyaccount \"account\"\ngetbalance (\"account\" minconf=1)\ngetbestblock\ngetbestblockhash\ngetblockcount\ngetblockhash index\ngetcoinjoinsbyacct\ngetinfo\ngetmasterpubkey (\"account\")\ngetmultisigoutinfo \"hash\" index\ngetnewaddress (\"account\" \"gappolicy\")\ngetpeerinfo\ngetrawchangeaddress (\"account\")\ngetreceivedbyaccount \"account\" (minconf=1)\ngetreceivedbyaddress \"address\" (minconf=1)\ngetstakeinfo\ngettickets includeimmature\ngettransaction \"txid\" (includewatchonly=false)\ngetunconfirmedbalance (\"account\")\ngetvotechoices (\"tickethash\")\ngetwalletfee\nhelp (\"command\")\nimportcfiltersv2 startheight [\"filter\",...]\nimportprivkey \"privkey\" (\"label\" rescan=true scanfrom)\nimportscript \"hex\" (rescan=true scanfrom)\nimportxpub \"name\" \"xpub\"\nlistaccounts (minconf=1)\nlistaddresstransactions [\"address\",...] (\"account\")\nlistalltransactions (\"account\")\nlistlockunspent (\"account\")\nlistreceivedbyaccount (minconf=1 includeempty=false includewatchonly=false)\nlistreceivedbyaddress (minconf=1 includeempty=false includewatchonly=false)\nlistsinceblock (\"blockhash\" targetconfirmations=1 includewatchonly=false)\nlisttransactions (\"account\" count=10 from=0 includewatchonly=false)\nlistunspent (minconf=1 maxconf=9999999 [\"address\",...] \"account\")\nlockaccount \"account\"\nlockunspent unlock [{\"amount\":n.nnn,\"txid\":\"value\",\"vout\":n,\"tree\":n},...]\nmixaccount\nmixoutput \"outpoint\"\npurchaseticket \"fromaccount\" spendlimit (minconf=1 \"ticketaddress\" numtickets=1 \"pooladdress\" poolfees expiry \"comment\" dontsigntx)\nredeemmultisigout \"hash\" index tree (\"address\")\nredeemmultisigouts \"fromscraddress\" (\"toaddress\" number)\nrenameaccount \"oldaccount\" \"newaccount\"\nrescanwallet (beginheight=0)\nrevoketickets\nsendfrom \"fromaccount\" \"toaddress\" amount (minconf=1 \"comment\" \"commentto\")\nsendfromtreasury \"key\" amounts\nsendmany \"fromaccount\" {\"address\":amount,...} (minconf=1 \"comment\")\nsendrawtransaction \"hextx\" (allowhighfees=false)\nsendtoaddress \"address\" amount (\"comment\" \"commentto\")\nsendtomultisig \"fromaccount\" amount [\"pubkey\",...] (nrequired=1 minconf=1 \"comment\")\nsendtotreasury amount\nsetaccountpassphrase \"account\" \"passphrase\"\nsettreasurypolicy \"key\" \"policy\"\nsettspendpolicy \"hash\" \"policy\"\nsettxfee amount\nsetvotechoice \"agendaid\" \"choiceid\" (\"tickethash\")\nsignmessage \"address\" \"message\"\nsignrawtransaction \"rawtx\" ([{\"txid\":\"value\",\"vout\":n,\"tree\":n,\"scriptpubkey\":\"value\",\"redeemscript\":\"value\"},...] [\"privkey\",...] flags=\"ALL\")\nsignrawtransactions [\"rawtx\",...] (send=true)\nstakepooluserinfo \"user\"\nsweepaccount \"sourceaccount\" \"destinationaddress\" (requiredconfirmations feeperkb)\nsyncstatus\nticketinfo (startheight=0)\nticketsforaddress \"address\"\ntreasurypolicy (\"key\")\ntspendpolicy (\"hash\")\nunlockaccount \"account\" \"passphrase\"\nvalidateaddress \"address\"\nvalidatepredcp0005cf\nverifymessage \"address\" \"signature\" \"message\"\nversion\nwalletinfo\nwalletislocked\nwalletlock\nwalletpassphrase \"passphrase\" timeout\nwalletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\nwalletpubpassphrasechange \"oldpassphrase\" \"newpassphrase\""
10 changes: 9 additions & 1 deletion internal/rpchelp/helpdescs_en_US.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) 2015 The btcsuite developers
// Copyright (c) 2015-2020 The Decred developers
// Copyright (c) 2015-2021 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

Expand Down Expand Up @@ -191,6 +191,14 @@ var helpDescsEnUS = map[string]string{
"getblockhash-index": "The block height",
"getblockhash--result0": "The main chain block hash",

// SyncStatusCmd help.
"syncstatus--synopsis": "Returns information about this wallet's synchronization to the network.",

// SyncStatusResult help.
"syncstatusresult-synced": "Whether or not the wallet is fully caught up to the network.",
"syncstatusresult-initialblockdownload": "Best guess of whether this wallet is in the initial block download mode used to catch up the blockchain when it is far behind.",
"syncstatusresult-headersfetchprogress": "Estimated progress of the headers fetching stage of the current sync process.",

// GetInfoCmd help.
"getinfo--synopsis": "Returns a JSON object containing various state info.",

Expand Down
3 changes: 2 additions & 1 deletion internal/rpchelp/methods.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) 2015 The btcsuite developers
// Copyright (c) 2015-2017 The Decred developers
// Copyright (c) 2015-2021 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

Expand Down Expand Up @@ -107,6 +107,7 @@ var Methods = []struct {
{"signrawtransactions", []interface{}{(*types.SignRawTransactionsResult)(nil)}},
{"stakepooluserinfo", []interface{}{(*types.StakePoolUserInfoResult)(nil)}},
{"sweepaccount", []interface{}{(*types.SweepAccountResult)(nil)}},
{"syncstatus", []interface{}{(*types.SyncStatusResult)(nil)}},
{"ticketinfo", []interface{}{(*[]types.TicketInfoResult)(nil)}},
{"ticketsforaddress", returnsBool},
{"treasurypolicy", []interface{}{(*[]types.TreasuryPolicyResult)(nil), (*types.TreasuryPolicyResult)(nil)}},
Expand Down
Loading

0 comments on commit f7d0826

Please sign in to comment.