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
690f6ea1
Commit
690f6ea1
authored
Jan 31, 2017
by
gluk256
Committed by
Felix Lange
Jan 31, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
cmd/wnode, whisper: add whisper CLI tool and mail server (#3580)
parent
1c140f73
Changes
8
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
769 additions
and
30 deletions
+769
-30
main.go
cmd/wnode/main.go
+537
-0
mailserver.go
whisper/mailserver/mailserver.go
+170
-0
api.go
whisper/shhapi/api.go
+6
-6
doc.go
whisper/whisperv5/doc.go
+1
-1
message_test.go
whisper/whisperv5/message_test.go
+33
-0
peer.go
whisper/whisperv5/peer.go
+5
-0
whisper.go
whisper/whisperv5/whisper.go
+17
-17
whisper_test.go
whisper/whisperv5/whisper_test.go
+0
-6
No files found.
cmd/wnode/main.go
0 → 100644
View file @
690f6ea1
This diff is collapsed.
Click to expand it.
whisper/mailserver/mailserver.go
0 → 100644
View file @
690f6ea1
// Copyright 2016 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
package
mailserver
import
(
"bytes"
"encoding/binary"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/rlp"
whisper
"github.com/ethereum/go-ethereum/whisper/whisperv5"
"github.com/syndtr/goleveldb/leveldb"
"github.com/syndtr/goleveldb/leveldb/util"
)
const
MailServerKeyName
=
"958e04ab302fb36ad2616a352cbac79d"
type
WMailServer
struct
{
db
*
leveldb
.
DB
w
*
whisper
.
Whisper
pow
float64
key
[]
byte
}
type
DBKey
struct
{
timestamp
uint32
hash
common
.
Hash
raw
[]
byte
}
func
NewDbKey
(
t
uint32
,
h
common
.
Hash
)
*
DBKey
{
const
sz
=
common
.
HashLength
+
4
var
k
DBKey
k
.
timestamp
=
t
k
.
hash
=
h
k
.
raw
=
make
([]
byte
,
sz
)
binary
.
BigEndian
.
PutUint32
(
k
.
raw
,
k
.
timestamp
)
copy
(
k
.
raw
[
4
:
],
k
.
hash
[
:
])
return
&
k
}
func
(
s
*
WMailServer
)
Init
(
shh
*
whisper
.
Whisper
,
path
string
,
password
string
,
pow
float64
)
{
var
err
error
if
len
(
path
)
==
0
{
utils
.
Fatalf
(
"DB file is not specified"
)
}
if
len
(
password
)
==
0
{
utils
.
Fatalf
(
"Password is not specified for MailServer"
)
}
s
.
db
,
err
=
leveldb
.
OpenFile
(
path
,
nil
)
if
err
!=
nil
{
utils
.
Fatalf
(
"Failed to open DB file: %s"
,
err
)
}
s
.
w
=
shh
s
.
pow
=
pow
err
=
s
.
w
.
AddSymKey
(
MailServerKeyName
,
[]
byte
(
password
))
if
err
!=
nil
{
utils
.
Fatalf
(
"Failed to create symmetric key for MailServer: %s"
,
err
)
}
s
.
key
=
s
.
w
.
GetSymKey
(
MailServerKeyName
)
}
func
(
s
*
WMailServer
)
Close
()
{
if
s
.
db
!=
nil
{
s
.
db
.
Close
()
}
}
func
(
s
*
WMailServer
)
Archive
(
env
*
whisper
.
Envelope
)
{
key
:=
NewDbKey
(
env
.
Expiry
-
env
.
TTL
,
env
.
Hash
())
rawEnvelope
,
err
:=
rlp
.
EncodeToBytes
(
env
)
if
err
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infof
(
"rlp.EncodeToBytes failed: %s"
,
err
)
}
else
{
err
=
s
.
db
.
Put
(
key
.
raw
,
rawEnvelope
,
nil
)
if
err
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infof
(
"Writing to DB failed: %s"
,
err
)
}
}
}
func
(
s
*
WMailServer
)
DeliverMail
(
peer
*
whisper
.
Peer
,
request
*
whisper
.
Envelope
)
{
ok
,
lower
,
upper
,
topic
:=
s
.
validate
(
peer
,
request
)
if
!
ok
{
return
}
var
err
error
var
zero
common
.
Hash
var
empty
whisper
.
TopicType
kl
:=
NewDbKey
(
lower
,
zero
)
ku
:=
NewDbKey
(
upper
,
zero
)
i
:=
s
.
db
.
NewIterator
(
&
util
.
Range
{
Start
:
kl
.
raw
,
Limit
:
ku
.
raw
},
nil
)
defer
i
.
Release
()
for
i
.
Next
()
{
var
envelope
whisper
.
Envelope
err
=
rlp
.
DecodeBytes
(
i
.
Value
(),
&
envelope
)
if
err
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infof
(
"RLP decoding failed: %s"
,
err
)
}
if
topic
==
empty
||
envelope
.
Topic
==
topic
{
err
=
s
.
w
.
SendP2PDirect
(
peer
,
&
envelope
)
if
err
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infof
(
"Failed to send direct message to peer: %s"
,
err
)
return
}
}
}
err
=
i
.
Error
()
if
err
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infof
(
"Level DB iterator error: %s"
,
err
)
}
}
func
(
s
*
WMailServer
)
validate
(
peer
*
whisper
.
Peer
,
request
*
whisper
.
Envelope
)
(
bool
,
uint32
,
uint32
,
whisper
.
TopicType
)
{
var
topic
whisper
.
TopicType
if
s
.
pow
>
0.0
&&
request
.
PoW
()
<
s
.
pow
{
return
false
,
0
,
0
,
topic
}
f
:=
whisper
.
Filter
{
KeySym
:
s
.
key
}
decrypted
:=
request
.
Open
(
&
f
)
if
decrypted
==
nil
{
glog
.
V
(
logger
.
Warn
)
.
Infof
(
"Failed to decrypt p2p request"
)
return
false
,
0
,
0
,
topic
}
if
len
(
decrypted
.
Payload
)
<
8
{
glog
.
V
(
logger
.
Warn
)
.
Infof
(
"Undersized p2p request"
)
return
false
,
0
,
0
,
topic
}
if
bytes
.
Equal
(
peer
.
ID
(),
decrypted
.
Signature
)
{
glog
.
V
(
logger
.
Warn
)
.
Infof
(
"Wrong signature of p2p request"
)
return
false
,
0
,
0
,
topic
}
lower
:=
binary
.
BigEndian
.
Uint32
(
decrypted
.
Payload
[
:
4
])
upper
:=
binary
.
BigEndian
.
Uint32
(
decrypted
.
Payload
[
4
:
8
])
if
len
(
decrypted
.
Payload
)
>=
8
+
whisper
.
TopicLength
{
topic
=
whisper
.
BytesToTopic
(
decrypted
.
Payload
[
8
:
])
}
return
true
,
lower
,
upper
,
topic
}
whisper/shhapi/api.go
View file @
690f6ea1
...
...
@@ -93,12 +93,12 @@ func (api *PublicWhisperAPI) MarkPeerTrusted(peerID hexutil.Bytes) error {
// data contains parameters (time frame, payment details, etc.), required
// by the remote email-like server. Whisper is not aware about the data format,
// it will just forward the raw data to the server.
func
(
api
*
PublicWhisperAPI
)
RequestHistoricMessages
(
peerID
hexutil
.
Bytes
,
data
hexutil
.
Bytes
)
error
{
if
api
.
whisper
==
nil
{
return
whisperOffLineErr
}
return
api
.
whisper
.
RequestHistoricMessages
(
peerID
,
data
)
}
//
func (api *PublicWhisperAPI) RequestHistoricMessages(peerID hexutil.Bytes, data hexutil.Bytes) error {
//
if api.whisper == nil {
//
return whisperOffLineErr
//
}
//
return api.whisper.RequestHistoricMessages(peerID, data)
//
}
// HasIdentity checks if the whisper node is configured with the private key
// of the specified public pair.
...
...
whisper/whisperv5/doc.go
View file @
690f6ea1
...
...
@@ -83,5 +83,5 @@ func (e unknownVersionError) Error() string {
// in order to bypass the expiry checks.
type
MailServer
interface
{
Archive
(
env
*
Envelope
)
DeliverMail
(
whisperPeer
*
Peer
,
data
[]
byt
e
)
DeliverMail
(
whisperPeer
*
Peer
,
request
*
Envelop
e
)
}
whisper/whisperv5/message_test.go
View file @
690f6ea1
...
...
@@ -22,6 +22,7 @@ import (
"testing"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
)
func
copyFromBuf
(
dst
[]
byte
,
src
[]
byte
,
beg
int
)
int
{
...
...
@@ -311,3 +312,35 @@ func TestEncryptWithZeroKey(t *testing.T) {
t
.
Fatalf
(
"wrapped with nil key, seed: %d."
,
seed
)
}
}
func
TestRlpEncode
(
t
*
testing
.
T
)
{
InitSingleTest
()
params
,
err
:=
generateMessageParams
()
if
err
!=
nil
{
t
.
Fatalf
(
"failed generateMessageParams with seed %d: %s."
,
seed
,
err
)
}
msg
:=
NewSentMessage
(
params
)
env
,
err
:=
msg
.
Wrap
(
params
)
if
err
!=
nil
{
t
.
Fatalf
(
"wrapped with zero key, seed: %d."
,
seed
)
}
raw
,
err
:=
rlp
.
EncodeToBytes
(
env
)
if
err
!=
nil
{
t
.
Fatalf
(
"RLP encode failed: %s."
,
err
)
}
var
decoded
Envelope
rlp
.
DecodeBytes
(
raw
,
&
decoded
)
if
err
!=
nil
{
t
.
Fatalf
(
"RLP decode failed: %s."
,
err
)
}
he
:=
env
.
Hash
()
hd
:=
decoded
.
Hash
()
if
he
!=
hd
{
t
.
Fatalf
(
"Hashes are not equal: %x vs. %x"
,
he
,
hd
)
}
}
whisper/whisperv5/peer.go
View file @
690f6ea1
...
...
@@ -175,3 +175,8 @@ func (p *Peer) broadcast() error {
glog
.
V
(
logger
.
Detail
)
.
Infoln
(
p
.
peer
,
"broadcasted"
,
len
(
transmit
),
"message(s)"
)
return
nil
}
func
(
p
*
Peer
)
ID
()
[]
byte
{
id
:=
p
.
peer
.
ID
()
return
id
[
:
]
}
whisper/whisperv5/whisper.go
View file @
690f6ea1
...
...
@@ -31,7 +31,6 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rlp"
"golang.org/x/crypto/pbkdf2"
set
"gopkg.in/fatih/set.v0"
)
...
...
@@ -125,13 +124,13 @@ func (w *Whisper) MarkPeerTrusted(peerID []byte) error {
return
nil
}
func
(
w
*
Whisper
)
RequestHistoricMessages
(
peerID
[]
byte
,
data
[]
byt
e
)
error
{
func
(
w
*
Whisper
)
RequestHistoricMessages
(
peerID
[]
byte
,
envelope
*
Envelop
e
)
error
{
p
,
err
:=
w
.
getPeer
(
peerID
)
if
err
!=
nil
{
return
err
}
p
.
trusted
=
true
return
p2p
.
Send
(
p
.
ws
,
p2pRequestCode
,
data
)
return
p2p
.
Send
(
p
.
ws
,
p2pRequestCode
,
envelope
)
}
func
(
w
*
Whisper
)
SendP2PMessage
(
peerID
[]
byte
,
envelope
*
Envelope
)
error
{
...
...
@@ -142,6 +141,10 @@ func (w *Whisper) SendP2PMessage(peerID []byte, envelope *Envelope) error {
return
p2p
.
Send
(
p
.
ws
,
p2pCode
,
envelope
)
}
func
(
w
*
Whisper
)
SendP2PDirect
(
peer
*
Peer
,
envelope
*
Envelope
)
error
{
return
p2p
.
Send
(
peer
.
ws
,
p2pCode
,
envelope
)
}
// NewIdentity generates a new cryptographic identity for the client, and injects
// it into the known identities for message decryption.
func
(
w
*
Whisper
)
NewIdentity
()
*
ecdsa
.
PrivateKey
{
...
...
@@ -347,9 +350,6 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
return
fmt
.
Errorf
(
"invalid envelope"
)
}
p
.
mark
(
envelope
)
if
wh
.
mailServer
!=
nil
{
wh
.
mailServer
.
Archive
(
envelope
)
}
}
case
p2pCode
:
// peer-to-peer message, sent directly to peer bypassing PoW checks, etc.
...
...
@@ -357,25 +357,22 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
// therefore might not satisfy the PoW, expiry and other requirements.
// these messages are only accepted from the trusted peer.
if
p
.
trusted
{
var
envelope
s
[]
*
Envelope
if
err
:=
packet
.
Decode
(
&
envelope
s
);
err
!=
nil
{
var
envelope
Envelope
if
err
:=
packet
.
Decode
(
&
envelope
);
err
!=
nil
{
glog
.
V
(
logger
.
Warn
)
.
Infof
(
"%v: failed to decode direct message: [%v], peer will be disconnected"
,
p
.
peer
,
err
)
return
fmt
.
Errorf
(
"garbage received (directMessage)"
)
}
for
_
,
envelope
:=
range
envelopes
{
wh
.
postEvent
(
envelope
,
true
)
}
wh
.
postEvent
(
&
envelope
,
true
)
}
case
p2pRequestCode
:
// Must be processed if mail server is implemented. Otherwise ignore.
if
wh
.
mailServer
!=
nil
{
s
:=
rlp
.
NewStream
(
packet
.
Payload
,
uint64
(
packet
.
Size
))
data
,
err
:=
s
.
Bytes
()
if
err
==
nil
{
wh
.
mailServer
.
DeliverMail
(
p
,
data
)
}
else
{
glog
.
V
(
logger
.
Error
)
.
Infof
(
"%v: bad requestHistoricMessages received: [%v]"
,
p
.
peer
,
err
)
var
request
Envelope
if
err
:=
packet
.
Decode
(
&
request
);
err
!=
nil
{
glog
.
V
(
logger
.
Warn
)
.
Infof
(
"%v: failed to decode p2p request message: [%v], peer will be disconnected"
,
p
.
peer
,
err
)
return
fmt
.
Errorf
(
"garbage received (p2p request)"
)
}
wh
.
mailServer
.
DeliverMail
(
p
,
&
request
)
}
default
:
// New message types might be implemented in the future versions of Whisper.
...
...
@@ -454,6 +451,9 @@ func (wh *Whisper) add(envelope *Envelope) error {
}
else
{
glog
.
V
(
logger
.
Detail
)
.
Infof
(
"cached whisper envelope [%x]: %v
\n
"
,
envelope
.
Hash
(),
envelope
)
wh
.
postEvent
(
envelope
,
false
)
// notify the local node about the new message
if
wh
.
mailServer
!=
nil
{
wh
.
mailServer
.
Archive
(
envelope
)
}
}
return
nil
}
...
...
whisper/whisperv5/whisper_test.go
View file @
690f6ea1
...
...
@@ -57,12 +57,6 @@ func TestWhisperBasic(t *testing.T) {
if
err
:=
w
.
MarkPeerTrusted
(
peerID
);
err
==
nil
{
t
.
Fatalf
(
"failed MarkPeerTrusted."
)
}
if
err
:=
w
.
RequestHistoricMessages
(
peerID
,
peerID
);
err
==
nil
{
t
.
Fatalf
(
"failed RequestHistoricMessages."
)
}
if
err
:=
w
.
SendP2PMessage
(
peerID
,
nil
);
err
==
nil
{
t
.
Fatalf
(
"failed SendP2PMessage."
)
}
exist
:=
w
.
HasSymKey
(
"non-existing"
)
if
exist
{
t
.
Fatalf
(
"failed HasSymKey."
)
...
...
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