Goでイーサー坊開発⑨Whisper通信プロトコルを作る

7604 ワード

Whisper
Whisperは、次の中心化されたアプリケーションの構築ブロックになることを目的とした、点対点アイデンティティに基づく簡単なメッセージングシステムである.柔軟性とプライバシーをかなりの代価で提供することを目的としています.次のセクションでは、Whisperをサポートするイーサー坊ノードを設定し、Whisperプロトコル上で暗号化メッセージを送信および受信する方法を学習します.
Whisperクライアントへの接続
Whisperクライアントへの接続を使用するには、まずwhisperを実行するEthernetノードに接続する必要があります.残念なことに、infuraのような公共ゲートウェイはwhisperをサポートしていません.これらのメッセージを無料で処理するお金の動力がないからです.Infuraは近い将来whisperをサポートするかもしれませんが、今は自分たちのgethノードを実行する必要があります.gethをインストールすると、gethを実行するときに--shh flagを追加してwhisperプロトコルをサポートし、--ws flagと--rpcを追加してwebsocketをサポートしてリアルタイム情報を受信します.
geth --rpc --shh --ws

私たちのGoアプリケーションでは、whisper/shhclientで見つけたgo-ethereum whisperクライアントパッケージをインポートし、クライアントを初期化し、デフォルトのwebsocketポート「8546」を使用してwebsocketsを介してローカルgethノードに接続します.
client, err := shhclient.Dial("ws://127.0.0.1:8546")
if err != nil {
    log.Fatal(err)
}

_ = client // we'll be using this in the     

メッセージを暗号化する鍵ペアを作成し、次の章でメッセージを送信します.
完全なコード
Commands
geth --rpc --shh --ws

whisper_client.go
package main

import (
    "log"

    "github.com/ethereum/go-ethereum/whisper/shhclient"
)

func main() {
    client, err := shhclient.Dial("ws://127.0.0.1:8546")
    if err != nil {
        log.Fatal(err)
    }

    _ = client // we'll be using this in the     
    fmt.Println("we have a whisper connection")
}

Whisperスプーンペアの生成
Whisperでは、メッセージは、所望の受信者以外の誰もがメッセージを読み取ることを防止するために、対称鍵または非対称鍵を使用して暗号化されなければならない.
Whisperクライアントに接続すると、クライアントのNewKeyPairメソッドを呼び出して、ノードが管理する新しい共通ペアとプライベートペアを生成する必要があります.この関数の結果は、次のセクションでメッセージを暗号化および復号化するために使用される鍵ペアを参照する一意のIDになります.
keyID, err := client.NewKeyPair(context.Background())
if err != nil {
    log.Fatal(err)
}

fmt.Println(keyID) // 0ec5cfe4e215239756054992dbc2e10f011db1cdfc88b9ba6301e2f9ea1b58d2

次の章では、暗号化されたメッセージを送信する方法について説明します.
完全なコード
Commands
geth --rpc --shh --ws

whisper_keypair.go
package main

import (
    "context"
    "fmt"
    "log"

    "github.com/ethereum/go-ethereum/whisper/shhclient"
)

func main() {
    client, err := shhclient.Dial("ws://127.0.0.1:8546")
    if err != nil {
        log.Fatal(err)
    }

    keyID, err := client.NewKeyPair(context.Background())
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(keyID) // 0ec5cfe4e215239756054992dbc2e10f011db1cdfc88b9ba6301e2f9ea1b58d2
}

Whisperでメッセージを送信
メッセージを作成できる前に、まず公開鍵を使用してメッセージを暗号化する必要があります.前章では、鍵ペアを参照する鍵IDを返すNewKeyPair関数を使用して公開鍵と秘密鍵ペアを生成する方法について学習した.PublicKey関数を呼び出して鍵ペアの公開鍵をバイト形式で読み出す必要があります.メッセージを暗号化します.
publicKey, err := client.PublicKey(context.Background(), keyID)
if err != nil {
    log.Print(err)
}

fmt.Println(hexutil.Encode(publicKey)) // 0x04f17356fd52b0d13e5ede84f998d26276f1fc9d08d9e73dcac6ded5f3553405db38c2f257c956f32a0c1fca4c3ff6a38a2c277c1751e59a574aecae26d3bf5d1d

