| 
									
										
										
										
											2017-04-14 10:29:00 +02:00
										 |  |  | // Copyright 2017 The go-ethereum Authors | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | // 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/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // This is a simple Whisper node. It could be used as a stand-alone bootstrap node. | 
					
						
							|  |  |  | // Also, could be used for different test and diagnostics purposes. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package main | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bufio" | 
					
						
							|  |  |  | 	"crypto/ecdsa" | 
					
						
							| 
									
										
										
										
											2018-03-01 16:04:09 +01:00
										 |  |  | 	crand "crypto/rand" | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	"crypto/sha512" | 
					
						
							|  |  |  | 	"encoding/binary" | 
					
						
							|  |  |  | 	"encoding/hex" | 
					
						
							|  |  |  | 	"flag" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 	"io/ioutil" | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	"os" | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 	"path/filepath" | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	"strconv" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/cmd/utils" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/console" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							| 
									
										
										
										
											2017-02-22 14:10:07 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/log" | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/p2p" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/p2p/discover" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/p2p/nat" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/whisper/mailserver" | 
					
						
							| 
									
										
										
										
											2018-02-10 14:35:32 +01:00
										 |  |  | 	whisper "github.com/ethereum/go-ethereum/whisper/whisperv6" | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	"golang.org/x/crypto/pbkdf2" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const quitCommand = "~Q" | 
					
						
							| 
									
										
										
										
											2018-03-01 16:04:09 +01:00
										 |  |  | const entropySize = 32 | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | // singletons | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	server     *p2p.Server | 
					
						
							|  |  |  | 	shh        *whisper.Whisper | 
					
						
							|  |  |  | 	done       chan struct{} | 
					
						
							|  |  |  | 	mailServer mailserver.WMailServer | 
					
						
							| 
									
										
										
										
											2018-03-01 16:04:09 +01:00
										 |  |  | 	entropy    [entropySize]byte | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	input = bufio.NewReader(os.Stdin) | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // encryption | 
					
						
							|  |  |  | var ( | 
					
						
							| 
									
										
										
										
											2018-02-10 14:35:32 +01:00
										 |  |  | 	symKey  []byte | 
					
						
							|  |  |  | 	pub     *ecdsa.PublicKey | 
					
						
							|  |  |  | 	asymKey *ecdsa.PrivateKey | 
					
						
							|  |  |  | 	nodeid  *ecdsa.PrivateKey | 
					
						
							|  |  |  | 	topic   whisper.TopicType | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	asymKeyID    string | 
					
						
							|  |  |  | 	asymFilterID string | 
					
						
							|  |  |  | 	symFilterID  string | 
					
						
							|  |  |  | 	symPass      string | 
					
						
							|  |  |  | 	msPassword   string | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // cmd arguments | 
					
						
							|  |  |  | var ( | 
					
						
							| 
									
										
										
										
											2018-02-26 19:26:36 +01:00
										 |  |  | 	bootstrapMode  = flag.Bool("standalone", false, "boostrap node: don't initiate connection to peers, just wait for incoming connections") | 
					
						
							|  |  |  | 	forwarderMode  = flag.Bool("forwarder", false, "forwarder mode: only forward messages, neither encrypt nor decrypt messages") | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 	mailServerMode = flag.Bool("mailserver", false, "mail server mode: delivers expired messages on demand") | 
					
						
							|  |  |  | 	requestMail    = flag.Bool("mailclient", false, "request expired messages from the bootstrap server") | 
					
						
							|  |  |  | 	asymmetricMode = flag.Bool("asym", false, "use asymmetric encryption") | 
					
						
							|  |  |  | 	generateKey    = flag.Bool("generatekey", false, "generate and show the private key") | 
					
						
							|  |  |  | 	fileExMode     = flag.Bool("fileexchange", false, "file exchange mode") | 
					
						
							| 
									
										
										
										
											2018-03-02 14:54:54 +01:00
										 |  |  | 	fileReader     = flag.Bool("filereader", false, "load and decrypt messages saved as files, display as plain text") | 
					
						
							| 
									
										
										
										
											2018-02-26 13:58:04 +01:00
										 |  |  | 	testMode       = flag.Bool("test", false, "use of predefined parameters for diagnostics (password, etc.)") | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 	echoMode       = flag.Bool("echo", false, "echo mode: prints some arguments for diagnostics") | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-26 21:05:48 +02:00
										 |  |  | 	argVerbosity = flag.Int("verbosity", int(log.LvlError), "log verbosity level") | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	argTTL       = flag.Uint("ttl", 30, "time-to-live for messages in seconds") | 
					
						
							|  |  |  | 	argWorkTime  = flag.Uint("work", 5, "work time in seconds") | 
					
						
							| 
									
										
										
										
											2017-06-13 11:49:07 +02:00
										 |  |  | 	argMaxSize   = flag.Uint("maxsize", uint(whisper.DefaultMaxMessageSize), "max size of message") | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 	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") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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") | 
					
						
							|  |  |  | 	argDBPath  = flag.String("dbpath", "", "path to the server's DB directory") | 
					
						
							|  |  |  | 	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)") | 
					
						
							|  |  |  | 	argTopic   = flag.String("topic", "", "topic in hexadecimal format (e.g. 70a4beef)") | 
					
						
							| 
									
										
										
										
											2018-02-26 13:58:04 +01:00
										 |  |  | 	argSaveDir = flag.String("savedir", "", "directory where all incoming messages will be saved as files") | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func main() { | 
					
						
							|  |  |  | 	processArgs() | 
					
						
							|  |  |  | 	initialize() | 
					
						
							|  |  |  | 	run() | 
					
						
							| 
									
										
										
										
											2018-03-04 23:30:18 +01:00
										 |  |  | 	shutdown() | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func processArgs() { | 
					
						
							|  |  |  | 	flag.Parse() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(*argIDFile) > 0 { | 
					
						
							|  |  |  | 		var err error | 
					
						
							|  |  |  | 		nodeid, err = crypto.LoadECDSA(*argIDFile) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2017-02-22 17:22:50 +02:00
										 |  |  | 			utils.Fatalf("Failed to load file [%s]: %s.", *argIDFile, err) | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const enodePrefix = "enode://" | 
					
						
							|  |  |  | 	if len(*argEnode) > 0 { | 
					
						
							|  |  |  | 		if (*argEnode)[:len(enodePrefix)] != enodePrefix { | 
					
						
							|  |  |  | 			*argEnode = enodePrefix + *argEnode | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(*argTopic) > 0 { | 
					
						
							|  |  |  | 		x, err := hex.DecodeString(*argTopic) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2017-02-22 17:22:50 +02:00
										 |  |  | 			utils.Fatalf("Failed to parse the topic: %s", err) | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-04-26 21:05:48 +02:00
										 |  |  | 		topic = whisper.BytesToTopic(x) | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if *asymmetricMode && len(*argPub) > 0 { | 
					
						
							| 
									
										
										
										
											2018-06-12 15:26:08 +02:00
										 |  |  | 		var err error | 
					
						
							|  |  |  | 		if pub, err = crypto.UnmarshalPubkey(common.FromHex(*argPub)); err != nil { | 
					
						
							| 
									
										
										
										
											2017-02-22 17:22:50 +02:00
										 |  |  | 			utils.Fatalf("invalid public key") | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 	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") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	if *echoMode { | 
					
						
							|  |  |  | 		echo() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func echo() { | 
					
						
							|  |  |  | 	fmt.Printf("ttl = %d \n", *argTTL) | 
					
						
							|  |  |  | 	fmt.Printf("workTime = %d \n", *argWorkTime) | 
					
						
							|  |  |  | 	fmt.Printf("pow = %f \n", *argPoW) | 
					
						
							|  |  |  | 	fmt.Printf("mspow = %f \n", *argServerPoW) | 
					
						
							|  |  |  | 	fmt.Printf("ip = %s \n", *argIP) | 
					
						
							|  |  |  | 	fmt.Printf("pub = %s \n", common.ToHex(crypto.FromECDSAPub(pub))) | 
					
						
							|  |  |  | 	fmt.Printf("idfile = %s \n", *argIDFile) | 
					
						
							|  |  |  | 	fmt.Printf("dbpath = %s \n", *argDBPath) | 
					
						
							|  |  |  | 	fmt.Printf("boot = %s \n", *argEnode) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func initialize() { | 
					
						
							| 
									
										
										
										
											2017-02-23 19:31:13 +01:00
										 |  |  | 	log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(*argVerbosity), log.StreamHandler(os.Stderr, log.TerminalFormat(false)))) | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	done = make(chan struct{}) | 
					
						
							|  |  |  | 	var peers []*discover.Node | 
					
						
							|  |  |  | 	var err error | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if *generateKey { | 
					
						
							|  |  |  | 		key, err := crypto.GenerateKey() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2017-02-22 17:22:50 +02:00
										 |  |  | 			utils.Fatalf("Failed to generate private key: %s", err) | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		k := hex.EncodeToString(crypto.FromECDSA(key)) | 
					
						
							|  |  |  | 		fmt.Printf("Random private key: %s \n", k) | 
					
						
							|  |  |  | 		os.Exit(0) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if *testMode { | 
					
						
							| 
									
										
										
										
											2017-02-23 09:41:47 +01:00
										 |  |  | 		symPass = "wwww" // ascii code: 0x77777777 | 
					
						
							| 
									
										
										
										
											2017-04-28 11:57:15 +02:00
										 |  |  | 		msPassword = "wwww" | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if *bootstrapMode { | 
					
						
							|  |  |  | 		if len(*argIP) == 0 { | 
					
						
							|  |  |  | 			argIP = scanLineA("Please enter your IP and port (e.g. 127.0.0.1:30348): ") | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-06 23:37:43 +01:00
										 |  |  | 	} else if *fileReader { | 
					
						
							|  |  |  | 		*bootstrapMode = true | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		if len(*argEnode) == 0 { | 
					
						
							|  |  |  | 			argEnode = scanLineA("Please enter the peer's enode: ") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		peer := discover.MustParseNode(*argEnode) | 
					
						
							|  |  |  | 		peers = append(peers, peer) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-06 23:37:43 +01:00
										 |  |  | 	if *mailServerMode { | 
					
						
							|  |  |  | 		if len(msPassword) == 0 { | 
					
						
							|  |  |  | 			msPassword, err = console.Stdin.PromptPassword("Please enter the Mail Server password: ") | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				utils.Fatalf("Failed to read Mail Server password: %s", err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-13 11:49:07 +02:00
										 |  |  | 	cfg := &whisper.Config{ | 
					
						
							|  |  |  | 		MaxMessageSize:     uint32(*argMaxSize), | 
					
						
							|  |  |  | 		MinimumAcceptedPOW: *argPoW, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-06 23:37:43 +01:00
										 |  |  | 	shh = whisper.New(cfg) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 	if *argPoW != whisper.DefaultMinimumPoW { | 
					
						
							|  |  |  | 		err := shh.SetMinimumPoW(*argPoW) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			utils.Fatalf("Failed to set PoW: %s", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-13 11:49:07 +02:00
										 |  |  | 	if uint32(*argMaxSize) != whisper.DefaultMaxMessageSize { | 
					
						
							|  |  |  | 		err := shh.SetMaxMessageSize(uint32(*argMaxSize)) | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			utils.Fatalf("Failed to set max message size: %s", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	asymKeyID, err = shh.NewKeyPair() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		utils.Fatalf("Failed to generate a new key pair: %s", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	asymKey, err = shh.GetPrivateKey(asymKeyID) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		utils.Fatalf("Failed to retrieve a new key pair: %s", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	if nodeid == nil { | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 		tmpID, err := shh.NewKeyPair() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			utils.Fatalf("Failed to generate a new key pair: %s", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		nodeid, err = shh.GetPrivateKey(tmpID) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			utils.Fatalf("Failed to retrieve a new key pair: %s", err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-13 13:15:20 +01:00
										 |  |  | 	maxPeers := 80 | 
					
						
							|  |  |  | 	if *bootstrapMode { | 
					
						
							|  |  |  | 		maxPeers = 800 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-04 23:30:18 +01:00
										 |  |  | 	_, err = crand.Read(entropy[:]) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		utils.Fatalf("crypto/rand failed: %s", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if *mailServerMode { | 
					
						
							|  |  |  | 		shh.RegisterServer(&mailServer) | 
					
						
							| 
									
										
										
										
											2018-05-04 11:10:18 +02:00
										 |  |  | 		if err := mailServer.Init(shh, *argDBPath, msPassword, *argServerPoW); err != nil { | 
					
						
							|  |  |  | 			utils.Fatalf("Failed to init MailServer: %s", err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-04 23:30:18 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	server = &p2p.Server{ | 
					
						
							|  |  |  | 		Config: p2p.Config{ | 
					
						
							|  |  |  | 			PrivateKey:     nodeid, | 
					
						
							| 
									
										
										
										
											2017-02-13 13:15:20 +01:00
										 |  |  | 			MaxPeers:       maxPeers, | 
					
						
							| 
									
										
										
										
											2018-02-15 13:43:48 +01:00
										 |  |  | 			Name:           common.MakeName("wnode", "6.0"), | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 			Protocols:      shh.Protocols(), | 
					
						
							|  |  |  | 			ListenAddr:     *argIP, | 
					
						
							|  |  |  | 			NAT:            nat.Any(), | 
					
						
							|  |  |  | 			BootstrapNodes: peers, | 
					
						
							|  |  |  | 			StaticNodes:    peers, | 
					
						
							|  |  |  | 			TrustedNodes:   peers, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-04 23:30:18 +01:00
										 |  |  | func startServer() error { | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	err := server.Start() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2018-03-04 23:30:18 +01:00
										 |  |  | 		fmt.Printf("Failed to start Whisper peer: %s.", err) | 
					
						
							|  |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fmt.Printf("my public key: %s \n", common.ToHex(crypto.FromECDSAPub(&asymKey.PublicKey))) | 
					
						
							|  |  |  | 	fmt.Println(server.NodeInfo().Enode) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if *bootstrapMode { | 
					
						
							|  |  |  | 		configureNode() | 
					
						
							|  |  |  | 		fmt.Println("Bootstrap Whisper node started") | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		fmt.Println("Whisper node started") | 
					
						
							|  |  |  | 		// first see if we can establish connection, then ask for user input | 
					
						
							|  |  |  | 		waitForConnection(true) | 
					
						
							|  |  |  | 		configureNode() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-06 23:37:43 +01:00
										 |  |  | 	if *fileExMode { | 
					
						
							|  |  |  | 		fmt.Printf("Please type the file name to be send. To quit type: '%s'\n", quitCommand) | 
					
						
							|  |  |  | 	} else if *fileReader { | 
					
						
							|  |  |  | 		fmt.Printf("Please type the file name to be decrypted. To quit type: '%s'\n", quitCommand) | 
					
						
							|  |  |  | 	} else if !*forwarderMode { | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 		fmt.Printf("Please type the message. To quit type: '%s'\n", quitCommand) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-03-04 23:30:18 +01:00
										 |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func configureNode() { | 
					
						
							|  |  |  | 	var err error | 
					
						
							|  |  |  | 	var p2pAccept bool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if *forwarderMode { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if *asymmetricMode { | 
					
						
							|  |  |  | 		if len(*argPub) == 0 { | 
					
						
							|  |  |  | 			s := scanLine("Please enter the peer's public key: ") | 
					
						
							| 
									
										
										
										
											2017-04-26 21:05:48 +02:00
										 |  |  | 			b := common.FromHex(s) | 
					
						
							|  |  |  | 			if b == nil { | 
					
						
							|  |  |  | 				utils.Fatalf("Error: can not convert hexadecimal string") | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-06-12 15:26:08 +02:00
										 |  |  | 			if pub, err = crypto.UnmarshalPubkey(b); err != nil { | 
					
						
							|  |  |  | 				utils.Fatalf("Error: invalid peer public key") | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if *requestMail { | 
					
						
							|  |  |  | 		p2pAccept = true | 
					
						
							|  |  |  | 		if len(msPassword) == 0 { | 
					
						
							|  |  |  | 			msPassword, err = console.Stdin.PromptPassword("Please enter the Mail Server password: ") | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							| 
									
										
										
										
											2017-02-22 17:22:50 +02:00
										 |  |  | 				utils.Fatalf("Failed to read Mail Server password: %s", err) | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-23 09:41:47 +01:00
										 |  |  | 	if !*asymmetricMode && !*forwarderMode { | 
					
						
							|  |  |  | 		if len(symPass) == 0 { | 
					
						
							| 
									
										
										
										
											2017-04-28 11:57:15 +02:00
										 |  |  | 			symPass, err = console.Stdin.PromptPassword("Please enter the password for symmetric encryption: ") | 
					
						
							| 
									
										
										
										
											2017-02-23 09:41:47 +01:00
										 |  |  | 			if err != nil { | 
					
						
							| 
									
										
										
										
											2017-02-22 17:22:50 +02:00
										 |  |  | 				utils.Fatalf("Failed to read passphrase: %v", err) | 
					
						
							| 
									
										
										
										
											2017-02-23 09:41:47 +01:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 		symKeyID, err := shh.AddSymKeyFromPassword(symPass) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			utils.Fatalf("Failed to create symmetric key: %s", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		symKey, err = shh.GetSymKey(symKeyID) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			utils.Fatalf("Failed to save symmetric key: %s", err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 		if len(*argTopic) == 0 { | 
					
						
							| 
									
										
										
										
											2017-02-23 09:41:47 +01:00
										 |  |  | 			generateTopic([]byte(symPass)) | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-04-28 11:57:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		fmt.Printf("Filter is configured for the topic: %x \n", topic) | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if *mailServerMode { | 
					
						
							|  |  |  | 		if len(*argDBPath) == 0 { | 
					
						
							|  |  |  | 			argDBPath = scanLineA("Please enter the path to DB file: ") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-10 14:35:32 +01:00
										 |  |  | 	symFilter := whisper.Filter{ | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 		KeySym:   symKey, | 
					
						
							| 
									
										
										
										
											2018-02-10 14:35:32 +01:00
										 |  |  | 		Topics:   [][]byte{topic[:]}, | 
					
						
							|  |  |  | 		AllowP2P: p2pAccept, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	symFilterID, err = shh.Subscribe(&symFilter) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		utils.Fatalf("Failed to install filter: %s", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	asymFilter := whisper.Filter{ | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 		KeyAsym:  asymKey, | 
					
						
							| 
									
										
										
										
											2017-04-26 21:05:48 +02:00
										 |  |  | 		Topics:   [][]byte{topic[:]}, | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 		AllowP2P: p2pAccept, | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-02-10 14:35:32 +01:00
										 |  |  | 	asymFilterID, err = shh.Subscribe(&asymFilter) | 
					
						
							| 
									
										
										
										
											2017-02-23 09:41:47 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		utils.Fatalf("Failed to install filter: %s", err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-23 09:41:47 +01:00
										 |  |  | func generateTopic(password []byte) { | 
					
						
							| 
									
										
										
										
											2017-04-26 21:05:48 +02:00
										 |  |  | 	x := pbkdf2.Key(password, password, 4096, 128, sha512.New) | 
					
						
							| 
									
										
										
										
											2017-02-23 09:41:47 +01:00
										 |  |  | 	for i := 0; i < len(x); i++ { | 
					
						
							|  |  |  | 		topic[i%whisper.TopicLength] ^= x[i] | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func waitForConnection(timeout bool) { | 
					
						
							|  |  |  | 	var cnt int | 
					
						
							|  |  |  | 	var connected bool | 
					
						
							|  |  |  | 	for !connected { | 
					
						
							|  |  |  | 		time.Sleep(time.Millisecond * 50) | 
					
						
							|  |  |  | 		connected = server.PeerCount() > 0 | 
					
						
							|  |  |  | 		if timeout { | 
					
						
							|  |  |  | 			cnt++ | 
					
						
							|  |  |  | 			if cnt > 1000 { | 
					
						
							| 
									
										
										
										
											2017-02-22 17:22:50 +02:00
										 |  |  | 				utils.Fatalf("Timeout expired, failed to connect") | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fmt.Println("Connected to peer.") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func run() { | 
					
						
							| 
									
										
										
										
											2018-03-04 23:30:18 +01:00
										 |  |  | 	err := startServer() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	defer server.Stop() | 
					
						
							|  |  |  | 	shh.Start(nil) | 
					
						
							|  |  |  | 	defer shh.Stop() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !*forwarderMode { | 
					
						
							|  |  |  | 		go messageLoop() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if *requestMail { | 
					
						
							|  |  |  | 		requestExpiredMessagesLoop() | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 	} else if *fileExMode { | 
					
						
							|  |  |  | 		sendFilesLoop() | 
					
						
							| 
									
										
										
										
											2018-03-02 14:54:54 +01:00
										 |  |  | 	} else if *fileReader { | 
					
						
							|  |  |  | 		fileReaderLoop() | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		sendLoop() | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-03-04 23:30:18 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-03 21:37:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-04 23:30:18 +01:00
										 |  |  | func shutdown() { | 
					
						
							| 
									
										
										
										
											2018-03-03 21:37:16 +01:00
										 |  |  | 	close(done) | 
					
						
							| 
									
										
										
										
											2018-03-04 23:30:18 +01:00
										 |  |  | 	mailServer.Close() | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func sendLoop() { | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		s := scanLine("") | 
					
						
							|  |  |  | 		if s == quitCommand { | 
					
						
							|  |  |  | 			fmt.Println("Quit command received") | 
					
						
							| 
									
										
										
										
											2018-03-03 21:37:16 +01:00
										 |  |  | 			return | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		sendMsg([]byte(s)) | 
					
						
							|  |  |  | 		if *asymmetricMode { | 
					
						
							|  |  |  | 			// print your own message for convenience, | 
					
						
							|  |  |  | 			// because in asymmetric mode it is impossible to decrypt it | 
					
						
							| 
									
										
										
										
											2017-02-23 09:41:47 +01:00
										 |  |  | 			timestamp := time.Now().Unix() | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 			from := crypto.PubkeyToAddress(asymKey.PublicKey) | 
					
						
							| 
									
										
										
										
											2017-02-23 09:41:47 +01:00
										 |  |  | 			fmt.Printf("\n%d <%x>: %s\n", timestamp, from, s) | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | func sendFilesLoop() { | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		s := scanLine("") | 
					
						
							|  |  |  | 		if s == quitCommand { | 
					
						
							|  |  |  | 			fmt.Println("Quit command received") | 
					
						
							| 
									
										
										
										
											2018-03-03 21:37:16 +01:00
										 |  |  | 			return | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		b, err := ioutil.ReadFile(s) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			fmt.Printf(">>> Error: %s \n", err) | 
					
						
							|  |  |  | 		} 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) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-02 14:54:54 +01:00
										 |  |  | func fileReaderLoop() { | 
					
						
							|  |  |  | 	watcher1 := shh.GetFilter(symFilterID) | 
					
						
							|  |  |  | 	watcher2 := shh.GetFilter(asymFilterID) | 
					
						
							|  |  |  | 	if watcher1 == nil && watcher2 == nil { | 
					
						
							|  |  |  | 		fmt.Println("Error: neither symmetric nor asymmetric filter is installed") | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		s := scanLine("") | 
					
						
							|  |  |  | 		if s == quitCommand { | 
					
						
							|  |  |  | 			fmt.Println("Quit command received") | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		raw, err := ioutil.ReadFile(s) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			fmt.Printf(">>> Error: %s \n", err) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			env := whisper.Envelope{Data: raw} // the topic is zero | 
					
						
							|  |  |  | 			msg := env.Open(watcher1)          // force-open envelope regardless of the topic | 
					
						
							|  |  |  | 			if msg == nil { | 
					
						
							|  |  |  | 				msg = env.Open(watcher2) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if msg == nil { | 
					
						
							|  |  |  | 				fmt.Printf(">>> Error: failed to decrypt the message \n") | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				printMessageInfo(msg) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | func scanLine(prompt string) string { | 
					
						
							|  |  |  | 	if len(prompt) > 0 { | 
					
						
							|  |  |  | 		fmt.Print(prompt) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	txt, err := input.ReadString('\n') | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-02-22 17:22:50 +02:00
										 |  |  | 		utils.Fatalf("input error: %s", err) | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	txt = strings.TrimRight(txt, "\n\r") | 
					
						
							|  |  |  | 	return txt | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func scanLineA(prompt string) *string { | 
					
						
							|  |  |  | 	s := scanLine(prompt) | 
					
						
							|  |  |  | 	return &s | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func scanUint(prompt string) uint32 { | 
					
						
							|  |  |  | 	s := scanLine(prompt) | 
					
						
							|  |  |  | 	i, err := strconv.Atoi(s) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-02-22 17:22:50 +02:00
										 |  |  | 		utils.Fatalf("Fail to parse the lower time limit: %s", err) | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return uint32(i) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | func sendMsg(payload []byte) common.Hash { | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	params := whisper.MessageParams{ | 
					
						
							|  |  |  | 		Src:      asymKey, | 
					
						
							|  |  |  | 		Dst:      pub, | 
					
						
							|  |  |  | 		KeySym:   symKey, | 
					
						
							|  |  |  | 		Payload:  payload, | 
					
						
							| 
									
										
										
										
											2017-04-26 21:05:48 +02:00
										 |  |  | 		Topic:    topic, | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 		TTL:      uint32(*argTTL), | 
					
						
							|  |  |  | 		PoW:      *argPoW, | 
					
						
							|  |  |  | 		WorkTime: uint32(*argWorkTime), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-26 21:05:48 +02:00
										 |  |  | 	msg, err := whisper.NewSentMessage(¶ms) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		utils.Fatalf("failed to create new message: %s", err) | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-03-06 23:37:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	envelope, err := msg.Wrap(¶ms) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		fmt.Printf("failed to seal message: %v \n", err) | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 		return common.Hash{} | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = shh.Send(envelope) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		fmt.Printf("failed to send message: %v \n", err) | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 		return common.Hash{} | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return envelope.Hash() | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func messageLoop() { | 
					
						
							| 
									
										
										
										
											2018-02-10 14:35:32 +01:00
										 |  |  | 	sf := shh.GetFilter(symFilterID) | 
					
						
							|  |  |  | 	if sf == nil { | 
					
						
							|  |  |  | 		utils.Fatalf("symmetric filter is not installed") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	af := shh.GetFilter(asymFilterID) | 
					
						
							|  |  |  | 	if af == nil { | 
					
						
							|  |  |  | 		utils.Fatalf("asymmetric filter is not installed") | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ticker := time.NewTicker(time.Millisecond * 50) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		select { | 
					
						
							|  |  |  | 		case <-ticker.C: | 
					
						
							| 
									
										
										
										
											2018-02-26 13:58:04 +01:00
										 |  |  | 			m1 := sf.Retrieve() | 
					
						
							|  |  |  | 			m2 := af.Retrieve() | 
					
						
							|  |  |  | 			messages := append(m1, m2...) | 
					
						
							| 
									
										
										
										
											2018-02-10 14:35:32 +01:00
										 |  |  | 			for _, msg := range messages { | 
					
						
							| 
									
										
										
										
											2018-03-06 23:37:43 +01:00
										 |  |  | 				reportedOnce := false | 
					
						
							|  |  |  | 				if !*fileExMode && len(msg.Payload) <= 2048 { | 
					
						
							|  |  |  | 					printMessageInfo(msg) | 
					
						
							|  |  |  | 					reportedOnce = true | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-26 19:26:36 +01:00
										 |  |  | 				// All messages are saved upon specifying argSaveDir. | 
					
						
							|  |  |  | 				// fileExMode only specifies how messages are displayed on the console after they are saved. | 
					
						
							|  |  |  | 				// if fileExMode == true, only the hashes are displayed, since messages might be too big. | 
					
						
							| 
									
										
										
										
											2018-02-26 13:58:04 +01:00
										 |  |  | 				if len(*argSaveDir) > 0 { | 
					
						
							| 
									
										
										
										
											2018-03-06 23:37:43 +01:00
										 |  |  | 					writeMessageToFile(*argSaveDir, msg, !reportedOnce) | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		case <-done: | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func printMessageInfo(msg *whisper.ReceivedMessage) { | 
					
						
							|  |  |  | 	timestamp := fmt.Sprintf("%d", msg.Sent) // unix timestamp for diagnostics | 
					
						
							|  |  |  | 	text := string(msg.Payload) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var address common.Address | 
					
						
							|  |  |  | 	if msg.Src != nil { | 
					
						
							|  |  |  | 		address = crypto.PubkeyToAddress(*msg.Src) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if whisper.IsPubKeyEqual(msg.Src, &asymKey.PublicKey) { | 
					
						
							|  |  |  | 		fmt.Printf("\n%s <%x>: %s\n", timestamp, address, text) // message from myself | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		fmt.Printf("\n%s [%x]: %s\n", timestamp, address, text) // message from a peer | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-06 23:37:43 +01:00
										 |  |  | func writeMessageToFile(dir string, msg *whisper.ReceivedMessage, show bool) { | 
					
						
							|  |  |  | 	if len(dir) == 0 { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 	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) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-06 23:37:43 +01:00
										 |  |  | 	env := shh.GetEnvelope(msg.EnvelopeHash) | 
					
						
							|  |  |  | 	if env == nil { | 
					
						
							|  |  |  | 		fmt.Printf("\nUnexpected error: envelope not found: %x\n", msg.EnvelopeHash) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-01 09:34:46 +01:00
										 |  |  | 	// this is a sample code; uncomment if you don't want to save your own messages. | 
					
						
							|  |  |  | 	//if whisper.IsPubKeyEqual(msg.Src, &asymKey.PublicKey) { | 
					
						
							|  |  |  | 	//	fmt.Printf("\n%s <%x>: message from myself received, not saved: '%s'\n", timestamp, address, name) | 
					
						
							|  |  |  | 	//	return | 
					
						
							|  |  |  | 	//} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-06 23:37:43 +01:00
										 |  |  | 	fullpath := filepath.Join(dir, name) | 
					
						
							|  |  |  | 	err := ioutil.WriteFile(fullpath, env.Data, 0644) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		fmt.Printf("\n%s {%x}: message received but not saved: %s\n", timestamp, address, err) | 
					
						
							|  |  |  | 	} else if show { | 
					
						
							|  |  |  | 		fmt.Printf("\n%s {%x}: message received and saved as '%s' (%d bytes)\n", timestamp, address, name, len(env.Data)) | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | func requestExpiredMessagesLoop() { | 
					
						
							| 
									
										
										
										
											2018-03-01 16:04:09 +01:00
										 |  |  | 	var key, peerID, bloom []byte | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	var timeLow, timeUpp uint32 | 
					
						
							|  |  |  | 	var t string | 
					
						
							| 
									
										
										
										
											2018-03-01 16:04:09 +01:00
										 |  |  | 	var xt whisper.TopicType | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 	keyID, err := shh.AddSymKeyFromPassword(msPassword) | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-02-22 17:22:50 +02:00
										 |  |  | 		utils.Fatalf("Failed to create symmetric key for mail request: %s", err) | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 	key, err = shh.GetSymKey(keyID) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		utils.Fatalf("Failed to save symmetric key for mail request: %s", err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-01-26 12:45:10 +01:00
										 |  |  | 	peerID = extractIDFromEnode(*argEnode) | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 	shh.AllowP2PMessagesFromPeer(peerID) | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		timeLow = scanUint("Please enter the lower limit of the time range (unix timestamp): ") | 
					
						
							|  |  |  | 		timeUpp = scanUint("Please enter the upper limit of the time range (unix timestamp): ") | 
					
						
							| 
									
										
										
										
											2018-03-06 23:37:43 +01:00
										 |  |  | 		t = scanLine("Enter the topic (hex). Press enter to request all messages, regardless of the topic: ") | 
					
						
							|  |  |  | 		if len(t) == whisper.TopicLength*2 { | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 			x, err := hex.DecodeString(t) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							| 
									
										
										
										
											2018-03-06 23:37:43 +01:00
										 |  |  | 				fmt.Printf("Failed to parse the topic: %s \n", err) | 
					
						
							|  |  |  | 				continue | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			xt = whisper.BytesToTopic(x) | 
					
						
							| 
									
										
										
										
											2018-03-01 16:04:09 +01:00
										 |  |  | 			bloom = whisper.TopicToBloom(xt) | 
					
						
							|  |  |  | 			obfuscateBloom(bloom) | 
					
						
							| 
									
										
										
										
											2018-03-06 23:37:43 +01:00
										 |  |  | 		} else if len(t) == 0 { | 
					
						
							| 
									
										
										
										
											2018-03-01 16:04:09 +01:00
										 |  |  | 			bloom = whisper.MakeFullNodeBloom() | 
					
						
							| 
									
										
										
										
											2018-03-06 23:37:43 +01:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			fmt.Println("Error: topic is invalid, request aborted") | 
					
						
							|  |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-06 23:37:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 		if timeUpp == 0 { | 
					
						
							|  |  |  | 			timeUpp = 0xFFFFFFFF | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-01 16:04:09 +01:00
										 |  |  | 		data := make([]byte, 8, 8+whisper.BloomFilterSize) | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 		binary.BigEndian.PutUint32(data, timeLow) | 
					
						
							|  |  |  | 		binary.BigEndian.PutUint32(data[4:], timeUpp) | 
					
						
							| 
									
										
										
										
											2018-03-01 16:04:09 +01:00
										 |  |  | 		data = append(data, bloom...) | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		var params whisper.MessageParams | 
					
						
							|  |  |  | 		params.PoW = *argServerPoW | 
					
						
							|  |  |  | 		params.Payload = data | 
					
						
							|  |  |  | 		params.KeySym = key | 
					
						
							| 
									
										
										
										
											2018-02-15 13:43:48 +01:00
										 |  |  | 		params.Src = asymKey | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 		params.WorkTime = 5 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-26 21:05:48 +02:00
										 |  |  | 		msg, err := whisper.NewSentMessage(¶ms) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			utils.Fatalf("failed to create new message: %s", err) | 
					
						
							| 
									
										
										
										
											2017-04-09 23:49:22 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 		env, err := msg.Wrap(¶ms) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2017-02-22 17:22:50 +02:00
										 |  |  | 			utils.Fatalf("Wrap failed: %s", err) | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		err = shh.RequestHistoricMessages(peerID, env) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2017-02-22 17:22:50 +02:00
										 |  |  | 			utils.Fatalf("Failed to send P2P message: %s", err) | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		time.Sleep(time.Second * 5) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-26 12:45:10 +01:00
										 |  |  | func extractIDFromEnode(s string) []byte { | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	n, err := discover.ParseNode(s) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-02-22 17:22:50 +02:00
										 |  |  | 		utils.Fatalf("Failed to parse enode: %s", err) | 
					
						
							| 
									
										
										
										
											2017-01-31 11:16:20 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return n.ID[:] | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-01 16:04:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | // obfuscateBloom adds 16 random bits to the the bloom | 
					
						
							|  |  |  | // filter, in order to obfuscate the containing topics. | 
					
						
							|  |  |  | // it does so deterministically within every session. | 
					
						
							|  |  |  | // despite additional bits, it will match on average | 
					
						
							|  |  |  | // 32000 times less messages than full node's bloom filter. | 
					
						
							|  |  |  | func obfuscateBloom(bloom []byte) { | 
					
						
							|  |  |  | 	const half = entropySize / 2 | 
					
						
							|  |  |  | 	for i := 0; i < half; i++ { | 
					
						
							|  |  |  | 		x := int(entropy[i]) | 
					
						
							|  |  |  | 		if entropy[half+i] < 128 { | 
					
						
							|  |  |  | 			x += 256 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		bloom[x/8] = 1 << uint(x%8) // set the bit number X | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |