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/btcchain"
|
||||||
"github.com/conformal/btcdb"
|
"github.com/conformal/btcdb"
|
||||||
|
"github.com/conformal/btcec"
|
||||||
"github.com/conformal/btcjson"
|
"github.com/conformal/btcjson"
|
||||||
"github.com/conformal/btcnet"
|
"github.com/conformal/btcnet"
|
||||||
"github.com/conformal/btcscript"
|
"github.com/conformal/btcscript"
|
||||||
|
@ -155,6 +156,7 @@ var rpcHandlersBeforeInit = map[string]commandHandler{
|
||||||
"submitblock": handleSubmitBlock,
|
"submitblock": handleSubmitBlock,
|
||||||
"validateaddress": handleValidateAddress,
|
"validateaddress": handleValidateAddress,
|
||||||
"verifychain": handleVerifyChain,
|
"verifychain": handleVerifyChain,
|
||||||
|
"verifymessage": handleVerifyMessage,
|
||||||
}
|
}
|
||||||
|
|
||||||
// list of commands that we recognise, but for which btcd has no support because
|
// 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{}{},
|
"settxfee": struct{}{},
|
||||||
"signmessage": struct{}{},
|
"signmessage": struct{}{},
|
||||||
"signrawtransaction": struct{}{},
|
"signrawtransaction": struct{}{},
|
||||||
"verifymessage": struct{}{},
|
|
||||||
"walletlock": struct{}{},
|
"walletlock": struct{}{},
|
||||||
"walletpassphrase": struct{}{},
|
"walletpassphrase": struct{}{},
|
||||||
"walletpassphrasechange": struct{}{},
|
"walletpassphrasechange": struct{}{},
|
||||||
|
@ -3143,6 +3144,67 @@ func handleVerifyChain(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{})
|
||||||
return err == nil, nil
|
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
|
// parseCmd parses a marshaled known command, returning any errors as a
|
||||||
// btcjson.Error that can be used in replies. The returned cmd may still
|
// 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.
|
// be non-nil if b is at least a valid marshaled JSON-RPC message.
|
||||||
|
|
Loading…
Reference in a new issue