次に、go-ethereum whisper/whisperv6パッケージからNewMessage構造を初期化することによって、次のプロパティが必要なプライベートメッセージを構築します.
  • Payloadバイト形式のメッセージコンテンツ
  • PublicKey暗号化公開鍵
  • TTLメッセージのアクティブ時間
  • PowTime勤務証明書の時間上限
  • PowTarget勤務証明書の時間下限
  • message := whisperv6.NewMessage{
      Payload:   []byte("Hello"),
      PublicKey: publicKey,
      TTL:       60,
      PowTime:   2,
      PowTarget: 2.5,
    }
    

    クライアントのPost関数を呼び出して、メッセージのハッシュ値を返すかどうかのメッセージをネットワークにブロードキャストすることができます.
    messageHash, err := client.Post(context.Background(), message)
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Println(messageHash) // 0xdbfc815d3d122a90d7fb44d1fc6a46f3d76ec752f3f3d04230fe5f1b97d2209a
    

    次の章では、メッセージをリアルタイムで受信するためにメッセージサブスクリプションを作成する方法について説明します.
    完全なコード
    Commands
    geth --shh --rpc --ws
    

    whisper_send.go
    package main
    
    import (
        "context"
        "fmt"
        "log"
    
        "github.com/ethereum/go-ethereum/common/hexutil"
        "github.com/ethereum/go-ethereum/whisper/shhclient"
        "github.com/ethereum/go-ethereum/whisper/whisperv6"
    )
    
    func main() {
        client, err := shhclient.Dial("ws://127.0.0.1:8546")
        if err != nil {
            log.Fatal(err)
        }
    
        keyID, err := client.NewKeyPair(context.Background())
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println(keyID) // 0ec5cfe4e215239756054992dbc2e10f011db1cdfc88b9ba6301e2f9ea1b58d2
    
        publicKey, err := client.PublicKey(context.Background(), keyID)
        if err != nil {
            log.Print(err)
        }
        fmt.Println(hexutil.Encode(publicKey)) // 0x04f17356fd52b0d13e5ede84f998d26276f1fc9d08d9e73dcac6ded5f3553405db38c2f257c956f32a0c1fca4c3ff6a38a2c277c1751e59a574aecae26d3bf5d1d
    
        message := whisperv6.NewMessage{
            Payload:   []byte("Hello"),
            PublicKey: publicKey,
            TTL:       60,
            PowTime:   2,
            PowTarget: 2.5,
        }
        messageHash, err := client.Post(context.Background(), message)
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println(messageHash) // 0xdbfc815d3d122a90d7fb44d1fc6a46f3d76ec752f3f3d04230fe5f1b97d2209a
    }
    

    Whisperメッセージの傍受/購読
    このセクションでは、WebsocketsのWhisperメッセージを購読します.まず、whisper/whisperv6パケットのMessageタイプからWhispeメッセージを受信するチャネルが必要です.
    messages := make(chan *whisperv6.Message)
    

    サブスクリプションを呼び出す前に、まずメッセージのフィルタ基準を決定する必要があります.whisperv 6パッケージから新しいCriteriaオブジェクトを初期化します.私たちは私たちのメッセージにのみ興味を持っているため、条件オブジェクトのPrivateKeyID属性をメッセージを暗号化するための同じ鍵IDに設定します.
    criteria := whisperv6.Criteria{
        PrivateKeyID: keyID,
    }
    

    次に、クライアントのSubscribeMessagesメソッドを呼び出し、所定の条件を満たすメッセージを購読する.HTTPはこの方法をサポートしていない.WebsocketsやIPCなどの双方向接続のみをサポートします.最後のパラメータは、以前に作成したメッセージチャネルです.
    sub, err := client.SubscribeMessages(context.Background(), criteria, messages)
    if err != nil {
      log.Fatal(err)
    }
    

    これで購読しました.select文を使用してメッセージを読み取り、購読中のエラーを処理できます.前節から思い出すと、メッセージの内容がPayload属性でバイトスライスされている場合は、人間が読むことができる文字列に変換できます.
    for {
        select {
        case err := 

    次の完全なコードを見て、完全な栗を取得します.これがメッセージ購読のすべての内容です.
    完全なコード
    Commands
    geth --shh --rpc --ws
    

    whisper_subscribe.go
    package main
    
    import (
        "context"
        "fmt"
        "log"
        "os"
        "runtime"
    
        "github.com/ethereum/go-ethereum/common/hexutil"
        "github.com/ethereum/go-ethereum/whisper/shhclient"
        "github.com/ethereum/go-ethereum/whisper/whisperv6"
    )
    
    func main() {
        client, err := shhclient.Dial("ws://127.0.0.1:8546")
        if err != nil {
            log.Fatal(err)
        }
    
        keyID, err := client.NewKeyPair(context.Background())
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println(keyID) // 0ec5cfe4e215239756054992dbc2e10f011db1cdfc88b9ba6301e2f9ea1b58d2
    
        messages := make(chan *whisperv6.Message)
        criteria := whisperv6.Criteria{
            PrivateKeyID: keyID,
        }
        sub, err := client.SubscribeMessages(context.Background(), criteria, messages)
        if err != nil {
            log.Fatal(err)
        }
    
        go func() {
            for {
                select {
                case err := 

    小編微信を追加:grey 0805、知識学習小分隊に参加~!