mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 06:36:43 +00:00
whisper: GetMessages fixed; size restriction updated
This commit is contained in:
parent
5c8fe28b72
commit
a02cf9a0ad
6 changed files with 81 additions and 81 deletions
|
|
@ -102,12 +102,12 @@ func (api *PublicWhisperAPI) HasIdentity(identity string) (bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteIdentity deletes the specifies key if it exists.
|
// DeleteIdentity deletes the specifies key if it exists.
|
||||||
func (api *PublicWhisperAPI) DeleteIdentity(identity string) error {
|
func (api *PublicWhisperAPI) DeleteIdentity(identity string) (bool, error) {
|
||||||
if api.whisper == nil {
|
if api.whisper == nil {
|
||||||
return whisperOffLineErr
|
return false, whisperOffLineErr
|
||||||
}
|
}
|
||||||
api.whisper.DeleteIdentity(identity)
|
success := api.whisper.DeleteIdentity(identity)
|
||||||
return nil
|
return success, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIdentity generates a new cryptographic identity for the client, and injects
|
// NewIdentity generates a new cryptographic identity for the client, and injects
|
||||||
|
|
@ -352,7 +352,7 @@ func (api *PublicWhisperAPI) Post(args PostArgs) error {
|
||||||
log.Error(fmt.Sprintf(err.Error()))
|
log.Error(fmt.Sprintf(err.Error()))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(envelope.Data) > MaxMessageLength {
|
if envelope.size() > MaxMessageLength {
|
||||||
info := "Post: message is too big"
|
info := "Post: message is too big"
|
||||||
log.Error(fmt.Sprintf(info))
|
log.Error(fmt.Sprintf(info))
|
||||||
return errors.New(info)
|
return errors.New(info)
|
||||||
|
|
|
||||||
|
|
@ -55,10 +55,13 @@ func TestBasic(t *testing.T) {
|
||||||
t.Fatalf("failed initial HasIdentity: false positive.")
|
t.Fatalf("failed initial HasIdentity: false positive.")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = api.DeleteIdentity(id)
|
success, err := api.DeleteIdentity(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed DeleteIdentity: %s.", err)
|
t.Fatalf("failed DeleteIdentity: %s.", err)
|
||||||
}
|
}
|
||||||
|
if success {
|
||||||
|
t.Fatalf("deleted non-existing identity: false positive.")
|
||||||
|
}
|
||||||
|
|
||||||
pub, err := api.NewIdentity()
|
pub, err := api.NewIdentity()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -76,10 +79,13 @@ func TestBasic(t *testing.T) {
|
||||||
t.Fatalf("failed HasIdentity: false negative.")
|
t.Fatalf("failed HasIdentity: false negative.")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = api.DeleteIdentity(pub)
|
success, err = api.DeleteIdentity(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)
|
||||||
}
|
}
|
||||||
|
if !success {
|
||||||
|
t.Fatalf("failed to delete second identity.")
|
||||||
|
}
|
||||||
|
|
||||||
exist, err = api.HasIdentity(pub)
|
exist, err = api.HasIdentity(pub)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -257,17 +263,23 @@ func TestUnmarshalPostArgs(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func waitForMessage(api *PublicWhisperAPI, id string, target int) bool {
|
func waitForMessages(api *PublicWhisperAPI, id string, target int) []*WhisperMessage {
|
||||||
for i := 0; i < 64; i++ {
|
// timeout: 2 seconds
|
||||||
all := api.GetMessages(id)
|
result := make([]*WhisperMessage, 0, target)
|
||||||
if len(all) >= target {
|
for i := 0; i < 100; i++ {
|
||||||
return true
|
mail := api.GetFilterChanges(id)
|
||||||
|
if len(mail) > 0 {
|
||||||
|
for _, m := range mail {
|
||||||
|
result = append(result, m)
|
||||||
}
|
}
|
||||||
time.Sleep(time.Millisecond * 16)
|
if len(result) >= target {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
time.Sleep(time.Millisecond * 20)
|
||||||
}
|
}
|
||||||
|
|
||||||
// timeout 1024 milliseconds
|
return result
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIntegrationAsym(t *testing.T) {
|
func TestIntegrationAsym(t *testing.T) {
|
||||||
|
|
@ -334,12 +346,7 @@ func TestIntegrationAsym(t *testing.T) {
|
||||||
t.Errorf("failed to post message: %s.", err)
|
t.Errorf("failed to post message: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ok := waitForMessage(api, id, 1)
|
mail := waitForMessages(api, id, 1)
|
||||||
if !ok {
|
|
||||||
t.Fatalf("failed to receive first message: timeout.")
|
|
||||||
}
|
|
||||||
|
|
||||||
mail := api.GetFilterChanges(id)
|
|
||||||
if len(mail) != 1 {
|
if len(mail) != 1 {
|
||||||
t.Fatalf("failed to GetFilterChanges: got %d messages.", len(mail))
|
t.Fatalf("failed to GetFilterChanges: got %d messages.", len(mail))
|
||||||
}
|
}
|
||||||
|
|
@ -356,12 +363,7 @@ func TestIntegrationAsym(t *testing.T) {
|
||||||
t.Fatalf("failed to post next message: %s.", err)
|
t.Fatalf("failed to post next message: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = waitForMessage(api, id, 2)
|
mail = waitForMessages(api, id, 1)
|
||||||
if !ok {
|
|
||||||
t.Fatalf("failed to receive second message: timeout.")
|
|
||||||
}
|
|
||||||
|
|
||||||
mail = api.GetFilterChanges(id)
|
|
||||||
if len(mail) != 1 {
|
if len(mail) != 1 {
|
||||||
t.Fatalf("failed to GetFilterChanges: got %d messages.", len(mail))
|
t.Fatalf("failed to GetFilterChanges: got %d messages.", len(mail))
|
||||||
}
|
}
|
||||||
|
|
@ -434,12 +436,7 @@ func TestIntegrationSym(t *testing.T) {
|
||||||
t.Fatalf("failed to post first message: %s.", err)
|
t.Fatalf("failed to post first message: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ok := waitForMessage(api, id, 1)
|
mail := waitForMessages(api, id, 1)
|
||||||
if !ok {
|
|
||||||
t.Fatalf("failed to receive first message: timeout.")
|
|
||||||
}
|
|
||||||
|
|
||||||
mail := api.GetFilterChanges(id)
|
|
||||||
if len(mail) != 1 {
|
if len(mail) != 1 {
|
||||||
t.Fatalf("failed GetFilterChanges: got %d messages.", len(mail))
|
t.Fatalf("failed GetFilterChanges: got %d messages.", len(mail))
|
||||||
}
|
}
|
||||||
|
|
@ -456,12 +453,7 @@ func TestIntegrationSym(t *testing.T) {
|
||||||
t.Fatalf("failed to post second message: %s.", err)
|
t.Fatalf("failed to post second message: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = waitForMessage(api, id, 2)
|
mail = waitForMessages(api, id, 1)
|
||||||
if !ok {
|
|
||||||
t.Fatalf("failed to receive second message: timeout.")
|
|
||||||
}
|
|
||||||
|
|
||||||
mail = api.GetFilterChanges(id)
|
|
||||||
if len(mail) != 1 {
|
if len(mail) != 1 {
|
||||||
t.Fatalf("failed second GetFilterChanges: got %d messages.", len(mail))
|
t.Fatalf("failed second GetFilterChanges: got %d messages.", len(mail))
|
||||||
}
|
}
|
||||||
|
|
@ -534,12 +526,7 @@ func TestIntegrationSymWithFilter(t *testing.T) {
|
||||||
t.Fatalf("failed to post message: %s.", err)
|
t.Fatalf("failed to post message: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ok := waitForMessage(api, id, 1)
|
mail := waitForMessages(api, id, 1)
|
||||||
if !ok {
|
|
||||||
t.Fatalf("failed to receive first message: timeout.")
|
|
||||||
}
|
|
||||||
|
|
||||||
mail := api.GetFilterChanges(id)
|
|
||||||
if len(mail) != 1 {
|
if len(mail) != 1 {
|
||||||
t.Fatalf("failed to GetFilterChanges: got %d messages.", len(mail))
|
t.Fatalf("failed to GetFilterChanges: got %d messages.", len(mail))
|
||||||
}
|
}
|
||||||
|
|
@ -556,12 +543,7 @@ func TestIntegrationSymWithFilter(t *testing.T) {
|
||||||
t.Fatalf("failed to post next message: %s.", err)
|
t.Fatalf("failed to post next message: %s.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = waitForMessage(api, id, 2)
|
mail = waitForMessages(api, id, 1)
|
||||||
if !ok {
|
|
||||||
t.Fatalf("failed to receive second message: timeout.")
|
|
||||||
}
|
|
||||||
|
|
||||||
mail = api.GetFilterChanges(id)
|
|
||||||
if len(mail) != 1 {
|
if len(mail) != 1 {
|
||||||
t.Fatalf("failed to GetFilterChanges: got %d messages.", len(mail))
|
t.Fatalf("failed to GetFilterChanges: got %d messages.", len(mail))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ const (
|
||||||
saltLength = 12
|
saltLength = 12
|
||||||
AESNonceMaxLength = 12
|
AESNonceMaxLength = 12
|
||||||
|
|
||||||
MaxMessageLength = 0x0FFFFF // todo: remove this restriction after testing. this should be regulated by PoW.
|
MaxMessageLength = 1024 * 1024
|
||||||
MinimumPoW = 10.0 // todo: review after testing.
|
MinimumPoW = 10.0 // todo: review after testing.
|
||||||
|
|
||||||
padSizeLimitLower = 128 // it can not be less - we don't want to reveal the absence of signature
|
padSizeLimitLower = 128 // it can not be less - we don't want to reveal the absence of signature
|
||||||
|
|
|
||||||
|
|
@ -102,11 +102,16 @@ func (fs *Filters) Get(id string) *Filter {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) {
|
func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) {
|
||||||
fs.mutex.RLock()
|
var j int
|
||||||
var msg *ReceivedMessage
|
var msg *ReceivedMessage
|
||||||
for j, watcher := range fs.watchers {
|
|
||||||
|
fs.mutex.RLock()
|
||||||
|
defer fs.mutex.RUnlock()
|
||||||
|
|
||||||
|
for _, watcher := range fs.watchers {
|
||||||
|
j++
|
||||||
if p2pMessage && !watcher.AcceptP2P {
|
if p2pMessage && !watcher.AcceptP2P {
|
||||||
log.Trace(fmt.Sprintf("msg [%x], filter [%s]: 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,10 +123,10 @@ func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) {
|
||||||
if match {
|
if match {
|
||||||
msg = env.Open(watcher)
|
msg = env.Open(watcher)
|
||||||
if msg == nil {
|
if msg == nil {
|
||||||
log.Trace(fmt.Sprintf("msg [%x], filter [%s]: failed to open", env.Hash(), j))
|
log.Trace(fmt.Sprintf("msg [%x], filter [%d]: failed to open", env.Hash(), j))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Trace(fmt.Sprintf("msg [%x], filter [%s]: does not match", env.Hash(), j))
|
log.Trace(fmt.Sprintf("msg [%x], filter [%d]: does not match", env.Hash(), j))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,11 +134,20 @@ func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) {
|
||||||
watcher.Trigger(msg)
|
watcher.Trigger(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fs.mutex.RUnlock() // we need to unlock before calling addDecryptedMessage
|
}
|
||||||
|
|
||||||
|
func (f *Filter) processEnvelope(env *Envelope) *ReceivedMessage {
|
||||||
|
if f.MatchEnvelope(env) {
|
||||||
|
msg := env.Open(f)
|
||||||
if msg != nil {
|
if msg != nil {
|
||||||
fs.whisper.addDecryptedMessage(msg)
|
return msg
|
||||||
|
} else {
|
||||||
|
log.Trace(fmt.Sprintf("processing msg [%x]: failed to open", env.Hash()))
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
log.Trace(fmt.Sprintf("processing msg [%x]: does not match", env.Hash()))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Filter) expectsAsymmetricEncryption() bool {
|
func (f *Filter) expectsAsymmetricEncryption() bool {
|
||||||
|
|
|
||||||
|
|
@ -258,6 +258,10 @@ func (msg *SentMessage) Wrap(options *MessageParams) (envelope *Envelope, err er
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if envelope.size() > MaxMessageLength {
|
||||||
|
log.Error(fmt.Sprintf("Envelope size must not exceed %d bytes", MaxMessageLength))
|
||||||
|
return nil, errors.New("Oversized message")
|
||||||
|
}
|
||||||
|
|
||||||
return envelope, nil
|
return envelope, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,6 @@ type Whisper struct {
|
||||||
keyMu sync.RWMutex
|
keyMu sync.RWMutex
|
||||||
|
|
||||||
envelopes map[common.Hash]*Envelope // Pool of envelopes currently tracked by this node
|
envelopes map[common.Hash]*Envelope // Pool of envelopes currently tracked by this node
|
||||||
messages map[common.Hash]*ReceivedMessage // Pool of successfully decrypted messages, which are not expired yet
|
|
||||||
expirations map[uint32]*set.SetNonTS // Message expiration pool
|
expirations map[uint32]*set.SetNonTS // Message expiration pool
|
||||||
poolMu sync.RWMutex // Mutex to sync the message and expiration pools
|
poolMu sync.RWMutex // Mutex to sync the message and expiration pools
|
||||||
|
|
||||||
|
|
@ -78,7 +77,6 @@ func New() *Whisper {
|
||||||
privateKeys: make(map[string]*ecdsa.PrivateKey),
|
privateKeys: make(map[string]*ecdsa.PrivateKey),
|
||||||
symKeys: make(map[string][]byte),
|
symKeys: make(map[string][]byte),
|
||||||
envelopes: make(map[common.Hash]*Envelope),
|
envelopes: make(map[common.Hash]*Envelope),
|
||||||
messages: make(map[common.Hash]*ReceivedMessage),
|
|
||||||
expirations: make(map[uint32]*set.SetNonTS),
|
expirations: make(map[uint32]*set.SetNonTS),
|
||||||
peers: make(map[*Peer]struct{}),
|
peers: make(map[*Peer]struct{}),
|
||||||
messageQueue: make(chan *Envelope, messageQueueLimit),
|
messageQueue: make(chan *Envelope, messageQueueLimit),
|
||||||
|
|
@ -188,10 +186,15 @@ func (w *Whisper) NewIdentity() *ecdsa.PrivateKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteIdentity deletes the specified key if it exists.
|
// DeleteIdentity deletes the specified key if it exists.
|
||||||
func (w *Whisper) DeleteIdentity(key string) {
|
func (w *Whisper) DeleteIdentity(key string) bool {
|
||||||
w.keyMu.Lock()
|
w.keyMu.Lock()
|
||||||
defer w.keyMu.Unlock()
|
defer w.keyMu.Unlock()
|
||||||
|
|
||||||
|
if w.privateKeys[key] != nil {
|
||||||
delete(w.privateKeys, key)
|
delete(w.privateKeys, key)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
|
|
@ -355,6 +358,9 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if packet.Size > MaxMessageLength {
|
||||||
|
return fmt.Errorf("oversized message received")
|
||||||
|
}
|
||||||
|
|
||||||
switch packet.Code {
|
switch packet.Code {
|
||||||
case statusCode:
|
case statusCode:
|
||||||
|
|
@ -435,7 +441,7 @@ func (wh *Whisper) add(envelope *Envelope) (bool, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(envelope.Data) > MaxMessageLength {
|
if envelope.size() > MaxMessageLength {
|
||||||
return false, fmt.Errorf("huge messages are not allowed [%x]", envelope.Hash())
|
return false, fmt.Errorf("huge messages are not allowed [%x]", envelope.Hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -558,7 +564,7 @@ func (w *Whisper) expire() {
|
||||||
w.poolMu.Lock()
|
w.poolMu.Lock()
|
||||||
defer w.poolMu.Unlock()
|
defer w.poolMu.Unlock()
|
||||||
|
|
||||||
w.stats.clear()
|
w.stats.reset()
|
||||||
now := uint32(time.Now().Unix())
|
now := uint32(time.Now().Unix())
|
||||||
for expiry, hashSet := range w.expirations {
|
for expiry, hashSet := range w.expirations {
|
||||||
if expiry < now {
|
if expiry < now {
|
||||||
|
|
@ -570,7 +576,6 @@ func (w *Whisper) expire() {
|
||||||
w.stats.memoryCleared += sz
|
w.stats.memoryCleared += sz
|
||||||
w.stats.totalMemoryUsed -= sz
|
w.stats.totalMemoryUsed -= sz
|
||||||
delete(w.envelopes, v.(common.Hash))
|
delete(w.envelopes, v.(common.Hash))
|
||||||
delete(w.messages, v.(common.Hash))
|
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
w.expirations[expiry].Clear()
|
w.expirations[expiry].Clear()
|
||||||
|
|
@ -596,15 +601,17 @@ func (w *Whisper) Envelopes() []*Envelope {
|
||||||
return all
|
return all
|
||||||
}
|
}
|
||||||
|
|
||||||
// Messages retrieves all the decrypted messages matching a filter id.
|
// Messages iterates through all currently floating envelopes
|
||||||
|
// and retrieves all the messages, that this filter could decrypt.
|
||||||
func (w *Whisper) Messages(id string) []*ReceivedMessage {
|
func (w *Whisper) Messages(id string) []*ReceivedMessage {
|
||||||
result := make([]*ReceivedMessage, 0)
|
result := make([]*ReceivedMessage, 0)
|
||||||
w.poolMu.RLock()
|
w.poolMu.RLock()
|
||||||
defer w.poolMu.RUnlock()
|
defer w.poolMu.RUnlock()
|
||||||
|
|
||||||
if filter := w.filters.Get(id); filter != nil {
|
if filter := w.filters.Get(id); filter != nil {
|
||||||
for _, msg := range w.messages {
|
for _, env := range w.envelopes {
|
||||||
if filter.MatchMessage(msg) {
|
msg := filter.processEnvelope(env)
|
||||||
|
if msg != nil {
|
||||||
result = append(result, msg)
|
result = append(result, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -620,14 +627,7 @@ func (w *Whisper) isEnvelopeCached(hash common.Hash) bool {
|
||||||
return exist
|
return exist
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Whisper) addDecryptedMessage(msg *ReceivedMessage) {
|
func (s *Statistics) reset() {
|
||||||
w.poolMu.Lock()
|
|
||||||
defer w.poolMu.Unlock()
|
|
||||||
|
|
||||||
w.messages[msg.EnvelopeHash] = msg
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Statistics) clear() {
|
|
||||||
s.memoryCleared = 0
|
s.memoryCleared = 0
|
||||||
s.messagesCleared = 0
|
s.messagesCleared = 0
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue