# 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.