mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 07:06:42 +00:00
whisper: final update
This commit is contained in:
parent
b26af42b63
commit
c6e0e93672
5 changed files with 94 additions and 18 deletions
|
|
@ -32,6 +32,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/console"
|
"github.com/ethereum/go-ethereum/console"
|
||||||
|
|
@ -80,6 +84,7 @@ var (
|
||||||
asymmetricMode = flag.Bool("a", false, "use asymmetric encryption")
|
asymmetricMode = flag.Bool("a", false, "use asymmetric encryption")
|
||||||
testMode = flag.Bool("t", false, "use of predefined parameters for diagnostics")
|
testMode = flag.Bool("t", false, "use of predefined parameters for diagnostics")
|
||||||
generateKey = flag.Bool("k", false, "generate and show the private key")
|
generateKey = flag.Bool("k", false, "generate and show the private key")
|
||||||
|
fileExMode = flag.Bool("x", false, "file exchange mode")
|
||||||
|
|
||||||
argVerbosity = flag.Int("verbosity", int(log.LvlWarn), "log verbosity level")
|
argVerbosity = flag.Int("verbosity", int(log.LvlWarn), "log verbosity level")
|
||||||
argTTL = flag.Uint("ttl", 30, "time-to-live for messages in seconds")
|
argTTL = flag.Uint("ttl", 30, "time-to-live for messages in seconds")
|
||||||
|
|
@ -87,12 +92,13 @@ var (
|
||||||
argPoW = flag.Float64("pow", whisper.DefaultMinimumPoW, "PoW for normal messages in float format (e.g. 2.7)")
|
argPoW = flag.Float64("pow", whisper.DefaultMinimumPoW, "PoW for normal messages in float format (e.g. 2.7)")
|
||||||
argServerPoW = flag.Float64("mspow", whisper.DefaultMinimumPoW, "PoW requirement for Mail Server request")
|
argServerPoW = flag.Float64("mspow", whisper.DefaultMinimumPoW, "PoW requirement for Mail Server request")
|
||||||
|
|
||||||
argIP = flag.String("ip", "", "IP address and port of this node (e.g. 127.0.0.1:30303)")
|
argIP = flag.String("ip", "", "IP address and port of this node (e.g. 127.0.0.1:30303)")
|
||||||
argPub = flag.String("pub", "", "public key for asymmetric encryption")
|
argPub = flag.String("pub", "", "public key for asymmetric encryption")
|
||||||
argDBPath = flag.String("dbpath", "", "path to the server's DB directory")
|
argDBPath = flag.String("dbpath", "", "path to the server's DB directory")
|
||||||
argIDFile = flag.String("idfile", "", "file name with node id (private key)")
|
argIDFile = flag.String("idfile", "", "file name with node id (private key)")
|
||||||
argEnode = flag.String("boot", "", "bootstrap node you want to connect to (e.g. enode://e454......08d50@52.176.211.200:16428)")
|
argEnode = flag.String("boot", "", "bootstrap node you want to connect to (e.g. enode://e454......08d50@52.176.211.200:16428)")
|
||||||
argTopic = flag.String("topic", "", "topic in hexadecimal format (e.g. 70a4beef)")
|
argTopic = flag.String("topic", "", "topic in hexadecimal format (e.g. 70a4beef)")
|
||||||
|
argSaveDir = flag.String("savedir", "", "directory where incoming messages will be saved as files")
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
@ -134,6 +140,14 @@ func processArgs() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(*argSaveDir) > 0 {
|
||||||
|
if _, err := os.Stat(*argSaveDir); os.IsNotExist(err) {
|
||||||
|
utils.Fatalf("Download directory '%s' does not exist", *argSaveDir)
|
||||||
|
}
|
||||||
|
} else if *fileExMode {
|
||||||
|
utils.Fatalf("Parameter 'savedir' is mandatory for file exchange mode")
|
||||||
|
}
|
||||||
|
|
||||||
if *echoMode {
|
if *echoMode {
|
||||||
echo()
|
echo()
|
||||||
}
|
}
|
||||||
|
|
@ -374,6 +388,8 @@ func run() {
|
||||||
|
|
||||||
if *requestMail {
|
if *requestMail {
|
||||||
requestExpiredMessagesLoop()
|
requestExpiredMessagesLoop()
|
||||||
|
} else if *fileExMode {
|
||||||
|
sendFilesLoop()
|
||||||
} else {
|
} else {
|
||||||
sendLoop()
|
sendLoop()
|
||||||
}
|
}
|
||||||
|
|
@ -399,6 +415,31 @@ func sendLoop() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sendFilesLoop() {
|
||||||
|
for {
|
||||||
|
s := scanLine("")
|
||||||
|
if s == quitCommand {
|
||||||
|
fmt.Println("Quit command received")
|
||||||
|
close(done)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b, err := ioutil.ReadFile(s)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf(">>> Error: %s \n", err)
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
h := sendMsg(b)
|
||||||
|
if (h == common.Hash{}) {
|
||||||
|
fmt.Printf(">>> Error: message was not sent \n")
|
||||||
|
} else {
|
||||||
|
timestamp := time.Now().Unix()
|
||||||
|
from := crypto.PubkeyToAddress(asymKey.PublicKey)
|
||||||
|
fmt.Printf("\n%d <%x>: sent message with hash %x\n", timestamp, from, h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func scanLine(prompt string) string {
|
func scanLine(prompt string) string {
|
||||||
if len(prompt) > 0 {
|
if len(prompt) > 0 {
|
||||||
fmt.Print(prompt)
|
fmt.Print(prompt)
|
||||||
|
|
@ -425,7 +466,7 @@ func scanUint(prompt string) uint32 {
|
||||||
return uint32(i)
|
return uint32(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendMsg(payload []byte) {
|
func sendMsg(payload []byte) common.Hash {
|
||||||
params := whisper.MessageParams{
|
params := whisper.MessageParams{
|
||||||
Src: asymKey,
|
Src: asymKey,
|
||||||
Dst: pub,
|
Dst: pub,
|
||||||
|
|
@ -441,13 +482,16 @@ func sendMsg(payload []byte) {
|
||||||
envelope, err := msg.Wrap(¶ms)
|
envelope, err := msg.Wrap(¶ms)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("failed to seal message: %v \n", err)
|
fmt.Printf("failed to seal message: %v \n", err)
|
||||||
return
|
return common.Hash{}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = shh.Send(envelope)
|
err = shh.Send(envelope)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("failed to send message: %v \n", err)
|
fmt.Printf("failed to send message: %v \n", err)
|
||||||
|
return common.Hash{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return envelope.Hash()
|
||||||
}
|
}
|
||||||
|
|
||||||
func messageLoop() {
|
func messageLoop() {
|
||||||
|
|
@ -463,7 +507,11 @@ func messageLoop() {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
messages := f.Retrieve()
|
messages := f.Retrieve()
|
||||||
for _, msg := range messages {
|
for _, msg := range messages {
|
||||||
printMessageInfo(msg)
|
if *fileExMode {
|
||||||
|
saveMessageInFile(msg)
|
||||||
|
} else {
|
||||||
|
printMessageInfo(msg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case <-done:
|
case <-done:
|
||||||
return
|
return
|
||||||
|
|
@ -487,6 +535,29 @@ func printMessageInfo(msg *whisper.ReceivedMessage) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func saveMessageInFile(msg *whisper.ReceivedMessage) {
|
||||||
|
timestamp := fmt.Sprintf("%d", msg.Sent)
|
||||||
|
name := fmt.Sprintf("%x", msg.EnvelopeHash)
|
||||||
|
|
||||||
|
var address common.Address
|
||||||
|
if msg.Src != nil {
|
||||||
|
address = crypto.PubkeyToAddress(*msg.Src)
|
||||||
|
}
|
||||||
|
|
||||||
|
if whisper.IsPubKeyEqual(msg.Src, &asymKey.PublicKey) {
|
||||||
|
// message from myself: don't save, only report
|
||||||
|
fmt.Printf("\n%s <%x>: message received: '%s'\n", timestamp, address, name)
|
||||||
|
} else {
|
||||||
|
fullpath := filepath.Join(*argSaveDir, name)
|
||||||
|
err := ioutil.WriteFile(fullpath, msg.Payload, 0644)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("\n%s [%x]: message received but not saved: %s\n", timestamp, address, err)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("\n%s [%x]: message received and saved as '%s'\n", timestamp, address, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func requestExpiredMessagesLoop() {
|
func requestExpiredMessagesLoop() {
|
||||||
var key, peerID []byte
|
var key, peerID []byte
|
||||||
var timeLow, timeUpp uint32
|
var timeLow, timeUpp uint32
|
||||||
|
|
@ -502,7 +573,7 @@ func requestExpiredMessagesLoop() {
|
||||||
utils.Fatalf("Failed to save symmetric key for mail request: %s", err)
|
utils.Fatalf("Failed to save symmetric key for mail request: %s", err)
|
||||||
}
|
}
|
||||||
peerID = extractIdFromEnode(*argEnode)
|
peerID = extractIdFromEnode(*argEnode)
|
||||||
shh.MarkPeerTrusted(peerID)
|
shh.AllowP2PMessagesFromPeer(peerID)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
timeLow = scanUint("Please enter the lower limit of the time range (unix timestamp): ")
|
timeLow = scanUint("Please enter the lower limit of the time range (unix timestamp): ")
|
||||||
|
|
|
||||||
|
|
@ -86,13 +86,19 @@ func (api *PublicWhisperAPI) SetMinimumPoW(val float64) error {
|
||||||
return api.whisper.SetMinimumPoW(val)
|
return api.whisper.SetMinimumPoW(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarkPeerTrusted marks specific peer trusted, which will allow it
|
// AllowP2PMessagesFromPeer marks specific peer trusted, which will allow it
|
||||||
// to send historic (expired) messages.
|
// to send historic (expired) messages.
|
||||||
func (api *PublicWhisperAPI) MarkPeerTrusted(peerID hexutil.Bytes) error {
|
func (api *PublicWhisperAPI) AllowP2PMessagesFromPeer(enode string) error {
|
||||||
if api.whisper == nil {
|
if api.whisper == nil {
|
||||||
return whisperOffLineErr
|
return whisperOffLineErr
|
||||||
}
|
}
|
||||||
return api.whisper.MarkPeerTrusted(peerID)
|
n, err := discover.ParseNode(enode)
|
||||||
|
if err != nil {
|
||||||
|
info := "Failed to parse enode of trusted peer: " + err.Error()
|
||||||
|
log.Error(info)
|
||||||
|
return errors.New(info)
|
||||||
|
}
|
||||||
|
return api.whisper.AllowP2PMessagesFromPeer(n.ID[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestHistoricMessages requests the peer to deliver the old (expired) messages.
|
// RequestHistoricMessages requests the peer to deliver the old (expired) messages.
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ const (
|
||||||
keyIdSize = 32
|
keyIdSize = 32
|
||||||
|
|
||||||
DefaultMaxMessageLength = 1024 * 1024
|
DefaultMaxMessageLength = 1024 * 1024
|
||||||
DefaultMinimumPoW = 10.0 // todo: review after testing.
|
DefaultMinimumPoW = 2.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
|
||||||
padSizeLimitUpper = 256 // just an arbitrary number, could be changed without losing compatibility
|
padSizeLimitUpper = 256 // just an arbitrary number, could be changed without losing compatibility
|
||||||
|
|
|
||||||
|
|
@ -77,8 +77,7 @@ type Whisper struct {
|
||||||
// Param s should be passed if you want to implement mail server, otherwise nil.
|
// Param s should be passed if you want to implement mail server, otherwise nil.
|
||||||
func New() *Whisper {
|
func New() *Whisper {
|
||||||
whisper := &Whisper{
|
whisper := &Whisper{
|
||||||
privateKeys: make(map[string]*ecdsa.PrivateKey),
|
privateKeys: make(map[string]*ecdsa.PrivateKey),
|
||||||
//identities: 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),
|
||||||
expirations: make(map[uint32]*set.SetNonTS),
|
expirations: make(map[uint32]*set.SetNonTS),
|
||||||
|
|
@ -158,7 +157,7 @@ func (w *Whisper) getPeer(peerID []byte) (*Peer, error) {
|
||||||
|
|
||||||
// MarkPeerTrusted marks specific peer trusted, which will allow it
|
// MarkPeerTrusted marks specific peer trusted, which will allow it
|
||||||
// to send historic (expired) messages.
|
// to send historic (expired) messages.
|
||||||
func (w *Whisper) MarkPeerTrusted(peerID []byte) error {
|
func (w *Whisper) AllowP2PMessagesFromPeer(peerID []byte) error {
|
||||||
p, err := w.getPeer(peerID)
|
p, err := w.getPeer(peerID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ func TestWhisperBasic(t *testing.T) {
|
||||||
if peer != nil {
|
if peer != nil {
|
||||||
t.Fatal("found peer for random key.")
|
t.Fatal("found peer for random key.")
|
||||||
}
|
}
|
||||||
if err := w.MarkPeerTrusted(peerID); err == nil {
|
if err := w.AllowP2PMessagesFromPeer(peerID); err == nil {
|
||||||
t.Fatalf("failed MarkPeerTrusted.")
|
t.Fatalf("failed MarkPeerTrusted.")
|
||||||
}
|
}
|
||||||
exist := w.HasSymKey("non-existing")
|
exist := w.HasSymKey("non-existing")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue