Skip to content

Commit 148af66

Browse files
committed
jsonrpc: Add runaccountmixer method.
This new method starts an account mixer in the background and returns to the client without blocking. This differs from the gRPC version of runaccountmixer which blocks until the account mixer returns.
1 parent 31c2f09 commit 148af66

File tree

5 files changed

+65
-1
lines changed

5 files changed

+65
-1
lines changed

internal/rpc/jsonrpc/methods.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"decred.org/dcrwallet/v5/rpc/client/dcrd"
2727
"decred.org/dcrwallet/v5/rpc/jsonrpc/types"
2828
"decred.org/dcrwallet/v5/spv"
29+
"decred.org/dcrwallet/v5/ticketbuyer"
2930
"decred.org/dcrwallet/v5/version"
3031
"decred.org/dcrwallet/v5/wallet"
3132
"decred.org/dcrwallet/v5/wallet/txauthor"
@@ -152,6 +153,7 @@ var handlers = map[string]handler{
152153
"redeemmultisigouts": {fn: (*Server).redeemMultiSigOuts},
153154
"renameaccount": {fn: (*Server).renameAccount},
154155
"rescanwallet": {fn: (*Server).rescanWallet},
156+
"runaccountmixer": {fn: (*Server).runAccountMixer},
155157
"sendfrom": {fn: (*Server).sendFrom},
156158
"sendfromtreasury": {fn: (*Server).sendFromTreasury},
157159
"sendmany": {fn: (*Server).sendMany},
@@ -5522,6 +5524,37 @@ func (s *Server) mixOutput(ctx context.Context, icmd any) (any, error) {
55225524
return nil, err
55235525
}
55245526

5527+
// runAccountMixer starts a new account mixer for the specified account (and
5528+
// branch).
5529+
func (s *Server) runAccountMixer(ctx context.Context, icmd any) (any, error) {
5530+
cmd := icmd.(*types.RunAccountMixerCmd)
5531+
w, ok := s.walletLoader.LoadedWallet()
5532+
if !ok {
5533+
return nil, errUnloadedWallet
5534+
}
5535+
5536+
tb := ticketbuyer.New(w, ticketbuyer.Config{
5537+
Mixing: true,
5538+
MixedAccountBranch: cmd.MixedAccountBranch,
5539+
MixedAccount: cmd.MixedAccount,
5540+
ChangeAccount: cmd.ChangeAccount,
5541+
BuyTickets: false,
5542+
MixChange: true,
5543+
})
5544+
5545+
// Start ticketbuyer in the background rather than blocking the rpc request.
5546+
// Use the server waitgroup to ensure Run can return cleanly rather than
5547+
// being killed mid database transaction.
5548+
s.wg.Add(1)
5549+
go func() {
5550+
defer s.wg.Done()
5551+
serverCtx := s.httpServer.BaseContext(nil)
5552+
_ = tb.Run(serverCtx, []byte(cmd.Passphrase))
5553+
}()
5554+
5555+
return nil, nil
5556+
}
5557+
55255558
func (s *Server) mixAccount(ctx context.Context, icmd any) (any, error) {
55265559
if !s.cfg.Mixing {
55275560
return nil, errors.E("Mixing is not configured")

internal/rpc/jsonrpc/rpcserverhelp.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ func helpDescsEnUS() map[string]string {
7373
"redeemmultisigouts": "redeemmultisigouts \"fromscraddress\" (\"toaddress\" number)\n\nTakes a hash, looks up all unspent outpoints and generates list artially signed transactions spending to either an address specified or internal addresses\n\nArguments:\n1. fromscraddress (string, required) Input script hash address.\n2. toaddress (string, optional) Address to look for (if not internal addresses).\n3. number (numeric, optional) Number of outpoints found.\n\nResult:\n{\n \"hex\": \"value\", (string) Resulting hash.\n \"complete\": true|false, (boolean) Shows if opperation was completed.\n \"errors\": [{ (array of object) Any errors generated.\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",
7474
"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",
7575
"rescanwallet": "rescanwallet (beginheight=0)\n\nRescan the block chain for wallet data, blocking until the rescan completes or exits with an error\n\nArguments:\n1. beginheight (numeric, optional, default=0) The height of the first block to begin the rescan from\n\nResult:\nNothing\n",
76+
"runaccountmixer": "runaccountmixer \"passphrase\" mixedaccount mixedaccountbranch changeaccount\n\nStarts a new account mixer for the specified account (and branch)\n\nArguments:\n1. passphrase (string, required) The private passphrase to unlock the wallet\n2. mixedaccount (numeric, required) The account number to which the mixing funds should end up\n3. mixedaccountbranch (numeric, required) The branch number to which the mixing funds should end up\n4. changeaccount (numeric, required) The account that will be used for any unmixed change that is waiting to be mixed\n\nResult:\nNothing\n",
7677
"sendfrom": "sendfrom \"fromaccount\" \"toaddress\" amount (minconf=1 \"comment\" \"commentto\")\n\nAuthors, signs, and sends a transaction that outputs some amount to a payment address.\nA change output is automatically included to send extra output value back to the original account.\n\nArguments:\n1. fromaccount (string, required) Account to pick unspent outputs from\n2. toaddress (string, required) Address to pay\n3. amount (numeric, required) Amount to send to the payment address valued in decred\n4. minconf (numeric, optional, default=1) Minimum number of block confirmations required before a transaction output is eligible to be spent\n5. comment (string, optional) Unused\n6. commentto (string, optional) Unused\n\nResult:\n\"value\" (string) The transaction hash of the sent transaction\n",
7778
"sendfromtreasury": "sendfromtreasury \"key\" amounts\n\nSend from treasury balance to multiple recipients.\n\nArguments:\n1. key (string, required) Politeia public key\n2. amounts (object, required) Pairs of payment addresses and the output amount to pay each\n{\n \"Address to pay\": Amount to send to the payment address valued in decred, (object) JSON object using payment addresses as keys and output amounts valued in decred to send to each address\n ...\n}\n\nResult:\n\"value\" (string) The transaction hash of the sent transaction\n",
7879
"sendmany": "sendmany \"fromaccount\" {\"address\":amount,...} (minconf=1 \"comment\")\n\nAuthors, signs, and sends a transaction that outputs to many payment addresses.\nA change output is automatically included to send extra output value back to the original account.\n\nArguments:\n1. fromaccount (string, required) Account to pick unspent outputs from\n2. amounts (object, required) Pairs of payment addresses and the output amount to pay each\n{\n \"Address to pay\": Amount to send to the payment address valued in decred, (object) JSON object using payment addresses as keys and output amounts valued in decred to send to each address\n ...\n}\n3. minconf (numeric, optional, default=1) Minimum number of block confirmations required before a transaction output is eligible to be spent\n4. comment (string, optional) Unused\n\nResult:\n\"value\" (string) The transaction hash of the sent transaction\n",
@@ -113,4 +114,4 @@ var localeHelpDescs = map[string]func() map[string]string{
113114
"en_US": helpDescsEnUS,
114115
}
115116

116-
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\"\ndisapprovepercent\ndiscoverusage (\"startblock\" discoveraccounts gaplimit)\ndumpprivkey \"address\"\nfundrawtransaction \"hexstring\" \"fundaccount\" ({\"changeaddress\":changeaddress,\"feerate\":feerate,\"conftarget\":conftarget})\ngetaccount \"address\"\ngetaccountaddress \"account\"\ngetaddressesbyaccount \"account\"\ngetbalance (\"account\" minconf=1)\ngetbestblock\ngetbestblockhash\ngetblockcount\ngetblockhash index\ngetblockheader \"hash\" (verbose=true)\ngetblock \"hash\" (verbose=true verbosetx=false)\ngetcoinjoinsbyacct\ngetcurrentnet\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)\ngettxout \"txid\" vout tree (includemempool=true)\ngetunconfirmedbalance (\"account\")\ngetvotechoices (\"tickethash\")\ngetwalletfee\ngetcfilterv2 \"blockhash\"\nhelp (\"command\")\nimportcfiltersv2 startheight [\"filter\",...]\nimportprivkey \"privkey\" (\"label\" rescan=true scanfrom)\nimportpubkey \"pubkey\" (\"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\"\nprocessunmanagedticket \"tickethash\"\npurchaseticket \"fromaccount\" spendlimit (minconf=1 numtickets=1 expiry \"comment\" dontsigntx)\nredeemmultisigout \"hash\" index tree (\"address\")\nredeemmultisigouts \"fromscraddress\" (\"toaddress\" number)\nrenameaccount \"oldaccount\" \"newaccount\"\nrescanwallet (beginheight=0)\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\"\nsetdisapprovepercent percent\nsettreasurypolicy \"key\" \"policy\" (\"ticket\")\nsettspendpolicy \"hash\" \"policy\" (\"ticket\")\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)\nspendoutputs \"account\" [\"previousoutpoint\",...] [{\"address\":\"value\",\"amount\":n.nnn},...]\nsweepaccount \"sourceaccount\" \"destinationaddress\" (requiredconfirmations feeperkb)\nsyncstatus\nticketinfo (startheight=0)\ntreasurypolicy (\"key\" \"ticket\")\ntspendpolicy (\"hash\" \"ticket\")\nunlockaccount \"account\" \"passphrase\"\nvalidateaddress \"address\"\nvalidatepredcp0005cf\nverifymessage \"address\" \"signature\" \"message\"\nversion\nwalletinfo\nwalletislocked\nwalletlock\nwalletpassphrase \"passphrase\" timeout\nwalletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\nwalletpubpassphrasechange \"oldpassphrase\" \"newpassphrase\""
117+
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\"\ndisapprovepercent\ndiscoverusage (\"startblock\" discoveraccounts gaplimit)\ndumpprivkey \"address\"\nfundrawtransaction \"hexstring\" \"fundaccount\" ({\"changeaddress\":changeaddress,\"feerate\":feerate,\"conftarget\":conftarget})\ngetaccount \"address\"\ngetaccountaddress \"account\"\ngetaddressesbyaccount \"account\"\ngetbalance (\"account\" minconf=1)\ngetbestblock\ngetbestblockhash\ngetblockcount\ngetblockhash index\ngetblockheader \"hash\" (verbose=true)\ngetblock \"hash\" (verbose=true verbosetx=false)\ngetcoinjoinsbyacct\ngetcurrentnet\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)\ngettxout \"txid\" vout tree (includemempool=true)\ngetunconfirmedbalance (\"account\")\ngetvotechoices (\"tickethash\")\ngetwalletfee\ngetcfilterv2 \"blockhash\"\nhelp (\"command\")\nimportcfiltersv2 startheight [\"filter\",...]\nimportprivkey \"privkey\" (\"label\" rescan=true scanfrom)\nimportpubkey \"pubkey\" (\"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\"\nprocessunmanagedticket \"tickethash\"\npurchaseticket \"fromaccount\" spendlimit (minconf=1 numtickets=1 expiry \"comment\" dontsigntx)\nredeemmultisigout \"hash\" index tree (\"address\")\nredeemmultisigouts \"fromscraddress\" (\"toaddress\" number)\nrenameaccount \"oldaccount\" \"newaccount\"\nrescanwallet (beginheight=0)\nrunaccountmixer \"passphrase\" mixedaccount mixedaccountbranch changeaccount\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\"\nsetdisapprovepercent percent\nsettreasurypolicy \"key\" \"policy\" (\"ticket\")\nsettspendpolicy \"hash\" \"policy\" (\"ticket\")\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)\nspendoutputs \"account\" [\"previousoutpoint\",...] [{\"address\":\"value\",\"amount\":n.nnn},...]\nsweepaccount \"sourceaccount\" \"destinationaddress\" (requiredconfirmations feeperkb)\nsyncstatus\nticketinfo (startheight=0)\ntreasurypolicy (\"key\" \"ticket\")\ntspendpolicy (\"hash\" \"ticket\")\nunlockaccount \"account\" \"passphrase\"\nvalidateaddress \"address\"\nvalidatepredcp0005cf\nverifymessage \"address\" \"signature\" \"message\"\nversion\nwalletinfo\nwalletislocked\nwalletlock\nwalletpassphrase \"passphrase\" timeout\nwalletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\nwalletpubpassphrasechange \"oldpassphrase\" \"newpassphrase\""

internal/rpchelp/helpdescs_en_US.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,13 @@ var helpDescsEnUS = map[string]string{
711711
"rescanwallet--synopsis": "Rescan the block chain for wallet data, blocking until the rescan completes or exits with an error",
712712
"rescanwallet-beginheight": "The height of the first block to begin the rescan from",
713713

714+
// RunAccountMixerCmd help.
715+
"runaccountmixer--synopsis": "Starts a new account mixer for the specified account (and branch)",
716+
"runaccountmixer-passphrase": "The private passphrase to unlock the wallet",
717+
"runaccountmixer-mixedaccount": "The account number to which the mixing funds should end up",
718+
"runaccountmixer-mixedaccountbranch": "The branch number to which the mixing funds should end up",
719+
"runaccountmixer-changeaccount": "The account that will be used for any unmixed change that is waiting to be mixed",
720+
714721
// SendFromCmd help.
715722
"sendfrom--synopsis": "Authors, signs, and sends a transaction that outputs some amount to a payment address.\n" +
716723
"A change output is automatically included to send extra output value back to the original account.",

internal/rpchelp/methods.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ var Methods = []struct {
9696
{"redeemmultisigouts", []any{(*types.RedeemMultiSigOutResult)(nil)}},
9797
{"renameaccount", nil},
9898
{"rescanwallet", nil},
99+
{"runaccountmixer", nil},
99100
{"sendfrom", returnsString},
100101
{"sendfromtreasury", returnsString},
101102
{"sendmany", returnsString},

rpc/jsonrpc/types/methods.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,27 @@ func NewWalletPassphraseChangeCmd(oldPassphrase, newPassphrase string) *WalletPa
11231123
}
11241124
}
11251125

1126+
// RunAccountMixerCmd defines the runaccountmixer JSON-RPC command.
1127+
type RunAccountMixerCmd struct {
1128+
Passphrase string
1129+
MixedAccount uint32
1130+
MixedAccountBranch uint32
1131+
ChangeAccount uint32
1132+
}
1133+
1134+
// NewRunAccountMixerCmd returns a new instance which can be used to issue a
1135+
// runaccountmixer JSON-RPC command.
1136+
func NewRunAccountMixerCmd(passphrase string, mixedAccount uint32,
1137+
mixedAccountBranch uint32, changeAccount uint32,
1138+
csppServer string) *RunAccountMixerCmd {
1139+
return &RunAccountMixerCmd{
1140+
Passphrase: passphrase,
1141+
MixedAccount: mixedAccount,
1142+
MixedAccountBranch: mixedAccountBranch,
1143+
ChangeAccount: changeAccount,
1144+
}
1145+
}
1146+
11261147
// MixAccountCmd defines the mixaccount JSON-RPC command.
11271148
type MixAccountCmd struct{}
11281149

@@ -1269,6 +1290,7 @@ func init() {
12691290
{"renameaccount", (*RenameAccountCmd)(nil)},
12701291
{"rescanwallet", (*RescanWalletCmd)(nil)},
12711292
{"revoketickets", (*RevokeTicketsCmd)(nil)},
1293+
{"runaccountmixer", (*RunAccountMixerCmd)(nil)},
12721294
{"sendfrom", (*SendFromCmd)(nil)},
12731295
{"sendfromtreasury", (*SendFromTreasuryCmd)(nil)},
12741296
{"sendmany", (*SendManyCmd)(nil)},

0 commit comments

Comments
 (0)