mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 07:06:42 +00:00
whisper: API refactoring (Post and Filter)
This commit is contained in:
parent
490d4701e1
commit
a25228a27c
10 changed files with 362 additions and 360 deletions
|
|
@ -199,23 +199,23 @@ func initialize() {
|
||||||
shh = whisper.New()
|
shh = whisper.New()
|
||||||
}
|
}
|
||||||
|
|
||||||
asymKeyID, err = shh.NewIdentity()
|
asymKeyID, err = shh.NewKeyPair()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to generate a new key pair: %s", err)
|
utils.Fatalf("Failed to generate a new key pair: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
asymKey, err = shh.GetIdentity(asymKeyID)
|
asymKey, err = shh.GetPrivateKey(asymKeyID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to retrieve a new key pair: %s", err)
|
utils.Fatalf("Failed to retrieve a new key pair: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if nodeid == nil {
|
if nodeid == nil {
|
||||||
tmpID, err := shh.NewIdentity()
|
tmpID, err := shh.NewKeyPair()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to generate a new key pair: %s", err)
|
utils.Fatalf("Failed to generate a new key pair: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeid, err = shh.GetIdentity(tmpID)
|
nodeid, err = shh.GetPrivateKey(tmpID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to retrieve a new key pair: %s", err)
|
utils.Fatalf("Failed to retrieve a new key pair: %s", err)
|
||||||
}
|
}
|
||||||
|
|
@ -325,10 +325,10 @@ func configureNode() {
|
||||||
}
|
}
|
||||||
|
|
||||||
filter := whisper.Filter{
|
filter := whisper.Filter{
|
||||||
KeySym: symKey,
|
KeySym: symKey,
|
||||||
KeyAsym: asymKey,
|
KeyAsym: asymKey,
|
||||||
Topics: []whisper.TopicType{topic},
|
Topics: []whisper.TopicType{topic},
|
||||||
AcceptP2P: p2pAccept,
|
AllowP2P: p2pAccept,
|
||||||
}
|
}
|
||||||
filterID, err = shh.Watch(&filter)
|
filterID, err = shh.Watch(&filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -102,11 +102,11 @@ func TestMailServer(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func deliverTest(t *testing.T, server *WMailServer, env *whisper.Envelope) {
|
func deliverTest(t *testing.T, server *WMailServer, env *whisper.Envelope) {
|
||||||
id, err := shh.NewIdentity()
|
id, err := shh.NewKeyPair()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to generate new key pair with seed %d: %s.", seed, err)
|
t.Fatalf("failed to generate new key pair with seed %d: %s.", seed, err)
|
||||||
}
|
}
|
||||||
testPeerID, err := shh.GetIdentity(id)
|
testPeerID, err := shh.GetPrivateKey(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to retireve new key pair with seed %d: %s.", seed, err)
|
t.Fatalf("failed to retireve new key pair with seed %d: %s.", seed, err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,12 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
mathrand "math/rand"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||||
)
|
)
|
||||||
|
|
||||||
var whisperOffLineErr = errors.New("whisper is offline")
|
var whisperOffLineErr = errors.New("whisper is offline")
|
||||||
|
|
@ -65,7 +65,7 @@ func (api *PublicWhisperAPI) Version() (hexutil.Uint, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stats returns the Whisper statistics for diagnostics.
|
// Stats returns the Whisper statistics for diagnostics.
|
||||||
func (api *PublicWhisperAPI) Stats() (string, error) {
|
func (api *PublicWhisperAPI) Info() (string, error) {
|
||||||
if api.whisper == nil {
|
if api.whisper == nil {
|
||||||
return "", whisperOffLineErr
|
return "", whisperOffLineErr
|
||||||
}
|
}
|
||||||
|
|
@ -108,29 +108,29 @@ func (api *PublicWhisperAPI) MarkPeerTrusted(peerID hexutil.Bytes) error {
|
||||||
|
|
||||||
// HasIdentity checks if the whisper node is configured with the private key
|
// HasIdentity checks if the whisper node is configured with the private key
|
||||||
// of the specified public pair.
|
// of the specified public pair.
|
||||||
func (api *PublicWhisperAPI) HasIdentity(id string) (bool, error) {
|
func (api *PublicWhisperAPI) HasKeyPair(id string) (bool, error) {
|
||||||
if api.whisper == nil {
|
if api.whisper == nil {
|
||||||
return false, whisperOffLineErr
|
return false, whisperOffLineErr
|
||||||
}
|
}
|
||||||
return api.whisper.HasIdentity(id), nil
|
return api.whisper.HasKeyPair(id), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteIdentity deletes the specifies key if it exists.
|
// DeleteIdentity deletes the specifies key if it exists.
|
||||||
func (api *PublicWhisperAPI) DeleteIdentity(id string) (bool, error) {
|
func (api *PublicWhisperAPI) DeleteKeyPair(id string) (bool, error) {
|
||||||
if api.whisper == nil {
|
if api.whisper == nil {
|
||||||
return false, whisperOffLineErr
|
return false, whisperOffLineErr
|
||||||
}
|
}
|
||||||
success := api.whisper.DeleteIdentity(id)
|
success := api.whisper.DeleteKeyPair(id)
|
||||||
return success, nil
|
return success, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIdentity generates a new cryptographic identity for the client, and injects
|
// NewKeyPair generates a new cryptographic identity for the client, and injects
|
||||||
// it into the known identities for message decryption.
|
// it into the known identities for message decryption.
|
||||||
func (api *PublicWhisperAPI) NewIdentity() (string, error) {
|
func (api *PublicWhisperAPI) NewKeyPair() (string, error) {
|
||||||
if api.whisper == nil {
|
if api.whisper == nil {
|
||||||
return "", whisperOffLineErr
|
return "", whisperOffLineErr
|
||||||
}
|
}
|
||||||
return api.whisper.NewIdentity()
|
return api.whisper.NewKeyPair()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPublicKey returns the public key for identity id
|
// GetPublicKey returns the public key for identity id
|
||||||
|
|
@ -138,7 +138,7 @@ func (api *PublicWhisperAPI) GetPublicKey(id string) (string, error) {
|
||||||
if api.whisper == nil {
|
if api.whisper == nil {
|
||||||
return "", whisperOffLineErr
|
return "", whisperOffLineErr
|
||||||
}
|
}
|
||||||
key, err := api.whisper.GetIdentity(id)
|
key, err := api.whisper.GetPrivateKey(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
@ -150,7 +150,7 @@ func (api *PublicWhisperAPI) GetPrivateKey(id string) (string, error) {
|
||||||
if api.whisper == nil {
|
if api.whisper == nil {
|
||||||
return "", whisperOffLineErr
|
return "", whisperOffLineErr
|
||||||
}
|
}
|
||||||
key, err := api.whisper.GetIdentity(id)
|
key, err := api.whisper.GetPrivateKey(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
@ -159,7 +159,7 @@ func (api *PublicWhisperAPI) GetPrivateKey(id string) (string, error) {
|
||||||
|
|
||||||
// GenerateSymKey generates a random symmetric key and stores it under id,
|
// GenerateSymKey generates a random symmetric key and stores it under id,
|
||||||
// which is then returned. Will be used in the future for session key exchange.
|
// which is then returned. Will be used in the future for session key exchange.
|
||||||
func (api *PublicWhisperAPI) GenerateSymKey() (string, error) {
|
func (api *PublicWhisperAPI) GenerateSymmetricKey() (string, error) {
|
||||||
if api.whisper == nil {
|
if api.whisper == nil {
|
||||||
return "", whisperOffLineErr
|
return "", whisperOffLineErr
|
||||||
}
|
}
|
||||||
|
|
@ -167,7 +167,7 @@ func (api *PublicWhisperAPI) GenerateSymKey() (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddSymKeyDirect stores the key, and returns its id.
|
// AddSymKeyDirect stores the key, and returns its id.
|
||||||
func (api *PublicWhisperAPI) AddSymKeyDirect(key hexutil.Bytes) (string, error) {
|
func (api *PublicWhisperAPI) AddSymmetricKeyDirect(key hexutil.Bytes) (string, error) {
|
||||||
if api.whisper == nil {
|
if api.whisper == nil {
|
||||||
return "", whisperOffLineErr
|
return "", whisperOffLineErr
|
||||||
}
|
}
|
||||||
|
|
@ -175,7 +175,7 @@ func (api *PublicWhisperAPI) AddSymKeyDirect(key hexutil.Bytes) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddSymKeyFromPassword generates the key from password, stores it, and returns its id.
|
// AddSymKeyFromPassword generates the key from password, stores it, and returns its id.
|
||||||
func (api *PublicWhisperAPI) AddSymKeyFromPassword(password string) (string, error) {
|
func (api *PublicWhisperAPI) AddSymmetricKeyFromPassword(password string) (string, error) {
|
||||||
if api.whisper == nil {
|
if api.whisper == nil {
|
||||||
return "", whisperOffLineErr
|
return "", whisperOffLineErr
|
||||||
}
|
}
|
||||||
|
|
@ -184,7 +184,7 @@ func (api *PublicWhisperAPI) AddSymKeyFromPassword(password string) (string, err
|
||||||
|
|
||||||
// HasSymKey returns true if there is a key associated with the given id.
|
// HasSymKey returns true if there is a key associated with the given id.
|
||||||
// Otherwise returns false.
|
// Otherwise returns false.
|
||||||
func (api *PublicWhisperAPI) HasSymKey(id string) (bool, error) {
|
func (api *PublicWhisperAPI) HasSymmetricKey(id string) (bool, error) {
|
||||||
if api.whisper == nil {
|
if api.whisper == nil {
|
||||||
return false, whisperOffLineErr
|
return false, whisperOffLineErr
|
||||||
}
|
}
|
||||||
|
|
@ -192,7 +192,7 @@ func (api *PublicWhisperAPI) HasSymKey(id string) (bool, error) {
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *PublicWhisperAPI) GetSymKey(name string) ([]byte, error) {
|
func (api *PublicWhisperAPI) GetSymmetricKey(name string) ([]byte, error) {
|
||||||
if api.whisper == nil {
|
if api.whisper == nil {
|
||||||
return nil, whisperOffLineErr
|
return nil, whisperOffLineErr
|
||||||
}
|
}
|
||||||
|
|
@ -200,7 +200,7 @@ func (api *PublicWhisperAPI) GetSymKey(name string) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteSymKey deletes the key associated with the name string if it exists.
|
// DeleteSymKey deletes the key associated with the name string if it exists.
|
||||||
func (api *PublicWhisperAPI) DeleteSymKey(name string) (bool, error) {
|
func (api *PublicWhisperAPI) DeleteSymmetricKey(name string) (bool, error) {
|
||||||
if api.whisper == nil {
|
if api.whisper == nil {
|
||||||
return false, whisperOffLineErr
|
return false, whisperOffLineErr
|
||||||
}
|
}
|
||||||
|
|
@ -208,77 +208,72 @@ func (api *PublicWhisperAPI) DeleteSymKey(name string) (bool, error) {
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWhisperFilter creates and registers a new message filter to watch for inbound whisper messages.
|
// Subscribe creates and registers a new filter to watch for inbound whisper messages.
|
||||||
// Returns the ID of the newly created Filter.
|
// Returns the ID of the newly created filter.
|
||||||
func (api *PublicWhisperAPI) NewFilter(args WhisperFilterArgs) (string, error) {
|
func (api *PublicWhisperAPI) Subscribe(args WhisperFilterArgs) (string, error) {
|
||||||
if api.whisper == nil {
|
if api.whisper == nil {
|
||||||
return "", whisperOffLineErr
|
return "", whisperOffLineErr
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
|
||||||
var symKey []byte
|
|
||||||
|
|
||||||
if len(args.KeyName) > 0 {
|
|
||||||
symKey, err = api.whisper.GetSymKey(args.KeyName)
|
|
||||||
if err != nil {
|
|
||||||
info := "NewFilter: symmetric key ID does not exist: " + args.KeyName
|
|
||||||
log.Error(fmt.Sprintf(info))
|
|
||||||
return "", errors.New(info)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := Filter{
|
filter := Filter{
|
||||||
Src: crypto.ToECDSAPub(common.FromHex(args.From)),
|
Src: crypto.ToECDSAPub(common.FromHex(args.SignedWith)),
|
||||||
KeySym: symKey,
|
PoW: args.MinPoW,
|
||||||
PoW: args.PoW,
|
Messages: make(map[common.Hash]*ReceivedMessage),
|
||||||
Messages: make(map[common.Hash]*ReceivedMessage),
|
AllowP2P: args.AllowP2P,
|
||||||
AcceptP2P: args.AcceptP2P,
|
|
||||||
}
|
|
||||||
if len(filter.KeySym) > 0 {
|
|
||||||
filter.SymKeyHash = crypto.Keccak256Hash(filter.KeySym)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
filter.Topics = append(filter.Topics, args.Topics...)
|
filter.Topics = append(filter.Topics, args.Topics...)
|
||||||
|
|
||||||
if len(args.Topics) == 0 && len(args.KeyName) != 0 {
|
if len(args.SignedWith) > 0 {
|
||||||
info := "NewFilter: at least one topic must be specified"
|
if !ValidatePublicKey(filter.Src) {
|
||||||
log.Error(fmt.Sprintf(info))
|
info := "NewFilter: Invalid 'From' address"
|
||||||
return "", errors.New(info)
|
log.Error(info)
|
||||||
}
|
|
||||||
|
|
||||||
if len(args.To) == 0 && len(filter.KeySym) == 0 {
|
|
||||||
info := "NewFilter: filter must contain either symmetric or asymmetric key"
|
|
||||||
log.Error(fmt.Sprintf(info))
|
|
||||||
return "", errors.New(info)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args.To) != 0 && len(filter.KeySym) != 0 {
|
|
||||||
info := "NewFilter: filter must not contain both symmetric and asymmetric key"
|
|
||||||
log.Error(fmt.Sprintf(info))
|
|
||||||
return "", errors.New(info)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args.To) > 0 {
|
|
||||||
dst := crypto.ToECDSAPub(common.FromHex(args.To))
|
|
||||||
if !ValidatePublicKey(dst) {
|
|
||||||
info := "NewFilter: Invalid 'To' address"
|
|
||||||
log.Error(fmt.Sprintf(info))
|
|
||||||
return "", errors.New(info)
|
return "", errors.New(info)
|
||||||
}
|
}
|
||||||
filter.KeyAsym, err = api.whisper.GetIdentity(string(args.To))
|
}
|
||||||
|
|
||||||
|
err := ValidateKeyID(args.Key)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ValidatePublicKey(filter.Src) {
|
||||||
|
info := "NewFilter: 'SignedWith' public key is invalid"
|
||||||
|
log.Error(info)
|
||||||
|
return "", errors.New(info)
|
||||||
|
}
|
||||||
|
|
||||||
|
if args.Symmetric {
|
||||||
|
if len(args.Topics) == 0 {
|
||||||
|
info := "NewFilter: at least one topic must be specified with symmetric encryption"
|
||||||
|
log.Error(info)
|
||||||
|
return "", errors.New(info)
|
||||||
|
}
|
||||||
|
|
||||||
|
symKey, err := api.whisper.GetSymKey(args.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
info := "NewFilter: invalid key ID: " + args.Key
|
||||||
|
log.Error(info)
|
||||||
|
return "", errors.New(info)
|
||||||
|
}
|
||||||
|
if !validateSymmetricKey(symKey) {
|
||||||
|
info := "NewFilter: retrieved key is invalid"
|
||||||
|
log.Error(info)
|
||||||
|
return "", errors.New(info)
|
||||||
|
}
|
||||||
|
|
||||||
|
filter.KeySym = symKey
|
||||||
|
filter.SymKeyHash = crypto.Keccak256Hash(filter.KeySym)
|
||||||
|
} else {
|
||||||
|
filter.KeyAsym, err = api.whisper.GetPrivateKey(args.Key)
|
||||||
|
if err != nil {
|
||||||
|
info := "NewFilter: invalid key ID: " + args.Key
|
||||||
|
log.Error(info)
|
||||||
|
return "", errors.New(info)
|
||||||
}
|
}
|
||||||
if filter.KeyAsym == nil {
|
if filter.KeyAsym == nil {
|
||||||
info := "NewFilter: non-existent identity provided"
|
info := "NewFilter: non-existent identity provided"
|
||||||
log.Error(fmt.Sprintf(info))
|
log.Error(info)
|
||||||
return "", errors.New(info)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args.From) > 0 {
|
|
||||||
if !ValidatePublicKey(filter.Src) {
|
|
||||||
info := "NewFilter: Invalid 'From' address"
|
|
||||||
log.Error(fmt.Sprintf(info))
|
|
||||||
return "", errors.New(info)
|
return "", errors.New(info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -286,9 +281,9 @@ func (api *PublicWhisperAPI) NewFilter(args WhisperFilterArgs) (string, error) {
|
||||||
return api.whisper.Watch(&filter)
|
return api.whisper.Watch(&filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UninstallFilter disables and removes an existing filter.
|
// Unsubscribe disables and removes an existing filter.
|
||||||
func (api *PublicWhisperAPI) UninstallFilter(filterId string) {
|
func (api *PublicWhisperAPI) Unsubscribe(id string) {
|
||||||
api.whisper.Unwatch(filterId)
|
api.whisper.Unsubscribe(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFilterChanges retrieves all the new messages matched by a filter since the last retrieval.
|
// GetFilterChanges retrieves all the new messages matched by a filter since the last retrieval.
|
||||||
|
|
@ -323,144 +318,110 @@ func (api *PublicWhisperAPI) Post(args PostArgs) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
var symKey []byte
|
|
||||||
|
|
||||||
if len(args.KeyName) > 0 {
|
|
||||||
symKey, err = api.whisper.GetSymKey(args.KeyName)
|
|
||||||
if err != nil {
|
|
||||||
info := "NewFilter: symmetric key ID does not exist: " + args.KeyName
|
|
||||||
log.Error(fmt.Sprintf(info))
|
|
||||||
return errors.New(info)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
params := MessageParams{
|
params := MessageParams{
|
||||||
TTL: args.TTL,
|
TTL: args.TTL,
|
||||||
Dst: crypto.ToECDSAPub(common.FromHex(args.To)),
|
WorkTime: args.PowTime,
|
||||||
KeySym: symKey,
|
PoW: args.PowTarget,
|
||||||
Topic: args.Topic,
|
|
||||||
Payload: args.Payload,
|
Payload: args.Payload,
|
||||||
Padding: args.Padding,
|
Padding: args.Padding,
|
||||||
WorkTime: args.WorkTime,
|
|
||||||
PoW: args.PoW,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(args.From) > 0 {
|
if len(args.SignWith) > 0 {
|
||||||
pub := crypto.ToECDSAPub(common.FromHex(args.From))
|
params.Src, err = api.whisper.GetPrivateKey(args.SignWith)
|
||||||
if !ValidatePublicKey(pub) {
|
|
||||||
info := "Post: Invalid 'From' address"
|
|
||||||
log.Error(fmt.Sprintf(info))
|
|
||||||
return errors.New(info)
|
|
||||||
}
|
|
||||||
params.Src, err = api.whisper.GetIdentity(string(args.From))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Error(err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if params.Src == nil {
|
if params.Src == nil {
|
||||||
info := "Post: non-existent identity provided"
|
info := "Post: empty identity"
|
||||||
log.Error(fmt.Sprintf(info))
|
log.Error(info)
|
||||||
return errors.New(info)
|
return errors.New(info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
filter := api.whisper.GetFilter(args.FilterID)
|
if len(args.Topic) == TopicLength {
|
||||||
if filter == nil && len(args.FilterID) > 0 {
|
params.Topic = BytesToTopic(args.Topic)
|
||||||
info := fmt.Sprintf("Post: wrong filter id %s", args.FilterID)
|
} else if len(args.Topic) != 0 {
|
||||||
log.Error(fmt.Sprintf(info))
|
info := fmt.Sprintf("Post: wrong topic size %d", len(args.Topic))
|
||||||
|
log.Error(info)
|
||||||
return errors.New(info)
|
return errors.New(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
if filter != nil {
|
if args.Type == "sym" {
|
||||||
// get the missing fields from the filter
|
err = ValidateKeyID(args.Key)
|
||||||
if params.KeySym == nil && filter.KeySym != nil {
|
if err != nil {
|
||||||
params.KeySym = filter.KeySym
|
log.Error(err.Error())
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
if params.Src == nil && filter.Src != nil {
|
params.KeySym, err = api.whisper.GetSymKey(args.Key)
|
||||||
params.Src = filter.KeyAsym
|
if err != nil {
|
||||||
|
log.Error(err.Error())
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
if (params.Topic == TopicType{}) {
|
if len(params.Topic) == 0 {
|
||||||
sz := len(filter.Topics)
|
info := "Post: topic is missing for symmetric encryption"
|
||||||
if sz < 1 {
|
log.Error(info)
|
||||||
info := fmt.Sprintf("Post: no topics in filter # %s", args.FilterID)
|
return errors.New(info)
|
||||||
log.Error(fmt.Sprintf(info))
|
|
||||||
return errors.New(info)
|
|
||||||
} else if sz == 1 {
|
|
||||||
params.Topic = filter.Topics[0]
|
|
||||||
} else {
|
|
||||||
// choose randomly
|
|
||||||
rnd := mathrand.Intn(sz)
|
|
||||||
params.Topic = filter.Topics[rnd]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
} else if args.Type == "asym" {
|
||||||
|
params.Dst = crypto.ToECDSAPub(common.FromHex(args.Key))
|
||||||
// validate
|
|
||||||
if len(args.To) == 0 && len(params.KeySym) == 0 {
|
|
||||||
info := "Post: message must be encrypted either symmetrically or asymmetrically"
|
|
||||||
log.Error(fmt.Sprintf(info))
|
|
||||||
return errors.New(info)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args.To) != 0 && len(params.KeySym) != 0 {
|
|
||||||
info := "Post: ambigous encryption method requested"
|
|
||||||
log.Error(fmt.Sprintf(info))
|
|
||||||
return errors.New(info)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args.To) > 0 {
|
|
||||||
if !ValidatePublicKey(params.Dst) {
|
if !ValidatePublicKey(params.Dst) {
|
||||||
info := "Post: Invalid 'To' address"
|
info := "NewFilter: 'SignWith' public key is invalid"
|
||||||
log.Error(fmt.Sprintf(info))
|
log.Error(info)
|
||||||
return errors.New(info)
|
return errors.New(info)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
info := "Post: wrong type (sym/asym)"
|
||||||
|
log.Error(info)
|
||||||
|
return errors.New(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
// encrypt and send
|
// encrypt and send
|
||||||
message := NewSentMessage(¶ms)
|
message := NewSentMessage(¶ms)
|
||||||
envelope, err := message.Wrap(¶ms)
|
envelope, err := message.Wrap(¶ms)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(fmt.Sprintf(err.Error()))
|
log.Error(err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if envelope.size() > api.whisper.maxMsgLength {
|
if envelope.size() > api.whisper.maxMsgLength {
|
||||||
info := "Post: message is too big"
|
info := "Post: message is too big"
|
||||||
log.Error(fmt.Sprintf(info))
|
log.Error(info)
|
||||||
return errors.New(info)
|
|
||||||
}
|
|
||||||
if (envelope.Topic == TopicType{} && envelope.IsSymmetric()) {
|
|
||||||
info := "Post: topic is missing for symmetric encryption"
|
|
||||||
log.Error(fmt.Sprintf(info))
|
|
||||||
return errors.New(info)
|
return errors.New(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.PeerID != nil {
|
if len(args.TargetPeer) != 0 {
|
||||||
return api.whisper.SendP2PMessage(args.PeerID, envelope)
|
n, err := discover.ParseNode(args.TargetPeer)
|
||||||
|
if err != nil {
|
||||||
|
info := "Post: failed to parse enode of target peer: " + err.Error()
|
||||||
|
log.Error(info)
|
||||||
|
return errors.New(info)
|
||||||
|
}
|
||||||
|
return api.whisper.SendP2PMessage(n.ID[:], envelope)
|
||||||
}
|
}
|
||||||
|
|
||||||
return api.whisper.Send(envelope)
|
return api.whisper.Send(envelope)
|
||||||
}
|
}
|
||||||
|
|
||||||
type PostArgs struct {
|
type PostArgs struct {
|
||||||
TTL uint32 `json:"ttl"`
|
Type string `json:"type"`
|
||||||
From string `json:"from"`
|
TTL uint32 `json:"ttl"`
|
||||||
To string `json:"to"`
|
SignWith string `json:"signWith"`
|
||||||
KeyName string `json:"keyname"`
|
Key string `json:"key"`
|
||||||
Topic TopicType `json:"topic"`
|
Topic hexutil.Bytes `json:"topic"`
|
||||||
Padding hexutil.Bytes `json:"padding"`
|
Padding hexutil.Bytes `json:"padding"`
|
||||||
Payload hexutil.Bytes `json:"payload"`
|
Payload hexutil.Bytes `json:"payload"`
|
||||||
WorkTime uint32 `json:"worktime"`
|
PowTime uint32 `json:"powTime"`
|
||||||
PoW float64 `json:"pow"`
|
PowTarget float64 `json:"powTarget"`
|
||||||
FilterID string `json:"filterID"`
|
TargetPeer string `json:"targetPeer"`
|
||||||
PeerID hexutil.Bytes `json:"peerID"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type WhisperFilterArgs struct {
|
type WhisperFilterArgs struct {
|
||||||
To string `json:"to"`
|
Symmetric bool
|
||||||
From string `json:"from"`
|
Key string
|
||||||
KeyName string `json:"keyname"`
|
SignedWith string
|
||||||
PoW float64 `json:"pow"`
|
MinPoW float64
|
||||||
Topics []TopicType `json:"topics"`
|
Topics []TopicType
|
||||||
AcceptP2P bool `json:"p2p"`
|
AllowP2P bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements the json.Unmarshaler interface, invoked to convert a
|
// UnmarshalJSON implements the json.Unmarshaler interface, invoked to convert a
|
||||||
|
|
@ -468,22 +429,29 @@ type WhisperFilterArgs struct {
|
||||||
func (args *WhisperFilterArgs) UnmarshalJSON(b []byte) (err error) {
|
func (args *WhisperFilterArgs) UnmarshalJSON(b []byte) (err error) {
|
||||||
// Unmarshal the JSON message and sanity check
|
// Unmarshal the JSON message and sanity check
|
||||||
var obj struct {
|
var obj struct {
|
||||||
To string `json:"to"`
|
Type string `json:"type"`
|
||||||
From string `json:"from"`
|
Key string `json:"key"`
|
||||||
KeyName string `json:"keyname"`
|
SignedWith string `json:"signedWith"`
|
||||||
PoW float64 `json:"pow"`
|
MinPoW float64 `json:"minPoW"`
|
||||||
Topics []interface{} `json:"topics"`
|
Topics []interface{} `json:"topics"`
|
||||||
AcceptP2P bool `json:"p2p"`
|
AllowP2P bool `json:"allowP2P"`
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(b, &obj); err != nil {
|
if err := json.Unmarshal(b, &obj); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
args.To = obj.To
|
if obj.Type == "sym" {
|
||||||
args.From = obj.From
|
args.Symmetric = true
|
||||||
args.KeyName = obj.KeyName
|
} else if obj.Type == "asym" {
|
||||||
args.PoW = obj.PoW
|
args.Symmetric = false
|
||||||
args.AcceptP2P = obj.AcceptP2P
|
} else {
|
||||||
|
return fmt.Errorf("Wrong type (sym/asym")
|
||||||
|
}
|
||||||
|
|
||||||
|
args.Key = obj.Key
|
||||||
|
args.SignedWith = obj.SignedWith
|
||||||
|
args.MinPoW = obj.MinPoW
|
||||||
|
args.AllowP2P = obj.AllowP2P
|
||||||
|
|
||||||
// Construct the topic array
|
// Construct the topic array
|
||||||
if obj.Topics != nil {
|
if obj.Topics != nil {
|
||||||
|
|
@ -514,34 +482,34 @@ func (args *WhisperFilterArgs) UnmarshalJSON(b []byte) (err error) {
|
||||||
|
|
||||||
// WhisperMessage is the RPC representation of a whisper message.
|
// WhisperMessage is the RPC representation of a whisper message.
|
||||||
type WhisperMessage struct {
|
type WhisperMessage struct {
|
||||||
Topic string `json:"topic"`
|
Topic string `json:"topic"`
|
||||||
Payload string `json:"payload"`
|
Payload string `json:"payload"`
|
||||||
Padding string `json:"padding"`
|
Padding string `json:"padding"`
|
||||||
From string `json:"from"`
|
Src string `json:"signedWith"`
|
||||||
To string `json:"to"`
|
Dst string `json:"receipientPublicKey"`
|
||||||
Sent uint32 `json:"sent"`
|
Timestamp uint32 `json:"timestamp"`
|
||||||
TTL uint32 `json:"ttl"`
|
TTL uint32 `json:"ttl"`
|
||||||
PoW float64 `json:"pow"`
|
PoW float64 `json:"pow"`
|
||||||
Hash string `json:"hash"`
|
Hash string `json:"hash"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWhisperMessage converts an internal message into an API version.
|
// NewWhisperMessage converts an internal message into an API version.
|
||||||
func NewWhisperMessage(message *ReceivedMessage) *WhisperMessage {
|
func NewWhisperMessage(message *ReceivedMessage) *WhisperMessage {
|
||||||
msg := WhisperMessage{
|
msg := WhisperMessage{
|
||||||
Topic: common.ToHex(message.Topic[:]),
|
Topic: common.ToHex(message.Topic[:]),
|
||||||
Payload: common.ToHex(message.Payload),
|
Payload: common.ToHex(message.Payload),
|
||||||
Padding: common.ToHex(message.Padding),
|
Padding: common.ToHex(message.Padding),
|
||||||
Sent: message.Sent,
|
Timestamp: message.Sent,
|
||||||
TTL: message.TTL,
|
TTL: message.TTL,
|
||||||
PoW: message.PoW,
|
PoW: message.PoW,
|
||||||
Hash: common.ToHex(message.EnvelopeHash.Bytes()),
|
Hash: common.ToHex(message.EnvelopeHash.Bytes()),
|
||||||
}
|
}
|
||||||
|
|
||||||
if message.Dst != nil {
|
if message.Dst != nil {
|
||||||
msg.To = common.ToHex(crypto.FromECDSAPub(message.Dst))
|
msg.Dst = common.ToHex(crypto.FromECDSAPub(message.Dst))
|
||||||
}
|
}
|
||||||
if isMessageSigned(message.Raw[0]) {
|
if isMessageSigned(message.Raw[0]) {
|
||||||
msg.From = common.ToHex(crypto.FromECDSAPub(message.SigToPubKey()))
|
msg.Src = common.ToHex(crypto.FromECDSAPub(message.SigToPubKey()))
|
||||||
}
|
}
|
||||||
return &msg
|
return &msg
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBasic(t *testing.T) {
|
func TestBasic(t *testing.T) {
|
||||||
|
|
@ -47,7 +48,7 @@ func TestBasic(t *testing.T) {
|
||||||
t.Fatalf("failed GetFilterChanges: premature result")
|
t.Fatalf("failed GetFilterChanges: premature result")
|
||||||
}
|
}
|
||||||
|
|
||||||
exist, err := api.HasIdentity(id)
|
exist, err := api.HasKeyPair(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed initial HasIdentity: %s.", err)
|
t.Fatalf("failed initial HasIdentity: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
@ -55,7 +56,7 @@ func TestBasic(t *testing.T) {
|
||||||
t.Fatalf("failed initial HasIdentity: false positive.")
|
t.Fatalf("failed initial HasIdentity: false positive.")
|
||||||
}
|
}
|
||||||
|
|
||||||
success, err := api.DeleteIdentity(id)
|
success, err := api.DeleteKeyPair(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed DeleteIdentity: %s.", err)
|
t.Fatalf("failed DeleteIdentity: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
@ -63,7 +64,7 @@ func TestBasic(t *testing.T) {
|
||||||
t.Fatalf("deleted non-existing identity: false positive.")
|
t.Fatalf("deleted non-existing identity: false positive.")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub, err := api.NewIdentity()
|
pub, err := api.NewKeyPair()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed NewIdentity: %s.", err)
|
t.Fatalf("failed NewIdentity: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
@ -71,7 +72,7 @@ func TestBasic(t *testing.T) {
|
||||||
t.Fatalf("failed NewIdentity: empty")
|
t.Fatalf("failed NewIdentity: empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
exist, err = api.HasIdentity(pub)
|
exist, err = api.HasKeyPair(pub)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed HasIdentity: %s.", err)
|
t.Fatalf("failed HasIdentity: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
@ -79,7 +80,7 @@ func TestBasic(t *testing.T) {
|
||||||
t.Fatalf("failed HasIdentity: false negative.")
|
t.Fatalf("failed HasIdentity: false negative.")
|
||||||
}
|
}
|
||||||
|
|
||||||
success, err = api.DeleteIdentity(pub)
|
success, err = api.DeleteKeyPair(pub)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to delete second identity: %s.", err)
|
t.Fatalf("failed to delete second identity: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
@ -87,7 +88,7 @@ func TestBasic(t *testing.T) {
|
||||||
t.Fatalf("failed to delete second identity.")
|
t.Fatalf("failed to delete second identity.")
|
||||||
}
|
}
|
||||||
|
|
||||||
exist, err = api.HasIdentity(pub)
|
exist, err = api.HasKeyPair(pub)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed HasIdentity(): %s.", err)
|
t.Fatalf("failed HasIdentity(): %s.", err)
|
||||||
}
|
}
|
||||||
|
|
@ -98,7 +99,7 @@ func TestBasic(t *testing.T) {
|
||||||
id = "arbitrary text"
|
id = "arbitrary text"
|
||||||
id2 := "another arbitrary string"
|
id2 := "another arbitrary string"
|
||||||
|
|
||||||
exist, err = api.HasSymKey(id)
|
exist, err = api.HasSymmetricKey(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed HasSymKey: %s.", err)
|
t.Fatalf("failed HasSymKey: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
@ -106,12 +107,12 @@ func TestBasic(t *testing.T) {
|
||||||
t.Fatalf("failed HasSymKey: false positive.")
|
t.Fatalf("failed HasSymKey: false positive.")
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err = api.GenerateSymKey()
|
id, err = api.GenerateSymmetricKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed GenerateSymKey: %s.", err)
|
t.Fatalf("failed GenerateSymKey: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
exist, err = api.HasSymKey(id)
|
exist, err = api.HasSymmetricKey(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed HasSymKey(): %s.", err)
|
t.Fatalf("failed HasSymKey(): %s.", err)
|
||||||
}
|
}
|
||||||
|
|
@ -120,17 +121,17 @@ func TestBasic(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const password = "some stuff here"
|
const password = "some stuff here"
|
||||||
id, err = api.AddSymKeyFromPassword(password)
|
id, err = api.AddSymmetricKeyFromPassword(password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed AddSymKey: %s.", err)
|
t.Fatalf("failed AddSymKey: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
id2, err = api.AddSymKeyFromPassword(password)
|
id2, err = api.AddSymmetricKeyFromPassword(password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed AddSymKey: %s.", err)
|
t.Fatalf("failed AddSymKey: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
exist, err = api.HasSymKey(id2)
|
exist, err = api.HasSymmetricKey(id2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed HasSymKey(id2): %s.", err)
|
t.Fatalf("failed HasSymKey(id2): %s.", err)
|
||||||
}
|
}
|
||||||
|
|
@ -138,11 +139,11 @@ func TestBasic(t *testing.T) {
|
||||||
t.Fatalf("failed HasSymKey(id2): false negative.")
|
t.Fatalf("failed HasSymKey(id2): false negative.")
|
||||||
}
|
}
|
||||||
|
|
||||||
k1, err := api.GetSymKey(id)
|
k1, err := api.GetSymmetricKey(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed GetSymKey(id): %s.", err)
|
t.Fatalf("failed GetSymKey(id): %s.", err)
|
||||||
}
|
}
|
||||||
k2, err := api.GetSymKey(id2)
|
k2, err := api.GetSymmetricKey(id2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed GetSymKey(id2): %s.", err)
|
t.Fatalf("failed GetSymKey(id2): %s.", err)
|
||||||
}
|
}
|
||||||
|
|
@ -151,7 +152,7 @@ func TestBasic(t *testing.T) {
|
||||||
t.Fatalf("installed keys are not equal")
|
t.Fatalf("installed keys are not equal")
|
||||||
}
|
}
|
||||||
|
|
||||||
exist, err = api.DeleteSymKey(id)
|
exist, err = api.DeleteSymmetricKey(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed DeleteSymKey(id): %s.", err)
|
t.Fatalf("failed DeleteSymKey(id): %s.", err)
|
||||||
}
|
}
|
||||||
|
|
@ -159,7 +160,7 @@ func TestBasic(t *testing.T) {
|
||||||
t.Fatalf("failed DeleteSymKey(id): false negative.")
|
t.Fatalf("failed DeleteSymKey(id): false negative.")
|
||||||
}
|
}
|
||||||
|
|
||||||
exist, err = api.HasSymKey(id)
|
exist, err = api.HasSymmetricKey(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed HasSymKey(id): %s.", err)
|
t.Fatalf("failed HasSymKey(id): %s.", err)
|
||||||
}
|
}
|
||||||
|
|
@ -170,12 +171,12 @@ func TestBasic(t *testing.T) {
|
||||||
|
|
||||||
func TestUnmarshalFilterArgs(t *testing.T) {
|
func TestUnmarshalFilterArgs(t *testing.T) {
|
||||||
s := []byte(`{
|
s := []byte(`{
|
||||||
"to":"0x70c87d191324e6712a591f304b4eedef6ad9bb9d",
|
"type":"asym",
|
||||||
"from":"0x9b2055d370f73ec7d8a03e965129118dc8f5bf83",
|
"key":"0x70c87d191324e6712a591f304b4eedef6ad9bb9d",
|
||||||
"keyname":"testname",
|
"signedWith":"0x9b2055d370f73ec7d8a03e965129118dc8f5bf83",
|
||||||
"pow":2.34,
|
"minPoW":2.34,
|
||||||
"topics":["0x00000000", "0x007f80ff", "0xff807f00", "0xf26e7779"],
|
"topics":["0x00000000", "0x007f80ff", "0xff807f00", "0xf26e7779"],
|
||||||
"p2p":true
|
"allowP2P":true
|
||||||
}`)
|
}`)
|
||||||
|
|
||||||
var f WhisperFilterArgs
|
var f WhisperFilterArgs
|
||||||
|
|
@ -184,20 +185,20 @@ func TestUnmarshalFilterArgs(t *testing.T) {
|
||||||
t.Fatalf("failed UnmarshalJSON: %s.", err)
|
t.Fatalf("failed UnmarshalJSON: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.To != "0x70c87d191324e6712a591f304b4eedef6ad9bb9d" {
|
if f.Symmetric {
|
||||||
t.Fatalf("wrong To: %x.", f.To)
|
t.Fatalf("wrong type.")
|
||||||
}
|
}
|
||||||
if f.From != "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83" {
|
if f.Key != "0x70c87d191324e6712a591f304b4eedef6ad9bb9d" {
|
||||||
t.Fatalf("wrong From: %x.", f.To)
|
t.Fatalf("wrong key: %s.", f.Key)
|
||||||
}
|
}
|
||||||
if f.KeyName != "testname" {
|
if f.SignedWith != "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83" {
|
||||||
t.Fatalf("wrong KeyName: %s.", f.KeyName)
|
t.Fatalf("wrong SignedWith: %s.", f.SignedWith)
|
||||||
}
|
}
|
||||||
if f.PoW != 2.34 {
|
if f.MinPoW != 2.34 {
|
||||||
t.Fatalf("wrong pow: %f.", f.PoW)
|
t.Fatalf("wrong MinPoW: %f.", f.MinPoW)
|
||||||
}
|
}
|
||||||
if !f.AcceptP2P {
|
if !f.AllowP2P {
|
||||||
t.Fatalf("wrong AcceptP2P: %v.", f.AcceptP2P)
|
t.Fatalf("wrong AllowP2P.")
|
||||||
}
|
}
|
||||||
if len(f.Topics) != 4 {
|
if len(f.Topics) != 4 {
|
||||||
t.Fatalf("wrong topics number: %d.", len(f.Topics))
|
t.Fatalf("wrong topics number: %d.", len(f.Topics))
|
||||||
|
|
@ -226,17 +227,16 @@ func TestUnmarshalFilterArgs(t *testing.T) {
|
||||||
|
|
||||||
func TestUnmarshalPostArgs(t *testing.T) {
|
func TestUnmarshalPostArgs(t *testing.T) {
|
||||||
s := []byte(`{
|
s := []byte(`{
|
||||||
|
"type":"sym",
|
||||||
"ttl":12345,
|
"ttl":12345,
|
||||||
"from":"0x70c87d191324e6712a591f304b4eedef6ad9bb9d",
|
"signWith":"0x70c87d191324e6712a591f304b4eedef6ad9bb9d",
|
||||||
"to":"0x9b2055d370f73ec7d8a03e965129118dc8f5bf83",
|
"key":"0x9b2055d370f73ec7d8a03e965129118dc8f5bf83",
|
||||||
"keyname":"shh_test",
|
|
||||||
"topic":"0xf26e7779",
|
"topic":"0xf26e7779",
|
||||||
"padding":"0x74686973206973206D79207465737420737472696E67",
|
"padding":"0x74686973206973206D79207465737420737472696E67",
|
||||||
"payload":"0x7061796C6F61642073686F756C642062652070736575646F72616E646F6D",
|
"payload":"0x7061796C6F61642073686F756C642062652070736575646F72616E646F6D",
|
||||||
"worktime":777,
|
"powTime":777,
|
||||||
"pow":3.1416,
|
"powTarget":3.1416,
|
||||||
"filterid":"test-filter-id",
|
"targetPeer":"enode://915533f667b1369793ebb9bda022416b1295235a1420799cd87a969467372546d808ebf59c5c9ce23f103d59b61b97df8af91f0908552485975397181b993461@127.0.0.1:12345"
|
||||||
"peerid":"0xf26e7779"
|
|
||||||
}`)
|
}`)
|
||||||
|
|
||||||
var a PostArgs
|
var a PostArgs
|
||||||
|
|
@ -245,19 +245,20 @@ func TestUnmarshalPostArgs(t *testing.T) {
|
||||||
t.Fatalf("failed UnmarshalJSON: %s.", err)
|
t.Fatalf("failed UnmarshalJSON: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if a.Type != "sym" {
|
||||||
|
t.Fatalf("wrong Type: %s.", a.Type)
|
||||||
|
}
|
||||||
if a.TTL != 12345 {
|
if a.TTL != 12345 {
|
||||||
t.Fatalf("wrong ttl: %d.", a.TTL)
|
t.Fatalf("wrong ttl: %d.", a.TTL)
|
||||||
}
|
}
|
||||||
if a.From != "0x70c87d191324e6712a591f304b4eedef6ad9bb9d" {
|
if a.SignWith != "0x70c87d191324e6712a591f304b4eedef6ad9bb9d" {
|
||||||
t.Fatalf("wrong From: %x.", a.To)
|
t.Fatalf("wrong From: %s.", a.SignWith)
|
||||||
}
|
}
|
||||||
if a.To != "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83" {
|
if a.Key != "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83" {
|
||||||
t.Fatalf("wrong To: %x.", a.To)
|
t.Fatalf("wrong Key: %s.", a.Key)
|
||||||
}
|
}
|
||||||
if a.KeyName != "shh_test" {
|
|
||||||
t.Fatalf("wrong KeyName: %s.", a.KeyName)
|
if BytesToTopic(a.Topic) != (TopicType{0xf2, 0x6e, 0x77, 0x79}) {
|
||||||
}
|
|
||||||
if a.Topic != (TopicType{0xf2, 0x6e, 0x77, 0x79}) {
|
|
||||||
t.Fatalf("wrong topic: %x.", a.Topic)
|
t.Fatalf("wrong topic: %x.", a.Topic)
|
||||||
}
|
}
|
||||||
if string(a.Padding) != "this is my test string" {
|
if string(a.Padding) != "this is my test string" {
|
||||||
|
|
@ -266,17 +267,14 @@ func TestUnmarshalPostArgs(t *testing.T) {
|
||||||
if string(a.Payload) != "payload should be pseudorandom" {
|
if string(a.Payload) != "payload should be pseudorandom" {
|
||||||
t.Fatalf("wrong Payload: %s.", string(a.Payload))
|
t.Fatalf("wrong Payload: %s.", string(a.Payload))
|
||||||
}
|
}
|
||||||
if a.WorkTime != 777 {
|
if a.PowTime != 777 {
|
||||||
t.Fatalf("wrong WorkTime: %d.", a.WorkTime)
|
t.Fatalf("wrong PowTime: %d.", a.PowTime)
|
||||||
}
|
}
|
||||||
if a.PoW != 3.1416 {
|
if a.PowTarget != 3.1416 {
|
||||||
t.Fatalf("wrong pow: %f.", a.PoW)
|
t.Fatalf("wrong PowTarget: %f.", a.PowTarget)
|
||||||
}
|
}
|
||||||
if a.FilterID != "test-filter-id" {
|
if a.TargetPeer != "enode://915533f667b1369793ebb9bda022416b1295235a1420799cd87a969467372546d808ebf59c5c9ce23f103d59b61b97df8af91f0908552485975397181b993461@127.0.0.1:12345" {
|
||||||
t.Fatalf("wrong FilterID: %s.", a.FilterID)
|
t.Fatalf("wrong PeerID: %s.", a.TargetPeer)
|
||||||
}
|
|
||||||
if !bytes.Equal(a.PeerID[:], a.Topic[:]) {
|
|
||||||
t.Fatalf("wrong PeerID: %x.", a.PeerID)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -309,7 +307,7 @@ func TestIntegrationAsym(t *testing.T) {
|
||||||
api.Start()
|
api.Start()
|
||||||
defer api.Stop()
|
defer api.Stop()
|
||||||
|
|
||||||
sig, err := api.NewIdentity()
|
sig, err := api.NewKeyPair()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed NewIdentity: %s.", err)
|
t.Fatalf("failed NewIdentity: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
@ -317,7 +315,7 @@ func TestIntegrationAsym(t *testing.T) {
|
||||||
t.Fatalf("wrong signature")
|
t.Fatalf("wrong signature")
|
||||||
}
|
}
|
||||||
|
|
||||||
exist, err := api.HasIdentity(sig)
|
exist, err := api.HasKeyPair(sig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed HasIdentity: %s.", err)
|
t.Fatalf("failed HasIdentity: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
@ -325,7 +323,7 @@ func TestIntegrationAsym(t *testing.T) {
|
||||||
t.Fatalf("failed HasIdentity: false negative.")
|
t.Fatalf("failed HasIdentity: false negative.")
|
||||||
}
|
}
|
||||||
|
|
||||||
key, err := api.NewIdentity()
|
key, err := api.NewKeyPair()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed NewIdentity(): %s.", err)
|
t.Fatalf("failed NewIdentity(): %s.", err)
|
||||||
}
|
}
|
||||||
|
|
@ -337,26 +335,27 @@ func TestIntegrationAsym(t *testing.T) {
|
||||||
topics[0] = TopicType{0x00, 0x64, 0x00, 0xff}
|
topics[0] = TopicType{0x00, 0x64, 0x00, 0xff}
|
||||||
topics[1] = TopicType{0xf2, 0x6e, 0x77, 0x79}
|
topics[1] = TopicType{0xf2, 0x6e, 0x77, 0x79}
|
||||||
var f WhisperFilterArgs
|
var f WhisperFilterArgs
|
||||||
f.To = key
|
f.Symmetric = false
|
||||||
f.From = sig
|
f.Key = key
|
||||||
|
f.SignedWith = sig
|
||||||
f.Topics = topics[:]
|
f.Topics = topics[:]
|
||||||
f.PoW = DefaultMinimumPoW / 2
|
f.MinPoW = DefaultMinimumPoW / 2
|
||||||
f.AcceptP2P = true
|
f.AllowP2P = true
|
||||||
|
|
||||||
id, err := api.NewFilter(f)
|
id, err := api.Subscribe(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create new filter: %s.", err)
|
t.Fatalf("failed to create new filter: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var p PostArgs
|
var p PostArgs
|
||||||
p.TTL = 2
|
p.TTL = 2
|
||||||
p.From = f.From
|
p.SignWith = f.SignedWith
|
||||||
p.To = f.To
|
p.Key = f.Key
|
||||||
p.Padding = []byte("test string")
|
p.Padding = []byte("test string")
|
||||||
p.Payload = []byte("extended test string")
|
p.Payload = []byte("extended test string")
|
||||||
p.PoW = DefaultMinimumPoW
|
p.PowTarget = DefaultMinimumPoW
|
||||||
p.Topic = TopicType{0xf2, 0x6e, 0x77, 0x79}
|
p.PowTime = 2
|
||||||
p.WorkTime = 2
|
p.Topic = hexutil.Bytes{0xf2, 0x6e, 0x77, 0x79} // topics[1]
|
||||||
|
|
||||||
err = api.Post(p)
|
err = api.Post(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -401,12 +400,12 @@ func TestIntegrationSym(t *testing.T) {
|
||||||
api.Start()
|
api.Start()
|
||||||
defer api.Stop()
|
defer api.Stop()
|
||||||
|
|
||||||
keyID, err := api.GenerateSymKey()
|
symKeyID, err := api.GenerateSymmetricKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed GenerateSymKey: %s.", err)
|
t.Fatalf("failed GenerateSymKey: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
sig, err := api.NewIdentity()
|
sig, err := api.NewKeyPair()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed NewIdentity: %s.", err)
|
t.Fatalf("failed NewIdentity: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
@ -414,7 +413,7 @@ func TestIntegrationSym(t *testing.T) {
|
||||||
t.Fatalf("wrong signature")
|
t.Fatalf("wrong signature")
|
||||||
}
|
}
|
||||||
|
|
||||||
exist, err := api.HasIdentity(sig)
|
exist, err := api.HasKeyPair(sig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed HasIdentity: %s.", err)
|
t.Fatalf("failed HasIdentity: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
@ -426,26 +425,28 @@ func TestIntegrationSym(t *testing.T) {
|
||||||
topics[0] = TopicType{0x00, 0x7f, 0x80, 0xff}
|
topics[0] = TopicType{0x00, 0x7f, 0x80, 0xff}
|
||||||
topics[1] = TopicType{0xf2, 0x6e, 0x77, 0x79}
|
topics[1] = TopicType{0xf2, 0x6e, 0x77, 0x79}
|
||||||
var f WhisperFilterArgs
|
var f WhisperFilterArgs
|
||||||
f.KeyName = keyID
|
f.Symmetric = true
|
||||||
|
f.Key = symKeyID
|
||||||
f.Topics = topics[:]
|
f.Topics = topics[:]
|
||||||
f.PoW = 0.324
|
f.MinPoW = 0.324
|
||||||
f.From = sig
|
f.SignedWith = sig
|
||||||
f.AcceptP2P = false
|
f.AllowP2P = false
|
||||||
|
|
||||||
id, err := api.NewFilter(f)
|
id, err := api.Subscribe(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create new filter: %s.", err)
|
t.Fatalf("failed to create new filter: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var p PostArgs
|
var p PostArgs
|
||||||
|
p.Type = "sym"
|
||||||
p.TTL = 1
|
p.TTL = 1
|
||||||
p.KeyName = keyID
|
p.Key = symKeyID
|
||||||
p.From = f.From
|
p.SignWith = f.SignedWith
|
||||||
p.Padding = []byte("test string")
|
p.Padding = []byte("test string")
|
||||||
p.Payload = []byte("extended test string")
|
p.Payload = []byte("extended test string")
|
||||||
p.PoW = DefaultMinimumPoW
|
p.PowTarget = DefaultMinimumPoW
|
||||||
p.Topic = TopicType{0xf2, 0x6e, 0x77, 0x79}
|
p.PowTime = 2
|
||||||
p.WorkTime = 2
|
p.Topic = hexutil.Bytes{0xf2, 0x6e, 0x77, 0x79}
|
||||||
|
|
||||||
err = api.Post(p)
|
err = api.Post(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -490,20 +491,20 @@ func TestIntegrationSymWithFilter(t *testing.T) {
|
||||||
api.Start()
|
api.Start()
|
||||||
defer api.Stop()
|
defer api.Stop()
|
||||||
|
|
||||||
keyID, err := api.GenerateSymKey()
|
symKeyID, err := api.GenerateSymmetricKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to GenerateSymKey: %s.", err)
|
t.Fatalf("failed to GenerateSymKey: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
sig, err := api.NewIdentity()
|
sigKeyID, err := api.NewKeyPair()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed NewIdentity: %s.", err)
|
t.Fatalf("failed NewIdentity: %s.", err)
|
||||||
}
|
}
|
||||||
if len(sig) == 0 {
|
if len(sigKeyID) == 0 {
|
||||||
t.Fatalf("wrong signature.")
|
t.Fatalf("wrong signature.")
|
||||||
}
|
}
|
||||||
|
|
||||||
exist, err := api.HasIdentity(sig)
|
exist, err := api.HasKeyPair(sigKeyID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed HasIdentity: %s.", err)
|
t.Fatalf("failed HasIdentity: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
@ -511,30 +512,36 @@ func TestIntegrationSymWithFilter(t *testing.T) {
|
||||||
t.Fatalf("failed HasIdentity: does not exist.")
|
t.Fatalf("failed HasIdentity: does not exist.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sigPubKey, err := api.GetPublicKey(sigKeyID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed GetPublicKey: %s.", err)
|
||||||
|
}
|
||||||
|
|
||||||
var topics [2]TopicType
|
var topics [2]TopicType
|
||||||
topics[0] = TopicType{0x00, 0x7f, 0x80, 0xff}
|
topics[0] = TopicType{0x00, 0x7f, 0x80, 0xff}
|
||||||
topics[1] = TopicType{0xf2, 0x6e, 0x77, 0x79}
|
topics[1] = TopicType{0xf2, 0x6e, 0x77, 0x79}
|
||||||
var f WhisperFilterArgs
|
var f WhisperFilterArgs
|
||||||
f.KeyName = keyID
|
f.Symmetric = true
|
||||||
|
f.Key = symKeyID
|
||||||
f.Topics = topics[:]
|
f.Topics = topics[:]
|
||||||
f.PoW = 0.324
|
f.MinPoW = 0.324
|
||||||
f.From = sig
|
f.SignedWith = sigPubKey
|
||||||
f.AcceptP2P = false
|
f.AllowP2P = false
|
||||||
|
|
||||||
id, err := api.NewFilter(f)
|
id, err := api.Subscribe(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create new filter: %s.", err)
|
t.Fatalf("failed to create new filter: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var p PostArgs
|
var p PostArgs
|
||||||
|
p.Type = "sym"
|
||||||
p.TTL = 1
|
p.TTL = 1
|
||||||
p.FilterID = id
|
p.SignWith = sigKeyID
|
||||||
p.From = sig
|
|
||||||
p.Padding = []byte("test string")
|
p.Padding = []byte("test string")
|
||||||
p.Payload = []byte("extended test string")
|
p.Payload = []byte("extended test string")
|
||||||
p.PoW = DefaultMinimumPoW
|
p.PowTarget = DefaultMinimumPoW
|
||||||
p.Topic = TopicType{0xf2, 0x6e, 0x77, 0x79}
|
p.PowTime = 2
|
||||||
p.WorkTime = 2
|
p.Topic = hexutil.Bytes{0xf2, 0x6e, 0x77, 0x79}
|
||||||
|
|
||||||
err = api.Post(p)
|
err = api.Post(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,11 @@ type Filter struct {
|
||||||
KeySym []byte // Key associated with the Topic
|
KeySym []byte // Key associated with the Topic
|
||||||
Topics []TopicType // Topics to filter messages with
|
Topics []TopicType // Topics to filter messages with
|
||||||
PoW float64 // Proof of work as described in the Whisper spec
|
PoW float64 // Proof of work as described in the Whisper spec
|
||||||
AcceptP2P bool // Indicates whether this filter is interested in direct peer-to-peer messages
|
AllowP2P bool // Indicates whether this filter is interested in direct peer-to-peer messages
|
||||||
SymKeyHash common.Hash // The Keccak256Hash of the symmetric key, needed for optimization
|
SymKeyHash common.Hash // The Keccak256Hash of the symmetric key, needed for optimization
|
||||||
|
|
||||||
Messages map[common.Hash]*ReceivedMessage
|
Messages map[common.Hash]*ReceivedMessage
|
||||||
mutex sync.RWMutex
|
mutex sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
type Filters struct {
|
type Filters struct {
|
||||||
|
|
@ -72,10 +72,14 @@ func (fs *Filters) Install(watcher *Filter) (string, error) {
|
||||||
return id, err
|
return id, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs *Filters) Uninstall(id string) {
|
func (fs *Filters) Uninstall(id string) bool {
|
||||||
fs.mutex.Lock()
|
fs.mutex.Lock()
|
||||||
defer fs.mutex.Unlock()
|
defer fs.mutex.Unlock()
|
||||||
delete(fs.watchers, id)
|
if fs.watchers[id] != nil {
|
||||||
|
delete(fs.watchers, id)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs *Filters) Get(id string) *Filter {
|
func (fs *Filters) Get(id string) *Filter {
|
||||||
|
|
@ -93,7 +97,7 @@ func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) {
|
||||||
|
|
||||||
for _, watcher := range fs.watchers {
|
for _, watcher := range fs.watchers {
|
||||||
j++
|
j++
|
||||||
if p2pMessage && !watcher.AcceptP2P {
|
if p2pMessage && !watcher.AllowP2P {
|
||||||
log.Trace(fmt.Sprintf("msg [%x], filter [%d]: p2p messages are not allowed", env.Hash(), j))
|
log.Trace(fmt.Sprintf("msg [%x], filter [%d]: p2p messages are not allowed", env.Hash(), j))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -491,7 +491,7 @@ func cloneFilter(orig *Filter) *Filter {
|
||||||
clone.KeySym = orig.KeySym
|
clone.KeySym = orig.KeySym
|
||||||
clone.Topics = orig.Topics
|
clone.Topics = orig.Topics
|
||||||
clone.PoW = orig.PoW
|
clone.PoW = orig.PoW
|
||||||
clone.AcceptP2P = orig.AcceptP2P
|
clone.AllowP2P = orig.AllowP2P
|
||||||
clone.SymKeyHash = orig.SymKeyHash
|
clone.SymKeyHash = orig.SymKeyHash
|
||||||
return &clone
|
return &clone
|
||||||
}
|
}
|
||||||
|
|
@ -655,7 +655,7 @@ func TestWatchers(t *testing.T) {
|
||||||
if f == nil {
|
if f == nil {
|
||||||
t.Fatalf("failed to get the filter with seed %d.", seed)
|
t.Fatalf("failed to get the filter with seed %d.", seed)
|
||||||
}
|
}
|
||||||
f.AcceptP2P = true
|
f.AllowP2P = true
|
||||||
total = 0
|
total = 0
|
||||||
filters.NotifyWatchers(envelopes[0], true)
|
filters.NotifyWatchers(envelopes[0], true)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -264,7 +264,7 @@ func (msg *ReceivedMessage) decryptSymmetric(key []byte, salt []byte, nonce []by
|
||||||
}
|
}
|
||||||
if len(nonce) != aesgcm.NonceSize() {
|
if len(nonce) != aesgcm.NonceSize() {
|
||||||
info := fmt.Sprintf("Wrong AES nonce size - want: %d, got: %d", len(nonce), aesgcm.NonceSize())
|
info := fmt.Sprintf("Wrong AES nonce size - want: %d, got: %d", len(nonce), aesgcm.NonceSize())
|
||||||
log.Error(fmt.Sprintf(info))
|
log.Error(info)
|
||||||
return errors.New(info)
|
return errors.New(info)
|
||||||
}
|
}
|
||||||
decrypted, err := aesgcm.Open(nil, nonce, msg.Raw, nil)
|
decrypted, err := aesgcm.Open(nil, nonce, msg.Raw, nil)
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,7 @@ func stopServers() {
|
||||||
for i := 0; i < NumNodes; i++ {
|
for i := 0; i < NumNodes; i++ {
|
||||||
n := nodes[i]
|
n := nodes[i]
|
||||||
if n != nil {
|
if n != nil {
|
||||||
n.shh.Unwatch(n.filerId)
|
n.shh.Unsubscribe(n.filerId)
|
||||||
n.shh.Stop()
|
n.shh.Stop()
|
||||||
n.server.Stop()
|
n.server.Stop()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Statistics struct {
|
type Statistics struct {
|
||||||
messagesCleared int
|
messagesCleared int
|
||||||
memoryCleared int
|
memoryCleared int
|
||||||
totalMemoryUsed int
|
memoryUsed int
|
||||||
|
cycles int
|
||||||
|
totalMessagesCleared int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Whisper represents a dark communication interface through the Ethereum
|
// Whisper represents a dark communication interface through the Ethereum
|
||||||
|
|
@ -189,7 +191,7 @@ func (w *Whisper) SendP2PDirect(peer *Peer, envelope *Envelope) error {
|
||||||
|
|
||||||
// NewIdentity generates a new cryptographic identity for the client, and injects
|
// NewIdentity generates a new cryptographic identity for the client, and injects
|
||||||
// it into the known identities for message decryption. Returns ID of the new key pair.
|
// it into the known identities for message decryption. Returns ID of the new key pair.
|
||||||
func (w *Whisper) NewIdentity() (string, error) {
|
func (w *Whisper) NewKeyPair() (string, error) {
|
||||||
key, err := crypto.GenerateKey()
|
key, err := crypto.GenerateKey()
|
||||||
if err != nil || !validatePrivateKey(key) {
|
if err != nil || !validatePrivateKey(key) {
|
||||||
key, err = crypto.GenerateKey() // retry once
|
key, err = crypto.GenerateKey() // retry once
|
||||||
|
|
@ -217,7 +219,7 @@ func (w *Whisper) NewIdentity() (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteIdentity deletes the specified key if it exists.
|
// DeleteIdentity deletes the specified key if it exists.
|
||||||
func (w *Whisper) DeleteIdentity(key string) bool {
|
func (w *Whisper) DeleteKeyPair(key string) bool {
|
||||||
w.keyMu.Lock()
|
w.keyMu.Lock()
|
||||||
defer w.keyMu.Unlock()
|
defer w.keyMu.Unlock()
|
||||||
|
|
||||||
|
|
@ -230,14 +232,14 @@ func (w *Whisper) DeleteIdentity(key string) bool {
|
||||||
|
|
||||||
// HasIdentity checks if the the whisper node is configured with the private key
|
// HasIdentity checks if the the whisper node is configured with the private key
|
||||||
// of the specified public pair.
|
// of the specified public pair.
|
||||||
func (w *Whisper) HasIdentity(id string) bool {
|
func (w *Whisper) HasKeyPair(id string) bool {
|
||||||
w.keyMu.RLock()
|
w.keyMu.RLock()
|
||||||
defer w.keyMu.RUnlock()
|
defer w.keyMu.RUnlock()
|
||||||
return w.privateKeys[id] != nil
|
return w.privateKeys[id] != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetIdentity retrieves the private key of the specified public identity.
|
// GetIdentity retrieves the private key of the specified public identity.
|
||||||
func (w *Whisper) GetIdentity(pubKey string) (*ecdsa.PrivateKey, error) {
|
func (w *Whisper) GetPrivateKey(pubKey string) (*ecdsa.PrivateKey, error) {
|
||||||
w.keyMu.RLock()
|
w.keyMu.RLock()
|
||||||
defer w.keyMu.RUnlock()
|
defer w.keyMu.RUnlock()
|
||||||
key := w.privateKeys[pubKey]
|
key := w.privateKeys[pubKey]
|
||||||
|
|
@ -361,9 +363,13 @@ func (w *Whisper) GetFilter(id string) *Filter {
|
||||||
return w.filters.Get(id)
|
return w.filters.Get(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unwatch removes an installed message handler.
|
// Unsubscribe removes an installed message handler.
|
||||||
func (w *Whisper) Unwatch(id string) {
|
func (w *Whisper) Unsubscribe(id string) error {
|
||||||
w.filters.Uninstall(id)
|
ok := w.filters.Uninstall(id)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Invalid ID")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send injects a message into the whisper send queue, to be distributed in the
|
// Send injects a message into the whisper send queue, to be distributed in the
|
||||||
|
|
@ -557,7 +563,7 @@ func (wh *Whisper) add(envelope *Envelope) (bool, error) {
|
||||||
log.Trace(fmt.Sprintf("whisper envelope already cached [%x]\n", envelope.Hash()))
|
log.Trace(fmt.Sprintf("whisper envelope already cached [%x]\n", envelope.Hash()))
|
||||||
} else {
|
} else {
|
||||||
log.Trace(fmt.Sprintf("cached whisper envelope [%x]: %v\n", envelope.Hash(), envelope))
|
log.Trace(fmt.Sprintf("cached whisper envelope [%x]: %v\n", envelope.Hash(), envelope))
|
||||||
wh.stats.totalMemoryUsed += envelope.size()
|
wh.stats.memoryUsed += envelope.size()
|
||||||
wh.postEvent(envelope, false) // notify the local node about the new message
|
wh.postEvent(envelope, false) // notify the local node about the new message
|
||||||
if wh.mailServer != nil {
|
if wh.mailServer != nil {
|
||||||
wh.mailServer.Archive(envelope)
|
wh.mailServer.Archive(envelope)
|
||||||
|
|
@ -649,7 +655,7 @@ func (w *Whisper) expire() {
|
||||||
hashSet.Each(func(v interface{}) bool {
|
hashSet.Each(func(v interface{}) bool {
|
||||||
sz := w.envelopes[v.(common.Hash)].size()
|
sz := w.envelopes[v.(common.Hash)].size()
|
||||||
w.stats.memoryCleared += sz
|
w.stats.memoryCleared += sz
|
||||||
w.stats.totalMemoryUsed -= sz
|
w.stats.memoryUsed -= sz
|
||||||
delete(w.envelopes, v.(common.Hash))
|
delete(w.envelopes, v.(common.Hash))
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
@ -660,8 +666,13 @@ func (w *Whisper) expire() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Whisper) Stats() string {
|
func (w *Whisper) Stats() string {
|
||||||
return fmt.Sprintf("Latest expiry cycle cleared %d messages (%d bytes). Memory usage: %d bytes.",
|
result := fmt.Sprintf("Memory usage: %d bytes.\nAverage messages cleared per expiry cycle: %d.",
|
||||||
w.stats.messagesCleared, w.stats.memoryCleared, w.stats.totalMemoryUsed)
|
w.stats.memoryUsed, w.stats.totalMessagesCleared/w.stats.cycles)
|
||||||
|
if w.stats.messagesCleared > 0 {
|
||||||
|
result += fmt.Sprintf("\nLatest expiry cycle cleared %d messages (%d bytes).",
|
||||||
|
w.stats.messagesCleared, w.stats.memoryCleared)
|
||||||
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// envelopes retrieves all the messages currently pooled by the node.
|
// envelopes retrieves all the messages currently pooled by the node.
|
||||||
|
|
@ -703,10 +714,20 @@ func (w *Whisper) isEnvelopeCached(hash common.Hash) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Statistics) reset() {
|
func (s *Statistics) reset() {
|
||||||
|
s.cycles++
|
||||||
|
s.totalMessagesCleared += s.messagesCleared
|
||||||
|
|
||||||
s.memoryCleared = 0
|
s.memoryCleared = 0
|
||||||
s.messagesCleared = 0
|
s.messagesCleared = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ValidateKeyID(id string) error {
|
||||||
|
if len(id) != keyIdSize*2 {
|
||||||
|
return fmt.Errorf("Wrong size of key ID")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func ValidatePublicKey(k *ecdsa.PublicKey) bool {
|
func ValidatePublicKey(k *ecdsa.PublicKey) bool {
|
||||||
return k != nil && k.X != nil && k.Y != nil && k.X.Sign() != 0 && k.Y.Sign() != 0
|
return k != nil && k.X != nil && k.Y != nil && k.X.Sign() != 0 && k.Y.Sign() != 0
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,11 +100,11 @@ func TestWhisperBasic(t *testing.T) {
|
||||||
t.Fatalf("failed BytesToIntBigEndian: %d.", be)
|
t.Fatalf("failed BytesToIntBigEndian: %d.", be)
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := w.NewIdentity()
|
id, err := w.NewKeyPair()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to generate new key pair: %s.", err)
|
t.Fatalf("failed to generate new key pair: %s.", err)
|
||||||
}
|
}
|
||||||
pk, err := w.GetIdentity(id)
|
pk, err := w.GetPrivateKey(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to retrieve new key pair: %s.", err)
|
t.Fatalf("failed to retrieve new key pair: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
@ -118,58 +118,60 @@ func TestWhisperBasic(t *testing.T) {
|
||||||
|
|
||||||
func TestWhisperIdentityManagement(t *testing.T) {
|
func TestWhisperIdentityManagement(t *testing.T) {
|
||||||
w := New()
|
w := New()
|
||||||
id1, err := w.NewIdentity()
|
id1, err := w.NewKeyPair()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to generate new key pair: %s.", err)
|
t.Fatalf("failed to generate new key pair: %s.", err)
|
||||||
}
|
}
|
||||||
id2, err := w.NewIdentity()
|
id2, err := w.NewKeyPair()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to generate new key pair: %s.", err)
|
t.Fatalf("failed to generate new key pair: %s.", err)
|
||||||
}
|
}
|
||||||
pk1, err := w.GetIdentity(id1)
|
pk1, err := w.GetPrivateKey(id1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to retrieve the key pair: %s.", err)
|
t.Fatalf("failed to retrieve the key pair: %s.", err)
|
||||||
}
|
}
|
||||||
pk2, err := w.GetIdentity(id2)
|
pk2, err := w.GetPrivateKey(id2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to retrieve the key pair: %s.", err)
|
t.Fatalf("failed to retrieve the key pair: %s.", err)
|
||||||
}
|
}
|
||||||
// todo: delete
|
|
||||||
//pub1 := common.ToHex(crypto.FromECDSAPub(&id1.PublicKey))
|
|
||||||
//pub2 := common.ToHex(crypto.FromECDSAPub(&id2.PublicKey))
|
|
||||||
//pub1 := pk1.PublicKey
|
|
||||||
//pub2 := pk2.PublicKey
|
|
||||||
|
|
||||||
if !w.HasIdentity(id1) {
|
if !w.HasKeyPair(id1) {
|
||||||
t.Fatalf("failed HasIdentity(pub1).")
|
t.Fatalf("failed HasIdentity(pk1).")
|
||||||
}
|
}
|
||||||
if !w.HasIdentity(id2) {
|
if !w.HasKeyPair(id2) {
|
||||||
t.Fatalf("failed HasIdentity(pub2).")
|
t.Fatalf("failed HasIdentity(pk2).")
|
||||||
}
|
}
|
||||||
if pk1 == nil {
|
if pk1 == nil {
|
||||||
t.Fatalf("failed GetIdentity(pub1).")
|
t.Fatalf("failed GetIdentity(pk1).")
|
||||||
}
|
}
|
||||||
if pk2 == nil {
|
if pk2 == nil {
|
||||||
t.Fatalf("failed GetIdentity(pub2).")
|
t.Fatalf("failed GetIdentity(pk2).")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !validatePrivateKey(pk1) {
|
||||||
|
t.Fatalf("pk1 is invalid.")
|
||||||
|
}
|
||||||
|
if !validatePrivateKey(pk2) {
|
||||||
|
t.Fatalf("pk2 is invalid.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete one identity
|
// Delete one identity
|
||||||
done := w.DeleteIdentity(id1)
|
done := w.DeleteKeyPair(id1)
|
||||||
if !done {
|
if !done {
|
||||||
t.Fatalf("failed to delete id1.")
|
t.Fatalf("failed to delete id1.")
|
||||||
}
|
}
|
||||||
pk1, err = w.GetIdentity(id1)
|
pk1, err = w.GetPrivateKey(id1)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("retrieve the key pair: false positive.")
|
t.Fatalf("retrieve the key pair: false positive.")
|
||||||
}
|
}
|
||||||
pk2, err = w.GetIdentity(id2)
|
pk2, err = w.GetPrivateKey(id2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to retrieve the key pair: %s.", err)
|
t.Fatalf("failed to retrieve the key pair: %s.", err)
|
||||||
}
|
}
|
||||||
if w.HasIdentity(id1) {
|
if w.HasKeyPair(id1) {
|
||||||
t.Fatalf("failed DeleteIdentity(pub1): still exist.")
|
t.Fatalf("failed DeleteIdentity(pub1): still exist.")
|
||||||
}
|
}
|
||||||
if !w.HasIdentity(id2) {
|
if !w.HasKeyPair(id2) {
|
||||||
t.Fatalf("failed DeleteIdentity(pub1): pub2 does not exist.")
|
t.Fatalf("failed DeleteIdentity(pub1): pub2 does not exist.")
|
||||||
}
|
}
|
||||||
if pk1 != nil {
|
if pk1 != nil {
|
||||||
|
|
@ -180,22 +182,22 @@ func TestWhisperIdentityManagement(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete again non-existing identity
|
// Delete again non-existing identity
|
||||||
done = w.DeleteIdentity(id1)
|
done = w.DeleteKeyPair(id1)
|
||||||
if done {
|
if done {
|
||||||
t.Fatalf("delete id1: false positive.")
|
t.Fatalf("delete id1: false positive.")
|
||||||
}
|
}
|
||||||
pk1, err = w.GetIdentity(id1)
|
pk1, err = w.GetPrivateKey(id1)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("retrieve the key pair: false positive.")
|
t.Fatalf("retrieve the key pair: false positive.")
|
||||||
}
|
}
|
||||||
pk2, err = w.GetIdentity(id2)
|
pk2, err = w.GetPrivateKey(id2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to retrieve the key pair: %s.", err)
|
t.Fatalf("failed to retrieve the key pair: %s.", err)
|
||||||
}
|
}
|
||||||
if w.HasIdentity(id1) {
|
if w.HasKeyPair(id1) {
|
||||||
t.Fatalf("failed delete non-existing identity: exist.")
|
t.Fatalf("failed delete non-existing identity: exist.")
|
||||||
}
|
}
|
||||||
if !w.HasIdentity(id2) {
|
if !w.HasKeyPair(id2) {
|
||||||
t.Fatalf("failed delete non-existing identity: pub2 does not exist.")
|
t.Fatalf("failed delete non-existing identity: pub2 does not exist.")
|
||||||
}
|
}
|
||||||
if pk1 != nil {
|
if pk1 != nil {
|
||||||
|
|
@ -206,22 +208,22 @@ func TestWhisperIdentityManagement(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete second identity
|
// Delete second identity
|
||||||
done = w.DeleteIdentity(id2)
|
done = w.DeleteKeyPair(id2)
|
||||||
if !done {
|
if !done {
|
||||||
t.Fatalf("failed to delete id2.")
|
t.Fatalf("failed to delete id2.")
|
||||||
}
|
}
|
||||||
pk1, err = w.GetIdentity(id1)
|
pk1, err = w.GetPrivateKey(id1)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("retrieve the key pair: false positive.")
|
t.Fatalf("retrieve the key pair: false positive.")
|
||||||
}
|
}
|
||||||
pk2, err = w.GetIdentity(id2)
|
pk2, err = w.GetPrivateKey(id2)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("retrieve the key pair: false positive.")
|
t.Fatalf("retrieve the key pair: false positive.")
|
||||||
}
|
}
|
||||||
if w.HasIdentity(id1) {
|
if w.HasKeyPair(id1) {
|
||||||
t.Fatalf("failed delete second identity: first identity exist.")
|
t.Fatalf("failed delete second identity: first identity exist.")
|
||||||
}
|
}
|
||||||
if w.HasIdentity(id2) {
|
if w.HasKeyPair(id2) {
|
||||||
t.Fatalf("failed delete second identity: still exist.")
|
t.Fatalf("failed delete second identity: still exist.")
|
||||||
}
|
}
|
||||||
if pk1 != nil {
|
if pk1 != nil {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue