Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
githubsands committed Oct 6, 2018
1 parent 2bde819 commit 2b2ea48
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 32 deletions.
11 changes: 10 additions & 1 deletion internal/rpchelp/helpdescs_en_US.go
Original file line number Diff line number Diff line change
Expand Up @@ -541,14 +541,23 @@ var helpDescsEnUS = map[string]string{
"verifymessage-message": "The message to verify",
"verifymessage--result0": "Whether the message was signed with the private key of 'address'",

// VerifySeedCmd help.
"verifyseed--synopsis": "Verifes if the inputted seed derived account key is associated with the running wallet account key",
"verifyseed-seed": "Seed to be checked against the running wallets",
"verifyseed-account": "Used to check if a watching only wallets public key is the same as the running wallets",

// VerifySeedResult help.
"verifyseedresult-keyresult": "The result of comparing an inputted seed with the running wallets. Useful to check if a watching only wallet's public key is the same as the running wallet",
"verifyseedresult-cointype": "Outputs the current cointype of the running wallet",

// Version help
"version--synopsis": "Returns application and API versions (semver) keyed by their names",
"version--result0--desc": "Version objects keyed by the program or API name",
"version--result0--key": "Program or API name",
"version--result0--value": "Object containing the semantic version",

// WalletLockCmd help.
"walletlock--synopsis": "Lock the wallet.",
"walletlock--synopsis": "Lock the wallet",

// WalletPassphraseCmd help.
"walletpassphrase--synopsis": "Unlock the wallet.",
Expand Down
1 change: 1 addition & 0 deletions internal/rpchelp/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ var Methods = []struct {
{"ticketsforaddress", returnsBool},
{"validateaddress", []interface{}{(*dcrjson.ValidateAddressWalletResult)(nil)}},
{"verifymessage", returnsBool},
{"verifyseed", []interface{}{(*dcrjson.VerifySeedResult)(nil)}},
{"version", []interface{}{(*map[string]dcrjson.VersionResult)(nil)}},
{"walletinfo", []interface{}{(*dcrjson.WalletInfoResult)(nil)}},
{"walletislocked", returnsBool},
Expand Down
84 changes: 84 additions & 0 deletions rpc/legacyrpc/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (
"github.com/decred/dcrwallet/wallet"
"github.com/decred/dcrwallet/wallet/txrules"
"github.com/decred/dcrwallet/wallet/udb"
"github.com/decred/dcrwallet/walletseed"
)

// API version constants
Expand Down Expand Up @@ -123,6 +124,7 @@ var handlers = map[string]handler{
"ticketsforaddress": {fn: ticketsForAddress},
"validateaddress": {fn: validateAddress},
"verifymessage": {fn: verifyMessage},
"verifyseed": {fn: verifySeed},
"version": {fn: version},
"walletinfo": {fn: walletInfo},
"walletlock": {fn: walletLock},
Expand Down Expand Up @@ -3423,6 +3425,88 @@ WrongAddrKind:
return nil, rpcErrorf(dcrjson.ErrRPCInvalidParameter, "address must be secp256k1 P2PK or P2PKH")
}

func deriveCoinTypeKey(seed []byte, coinType uint32, params *chaincfg.Params) (*hdkeychain.ExtendedKey, error) {
// Create new root from the inputted seed and the current net
root, err := hdkeychain.NewMaster(seed[:], params)
if err != nil {
return nil, err
}

// BIP0032 hierarchy: m/<purpose>'/
// Where purpose = 44 and the ' indicates hardening with the HardenedKeyStart 0x80000000
purpose, err := root.Child(44 + hdkeychain.HardenedKeyStart)
if err != nil {
return nil, err
}
defer purpose.Zero()

// BIP0044 hierarchy: m/<purpose>'/<coin type>'
// Where coin type is either the legacy coin type, 20, or the coin type described in SLIP0044, 44. Note these parameters
// are only appropraite for main net.
coinTypePrivKey, err := purpose.Child(coinType + hdkeychain.HardenedKeyStart)
if err != nil {
return nil, err
}

return coinTypePrivKey, nil
}

// verifySeed checks if a user inputted seed is equivelent to the running wallets.
// Returns a a JSON object, with the dscribed bool and coin type.
func verifySeed(s *Server, icmd interface{}) (interface{}, error) {
cmd := icmd.(*dcrjson.VerifySeedCmd)
w, ok := s.walletLoader.LoadedWallet()
if !ok {
return nil, errUnloadedWallet
}

// obtain the wallet public key to check agaisnt the wallet derived seed
account := 0
if cmd.Account != nil {
account = int(*cmd.Account)
}

coinType, err := w.CoinType()
if err != nil {
return nil, err
}

decodedSeed, err := walletseed.DecodeUserInput(cmd.Seed)
if err != nil {
return nil, err
}

coinTypePrivKey, err := deriveCoinTypeKey(decodedSeed, coinType, w.ChainParams())
if err != nil {
return nil, err
}
defer coinTypePrivKey.Zero()

// Both derivedAccountKey and walletDerivedAccountKey use the BIP044 hierachy: m/44'/<coin type>'/<account>'
accountKey, err := coinTypePrivKey.Child(uint32(account) + hdkeychain.HardenedKeyStart)
if err != nil {
return nil, err
}
defer accountKey.Zero()

// To be matched with walletxPubKey.
seedxPubKey, err := accountKey.Neuter()
if err != nil {
return nil, err
}

// need to get walletsPubKey
walletxPubKey, err := w.MasterPubKey(uint32(account))
if err != nil {
return nil, err
}

return &dcrjson.VerifySeedResult{
Result: walletxPubKey.String() == seedxPubKey.String(),
CoinType: coinType,
}, nil
}

// version handles the version command by returning the RPC API versions of the
// wallet and, optionally, the consensus RPC server as well if it is associated
// with the server. The chainClient is optional, and this is simply a helper
Expand Down
3 changes: 2 additions & 1 deletion rpc/legacyrpc/rpcserverhelp.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ func helpDescsEnUS() map[string]string {
"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",
"validateaddress": "validateaddress \"address\"\n\nVerify that an address is valid.\nExtra details are returned if the address is controlled by this wallet.\nThe following fields are valid only when the address is controlled by this wallet (ismine=true): isscript, pubkey, iscompressed, account, addresses, hex, script, and sigsrequired.\nThe following fields are only valid when address has an associated public key: pubkey, iscompressed.\nThe following fields are only valid when address is a pay-to-script-hash address: addresses, hex, and script.\nIf the address is a multisig address controlled by this wallet, the multisig fields will be left unset if the wallet is locked since the redeem script cannot be decrypted.\n\nArguments:\n1. address (string, required) Address to validate\n\nResult:\n{\n \"isvalid\": true|false, (boolean) Whether or not the address is valid\n \"address\": \"value\", (string) The payment address (only when isvalid is true)\n \"ismine\": true|false, (boolean) Whether this address is controlled by the wallet (only when isvalid is true)\n \"iswatchonly\": true|false, (boolean) Unset\n \"isscript\": true|false, (boolean) Whether the payment address is a pay-to-script-hash address (only when isvalid is true)\n \"pubkeyaddr\": \"value\", (string) The pubkey for this payment address (only when isvalid is true)\n \"pubkey\": \"value\", (string) The associated public key of the payment address, if any (only when isvalid is true)\n \"iscompressed\": true|false, (boolean) Whether the address was created by hashing a compressed public key, if any (only when isvalid is true)\n \"account\": \"value\", (string) The account this payment address belongs to (only when isvalid is true)\n \"addresses\": [\"value\",...], (array of string) All associated payment addresses of the script if address is a multisig address (only when isvalid is true)\n \"hex\": \"value\", (string) The redeem script \n \"script\": \"value\", (string) The class of redeem script for a multisig address\n \"sigsrequired\": n, (numeric) The number of required signatures to redeem outputs to the multisig address\n} \n",
"verifymessage": "verifymessage \"address\" \"signature\" \"message\"\n\nVerify a message was signed with the associated private key of some address.\n\nArguments:\n1. address (string, required) Address used to sign message\n2. signature (string, required) The signature to verify\n3. message (string, required) The message to verify\n\nResult:\ntrue|false (boolean) Whether the message was signed with the private key of 'address'\n",
"verifyseed": "verifyseed \"seed\" (account)\n\nVerifes if the inputted seed derived account key is associated with the running wallet account key\n\nArguments:\n1. seed (string, required) Seed to be checked against the running wallets\n2. account (numeric, optional) Used to check if a watching only wallets public key is the same as the running wallets\n\nResult:\n{\n \"keyresult\": true|false, (boolean) The result of comparing an inputted seed with the running wallets. Useful to check if a watching only wallet's public key is the same as the running wallet\n \"cointype\": n, (numeric) Outputs the current cointype of the running wallet\n} \n",
"version": "version\n\nReturns application and API versions (semver) keyed by their names\n\nArguments:\nNone\n\nResult:\n{\n \"Program or API name\": Object containing the semantic version, (object) Version objects keyed by the program or API name\n ...\n}\n",
"walletinfo": "walletinfo\n\nReturns global information about the wallet\n\nArguments:\nNone\n\nResult:\n{\n \"daemonconnected\": true|false, (boolean) Whether or not the wallet is currently connected to the daemon RPC\n \"unlocked\": true|false, (boolean) Whether or not the wallet is unlocked\n \"txfee\": n.nnn, (numeric) Transaction fee per kB of the serialized tx size in coins\n \"ticketfee\": n.nnn, (numeric) Ticket fee per kB of the serialized tx size in coins\n \"ticketpurchasing\": true|false, (boolean) Whether or not the wallet is currently purchasing tickets\n \"votebits\": n, (numeric) Vote bits setting\n \"votebitsextended\": \"value\", (string) Extended vote bits setting\n \"voteversion\": n, (numeric) Version of votes that will be generated\n \"voting\": true|false, (boolean) Whether or not the wallet is currently voting tickets\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",
Expand All @@ -86,4 +87,4 @@ var localeHelpDescs = map[string]func() map[string]string{
"en_US": helpDescsEnUS,
}

var requestUsages = "accountaddressindex \"account\" branch\naccountsyncaddressindex \"account\" branch index\naddmultisigaddress nrequired [\"key\",...] (\"account\")\naddticket \"tickethex\"\nconsolidate inputs (\"account\" \"address\")\ncreatemultisig nrequired [\"key\",...]\ncreatenewaccount \"account\"\ndumpprivkey \"address\"\nexportwatchingwallet (\"account\" download=false)\ngeneratevote \"blockhash\" height \"tickethash\" votebits \"votebitsext\"\ngetaccountaddress \"account\"\ngetaccount \"address\"\ngetaddressesbyaccount \"account\"\ngetbalance (\"account\" minconf=1)\ngetbestblockhash\ngetbestblock\ngetblockcount\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)\nkeypoolrefill (newsize=100)\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\"\nstartautobuyer \"account\" \"passphrase\" (balancetomaintain maxfeeperkb maxpricerelative maxpriceabsolute \"votingaddress\" \"pooladdress\" poolfees maxperblock)\nstopautobuyer\nsweepaccount \"sourceaccount\" \"destinationaddress\" (requiredconfirmations feeperkb)\nticketsforaddress \"address\"\nvalidateaddress \"address\"\nverifymessage \"address\" \"signature\" \"message\"\nversion\nwalletinfo\nwalletislocked\nwalletlock\nwalletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\nwalletpassphrase \"passphrase\" timeout"
var requestUsages = "accountaddressindex \"account\" branch\naccountsyncaddressindex \"account\" branch index\naddmultisigaddress nrequired [\"key\",...] (\"account\")\nconsolidate inputs (\"account\" \"address\")\ncreatemultisig nrequired [\"key\",...]\ndumpprivkey \"address\"\ngetaccount \"address\"\ngetaccountaddress \"account\"\ngetaddressesbyaccount \"account\"\ngetbalance (\"account\" minconf=1)\ngetbestblockhash\ngetblockcount\ngetinfo\ngetmasterpubkey (\"account\")\ngetmultisigoutinfo \"hash\" index\ngetnewaddress (\"account\" \"gappolicy\")\ngetrawchangeaddress (\"account\")\ngetreceivedbyaccount \"account\" (minconf=1)\ngetreceivedbyaddress \"address\" (minconf=1)\ngettickets includeimmature\ngettransaction \"txid\" (includewatchonly=false)\ngetvotechoices\nhelp (\"command\")\nimportprivkey \"privkey\" (\"label\" rescan=true scanfrom)\nimportscript \"hex\" (rescan=true scanfrom)\nkeypoolrefill (newsize=100)\nlistaccounts (minconf=1)\nlistlockunspent\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\",...])\nlockunspent unlock [{\"amount\":n.nnn,\"txid\":\"value\",\"vout\":n,\"tree\":n},...]\nredeemmultisigout \"hash\" index tree (\"address\")\nredeemmultisigouts \"fromscraddress\" (\"toaddress\" number)\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\")\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)\nstartautobuyer \"account\" \"passphrase\" (balancetomaintain maxfeeperkb maxpricerelative maxpriceabsolute \"votingaddress\" \"pooladdress\" poolfees maxperblock)\nstopautobuyer\nsweepaccount \"sourceaccount\" \"destinationaddress\" (requiredconfirmations feeperkb)\nvalidateaddress \"address\"\nverifymessage \"address\" \"signature\" \"message\"\nverifyseed \"seed\" (account)\nversion\nwalletlock\nwalletpassphrase \"passphrase\" timeout\nwalletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\ncreatenewaccount \"account\"\nexportwatchingwallet (\"account\" download=false)\ngetbestblock\ngetunconfirmedbalance (\"account\")\nlistaddresstransactions [\"address\",...] (\"account\")\nlistalltransactions (\"account\")\nrenameaccount \"oldaccount\" \"newaccount\"\nwalletislocked\nwalletinfo\npurchaseticket \"fromaccount\" spendlimit (minconf=1 \"ticketaddress\" numtickets \"pooladdress\" poolfees expiry \"comment\" ticketfee)\ngeneratevote \"blockhash\" height \"tickethash\" votebits \"votebitsext\"\ngetstakeinfo\ngetticketfee\nsetticketfee fee\ngetwalletfee\naddticket \"tickethex\"\nlistscripts\nstakepooluserinfo \"user\"\nticketsforaddress \"address\""
60 changes: 30 additions & 30 deletions wallet/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -1887,35 +1887,6 @@ func (w *Wallet) MasterPubKey(account uint32) (*hdkeychain.ExtendedKey, error) {
return extKey, nil
}

// GetTransactionsByHashes returns all known transactions identified by a slice
// of transaction hashes. It is possible that not all transactions are found,
// and in this case the known results will be returned along with an inventory
// vector of all missing transactions and an error with code
// NotExist.
func (w *Wallet) GetTransactionsByHashes(txHashes []*chainhash.Hash) (txs []*wire.MsgTx, notFound []*wire.InvVect, err error) {
err = walletdb.View(w.db, func(dbtx walletdb.ReadTx) error {
ns := dbtx.ReadBucket(wtxmgrNamespaceKey)
for _, hash := range txHashes {
tx, err := w.TxStore.Tx(ns, hash)
if err != nil {
return err
}
if tx == nil {
notFound = append(notFound, wire.NewInvVect(wire.InvTypeTx, hash))
} else {
txs = append(txs, tx)
}
}
return nil
})
if err != nil {
return
}
if len(notFound) != 0 {
err = errors.E(errors.NotExist, "transaction(s) not found")
}
return
=======
// CoinTypeKey returns the BIP0044 coin type private key for the passed account.
func (w *Wallet) CoinTypeKey() (*hdkeychain.ExtendedKey, error) {
const op errors.Op = "wallet.CoinTypeKey"
Expand Down Expand Up @@ -1944,7 +1915,36 @@ func (w *Wallet) CoinType() (uint32, error) {
return 0, errors.E(op, err)
}
return coinType, nil
>>>>>>> wallet: Add CoinTypeKey and CoinType functions
}

// GetTransactionsByHashes returns all known transactions identified by a slice
// of transaction hashes. It is possible that not all transactions are found,
// and in this case the known results will be returned along with an inventory
// vector of all missing transactions and an error with code
// NotExist.
func (w *Wallet) GetTransactionsByHashes(txHashes []*chainhash.Hash) (txs []*wire.MsgTx, notFound []*wire.InvVect, err error) {
err = walletdb.View(w.db, func(dbtx walletdb.ReadTx) error {
ns := dbtx.ReadBucket(wtxmgrNamespaceKey)
for _, hash := range txHashes {
tx, err := w.TxStore.Tx(ns, hash)
if err != nil {
return err
}
if tx == nil {
notFound = append(notFound, wire.NewInvVect(wire.InvTypeTx, hash))
} else {
txs = append(txs, tx)
}
}
return nil
})
if err != nil {
return
}
if len(notFound) != 0 {
err = errors.E(errors.NotExist, "transaction(s) not found")
}
return
}

// CreditCategory describes the type of wallet transaction output. The category
Expand Down

0 comments on commit 2b2ea48

Please sign in to comment.