Noise Protocol
Lightning Networkでは、メッセージ交換のために、node間のセッションを確立する。このときのやりとりは、その後のprotocolとは異なる。そのために、Noise Protocol Frameworkが利用される。
Noise is a framework for building crypto protocols. Noise protocols support mutual and optional authentication, identity hiding, forward secrecy, zero round-trip encryption, and other advanced features.
である。WhatsAppでも利用されているプロトコルだ。 golangのパッケージもある。これからセッション確立から実装する。
相手ノードとはIPアドレスなどでTCP接続を行った後、相手をnode_id(Bitcoinの公開鍵と同じ計算で求めた33バイトのデータ)で指定してネゴシエーションを行う。 1.5往復して相手のノードに間違いが無ければ、ネゴシエーションが完了する。
LNDに置いては、brontideというpackageにこれはまとめられていて、下記の要領で接続を実施している。
// Create a test connection, grabbing either side of the connection
// into local variables. If the initial crypto handshake fails, then
// we'll get a non-nil error here.
localConn, remoteConn, cleanUp, err := establishTestConnection()
if err != nil {
t.Fatalf("unable to establish test connection: %v", err)
}
defer cleanUp()
// Test out some message full-message reads.
for i := 0; i < 10; i++ {
msg := []byte("hello" + string(i))
if _, err := localConn.Write(msg); err != nil {
t.Fatalf("remote conn failed to write: %v", err)
}
readBuf := make([]byte, len(msg))
if _, err := remoteConn.Read(readBuf); err != nil {
t.Fatalf("local conn failed to read: %v", err)
}
if !bytes.Equal(readBuf, msg) {
t.Fatalf("messages don't match, %v vs %v",
string(readBuf), string(msg))
}
}
// Now try incremental message reads. This simulates first writing a
// message header, then a message body.
outMsg := []byte("hello world")
if _, err := localConn.Write(outMsg); err != nil {
t.Fatalf("remote conn failed to write: %v", err)
}
readBuf := make([]byte, len(outMsg))
if _, err := remoteConn.Read(readBuf[:len(outMsg)/2]); err != nil {
t.Fatalf("local conn failed to read: %v", err)
}
if _, err := remoteConn.Read(readBuf[len(outMsg)/2:]); err != nil {
t.Fatalf("local conn failed to read: %v", err)
}
if !bytes.Equal(outMsg, readBuf) {
t.Fatalf("messages don't match, %v vs %v",
string(readBuf), string(outMsg))
}