Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

grpc: Return more info for ValidateAddress. #2091

Merged
merged 2 commits into from Dec 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 15 additions & 15 deletions internal/rpc/rpcserver/server.go
Expand Up @@ -1990,11 +1990,17 @@ func (s *walletServer) ValidateAddress(ctx context.Context, req *pb.ValidateAddr

result.IsValid = true

// NOTE: ValidateAddress only sets script type for owned and P2SH, but
// perhaps it should regardless of address type and ownership:
// ver, scr := addr.PaymentScript()
// class, _ := stdscript.ExtractAddrs(ver, scr, s.wallet.ChainParams())
// result.ScriptType = pb.ValidateAddressResponse_ScriptType(scProto(class))
ver, scr := addr.PaymentScript()
class, _ := stdscript.ExtractAddrs(ver, scr, s.wallet.ChainParams())
result.ScriptType = pb.ValidateAddressResponse_ScriptType(scProto(class))
result.PayToAddrScript = scr
if pker, ok := addr.(stdaddr.SerializedPubKeyer); ok {
result.PubKey = pker.SerializedPubKey()
result.PubKeyAddr = addr.String()
}
if class == stdscript.STScriptHash {
result.IsScript = true
}

ka, err := s.wallet.KnownAddress(ctx, addr)
if err != nil {
Expand Down Expand Up @@ -2024,15 +2030,9 @@ func (s *walletServer) ValidateAddress(ctx context.Context, req *pb.ValidateAddr
}
result.PubKeyAddr = pubKeyAddr.String()
case wallet.P2SHAddress:
result.IsScript = true
version, script := ka.PaymentScript() // addr.PaymentScript()
result.PayToAddrScript = script

// BUG: ka.RedeemScript would only be relevant now since we know the
// PaymentScript class (P2SH), addresses, and required sigs.
class, addrs := stdscript.ExtractAddrs(version, script, s.wallet.ChainParams())
reqSigs := stdscript.DetermineRequiredSigs(version, script)

version, redeem := ka.RedeemScript()
class, addrs := stdscript.ExtractAddrs(version, redeem, s.wallet.ChainParams())
reqSigs := stdscript.DetermineRequiredSigs(version, redeem)
addrStrings := make([]string, len(addrs))
for i, a := range addrs {
addrStrings[i] = a.String()
Expand All @@ -2050,7 +2050,7 @@ func (s *walletServer) ValidateAddress(ctx context.Context, req *pb.ValidateAddr
switch ka := ka.(type) {
case wallet.BIP0044Address:
_, branch, child := ka.Path()
result.IsInternal = branch == 1
result.IsInternal = branch == udb.InternalBranch
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For future reference, udb should not be used anywhere outside of the wallet package. This is a layering violation and it's making it more difficult to convert the package to being internal (but this particular case is not as bad as say, depending on a type defined by that package).

result.Index = child
}

Expand Down
67 changes: 61 additions & 6 deletions rpc/grpc_example/main.go
Expand Up @@ -18,7 +18,7 @@ import (
)

var (
certificateFile = filepath.Join(dcrutil.AppDataDir("dcrwallet", false), "testnet3", "rpc.cert")
certificateFile = filepath.Join(dcrutil.AppDataDir("dcrwallet", false), "rpc.cert")
JoeGruffins marked this conversation as resolved.
Show resolved Hide resolved
walletClientCertFile = "client.pem" // must be part of ~/.dcrwallet/clients.pem
walletClientKeyFile = "client-key.pem"
)
Expand Down Expand Up @@ -85,16 +85,45 @@ func main() {
}

wsClient := pb.NewWalletServiceClient(conn)
validateAddrRequest := &pb.ValidateAddressRequest{
Address: "TcpEWwGdCN3RCNAQUhBn8f2Xdko2JzcQSQs", // ValidateAddress only sets ScriptType for owned and P2SH addresses.

for _, script := range importScripts {
// NOTE: These scripts will forever be imported into your
// testing wallet.
scriptB, err := hex.DecodeString(script)
if err != nil {
fmt.Println(err)
return
}
importScriptRequest := &pb.ImportScriptRequest{
Script: scriptB,
}
_, err = wsClient.ImportScript(context.Background(), importScriptRequest)
if err != nil {
fmt.Println(err)
return
}
}
validateAddrResp, err := wsClient.ValidateAddress(context.Background(), validateAddrRequest)

// Add an owned address to validated addresses.
nextAddressResp, err := wsClient.NextAddress(context.Background(), new(pb.NextAddressRequest))
if err != nil {
fmt.Println(err)
return
}
fmt.Println(validateAddrResp.ScriptType) // unset / non-standard unless wallet-owned AND P2SH!
fmt.Println(prototext.MarshalOptions{Multiline: true}.Format(validateAddrResp))
validateAddrs = append(validateAddrs, nextAddressResp.Address)

for _, addr := range validateAddrs {
validateAddrRequest := &pb.ValidateAddressRequest{
Address: addr,
}
validateAddrResp, err := wsClient.ValidateAddress(context.Background(), validateAddrRequest)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(validateAddrResp.ScriptType)
fmt.Println(prototext.MarshalOptions{Multiline: true}.Format(validateAddrResp))
}
}

var txns = []string{
Expand All @@ -114,3 +143,29 @@ var txns = []string{
// solo ticket
"01000000016db59a8f8e1c9db0a963b08a30f02f1cea95ddd430303a8d9859ee730c01d8650000000000ffffffff03a9d396620200000000001aba76a914fd5e20128a2e5c4bd9abf93386912b627951e5c488ac00000000000000000000206a1e899eb23ed3b51cfe839f708678af833daa5f28794ddf966202000000004e000000000000000000001abd76a914000000000000000000000000000000000000000088ac0000000090720c00014ddf966202000000ffffff7fffffffff6b483045022100e04b03b2844ade2ab84847902dac3ccd6022bc23dc012a11390a59046c59186902202c0f6bddfa4b4c2494f40bfc8a7ec07ab570c4be6d66fa10b48555deb66148d101210248be5d2501e3a9ed3079138a48e943c12e78da56ed752caf590c510f1ce3c929",
}

var importScripts = []string{
// TSPEND
"c376a914d17043c104a57393aa7353e1510e39eab811e3db88ac",
// 2 of 2 multisig
"522103d484eb60ad03549e731ae9045281f8ee14ff6ea11b697f32cde3d8a18992261b210342b0b9c0ecb53cb9761beb0d010bbf08b5049d2a4d3bea5d3a1d95eb664931cb52ae",
// NonStandard
"01",
}

var validateAddrs = []string{
"TcpEWwGdCN3RCNAQUhBn8f2Xdko2JzcQSQs",

"TkKkYvSrnu8orwhtedcJGkD7guarvZUbUAtjr4iKqD9Y8pNEf8iHu", // PubKeyEcdsaSecp256k1V0
"Tsp18L8qTcjzigYXrD5GSdwDmhVYBpKmfUL", // PubKeyHashEcdsaSecp256k1V0
"TkKnVfd6EvzEYAqiELWstkASHgVyYH8JK3gNvAxUX79C9CrnsV8W6", // PubKeyEd25519V0
"TedZCnJ5uQ8z7VzKqdBhP1WP2RBYaaoCiUe", // PubKeyHashEd25519V0
"TkKpSQoKgxqfDPyXp3RTWk7ktTR69zn19vU1zHCdD18r9bMTvDKT3", // PubKeySchnorrSecp256k1V0
"TSs3jHQMbbZGPyftUh4cgaALzgDZhfXGtxn", // PubKeyHashSchnorrSecp256k1V0
"TcvVou7ooM4rJRWNeJYwehJ9fQq1HTc5pbK", // ScriptHashV0

// These are owned imported scripts.
"TcfdqCrK2fiFJBZnGj5N6xs6rMsbQBsJBYf", // TSPEND
"TcrzaAVMbFURm1PpukWru8yE2uBTjvQePoa", // 2 of 2 multisig
"TckSpBht36nMZgnDDjv7xaHUrgCyJpxQiLA", // NonStandard
}
2 changes: 1 addition & 1 deletion wallet/addresses.go
Expand Up @@ -141,7 +141,7 @@ func (m *managedAddress) p2shScript() (uint16, []byte) {
s := []byte{
0: txscript.OP_HASH160,
1: txscript.OP_DATA_20,
22: txscript.OP_EQUALVERIFY,
22: txscript.OP_EQUAL,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

afaict this is correct. It was producing non-standard scripts according to decodescript, and the value was different than what stdaddr will return.

https://github.com/decred/dcrd/blob/931a579e127b466e0776dedf3ee4ae1b5cc25e14/txscript/stdaddr/addressv0.go#L990-L1012

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, it is not OP_EQUALVERIFY

}
copy(s[2:22], sh)
return 0, s
Expand Down
7 changes: 3 additions & 4 deletions wallet/udb/addressmanager.go
Expand Up @@ -103,12 +103,11 @@ func isReservedAccountNum(acct uint32) bool {
// particular, it converts all pubkeys to pubkey hash addresses so they are
// interchangeable by callers.
func normalizeAddress(addr stdaddr.Address) stdaddr.Address {
switch addr := addr.(type) {
case *stdaddr.AddressPubKeyEcdsaSecp256k1V0:
// Return public key hash for public keys.
if addr, ok := addr.(stdaddr.AddressPubKeyHasher); ok {
return addr.AddressPubKeyHash()
default:
return addr
}
return addr
}

// scryptOptions is used to hold the scrypt parameters needed when deriving new
Expand Down