Skip to content

Commit

Permalink
Feature: use the Aleph.im P2P service (#328)
Browse files Browse the repository at this point in the history
Problem: P2P communication with the JS P2P daemon is sometimes unstable.

Solution: develop a new P2P service for Aleph.im nodes to replace this daemon.

* Rewrote all the calls to the P2P daemon to use the new service instead
* Adapted Docker Compose files
* Decommissioned the P2P protocol implementation as streams are not supported by the new service for now
* The key generation mechanism now writes the private key file in PKCS8 DER format, for compatibility with the P2P service
* Added a migration script to migrate the private key of existing nodes to the new format
  • Loading branch information
odesenfans authored Oct 14, 2022
1 parent 1bc15fe commit f887c6f
Show file tree
Hide file tree
Showing 35 changed files with 292 additions and 657 deletions.
6 changes: 0 additions & 6 deletions .github/workflows/pyaleph-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@ jobs:
with:
# Fetch the whole history for all tags and branches (required for aleph.__version__)
fetch-depth: 0
# Install nodejs for jsp2pd
- uses: actions/setup-node@v2
with:
node-version: '16'
- name: Set up Python 3.8
id: setup-python
uses: actions/setup-python@v2
Expand All @@ -45,8 +41,6 @@ jobs:
with:
path: ${{ steps.pip-cache.outputs.dir }}
key: ${{ runner.os }}-python-${{ steps.setup-python.outputs.python-version }}-pip-${{ hashFiles('setup.cfg') }}
- name: Install jsp2pd
run: npm install --global [email protected]
- name: Install Python dependencies
run: |
pip install .[testing]
Expand Down
1 change: 0 additions & 1 deletion deployment/docker-build/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ p2p:
http_port: 4024
port: 4025
control_port: 4030
listen_port: 4031
reconnect_delay: 60

sentry:
Expand Down
43 changes: 30 additions & 13 deletions deployment/docker-build/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,48 @@ volumes:
pyaleph-mongodb:

services:
p2pd:

rabbitmq:
restart: always
image: alephim/jsp2pd:0.10.2-1.0.0
image: rabbitmq:3.10.7-management
networks:
- pyaleph
environment:
PRIVATE_KEY_FILE: "/etc/jsp2pd/keys/serialized-node-secret.key"
LISTEN_MADDR: "/ip4/0.0.0.0/tcp/4030"
HOST_MADDRS: "/ip4/0.0.0.0/tcp/4025"
PUBSUB: "true"
PUBSUB_ROUTER: "floodsub"
RABBITMQ_DEFAULT_USER: guest
RABBITMQ_DEFAULT_PASS: guest
ports:
- "4025:4025"
- "4030:4030"
- "127.0.0.1:5672:5672"
- "127.0.0.1:15672:15672"

p2p-service:
restart: always
image: alephim/p2p-service:0.1.1
networks:
- pyaleph
volumes:
- ../../keys:/etc/jsp2pd/keys
- ../../config.yml:/etc/p2p-service/config.yml
- ../../keys/node-secret.pkcs8.der:/etc/p2p-service/node-secret.pkcs8.der
depends_on:
- rabbitmq
environment:
RUST_LOG: info
ports:
- "4025:4025"
- "127.0.0.1:4030:4030"
command:
- "--config"
- "/etc/p2p-service/config.yml"
- "--private-key-file"
- "/etc/p2p-service/node-secret.pkcs8.der"

ipfs:
restart: always
image: ipfs/kubo:v0.15.0
ports:
- "4001:4001"
- "4001:4001/udp"
- "5001:5001"
- "8080:8080"
- "127.0.0.1:5001:5001"
- "127.0.0.1:8080:8080"
volumes:
- "pyaleph-ipfs:/data/ipfs"
environment:
Expand All @@ -50,7 +67,7 @@ services:
networks:
- pyaleph
ports:
- "27017:27017"
- "127.0.0.1:27017:27017"

networks:
pyaleph:
13 changes: 0 additions & 13 deletions deployment/docker-build/jsp2pd/build_jsp2pd.sh

This file was deleted.

14 changes: 0 additions & 14 deletions deployment/docker-build/jsp2pd/jsp2pd.dockerfile

This file was deleted.

78 changes: 78 additions & 0 deletions deployment/migrations/scripts/0003-convert-key-to-pkcs8-der.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"""
This migration converts the PEM private key file to PKCS8 DER for compatibility
with the new Aleph.im P2P service. The Rust implementation of libp2p can only load
RSA keys in that format.
"""


import logging
import os
from pathlib import Path
from typing import Optional

import yaml
from Crypto.PublicKey import RSA
from p2pclient.libp2p_stubs.crypto.rsa import RSAPrivateKey

from aleph.exceptions import InvalidKeyDirException

LOGGER = logging.getLogger(os.path.basename(__file__))


PKCS8_DER_KEY_FILE = "node-secret.pkcs8.der"


def convert_pem_key_file_to_pkcs8_der(
pem_key_file: Path, pkcs8_der_key_file: Path
) -> None:
with pem_key_file.open() as pem:
private_key = RSAPrivateKey(RSA.import_key(pem.read()))

with pkcs8_der_key_file.open("wb") as der:
der.write(private_key.impl.export_key(format="DER", pkcs=8))


def get_key_from_config(config_file: Path) -> Optional[str]:
"""
In previous versions of the CCN, it was possible to set the key value directly
in the config file. This function tries to find it in the config or returns None.
:param config_file: Path to the CCN configuration file.
:return: The private key used to identify the node on the P2P network, or None
if the key is not provided in the config file.
"""
with open(config_file) as f:
config = yaml.safe_load(f)

try:
return config["p2p"]["key"]
except KeyError:
return None


def upgrade(**kwargs):
key_dir = Path(kwargs["key_dir"])
pem_key_file = key_dir / "node-secret.key"

# Nothing to do if the PKCS8 DER key file already exists
pkcs8_der_key_file = key_dir / PKCS8_DER_KEY_FILE
if pkcs8_der_key_file.is_file():
LOGGER.info(
"Key file %s already exists, nothing to do",
pkcs8_der_key_file,
)
return

if not key_dir.is_dir():
raise InvalidKeyDirException(
f"The specified key directory ('{key_dir}') is not a directory."
)

LOGGER.info("Converting the private key file to PKCS8 DER format...")
convert_pem_key_file_to_pkcs8_der(pem_key_file, pkcs8_der_key_file)
LOGGER.info("Successfully created %s.", pkcs8_der_key_file)


def downgrade(**kwargs):
# Nothing to do, the key file is still present in the key directory
pass
37 changes: 27 additions & 10 deletions deployment/samples/docker-compose/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,45 @@ services:
depends_on:
- mongodb
- ipfs
- p2pd
- p2p-service
networks:
- pyaleph
logging:
options:
max-size: 50m

p2pd:
p2p-service:
restart: always
image: alephim/jsp2pd:0.10.2-1.0.0
image: alephim/p2p-service:0.1.1
networks:
- pyaleph
volumes:
- ./config.yml:/etc/p2p-service/config.yml
- ./keys/node-secret.pkcs8.der:/etc/p2p-service/node-secret.pkcs8.der
depends_on:
- rabbitmq
environment:
PRIVATE_KEY_FILE: "/etc/jsp2pd/keys/serialized-node-secret.key"
LISTEN_MADDR: "/ip4/0.0.0.0/tcp/4030"
HOST_MADDRS: "/ip4/0.0.0.0/tcp/4025"
PUBSUB: "true"
PUBSUB_ROUTER: "floodsub"
RUST_LOG: info
ports:
- "4025:4025"
volumes:
- ./keys:/etc/jsp2pd/keys
- "127.0.0.1:4030:4030"
command:
- "--config"
- "/etc/p2p-service/config.yml"
- "--private-key-file"
- "/etc/p2p-service/node-secret.pkcs8.der"

rabbitmq:
restart: always
image: rabbitmq:3.10.7-management
networks:
- pyaleph
environment:
RABBITMQ_DEFAULT_USER: guest
RABBITMQ_DEFAULT_PASS: guest
ports:
- "127.0.0.1:5672:5672"
- "127.0.0.1:15672:15672"

ipfs:
restart: always
Expand Down
7 changes: 5 additions & 2 deletions deployment/samples/docker-compose/sample-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,15 @@ aleph:
queue_topic: ALEPH-TEST

p2p:
daemon_host: p2pd
daemon_host: p2p-service
http_port: 4024
port: 4025
control_port: 4030
listen_port: 4031
reconnect_delay: 60

rabbitmq:
host: rabbitmq
port: 5672

sentry:
dsn: ""
37 changes: 27 additions & 10 deletions deployment/samples/docker-monitoring/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,45 @@ services:
depends_on:
- mongodb
- ipfs
- p2pd
- p2p-service
networks:
- pyaleph
logging:
options:
max-size: 50m

p2pd:
p2p-service:
restart: always
image: alephim/jsp2pd:0.10.2-1.0.0
image: alephim/p2p-service:0.1.1
networks:
- pyaleph
volumes:
- ./config.yml:/etc/p2p-service/config.yml
- ./keys/node-secret.pkcs8.der:/etc/p2p-service/node-secret.pkcs8.der
depends_on:
- rabbitmq
environment:
PRIVATE_KEY_FILE: "/etc/jsp2pd/keys/serialized-node-secret.key"
LISTEN_MADDR: "/ip4/0.0.0.0/tcp/4030"
HOST_MADDRS: "/ip4/0.0.0.0/tcp/4025"
PUBSUB: "true"
PUBSUB_ROUTER: "floodsub"
RUST_LOG: info
ports:
- "4025:4025"
volumes:
- ./keys:/etc/jsp2pd/keys
- "127.0.0.1:4030:4030"
command:
- "--config"
- "/etc/p2p-service/config.yml"
- "--private-key-file"
- "/etc/p2p-service/node-secret.pkcs8.der"

rabbitmq:
restart: always
image: rabbitmq:3.10.7-management
networks:
- pyaleph
environment:
RABBITMQ_DEFAULT_USER: guest
RABBITMQ_DEFAULT_PASS: guest
ports:
- "127.0.0.1:5672:5672"
- "127.0.0.1:15672:15672"

ipfs:
restart: always
Expand Down
3 changes: 1 addition & 2 deletions deployment/samples/docker-monitoring/sample-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,10 @@ aleph:
queue_topic: ALEPH-TEST

p2p:
daemon_host: p2pd
daemon_host: p2p-service
http_port: 4024
port: 4025
control_port: 4030
listen_port: 4031
reconnect_delay: 60

sentry:
Expand Down
3 changes: 3 additions & 0 deletions deployment/scripts/run_aleph_ccn.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,11 @@ function wait_for_it()
DB_URI=$(get_config mongodb.uri | sed "s-mongodb://--")
IPFS_HOST=$(get_config ipfs.host)
IPFS_PORT=$(get_config ipfs.port)
RABBITMQ_HOST=$(get_config rabbitmq.host)
RABBITMQ_PORT=$(get_config rabbitmq.port)

wait_for_it "${DB_URI}"
wait_for_it -h "${IPFS_HOST}" -p "${IPFS_PORT}"
wait_for_it -h "${RABBITMQ_HOST}" -p "${RABBITMQ_PORT}"

exec pyaleph "${PYALEPH_ARGS[@]}"
1 change: 0 additions & 1 deletion docs/guides/private_net.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ Example of config file at this point (I disabled IPFS but you can leave it enabl
p2p:
host: 0.0.0.0
control_port: 4030
listen_port: 4031
http_port: 4024
port: 4025
peers: []
Expand Down
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ install_requires =
aioipfs@git+https://github.com/aleph-im/aioipfs.git@76d5624661e879a13b70f3ea87dc9c9604c7eda7
aleph-client==0.4.6
aleph-message==0.2.2
aleph-p2p-client@git+https://github.com/aleph-im/p2p-service-client-python@f9fc6057be5bf1712180129c831116a740441434
aleph-pytezos@git+https://github.com/aleph-im/aleph-pytezos.git@97fe92ffa6e21ef5ec17ef4fa16c86022b30044c
coincurve==15.0.1
configmanager==1.35.1
Expand Down
Loading

0 comments on commit f887c6f

Please sign in to comment.