# Week8 Update ## TL;DR 1. Implement the [peerid spec](https://github.com/libp2p/specs/blob/master/peer-ids/peer-ids.md#peer-ids) in the zig-libp2p, opened the [PR](https://github.com/zen-eth/zig-libp2p/pull/48). 2. Implement the [protocol-negotiation spec](https://github.com/libp2p/specs/tree/master/connections#protocol-negotiation) and the [multistream-select spec](https://github.com/libp2p/specs/tree/master/connections#multistream-select) in the zig-libp2p, opened the [PR](https://github.com/zen-eth/zig-libp2p/pull/50). ## Peer ID A Peer Identity (often written `PeerID`) is a unique reference to a specific peer within the overall peer-to-peer network. As well as serving as a unique identifier for each peer, a Peer ID is a verifiable link between a peer and its public cryptographic key. Each libp2p peer controls a private key, which it keeps secret from all other peers. Every private key has a corresponding public key, which is shared with other peers. Together, the public and private key (or "key pair") allow peers to establish [secure communication](https://docs.libp2p.io/concepts/secure-comm/overview/) channels with each other. Conceptually, a Peer ID is a [cryptographic hash](https://en.wikipedia.org/wiki/Cryptographic_hash_function) of a peer's public key. When peers establish a secure channel, the hash can be used to verify that the public key used to secure the channel is the same one used to identify the peer. The [Peer ID spec](https://github.com/libp2p/specs/blob/master/peer-ids/peer-ids.md) goes into detail about the byte formats used for libp2p public keys and how to hash the key to produce a valid Peer ID. ### How are Peer Ids represented as strings? Peer Ids are [multihashes](https://docs.libp2p.io/concepts/appendix/glossary/#multihash), which are defined as a compact binary format. It's very common to see multihashes encoded into [base 58](https://en.wikipedia.org/wiki/Binary-to-text_encoding#Base58), using [the same alphabet used by bitcoin](https://en.bitcoinwiki.org/wiki/Base58#Alphabet_Base58). Here's an example of a Peer ID represented as a base58-encoded multihash: `QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N` While it's possible to represent multihashes in many textual formats (for example as hexadecimal, base64, etc), Peer Ids *always* use the base58 encoding, with no [multibase prefix](https://github.com/multiformats/multibase) when encoded into strings. ### Peer IDs in multiaddrs A Peer ID can be encoded into a [multiaddr](https://docs.libp2p.io/concepts/appendix/glossary/#multiaddr) as a `/p2p` address with the Peer ID as a parameter. If my Peer ID is `QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N`, a libp2p multiaddress for me would be: ```shell /p2p/QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N ``` As with other multiaddrs, a `/p2p` address can be encapsulated into another multiaddr to compose into a new multiaddr. For example, I can combine the above with a [transport](https://docs.libp2p.io/concepts/transports/overview/) address `/ip4/198.51.100.0/tcp/4242` to produce this very useful address: ```shell /ip4/198.51.100.0/tcp/4242/p2p/QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N ``` This provides enough information to dial a specific peer over a TCP/IP transport. If some other peer has taken over that IP address or port, it will be immediately obvious, since they will not have control over the key pair used to produce the Peer ID embedded in the address. For more on addresses in libp2p, see [Addressing](https://docs.libp2p.io/concepts/fundamentals/addressing/) The multiaddr protocol for libp2p addresses was originally written `/ipfs` and was later renamed to `/p2p`. The two are equivalent and have the same binary representation in multiaddrs. Which one is rendered in the string format depends on the version of the multiaddr library in use. ## Protocol Negotiation One of libp2p's core design goals is to be adaptable to many network environments, including those that don't yet exist. To provide this flexibility, the connection upgrade process supports multiple protocols for connection security and stream multiplexing and allows peers to select which to use for each connection. The process of selecting protocols is called **protocol negotiation**. In addition to its role in the connection upgrade process, protocol negotiation is also used whenever [a new stream is opened over an existing connection](https://github.com/libp2p/specs/tree/master/connections#opening-new-streams-over-a-connection). This allows libp2p applications to route application-specific protocols to the correct handler functions. Each protocol supported by a peer is identified using a unique string called a **protocol id**. While any string can be used, the conventional format is a path-like structure containing a short name and a version number, separated by `/` characters. For example: `/yamux/1.0.0` identifies version 1.0.0 of the [`yamux` stream multiplexing protocol](https://github.com/hashicorp/yamux/blob/master/spec.md). multistream-select itself has a protocol id of `/multistream/1.0.0`. Including a version number in the protocol id simplifies the case where you want to concurrently support multiple versions of a protocol, perhaps a stable version and an in-development version. By default, libp2p will route each protocol id to its handler function using exact literal matching of the protocol id, so new versions will need to be registered separately. However, the handler function receives the protocol id negotiated for each new stream, so it's possible to register the same handler for multiple versions of a protocol and dynamically alter functionality based on the version in use for a given stream. ### multistream-select libp2p uses a protocol called multistream-select for protocol negotiation. Below we cover the basics of multistream-select and its use in libp2p. For more details, see [the multistream-select repository](https://github.com/multiformats/multistream-select). Before engaging in the multistream-select negotiation process, it is assumed that the peers have already established a bidirectional communication channel, which may or may not have the security and multiplexing capabilities of a libp2p connection. If those capabilities are missing, multistream-select is used in the [connection upgrade process](https://github.com/libp2p/specs/tree/master/connections#upgrading-connections) to determine how to provide them. Messages are sent encoded as UTF-8 byte strings, and they are always followed by a `\n` newline character. Each message is also prefixed with its length in bytes (including the newline), encoded as an unsigned variable-length integer according to the rules of the [multiformats unsigned varint spec](https://github.com/multiformats/unsigned-varint). For example, the string `"na"` is sent as the following bytes (shown here in hex): ``` 0x036e610a ``` The first byte is the varint-encoded length (`0x03`), followed by `na` (`0x6e 0x61`), then the newline (`0x0a`). ## Next Try to start desgin the [PubSub protocol framework](https://github.com/libp2p/specs/tree/master/pubsub) in zig-libp2p.