connection establish
lncli --network=simnet connect pubkey@host
の裏でどうゆう処理が走っているのか。一からたどる。 コマンドは、LNDではcliが利用される。
// connectToPeer establishes a connection to a remote peer. errChan is used to
// notify the caller if the connection attempt has failed. Otherwise, it will be
// closed.
func (s *server) connectToPeer(addr *lnwire.NetAddress, errChan chan<- error) {
conn, err := brontide.Dial(s.identityPriv, addr, cfg.net.Dial)
brontide.Dialは、noise protocolをサポートするスタンドアローンのlndのパッケージ。このメソッドでは、BOLT8で定義されるHandshake Exchangeが実行される。
ACT 1
-> e, es
// Initiate the handshake by sending the first act to the receiver.
actOne, err := b.noise.GenActOne()
if err != nil {
b.conn.Close()
return nil, err
}
if _, err := conn.Write(actOne[:]); err != nil {
b.conn.Close()
return nil, err
}
// We'll ensure that we get ActTwo from the remote peer in a timely
// manner. If they don't respond within 1s, then we'll kill the
// connection.
err = conn.SetReadDeadline(time.Now().Add(handshakeReadTimeout))
if err != nil {
b.conn.Close()
return nil, err
}
一秒以内にACT 2が帰ってこない場合、エラーとする。b.noise.GenActOne()では、
// e
b.localEphemeral, err = b.ephemeralGen()
if err != nil {
return actOne, err
}
ephemeral := b.localEphemeral.PubKey().SerializeCompressed()
b.mixHash(ephemeral)
// es
s := ecdh(b.remoteStatic, b.localEphemeral)
b.mixKey(s[:])
authPayload := b.EncryptAndHash([]byte{})
actOne[0] = HandshakeVersion
copy(actOne[1:34], ephemeral)
copy(actOne[34:], authPayload)
としてactOneを作る。act twoをreceiveしたら、
ACT 3
-> s, se
// Finally, complete the handshake by sending over our encrypted static
// key and execute the final ECDH operation.
actThree, err := b.noise.GenActThree()
if err != nil {
b.conn.Close()
return nil, err
}
if _, err := conn.Write(actThree[:]); err != nil {
b.conn.Close()
return nil, err
}
// We'll reset the deadline as it's no longer critical beyond the
// initial handshake.
err = conn.SetReadDeadline(time.Time{})
if err != nil {
b.conn.Close()
return nil, err
}
これにより、ネゴシエーションが完了する。 それ以降は、ネゴシエーション時に交換した鍵情報で、BOLTのメッセージを符号化/復号化を行う。
bolt message
noise protocolによるhand shakeが終わったら、次はboltによるやり取りになる。
その際は、initからすべてが始まる。
まずは、brontide packageでhand shakeしたあとの動き。
// connectToPeer establishes a connection to a remote peer. errChan is used to
// notify the caller if the connection attempt has failed. Otherwise, it will be
// closed.
func (s *server) connectToPeer(addr *lnwire.NetAddress, errChan chan<- error) {
conn, err := brontide.Dial(s.identityPriv, addr, cfg.net.Dial)
if err != nil {
srvrLog.Errorf("Unable to connect to %v: %v", addr, err)
select {
case errChan <- err:
case <-s.quit:
}
return
}
close(errChan)
s.OutboundPeerConnected(nil, conn)
}
から、
// OutboundPeerConnected initializes a new peer in response to a new outbound
// connection.
// NOTE: This function is safe for concurrent access.
func (s *server) OutboundPeerConnected(connReq *connmgr.ConnReq, conn net.Conn) {
// Exit early if we have already been instructed to shutdown, this
// prevents any delayed callbacks from accidentally registering peers.
if s.Stopped() {
return
}
nodePub := conn.(*brontide.Conn).RemotePub()
pubStr := string(nodePub.SerializeCompressed())
でpeerを登録する。