Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
59bff465
Commit
59bff465
authored
Apr 14, 2015
by
Péter Szilágyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
whisper: general cleanups, documentation
parent
5205b2f1
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
146 additions
and
129 deletions
+146
-129
envelope.go
whisper/envelope.go
+1
-11
filter.go
whisper/filter.go
+7
-4
peer.go
whisper/peer.go
+0
-4
whisper.go
whisper/whisper.go
+138
-110
No files found.
whisper/envelope.go
View file @
59bff465
...
...
@@ -24,7 +24,7 @@ type Envelope struct {
Data
[]
byte
Nonce
uint32
hash
common
.
Hash
hash
common
.
Hash
// Cached hash of the envelope to avoid rehashing every time
}
// NewEnvelope wraps a Whisper message with expiration and destination data
...
...
@@ -59,16 +59,6 @@ func (self *Envelope) Seal(pow time.Duration) {
}
}
// valid checks whether the claimed proof of work was indeed executed.
// TODO: Is this really useful? Isn't this always true?
func
(
self
*
Envelope
)
valid
()
bool
{
d
:=
make
([]
byte
,
64
)
copy
(
d
[
:
32
],
self
.
rlpWithoutNonce
())
binary
.
BigEndian
.
PutUint32
(
d
[
60
:
],
self
.
Nonce
)
return
common
.
FirstBitSet
(
common
.
BigD
(
crypto
.
Sha3
(
d
)))
>
0
}
// rlpWithoutNonce returns the RLP encoded envelope contents, except the nonce.
func
(
self
*
Envelope
)
rlpWithoutNonce
()
[]
byte
{
enc
,
_
:=
rlp
.
EncodeToBytes
([]
interface
{}{
self
.
Expiry
,
self
.
TTL
,
self
.
Topics
,
self
.
Data
})
...
...
whisper/filter.go
View file @
59bff465
// Contains the message filter for fine grained subscriptions.
package
whisper
import
"crypto/ecdsa"
// Filter is used to subscribe to specific types of whisper messages.
type
Filter
struct
{
To
*
ecdsa
.
PublicKey
From
*
ecdsa
.
PublicKey
Topics
[]
Topic
Fn
func
(
*
Message
)
To
*
ecdsa
.
PublicKey
// Recipient of the message
From
*
ecdsa
.
PublicKey
// Sender of the message
Topics
[]
Topic
// Topics to watch messages on
Fn
func
(
*
Message
)
// Handler in case of a match
}
whisper/peer.go
View file @
59bff465
...
...
@@ -9,10 +9,6 @@ import (
"gopkg.in/fatih/set.v0"
)
const
(
protocolVersion
uint64
=
0x02
)
type
peer
struct
{
host
*
Whisper
peer
*
p2p
.
Peer
...
...
whisper/whisper.go
View file @
59bff465
...
...
@@ -2,7 +2,6 @@ package whisper
import
(
"crypto/ecdsa"
"errors"
"sync"
"time"
...
...
@@ -17,12 +16,16 @@ import (
)
const
(
statusMsg
=
0x0
envelopesMsg
=
0x01
whisperVersion
=
0x02
statusMsg
=
0x00
envelopesMsg
=
0x01
protocolVersion
uint64
=
0x02
protocolName
=
"shh"
signatureFlag
=
byte
(
1
<<
7
)
signatureLength
=
65
expirationTicks
=
800
*
time
.
Millisecond
)
const
(
...
...
@@ -42,9 +45,9 @@ type Whisper struct {
protocol
p2p
.
Protocol
filters
*
filter
.
Filters
mmu
sync
.
RWMutex
messages
map
[
common
.
Hash
]
*
Envelope
expiry
map
[
uint32
]
*
set
.
SetNonTS
mmu
sync
.
RWMutex
// Message mutex to sync the below pool
messages
map
[
common
.
Hash
]
*
Envelope
// Pool of messages currently tracked by this node
expiry
map
[
uint32
]
*
set
.
SetNonTS
// Message expiration pool (TODO: something lighter)
quit
chan
struct
{}
...
...
@@ -63,8 +66,8 @@ func New() *Whisper {
// p2p whisper sub protocol handler
whisper
.
protocol
=
p2p
.
Protocol
{
Name
:
"shh"
,
Version
:
uint
(
whisper
Version
),
Name
:
protocolName
,
Version
:
uint
(
protocol
Version
),
Length
:
2
,
Run
:
whisper
.
msgHandler
,
}
...
...
@@ -72,42 +75,74 @@ func New() *Whisper {
return
whisper
}
func
(
self
*
Whisper
)
Version
()
uint
{
return
self
.
protocol
.
Version
}
func
(
self
*
Whisper
)
Start
()
{
glog
.
V
(
logger
.
Info
)
.
Infoln
(
"Whisper started"
)
go
self
.
update
()
}
func
(
self
*
Whisper
)
Stop
()
{
close
(
self
.
quit
)
// Protocol returns the whisper sub-protocol handler for this particular client.
func
(
self
*
Whisper
)
Protocol
()
p2p
.
Protocol
{
return
self
.
protocol
}
func
(
self
*
Whisper
)
Send
(
envelope
*
Envelope
)
error
{
return
self
.
add
(
envelope
)
// Version returns the whisper sub-protocols version number.
func
(
self
*
Whisper
)
Version
()
uint
{
return
self
.
protocol
.
Version
}
// NewIdentity generates a new cryptographic identity for the client, and injects
// it into the known identities for message decryption.
func
(
self
*
Whisper
)
NewIdentity
()
*
ecdsa
.
PrivateKey
{
key
,
err
:=
crypto
.
GenerateKey
()
if
err
!=
nil
{
panic
(
err
)
}
self
.
keys
[
string
(
crypto
.
FromECDSAPub
(
&
key
.
PublicKey
))]
=
key
return
key
}
// HasIdentity checks if the the whisper node is configured with the private key
// of the specified public pair.
func
(
self
*
Whisper
)
HasIdentity
(
key
*
ecdsa
.
PublicKey
)
bool
{
return
self
.
keys
[
string
(
crypto
.
FromECDSAPub
(
key
))]
!=
nil
}
// GetIdentity retrieves the private key of the specified public identity.
func
(
self
*
Whisper
)
GetIdentity
(
key
*
ecdsa
.
PublicKey
)
*
ecdsa
.
PrivateKey
{
return
self
.
keys
[
string
(
crypto
.
FromECDSAPub
(
key
))]
}
// Watch installs a new message handler to run in case a matching packet arrives
// from the whisper network.
func
(
self
*
Whisper
)
Watch
(
options
Filter
)
int
{
filter
:=
filter
.
Generic
{
Str1
:
string
(
crypto
.
FromECDSAPub
(
options
.
To
)),
Str2
:
string
(
crypto
.
FromECDSAPub
(
options
.
From
)),
Data
:
NewTopicSet
(
options
.
Topics
),
Fn
:
func
(
data
interface
{})
{
options
.
Fn
(
data
.
(
*
Message
))
},
}
return
self
.
filters
.
Install
(
filter
)
}
// Unwatch removes an installed message handler.
func
(
self
*
Whisper
)
Unwatch
(
id
int
)
{
self
.
filters
.
Uninstall
(
id
)
}
// Send injects a message into the whisper send queue, to be distributed in the
// network in the coming cycles.
func
(
self
*
Whisper
)
Send
(
envelope
*
Envelope
)
error
{
return
self
.
add
(
envelope
)
}
func
(
self
*
Whisper
)
Start
()
{
glog
.
V
(
logger
.
Info
)
.
Infoln
(
"Whisper started"
)
go
self
.
update
()
}
func
(
self
*
Whisper
)
Stop
()
{
close
(
self
.
quit
)
glog
.
V
(
logger
.
Info
)
.
Infoln
(
"Whisper stopped"
)
}
// func (self *Whisper) RemoveIdentity(key *ecdsa.PublicKey) bool {
// k := string(crypto.FromECDSAPub(key))
// if _, ok := self.keys[k]; ok {
...
...
@@ -117,22 +152,7 @@ func (self *Whisper) GetIdentity(key *ecdsa.PublicKey) *ecdsa.PrivateKey {
// return false
// }
func
(
self
*
Whisper
)
Watch
(
opts
Filter
)
int
{
return
self
.
filters
.
Install
(
filter
.
Generic
{
Str1
:
string
(
crypto
.
FromECDSAPub
(
opts
.
To
)),
Str2
:
string
(
crypto
.
FromECDSAPub
(
opts
.
From
)),
Data
:
NewTopicSet
(
opts
.
Topics
),
Fn
:
func
(
data
interface
{})
{
opts
.
Fn
(
data
.
(
*
Message
))
},
})
}
func
(
self
*
Whisper
)
Unwatch
(
id
int
)
{
self
.
filters
.
Uninstall
(
id
)
}
func
(
self
*
Whisper
)
Messages
(
id
int
)
(
messages
[]
*
Message
)
{
/*func (self *Whisper) Messages(id int) (messages []*Message) {
filter := self.filters.Get(id)
if filter != nil {
for _, e := range self.messages {
...
...
@@ -146,6 +166,36 @@ func (self *Whisper) Messages(id int) (messages []*Message) {
}
return
}*/
// add inserts a new envelope into the message pool to be distributed within the
// whisper network. It also inserts the envelope into the expiration pool at the
// appropriate time-stamp.
func
(
self
*
Whisper
)
add
(
envelope
*
Envelope
)
error
{
self
.
mmu
.
Lock
()
defer
self
.
mmu
.
Unlock
()
// Insert the message into the tracked pool
hash
:=
envelope
.
Hash
()
if
_
,
ok
:=
self
.
messages
[
hash
];
ok
{
glog
.
V
(
logger
.
Detail
)
.
Infof
(
"whisper envelope already cached: %x
\n
"
,
envelope
)
return
nil
}
self
.
messages
[
hash
]
=
envelope
// Insert the message into the expiration pool for later removal
if
self
.
expiry
[
envelope
.
Expiry
]
==
nil
{
self
.
expiry
[
envelope
.
Expiry
]
=
set
.
NewNonTS
()
}
if
!
self
.
expiry
[
envelope
.
Expiry
]
.
Has
(
hash
)
{
self
.
expiry
[
envelope
.
Expiry
]
.
Add
(
hash
)
// Notify the local node of a message arrival
go
self
.
postEvent
(
envelope
)
}
glog
.
V
(
logger
.
Detail
)
.
Infof
(
"cached whisper envelope %x
\n
"
,
envelope
)
return
nil
}
// Main handler for passing whisper messages to whisper peer objects
...
...
@@ -182,53 +232,76 @@ func (self *Whisper) msgHandler(peer *p2p.Peer, ws p2p.MsgReadWriter) error {
}
}
// takes care of adding envelopes to the messages pool. At this moment no sanity checks are being performed.
func
(
self
*
Whisper
)
add
(
envelope
*
Envelope
)
error
{
if
!
envelope
.
valid
()
{
return
errors
.
New
(
"invalid pow provided for envelope"
)
// postEvent opens an envelope with the configured identities and delivers the
// message upstream from application processing.
func
(
self
*
Whisper
)
postEvent
(
envelope
*
Envelope
)
{
if
message
:=
self
.
open
(
envelope
);
message
!=
nil
{
self
.
filters
.
Notify
(
createFilter
(
message
,
envelope
.
Topics
),
message
)
}
}
self
.
mmu
.
Lock
()
defer
self
.
mmu
.
Unlock
()
hash
:=
envelope
.
Hash
()
self
.
messages
[
hash
]
=
envelope
if
self
.
expiry
[
envelope
.
Expiry
]
==
nil
{
self
.
expiry
[
envelope
.
Expiry
]
=
set
.
NewNonTS
()
// open tries to decrypt a whisper envelope with all the configured identities,
// returning the decrypted message and the key used to achieve it. If not keys
// are configured, open will return the payload as if non encrypted.
func
(
self
*
Whisper
)
open
(
envelope
*
Envelope
)
*
Message
{
// Short circuit if no identity is set, and assume clear-text
if
len
(
self
.
keys
)
==
0
{
if
message
,
err
:=
envelope
.
Open
(
nil
);
err
==
nil
{
return
message
}
}
if
!
self
.
expiry
[
envelope
.
Expiry
]
.
Has
(
hash
)
{
self
.
expiry
[
envelope
.
Expiry
]
.
Add
(
hash
)
go
self
.
postEvent
(
envelope
)
// Iterate over the keys and try to decrypt the message
for
_
,
key
:=
range
self
.
keys
{
message
,
err
:=
envelope
.
Open
(
key
)
if
err
==
nil
||
err
==
ecies
.
ErrInvalidPublicKey
{
message
.
To
=
&
key
.
PublicKey
return
message
}
}
glog
.
V
(
logger
.
Detail
)
.
Infof
(
"added whisper envelope %x
\n
"
,
envelope
)
// Failed to decrypt, don't return anything
return
nil
}
// createFilter creates a message filter to check against installed handlers.
func
createFilter
(
message
*
Message
,
topics
[]
Topic
)
filter
.
Filter
{
return
filter
.
Generic
{
Str1
:
string
(
crypto
.
FromECDSAPub
(
message
.
To
)),
Str2
:
string
(
crypto
.
FromECDSAPub
(
message
.
Recover
())),
Data
:
NewTopicSet
(
topics
),
}
}
// update loops until the lifetime of the whisper node, updating its internal
// state by expiring stale messages from the pool.
func
(
self
*
Whisper
)
update
()
{
expire
:=
time
.
NewTicker
(
800
*
time
.
Millisecond
)
out
:
// Start a ticker to check for expirations
expire
:=
time
.
NewTicker
(
expirationTicks
)
// Repeat updates until termination is requested
for
{
select
{
case
<-
expire
.
C
:
self
.
expire
()
case
<-
self
.
quit
:
break
out
return
}
}
}
// expire iterates over all the expiration timestamps, removing all stale
// messages from the pools.
func
(
self
*
Whisper
)
expire
()
{
self
.
mmu
.
Lock
()
defer
self
.
mmu
.
Unlock
()
now
:=
uint32
(
time
.
Now
()
.
Unix
())
for
then
,
hashSet
:=
range
self
.
expiry
{
// Short circuit if a future time
if
then
>
now
{
continue
}
// Dump all expired messages and remove timestamp
hashSet
.
Each
(
func
(
v
interface
{})
bool
{
delete
(
self
.
messages
,
v
.
(
common
.
Hash
))
return
true
...
...
@@ -237,59 +310,14 @@ func (self *Whisper) expire() {
}
}
func
(
self
*
Whisper
)
envelopes
()
(
envelopes
[]
*
Envelope
)
{
// envelopes retrieves all the messages currently pooled by the node.
func
(
self
*
Whisper
)
envelopes
()
[]
*
Envelope
{
self
.
mmu
.
RLock
()
defer
self
.
mmu
.
RUnlock
()
envelopes
=
make
([]
*
Envelope
,
len
(
self
.
messages
))
i
:=
0
envelopes
:=
make
([]
*
Envelope
,
0
,
len
(
self
.
messages
))
for
_
,
envelope
:=
range
self
.
messages
{
envelopes
[
i
]
=
envelope
i
++
}
return
}
func
(
self
*
Whisper
)
Protocol
()
p2p
.
Protocol
{
return
self
.
protocol
}
// postEvent opens an envelope with the configured identities and delivers the
// message upstream from application processing.
func
(
self
*
Whisper
)
postEvent
(
envelope
*
Envelope
)
{
if
message
:=
self
.
open
(
envelope
);
message
!=
nil
{
self
.
filters
.
Notify
(
createFilter
(
message
,
envelope
.
Topics
),
message
)
}
}
// open tries to decrypt a whisper envelope with all the configured identities,
// returning the decrypted message and the key used to achieve it. If not keys
// are configured, open will return the payload as if non encrypted.
func
(
self
*
Whisper
)
open
(
envelope
*
Envelope
)
*
Message
{
// Short circuit if no identity is set, and assume clear-text
if
len
(
self
.
keys
)
==
0
{
if
message
,
err
:=
envelope
.
Open
(
nil
);
err
==
nil
{
return
message
}
}
// Iterate over the keys and try to decrypt the message
for
_
,
key
:=
range
self
.
keys
{
message
,
err
:=
envelope
.
Open
(
key
)
if
err
==
nil
||
err
==
ecies
.
ErrInvalidPublicKey
{
message
.
To
=
&
key
.
PublicKey
return
message
}
}
// Failed to decrypt, don't return anything
return
nil
}
// createFilter creates a message filter to check against installed handlers.
func
createFilter
(
message
*
Message
,
topics
[]
Topic
)
filter
.
Filter
{
return
filter
.
Generic
{
Str1
:
string
(
crypto
.
FromECDSAPub
(
message
.
To
)),
Str2
:
string
(
crypto
.
FromECDSAPub
(
message
.
Recover
())),
Data
:
NewTopicSet
(
topics
),
envelopes
=
append
(
envelopes
,
envelope
)
}
return
envelopes
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment