Implement verifymessage RPC.
This commit is contained in:
parent
6793bb23ac
commit
139d9cb447
1 changed files with 63 additions and 1 deletions
64
rpcserver.go
64
rpcserver.go
|
@ -28,6 +28,7 @@ import (
|
|||
|
||||
"github.com/conformal/btcchain"
|
||||
"github.com/conformal/btcdb"
|
||||
"github.com/conformal/btcec"
|
||||
"github.com/conformal/btcjson"
|
||||
"github.com/conformal/btcnet"
|
||||
"github.com/conformal/btcscript"
|
||||
|
@ -155,6 +156,7 @@ var rpcHandlersBeforeInit = map[string]commandHandler{
|
|||
"submitblock": handleSubmitBlock,
|
||||
"validateaddress": handleValidateAddress,
|
||||
"verifychain": handleVerifyChain,
|
||||
"verifymessage": handleVerifyMessage,
|
||||
}
|
||||
|
||||
// list of commands that we recognise, but for which btcd has no support because
|
||||
|
@ -200,7 +202,6 @@ var rpcAskWallet = map[string]struct{}{
|
|||
"settxfee": struct{}{},
|
||||
"signmessage": struct{}{},
|
||||
"signrawtransaction": struct{}{},
|
||||
"verifymessage": struct{}{},
|
||||
"walletlock": struct{}{},
|
||||
"walletpassphrase": struct{}{},
|
||||
"walletpassphrasechange": struct{}{},
|
||||
|
@ -3143,6 +3144,67 @@ func handleVerifyChain(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{})
|
|||
return err == nil, nil
|
||||
}
|
||||
|
||||
// handleVerifyMessage implements the verifymessage command.
|
||||
func handleVerifyMessage(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
|
||||
c := cmd.(*btcjson.VerifyMessageCmd)
|
||||
|
||||
// Decode the provided address.
|
||||
addr, err := btcutil.DecodeAddress(c.Address, activeNetParams.Params)
|
||||
if err != nil {
|
||||
return nil, btcjson.Error{
|
||||
Code: btcjson.ErrInvalidAddressOrKey.Code,
|
||||
Message: fmt.Sprintf("%s: %v",
|
||||
btcjson.ErrInvalidAddressOrKey.Message, err),
|
||||
}
|
||||
}
|
||||
|
||||
// Only P2PKH addresses are valid for signing.
|
||||
if _, ok := addr.(*btcutil.AddressPubKeyHash); !ok {
|
||||
return nil, btcjson.Error{
|
||||
Code: btcjson.ErrType.Code,
|
||||
Message: "Address is not a pay-to-pubkey-hash address",
|
||||
}
|
||||
}
|
||||
|
||||
// Decode base64 signature.
|
||||
sig, err := base64.StdEncoding.DecodeString(c.Signature)
|
||||
if err != nil {
|
||||
return nil, btcjson.Error{
|
||||
Code: btcjson.ErrParse.Code,
|
||||
Message: fmt.Sprintf("Malformed base64 encoding: %v", err),
|
||||
}
|
||||
}
|
||||
|
||||
// Validate the signature - this just shows that it was valid at all.
|
||||
// we will compare it with the key next.
|
||||
pk, wasCompressed, err := btcec.RecoverCompact(btcec.S256(), sig,
|
||||
btcwire.DoubleSha256([]byte("Bitcoin Signed Message:\n"+c.Message)))
|
||||
if err != nil {
|
||||
// Mirror Bitcoin Core behavior, which treats error in RecoverCompact as
|
||||
// invalid signature.
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Reconstruct the pubkey hash.
|
||||
btcPK := (*btcec.PublicKey)(pk)
|
||||
var serializedPK []byte
|
||||
if wasCompressed {
|
||||
serializedPK = btcPK.SerializeCompressed()
|
||||
} else {
|
||||
serializedPK = btcPK.SerializeUncompressed()
|
||||
}
|
||||
address, err := btcutil.NewAddressPubKey(serializedPK,
|
||||
activeNetParams.Params)
|
||||
if err != nil {
|
||||
// Again mirror Bitcoin Core behavior, which treats error in public key
|
||||
// reconstruction as invalid signature.
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Return boolean if addresses match.
|
||||
return address.EncodeAddress() == c.Address, nil
|
||||
}
|
||||
|
||||
// parseCmd parses a marshaled known command, returning any errors as a
|
||||
// btcjson.Error that can be used in replies. The returned cmd may still
|
||||
// be non-nil if b is at least a valid marshaled JSON-RPC message.
|
||||
|
|
Loading…
Reference in a new issue