[lbry] rpc: getaddressinfo
Co-authored-by: Brannon King <countprimes@gmail.com>
This commit is contained in:
parent
879bf10dde
commit
f52bea1e37
2 changed files with 157 additions and 1 deletions
|
@ -78,6 +78,7 @@ var rpcHandlers = map[string]struct {
|
||||||
"getaccount": {handler: getAccount},
|
"getaccount": {handler: getAccount},
|
||||||
"getaccountaddress": {handler: getAccountAddress},
|
"getaccountaddress": {handler: getAccountAddress},
|
||||||
"getaddressesbyaccount": {handler: getAddressesByAccount},
|
"getaddressesbyaccount": {handler: getAddressesByAccount},
|
||||||
|
"getaddressinfo": {handler: getAddressInfo},
|
||||||
"getbalance": {handler: getBalance},
|
"getbalance": {handler: getBalance},
|
||||||
"getbestblockhash": {handler: getBestBlockHash},
|
"getbestblockhash": {handler: getBestBlockHash},
|
||||||
"getblockcount": {handler: getBlockCount},
|
"getblockcount": {handler: getBlockCount},
|
||||||
|
@ -415,6 +416,161 @@ func getAddressesByAccount(icmd interface{}, w *wallet.Wallet) (interface{}, err
|
||||||
return addrStrs, nil
|
return addrStrs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getAddressInfo handles a getaddressinfo request by returning
|
||||||
|
// information about the given address.
|
||||||
|
// Some of the information will only be present if the address
|
||||||
|
// is in the active wallet.
|
||||||
|
func getAddressInfo(icmd interface{}, w *wallet.Wallet) (interface{}, error) {
|
||||||
|
cmd := icmd.(*btcjson.GetAddressInfoCmd)
|
||||||
|
|
||||||
|
var result btcjson.GetAddressInfoResult
|
||||||
|
|
||||||
|
addr, err := decodeAddress(cmd.Address, w.ChainParams())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.Address = addr.EncodeAddress()
|
||||||
|
|
||||||
|
buf := bytes.NewBuffer(nil)
|
||||||
|
switch a := addr.(type) {
|
||||||
|
case *btcutil.AddressPubKey:
|
||||||
|
pubKey := a.PubKey().SerializeCompressed()
|
||||||
|
pubKeyStr := hex.EncodeToString(pubKey)
|
||||||
|
result.PubKey = &pubKeyStr
|
||||||
|
isCompressed := true
|
||||||
|
result.IsCompressed = &isCompressed
|
||||||
|
case *btcutil.AddressPubKeyHash:
|
||||||
|
buf.WriteByte(0x76) // OP_DUP
|
||||||
|
buf.WriteByte(0xA9) // OP_HASH160
|
||||||
|
buf.WriteByte(0x14) // OP_DATA_20
|
||||||
|
buf.Write(addr.ScriptAddress())
|
||||||
|
buf.WriteByte(0x88) // OP_EQUALVERIFY
|
||||||
|
buf.WriteByte(0xAC) // OP_CHECKSIG
|
||||||
|
case *btcutil.AddressScriptHash:
|
||||||
|
buf.WriteByte(0xA9) // OP_HASH160
|
||||||
|
buf.Write(a.ScriptAddress())
|
||||||
|
buf.WriteByte(0x87) // OP_EQUAL
|
||||||
|
result.IsScript = true
|
||||||
|
case *btcutil.AddressWitnessPubKeyHash:
|
||||||
|
buf.WriteByte(0x00) // OP_0
|
||||||
|
buf.Write(a.ScriptAddress())
|
||||||
|
result.IsWitness = true
|
||||||
|
program := hex.EncodeToString(a.WitnessProgram())
|
||||||
|
result.WitnessProgram = &program
|
||||||
|
result.WitnessVersion = int(a.WitnessVersion())
|
||||||
|
case *btcutil.AddressWitnessScriptHash:
|
||||||
|
buf.WriteByte(0x00) // OP_0
|
||||||
|
buf.Write(a.ScriptAddress())
|
||||||
|
result.IsScript = true
|
||||||
|
result.IsWitness = true
|
||||||
|
program := hex.EncodeToString(a.WitnessProgram())
|
||||||
|
result.WitnessProgram = &program
|
||||||
|
result.WitnessVersion = int(a.WitnessVersion())
|
||||||
|
}
|
||||||
|
result.ScriptPubKey = hex.EncodeToString(buf.Bytes())
|
||||||
|
|
||||||
|
ainfo, err := w.AddressInfo(addr)
|
||||||
|
if err != nil {
|
||||||
|
if waddrmgr.IsError(err, waddrmgr.ErrAddressNotFound) {
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result.IsMine = true
|
||||||
|
result.IsChange = ainfo.Internal()
|
||||||
|
isCompressed := ainfo.Compressed()
|
||||||
|
result.IsCompressed = &isCompressed
|
||||||
|
|
||||||
|
switch ma := ainfo.(type) {
|
||||||
|
case waddrmgr.ManagedPubKeyAddress:
|
||||||
|
pubKey := ma.ExportPubKey()
|
||||||
|
result.PubKey = &pubKey
|
||||||
|
|
||||||
|
scope, path, isHD := ma.DerivationInfo()
|
||||||
|
if isHD {
|
||||||
|
|
||||||
|
hdPath := fmt.Sprintf("%s/%d/%d/%d",
|
||||||
|
scope.String(), path.Account, path.Branch, path.Index)
|
||||||
|
if path.Account >= 0x80000000 {
|
||||||
|
hdPath = fmt.Sprintf("%s/%d'/%d/%d",
|
||||||
|
scope.String(), path.Account-0x80000000, path.Branch, path.Index)
|
||||||
|
|
||||||
|
}
|
||||||
|
result.HDKeyPath = &hdPath
|
||||||
|
}
|
||||||
|
|
||||||
|
case waddrmgr.ManagedScriptAddress:
|
||||||
|
result.IsScript = true
|
||||||
|
|
||||||
|
// The script is only available if the manager is unlocked, so
|
||||||
|
// just break out now if there is an error.
|
||||||
|
script, err := ma.Script()
|
||||||
|
if err != nil {
|
||||||
|
if waddrmgr.IsError(err, waddrmgr.ErrWatchingOnly) {
|
||||||
|
result.IsWatchOnly = true
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
hexScript := hex.EncodeToString(script)
|
||||||
|
result.Hex = &hexScript
|
||||||
|
|
||||||
|
// This typically shouldn't fail unless an invalid script was
|
||||||
|
// imported. However, if it fails for any reason, there is no
|
||||||
|
// further information available, so just set the script type
|
||||||
|
// a non-standard and break out now.
|
||||||
|
class, addrs, reqSigs, err := txscript.ExtractPkScriptAddrs(script, w.ChainParams())
|
||||||
|
if err != nil {
|
||||||
|
class = txscript.NonStandardTy
|
||||||
|
result.ScriptType = &class
|
||||||
|
break
|
||||||
|
}
|
||||||
|
addrStrings := make([]string, len(addrs))
|
||||||
|
for i, a := range addrs {
|
||||||
|
addrStrings[i] = a.EncodeAddress()
|
||||||
|
}
|
||||||
|
result.PubKeys = &addrStrings
|
||||||
|
|
||||||
|
// Multi-signature scripts also provide the number of required
|
||||||
|
// signatures.
|
||||||
|
result.ScriptType = &class
|
||||||
|
if class == txscript.MultiSigTy {
|
||||||
|
result.SignaturesRequired = &reqSigs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// type embeddedAddressInfo struct {
|
||||||
|
// # Address string `json:"address"`
|
||||||
|
// # ScriptPubKey string `json:"scriptPubKey"`
|
||||||
|
// Solvable bool `json:"solvable"`
|
||||||
|
// Descriptor *string `json:"desc,omitempty"`
|
||||||
|
// IsScript bool `json:"isscript"`
|
||||||
|
// IsChange bool `json:"ischange"`
|
||||||
|
// IsWitness bool `json:"iswitness"`
|
||||||
|
// WitnessVersion int `json:"witness_version,omitempty"`
|
||||||
|
// WitnessProgram *string `json:"witness_program,omitempty"`
|
||||||
|
// ScriptType *txscript.ScriptClass `json:"script,omitempty"`
|
||||||
|
// Hex *string `json:"hex,omitempty"`
|
||||||
|
// PubKeys *[]string `json:"pubkeys,omitempty"`
|
||||||
|
// SignaturesRequired *int `json:"sigsrequired,omitempty"`
|
||||||
|
// PubKey *string `json:"pubkey,omitempty"`
|
||||||
|
// IsCompressed *bool `json:"iscompressed,omitempty"`
|
||||||
|
// HDMasterFingerprint *string `json:"hdmasterfingerprint,omitempty"`
|
||||||
|
// Labels []string `json:"labels"`
|
||||||
|
// }
|
||||||
|
|
||||||
|
// type GetAddressInfoResult struct {
|
||||||
|
// embeddedAddressInfo
|
||||||
|
// IsMine bool `json:"ismine"`
|
||||||
|
// IsWatchOnly bool `json:"iswatchonly"`
|
||||||
|
// Timestamp *int `json:"timestamp,omitempty"`
|
||||||
|
// HDKeyPath *string `json:"hdkeypath,omitempty"`
|
||||||
|
// HDSeedID *string `json:"hdseedid,omitempty"`
|
||||||
|
// Embedded *embeddedAddressInfo `json:"embedded,omitempty"`
|
||||||
|
// }
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
// getBalance handles a getbalance request by returning the balance for an
|
// getBalance handles a getbalance request by returning the balance for an
|
||||||
// account (wallet), or an error if the requested account does not
|
// account (wallet), or an error if the requested account does not
|
||||||
// exist.
|
// exist.
|
||||||
|
|
|
@ -53,7 +53,7 @@ const (
|
||||||
WitnessScript
|
WitnessScript
|
||||||
)
|
)
|
||||||
|
|
||||||
// ManagedAddress is an interface that provides acces to information regarding
|
// ManagedAddress is an interface that provides access to information regarding
|
||||||
// an address managed by an address manager. Concrete implementations of this
|
// an address managed by an address manager. Concrete implementations of this
|
||||||
// type may provide further fields to provide information specific to that type
|
// type may provide further fields to provide information specific to that type
|
||||||
// of address.
|
// of address.
|
||||||
|
|
Loading…
Reference in a new issue