# Algorand Specifications

The following section presents how the two Algorand _network layers_ (WSWS and P2PP2P) resolve _peer addressing_, to univocally identify themselves amongst PeerPeers, establish two-way connections, and effectively route messages regardless of the underlying architecture.

The Relay Network WSWS relies on an `ip:port` scheme to let a PeerPeer present itself to and address other peers.

This schema is defined in the `NetAddress` parameter of the _node configuration_.

> See details in the node configuration [non-normative section](https://specs.algorand.co/node/non-normative/node-nn-appendix-b).

The `PublicAddress` also can be set in the _node configuration_ to let a PeerPeer differentiate itself from other peers, and to be used in the [identity challenges](https://specs.algorand.co/network/non-normative/network-nn-identity).

> Important
>
> **IMPLEMENTATION:**
>
> The reference implementation checks the scheme of network addresses against this _regex_:
>
> `^[-a-zA-Z0-9.]+:\d+$`

> Important
>
> **IMPLEMENTATION:**
>
> Websocket network address [reference implementation](https://github.com/algorand/go-algorand/blob/df0613a04432494d0f437433dd1efd02481db838/network/wsNetwork.go#L332).

The Peer-to-Peer Network P2PP2P makes use of the underlying [`libp2p`](https://specs.algorand.co/network/non-normative/network-nn-appendix-a) library primitives for PeerPeer addressing, identification, and connection.

> This section relies on the `libp2p` [specifications](https://github.com/libp2p/specs) and [developer documentation](https://docs.libp2p.io/concepts/fundamentals/).

In this addressing scheme, each node participating in the P2PP2P network holds a public and private [Ed25519](https://specs.algorand.co/crypto/crypto-ed25519) key pair. The private key is kept secret, and the public key is shared with all participants.

The _peer identity_ (`PeerID`) is a _unique_ reference to a specific PeerPeer within the P2PP2P network, serving as a unique identifier for each PeerPeer. It is linked to the public key of the participant, as it is derived as a hash of said key, encoded in `base58`.

> See `libp2p` [PeerID specification](https://github.com/libp2p/specs/blob/master/peer-ids/peer-ids.md) for details on how these are constructed and encoded.

The `PeerID` are visible and may be incorporated into [multiaddresses](https://specs.algorand.co/network/non-normative/network-nn-addressing#multiaddress) to route messages.

PeerPeer private keys are used to sign all messages and are kept as secrets by the node.

> Important
>
> **IMPLEMENTATION:**
>
> `PeerID` are cast-able to `str` type and are used as plain strings in packages where importing `libp2p` packages may not be needed.

> Important
>
> **IMPLEMENTATION:**
>
> A `GetPrivKey` [function](https://github.com/algorand/go-algorand/blob/eff5fb40deb279ba8b2d7f25fbfa5bfe8002d422/network/p2p/peerID.go#L56) manages loading and creation of private keys in the P2PP2P network. It prioritizes, in this order:
>
> 1. User supplied path to `privKey`,
> 2. The default path to `privKey`,
> 3. Generating a new `privKey`.

> Important
>
> **IMPLEMENTATION:**
>
> If a new private key is generated, and should be persisted, its default path is
> `"peerIDPrivKey.key"` (inside the root directory). The behavior of this lookup is governed by _node configuration_ values `P2PPersistPeerID` and `P2PPrivateKeyLocation` (see the Algorand Infrastructure [non-normative section](https://specs.algorand.co/node/non-normative/node-nn-appendix-b)).

A multiaddress is a convention for encoding multiple layers of addressing information into a single “future-proof” path structure. It allows overlay of protocols and interoperation of many _peer addressing_ layers.

When exchanging addresses, peers send a multiaddress containing both their network address and `PeerID`.

Regular `NetAddress` (as the scheme presented in the [previous section](https://specs.algorand.co/network/non-normative/network-nn-addressing#websocket-addressing-scheme)) may be easily converted into a `libp2p` formatted listen multiaddress.

Given a network address `[a]:[b]` (where `[a]` is the IP address and `[b]` is the open port), the conversion scheme is `/ip4/[a]/tcp/[b]`.

> Refer to the `libp2p` [specifications](https://github.com/libp2p/specs/blob/master/addressing/README.md#the-p2p-multiaddr) for further detail on this structure.

> Important
>
> **EXAMPLE:**
>
> Here are some examples of syntactically valid _multiaddresses_:
>
> - `/ip4/127.0.0.1/tcp/8080`, for a multiaddress composed only of a network address listening to `localhost` on the port `8080`.
> - `/ip4/192.168.1.1/tcp/8180/p2p/Qmewz5ZHN1AAGTarRbMupNPbZRfg3p5jUGoJ3JYEatJVVk`, for a multiaddress composed of a network address `192.168.1.1:8180`, joined together with the `PeerID` equal to `Qmewz5ZHN1AAGTarRbMupNPbZRfg3p5jUGoJ3JYEatJVVk`.
> - `/ip4/192.255.2.8/tcp/8180/ws`, for a multiaddress composed only of a network address `192.255.2.8:8180` indicating that the connection is through websockets `ws`.

The hybrid network maintains a single `IdentityTracker` entity, shared between both network definitions (WSWS and P2PP2P).

Note that a `PublicAddress` must be set for hybrid nodes to operate properly.

For _peer identity_ deduplication, a signing schema involving both the P2PP2P private key and the WSWS identity challenge is put in place. This is to correlate both PeerPeer definitions and prevent it from existing in both PeerPeer lists.

> See the hybrid network [identity challenge](https://specs.algorand.co/network/non-normative/network-nn-identity#hybrid-network-identity-challenge) for further details on this process.
