diff --git a/.vitepress/config.mts b/.vitepress/config.mts index 904cbad..67a0724 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -157,7 +157,7 @@ function nav() { { text: "Menu", items: [ - { text: "Get Started", link: "/docs/how-to-guides/overview" }, + // { text: "Get Started", link: "/docs/how-to-guides/overview" }, { text: "Learn", link: "/docs/learn/overview/intro" }, { text: "Resources", @@ -184,53 +184,52 @@ function nav() { function sidebarHome() { return [ { - text: "Learn", + text: "Overview of Optimum", collapsed: false, items: [ { - text: "Overview of Optimum", - collapsed: true, - items: [ - { - text: "Introduction", - link: "/docs/learn/overview/intro", - }, - { - text: "OptimumP2P", - link: "/docs/learn/overview/p2p.md", - }, - { - text: "Optimum DeRAM", - link: "/docs/learn/overview/deram.md", - }, - ], + text: "Introduction", + link: "/docs/learn/overview/intro", + }, + { + text: "OptimumP2P", + link: "/docs/learn/overview/p2p.md", + }, + { + text: "Optimum DeRAM", + link: "/docs/learn/overview/deram.md", }, - // { - // text: "OptimumP2P", - // collapsed: true, - // items: [ - // ], - // }, - // { - // text: "MUM", - // collapsed: true, - // items: [ - // { - // text: "Overview of MUM", - // link: "/docs/learn/mum", - // }, - // { - // text: "How to stake MUM", - // link: "/docs/learn/how-to-stake-mum", - // }, - // ], - // }, ], }, { - text: "How-to Guides (Under Construction 🚧)", - collapsed: true, - items: [], + text: "Getting Started", + collapsed: false, + items: [ + { + text: "Quick Start", + link: "/docs/guides/overview", + }, + { + text: "Getting Started with CLI", + link: "/docs/guides/01-getting-started-cli", + }, + { + text: "Getting Started with Docker", + link: "/docs/guides/02-getting-started-docker", + }, + { + text: "Understanding Key Parameters", + link: "/docs/guides/03-parameters", + }, + { + text: "Common Experiments", + link: "/docs/guides/04-experiments", + }, + { + text: "FAQ", + link: "/docs/guides/05-faq-glossary", + }, + ], }, { text: "Research", diff --git a/docs/guides/01-getting-started-cli.md b/docs/guides/01-getting-started-cli.md new file mode 100644 index 0000000..7a1b44d --- /dev/null +++ b/docs/guides/01-getting-started-cli.md @@ -0,0 +1,460 @@ +# Getting Started with mump2p CLI + +The `mump2p` CLI is the quickest way to interact with [OptimumP2P](https://github.com/getoptimum/optimum-p2p) without running your own infrastructure. + +In the next 5 minutes, you'll have: + +* A working CLI +* Your first published message +* A subscription feeding you live data + +The `mump2p` CLI is your shortcut into `OptimumP2P` — a high-performance, RLNC-enhanced peer-to-peer network. + +Instead of: + +* Manually locating and connecting to active OptimumP2P nodes +* Handling low-level peer discovery and connection logic +* Managing complex network and encoding configurations + +The `mump2p` CLI connects you directly to our hosted `optimum-proxy` (available in multiple regions) and start sending or receiving messages instantly. +It connects to an `optimum-proxy` and lets you publish and subscribe to real-time topics — with authentication, usage tracking, and advanced delivery options. + +## Why Optimum Proxy? + +OptimumP2P is a **peer-to-peer network** where nodes exchange messages over a `RLNC-enhanced` pubsub mesh. +If you connect directly to a P2P node, you need to: + +* Know node IP/port. +* Handle peer discovery. +* Many more complex configuration operations. + +The **Optimum Proxies** removes that complexity: + +* Acts as **points of entry**. +* Maintains connections to multiple OptimumP2P nodes. +* Enforces thresholds and applies filters. +* Tracks usage and applies fair rate limits. + +With `mump2p`, you connect only to the proxy — it does the rest. + +## Why Authentication? + +Authentication in `mump2p-cli` is not just about logging in, it enables: + +* **Access Control**: Only authorized users can publish/subscribe to protected topics. +* **Rate Limits**: Prevents spam and ensures fair use. +* **Usage Tracking**: Monitor your publish/subscription stats. +* **Account Linking**: Associate activity with your user or team. + +Without authentication, you can only use **open/public topics** with strict limits. + +## How It Fits into the Network + +![mump2p CLI Architecture](../../static/img/mump2p.png) + +* CLI talks to the Proxy via HTTP/WebSocket or gRPC. +* Proxy connects to the P2P Mesh (multiple nodes across regions). +* Mesh uses RLNC for efficient message delivery and reconstruction. +* Your client receives fully decoded messages in real-time. + +## 1. Install mump2p CLI + +### Quick Install (One Command) + +```bash +curl -sSL https://raw.githubusercontent.com/getoptimum/mump2p-cli/main/install.sh | bash +``` + +This automatically: + +* Detects your OS (Linux/macOS) +* Downloads the latest release +* Sets correct permissions +* Verifies installation works + +### Manual Install + +If you prefer manual installation: + +| OS | Command | +|---|---| +| **Linux** | `curl -L -o mump2p https://github.com/getoptimum/mump2p-cli/releases/latest/download/mump2p-linux && chmod +x mump2p` | +| **macOS** | `curl -L -o mump2p https://github.com/getoptimum/mump2p-cli/releases/latest/download/mump2p-mac && chmod +x mump2p` | + +### Verify Installation + +```bash +./mump2p version +``` + +**Output:** + +```bash +Version: v0.0.1-rc4 +Commit: fdbee67 +``` + +You can visit [mump2p-cli release page](https://github.com/getoptimum/mump2p-cli/releases) for the latest version. + +--- + +### 2. Authenticate + +*mump2p-cli currently uses [auth0](https://auth0.com/) to manage authentication/authorization*. + +Login via device authorization flow: + +```sh +./mump2p login +``` + +**Output:** + +```bash +Initiating authentication... + +To complete authentication: +1. Visit: https://your-auth-domain.auth0.com/activate?user_code=XXXX-XXXX +2. Or go to https://your-auth-domain.auth0.com/activate and enter code: XXXX-XXXX +3. This code expires in 15 minutes + +Waiting for you to complete authentication in the browser... + +✅ Successfully authenticated +Token expires at: 18 Aug 25 13:15 IST +``` + +1. CLI shows a URL and a code. +2. Open the URL in your browser. +3. Enter the code to complete authentication. +4. CLI stores a JWT for future requests. + +#### Check status + +```sh +./mump2p whoami +``` + +**Output:** + +```bash +Authentication Status: +---------------------- +Client ID: google-oauth2|100677750055416883405 +Expires: 18 Aug 25 13:15 IST +Valid for: 24h0m0s +Is Active: true + +Rate Limits: +------------ +Publish Rate: 1000 per hour +Publish Rate: 8 per second +Max Message Size: 4.00 MB +Daily Quota: 5120.00 MB +``` + +**Important: By default `Is Active` is `false`. Contact us to activate your account.** + +#### Other auth commands + +```sh +./mump2p refresh # Refresh token +./mump2p logout # Logout +``` + +**Refresh Output:** + +```bash +Current token status: +Expires at: 18 Aug 25 13:15 IST +Valid for: 23h56m0s +Refreshing token... +✅ Token refreshed successfully +New expiration: 18 Aug 25 13:19 IST +Valid for: 24h0m0s +``` + +**Logout Output:** + +```bash +✅ Successfully logged out +``` + +### 3. Choose a Proxy Location + +**Available Service URLs:** + +| Location | URL | +| ------------------- | ------------------- | +| **Tokyo (Default)** | 34.146.222.111:8080 | +| **Tokyo** | 35.221.118.95:8080 | +| **Singapore** | 34.142.205.26:8080 | + +Use a custom location + +```sh +--service-url="http://34.142.205.26:8080" +``` + +--- + +### 4. Subscribe to a Topic + +#### Basic subscription + +```sh +./mump2p subscribe --topic=demo +``` + +**Output:** + +```bash +claims is &{google-oauth2|100677750055416883405 2025-08-17 13:15:07 +0530 IST 2025-08-18 13:15:07 +0530 IST true 4194304 1000 8 5368709120 google-oauth2|100677750055416883405 1755416706719} +claims is google-oauth2|100677750055416883405 +Sending HTTP POST subscription request... +HTTP POST subscription successful: {"status":"subscribed","topic":"demo"} +Opening WebSocket connection... +Listening for messages on topic 'demo'... Press Ctrl+C to exit +``` + +#### Save messages locally + +```sh +./mump2p subscribe --topic=demo --persist=/path/to/ +``` + +**Output:** + +```bash +Persisting data to: /path/to/messages.log +claims is &{google-oauth2|100677750055416883405 2025-08-17 13:15:07 +0530 IST 2025-08-18 13:15:07 +0530 IST true 4194304 1000 8 5368709120 google-oauth2|100677750055416883405 1755416706719} +claims is google-oauth2|100677750055416883405 +Sending HTTP POST subscription request... +HTTP POST subscription successful: {"status":"subscribed","topic":"demo"} +Opening WebSocket connection... +Listening for messages on topic 'demo'... Press Ctrl+C to exit +``` + +**Persisted message format:** + +```bash +[2025-08-17T13:19:08+05:30] Testing persistence! +``` + +#### Forward to webhook + +```sh +./mump2p subscribe --topic=demo --webhook=https://your-server.com/webhook +``` + +**Output:** + +```bash +Forwarding messages to webhook: https://your-server.com/webhook +claims is &{google-oauth2|100677750055416883405 2025-08-17 13:15:07 +0530 IST 2025-08-18 13:15:07 +0530 IST true 4194304 1000 8 5368709120 google-oauth2|100677750055416883405 1755416706719} +claims is google-oauth2|100677750055416883405 +Sending HTTP POST subscription request... +HTTP POST subscription successful: {"status":"subscribed","topic":"demo"} +Opening WebSocket connection... +Listening for messages on topic 'demo'... Press Ctrl+C to exit +``` + +#### gRPC Subscription + +For high-performance streaming, use gRPC mode: + +```sh +./mump2p subscribe --topic=demo --grpc +``` + +**Output:** + +```bash +claims is &{google-oauth2|100677750055416883405 2025-08-21 16:01:29 +0530 IST 2025-08-22 16:01:29 +0530 IST true 4194304 1000 8 5368709120 google-oauth2|100677750055416883405 1755772288994} +claims is google-oauth2|100677750055416883405 +Sending HTTP POST subscription request... +HTTP POST subscription successful: {"client":"google-oauth2|100677750055416883405","status":"subscribed"} +Listening for messages on topic 'demo' via gRPC... Press Ctrl+C to exit +``` + +--- + +### 5. Publish a Message + +#### Text + +```sh +./mump2p publish --topic=demo --message="Hello from CLI!" +``` + +**Output:** + +```bash +✅ Published inline message +{"status":"published","topic":"demo"} +``` + +#### File + +```sh +./mump2p publish --topic=demo --file=/path/to/file.json +``` + +**Output:** + +```bash +✅ Published sample-data.json +{"status":"published","topic":"demo"} +``` + +#### gRPC Publishing + +For high-performance publishing, use gRPC mode: + +```sh +./mump2p publish --topic=demo --message="Hello via gRPC!" --grpc +``` + +**Output:** + +```bash +✅ Published via gRPC inline message +``` + +#### With threshold + +```sh +./mump2p publish --topic=demo --message="High reliability" --threshold=0.9 +``` + +--- + +### 6. Check Usage & Limits + +```sh +./mump2p usage +``` + +**Output:** + +```bash + Publish (hour): 0 / 1000 + Publish (second): 0 / 8 + Data Used: 0.0000 MB / 5120.0000 MB + Next Reset: 18 Aug 25 13:15 IST (24h0m0s from now) + Last Publish: 07 Aug 25 06:33 -0700 +``` + +Shows: + +* Publish count (per hour/day) +* Quota usage +* Time until reset +* Token expiry + +--- + +### 7. Check Proxy Health + +Monitor the health and system metrics of the proxy server: + +```sh +./mump2p health +``` + +**Output:** + +```bash +Proxy Health Status: +------------------- +Status: ok +Memory Used: 7.06% +CPU Used: 0.30% +Disk Used: 44.91% +``` + +#### Check specific proxy + +```sh +./mump2p health --service-url="http://35.221.118.95:8080" +``` + +--- + +### 8. Common Issues + +#### Unauthorized + +```sh +Error: your account is inactive +``` + +→ Contact admin to activate account. + +#### Rate limit exceeded + +```sh +Error: per-hour limit reached +``` + +→ Wait until reset or request higher tier. + +#### Connection refused + +```sh +Error: HTTP publish failed: dial tcp ... +``` + +→ Proxy not reachable. Check --service-url. + +#### Topic not assigned + +```sh +Error: publish error: topic not assigned +``` + +→ Topic needs to be subscribed to first or doesn't exist. + +#### Missing message or file + +```sh +Error: either --message or --file must be provided +``` + +→ Provide either --message or --file parameter. + +#### Conflicting parameters + +```sh +Error: only one of --message or --file should be used at a time +``` + +→ Use only one of --message or --file, not both. + +#### Authentication required + +```sh +Error: authentication required: token has expired, please login again +``` + +→ Run `./mump2p login` to authenticate. + +### 9. Important Tips + +* Use descriptive topic names per team. +* Keep `whoami` and `usage` handy. +* For high-volume topics, increase webhook queue size. +* Start with hosted proxy, then try local deployment for full control. +* Subscribe to a topic before publishing to it. +* Use the `--service-url` flag to connect to different gateways for better performance. +* Use `--grpc` flag for high-performance streaming and publishing. +* Monitor proxy health with `./mump2p health` for troubleshooting. + +--- + +#### Important Links + +* [mump2p CLI Source Code](https://github.com/getoptimum/mump2p-cli) +* [Developer Guide](https://github.com/getoptimum/mump2p-cli/blob/main/docs/guide.md) +* [Release Page](https://github.com/getoptimum/mump2p-cli/releases) +* [Available Service URLs](https://github.com/getoptimum/mump2p-cli?tab=readme-ov-file#3-service-url--connectivity-issues) diff --git a/docs/guides/02-getting-started-docker.md b/docs/guides/02-getting-started-docker.md new file mode 100644 index 0000000..53f0689 --- /dev/null +++ b/docs/guides/02-getting-started-docker.md @@ -0,0 +1,671 @@ +# Getting Started with Docker (Local Deployment) + +Running **OptimumP2P** locally with Docker gives you **full control** over configuration, topology, and experiments. +You can run the network in two primary ways: + +**1. OptimumProxy + OptimumP2P** — Clients connect to an **Optimum Proxy**, which manages P2P connections for them. + +![OptimumProxy + OptimumP2P Architecture](../../static/img/docker_1.png) + +* Simplifies client configuration — only the Proxy address is needed. +* Proxy handles shard reassembly, threshold logic, and node selection automatically. +* Easier scaling and centralized policy control. + +**2. Direct OptimumP2P** — Clients connect directly to **OptimumP2P nodes** (each node must run the gRPC API). + +![Direct OptimumP2P Architecture](../../static/img/docker_2.png) + +* Fewer network hops = potentially lower latency. +* Clients must know node addresses and manage failover logic. +* Best for specialized or performance-critical workloads. + + +While the [mump2p-cli (Hosted Proxy)](./01-getting-started-cli.md) lets you get started instantly, +local deployment offers: + +* **Custom Configuration** — Tune thresholds, shard factors, and mesh sizes. +* **Full Control** — Decide how many nodes, their topology, and resource allocation. +* **Private Testing** — Run in isolated networks without using public proxies. +* **Advanced Experiments** — Simulate network conditions, failure scenarios, and scaling. + +## Which mode should I use? + +Choose the deployment mode that best fits your use case: + +| **Mode A: Proxy + OptimumP2P** | **Mode B: Direct OptimumP2P** | +|---|---| +| **One endpoint** — simpler client config | **Lowest latency** — fewer network hops | +| **Policy control** — rate limiting, auth | **Direct control** — no proxy overhead | +| **Auto failover** — proxy handles node selection | **Manual failover** — clients manage addresses | + +**Quick Decision:** + +* **Want simpler setup and client code?** → **[Start with Mode A](#4-mode-a--optimumproxy--optimump2p-recommended)** +* **Need maximum performance and control?** → **[Jump to Mode B](#5-mode-b--direct-optimump2p-advanced--lower-latency)** + +## 1. Before You Start + +### Requirements + +* **[Docker](https://docs.docker.com/engine/install/)** — Container runtime for running OptimumP2P components +* **[Docker Compose](https://docs.docker.com/compose/install/)** — Tool for defining multi-container applications +* **[Go v1.24+](https://golang.org/dl/)** — Required for building custom gRPC clients +* At least **2 GB free RAM** for running multiple nodes locally + +> **Quick Docker Install:** +> +> * **Linux**: `curl -fsSL https://get.docker.com | sh` +> * **macOS**: [Docker Desktop for Mac](https://docs.docker.com/desktop/install/mac-install/) +> * **Windows**: [Docker Desktop for Windows](https://docs.docker.com/desktop/install/windows-install/) + +### Components + +| Component | Purpose | Docker Images | +| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- | +| **OptimumP2P Node** | RLNC-enabled mesh peer, encodes/decodes message shards, handles peer discovery and subscriptions. Optional gRPC API for direct clients. | `getoptimum/p2pnode:v0.0.1-rc2` | +| **Optimum Proxy** | Bridges clients and the mesh, manages subscriptions, shard reassembly, threshold logic, and node selection. | `getoptimum/proxy:v0.0.1-rc3` | + + + +### Directory layout + +Create a clean working folder: + +```sh +mkdir -p ~/optimum-local/{proxy-p2p,direct-p2p,identity} +cd ~/optimum-local +``` + +We’ll keep identity in `./identity` folder so you can reuse keys across restarts. + + + +## 2. Pick Your Mode + +| Recommended mode | Why | +| ----------------------------- | ----------------------------------------------------------------------------------------- | +| **OptimumProxy + OptimumP2P** | One endpoint for clients, proxy handles matching, decoding thresholds, fanout, and policy | +| **Direct OptimumP2P** | Fewer hops, you control connection/retry logic and node selection | + + +## 3. Generate a Bootstrap Identity (once) + +OptimumP2P nodes need a **P2P identity** (cryptographic keypair) for peer-to-peer communication. The bootstrap node needs a persistent identity so other nodes can discover it reliably. + +**What is P2P Identity?** + +* A cryptographic private key stored in `identity/p2p.key` +* Used for peer authentication and discovery +* Generates a unique **Peer ID** (like `12D3KooW...`) that other nodes use to connect + +### Quick One-Command Setup + +```bash +curl -sSL https://raw.githubusercontent.com/getoptimum/optimum-dev-setup-guide/main/script/generate-identity.sh | bash +``` + +This script: + +* Creates `./identity/` directory +* Generates P2P keypair using the existing keygen utility +* Saves to `identity/p2p.key` with proper checksum format +* Exports `BOOTSTRAP_PEER_ID` environment variable +* Handles existing identity gracefully +* Uses the correct file format expected by OptimumP2P nodes + +**Output:** + +```bash +[INFO] Generating P2P Bootstrap Identity... +[INFO] Creating identity directory... +[INFO] Using existing keygen script... +[INFO] Generating P2P keypair... +[SUCCESS] Generated P2P identity successfully! +[SUCCESS] Identity saved to: ./identity/p2p.key +[SUCCESS] Peer ID: 12D3KooWLsSmLLoE2T7JJ3ZyPqoXEusnBhsBA1ynJETsziCKGsBw +[INFO] To use in docker-compose: +export BOOTSTRAP_PEER_ID=12D3KooWLsSmLLoE2T7JJ3ZyPqoXEusnBhsBA1ynJETsziCKGsBw +[SUCCESS] Done! Your OptimumP2P peer ID: 12D3KooWLsSmLLoE2T7JJ3ZyPqoXEusnBhsBA1ynJETsziCKGsBw +``` + +**What this creates:** + +* `./identity/p2p.key` — JSON file containing the private key and peer ID +* `BOOTSTRAP_PEER_ID` environment variable for use in docker-compose files + +> **Note:** This process creates a persistent identity that will be reused across container restarts. The `identity/` folder is mounted into containers so the same keypair is shared by the bootstrap node. + +This guide covers: + +* Setting up Docker Compose for both approach. +* Running and verifying the network. +* Connecting via CLI (`mump2p-cli`) or `gRPC clients` (Go examples included). +* Adjusting key parameters for your environment. + +## 4. Mode A — OptimumProxy + OptimumP2P (Recommended) + +### Create the docker-compose file + +Save as `./proxy-p2p/docker-compose.yml`: + +```yaml +services: + proxy: + image: 'getoptimum/proxy:v0.0.1-rc3' + platform: linux/amd64 + environment: + - PROXY_PORT=:8080 # internal port, mapped below + - CLUSTER_ID=proxy-1 + - ENABLE_AUTH=false # set true in prod; see "Auth" below + - LOG_LEVEL=debug + # list of P2P node sidecar (gRPC) addresses (container DNS names) + - P2P_NODES=p2pnode-1:33212,p2pnode-2:33212 + depends_on: + - p2pnode-1 + - p2pnode-2 + ports: + - "8081:8080" # HTTP/WebSocket API (POST /publish, WS /ws, GET /health) + - "50051:50051" # (optional) proxy gRPC, if exposed by your proxy build + networks: + testnet: + ipv4_address: 172.28.0.10 + + p2pnode-1: + image: 'getoptimum/p2pnode:v0.0.1-rc2' + platform: linux/amd64 + volumes: + - ../identity:/identity + environment: + - LOG_LEVEL=debug + - CLUSTER_ID=p2pnode-1 + - NODE_MODE=optimum # or gossipsub + - IDENTITY_DIR=/identity + # Ports + - SIDECAR_PORT=33212 # client/proxy gRPC port + - API_PORT=9090 # node REST API + - OPTIMUM_PORT=7070 # inter-node P2P + # Mesh & RLNC + - OPTIMUM_MESH_TARGET=6 + - OPTIMUM_MESH_MIN=3 + - OPTIMUM_MESH_MAX=12 + - OPTIMUM_MAX_MSG_SIZE=1048576 + - OPTIMUM_SHARD_FACTOR=4 + - OPTIMUM_SHARD_MULT=1.5 + - OPTIMUM_THRESHOLD=0.75 + ports: + - "33221:33212" # sidecar gRPC (host) + - "9091:9090" # node API (host) + - "7071:7070" # P2P (host; optional if single host only) + networks: + testnet: + ipv4_address: 172.28.0.11 + + p2pnode-2: + image: 'getoptimum/p2pnode:latest' + platform: linux/amd64 + environment: + - LOG_LEVEL=debug + - CLUSTER_ID=p2pnode-2 + - NODE_MODE=optimum + - SIDECAR_PORT=33212 + - API_PORT=9090 + - OPTIMUM_PORT=7070 + - OPTIMUM_MAX_MSG_SIZE=1048576 + - OPTIMUM_MESH_TARGET=6 + - OPTIMUM_MESH_MIN=3 + - OPTIMUM_MESH_MAX=12 + - OPTIMUM_SHARD_FACTOR=4 + - OPTIMUM_SHARD_MULT=1.5 + - OPTIMUM_THRESHOLD=0.75 + # Bootstrap to node-1 (libp2p multiaddr) + - BOOTSTRAP_PEERS=/ip4/172.28.0.11/tcp/7070/p2p/${BOOTSTRAP_PEER_ID} + ports: + - "33222:33212" + - "9092:9090" + - "7072:7070" + networks: + testnet: + ipv4_address: 172.28.0.12 + +networks: + testnet: + driver: bridge + ipam: + config: + - subnet: 172.28.0.0/16 +``` + +*Why fixed IPs?* + +It makes the bootstrap address deterministic `(/ip4/172.28.0.11/tcp/7070/p2p/)`. +You can use the default bridge and service names, but then set `BOOTSTRAP_PEERS` to a reachable address. + +See the [Parameter Section](./03-parameters.md) for config options and port usage. + +### Start the Network + +```sh +cd ~/optimum-local/proxy-p2p +export BOOTSTRAP_PEER_ID= +docker compose up -d +``` + +### Validate everything is healthy + +```sh +docker compose ps +docker compose logs -f proxy | sed -n '1,120p +``` + +#### Health checks + +```sh +# Proxy +curl -s http://localhost:8081/api/v1/version +curl -s http://localhost:8081/api/v1/health + +# Nodes +curl -s http://localhost:9091/api/v1/health +curl -s http://localhost:9092/api/v1/health + +# Peers seen by node-2 (should include node-1) +curl -s http://localhost:9092/api/v1/node-state | jq '.peers' +``` + +You should see the mesh forming and node-2 discovering node-1 via the bootstrap address. + + +### Send & receive (Proxy mode) using mump2p-cli + +If you haven't already installed `mump2p-cli`, see the [**Getting Started with mump2p-cli**](./01-getting-started-cli.md) chapter. + +**Subscribe:** + +```sh +./mump2p subscribe --topic=demo --service-url=http://localhost:8081 +``` + +**Publish (in a new terminal):** + +```sh +./mump2p publish --topic=demo --message="Hello via Proxy" --service-url=http://localhost:8081 +``` + +You should see your subscriber print the message immediately. + + +### Use Proxy using REST API and WebSocket (optional) + +**Publish a message:** + +```sh +curl -X POST http://localhost:8081/api/v1/publish \ + -H "Content-Type: application/json" \ + -d '{ + "client_id": "your-client-id", + "topic": "example-topic", + "message": "Hello, world!" +}' +``` + +**Parameters:** + +* `client_id` – Unique identifier for the client (required) +* `topic` – The topic to publish the message to +* `message` – The content to broadcast to subscribers + +> **Important:** The `client_id` field is required for all publish requests. This should be the same ID used when subscribing to topics. If you're using WebSocket connections, use the same `client_id` for consistency. + +**Subscribe to a topic:** + +```sh +curl -X POST http://localhost:8081/api/v1/subscribe \ + -H "Content-Type: application/json" \ + -d '{ + "client_id": "unique-client-id", + "topic": "example-topic", + "threshold": 0.7 +}' +``` + +**Parameters:** + +* `client_id` – Unique identifier for the client (required) +* `topic` – The topic to subscribe to +* `threshold` (optional, float) – Minimum percentage (0.1–1.0) of active nodes that must report a message before it's forwarded to this client + * Default: 0.1 (10% confirmation) + +**Connect via WebSocket:** + +```sh +wscat -c "ws://localhost:8081/api/v1/ws?client_id=unique-client-id" +``` + +> **Important:** WebSocket has limitations, and you may experience unreliable delivery when publishing message bursts. A gRPC connection (shown below) provides more reliable streaming. + +**Rate Limits:** + +Rate limits are enforced based on client configuration. Exceeding limits results in 429 responses. + +> **Note:** Since authentication is disabled in our local setup (`ENABLE_AUTH=false`), no JWT tokens are required for these requests. + +### Use Proxy using gRPC Stream + +For a complete working proxy client with both REST subscription and gRPC streaming, see the full implementation: + +**[Complete Proxy Client Example](https://github.com/getoptimum/optimum-dev-setup-guide/blob/main/grpc_proxy_client/proxy_client.go)** + +The proxy client provides: + +* **REST API subscription** for topic registration and threshold configuration +* **gRPC bidirectional streaming** for real-time message delivery +* **Message publishing** via REST API endpoints +* **Configurable parameters** for topic, threshold, and message count +* **Flow control settings** for robust connections + +```go +// Basic proxy client implementation (see full version in GitHub link above) +package main + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "log" + "math" + "net/http" + "time" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + + protobuf "proxy_client/grpc" // Generated from gateway_stream.proto +) + +const ( + proxyREST = "http://localhost:8081" // REST API for subscription/publishing + proxyGRPC = "localhost:50051" // gRPC endpoint for streaming +) + +func main() { + clientID := "client_demo123" + topic := "demo" + threshold := 0.1 + + // 1. Subscribe via REST API + body := map[string]interface{}{ + "client_id": clientID, + "topic": topic, + "threshold": threshold, + } + data, _ := json.Marshal(body) + resp, err := http.Post(proxyREST+"/api/v1/subscribe", "application/json", bytes.NewReader(data)) + if err != nil { + log.Fatalf("subscription failed: %v", err) + } + resp.Body.Close() + + // 2. Connect to gRPC stream + conn, err := grpc.NewClient(proxyGRPC, + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithInitialWindowSize(1024*1024*1024), // 1GB per-stream receive window + grpc.WithInitialConnWindowSize(1024*1024*1024), // 1GB connection-level receive window + grpc.WithDefaultCallOptions( + grpc.MaxCallRecvMsgSize(math.MaxInt), + grpc.MaxCallSendMsgSize(math.MaxInt), + ), + ) + if err != nil { + log.Fatalf("gRPC connection failed: %v", err) + } + defer conn.Close() + + client := protobuf.NewProxyStreamClient(conn) + stream, err := client.ClientStream(context.Background()) + if err != nil { + log.Fatalf("stream creation failed: %v", err) + } + + // 3. Send client ID to establish stream + if err := stream.Send(&protobuf.ProxyMessage{ClientId: clientID}); err != nil { + log.Fatalf("client ID send failed: %v", err) + } + + // 4. Handle incoming messages + go func() { + for { + resp, err := stream.Recv() + if err == io.EOF { + log.Println("Stream closed by server") + return + } + if err != nil { + log.Printf("Stream receive error: %v", err) + return + } + log.Printf("Received: Topic=%s, Message=%s", resp.Topic, string(resp.Message)) + } + }() + + // 5. Publish messages via REST API + for i := 0; i < 3; i++ { + msg := fmt.Sprintf("Hello message %d @ %s", i+1, time.Now().Format("15:04:05")) + publishBody := map[string]interface{}{ + "client_id": clientID, + "topic": topic, + "message": msg, + } + publishData, _ := json.Marshal(publishBody) + + log.Printf("Publishing: %s", msg) + resp, err := http.Post(proxyREST+"/api/v1/publish", "application/json", bytes.NewReader(publishData)) + if err != nil { + log.Printf("Publish error: %v", err) + } else { + resp.Body.Close() + } + + time.Sleep(2 * time.Second) + } + + // Keep client running to receive messages + time.Sleep(10 * time.Second) +} +``` + +## 5. Mode B — Direct OptimumP2P (Advanced / Lower Latency) + +In this mode, clients connect `straight to node sidecar gRPC`. You’ll manage client-side reconnection, backoff, and which node to hit. + +### Create the docker-compose file + +Save as `./direct-p2p/docker-compose.yml`: + +```yaml +services: + p2pnode-1: + image: 'getoptimum/p2pnode:latest' + platform: linux/amd64 + volumes: + - ../identity:/identity + environment: + - LOG_LEVEL=debug + - CLUSTER_ID=p2pnode-1 + - NODE_MODE=optimum + - IDENTITY_DIR=/identity + - SIDECAR_PORT=33212 + - API_PORT=9090 + - OPTIMUM_PORT=7070 + - OPTIMUM_MESH_TARGET=6 + - OPTIMUM_MESH_MIN=3 + - OPTIMUM_MESH_MAX=12 + - OPTIMUM_MAX_MSG_SIZE=1048576 + - OPTIMUM_SHARD_FACTOR=4 + - OPTIMUM_SHARD_MULT=1.5 + - OPTIMUM_THRESHOLD=0.75 + ports: + - "33221:33212" + - "9091:9090" + - "7071:7070" + networks: + testnet: + ipv4_address: 172.28.0.11 + + p2pnode-2: + image: 'getoptimum/p2pnode:latest' + platform: linux/amd64 + environment: + - LOG_LEVEL=debug + - CLUSTER_ID=p2pnode-2 + - NODE_MODE=optimum + - SIDECAR_PORT=33212 + - API_PORT=9090 + - OPTIMUM_PORT=7070 + - OPTIMUM_MESH_TARGET=6 + - OPTIMUM_MESH_MIN=3 + - OPTIMUM_MESH_MAX=12 + - OPTIMUM_MAX_MSG_SIZE=1048576 + - OPTIMUM_SHARD_FACTOR=4 + - OPTIMUM_SHARD_MULT=1.5 + - OPTIMUM_THRESHOLD=0.75 + - BOOTSTRAP_PEERS=/ip4/172.28.0.11/tcp/7070/p2p/${BOOTSTRAP_PEER_ID} + ports: + - "33222:33212" + - "9092:9090" + - "7072:7070" + networks: + testnet: + ipv4_address: 172.28.0.12 + +networks: + testnet: + driver: bridge + ipam: + config: + - subnet: 172.28.0.0/16 +``` + +### Start and validate + +```sh +cd ~/optimum-local/direct-p2p +export BOOTSTRAP_PEER_ID= +docker compose up -d +docker compose ps +curl -s http://localhost:9091/api/v1/health +curl -s http://localhost:9092/api/v1/health +``` + +### Minimal Direct P2P sidecar gRPC stream client + +For a complete working P2P client that connects directly to nodes, see the full implementation with trace handling: + +**[Complete P2P Client Example](https://github.com/getoptimum/optimum-dev-setup-guide/blob/main/grpc_p2p_client/p2p_client.go)** + +The client includes: + +* **Message publishing and subscribing** with gRPC streaming +* **Protocol trace handling** for both GossipSub and OptimumP2P +* **Metrics collection** via `MessageTraceGossipSub` and `MessageTraceOptimumP2P` responses +* **Stress testing capabilities** with batch message publishing + +```go +// Basic client skeleton (see full implementation in GitHub link above) +package main + +import ( + "context" + "fmt" + "log" + "math" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + + protobuf "p2p_client/grpc" // Generated from p2p_stream.proto +) + +func main() { + conn, err := grpc.NewClient("localhost:33221", + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithDefaultCallOptions( + grpc.MaxCallRecvMsgSize(math.MaxInt), + grpc.MaxCallSendMsgSize(math.MaxInt), + ), + ) + if err != nil { log.Fatal(err) } + defer conn.Close() + + client := protobuf.NewCommandStreamClient(conn) + stream, _ := client.ListenCommands(context.Background()) + + // Subscribe to topic + stream.Send(&protobuf.Request{ + Command: int32(CommandSubscribeToTopic), + Topic: "demo", + }) + + // Handle responses including trace data + for { + resp, _ := stream.Recv() + switch resp.GetCommand() { + case protobuf.ResponseType_Message: + fmt.Printf("MSG: %s\n", string(resp.GetData())) + case protobuf.ResponseType_MessageTraceGossipSub: + fmt.Printf("[TRACE] GossipSub trace: %d bytes\n", len(resp.GetData())) + case protobuf.ResponseType_MessageTraceOptimumP2P: + fmt.Printf("[TRACE] OptimumP2P trace: %d bytes\n", len(resp.GetData())) + } + } +} +``` + +For all available configuration variables, observability and validations check the [Parameters Section](./03-parameters.md). + +## Troubleshooting + +### No peers / mesh empty + +* Check `BOOTSTRAP_PEERS` uses a reachable address of a running node. +* If using static IPs, confirm the `testnet` subnet and container IPs match the compose file. +* Look for `bootstrap` lines in docker compose logs `p2pnode`. + +### “connection refused” from client + +* Ensure you’re pointing to the host-mapped ports (e.g., 33221, 8081). +* Run docker compose ps and confirm port bindings. +* Firewalls: allow inbound localhost traffic. + +### Proxy can’t reach nodes + +* Inside the proxy container, resolve and ping node hosts: + +```sh +docker compose exec proxy sh -lc 'nc -zv p2pnode-1 33212' +``` + +* Make sure `P2P_NODES` hostnames match the `service names` in compose. + +### Port conflicts + +* Change host mappings in ports: (e.g., 33223:33212, 9093:9090, 7073:7070). + +### Protocol mismatch + +* All nodes in a mesh must use the same NODE_MODE (optimum or gossipsub). + +### Stop and Clean + +Stop: + +```sh +docker compose down +``` + +Full reset (containers, volumes, images created by this compose file): + +```sh +docker compose down -v --rmi local +``` diff --git a/docs/guides/03-parameters.md b/docs/guides/03-parameters.md new file mode 100644 index 0000000..017ede6 --- /dev/null +++ b/docs/guides/03-parameters.md @@ -0,0 +1,208 @@ +# Understanding Key Parameters in OptimumP2P + +OptimumP2P nodes can operate in **two distinct protocol modes**, configured via: + +```sh +NODE_MODE=optimum # RLNC-enhanced gossip +NODE_MODE=gossipsub # Standard libp2p gossip +``` + +Each mode has its own parameter set, with some shared configurations. + +We support **two protocol modes** to let developers and researchers compare **performance, reliability, and bandwidth trade-offs** in real-world scenarios — without changing the rest of their infrastructure. + +## OptimumP2P (RLNC) Mode — `NODE_MODE=optimum` + +OptimumP2P extends the gossip protocol with **Random Linear Network Coding**: + +* Messages are split into **shards** +* Shards can be forwarded early once a threshold is reached +* Improves delivery resilience in lossy or high-latency environments + +Example Docker service: + +```yaml +p2pnode-1: + image: 'getoptimum/p2pnode:latest' + environment: + - NODE_MODE=optimum + - LOG_LEVEL=debug + - CLUSTER_ID=p2pnode-1 + - OPTIMUM_PORT=7070 + - OPTIMUM_MAX_MSG_SIZE=1048576 + - OPTIMUM_MESH_TARGET=6 + - OPTIMUM_MESH_MIN=3 + - OPTIMUM_MESH_MAX=12 + - OPTIMUM_SHARD_FACTOR=4 + - OPTIMUM_SHARD_MULT=1.5 + - OPTIMUM_THRESHOLD=0.75 + - BOOTSTRAP_PEERS=/ip4/172.28.0.12/tcp/7070/p2p/${BOOTSTRAP_PEER_ID} +``` + +### Parameters + +| Parameter | Default | Purpose | +| ---------------------- | ------------- | ---------------------------------------------- | +| `OPTIMUM_PORT ` | 7070 | TCP port used for RLNC gossip. | +| `OPTIMUM_MAX_MSG_SIZE` | 1048576 (1MB) | Max allowed message size (full payload). | +| `OPTIMUM_MESH_TARGET` | 6 | Desired peers in mesh. | +| `OPTIMUM_MESH_MIN` | 3 | Minimum peers before adding more. | +| `OPTIMUM_MESH_MAX` | 12 | Max peers before pruning. | +| `OPTIMUM_SHARD_FACTOR` | 4 | Number of shards per message. | +| `OPTIMUM_SHARD_MULT` | 1.5 | Redundancy multiplier (extra shards). | +| `OPTIMUM_THRESHOLD` | 0.75 | Fraction of shards required to forward/decode. | +| `BOOTSTRAP_PEERS` | (none) | List of peer multiaddrs to connect at startup. | + + +## GossipSub Mode — `NODE_MODE=gossipsub` + +GossipSub is the **standard libp2p pub/sub** protocol: + +* Maintains topic-specific peer meshes +* Exchanges message availability metadata with non-mesh peers +* Widely used for blockchain gossip + +Example Docker service: + +```yaml +p2pnode-1: + image: 'getoptimum/p2pnode:latest' + environment: + - NODE_MODE=gossipsub + - LOG_LEVEL=debug + - CLUSTER_ID=p2pnode-1 + - GOSSIPSUB_PORT=6060 + - GOSSIPSUB_MAX_MSG_SIZE=1048576 + - GOSSIPSUB_MESH_TARGET=6 + - GOSSIPSUB_MESH_MIN=4 + - GOSSIPSUB_MESH_MAX=12 + - BOOTSTRAP_PEERS=/ip4/172.28.0.12/tcp/6060/p2p/${BOOTSTRAP_PEER_ID} +``` + + +### Parameters + +| Parameter | Default | Purpose | +| ------------------------ | ------------- | ---------------------------------------------- | +| `GOSSIPSUB_PORT` | 6060 | TCP port for gossip pub/sub. | +| `GOSSIPSUB_MAX_MSG_SIZE` | 1048576 (1MB) | Max allowed message size. | +| `GOSSIPSUB_MESH_TARGET` | 6 | Desired peers in mesh. | +| `GOSSIPSUB_MESH_MIN` | 4 | Minimum peers before adding more. | +| `GOSSIPSUB_MESH_MAX` | 12 | Max peers before pruning. | +| `BOOTSTRAP_PEERS` | (none) | List of peer multiaddrs to connect at startup. | + + +You can refer to the [GossipSub parameter specification](https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.0.md#parameters) for a detailed explanation of the standard pub/sub settings. + + +### Shared Parameters (Both `optimum` and `gossipsub` mode) + +| Parameter | Default | Purpose | +| -------------- | --------- | -------------------------------------------------- | +| `LOG_LEVEL` | debug | Log verbosity (debug, info, warn, error). | +| `CLUSTER_ID` | (none) | Logical group name for metrics and identification. | +| `SIDECAR_PORT` | 33212 | gRPC sidecar port for proxy ↔ P2P communication. | +| `API_PORT` | 9090 | HTTP API port for node management. | +| `IDENTITY_DIR` | /identity | Directory containing node’s private key. | + +## OptimumProxy Configuration Parameters + +When using **Proxy + P2P deployment**, the proxy service connects clients to P2P nodes and optionally enforces authentication. + +Example Docker service: + +```yaml +proxy-1: + image: 'getoptimum/proxy:latest' + environment: + - PROXY_HTTP_PORT=:8080 + - PROXY_GRPC_PORT=:50051 + - CLUSTER_ID=proxy-1 + - ENABLE_AUTH=false + - LOG_LEVEL=debug + - P2P_NODES=p2pnode-1:33212,p2pnode-2:33212 +``` + +| Parameter | Default | Purpose | +| --------------------------------- | ------- | ---------------------------------------------------------- | +| `PROXY_HTTP_PORT` | :8080 | HTTP API port for clients. | +| `PROXY_GRPC_PORT` | :50051 | gRPC API port for clients. | +| `ENABLE_AUTH` | false | Enable Auth0 authentication. | +| `AUTH0_DOMAIN` / `AUTH0_AUDIENCE` | (none) | Auth0 settings (required if `ENABLE_AUTH`=true). | +| `P2P_NODES` | (none) | Comma-separated list of host:port for sidecar connections. | +| `SUBSCRIBER_THRESHOLD` | 0.1 | % of connected subscribers needed to forward a message. | + +## Recommended Default Configuration + +The following table shows the **production defaults**, which are optimized for typical deployment scenarios: + +### For Quick Start (Copy-Paste Ready) + +**OptimumP2P Mode (`NODE_MODE=optimum`):** + +```yaml +environment: + - NODE_MODE=optimum + - LOG_LEVEL=production + - CLUSTER_ID=my-cluster + - SIDECAR_PORT=33212 + - API_PORT=8081 + - IDENTITY_DIR=/identity + - OPTIMUM_PORT=7070 + - OPTIMUM_MAX_MSG_SIZE=1048576 + - OPTIMUM_RANDOM_MSG_SIZE=512 + - OPTIMUM_MESH_TARGET=6 + - OPTIMUM_MESH_MIN=4 + - OPTIMUM_MESH_MAX=12 + - OPTIMUM_SHARD_FACTOR=4 + - OPTIMUM_SHARD_MULT=1.5 + - OPTIMUM_THRESHOLD=0.75 + - BOOTSTRAP_PEERS="" +``` + +**GossipSub Mode (`NODE_MODE=gossipsub`):** + +```yaml +environment: + - NODE_MODE=gossipsub + - LOG_LEVEL=production + - CLUSTER_ID=my-cluster + - SIDECAR_PORT=33212 + - API_PORT=8081 + - IDENTITY_DIR=/identity + - GOSSIPSUB_PORT=6060 + - GOSSIPSUB_MAX_MSG_SIZE=1048576 + - GOSSIPSUB_MESH_TARGET=6 + - GOSSIPSUB_MESH_MIN=4 + - GOSSIPSUB_MESH_MAX=12 + - BOOTSTRAP_PEERS="" +``` + +### Complete Defaults Reference + +| Parameter | Default Value | Used In Mode | Description | +| ---------------------------- | ------------- | ------------ | ---------------------------------------------- | +| `LOG_LEVEL` | production | Both | Log verbosity (production/debug/info/warn/error) | +| `CLUSTER_ID` | "" | Both | Logical group name for metrics | +| `NODE_MODE` | "" | Both | Protocol mode (optimum/gossipsub) | +| `SIDECAR_PORT` | 33212 | Both | gRPC sidecar port | +| `API_PORT` | 8081 | Both | HTTP API port | +| `IDENTITY_DIR` | /tmp | Both | Directory for node private key | +| `OPTIMUM_PORT` | 7070 | optimum | TCP port for RLNC gossip | +| `OPTIMUM_MAX_MSG_SIZE` | 1048576 | optimum | Max message size (1MB) | +| `OPTIMUM_RANDOM_MSG_SIZE` | 512 | optimum | Random message size for testing | +| `OPTIMUM_MESH_TARGET` | 6 | optimum | Desired peers in mesh | +| `OPTIMUM_MESH_MIN` | 4 | optimum | Minimum peers before adding more | +| `OPTIMUM_MESH_MAX` | 12 | optimum | Max peers before pruning | +| `OPTIMUM_SHARD_FACTOR` | 4 | optimum | Number of shards per message | +| `OPTIMUM_SHARD_MULT` | 1.5 | optimum | Redundancy multiplier (extra shards) | +| `OPTIMUM_THRESHOLD` | 0.75 | optimum | Forward/decode threshold (75%) | +| `GOSSIPSUB_PORT` | 6060 | gossipsub | TCP port for standard gossip | +| `GOSSIPSUB_MAX_MSG_SIZE` | 1048576 | gossipsub | Max message size (1MB) | +| `GOSSIPSUB_MESH_TARGET` | 6 | gossipsub | Desired peers in mesh | +| `GOSSIPSUB_MESH_MIN` | 4 | gossipsub | Minimum peers before adding more | +| `GOSSIPSUB_MESH_MAX` | 12 | gossipsub | Max peers before pruning | +| `BOOTSTRAP_PEERS` | [] | Both | List of peer multiaddrs for bootstrap | + +> **Note:** These are the production defaults used by OptimumP2P nodes. For experimental tuning, see [Common Experiments](./04-experiments.md). + diff --git a/docs/guides/04-experiments.md b/docs/guides/04-experiments.md new file mode 100644 index 0000000..3c245c0 --- /dev/null +++ b/docs/guides/04-experiments.md @@ -0,0 +1,142 @@ +# Common Experiments + +Once your OptimumP2P network is running (see [Parameters](./03-parameters.md)), you can try different experiments to understand **performance, reliability, and scaling behavior**. + +> **Before You Begin:** +> Make sure you’ve read: +> +> * [Node Modes & Config Parameters](./03-parameters.md) — to understand what each env var controls. +> * [mump2p CLI](./01-getting-started-cli.md) and [gRPC Client Setup](./02-getting-started-docker.md) — for sending and receiving test messages. + +Each experiment below lists the **goal**, a quick **how-to**, and **what to observe**. + +You can run them using: + +* **mump2p CLI** (see [CLI Guide](./01-getting-started-cli.md)) +* **gRPC client** (with `MessageTraceGossipSub` or `MessageTraceOptimumP2P` for protocol metrics) + + + +## 1. GossipSub vs OptimumP2P + +**Goal:** Compare standard libp2p gossip to RLNC-enhanced gossip to confirm OptimumP2P is faster. + +**How:** + +* Run one cluster with `NODE_MODE=gossipsub`. +* Run another with `NODE_MODE=optimum`. +* Publish the same workload to both networks. + +**Observe:** + +* **Delivery latency** (primary metric - OptimumP2P should be faster) +* **Bandwidth usage** (OptimumP2P should use less) +* **Success rate** (both should deliver messages successfully) + +**Expected Result:** OptimumP2P should show lower latency and bandwidth usage. + + +## 2. Shard Factor Sweep + +**Goal:** Find the optimal number of coded shards for your message size and network. + +**How:** + +* Test range: `OPTIMUM_SHARD_FACTOR` = 2, 4, 8, 16, 32, 64 (powers of 2 recommended). +* Keep all other parameters the same. +* Test with 1MB messages. + +**Observe:** + +* **Delivery latency** (primary metric) +* **Success rate** (messages should still deliver) + +**Expected Result:** For 1MB messages, shard factors 4-8 typically provide the best balance of performance and reliability. Too few shards (≤2) cause delivery failures, while too many shards (≥32) increase latency due to overhead. Start with shard factor 4-8 and tune based on your network conditions. + + +## 3. Forward Threshold Tuning + +**Goal:** Find the optimal threshold for forwarding coded shards early. + +**How:** + +* Fix `OPTIMUM_SHARD_FACTOR=8`. +* Test `OPTIMUM_THRESHOLD` at 0.5, 0.7, 0.9, 1.0. +* Publish small messages in a 20-30 node network. + +**Observe:** + +* **Delivery latency** (primary metric) +* **Bandwidth usage** (threshold=1.0 should use most bandwidth) + +**Expected Result:** Threshold 0.7 provides optimal performance for small networks - delivering 100% success rate with lowest latency. Thresholds below 0.6 may cause delivery failures, while values above 0.8 can reduce success rate and increase latency. + + +## 4. Mesh Density Impact + +**Goal:** Compare OptimumP2P vs GossipSub with different mesh sizes. + +**How:** + +* Test both `NODE_MODE=gossipsub` and `NODE_MODE=optimum`. +* For GossipSub: try `GOSSIPSUB_MESH_TARGET` = 4, 6, 8. +* For OptimumP2P: try `OPTIMUM_MESH_TARGET` = 6, 12, 18. +* Run the same publish/subscribe test. + +**Observe:** + +* **Delivery latency** (primary metric) +* **Bandwidth usage** + +**Expected Result:** OptimumP2P should perform better with higher mesh targets (around 12) while GossipSub optimal around 6. + + + + + +## 5. Load Test + +**Goal:** Find when OptimumP2P vs GossipSub starts to fail under stress. + +**How:** + +* Test both `NODE_MODE=gossipsub` and `NODE_MODE=optimum`. +* Vary **message size** (1KB → 10MB) and **message frequency** (1 → 1000 msg/s). +* Use multiple publishers if needed. + +**Observe:** + +* **When delivery starts to fail** (primary metric) +* **Delivery rate degradation** + +**Expected Result:** OptimumP2P should handle higher stress levels before failing compared to GossipSub. + + +> **Tip:** Enable protocol traces in the gRPC client to get hop-by-hop delivery info: +> +> * `MessageTraceGossipSub` for GossipSub mode. +> * `MessageTraceOptimumP2P` for OptimumP2P mode. + +## Metrics Collection + +For comprehensive metrics collection during experiments, use the gRPC P2P client with trace handling: + +**[P2P Client with Metrics Collection](https://github.com/getoptimum/optimum-dev-setup-guide/blob/main/grpc_p2p_client/p2p_client.go)** + +The client automatically captures and displays: + +* **GossipSub traces**: Peer routing, message delivery status, hop counts, latency +* **OptimumP2P traces**: Shard encoding/decoding, reconstruction efficiency, redundancy metrics +* **Message-level data**: Delivery success rates, end-to-end latency, bandwidth usage + +**Key trace handlers:** + +```go +case protobuf.ResponseType_MessageTraceGossipSub: + fmt.Printf("[TRACE] GossipSub trace received: %s\n", string(resp.GetData())) + +case protobuf.ResponseType_MessageTraceOptimumP2P: + fmt.Printf("[TRACE] OptimumP2P trace received: %s\n", string(resp.GetData())) +``` + +Use this client instead of the CLI for detailed performance analysis during experiments. diff --git a/docs/guides/05-faq-glossary.md b/docs/guides/05-faq-glossary.md new file mode 100644 index 0000000..c354c81 --- /dev/null +++ b/docs/guides/05-faq-glossary.md @@ -0,0 +1,104 @@ +# Frequently Asked Questions (FAQs) + +## CLI Issues + +For all CLI-related problems (authentication, installation, rate limits, connection issues), please refer to the comprehensive FAQ in the CLI repository: + +**👉 [mump2p CLI FAQ & Troubleshooting](https://github.com/getoptimum/mump2p-cli#faq---common-issues--troubleshooting)** + +It includes detailed troubleshooting for: + +* Authentication and login problems +* Installation issues across different operating systems +* Rate limiting and usage issues +* Service URL and connectivity problems +* Common syntax and usage errors + +## Docker Setup Issues + +### Identity Generation Problems + +### Q: `docker run ... generate-key` command doesn't work + +**A:** Use the identity generation script instead: + +```bash +curl -sSL https://raw.githubusercontent.com/getoptimum/optimum-dev-setup-guide/main/script/generate-identity.sh | bash +``` + +This generates `p2p.key` and exports `BOOTSTRAP_PEER_ID` automatically. + +### Container Startup Issues + +### Q: Containers fail to start or can't connect to each other + +**A:** Common fixes: + +1. **Check Docker images**: Use correct versions (`getoptimum/proxy:v0.0.1-rc3`, `getoptimum/p2pnode:v0.0.1-rc2`) +2. **Network conflicts**: Change subnet in docker-compose if `172.28.0.0/16` conflicts +3. **Port conflicts**: Ensure ports 8080, 8081, 33221, 9091, 7071 are available +4. **Platform issues**: Add `platform: linux/amd64` for M1 Macs + +### Q: "Connection refused" when clients try to connect + +**A:** Verify: + +* Containers are running: `docker ps` +* Ports are properly mapped in docker-compose +* No firewall blocking connections +* Using correct service URLs (localhost:8080 for proxy, localhost:33221 for direct P2P) + + +## gRPC Client Issues + +### Q: gRPC client gets "connection refused" or timeout errors + +**A:** Check: + +1. **Containers are running**: `docker ps` to verify proxy and p2pnode containers are up +2. **Correct ports**: Proxy gRPC on `localhost:50051`, P2P sidecar on `localhost:33221` +3. **Use latest client examples**: Reference [`optimum-dev-setup-guide/grpc_proxy_client/proxy_client.go`](https://github.com/getoptimum/optimum-dev-setup-guide/blob/main/grpc_proxy_client/proxy_client.go) + +### Q: Getting "method not found" or protobuf errors + +**A:** Use the correct protobuf definitions from [`optimum-dev-setup-guide`](https://github.com/getoptimum/optimum-dev-setup-guide): + +* [`grpc_proxy_client/proto/gateway_stream.proto`](https://github.com/getoptimum/optimum-dev-setup-guide/blob/main/grpc_proxy_client/proto/gateway_stream.proto) +* [`grpc_p2p_client/proto/p2p_stream.proto`](https://github.com/getoptimum/optimum-dev-setup-guide/blob/main/grpc_p2p_client/proto/p2p_stream.proto) + + + +## Development Issues + +### Q: Go client code compilation errors + +**A:** Use the exact Go versions and dependencies from [`optimum-dev-setup-guide`](https://github.com/getoptimum/optimum-dev-setup-guide): + +* [`grpc_proxy_client/go.mod`](https://github.com/getoptimum/optimum-dev-setup-guide/blob/main/grpc_proxy_client/go.mod) +* [`grpc_p2p_client/go.mod`](https://github.com/getoptimum/optimum-dev-setup-guide/blob/main/grpc_p2p_client/go.mod) + +### Q: Code examples don't work as expected + +**A:** All examples are tested against [`optimum-dev-setup-guide`](https://github.com/getoptimum/optimum-dev-setup-guide). Check: + +1. Environment variables are set correctly +2. Docker containers are running +3. Using the latest example code from the repository + +## General Troubleshooting + +### First Steps + +When something doesn't work: + +1. **Check container logs**: `docker logs ` +2. **Verify network connectivity**: `docker network ls` and `docker network inspect` +3. **Test basic connectivity**: `curl http://localhost:8080/health` +4. **Check authentication**: `mump2p whoami` +5. **Verify versions**: Use latest CLI and Docker images + +### Getting Help + +* **CLI Issues**: [mump2p-cli FAQ](https://github.com/getoptimum/mump2p-cli#faq---common-issues--troubleshooting) +* **Setup Issues**: Check [`optimum-dev-setup-guide`](https://github.com/getoptimum/optimum-dev-setup-guide) +* **Protocol Questions**: See [OptimumP2P Documentation](./p2p.md) diff --git a/docs/guides/overview.md b/docs/guides/overview.md new file mode 100644 index 0000000..b702ae3 --- /dev/null +++ b/docs/guides/overview.md @@ -0,0 +1,85 @@ +# Quick Start + +This developer guide is your complete reference for installing, configuring, and operating **OptimumP2P**. + +This guide walks you through everything you need to **understand**, **deploy**, **run**, and **experiment** with OptimumP2P. It's designed for beginners but complete enough for advanced developers to jump in and integrate. + +Whether you are an application developer, systems engineer, or hackathon participant, this guide will help you: + +1. **Install and run** OptimumP2P in different environments +2. **Connect clients** via gRPC, REST, or CLI +3. **Tune parameters** for performance or reliability +4. **Run experiments** to validate system behavior +5. **Monitor and debug** your deployment + +## Start Building + +Choose your path to get started with OptimumP2P: + +### **Try OptimumP2P (≤5 min)** + +**[Using mump2p-cli](01-getting-started-cli.md)** — Connect to hosted proxy, no setup required + +* One-command installation +* Instant messaging with hosted infrastructure +* Perfect for testing and prototyping + +### **Run Locally** + +**[Local Setup with Docker](02-getting-started-docker.md)** — Full control over configuration + +* Complete local network deployment +* Experiment with different parameters +* Compare OptimumP2P vs GossipSub performance + +### **Understanding & Experimenting** + +Essential for hackathon success: + +* **[Understanding Key Parameters](03-parameters.md)** — Tune thresholds, shards, and mesh settings +* **[Common Experiments](04-experiments.md)** — Test performance under different conditions +* **[FAQ](05-faq-glossary.md)** — Quick answers and debugging help + + +## What This Guide Covers + +This guide is organized into self-contained sections: + +1. **[Using mump2p-cli](01-getting-started-cli.md)** — Connect to hosted proxy with no setup required. +2. **[Local Setup with Docker](02-getting-started-docker.md)** — Run your own local proxy and P2P nodes for full control. +3. **[Understanding Key Parameters](03-parameters.md)** — Tune thresholds, shards, and mesh settings for your workload. +4. **[Common Experiments](04-experiments.md)** — Test performance and reliability under different conditions. +5. **[FAQ](05-faq-glossary.md)** — Quick answers and debugging help. + + +## Who This Guide Is For + +* **Application developers** who want to integrate fast, resilient messaging. +* **Infrastructure engineers** deploying distributed systems. +* **Hackathon teams** experimenting with real-time messaging. +* **Researchers** testing RLNC in real-world scenarios. + + +## Key Concepts + +Before diving deep, familiarize yourself with these terms and how they relate to OptimumP2P's architecture: + +| Term | Description | +|--------------|-------------| +| **Topic** | A named channel for publishing and subscribing to messages. Peers in the same topic exchange messages relevant only to that topic. | +| **Message** | The original data you publish to a topic (e.g., text, JSON, binary). | +| **Shard** | A coded fragment of a message produced by RLNC (Random Linear Network Coding). Shards allow messages to be reconstructed even if some are lost. | +| **Threshold**| The fraction of shards required to successfully decode a message. For example, a threshold of 0.7 means only 70% of shards are needed. | +| **RLNC** | Random Linear Network Coding — a technique that mixes message fragments mathematically for redundancy and efficiency. | +| **Mesh** | The set of directly connected peers in a topic. The mesh topology affects redundancy, latency, and fault tolerance. | +| **Bootstrap Node** | A known peer address used to join the P2P network and discover other peers. | +| **Optimum Proxy** | Bridge nodes between clients and the P2P mesh. It manages subscriptions, publications, and threshold logic on behalf of clients. | +| **Direct P2P Mode** | Clients connect directly to P2P nodes via gRPC without going through a proxy. This can reduce latency but requires more configuration. | +| **Mesh Parameters** | Settings such as `MESH_TARGET` that define how many peers a node tries to keep in its topic mesh. | +| **Fanout** | A temporary set of peers a publisher sends messages to when it is not part of the topic mesh. | +| **Control Messages** | Special messages like GRAFT, PRUNE, IHAVE, IWANT used for GossipSub mesh management. OptimumP2P integrates similar control flows for RLNC. | +| **Node Discovery** | The process by which proxies or nodes automatically learn about other nodes to connect to. | +| **gRPC API** | The RPC interface provided by either a P2P node or a proxy for client communication. | + +For more technical details, see the **[OptimumP2P Technical Overview](../learn/overview/p2p.md)**. + diff --git a/docs/learn/overview/deram.md b/docs/learn/overview/deram.md index 96db1ed..d4253ba 100644 --- a/docs/learn/overview/deram.md +++ b/docs/learn/overview/deram.md @@ -1,8 +1,8 @@ # Introduction to Optimum DeRAM -Optimum is a highly-effective (low-latency, high-throughput), scalable, and secure -decentralized memory (DeRAM) solution. In essence, it introduces an atomic -read/write memory designed for the Web3 environment, addressing the unique +**Optimum DeRAM (Decentralized Memory)** is a highly effective, low-latency, high-throughput, +and scalable memory abstraction built within the Optimum protocol. +In essence, it introduces an atomic read/write memory designed for the Web3 environment, addressing the unique challenges posed by asynchronous communication, high node churn, decentralized decision-making, and the presence of potentially malicious nodes. @@ -17,8 +17,10 @@ primitives. This flexibility contributes to improved durability, reduced bandwidth usage, and enhanced fault tolerance within a distributed storage framework. -Our system is implemented as a network of functionally homogeneous nodes, termed +Our system is implemented as a network of functionally hetrogeneous nodes, termed Flexnodes, which collectively provide decentralized storage and communication services. External clients can interact with any Flexnode to perform read/write operations, using this system both for data storage and as a communication socket within the network. + +**More coming soon.** diff --git a/docs/learn/overview/intro.md b/docs/learn/overview/intro.md index b2e5fc6..2eb3595 100644 --- a/docs/learn/overview/intro.md +++ b/docs/learn/overview/intro.md @@ -4,29 +4,47 @@ description: Get a quick primer on the constituent components of the Optimum pro # Introduction to Optimum -Optimum is the world’s first decentralized, high-performance memory infrastructure -for any blockchain — designed to scale data access, reduce network strain, and -power the next generation of dApps. Powered by Random Linear Network Coding (RLNC) -— a proven, MIT-developed data encoding technique — Optimum turns sluggish, -redundant networks into fast, efficient, scalable systems. - -Optimum is a decentralized network of flexnodes that can be run by anyone and -permissionlessly connect to any blockchain. - -With Optimum, blockchains gain a memory bus and RAM that rivals the performance -of modern computing. At its core, Optimum is building a provably optimal memory -infrastructure that transforms blockchains into high-speed, scalable computing -networks. The architecture is modular, permissionless, and easy to integrate via -APIs. - -Optimum's products include Optimum P2P and decentralized Random Access Memory - -DeRAM that deliver benefits across the entire blockchain ecosystem: - -* **For validators**: Accelerated data propagation, lower operational costs, - higher APY and MEV income -* **For L1 and L2 blockchains**: Faster block propagation, reduced bandwidth - consumption, and optimized storage -* **For dApp developers**: Improved transaction relay and prioritization, - enabling latency, throughput, and cost-sensitive apps -* **For end users**: Faster transactions and more responsive interfaces, improve - user experience +**Optimum** is the world's first decentralized **shared-memory and network-communication** layer for blockchains. It accelerates **low-latency gossip** across geographically distributed nodes to scale data access and reduce network congestion for latency-sensitive dApps. + +Powered by [Random Linear Network Coding (RLNC)](./p2p.md#random-linear-network-coding-rlnc-fundamentals) — a cutting-edge data encoding technique developed under the supervision of **Professor Muriel Medard, EECS, MIT**. By applying RLNC to gossip, Optimum reduces redundancy and improves loss tolerance; under standard RLNC models, the dissemination strategy is **provably optimal** for throughput/latency under loss and contention. + +**Network & roles.** Optimum runs as a permissionless network of **[flexnodes](#flexnodes)** that anyone can operate alongside existing clients and P2P stacks. + +## Products + +Builders and operators can adopt **OptimumP2P** now for measurable latency gains. DeRAM and DeROM are next to unlock low-latency reads/writes. + +### OptimumP2P + +RLNC-accelerated, libp2p/gossipsub-compatible pub/sub for fast, resilient propagation of blocks, blobs, and transactions. +**Get started:** [Overview](../../learn/overview/p2p.md) · [Quickstart](../../guides/01-getting-started-cli.md) + +### Optimum DeRAM (Decentralized Random Access Memory) + +Decentralized **read-write** memory exposing low-latency shared-state semantics across nodes. +**Get started:** [Introduction](./deram.md) + +### Optimum DeROM (Decentralized Read-Only Memory) + +Decentralized **read-only/append-oriented** memory optimized for broadcast and caching. +**Get started:** [Coming next] + +## Flexnodes + +A **flexnode** is an operator-run node that participates in Optimum's coded gossip and serves memory requests. Flexnodes: + +* encode, decode, and forward RLNC-coded gossip frames; +* maintain bounded coded buffers to recover loss and smooth tail latency; +* serve **DeRAM/DeROM** reads/writes per policy and quotas via stable APIs; +* interoperate with existing clients and libp2p/gossipsub where applicable. + +## Start here + +* **Try OptimumP2P (≤5 min):** [Using mump2p-cli](../../guides/01-getting-started-cli.md) +* **Run locally:** [Local Setup with Docker](../../guides/02-getting-started-docker.md) +* **Integrate:** [Publish/Subscribe via Optimum Proxy endpoints](https://github.com/getoptimum/optimum-dev-setup-guide) + +### Intended users + +L1/L2 teams (faster block/blob propagation); validators (lower missed-slot risk → APY/MEV uplift); node operators & builders (lower tail latency); dApp developers (faster inclusion); end users (snappier UX). + diff --git a/docs/learn/overview/p2p.md b/docs/learn/overview/p2p.md index c5b7ffa..12636ac 100644 --- a/docs/learn/overview/p2p.md +++ b/docs/learn/overview/p2p.md @@ -1,86 +1,93 @@ # OptimumP2P -OptimumP2P is a novel gossip algorithm that uses [Random Linear Network Coding (RLNC)](https://x.com/get_optimum/status/1891520664726802439) to enhance message dissemination in peer-to-peer networks. It is built on top of [libp2p](https://docs.libp2p.io/) and serves as an enhanced alternative to traditional gossip protocols like [GossipSub](https://github.com/libp2p/specs/tree/master/pubsub/gossipsub), providing faster data propagation, improved bandwidth efficiency, and better fault tolerance through network coding techniques. +**OptimumP2P** is a next-generation gossip protocol that uses [Random Linear Network Coding (RLNC)](https://x.com/get_optimum/status/1891520664726802439) to revolutionize message dissemination in peer-to-peer networks. Built on [libp2p](https://docs.libp2p.io/), it offers a high-performance alternative to traditional protocols like [GossipSub](https://github.com/libp2p/specs/tree/master/pubsub/gossipsub), delivering faster propagation, better bandwidth efficiency, and better fault tolerance using network coding. + ## How OptimumP2P Works -OptimumP2P is a gossip mechanism based on RLNC, also known as Galois Gossip, that builds upon [libp2p](https://docs.libp2p.io/)'s [GossipSub](https://github.com/libp2p/specs/tree/master/pubsub/gossipsub) protocol. Instead of transmitting complete messages between peers, OptimumP2P breaks messages into coded shards that can be independently forwarded and mathematically recombined to reconstruct the original data. +OptimumP2P is a gossip mechanism based on RLNC, also known as **Galois Gossip**, that builds upon [libp2p](https://docs.libp2p.io/)'s [GossipSub](https://github.com/libp2p/specs/tree/master/pubsub/gossipsub) protocol. Instead of transmitting complete messages between peers, OptimumP2P breaks messages into coded shards that can be independently forwarded and mathematically recombined to reconstruct the original data. ### Node Architecture -OptimumP2P is implemented as a P2P node that enhances traditional gossip protocols with RLNC capabilities. The node maintains: +Each OptimumP2P node is a standard libp2p host enhanced with RLNC logic. Core components include: -* **[libp2p](https://docs.libp2p.io/) Host**: The underlying network layer for peer connections -* **Mesh Topology**: Maintains peer connections similar to [GossipSub](https://github.com/libp2p/specs/tree/master/pubsub/gossipsub) with configurable mesh degrees -* **RLNC Parameters**: Configurable parameters for encoding and forwarding behavior (see [Configuration Parameters](#configuration-parameters)) +* **libp2p Host** – Provides peer discovery, secure communication, and network transport. +* **Mesh Topology** – Maintains a configurable gossip mesh with peer degrees similar to GossipSub. +* **RLNC** – Manages encoding, recoding, and decoding of shards based on tunable parameters. + +> See [Configuration Parameters](#configuration-parameters) for details. ### Random Linear Network Coding (RLNC) Fundamentals -RLNC is the core technology that provides OptimumP2P its performance advantages. The process transforms a single large message into a set of smaller, mathematically-related pieces. +RLNC enables performance gains by dividing messages into linearly coded shards. These shards can be forwarded, recombined, and decoded efficiently without requiring complete message delivery. ![RLNC Coding and Composability](/static/img/rlnc.png) -**Key Principles:** +#### Key Concepts -* **Encoding**: Original data is divided into `k` pieces. These pieces are then used to generate a larger set of `n` coded shards by creating random linear combinations of the original pieces. The coefficients for these combinations are chosen from a finite field to ensure linear independence. -* **Early Forwarding & Composability**: A key feature of RLNC is that nodes do not need to wait to receive all `k` pieces to contribute to the network. As soon as a node receives a shard, it can be combined with other received shards to create and forward a *new, unique* coded shard (a process called recoding). This continuous "mixing" of information allows data to propagate fluidly and rapidly. -* **Decoding**: A receiver only needs to collect *any* `k` linearly independent shards to reconstruct the original message by solving a system of linear equations. This makes the system highly resilient to packet loss, as the specific shards that arrive do not matter, only the total number of unique shards. +* **Encoding**: The original message is split into `k` fragments. These are used to produce `n` coded shards via random linear combinations over a finite field, ensuring uniqueness and redundancy. +* **Recoding (Composability)**: Any node that receives a shard can immediately create a new coded shard from its current shard set — without waiting for the full message. This enables continuous, fast, and fault-tolerant propagation. +* **Decoding**: Nodes only need `k` linearly independent shards to reconstruct the original message using linear algebra (matrix inversion). This ensures high resilience to data loss. -This approach offers several advantages: +#### Benefits * **Lower Latency**: Messages are broken into coded shards, which can be forwarded to the next node before the whole message is received. -* **Loss Tolerance**: Messages can be decoded with any combination of shards, as long as a sufficient number reach the destination. +* **High Loss Tolerance**: Messages can be decoded with any combination of shards, as long as a sufficient number reach the destination. * **Bandwidth Efficiency**: Sharding and recoding reduce the amount of redundant data transmission, lowering overall bandwidth usage. -### Protocol Operation - -When a node publishes a message in OptimumP2P: +## Protocol Operation -1. **Message Preparation**: The original message is prepared for coding by adding length prefixes and padding if necessary -2. **RLNC Encoding**: The message is divided into `k` fragments and encoded using RLNC into multiple shards using configurable parameters: - * `ShredFactor`: Controls how the data is fragmented - * `PublisherShardMultiplier`: Determines how many shards to create initially -3. **Coded Shard Distribution**: The publisher sends different coded shards to different peers in round-robin fashion +### When Publishing When a node receives a shard: -1. **Validation**: The node checks if the shard provides new degrees of freedom (linearly independent information) -2. **Storage**: Valid shards are added to the node's shard set for that message -3. **Decoding Attempt**: If the node has collected `k` or more linearly independent shards, it attempts to decode the original message -4. **Forwarding Logic**: - * **From Publisher**: Coded shards received directly from the publisher are forwarded immediately to all mesh peers - * **From Intermediate Nodes**: If the node has more than a threshold number of shards (`ForwardShardThreshold`), it creates a new recoded shard and forwards it to mesh peers +1. **Message Preparation**: Add length prefix and pad if necessary. +2. **Encoding**: + * Fragment the message using `ShredFactor` + * Generate coded shards: `num_shards = ShredFactor * PublisherShardMultiplier` +3. **Shard Distribution**: Send different coded shards to different peers in round-robin fashion. + +### When Receiving a Shard + +1. **Validation**: Check for linear independence; discard redundant shards. +2. **Storage**: Add to shard set for that message. +3. **Decoding**: Attempt decoding once `k` unique shards are available. +4. **Forwarding**: + * `From Publisher`: Shards are immediately forwarded to all mesh peers. + * `From Peers`: If shard count exceeds `ForwardShardThreshold`, generate and forward a recoded shard. + +--- ### Control Messages -OptimumP2P uses control messages similar to [GossipSub](https://github.com/libp2p/specs/tree/master/pubsub/gossipsub) to optimize traffic: +OptimumP2P uses and extends [GossipSub's](https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.0.md#control-messages) control messages for optimized mesh performance: -* **IDONTWANT**: Announced when a node has successfully decoded a message, preventing peers from sending more coded shards for that message -* **IHAVE**: Announces that a node has a complete message and can provide coded shards to other nodes -* **IWANT**: Requests additional coded shards for a message that hasn't been fully decoded -* **GRAFT/PRUNE**: Manages mesh topology similar to [GossipSub](https://github.com/libp2p/specs/tree/master/pubsub/gossipsub) +| Message | Purpose | +|-------------|-------------------------------------------------------------------------| +| `IDONTWANT` | Informs peers not to send more shards for a decoded message | +| `IHAVE` | Advertises that a node holds coded shards for a message | +| `IWANT` | Requests additional shards for an undecoded message | +| `GRAFT`/`PRUNE` | Maintains optimal mesh size by adding/removing peers dynamically | ## Configuration Parameters OptimumP2P provides several configurable parameters to tune performance for different network conditions and requirements: -### RLNC Encoding Parameters +### RLNC Encoding -* **ShredFactor**: Controls how the data is fragmented into pieces before encoding. Higher values provide more granular sharding but increase computational overhead. -* **PublisherShardMultiplier**: Determines how many coded shards to create initially when publishing a message. Formula: `coded_shards_created = ShredFactor * PublisherShardMultiplier` -* **ForwardShardThreshold**: Sets the threshold for intermediate nodes to create and forward new recoded shards. Nodes forward when they have more than `ShredFactor * ForwardShardThreshold` shards +* **ShredFactor**: Number of base fragments to split a message into before encoding. Higher values provide more granular sharding but increase computational overhead. +* **PublisherShardMultiplier**: Determines how many coded shards to create initially when publishing a message. Formula: `coded_shards_created = ShredFactor * PublisherShardMultiplier`. +* **ForwardShardThreshold**: Sets the threshold for intermediate nodes to create and forward new recoded shards. Nodes forward when they have more than `ShredFactor * ForwardShardThreshold` shards. ### Mesh Topology Parameters -* **MeshDegreeTarget**: Target number of peers to maintain in the mesh overlay -* **MeshDegreeMin**: Minimum number of mesh peers before triggering grafting -* **MeshDegreeMax**: Maximum number of mesh peers before triggering pruning - -### Performance Tuning +OptimumP2P builds upon libp2p's [GossipSub mesh topology](https://docs.libp2p.io/concepts/pubsub/overview/#full-message), where peers maintain **full-message peerings** for reliable data transmission and **metadata-only peerings** for gossip and network maintenance. -* **RandomMessageSize**: Default message size used for testing and benchmarking (in bytes) +* **MeshDegreeTarget**: Target number of peers to maintain in the mesh overlay. This controls the trade-off between speed, reliability, resilience and efficiency of the network. A higher peering degree helps messages get delivered faster with better reliability, but increases bandwidth usage due to redundant message copies. +* **MeshDegreeMin**: Minimum number of mesh peers before triggering [grafting](https://docs.libp2p.io/concepts/pubsub/overview/#grafting-and-pruning) (converting metadata-only connections to full-message). +* **MeshDegreeMax**: Maximum number of mesh peers before triggering [pruning](https://docs.libp2p.io/concepts/pubsub/overview/#grafting-and-pruning) (converting full-message peerings back to metadata-only). -These parameters can be adjusted based on network conditions, bandwidth constraints, and latency requirements to optimize OptimumP2P performance for specific use cases. +In libp2p's default implementation, the ideal network peering degree is 6 with anywhere from 4–12 being acceptable. OptimumP2P inherits these mesh management mechanisms while optimizing shard propagation through the established topology. ## Use Cases @@ -90,12 +97,13 @@ OptimumP2P serves as a foundational, general-purpose data propagation protocol w OptimumP2P supercharges validator and full node performance in bandwidth-constrained and latency-sensitive networks: -* **[Ethereum](https://ethereum.org/)**: Faster mempool propagation, lower uncle rates, and potential integration into both execution and consensus paths -* **[Solana](https://solana.com/)**: Enhances Turbine-style data sharding with fault-tolerant packet loss recovery -* **[Cosmos](https://cosmos.network/) & IBC networks**: Strengthens interchain relaying with lower-latency packet delivery and cross-zone message reliability +* **[Ethereum](https://ethereum.org/)**: Faster mempool propagation, lower uncle rates, and potential integration into both execution and consensus layers. +* **[Solana](https://solana.com/)**: Enhances Turbine-style data sharding with fault-tolerant packet loss recovery. +* **[Cosmos](https://cosmos.network/) & IBC networks**: Low-latency interchain packet routing and zone-to-zone messaging. -### DeFi Chains +### DeFi, AI, DePIN, Gaming & Social Chains + + ## Security Model -OptimumP2P's security model is built upon the robust foundations of **[libp2p](https://docs.libp2p.io/)**. As such, it inherits a comprehensive suite of security features designed for hostile peer-to-peer environments. For a full overview of these protections, refer to the [libp2p security considerations](https://docs.libp2p.io/concepts/security/security-considerations/). +OptimumP2P inherits libp2p’s robust security foundation, and adds safeguards specific to network coding. -Key inherited security features include: +### Inherited from libp2p * **Authenticated and Encrypted Channels**: All peer-to-peer communication is secured using [Noise](https://noiseprotocol.org/) or [TLS](https://tools.ietf.org/html/rfc8446), preventing eavesdropping and tampering. * **Sybil and Eclipse Attack Mitigation**: The protocol uses [libp2p](https://docs.libp2p.io/)'s peer discovery and management systems, which include defenses against an attacker flooding the network with malicious nodes to gain control or isolate honest peers. -### Network Coding-Specific Security: Pollution Attacks +For a full overview of these protections, refer to the [libp2p security considerations](https://docs.libp2p.io/concepts/security/security-considerations/). + +### OptimumP2P avoids Pollution Attacks -The primary security challenge unique to network coding is the risk of **pollution attacks**. In such an attack, a malicious actor injects corrupted or invalid coded shards into the network, with the goal of preventing honest nodes from successfully decoding the original message. +In **pollution attacks** attack, a malicious actor injects corrupted or invalid coded shards into the network, with the goal of preventing honest nodes from successfully decoding the original message. OptimumP2P mitigates this risk through a multi-layered approach centered on **source authentication**. diff --git a/docs/research/gossip/decentralized-access.md b/docs/research/gossip/decentralized-access.md index 79fed56..174e861 100644 --- a/docs/research/gossip/decentralized-access.md +++ b/docs/research/gossip/decentralized-access.md @@ -6,8 +6,34 @@ *[Joint Optimization of Storage and Transmission via Coding Traffic Flows for Content Distribution](https://ece.northeastern.edu/fac-ece/ioannidis/static/pdf/2023/m7210-malak-final.pdf)*, **WiOpt**, (Best Paper Award), August 2023. +## [2022] + +**Nicolas Nicolaou, Viveck R. Cadambe, N. Prakash, Andria Trigeorgi, Kishori M. Konwar, Muriel Médard, Nancy A. Lynch**, +*[ARES: Adaptive, Reconfigurable, Erasure coded, Atomic Storage](https://dl.acm.org/doi/10.1145/3510613)*, +**ACM Transactions on Storage**, vol. 18, no. 4, pp. 33:1-33:39, 2022. + +## [2021] + +**Guo-Shu Gao, Kishori M. Konwar, Juan Mantica, Haochen Pan, Darius Russell Kish, Lewis Tseng, Zezhi Wang, Yingjian Wu**, +*[Practical Experience Report: Cassandra+: Trading-Off Consistency, Latency, and Fault-tolerance in Cassandra](https://par.nsf.gov/servlets/purl/10283392)*, +**ICDCN**, pp. 191-195, 2021. + +## [2020] + +**Viveck R. Cadambe, Kishori M. Konwar, Muriel Médard, Haochen Pan, Lewis Tseng, Yingjian Wu**, +*[CassandrEAS: Highly Available and Storage-Efficient Distributed Key-Value Store with Erasure Coding](https://ieeexplore.ieee.org/document/9309315)*, +**NCA**, pp. 1-8, 2020. + ## [2019] +**Nicolas C. Nicolaou, Viveck R. Cadambe, N. Prakash, Kishori M. Konwar, Muriel Médard, Nancy A. Lynch**, +*[ARES: Adaptive, Reconfigurable, Erasure Coded, Atomic Storage](https://arxiv.org/abs/1805.03727)*, +**ICDCS**, pp. 2195-2205, 2019. + +**Kishori M. Konwar, N. Prakash, Muriel Médard, Nancy A. Lynch**, +*[Fast Lean Erasure-Coded Atomic Memory Object](https://drops.dagstuhl.de/entities/document/10.4230/LIPIcs.OPODIS.2019.12)*, +**OPODIS**, pp. 12:1-12:17, 2019. + **P. J. Braun, Malak, D., Médard, M., and Ekler, P.**, *[Enabling multi-source coded downloads](https://drive.google.com/file/d/1s8NkV3flsnfyxGYpLtphutWsFgk8mDzk/view?usp=sharing)*, **IEEE International Conference on EDGE Computing (EDGE)**, 2019. @@ -30,10 +56,24 @@ ## [2017] +**Kishori M. Konwar, N. Prakash, Nancy A. Lynch, Muriel Médard**, +*[A Layered Architecture for Erasure-Coded Consistent Distributed Storage](https://dl.acm.org/doi/10.1145/3087801.3087809)*, +**PODC**, pp. 63-72, 2017. + **C. W. Sørensen, Lucani, D. E., and Médard, M.**, *[On Network Coded File System Shim: Over-the-top Multipath Multi-Source Made Easy](https://drive.google.com/file/d/17FUlu3dWcFa4X9L2SATMVD-rRpb6pzkM/view?usp=drive_link)*, **IEEE ICC SAC Symposium Cloud Communications and Networking Track**, 2017. +## [2016] + +**Kishori M. Konwar, N. Prakash, Erez Kantor, Nancy A. Lynch, Muriel Médard, Alexander A. Schwarzmann**, +*[Storage-Optimized Data-Atomic Algorithms for Handling Erasures and Errors in Distributed Storage Systems](https://ieeexplore.ieee.org/document/7516084)*, +**IPDPS**, pp. 720-729, 2016. + +**Kishori M. Konwar, N. Prakash, Nancy A. Lynch, Muriel Médard**, +*[RADON: Repairable Atomic Data Object in Networks](https://drops.dagstuhl.de/entities/document/10.4230/LIPIcs.OPODIS.2016.28)*, +**OPODIS**, pp. 28:1-28:17, 2016. + ## [2014] **F. H. P. Fitzek, Toth, T., Szabados, A., Pederson, M. V., Lucani, D. E., Sipos, M., Charaf, H., and Médard, M.**, diff --git a/index.md b/index.md index ba25200..6750a5e 100644 --- a/index.md +++ b/index.md @@ -13,20 +13,17 @@ hero: actions: - theme: brand text: Get Started - link: /docs/how-to-guides/overview - - theme: alt - text: Introduction link: /docs/learn/overview/intro features: - - title: Overview + - title: Learn Optimum details: Learn more about Optimum, the various components involved, and how it could benefit your project. link: /docs/learn/overview/intro icon: 🎓 - - title: How-to Guides (Under Construction 🚧) - details: Explore step-by-step guides for running and integrating with various types of nodes, how to read and write data, and how to gossip. - # link: /docs/how-to-guides/overview - icon: ⚙️ + - title: Quickstart & Developer Guide + details: Complete guide for building applications on OptimumP2P with deployment options, client examples, and configuration. + link: /docs/guides/overview + icon: 🚀 - title: Research details: Access resources for understanding the inner workings of Optimum and the research behind the technology. link: /docs/research/overview diff --git a/package.json b/package.json index f2211cb..f66540c 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ }, "devDependencies": { "@eslint/js": "^9.22.0", + "@types/node": "^24.1.0", "@typescript-eslint/eslint-plugin": "^8.26.1", "@typescript-eslint/parser": "^8.26.1", "eslint": "^9.22.0", diff --git a/static/img/P2P_data_flow_dark.png b/static/img/P2P_data_flow_dark.png new file mode 100644 index 0000000..bf3a3e2 Binary files /dev/null and b/static/img/P2P_data_flow_dark.png differ diff --git a/static/img/P2P_data_flow_light.png b/static/img/P2P_data_flow_light.png new file mode 100644 index 0000000..6de7ae1 Binary files /dev/null and b/static/img/P2P_data_flow_light.png differ diff --git a/static/img/docker_1.png b/static/img/docker_1.png new file mode 100644 index 0000000..679bf96 Binary files /dev/null and b/static/img/docker_1.png differ diff --git a/static/img/docker_2.png b/static/img/docker_2.png new file mode 100644 index 0000000..d287ca8 Binary files /dev/null and b/static/img/docker_2.png differ diff --git a/static/img/img_2.png b/static/img/img_2.png new file mode 100644 index 0000000..fda31da Binary files /dev/null and b/static/img/img_2.png differ diff --git a/static/img/mump2p.png b/static/img/mump2p.png new file mode 100644 index 0000000..c96f2be Binary files /dev/null and b/static/img/mump2p.png differ diff --git a/yarn.lock b/yarn.lock index fc4f605..52ee578 100644 --- a/yarn.lock +++ b/yarn.lock @@ -54,11 +54,6 @@ resolved "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.20.4.tgz" integrity sha512-OCGa8hKAP6kQKBwi+tu9flTXshz4qeCK5P8J6bI1qq8KYs+/TU1xSotT+E7hO+uyDanGU6dT6soiMSi4A38JgA== -"@algolia/client-common@5.34.1": - version "5.34.1" - resolved "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.34.1.tgz" - integrity sha512-otPWALs72KvmVuP0CN0DI6sqVx1jQWKi+/DgAiP8DysVMgiNlva3GDKTtAK6XVGlT08f4h32FNuL0yQODuCfKA== - "@algolia/client-insights@5.20.4": version "5.20.4" resolved "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.20.4.tgz" @@ -89,16 +84,6 @@ "@algolia/requester-fetch" "5.20.4" "@algolia/requester-node-http" "5.20.4" -"@algolia/client-search@>= 4.9.1 < 6": - version "5.34.1" - resolved "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.34.1.tgz" - integrity sha512-bt5hC9vvjaKvdvsgzfXJ42Sl3qjQqoi/FD8V7HOQgtNFhwSauZOlgLwFoUiw67sM+r7ehF7QDk5WRDgY7fAkIg== - dependencies: - "@algolia/client-common" "5.34.1" - "@algolia/requester-browser-xhr" "5.34.1" - "@algolia/requester-fetch" "5.34.1" - "@algolia/requester-node-http" "5.34.1" - "@algolia/client-search@5.20.4": version "5.20.4" resolved "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.20.4.tgz" @@ -146,13 +131,6 @@ dependencies: "@algolia/client-common" "5.20.4" -"@algolia/requester-browser-xhr@5.34.1": - version "5.34.1" - resolved "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.34.1.tgz" - integrity sha512-567LfFTc9VOiPtuySQohoqaWMeohYWbXK71aMSin+SLMgeKX7hz5LrVmkmMQj9udwWK6/mtHEYZGPYHSuXpLQg== - dependencies: - "@algolia/client-common" "5.34.1" - "@algolia/requester-fetch@5.20.4": version "5.20.4" resolved "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.20.4.tgz" @@ -160,13 +138,6 @@ dependencies: "@algolia/client-common" "5.20.4" -"@algolia/requester-fetch@5.34.1": - version "5.34.1" - resolved "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.34.1.tgz" - integrity sha512-YRbygPgGBEik5U593JvyjgxFjcsyZMR25eIQxNHvSQumdAzt5A4E4Idw3yXnwhrmMdjML54ZXT7EAjnTjWy8Xw== - dependencies: - "@algolia/client-common" "5.34.1" - "@algolia/requester-node-http@5.20.4": version "5.20.4" resolved "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.20.4.tgz" @@ -174,13 +145,6 @@ dependencies: "@algolia/client-common" "5.20.4" -"@algolia/requester-node-http@5.34.1": - version "5.34.1" - resolved "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.34.1.tgz" - integrity sha512-o0mqRYbS82Rt4DE02Od7RL6pNtV7oSxScPuIw8LW4aqO2V5eCF05Pry/SnUgcI/Vb2QCYC66hytBCqzyC/toZA== - dependencies: - "@algolia/client-common" "5.34.1" - "@babel/helper-string-parser@^7.27.1": version "7.27.1" resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz" @@ -191,7 +155,7 @@ resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz" integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== -"@babel/parser@^7.23.5", "@babel/parser@^7.25.3": +"@babel/parser@^7.25.3": version "7.28.0" resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz" integrity sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g== @@ -241,16 +205,16 @@ resolved "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz" integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== -"@esbuild/android-arm@0.21.5": - version "0.21.5" - resolved "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz" - integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== - "@esbuild/android-arm64@0.21.5": version "0.21.5" resolved "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz" integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== +"@esbuild/android-arm@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz" + integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== + "@esbuild/android-x64@0.21.5": version "0.21.5" resolved "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz" @@ -276,16 +240,16 @@ resolved "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz" integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== -"@esbuild/linux-arm@0.21.5": - version "0.21.5" - resolved "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz" - integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== - "@esbuild/linux-arm64@0.21.5": version "0.21.5" resolved "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz" integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== +"@esbuild/linux-arm@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz" + integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== + "@esbuild/linux-ia32@0.21.5": version "0.21.5" resolved "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz" @@ -399,7 +363,7 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@^9.22.0", "@eslint/js@9.22.0": +"@eslint/js@9.22.0", "@eslint/js@^9.22.0": version "9.22.0" resolved "https://registry.npmjs.org/@eslint/js/-/js-9.22.0.tgz" integrity sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ== @@ -482,7 +446,7 @@ "@nodelib/fs.stat" "2.0.5" run-parallel "^1.1.9" -"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== @@ -595,7 +559,7 @@ resolved "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.35.0.tgz" integrity sha512-PIQeY5XDkrOysbQblSW7v3l1MDZzkTEzAfTPkj5VAu3FW8fS4ynyLg2sINp0fp3SjZ8xkRYpLqoKcYqAkhU1dw== -"@shikijs/core@^2.1.0", "@shikijs/core@2.5.0": +"@shikijs/core@2.5.0", "@shikijs/core@^2.1.0": version "2.5.0" resolved "https://registry.npmjs.org/@shikijs/core/-/core-2.5.0.tgz" integrity sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg== @@ -646,7 +610,7 @@ "@shikijs/core" "2.5.0" "@shikijs/types" "2.5.0" -"@shikijs/types@^2.1.0", "@shikijs/types@2.5.0": +"@shikijs/types@2.5.0", "@shikijs/types@^2.1.0": version "2.5.0" resolved "https://registry.npmjs.org/@shikijs/types/-/types-2.5.0.tgz" integrity sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw== @@ -666,7 +630,7 @@ dependencies: "@types/ms" "*" -"@types/estree@^1.0.6", "@types/estree@1.0.6": +"@types/estree@1.0.6", "@types/estree@^1.0.6": version "1.0.6" resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz" integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== @@ -718,6 +682,13 @@ resolved "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz" integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== +"@types/node@^24.1.0": + version "24.2.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-24.2.0.tgz#cde712f88c5190006d6b069232582ecd1f94a760" + integrity sha512-3xyG3pMCq3oYCNg7/ZP+E1ooTaGB4cG8JWRsqqOYQdbWNY4zbaV0Ennrd7stjiJEFZCaybcIgpTjJWHRfBSIDw== + dependencies: + undici-types "~7.10.0" + "@types/unist@*", "@types/unist@^2.0.0": version "2.0.11" resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz" @@ -733,7 +704,7 @@ resolved "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz" integrity sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA== -"@typescript-eslint/eslint-plugin@^8.26.1", "@typescript-eslint/eslint-plugin@8.26.1": +"@typescript-eslint/eslint-plugin@8.26.1", "@typescript-eslint/eslint-plugin@^8.26.1": version "8.26.1" resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.1.tgz" integrity sha512-2X3mwqsj9Bd3Ciz508ZUtoQQYpOhU/kWoUqIf49H8Z0+Vbh6UF/y0OEYp0Q0axOGzaBGs7QxRwq0knSQ8khQNA== @@ -748,7 +719,7 @@ natural-compare "^1.4.0" ts-api-utils "^2.0.1" -"@typescript-eslint/parser@^8.0.0 || ^8.0.0-alpha.0", "@typescript-eslint/parser@^8.26.1", "@typescript-eslint/parser@8.26.1": +"@typescript-eslint/parser@8.26.1", "@typescript-eslint/parser@^8.26.1": version "8.26.1" resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.26.1.tgz" integrity sha512-w6HZUV4NWxqd8BdeFf81t07d7/YV9s7TCWrQQbG5uhuvGUAW+fq1usZ1Hmz9UPNLniFnD8GLSsDpjP0hm1S4lQ== @@ -843,17 +814,6 @@ "@vue/compiler-core" "3.5.13" "@vue/shared" "3.5.13" -"@vue/compiler-sfc@2.7.16": - version "2.7.16" - resolved "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.16.tgz" - integrity sha512-KWhJ9k5nXuNtygPU7+t1rX6baZeqOYLEforUPjgNDBnLicfHCoi48H87Q8XyLZOrNNsmhuwKqtpDQWjEFe6Ekg== - dependencies: - "@babel/parser" "^7.23.5" - postcss "^8.4.14" - source-map "^0.6.1" - optionalDependencies: - prettier "^1.18.2 || ^2.0.0" - "@vue/compiler-sfc@3.5.13": version "3.5.13" resolved "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz" @@ -937,12 +897,12 @@ "@vue/compiler-ssr" "3.5.13" "@vue/shared" "3.5.13" -"@vue/shared@^3.5.13", "@vue/shared@3.5.13": +"@vue/shared@3.5.13", "@vue/shared@^3.5.13": version "3.5.13" resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz" integrity sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ== -"@vueuse/core@^12.4.0", "@vueuse/core@12.8.2": +"@vueuse/core@12.8.2", "@vueuse/core@^12.4.0": version "12.8.2" resolved "https://registry.npmjs.org/@vueuse/core/-/core-12.8.2.tgz" integrity sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ== @@ -978,7 +938,7 @@ acorn-jsx@^5.3.2: resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.14.0: +acorn@^8.14.0: version "8.14.1" resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz" integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== @@ -993,7 +953,7 @@ ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -algoliasearch@^5.14.2, "algoliasearch@>= 4.9.1 < 6": +algoliasearch@^5.14.2: version "5.20.4" resolved "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.20.4.tgz" integrity sha512-wjfzqruxovJyDqga8M6Xk5XtfuVg3igrWjhjgkRya87+WwfEa1kg+IluujBLzgAiMSd6rO6jqRb7czjgeeSYgQ== @@ -1041,17 +1001,7 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -ansi-styles@^6.0.0: - version "6.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz" - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== - -ansi-styles@^6.1.0: - version "6.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz" - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== - -ansi-styles@^6.2.1: +ansi-styles@^6.0.0, ansi-styles@^6.1.0, ansi-styles@^6.2.1: version "6.2.1" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== @@ -1211,6 +1161,11 @@ comma-separated-tokens@^2.0.0: resolved "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz" integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg== +commander@9.2.0: + version "9.2.0" + resolved "https://registry.npmjs.org/commander/-/commander-9.2.0.tgz" + integrity sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w== + commander@^13.1.0, commander@~13.1.0: version "13.1.0" resolved "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz" @@ -1226,11 +1181,6 @@ commander@^8.3.0: resolved "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== -commander@9.2.0: - version "9.2.0" - resolved "https://registry.npmjs.org/commander/-/commander-9.2.0.tgz" - integrity sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" @@ -1273,7 +1223,7 @@ cssesc@^3.0.0: resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== -csstype@^3.1.0, csstype@^3.1.3: +csstype@^3.1.3: version "3.1.3" resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz" integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== @@ -1386,12 +1336,7 @@ entities@^2.0.0: resolved "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== -entities@^4.4.0: - version "4.5.0" - resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz" - integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== - -entities@^4.5.0: +entities@^4.4.0, entities@^4.5.0: version "4.5.0" resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== @@ -1470,7 +1415,7 @@ eslint-visitor-keys@^4.2.0: resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz" integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== -"eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^8.57.0 || ^9.0.0", eslint@^9.22.0: +eslint@^9.22.0: version "9.22.0" resolved "https://registry.npmjs.org/eslint/-/eslint-9.22.0.tgz" integrity sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ== @@ -1642,7 +1587,7 @@ flatted@^3.2.9: resolved "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz" integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== -focus-trap@^7, focus-trap@^7.6.4: +focus-trap@^7.6.4: version "7.6.4" resolved "https://registry.npmjs.org/focus-trap/-/focus-trap-7.6.4.tgz" integrity sha512-xx560wGBk7seZ6y933idtjJQc1l+ck+pI3sKvhKozdBV1dRZoKhkW5xoCaFv9tQiX5RH1xfSxjuNu6g+lmN/gw== @@ -2043,7 +1988,7 @@ mark.js@8.11.1: resolved "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz" integrity sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ== -markdown-it-mathjax3@^4, markdown-it-mathjax3@^4.3.2: +markdown-it-mathjax3@^4.3.2: version "4.3.2" resolved "https://registry.npmjs.org/markdown-it-mathjax3/-/markdown-it-mathjax3-4.3.2.tgz" integrity sha512-TX3GW5NjmupgFtMJGRauioMbbkGsOXAAt1DZ/rzzYmTHqzkO1rNAdiMD4NiruurToPApn2kYy76x02QN26qr2w== @@ -2144,7 +2089,7 @@ mhchemparser@^4.1.0: resolved "https://registry.npmjs.org/mhchemparser/-/mhchemparser-4.2.1.tgz" integrity sha512-kYmyrCirqJf3zZ9t/0wGgRZ4/ZJw//VwaRVGA75C4nhE60vtnIzhl9J9ndkX/h6hxSN7pjg/cE0VxbnNM+bnDQ== -micromark-core-commonmark@^2.0.0, micromark-core-commonmark@2.0.2: +micromark-core-commonmark@2.0.2, micromark-core-commonmark@^2.0.0: version "2.0.2" resolved "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.2.tgz" integrity sha512-FKjQKbxd1cibWMM1P9N+H8TwlgGgSkWZMmfuVucLCHaYqeSvJ0hFeHsIa65pA2nYbes0f8LDHPMrd9X7Ujxg9w== @@ -2361,7 +2306,7 @@ micromark-util-symbol@^2.0.0: resolved "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz" integrity sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q== -micromark-util-types@^2.0.0, micromark-util-types@2.0.1: +micromark-util-types@2.0.1, micromark-util-types@^2.0.0: version "2.0.1" resolved "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.1.tgz" integrity sha512-534m2WhVTddrcKVepwmVEVnUAmtrx9bfIjNoQHRqfnvdaHQiFytEhJoTgpWJvDEXCO5gLTQh3wYC1PgOJA4NSQ== @@ -2629,7 +2574,7 @@ postcss-selector-parser@^6.0.15: cssesc "^3.0.0" util-deprecate "^1.0.2" -postcss@^8, postcss@^8.4.14, postcss@^8.4.43, postcss@^8.4.48: +postcss@^8.4.43, postcss@^8.4.48: version "8.5.3" resolved "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz" integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A== @@ -2648,11 +2593,6 @@ prelude-ls@^1.2.1: resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -"prettier@^1.18.2 || ^2.0.0": - version "2.8.8" - resolved "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz" - integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== - prettier@^3.5.3: version "3.5.3" resolved "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz" @@ -2770,11 +2710,6 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -"search-insights@>= 1 < 3": - version "2.17.3" - resolved "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz" - integrity sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ== - select@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/select/-/select-1.1.2.tgz" @@ -2847,11 +2782,6 @@ source-map-js@^1.2.0, source-map-js@^1.2.1: resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== -source-map@^0.6.1: - version "0.6.1" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - space-separated-tokens@^2.0.0: version "2.0.2" resolved "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz" @@ -3018,7 +2948,7 @@ typescript-eslint@^8.26.1: "@typescript-eslint/parser" "8.26.1" "@typescript-eslint/utils" "8.26.1" -typescript@*, typescript@^5.2.2, typescript@>=4.8.4, "typescript@>=4.8.4 <5.9.0": +typescript@^5.2.2: version "5.8.2" resolved "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz" integrity sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ== @@ -3028,6 +2958,11 @@ uc.micro@^2.0.0, uc.micro@^2.1.0: resolved "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz" integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A== +undici-types@~7.10.0: + version "7.10.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.10.0.tgz#4ac2e058ce56b462b056e629cc6a02393d3ff350" + integrity sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag== + unist-util-is@^6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz" @@ -3109,7 +3044,7 @@ vfile@^6.0.0: "@types/unist" "^3.0.0" vfile-message "^4.0.0" -"vite@^5.0.0 || ^6.0.0", vite@^5.4.14: +vite@^5.4.14: version "5.4.14" resolved "https://registry.npmjs.org/vite/-/vite-5.4.14.tgz" integrity sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA== @@ -3151,7 +3086,7 @@ vue-clipboard2@^0.3.3: dependencies: clipboard "^2.0.0" -vue-eslint-parser@^10.0.0, vue-eslint-parser@^10.1.1: +vue-eslint-parser@^10.1.1: version "10.1.1" resolved "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.1.1.tgz" integrity sha512-bh2Z/Au5slro9QJ3neFYLanZtb1jH+W2bKqGHXAoYD4vZgNG3KeotL7JpPv5xzY4UXUXJl7TrIsnzECH63kd3Q== @@ -3171,15 +3106,7 @@ vue-resize@^1.0.1: dependencies: "@babel/runtime" "^7.13.10" -vue@^2.6.0: - version "2.7.16" - resolved "https://registry.npmjs.org/vue/-/vue-2.7.16.tgz" - integrity sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw== - dependencies: - "@vue/compiler-sfc" "2.7.16" - csstype "^3.1.0" - -vue@^3.2.25, vue@^3.5.13, vue@3.5.13: +vue@^3.5.13: version "3.5.13" resolved "https://registry.npmjs.org/vue/-/vue-3.5.13.tgz" integrity sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==