github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/cmd/wnode/main.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:32</date> 10 //</624342607195017216> 11 12 13 //这是一个简单的耳语节点。它可以用作独立的引导节点。 14 //也可用于不同的测试和诊断目的。 15 16 package main 17 18 import ( 19 "bufio" 20 "crypto/ecdsa" 21 crand "crypto/rand" 22 "crypto/sha512" 23 "encoding/binary" 24 "encoding/hex" 25 "flag" 26 "fmt" 27 "io/ioutil" 28 "os" 29 "path/filepath" 30 "strconv" 31 "strings" 32 "time" 33 34 "github.com/ethereum/go-ethereum/cmd/utils" 35 "github.com/ethereum/go-ethereum/common" 36 "github.com/ethereum/go-ethereum/console" 37 "github.com/ethereum/go-ethereum/crypto" 38 "github.com/ethereum/go-ethereum/log" 39 "github.com/ethereum/go-ethereum/p2p" 40 "github.com/ethereum/go-ethereum/p2p/discover" 41 "github.com/ethereum/go-ethereum/p2p/nat" 42 "github.com/ethereum/go-ethereum/whisper/mailserver" 43 whisper "github.com/ethereum/go-ethereum/whisper/whisperv6" 44 "golang.org/x/crypto/pbkdf2" 45 ) 46 47 const quitCommand = "~Q" 48 const entropySize = 32 49 50 //独生子女 51 var ( 52 server *p2p.Server 53 shh *whisper.Whisper 54 done chan struct{} 55 mailServer mailserver.WMailServer 56 entropy [entropySize]byte 57 58 input = bufio.NewReader(os.Stdin) 59 ) 60 61 //加密 62 var ( 63 symKey []byte 64 pub *ecdsa.PublicKey 65 asymKey *ecdsa.PrivateKey 66 nodeid *ecdsa.PrivateKey 67 topic whisper.TopicType 68 69 asymKeyID string 70 asymFilterID string 71 symFilterID string 72 symPass string 73 msPassword string 74 ) 75 76 //CMD参数 77 var ( 78 bootstrapMode = flag.Bool("standalone", false, "boostrap node: don't initiate connection to peers, just wait for incoming connections") 79 forwarderMode = flag.Bool("forwarder", false, "forwarder mode: only forward messages, neither encrypt nor decrypt messages") 80 mailServerMode = flag.Bool("mailserver", false, "mail server mode: delivers expired messages on demand") 81 requestMail = flag.Bool("mailclient", false, "request expired messages from the bootstrap server") 82 asymmetricMode = flag.Bool("asym", false, "use asymmetric encryption") 83 generateKey = flag.Bool("generatekey", false, "generate and show the private key") 84 fileExMode = flag.Bool("fileexchange", false, "file exchange mode") 85 fileReader = flag.Bool("filereader", false, "load and decrypt messages saved as files, display as plain text") 86 testMode = flag.Bool("test", false, "use of predefined parameters for diagnostics (password, etc.)") 87 echoMode = flag.Bool("echo", false, "echo mode: prints some arguments for diagnostics") 88 89 argVerbosity = flag.Int("verbosity", int(log.LvlError), "log verbosity level") 90 argTTL = flag.Uint("ttl", 30, "time-to-live for messages in seconds") 91 argWorkTime = flag.Uint("work", 5, "work time in seconds") 92 argMaxSize = flag.Uint("maxsize", uint(whisper.DefaultMaxMessageSize), "max size of message") 93 argPoW = flag.Float64("pow", whisper.DefaultMinimumPoW, "PoW for normal messages in float format (e.g. 2.7)") 94 argServerPoW = flag.Float64("mspow", whisper.DefaultMinimumPoW, "PoW requirement for Mail Server request") 95 96 argIP = flag.String("ip", "", "IP address and port of this node (e.g. 127.0.0.1:30303)") 97 argPub = flag.String("pub", "", "public key for asymmetric encryption") 98 argDBPath = flag.String("dbpath", "", "path to the server's DB directory") 99 argIDFile = flag.String("idfile", "", "file name with node id (private key)") 100 argEnode = flag.String("boot", "", "bootstrap node you want to connect to (e.g. enode://E454……08D50@52.176.211.200:16428)”) 101 argTopic = flag.String("topic", "", "topic in hexadecimal format (e.g. 70a4beef)") 102 argSaveDir = flag.String("savedir", "", "directory where all incoming messages will be saved as files") 103 ) 104 105 func main() { 106 processArgs() 107 initialize() 108 run() 109 shutdown() 110 } 111 112 func processArgs() { 113 flag.Parse() 114 115 if len(*argIDFile) > 0 { 116 var err error 117 nodeid, err = crypto.LoadECDSA(*argIDFile) 118 if err != nil { 119 utils.Fatalf("Failed to load file [%s]: %s.", *argIDFile, err) 120 } 121 } 122 123 const enodePrefix = "enode://“ 124 if len(*argEnode) > 0 { 125 if (*argEnode)[:len(enodePrefix)] != enodePrefix { 126 *argEnode = enodePrefix + *argEnode 127 } 128 } 129 130 if len(*argTopic) > 0 { 131 x, err := hex.DecodeString(*argTopic) 132 if err != nil { 133 utils.Fatalf("Failed to parse the topic: %s", err) 134 } 135 topic = whisper.BytesToTopic(x) 136 } 137 138 if *asymmetricMode && len(*argPub) > 0 { 139 var err error 140 if pub, err = crypto.UnmarshalPubkey(common.FromHex(*argPub)); err != nil { 141 utils.Fatalf("invalid public key") 142 } 143 } 144 145 if len(*argSaveDir) > 0 { 146 if _, err := os.Stat(*argSaveDir); os.IsNotExist(err) { 147 utils.Fatalf("Download directory '%s' does not exist", *argSaveDir) 148 } 149 } else if *fileExMode { 150 utils.Fatalf("Parameter 'savedir' is mandatory for file exchange mode") 151 } 152 153 if *echoMode { 154 echo() 155 } 156 } 157 158 func echo() { 159 fmt.Printf("ttl = %d \n", *argTTL) 160 fmt.Printf("workTime = %d \n", *argWorkTime) 161 fmt.Printf("pow = %f \n", *argPoW) 162 fmt.Printf("mspow = %f \n", *argServerPoW) 163 fmt.Printf("ip = %s \n", *argIP) 164 fmt.Printf("pub = %s \n", common.ToHex(crypto.FromECDSAPub(pub))) 165 fmt.Printf("idfile = %s \n", *argIDFile) 166 fmt.Printf("dbpath = %s \n", *argDBPath) 167 fmt.Printf("boot = %s \n", *argEnode) 168 } 169 170 func initialize() { 171 log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(*argVerbosity), log.StreamHandler(os.Stderr, log.TerminalFormat(false)))) 172 173 done = make(chan struct{}) 174 var peers []*discover.Node 175 var err error 176 177 if *generateKey { 178 key, err := crypto.GenerateKey() 179 if err != nil { 180 utils.Fatalf("Failed to generate private key: %s", err) 181 } 182 k := hex.EncodeToString(crypto.FromECDSA(key)) 183 fmt.Printf("Random private key: %s \n", k) 184 os.Exit(0) 185 } 186 187 if *testMode { 188 symPass = "wwww" //ASCII码:0x77777777 189 msPassword = "wwww" 190 } 191 192 if *bootstrapMode { 193 if len(*argIP) == 0 { 194 argIP = scanLineA("Please enter your IP and port (e.g. 127.0.0.1:30348): ") 195 } 196 } else if *fileReader { 197 *bootstrapMode = true 198 } else { 199 if len(*argEnode) == 0 { 200 argEnode = scanLineA("Please enter the peer's enode: ") 201 } 202 peer := discover.MustParseNode(*argEnode) 203 peers = append(peers, peer) 204 } 205 206 if *mailServerMode { 207 if len(msPassword) == 0 { 208 msPassword, err = console.Stdin.PromptPassword("Please enter the Mail Server password: ") 209 if err != nil { 210 utils.Fatalf("Failed to read Mail Server password: %s", err) 211 } 212 } 213 } 214 215 cfg := &whisper.Config{ 216 MaxMessageSize: uint32(*argMaxSize), 217 MinimumAcceptedPOW: *argPoW, 218 } 219 220 shh = whisper.New(cfg) 221 222 if *argPoW != whisper.DefaultMinimumPoW { 223 err := shh.SetMinimumPoW(*argPoW) 224 if err != nil { 225 utils.Fatalf("Failed to set PoW: %s", err) 226 } 227 } 228 229 if uint32(*argMaxSize) != whisper.DefaultMaxMessageSize { 230 err := shh.SetMaxMessageSize(uint32(*argMaxSize)) 231 if err != nil { 232 utils.Fatalf("Failed to set max message size: %s", err) 233 } 234 } 235 236 asymKeyID, err = shh.NewKeyPair() 237 if err != nil { 238 utils.Fatalf("Failed to generate a new key pair: %s", err) 239 } 240 241 asymKey, err = shh.GetPrivateKey(asymKeyID) 242 if err != nil { 243 utils.Fatalf("Failed to retrieve a new key pair: %s", err) 244 } 245 246 if nodeid == nil { 247 tmpID, err := shh.NewKeyPair() 248 if err != nil { 249 utils.Fatalf("Failed to generate a new key pair: %s", err) 250 } 251 252 nodeid, err = shh.GetPrivateKey(tmpID) 253 if err != nil { 254 utils.Fatalf("Failed to retrieve a new key pair: %s", err) 255 } 256 } 257 258 maxPeers := 80 259 if *bootstrapMode { 260 maxPeers = 800 261 } 262 263 _, err = crand.Read(entropy[:]) 264 if err != nil { 265 utils.Fatalf("crypto/rand failed: %s", err) 266 } 267 268 if *mailServerMode { 269 shh.RegisterServer(&mailServer) 270 if err := mailServer.Init(shh, *argDBPath, msPassword, *argServerPoW); err != nil { 271 utils.Fatalf("Failed to init MailServer: %s", err) 272 } 273 } 274 275 server = &p2p.Server{ 276 Config: p2p.Config{ 277 PrivateKey: nodeid, 278 MaxPeers: maxPeers, 279 Name: common.MakeName("wnode", "6.0"), 280 Protocols: shh.Protocols(), 281 ListenAddr: *argIP, 282 NAT: nat.Any(), 283 BootstrapNodes: peers, 284 StaticNodes: peers, 285 TrustedNodes: peers, 286 }, 287 } 288 } 289 290 func startServer() error { 291 err := server.Start() 292 if err != nil { 293 fmt.Printf("Failed to start Whisper peer: %s.", err) 294 return err 295 } 296 297 fmt.Printf("my public key: %s \n", common.ToHex(crypto.FromECDSAPub(&asymKey.PublicKey))) 298 fmt.Println(server.NodeInfo().Enode) 299 300 if *bootstrapMode { 301 configureNode() 302 fmt.Println("Bootstrap Whisper node started") 303 } else { 304 fmt.Println("Whisper node started") 305 //首先看看我们是否可以建立连接,然后请求用户输入 306 waitForConnection(true) 307 configureNode() 308 } 309 310 if *fileExMode { 311 fmt.Printf("Please type the file name to be send. To quit type: '%s'\n", quitCommand) 312 } else if *fileReader { 313 fmt.Printf("Please type the file name to be decrypted. To quit type: '%s'\n", quitCommand) 314 } else if !*forwarderMode { 315 fmt.Printf("Please type the message. To quit type: '%s'\n", quitCommand) 316 } 317 return nil 318 } 319 320 func configureNode() { 321 var err error 322 var p2pAccept bool 323 324 if *forwarderMode { 325 return 326 } 327 328 if *asymmetricMode { 329 if len(*argPub) == 0 { 330 s := scanLine("Please enter the peer's public key: ") 331 b := common.FromHex(s) 332 if b == nil { 333 utils.Fatalf("Error: can not convert hexadecimal string") 334 } 335 if pub, err = crypto.UnmarshalPubkey(b); err != nil { 336 utils.Fatalf("Error: invalid peer public key") 337 } 338 } 339 } 340 341 if *requestMail { 342 p2pAccept = true 343 if len(msPassword) == 0 { 344 msPassword, err = console.Stdin.PromptPassword("Please enter the Mail Server password: ") 345 if err != nil { 346 utils.Fatalf("Failed to read Mail Server password: %s", err) 347 } 348 } 349 } 350 351 if !*asymmetricMode && !*forwarderMode { 352 if len(symPass) == 0 { 353 symPass, err = console.Stdin.PromptPassword("Please enter the password for symmetric encryption: ") 354 if err != nil { 355 utils.Fatalf("Failed to read passphrase: %v", err) 356 } 357 } 358 359 symKeyID, err := shh.AddSymKeyFromPassword(symPass) 360 if err != nil { 361 utils.Fatalf("Failed to create symmetric key: %s", err) 362 } 363 symKey, err = shh.GetSymKey(symKeyID) 364 if err != nil { 365 utils.Fatalf("Failed to save symmetric key: %s", err) 366 } 367 if len(*argTopic) == 0 { 368 generateTopic([]byte(symPass)) 369 } 370 371 fmt.Printf("Filter is configured for the topic: %x \n", topic) 372 } 373 374 if *mailServerMode { 375 if len(*argDBPath) == 0 { 376 argDBPath = scanLineA("Please enter the path to DB file: ") 377 } 378 } 379 380 symFilter := whisper.Filter{ 381 KeySym: symKey, 382 Topics: [][]byte{topic[:]}, 383 AllowP2P: p2pAccept, 384 } 385 symFilterID, err = shh.Subscribe(&symFilter) 386 if err != nil { 387 utils.Fatalf("Failed to install filter: %s", err) 388 } 389 390 asymFilter := whisper.Filter{ 391 KeyAsym: asymKey, 392 Topics: [][]byte{topic[:]}, 393 AllowP2P: p2pAccept, 394 } 395 asymFilterID, err = shh.Subscribe(&asymFilter) 396 if err != nil { 397 utils.Fatalf("Failed to install filter: %s", err) 398 } 399 } 400 401 func generateTopic(password []byte) { 402 x := pbkdf2.Key(password, password, 4096, 128, sha512.New) 403 for i := 0; i < len(x); i++ { 404 topic[i%whisper.TopicLength] ^= x[i] 405 } 406 } 407 408 func waitForConnection(timeout bool) { 409 var cnt int 410 var connected bool 411 for !connected { 412 time.Sleep(time.Millisecond * 50) 413 connected = server.PeerCount() > 0 414 if timeout { 415 cnt++ 416 if cnt > 1000 { 417 utils.Fatalf("Timeout expired, failed to connect") 418 } 419 } 420 } 421 422 fmt.Println("Connected to peer.") 423 } 424 425 func run() { 426 err := startServer() 427 if err != nil { 428 return 429 } 430 defer server.Stop() 431 shh.Start(nil) 432 defer shh.Stop() 433 434 if !*forwarderMode { 435 go messageLoop() 436 } 437 438 if *requestMail { 439 requestExpiredMessagesLoop() 440 } else if *fileExMode { 441 sendFilesLoop() 442 } else if *fileReader { 443 fileReaderLoop() 444 } else { 445 sendLoop() 446 } 447 } 448 449 func shutdown() { 450 close(done) 451 mailServer.Close() 452 } 453 454 func sendLoop() { 455 for { 456 s := scanLine("") 457 if s == quitCommand { 458 fmt.Println("Quit command received") 459 return 460 } 461 sendMsg([]byte(s)) 462 if *asymmetricMode { 463 //为方便起见,请打印您自己的消息, 464 //因为在非对称模式下是不可能解密的 465 timestamp := time.Now().Unix() 466 from := crypto.PubkeyToAddress(asymKey.PublicKey) 467 fmt.Printf("\n%d <%x>: %s\n", timestamp, from, s) 468 } 469 } 470 } 471 472 func sendFilesLoop() { 473 for { 474 s := scanLine("") 475 if s == quitCommand { 476 fmt.Println("Quit command received") 477 return 478 } 479 b, err := ioutil.ReadFile(s) 480 if err != nil { 481 fmt.Printf(">>> Error: %s \n", err) 482 } else { 483 h := sendMsg(b) 484 if (h == common.Hash{}) { 485 fmt.Printf(">>> Error: message was not sent \n") 486 } else { 487 timestamp := time.Now().Unix() 488 from := crypto.PubkeyToAddress(asymKey.PublicKey) 489 fmt.Printf("\n%d <%x>: sent message with hash %x\n", timestamp, from, h) 490 } 491 } 492 } 493 } 494 495 func fileReaderLoop() { 496 watcher1 := shh.GetFilter(symFilterID) 497 watcher2 := shh.GetFilter(asymFilterID) 498 if watcher1 == nil && watcher2 == nil { 499 fmt.Println("Error: neither symmetric nor asymmetric filter is installed") 500 return 501 } 502 503 for { 504 s := scanLine("") 505 if s == quitCommand { 506 fmt.Println("Quit command received") 507 return 508 } 509 raw, err := ioutil.ReadFile(s) 510 if err != nil { 511 fmt.Printf(">>> Error: %s \n", err) 512 } else { 513 env := whisper.Envelope{Data: raw} //主题为零 514 msg := env.Open(watcher1) //不管主题如何,都强制打开信封 515 if msg == nil { 516 msg = env.Open(watcher2) 517 } 518 if msg == nil { 519 fmt.Printf(">>> Error: failed to decrypt the message \n") 520 } else { 521 printMessageInfo(msg) 522 } 523 } 524 } 525 } 526 527 func scanLine(prompt string) string { 528 if len(prompt) > 0 { 529 fmt.Print(prompt) 530 } 531 txt, err := input.ReadString('\n') 532 if err != nil { 533 utils.Fatalf("input error: %s", err) 534 } 535 txt = strings.TrimRight(txt, "\n\r") 536 return txt 537 } 538 539 func scanLineA(prompt string) *string { 540 s := scanLine(prompt) 541 return &s 542 } 543 544 func scanUint(prompt string) uint32 { 545 s := scanLine(prompt) 546 i, err := strconv.Atoi(s) 547 if err != nil { 548 utils.Fatalf("Fail to parse the lower time limit: %s", err) 549 } 550 return uint32(i) 551 } 552 553 func sendMsg(payload []byte) common.Hash { 554 params := whisper.MessageParams{ 555 Src: asymKey, 556 Dst: pub, 557 KeySym: symKey, 558 Payload: payload, 559 Topic: topic, 560 TTL: uint32(*argTTL), 561 PoW: *argPoW, 562 WorkTime: uint32(*argWorkTime), 563 } 564 565 msg, err := whisper.NewSentMessage(¶ms) 566 if err != nil { 567 utils.Fatalf("failed to create new message: %s", err) 568 } 569 570 envelope, err := msg.Wrap(¶ms) 571 if err != nil { 572 fmt.Printf("failed to seal message: %v \n", err) 573 return common.Hash{} 574 } 575 576 err = shh.Send(envelope) 577 if err != nil { 578 fmt.Printf("failed to send message: %v \n", err) 579 return common.Hash{} 580 } 581 582 return envelope.Hash() 583 } 584 585 func messageLoop() { 586 sf := shh.GetFilter(symFilterID) 587 if sf == nil { 588 utils.Fatalf("symmetric filter is not installed") 589 } 590 591 af := shh.GetFilter(asymFilterID) 592 if af == nil { 593 utils.Fatalf("asymmetric filter is not installed") 594 } 595 596 ticker := time.NewTicker(time.Millisecond * 50) 597 598 for { 599 select { 600 case <-ticker.C: 601 m1 := sf.Retrieve() 602 m2 := af.Retrieve() 603 messages := append(m1, m2...) 604 for _, msg := range messages { 605 reportedOnce := false 606 if !*fileExMode && len(msg.Payload) <= 2048 { 607 printMessageInfo(msg) 608 reportedOnce = true 609 } 610 611 //在指定argsavedir时保存所有消息。 612 // 613 //如果fileexmode==true,则只显示哈希值,因为消息可能太大。 614 if len(*argSaveDir) > 0 { 615 writeMessageToFile(*argSaveDir, msg, !reportedOnce) 616 } 617 } 618 case <-done: 619 return 620 } 621 } 622 } 623 624 func printMessageInfo(msg *whisper.ReceivedMessage) { 625 timestamp := fmt.Sprintf("%d", msg.Sent) //用于诊断的Unix时间戳 626 text := string(msg.Payload) 627 628 var address common.Address 629 if msg.Src != nil { 630 address = crypto.PubkeyToAddress(*msg.Src) 631 } 632 633 if whisper.IsPubKeyEqual(msg.Src, &asymKey.PublicKey) { 634 fmt.Printf("\n%s <%x>: %s\n", timestamp, address, text) //我的信息 635 } else { 636 fmt.Printf("\n%s [%x]: %s\n", timestamp, address, text) // 637 } 638 } 639 640 func writeMessageToFile(dir string, msg *whisper.ReceivedMessage, show bool) { 641 if len(dir) == 0 { 642 return 643 } 644 645 timestamp := fmt.Sprintf("%d", msg.Sent) 646 name := fmt.Sprintf("%x", msg.EnvelopeHash) 647 648 var address common.Address 649 if msg.Src != nil { 650 address = crypto.PubkeyToAddress(*msg.Src) 651 } 652 653 env := shh.GetEnvelope(msg.EnvelopeHash) 654 if env == nil { 655 fmt.Printf("\nUnexpected error: envelope not found: %x\n", msg.EnvelopeHash) 656 return 657 } 658 659 //这是一个示例代码;如果不想保存自己的消息,请取消注释。 660 //如果whisper.ispubkeyequal(msg.src,&asymkey.publickey) 661 //fmt.printf(“\n%s<%x>:我收到的消息,未保存:“%s'\n”,时间戳,地址,名称) 662 //返回 663 //} 664 665 fullpath := filepath.Join(dir, name) 666 err := ioutil.WriteFile(fullpath, env.Data, 0644) 667 if err != nil { 668 fmt.Printf("\n%s {%x}: message received but not saved: %s\n", timestamp, address, err) 669 } else if show { 670 fmt.Printf("\n%s {%x}: message received and saved as '%s' (%d bytes)\n", timestamp, address, name, len(env.Data)) 671 } 672 } 673 674 func requestExpiredMessagesLoop() { 675 var key, peerID, bloom []byte 676 var timeLow, timeUpp uint32 677 var t string 678 var xt whisper.TopicType 679 680 keyID, err := shh.AddSymKeyFromPassword(msPassword) 681 if err != nil { 682 utils.Fatalf("Failed to create symmetric key for mail request: %s", err) 683 } 684 key, err = shh.GetSymKey(keyID) 685 if err != nil { 686 utils.Fatalf("Failed to save symmetric key for mail request: %s", err) 687 } 688 peerID = extractIDFromEnode(*argEnode) 689 shh.AllowP2PMessagesFromPeer(peerID) 690 691 for { 692 timeLow = scanUint("Please enter the lower limit of the time range (unix timestamp): ") 693 timeUpp = scanUint("Please enter the upper limit of the time range (unix timestamp): ") 694 t = scanLine("Enter the topic (hex). Press enter to request all messages, regardless of the topic: ") 695 if len(t) == whisper.TopicLength*2 { 696 x, err := hex.DecodeString(t) 697 if err != nil { 698 fmt.Printf("Failed to parse the topic: %s \n", err) 699 continue 700 } 701 xt = whisper.BytesToTopic(x) 702 bloom = whisper.TopicToBloom(xt) 703 obfuscateBloom(bloom) 704 } else if len(t) == 0 { 705 bloom = whisper.MakeFullNodeBloom() 706 } else { 707 fmt.Println("Error: topic is invalid, request aborted") 708 continue 709 } 710 711 if timeUpp == 0 { 712 timeUpp = 0xFFFFFFFF 713 } 714 715 data := make([]byte, 8, 8+whisper.BloomFilterSize) 716 binary.BigEndian.PutUint32(data, timeLow) 717 binary.BigEndian.PutUint32(data[4:], timeUpp) 718 data = append(data, bloom...) 719 720 var params whisper.MessageParams 721 params.PoW = *argServerPoW 722 params.Payload = data 723 params.KeySym = key 724 params.Src = asymKey 725 params.WorkTime = 5 726 727 msg, err := whisper.NewSentMessage(¶ms) 728 if err != nil { 729 utils.Fatalf("failed to create new message: %s", err) 730 } 731 env, err := msg.Wrap(¶ms) 732 if err != nil { 733 utils.Fatalf("Wrap failed: %s", err) 734 } 735 736 err = shh.RequestHistoricMessages(peerID, env) 737 if err != nil { 738 utils.Fatalf("Failed to send P2P message: %s", err) 739 } 740 741 time.Sleep(time.Second * 5) 742 } 743 } 744 745 func extractIDFromEnode(s string) []byte { 746 n, err := discover.ParseNode(s) 747 if err != nil { 748 utils.Fatalf("Failed to parse enode: %s", err) 749 } 750 return n.ID[:] 751 } 752 753 //模糊布卢姆增加16个随机位的布卢姆 754 //筛选,以便混淆包含的主题。 755 //它在每个会话中都具有确定性。 756 //尽管有额外的位,它将平均匹配 757 //比完整节点的Bloom过滤器少32000倍的消息。 758 func obfuscateBloom(bloom []byte) { 759 const half = entropySize / 2 760 for i := 0; i < half; i++ { 761 x := int(entropy[i]) 762 if entropy[half+i] < 128 { 763 x += 256 764 } 765 766 bloom[x/8] = 1 << uint(x%8) //设置位号x 767 } 768 } 769