Skip to content

Commit 2af2cfa

Browse files
committed
multi: implement removescript rpc.
1 parent 6227901 commit 2af2cfa

File tree

10 files changed

+267
-2
lines changed

10 files changed

+267
-2
lines changed

internal/rpchelp/helpdescs_en_US.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,10 @@ var helpDescsEnUS = map[string]string{
594594
"redeemmultisigouts-toaddress": "Address to look for (if not internal addresses).",
595595
"redeemmultisigouts-fromscraddress": "Input script hash address.",
596596

597+
// RemoveScript help.
598+
"removescript--synopsis": "Removes the provided script from the wallet.",
599+
"removescript-script": "The script to remove.",
600+
597601
// RescanWallet help.
598602
"rescanwallet--synopsis": "Rescan the block chain for wallet data, blocking until the rescan completes or exits with an error",
599603
"rescanwallet-beginheight": "The height of the first block to begin the rescan from",

internal/rpchelp/methods.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ var Methods = []struct {
7777
{"redeemmultisigout", []interface{}{(*types.RedeemMultiSigOutResult)(nil)}},
7878
{"redeemmultisigouts", []interface{}{(*types.RedeemMultiSigOutResult)(nil)}},
7979
{"renameaccount", nil},
80+
{"removescript", nil},
8081
{"rescanwallet", nil},
8182
{"revoketickets", nil},
8283
{"sendfrom", returnsString},

rpc/jsonrpc/methods.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ var handlers = map[string]handler{
119119
"sweepaccount": {fn: (*Server).sweepAccount},
120120
"redeemmultisigout": {fn: (*Server).redeemMultiSigOut},
121121
"redeemmultisigouts": {fn: (*Server).redeemMultiSigOuts},
122+
"removescript": {fn: (*Server).removeScript},
122123
"stakepooluserinfo": {fn: (*Server).stakePoolUserInfo},
123124
"ticketsforaddress": {fn: (*Server).ticketsForAddress},
124125
"validateaddress": {fn: (*Server).validateAddress},
@@ -2426,6 +2427,24 @@ func (s *Server) redeemMultiSigOuts(ctx context.Context, icmd interface{}) (inte
24262427
return types.RedeemMultiSigOutsResult{Results: rmsoResults}, nil
24272428
}
24282429

2430+
// removeScript purges the provided script from the wallet.
2431+
func (s *Server) removeScript(ctx context.Context, icmd interface{}) (interface{}, error) {
2432+
cmd := icmd.(*types.RemoveScriptCmd)
2433+
w, ok := s.walletLoader.LoadedWallet()
2434+
if !ok {
2435+
return nil, errUnloadedWallet
2436+
}
2437+
2438+
script := []byte(cmd.Script)
2439+
scriptAddr, err := dcrutil.NewAddressScriptHash(script, w.ChainParams())
2440+
if err != nil {
2441+
return nil, err
2442+
}
2443+
2444+
err = w.RemoveAddress(scriptAddr)
2445+
return nil, err
2446+
}
2447+
24292448
// rescanWallet initiates a rescan of the block chain for wallet data, blocking
24302449
// until the rescan completes or exits with an error.
24312450
func (s *Server) rescanWallet(ctx context.Context, icmd interface{}) (interface{}, error) {

rpc/jsonrpc/rpcserverhelp.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ func helpDescsEnUS() map[string]string {
5454
"redeemmultisigout": "redeemmultisigout \"hash\" index tree (\"address\")\n\nTakes the input and constructs a P2PKH paying to the specified address.\n\nArguments:\n1. hash (string, required) Hash of the input transaction\n2. index (numeric, required) Idx of the input transaction\n3. tree (numeric, required) Tree the transaction is on.\n4. address (string, optional) Address to pay to.\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",
5555
"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",
5656
"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",
57+
"removescript": "removescript \"script\"\n\nRemoves the provided script from the wallet.\n\nArguments:\n1. script (string, required) The script to remove.\n\nResult:\nNothing\n",
5758
"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",
5859
"revoketickets": "revoketickets\n\nRequests the wallet create revovactions for any previously missed tickets. Wallet must be unlocked.\n\nArguments:\nNone\n\nResult:\nNothing\n",
5960
"sendfrom": "sendfrom \"fromaccount\" \"toaddress\" amount (minconf=1 \"comment\" \"commentto\")\n\nDEPRECATED -- Authors, 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",
@@ -84,4 +85,4 @@ var localeHelpDescs = map[string]func() map[string]string{
8485
"en_US": helpDescsEnUS,
8586
}
8687

87-
var requestUsages = "abandontransaction \"hash\"\naccountaddressindex \"account\" branch\naccountsyncaddressindex \"account\" branch index\naddmultisigaddress nrequired [\"key\",...] (\"account\")\naddticket \"tickethex\"\nconsolidate inputs (\"account\" \"address\")\ncreatemultisig nrequired [\"key\",...]\ncreatenewaccount \"account\"\ndumpprivkey \"address\"\ngeneratevote \"blockhash\" height \"tickethash\" votebits \"votebitsext\"\ngetaccountaddress \"account\"\ngetaccount \"address\"\ngetaddressesbyaccount \"account\"\ngetbalance (\"account\" minconf=1)\ngetbestblockhash\ngetbestblock\ngetblockcount\ngetblockhash index\ngetinfo\ngetmasterpubkey (\"account\")\ngetmultisigoutinfo \"hash\" index\ngetnewaddress (\"account\" \"gappolicy\")\ngetrawchangeaddress (\"account\")\ngetreceivedbyaccount \"account\" (minconf=1)\ngetreceivedbyaddress \"address\" (minconf=1)\ngetstakeinfo\ngetticketfee\ngettickets includeimmature\ngettransaction \"txid\" (includewatchonly=false)\ngetunconfirmedbalance (\"account\")\ngetvotechoices\ngetwalletfee\nhelp (\"command\")\nimportprivkey \"privkey\" (\"label\" rescan=true scanfrom)\nimportscript \"hex\" (rescan=true scanfrom)\nlistaccounts (minconf=1)\nlistaddresstransactions [\"address\",...] (\"account\")\nlistalltransactions (\"account\")\nlistlockunspent\nlistreceivedbyaccount (minconf=1 includeempty=false includewatchonly=false)\nlistreceivedbyaddress (minconf=1 includeempty=false includewatchonly=false)\nlistscripts\nlistsinceblock (\"blockhash\" targetconfirmations=1 includewatchonly=false)\nlisttransactions (\"account\" count=10 from=0 includewatchonly=false)\nlistunspent (minconf=1 maxconf=9999999 [\"address\",...])\nlockunspent unlock [{\"amount\":n.nnn,\"txid\":\"value\",\"vout\":n,\"tree\":n},...]\npurchaseticket \"fromaccount\" spendlimit (minconf=1 \"ticketaddress\" numtickets \"pooladdress\" poolfees expiry \"comment\" ticketfee)\nredeemmultisigout \"hash\" index tree (\"address\")\nredeemmultisigouts \"fromscraddress\" (\"toaddress\" number)\nrenameaccount \"oldaccount\" \"newaccount\"\nrescanwallet (beginheight=0)\nrevoketickets\nsendfrom \"fromaccount\" \"toaddress\" amount (minconf=1 \"comment\" \"commentto\")\nsendmany \"fromaccount\" {\"address\":amount,...} (minconf=1 \"comment\")\nsendtoaddress \"address\" amount (\"comment\" \"commentto\")\nsendtomultisig \"fromaccount\" amount [\"pubkey\",...] (nrequired=1 minconf=1 \"comment\")\nsetticketfee fee\nsettxfee amount\nsetvotechoice \"agendaid\" \"choiceid\"\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)\nticketsforaddress \"address\"\nvalidateaddress \"address\"\nverifymessage \"address\" \"signature\" \"message\"\nversion\nwalletinfo\nwalletislocked\nwalletlock\nwalletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\nwalletpassphrase \"passphrase\" timeout"
88+
var requestUsages = "abandontransaction \"hash\"\naccountaddressindex \"account\" branch\naccountsyncaddressindex \"account\" branch index\naddmultisigaddress nrequired [\"key\",...] (\"account\")\naddticket \"tickethex\"\nconsolidate inputs (\"account\" \"address\")\ncreatemultisig nrequired [\"key\",...]\ncreatenewaccount \"account\"\ndumpprivkey \"address\"\ngeneratevote \"blockhash\" height \"tickethash\" votebits \"votebitsext\"\ngetaccountaddress \"account\"\ngetaccount \"address\"\ngetaddressesbyaccount \"account\"\ngetbalance (\"account\" minconf=1)\ngetbestblockhash\ngetbestblock\ngetblockcount\ngetblockhash index\ngetinfo\ngetmasterpubkey (\"account\")\ngetmultisigoutinfo \"hash\" index\ngetnewaddress (\"account\" \"gappolicy\")\ngetrawchangeaddress (\"account\")\ngetreceivedbyaccount \"account\" (minconf=1)\ngetreceivedbyaddress \"address\" (minconf=1)\ngetstakeinfo\ngetticketfee\ngettickets includeimmature\ngettransaction \"txid\" (includewatchonly=false)\ngetunconfirmedbalance (\"account\")\ngetvotechoices\ngetwalletfee\nhelp (\"command\")\nimportprivkey \"privkey\" (\"label\" rescan=true scanfrom)\nimportscript \"hex\" (rescan=true scanfrom)\nlistaccounts (minconf=1)\nlistaddresstransactions [\"address\",...] (\"account\")\nlistalltransactions (\"account\")\nlistlockunspent\nlistreceivedbyaccount (minconf=1 includeempty=false includewatchonly=false)\nlistreceivedbyaddress (minconf=1 includeempty=false includewatchonly=false)\nlistscripts\nlistsinceblock (\"blockhash\" targetconfirmations=1 includewatchonly=false)\nlisttransactions (\"account\" count=10 from=0 includewatchonly=false)\nlistunspent (minconf=1 maxconf=9999999 [\"address\",...])\nlockunspent unlock [{\"amount\":n.nnn,\"txid\":\"value\",\"vout\":n,\"tree\":n},...]\npurchaseticket \"fromaccount\" spendlimit (minconf=1 \"ticketaddress\" numtickets \"pooladdress\" poolfees expiry \"comment\" ticketfee)\nredeemmultisigout \"hash\" index tree (\"address\")\nredeemmultisigouts \"fromscraddress\" (\"toaddress\" number)\nrenameaccount \"oldaccount\" \"newaccount\"\nremovescript \"script\"\nrescanwallet (beginheight=0)\nrevoketickets\nsendfrom \"fromaccount\" \"toaddress\" amount (minconf=1 \"comment\" \"commentto\")\nsendmany \"fromaccount\" {\"address\":amount,...} (minconf=1 \"comment\")\nsendtoaddress \"address\" amount (\"comment\" \"commentto\")\nsendtomultisig \"fromaccount\" amount [\"pubkey\",...] (nrequired=1 minconf=1 \"comment\")\nsetticketfee fee\nsettxfee amount\nsetvotechoice \"agendaid\" \"choiceid\"\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)\nticketsforaddress \"address\"\nvalidateaddress \"address\"\nverifymessage \"address\" \"signature\" \"message\"\nversion\nwalletinfo\nwalletislocked\nwalletlock\nwalletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\nwalletpassphrase \"passphrase\" timeout"

rpc/jsonrpc/types/methods.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,11 @@ func NewRenameAccountCmd(oldAccount, newAccount string) *RenameAccountCmd {
899899
}
900900
}
901901

902+
// RemoveScriptCmd defines the removescript JSON-RPC command.
903+
type RemoveScriptCmd struct {
904+
Script string
905+
}
906+
902907
// RescanWalletCmd describes the rescanwallet JSON-RPC request and parameters.
903908
type RescanWalletCmd struct {
904909
BeginHeight *int `jsonrpcdefault:"0"`
@@ -1326,6 +1331,7 @@ func init() {
13261331
{"redeemmultisigout", (*RedeemMultiSigOutCmd)(nil)},
13271332
{"redeemmultisigouts", (*RedeemMultiSigOutsCmd)(nil)},
13281333
{"renameaccount", (*RenameAccountCmd)(nil)},
1334+
{"removescript", (*RemoveScriptCmd)(nil)},
13291335
{"rescanwallet", (*RescanWalletCmd)(nil)},
13301336
{"revoketickets", (*RevokeTicketsCmd)(nil)},
13311337
{"sendfrom", (*SendFromCmd)(nil)},

wallet/udb/addressdb.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package udb
88
import (
99
"crypto/sha256"
1010
"encoding/binary"
11+
"fmt"
1112
"time"
1213

1314
"github.com/decred/dcrwallet/errors"
@@ -796,6 +797,34 @@ func putAddrAccountIndex(ns walletdb.ReadWriteBucket, account uint32, addrHash [
796797
return nil
797798
}
798799

800+
// removeAddrAccountIndex removes the provided key to the address account index of the database.
801+
func removeAddrAccountIndex(ns walletdb.ReadWriteBucket, addrHash []byte) error {
802+
bucket := ns.NestedReadWriteBucket(addrAcctIdxBucketName)
803+
accountB := bucket.Get(addrHash)
804+
805+
if accountB != nil {
806+
msg := fmt.Sprintf("no account value found for address hash %x", addrHash)
807+
return errors.E(errors.IO, msg)
808+
}
809+
810+
err := bucket.Delete(addrHash)
811+
if err != nil {
812+
return errors.E(errors.IO, err)
813+
}
814+
815+
abkt := bucket.NestedReadWriteBucket(accountB)
816+
if err != nil {
817+
return errors.E(errors.IO, err)
818+
}
819+
820+
err = abkt.Delete(addrHash)
821+
if err != nil {
822+
return errors.E(errors.IO, err)
823+
}
824+
825+
return nil
826+
}
827+
799828
// putAccountRow stores the provided account information to the database. This
800829
// is used a common base for storing the various account types.
801830
func putAccountRow(ns walletdb.ReadWriteBucket, account uint32, row *dbAccountRow) error {
@@ -1093,6 +1122,18 @@ func putAddress(ns walletdb.ReadWriteBucket, addressID []byte, row *dbAddressRow
10931122
return putAddrAccountIndex(ns, row.account, addrHash[:])
10941123
}
10951124

1125+
// removeAddress removes the provided address id.
1126+
func removeAddress(ns walletdb.ReadWriteBucket, addressID []byte) error {
1127+
bucket := ns.NestedReadWriteBucket(addrBucketName)
1128+
addrHash := sha256.Sum256(addressID)
1129+
err := bucket.Delete(addrHash[:])
1130+
if err != nil {
1131+
return errors.E(errors.IO, err)
1132+
}
1133+
1134+
return removeAddrAccountIndex(ns, addrHash[:])
1135+
}
1136+
10961137
// putChainedAddress stores the provided chained address information to the
10971138
// database.
10981139
func putChainedAddress(ns walletdb.ReadWriteBucket, addressID []byte, account uint32,

wallet/udb/addressmanager.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,6 +1261,11 @@ func (m *Manager) ImportScript(ns walletdb.ReadWriteBucket, script []byte) (Mana
12611261
return newScriptAddress(m, ImportedAddrAccount, scriptHash)
12621262
}
12631263

1264+
// RemoveAddress removes the provided address from the manager.
1265+
func (m *Manager) RemoveAddress(ns walletdb.ReadWriteBucket, addressID []byte) error {
1266+
return removeAddress(ns, addressID)
1267+
}
1268+
12641269
// IsLocked returns whether or not the address managed is locked. When it is
12651270
// unlocked, the decryption key needed to decrypt private keys used for signing
12661271
// is in memory.

0 commit comments

Comments
 (0)