From bb0500d935cbc31f243df9de685266251c151382 Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sat, 2 May 2026 17:33:17 +0000 Subject: [PATCH 01/23] contrib/net-profiler --- contrib/network-profiler/.gitignore | 4 + contrib/network-profiler/README.md | 75 +++++++++ .../network_profiler/__init__.py | 5 + .../network_profiler/__main__.py | 4 + .../network-profiler/network_profiler/cli.py | 67 ++++++++ .../network_profiler/measure.py | 149 ++++++++++++++++++ .../network_profiler/model.py | 60 +++++++ .../network_profiler/remote.py | 80 ++++++++++ .../network_profiler/render.py | 131 +++++++++++++++ contrib/network-profiler/pyproject.toml | 13 ++ .../network-profiler/tests/test_measure.py | 16 ++ contrib/network-profiler/tests/test_remote.py | 20 +++ 12 files changed, 624 insertions(+) create mode 100644 contrib/network-profiler/.gitignore create mode 100644 contrib/network-profiler/README.md create mode 100644 contrib/network-profiler/network_profiler/__init__.py create mode 100644 contrib/network-profiler/network_profiler/__main__.py create mode 100644 contrib/network-profiler/network_profiler/cli.py create mode 100644 contrib/network-profiler/network_profiler/measure.py create mode 100644 contrib/network-profiler/network_profiler/model.py create mode 100644 contrib/network-profiler/network_profiler/remote.py create mode 100644 contrib/network-profiler/network_profiler/render.py create mode 100644 contrib/network-profiler/pyproject.toml create mode 100644 contrib/network-profiler/tests/test_measure.py create mode 100644 contrib/network-profiler/tests/test_remote.py diff --git a/contrib/network-profiler/.gitignore b/contrib/network-profiler/.gitignore new file mode 100644 index 0000000..7966721 --- /dev/null +++ b/contrib/network-profiler/.gitignore @@ -0,0 +1,4 @@ +__pycache__/ +*.py[cod] +.pytest_cache/ +results/ diff --git a/contrib/network-profiler/README.md b/contrib/network-profiler/README.md new file mode 100644 index 0000000..71d15ef --- /dev/null +++ b/contrib/network-profiler/README.md @@ -0,0 +1,75 @@ +# Network Profiler + +Pairwise network profiler for machines managed through +[`ResearchComputer/remote-cluster-controller`](https://github.com/ResearchComputer/remote-cluster-controller). + +It runs commands on every source machine, targets every other machine, records +latency with `ping`, optionally records bandwidth with `iperf3`, and renders an +HTML heatmap. + +## Configure machines + +Copy `examples/machines.example.json` and update: + +- `machines[].name`: label used in output. +- `machines[].address`: address reachable from the other remote machines. +- `machines[].rcc_host`: host identifier understood by `remote-cluster-controller`. +- `remote_command`: argv template for running a shell command on a remote host. + +The default remote command template is: + +```json +[ + "remote-cluster-controller", + "exec", + "--host", + "{host}", + "--", + "bash", + "-lc", + "{command}" +] +``` + +If your local checkout exposes a different CLI, change only `remote_command`. +The template supports `{host}`, `{name}`, `{address}`, and `{command}`. + +## Run + +Show what will be executed: + +```bash +python3 -m network_profiler plan --config machines.json +``` + +Collect latency only: + +```bash +python3 -m network_profiler collect --config machines.json --output results/network.jsonl +``` + +Collect latency and bandwidth: + +```bash +python3 -m network_profiler collect --config machines.json --iperf --output results/network.jsonl +``` + +Render heatmaps: + +```bash +python3 -m network_profiler heatmap --input results/network.jsonl --output results/ping.html +python3 -m network_profiler heatmap --input results/network.jsonl --kind iperf3 --output results/iperf.html +``` + +## Remote requirements + +Each remote machine needs: + +- `bash` +- `ping` +- `iperf3` only when `--iperf` is used +- network paths that allow source machines to reach target `address` values +- TCP access to `iperf_port` between remote machines when collecting bandwidth + +The JSONL output preserves every command, success flag, parsed metrics, and +failure text so failed links can be inspected without rerunning the whole sweep. diff --git a/contrib/network-profiler/network_profiler/__init__.py b/contrib/network-profiler/network_profiler/__init__.py new file mode 100644 index 0000000..8574b86 --- /dev/null +++ b/contrib/network-profiler/network_profiler/__init__.py @@ -0,0 +1,5 @@ +"""Network profiling utilities for remote clusters.""" + +__all__ = ["__version__"] + +__version__ = "0.1.0" diff --git a/contrib/network-profiler/network_profiler/__main__.py b/contrib/network-profiler/network_profiler/__main__.py new file mode 100644 index 0000000..bfdcd0c --- /dev/null +++ b/contrib/network-profiler/network_profiler/__main__.py @@ -0,0 +1,4 @@ +from .cli import main + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/contrib/network-profiler/network_profiler/cli.py b/contrib/network-profiler/network_profiler/cli.py new file mode 100644 index 0000000..504d3b3 --- /dev/null +++ b/contrib/network-profiler/network_profiler/cli.py @@ -0,0 +1,67 @@ +from __future__ import annotations + +from pathlib import Path +import argparse +import json + +from .measure import collect +from .model import load_config +from .remote import RemoteRunner +from .render import render_heatmap + + +def build_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description="Profile pairwise network conditions across remote machines.") + subparsers = parser.add_subparsers(dest="command", required=True) + + plan = subparsers.add_parser("plan", help="Show the remote commands that would be executed.") + plan.add_argument("--config", type=Path, required=True) + + collect_parser = subparsers.add_parser("collect", help="Collect pairwise ping and optional iperf3 metrics.") + collect_parser.add_argument("--config", type=Path, required=True) + collect_parser.add_argument("--output", type=Path, default=Path("results/network-measurements.jsonl")) + collect_parser.add_argument("--iperf", action="store_true", help="Also collect iperf3 bandwidth measurements.") + collect_parser.add_argument("--dry-run", action="store_true") + + heatmap = subparsers.add_parser("heatmap", help="Render an HTML heatmap from JSONL measurements.") + heatmap.add_argument("--input", type=Path, default=Path("results/network-measurements.jsonl")) + heatmap.add_argument("--output", type=Path, default=Path("results/network-heatmap.html")) + heatmap.add_argument("--kind", choices=["ping", "iperf3"], default="ping") + heatmap.add_argument("--metric", default=None, help="Defaults to avg for ping, mbps for iperf3.") + return parser + + +def show_plan(config_path: Path) -> None: + config = load_config(config_path) + runner = RemoteRunner(config, dry_run=True) + rows = [] + for source in config.machines: + for target in config.machines: + if source == target: + continue + rows.append( + { + "source": source.name, + "target": target.name, + "ping": runner.run(source, f"ping -c {config.ping_count} {target.address}").command, + "iperf_server": runner.run(target, f"iperf3 -s -1 -p {config.iperf_port}").command, + "iperf_client": runner.run(source, f"iperf3 -J -c {target.address} -p {config.iperf_port}").command, + } + ) + print(json.dumps(rows, indent=2)) + + +def main(argv: list[str] | None = None) -> int: + args = build_parser().parse_args(argv) + if args.command == "plan": + show_plan(args.config) + return 0 + if args.command == "collect": + config = load_config(args.config) + collect(config, args.output, include_iperf=args.iperf, dry_run=args.dry_run) + return 0 + if args.command == "heatmap": + metric = args.metric or ("avg" if args.kind == "ping" else "mbps") + render_heatmap(args.input, args.output, args.kind, metric) + return 0 + raise AssertionError(args.command) diff --git a/contrib/network-profiler/network_profiler/measure.py b/contrib/network-profiler/network_profiler/measure.py new file mode 100644 index 0000000..6d8ec65 --- /dev/null +++ b/contrib/network-profiler/network_profiler/measure.py @@ -0,0 +1,149 @@ +from __future__ import annotations + +from datetime import datetime, timezone +from pathlib import Path +from typing import Any +import json +import re +import time + +from .model import Machine, ProfilerConfig +from .remote import RemoteRunner + +PING_RE = re.compile( + r"rtt min/avg/max/(?:mdev|stddev) = " + r"(?P[0-9.]+)/(?P[0-9.]+)/(?P[0-9.]+)/(?P[0-9.]+) ms" +) + + +def timestamp() -> str: + return datetime.now(timezone.utc).isoformat(timespec="seconds") + + +def parse_ping(output: str) -> dict[str, float] | None: + match = PING_RE.search(output) + if not match: + return None + return {key: float(value) for key, value in match.groupdict().items()} + + +def parse_iperf(output: str) -> dict[str, float] | None: + try: + data = json.loads(output) + except json.JSONDecodeError: + return None + + end = data.get("end", {}) + summary = end.get("sum_received") or end.get("sum") or end.get("sum_sent") + if not summary: + return None + bits_per_second = float(summary.get("bits_per_second", 0.0)) + return { + "mbps": bits_per_second / 1_000_000, + "seconds": float(summary.get("seconds", 0.0)), + "bytes": float(summary.get("bytes", 0.0)), + } + + +def measurement_record( + kind: str, + source: Machine, + target: Machine, + ok: bool, + command: str, + metrics: dict[str, Any] | None = None, + error: str | None = None, +) -> dict[str, Any]: + return { + "timestamp": timestamp(), + "kind": kind, + "source": source.name, + "target": target.name, + "target_address": target.address, + "ok": ok, + "metrics": metrics or {}, + "error": error, + "command": command, + } + + +def append_jsonl(path: Path, record: dict[str, Any]) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + with path.open("a", encoding="utf-8") as f: + f.write(json.dumps(record, sort_keys=True) + "\n") + + +def iter_pairs(machines: list[Machine]) -> list[tuple[Machine, Machine]]: + return [(source, target) for source in machines for target in machines if source != target] + + +def collect( + config: ProfilerConfig, + output: Path, + include_iperf: bool, + dry_run: bool = False, +) -> None: + runner = RemoteRunner(config, dry_run=dry_run) + for source, target in iter_pairs(config.machines): + ping_cmd = f"ping -c {config.ping_count} -W {config.connect_timeout_seconds} {shlex_quote(target.address)}" + ping = runner.run(source, ping_cmd, timeout=config.connect_timeout_seconds * config.ping_count + 10) + ping_metrics = parse_ping(ping.stdout) + append_jsonl( + output, + measurement_record( + "ping", + source, + target, + ping.returncode == 0 and ping_metrics is not None, + ping.command, + ping_metrics, + None if ping.returncode == 0 else ping.stderr.strip() or ping.stdout.strip(), + ), + ) + + if not include_iperf: + continue + + server_cmd = ( + f"nohup iperf3 -s -1 -p {config.iperf_port} >/tmp/network-profiler-iperf3.log 2>&1 &" + ) + server = runner.run(target, server_cmd, timeout=config.connect_timeout_seconds) + if server.returncode != 0: + append_jsonl( + output, + measurement_record( + "iperf3", + source, + target, + False, + server.command, + error=server.stderr.strip() or server.stdout.strip(), + ), + ) + continue + + time.sleep(1) + iperf_cmd = ( + f"iperf3 -J -c {shlex_quote(target.address)} " + f"-p {config.iperf_port} -t {config.iperf_seconds}" + ) + iperf = runner.run(source, iperf_cmd, timeout=config.iperf_seconds + config.connect_timeout_seconds + 10) + iperf_metrics = parse_iperf(iperf.stdout) + append_jsonl( + output, + measurement_record( + "iperf3", + source, + target, + iperf.returncode == 0 and iperf_metrics is not None, + iperf.command, + iperf_metrics, + None if iperf.returncode == 0 else iperf.stderr.strip() or iperf.stdout.strip(), + ), + ) + + +def shlex_quote(value: str) -> str: + import shlex + + return shlex.quote(value) diff --git a/contrib/network-profiler/network_profiler/model.py b/contrib/network-profiler/network_profiler/model.py new file mode 100644 index 0000000..69a4202 --- /dev/null +++ b/contrib/network-profiler/network_profiler/model.py @@ -0,0 +1,60 @@ +from __future__ import annotations + +from dataclasses import dataclass +from pathlib import Path +from typing import Any +import json + + +@dataclass(frozen=True) +class Machine: + name: str + address: str + rcc_host: str + + +@dataclass(frozen=True) +class ProfilerConfig: + machines: list[Machine] + remote_command: list[str] | None + ping_count: int + iperf_seconds: int + iperf_port: int + connect_timeout_seconds: int + + +def load_config(path: Path) -> ProfilerConfig: + with path.open("r", encoding="utf-8") as f: + raw = json.load(f) + + machines = [ + Machine( + name=str(item["name"]), + address=str(item.get("address", item["name"])), + rcc_host=str(item.get("rcc_host", item["name"])), + ) + for item in raw["machines"] + ] + if len({machine.name for machine in machines}) != len(machines): + raise ValueError("machine names must be unique") + + defaults: dict[str, Any] = { + "ping_count": 5, + "iperf_seconds": 5, + "iperf_port": 5201, + "connect_timeout_seconds": 10, + } + defaults.update(raw) + + remote_command = raw.get("remote_command") + if remote_command is not None and not isinstance(remote_command, list): + raise ValueError("remote_command must be a JSON array of command arguments") + + return ProfilerConfig( + machines=machines, + remote_command=remote_command, + ping_count=int(defaults["ping_count"]), + iperf_seconds=int(defaults["iperf_seconds"]), + iperf_port=int(defaults["iperf_port"]), + connect_timeout_seconds=int(defaults["connect_timeout_seconds"]), + ) diff --git a/contrib/network-profiler/network_profiler/remote.py b/contrib/network-profiler/network_profiler/remote.py new file mode 100644 index 0000000..98ee9a2 --- /dev/null +++ b/contrib/network-profiler/network_profiler/remote.py @@ -0,0 +1,80 @@ +from __future__ import annotations + +from dataclasses import dataclass +import os +import shlex +import subprocess + +from .model import Machine, ProfilerConfig + + +@dataclass(frozen=True) +class CommandResult: + host: str + command: str + returncode: int + stdout: str + stderr: str + + +class RemoteRunner: + def __init__(self, config: ProfilerConfig, dry_run: bool = False): + self.config = config + self.dry_run = dry_run + + def build_args(self, machine: Machine, command: str) -> list[str]: + template = self.config.remote_command + if template is None: + env_template = os.environ.get("NETWORK_PROFILER_REMOTE_CMD") + if env_template: + return [ + part.format( + host=machine.rcc_host, + name=machine.name, + address=machine.address, + command=command, + ) + for part in shlex.split(env_template) + ] + template = [ + "remote-cluster-controller", + "exec", + "--host", + "{host}", + "--", + "bash", + "-lc", + "{command}", + ] + + return [ + str(part).format( + host=machine.rcc_host, + name=machine.name, + address=machine.address, + command=command, + ) + for part in template + ] + + def run(self, machine: Machine, command: str, timeout: int | None = None) -> CommandResult: + args = self.build_args(machine, command) + if self.dry_run: + rendered = shlex.join(args) + return CommandResult(machine.name, rendered, 0, rendered + "\n", "") + + completed = subprocess.run( + args, + check=False, + text=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + timeout=timeout, + ) + return CommandResult( + host=machine.name, + command=shlex.join(args), + returncode=completed.returncode, + stdout=completed.stdout, + stderr=completed.stderr, + ) diff --git a/contrib/network-profiler/network_profiler/render.py b/contrib/network-profiler/network_profiler/render.py new file mode 100644 index 0000000..a1cf329 --- /dev/null +++ b/contrib/network-profiler/network_profiler/render.py @@ -0,0 +1,131 @@ +from __future__ import annotations + +from collections import defaultdict +from pathlib import Path +from typing import Any +import html +import json + + +def load_records(path: Path) -> list[dict[str, Any]]: + records: list[dict[str, Any]] = [] + with path.open("r", encoding="utf-8") as f: + for line in f: + line = line.strip() + if line: + records.append(json.loads(line)) + return records + + +def latest_metric(records: list[dict[str, Any]], kind: str, metric: str) -> dict[tuple[str, str], float]: + values: dict[tuple[str, str], float] = {} + for record in records: + if record.get("kind") != kind or not record.get("ok"): + continue + raw_value = record.get("metrics", {}).get(metric) + if raw_value is None: + continue + values[(record["source"], record["target"])] = float(raw_value) + return values + + +def machine_order(records: list[dict[str, Any]]) -> list[str]: + names: set[str] = set() + for record in records: + names.add(record["source"]) + names.add(record["target"]) + return sorted(names) + + +def color(value: float, low: float, high: float, invert: bool) -> str: + if high <= low: + ratio = 0.5 + else: + ratio = (value - low) / (high - low) + ratio = max(0.0, min(1.0, ratio)) + if invert: + ratio = 1.0 - ratio + red = int(230 - 180 * ratio) + green = int(70 + 140 * ratio) + blue = int(70 + 40 * ratio) + return f"rgb({red},{green},{blue})" + + +def render_heatmap(records_path: Path, output_path: Path, kind: str, metric: str) -> None: + records = load_records(records_path) + values = latest_metric(records, kind, metric) + names = machine_order(records) + all_values = list(values.values()) + low = min(all_values) if all_values else 0.0 + high = max(all_values) if all_values else 1.0 + invert = kind == "ping" + + failures = defaultdict(int) + for record in records: + if record.get("ok"): + continue + failures[(record["source"], record["target"], record["kind"])] += 1 + + cells = [] + for source in names: + row = [f"{html.escape(source)}"] + for target in names: + if source == target: + row.append('self') + continue + value = values.get((source, target)) + if value is None: + row.append('missing') + continue + title = html.escape(f"{source} -> {target}: {value:.2f} {metric}") + row.append( + f'' + f"{value:.2f}" + ) + cells.append("" + "".join(row) + "") + + header = "".join(f"{html.escape(name)}" for name in names) + failure_rows = "".join( + f"{html.escape(src)}{html.escape(dst)}" + f"{html.escape(fail_kind)}{count}" + for (src, dst, fail_kind), count in sorted(failures.items()) + ) + if not failure_rows: + failure_rows = 'No failed measurements recorded.' + + output_path.parent.mkdir(parents=True, exist_ok=True) + output_path.write_text( + f""" + + + +Network {html.escape(kind)} heatmap + + + +

Network {html.escape(kind)} heatmap

+

Metric: {html.escape(metric)}. Lower is better for ping; higher is better for iperf3.

+ +{header} + +{''.join(cells)} + +
source \\ target
+

Failures

+ + +{failure_rows} +
sourcetargetkindcount
+ + +""", + encoding="utf-8", + ) diff --git a/contrib/network-profiler/pyproject.toml b/contrib/network-profiler/pyproject.toml new file mode 100644 index 0000000..2f5d366 --- /dev/null +++ b/contrib/network-profiler/pyproject.toml @@ -0,0 +1,13 @@ +[project] +name = "network-profiler" +version = "0.1.0" +description = "Pairwise network profiling over remote-cluster-controller managed machines" +requires-python = ">=3.11" +dependencies = [] + +[project.scripts] +network-profiler = "network_profiler.cli:main" + +[tool.pytest.ini_options] +testpaths = ["tests"] +pythonpath = ["."] diff --git a/contrib/network-profiler/tests/test_measure.py b/contrib/network-profiler/tests/test_measure.py new file mode 100644 index 0000000..5135fad --- /dev/null +++ b/contrib/network-profiler/tests/test_measure.py @@ -0,0 +1,16 @@ +from network_profiler.measure import parse_iperf, parse_ping + + +def test_parse_linux_ping_summary() -> None: + output = "rtt min/avg/max/mdev = 1.234/5.678/9.012/0.321 ms" + assert parse_ping(output) == { + "min": 1.234, + "avg": 5.678, + "max": 9.012, + "jitter": 0.321, + } + + +def test_parse_iperf_sum_received() -> None: + output = '{"end":{"sum_received":{"bits_per_second":123000000,"seconds":5,"bytes":1000}}}' + assert parse_iperf(output) == {"mbps": 123.0, "seconds": 5.0, "bytes": 1000.0} diff --git a/contrib/network-profiler/tests/test_remote.py b/contrib/network-profiler/tests/test_remote.py new file mode 100644 index 0000000..e63c675 --- /dev/null +++ b/contrib/network-profiler/tests/test_remote.py @@ -0,0 +1,20 @@ +from network_profiler.model import Machine, ProfilerConfig +from network_profiler.remote import RemoteRunner + + +def test_remote_command_template_expands_host_and_command() -> None: + config = ProfilerConfig( + machines=[], + remote_command=["rcc", "run", "{host}", "{command}"], + ping_count=5, + iperf_seconds=5, + iperf_port=5201, + connect_timeout_seconds=10, + ) + machine = Machine(name="node-a", address="10.0.0.1", rcc_host="cluster/node-a") + assert RemoteRunner(config).build_args(machine, "hostname") == [ + "rcc", + "run", + "cluster/node-a", + "hostname", + ] From 71fe7a4e2f0f052c87a0904a2bae930cc1b55c2d Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sat, 2 May 2026 20:40:19 +0200 Subject: [PATCH 02/23] add mesh-bench design proposal Spec for an OpenTela-native pairwise network profiler that brings up an isolated mesh on remote machines, measures libp2p_ping / HTTP-over-libp2p latency / throughput across every pair, and writes JSONL. Motivated by the relay-circuit NO_RESERVATION debugging effort: raw IP ping/iperf3 numbers don't characterise what production traffic actually experiences (TLS, multiplexing, relay hops). Adds /v1/probe/echo, /v1/probe/run, libp2p ping registration, and otela probe / peer-id CLI commands as always-on diagnostic surface. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../2026-05-02-mesh-bench-design.mdx | 396 ++++++++++++++++++ docs/content/docs/proposals/meta.json | 3 +- 2 files changed, 398 insertions(+), 1 deletion(-) create mode 100644 docs/content/docs/proposals/2026-05-02-mesh-bench-design.mdx diff --git a/docs/content/docs/proposals/2026-05-02-mesh-bench-design.mdx b/docs/content/docs/proposals/2026-05-02-mesh-bench-design.mdx new file mode 100644 index 0000000..f54df74 --- /dev/null +++ b/docs/content/docs/proposals/2026-05-02-mesh-bench-design.mdx @@ -0,0 +1,396 @@ +--- +title: Mesh Bench — OpenTela-native pairwise network profiling +description: Design for an on-demand, libp2p-level latency and throughput benchmark across an OpenTela mesh, driven by the contrib network profiler. +--- + +**Date:** 2026-05-02 +**Status:** Draft +**Author:** Claude + +## Overview + +`net-profiler bench` measures pairwise libp2p latency and throughput across an +OpenTela mesh by bringing up an isolated, single-purpose mesh on a set of +remote machines, sweeping every (source, destination) pair through three probe +kinds, and writing per-pair results to JSONL. + +It exists because the existing `contrib/network-profiler/` measures raw IP RTT +via `ping` and `iperf3`. Those numbers do not characterise what OpenTela +actually experiences — its production traffic rides +HTTP-over-libp2p with TLS, multiplexing, and (on Euler) relay-circuit hops. +When relay reservations fail with `NO_RESERVATION`, raw `iperf3` between login +nodes provides no signal. A profiler that drives the actual libp2p path does. + +## Goals + +- **On-demand pairwise sweep** — single command, fresh mesh per run, JSONL + output. Parallels `contrib/network-profiler/` so the two coexist as raw-IP + baseline vs. OpenTela-native measurement. +- **Three probe kinds** — `libp2p_ping` (raw `/ipfs/ping/1.0.0` RTT), + `latency` (HTTP-over-libp2p `GET /v1/health` RTT), `throughput` + (HTTP-over-libp2p byte-stream of configurable size). The gap between + `libp2p_ping` and `latency` quantifies HTTP-tunnel overhead. +- **Production-realistic path** — measurements ride the same code path as user + traffic: warm libp2p connections, real relay circuits, real TLS. +- **Isolation** — each run uses a fresh config dir, fresh keys, dedicated + ports. No interaction with any persistent OpenTela state on the same hosts. +- **Diagnostic surface, always available** — the new HTTP and CLI surface + ships in the OpenTela binary unconditionally. No feature flag. + +## Non-goals + +- Continuous mesh health monitoring (would write `Peer.Latency`, gossip RTT + through the CRDT). Future work, but explicitly out of scope here. +- Replacing `contrib/network-profiler/`. Raw IP and OpenTela-native answer + different questions; both are kept. +- Built-in heatmap rendering for the new throughput dimension. The existing + `render.py` is reused with a small tweak; multi-kind dashboards are future + work. +- Authorisation on probe endpoints. They are unauthenticated, same as + `/v1/health`. + +## Architecture + +``` +┌──────────────────── developer laptop ────────────────────┐ +│ net-profiler bench --config machines.json │ +│ ┌─ phases ────────────────────────────────────────────┐ │ +│ │ 1. init (rcc → otela init per host) │ │ +│ │ 2. discover (rcc → otela peer-id per host) │ │ +│ │ 3. configure (build per-host config locally) │ │ +│ │ 4. push (rcc → write config via stdin) │ │ +│ │ 5. start (rcc → nohup otela start &) │ │ +│ │ 6. converge (poll /v1/dnt/table per host) │ │ +│ │ 7. sweep (rcc → otela probe per pair × kind) │ │ +│ │ 8. teardown (rcc → pkill + rm -rf) │ │ +│ └─────────────────────────────────────────────────────┘ │ +└──────────────────────────────────────────────────────────┘ + │ rcc / libp2p + ┌──────────────────┼──────────────────┐ + ▼ ▼ ▼ + ┌──────────┐ ┌──────────┐ ┌──────────┐ + │ clariden │◀─────▶│ bristen │◀─────▶│ euler │ … + │ otela │ libp2p│ otela │ libp2p│ otela │ + └──────────┘ └──────────┘ └──────────┘ + listens on bench-only new endpoints: + bench port, config dir, /v1/probe/echo + isolated CRDT no production /v1/probe/run + state services /ipfs/ping/1.0.0 +``` + +The profiler runs on the developer laptop and dispatches every step over rcc. +Each remote machine runs a fresh `otela` process bound to a bench-only HTTP +port (default 19090) and libp2p port (default 19091), reading from a +per-run config dir at `/tmp/otela-bench-/` so production state is +untouched. + +## New OpenTela surface (Go side) + +### `src/internal/server/probe_handler.go` (new) + +Two endpoints, both registered in `server.go` alongside existing routes, +both unauthenticated. + +**`GET /v1/probe/echo?bytes=N`** — server-side responder. Streams `N` zero +bytes back with `Content-Length: N`. Hard cap of 1 GiB to prevent accidental +DoS. Returns 400 on missing or invalid `bytes`. Used by the originator's +throughput probe. + +**`POST /v1/probe/run`** — originator endpoint. JSON body: + +```json +{ + "target": "", + "kind": "latency" | "throughput" | "libp2p_ping", + "bytes": , + "count": , + "timeout_ms": +} +``` + +Behavior per kind. In all cases the originator dials the target peer +through an internal libp2p HTTP client (the same `gostream`-based transport +that `P2PForwardHandler` uses), not a self-recursive HTTP call through +`/v1/p2p/`. The originator handler bypasses Gin and goes straight to the +libp2p layer: + +- `latency` — `count` sequential `GET /v1/health` calls dialed at the target + peer over libp2p HTTP. Records each round-trip in nanoseconds. +- `throughput` — `count` sequential `GET /v1/probe/echo?bytes=` calls + dialed at the target peer over libp2p HTTP. Drains each response body, + records `bytes_received`, `elapsed_ns`, derives `mbps`. +- `libp2p_ping` — `count` `ping.NewPingService(host).Ping(ctx, peerID)` + round-trips via the libp2p ping protocol. Bypasses HTTP entirely. + +Per-sample failures inside a `count` batch are recorded but do not fail the +whole run; the response includes `failed_samples`. On total failure (peer +unreachable, stream reset, all samples errored) the response is +`{ok: false, error: "…"}`. + +The originator endpoint lives on the *running node*, not in the CLI, because +the CLI process would have to spin up its own libp2p host to make a call — +slow and pollutes the mesh just to make one measurement. The running node +already has warm libp2p connections, which is the path we want to measure. + +### `src/internal/protocol/host.go` (modify) + +Register libp2p's built-in ping service after `newHost()`: + +```go +import "github.com/libp2p/go-libp2p/p2p/protocol/ping" + +// after host construction +ping.NewPingService(host) +``` + +This adds `/ipfs/ping/1.0.0` to the registered protocols. No config flag — +diagnostic surface, always on. The same protocol is what +`POST /v1/probe/run?kind=libp2p_ping` invokes. + +### `src/entry/cmd/probe.go` (new) + +Thin CLI shim. Reads the local config to find the running node's HTTP port, +POSTs to `http://127.0.0.1:/v1/probe/run` with the JSON body, prints +the response body to stdout. Exit code 0 on `ok:true`, 1 otherwise. + +``` +otela probe --target + [--kind latency|throughput|libp2p_ping] (default: latency) + [--bytes 10485760] (10 MiB) + [--count 20] + [--timeout 60s] + [--config-dir /etc/opentela] +``` + +The CLI exists primarily so the Python profiler can invoke probes via +`rcc run`, but it doubles as a useful per-host diagnostic when SSH'd in. + +### `src/entry/cmd/peerid.go` (new) + +``` +otela peer-id [--config-dir /etc/opentela] +``` + +Reads the keypair from the config dir, prints the PeerID to stdout, exits. +No HTTP call. Used by the profiler's discover phase so PeerIDs are known +before the start phase. + +## Python profiler `bench` command + +Implementation lives in `contrib/network-profiler/network_profiler/bench.py` +(new). The existing `cli.py` grows a `bench` subcommand alongside `plan`, +`collect`, `heatmap`. + +### Phases + +1. **Init** — for each host: + `rcc run --profile -- otela init --config-dir /tmp/otela-bench-`. + Each host generates its own keypair locally; we do not reimplement libp2p + PeerID derivation in Python. + +2. **Discover PeerIDs** — for each host: + `rcc run --profile -- otela peer-id --config-dir /tmp/otela-bench-`. + Stash the `host → PeerID` map in memory. + +3. **Configure** — locally render per-host `config.yaml` with: + - HTTP port `19090`, libp2p listen `/ip4/0.0.0.0/tcp/19091` (both + overridable per-host in `machines.json`) + - `bootstrap_peers`: every other host as `/ip4/
/tcp/19091/p2p/` + - `cleanslate: true`, `security.require_signed_binary: false` + - All `scalability.*` feature flags off — measure baseline + - No services registered; bench nodes are bare libp2p endpoints + +4. **Push** — for each host: + `rcc run --profile -- bash -c 'base64 -d > /tmp/otela-bench-/config.yaml'` + with the b64-encoded config piped through stdin. Avoids fragile filename + quoting and stays inside rcc's existing exec surface (no `rcc push` of + project trees needed). + +5. **Start** — for each host: + `rcc run --profile -- bash -lc 'nohup otela start --config-dir /tmp/otela-bench- >>/tmp/otela-bench-/log 2>&1 &'`. + Then poll `rcc run -- curl -fsS http://127.0.0.1:19090/v1/health` until 200, + 30s timeout per host. + +6. **Converge** — for each host, poll + `rcc run -- curl -s http://127.0.0.1:19090/v1/dnt/table` until every + peer's PeerID appears, 60s timeout per host. Convergence outcomes are + recorded in `run.json` whether or not all hosts converge in time. + +7. **Sweep** — for each `(src, dst, kind)` tuple where `src != dst`: + `rcc run --profile -- otela probe --target --kind --count --bytes --config-dir /tmp/otela-bench-`. + Capture stdout JSON, append a record to `measurements.jsonl`. + Default plan: `libp2p_ping` (count=20), `latency` (count=20), + `throughput` (count=3, bytes=10 MiB). Sequential by kind, optional + `--parallel K` for within-kind concurrency. + +8. **Teardown** — for each host: + `rcc run -- bash -c 'pkill -f "otela start --config-dir /tmp/otela-bench-" && rm -rf /tmp/otela-bench-'`. + `pgrep` matches the unique runID path so production nodes cannot be killed. + `--keep` flag skips this phase for post-mortem inspection. + +### CLI surface + +``` +net-profiler bench --config machines.json + [--output results//] + [--latency-count 20] + [--throughput-bytes 10485760] + [--throughput-count 3] + [--parallel 4] + [--http-port 19090] [--libp2p-port 19091] + [--keep] [--run-id ] +``` + +### Signal handling + +SIGINT during any phase runs phase 8 (teardown) before exiting non-zero. +A Ctrl-C never leaves dangling `otela` processes or temp dirs. + +## Output format + +Two files per run, both under `results//`. + +### `measurements.jsonl` + +One JSON record per (src, dst, kind) tuple, one record per line. + +```json +{ + "run_id": "2026-05-02T20-45-12-ab12cd", + "timestamp": "2026-05-02T20:45:30Z", + "kind": "latency", + "source": "clariden", + "target": "bristen", + "source_peer_id": "12D3KooW...", + "target_peer_id": "12D3KooW...", + "ok": true, + "config": {"count": 20, "bytes": null}, + "metrics": { + "min_ns": 1842000, "avg_ns": 2104500, + "p50_ns": 2050000, "p95_ns": 2410000, "max_ns": 2890000, + "min_ms": 1.842, "avg_ms": 2.105, + "p50_ms": 2.050, "p95_ms": 2.410, "max_ms": 2.890, + "samples_ns": [1842000, 2103000, /* … */], + "failed_samples": 0 + }, + "error": null, + "command": "rcc run --profile clariden -- otela probe --target 12D3KooW... --kind latency --count 20" +} +``` + +For `kind=throughput`, `metrics` is: + +```json +{ + "bytes_received": 10485760, + "elapsed_ns": 412300000, + "mbps": 203.4, + "iterations": [ + {"bytes_received": 10485760, "elapsed_ns": 410100000, "mbps": 204.5}, + /* … */ + ], + "failed_samples": 0 +} +``` + +For `kind=libp2p_ping`, the shape matches `latency`. + +Both nanosecond and millisecond fields are emitted to keep +`render.py` compatible without Python-side conversion. `render.py` learns +to recognise `avg_ms` as an alias for the legacy `avg` metric. + +### `run.json` + +One-shot run summary for post-mortem and timing analysis. + +```json +{ + "run_id": "2026-05-02T20-45-12-ab12cd", + "started_at": "2026-05-02T20:45:00Z", + "ended_at": "2026-05-02T20:48:14Z", + "config_file": "machines.json", + "machines": [ + { + "name": "clariden", + "address": "clariden.cscs.ch", + "peer_id": "12D3KooW...", + "http_port": 19090, + "libp2p_port": 19091 + } + ], + "convergence": { + "clariden": {"converged_at": "2026-05-02T20:45:18Z", "elapsed_s": 8.2, "complete": true} + }, + "phases": { + "init_s": 1.4, "discover_s": 0.9, "configure_s": 0.1, + "push_s": 0.6, "start_s": 12.3, "converge_s": 14.7, + "sweep_s": 92.4, "teardown_s": 3.1 + }, + "totals": { + "pairs": 12, "kinds": ["libp2p_ping","latency","throughput"], + "ok": 34, "failed": 2 + } +} +``` + +## Failure handling + +| Phase | Failure mode | Behavior | +| --- | --- | --- | +| Init / Discover | A host's `otela init` or `otela peer-id` fails | Abort. Run teardown on hosts already initialised. Exit non-zero with the failing host named. | +| Configure / Push | rcc stdin write fails | Abort. Run teardown on initialised hosts. Clear error. | +| Start | A host does not return 200 from `/v1/health` within 30s | Tail the host's `/tmp/otela-bench-/log` via `rcc run -- tail -50`, attach to the error. Abort. Run teardown. | +| Converge | A host's `/v1/dnt/table` does not list every peer within 60s | Record the partial mesh in `run.json.convergence`. **Proceed to sweep** — partial-mesh measurements are themselves diagnostic for the relay-circuit problem. | +| Sweep | A single (src, dst, kind) probe fails | Record `ok: false, error: "…"` in JSONL, continue. The sweep never aborts on per-pair failure. | +| Teardown | `pkill` finds nothing or `rm -rf` fails | Log warning. Do not fail the run. | +| SIGINT during any phase | User pressed Ctrl-C | Run phase 8 (teardown) immediately, exit non-zero. | + +Idempotency: the run-ID appears in every temp path and in the `pkill` matcher, +so re-running is safe — old runs are not touched, new ones do not collide. + +## Testing + +- **Python unit tests** (`contrib/network-profiler/tests/`): + config rendering (multiaddr formatting, port assignment, bootstrap-list + construction), JSONL record shape, run-ID generation, signal handler + invokes teardown. +- **Go unit tests** (`src/internal/server/`): + `/v1/probe/echo` byte-count correctness and boundary cases (0 bytes, + > 1 GiB rejected); `/v1/probe/run` with a mocked libp2p HTTP transport for + each `kind`. +- **Go integration tests** (`src/internal/protocol/`): + start two in-process libp2p hosts, register the probe handler on both, + exercise round-trips for each kind. No SSH, no real network. +- **End-to-end** — a `make bench-smoke` target brings up two `otela` + instances on localhost in different config dirs, runs `net-profiler bench` + against a `machines.json` whose `remote_command` is just + `["bash", "-lc", "{command}"]` (no rcc, exec locally). Validates the + full pipeline without cluster access. +- **Manual validation** — actual run against + clariden + bristen + euler + sgs-amd-01 once addresses and the + sgs-amd-01 host key are sorted. This is the relay-circuit-diagnosis + test case that motivated the project. + +## Open questions and future work + +- **Minimum config for `otela start --config-dir `.** The bench + config sets `cleanslate`, `billing.enabled: false`, no services, no + scalability flags, and the keypair generated by `otela init`. The + implementation plan must verify this is sufficient — if `otela start` + insists on a Solana wallet or other state, the bench-config generator + grows to cover it. No design change either way. +- **`/v1/dnt/table` shape** for convergence polling. The endpoint already + returns the full peer table; this assumes the JSON is stable enough to + parse. If it is not, the discover phase records what it finds rather + than asserting on shape. +- **Concurrent throughput** — current design measures single-stream + throughput. Multi-stream and bidirectional are future work; the probe + endpoint surface can grow `streams` and `direction` parameters without + breaking the JSONL schema. +- **Continuous mesh health** — writing `Peer.Latency`, gossiping per-peer + RTT through the CRDT, exposing per-peer histograms in `/metrics`. The + probe primitives in this design are the foundation for that follow-up. +- **Heatmap rendering for throughput** — `render.py` will read + `metrics.mbps` for `kind=throughput` after a small tweak. Multi-panel + dashboards (latency vs throughput vs libp2p_ping side-by-side) are + future work. diff --git a/docs/content/docs/proposals/meta.json b/docs/content/docs/proposals/meta.json index fd282ed..fc87603 100644 --- a/docs/content/docs/proposals/meta.json +++ b/docs/content/docs/proposals/meta.json @@ -2,6 +2,7 @@ "title": "Proposals", "pages": [ "solana-settlement-design", - "security-hardening" + "security-hardening", + "2026-05-02-mesh-bench-design" ] } From 2486df378331536d58ac03dd80f3fb33ecdba7f1 Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sat, 2 May 2026 23:38:19 +0200 Subject: [PATCH 03/23] add --config-dir flag for per-instance opentela state Allows multiple otela processes to coexist on one host with isolated config and key storage. Foundation for the mesh-bench runner. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/entry/cmd/root.go | 8 ++++++++ src/internal/protocol/key.go | 22 ++++++++++++++++------ src/internal/protocol/key_test.go | 19 +++++++++++++++++++ 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/entry/cmd/root.go b/src/entry/cmd/root.go index 076aeee..1e17872 100644 --- a/src/entry/cmd/root.go +++ b/src/entry/cmd/root.go @@ -5,6 +5,7 @@ import ( "opentela/internal/common" "os" "path" + "path/filepath" "strconv" "strings" @@ -33,6 +34,10 @@ var rootcmd = &cobra.Command{ //nolint:gochecknoinits func init() { rootcmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.config/opentela/cfg.yaml)") + rootcmd.PersistentFlags().String("config-dir", "", "use this directory as the config root (overrides --config and key location)") + if err := viper.BindPFlag("config_dir", rootcmd.PersistentFlags().Lookup("config-dir")); err != nil { + common.Logger.Error("Could not bind config-dir flag", "error", err) + } startCmd.Flags().String("wallet.account", "", "wallet account") startCmd.Flags().String("account.wallet", "", "path to wallet key file") startCmd.Flags().String("bootstrap.addr", "", "bootstrap address") @@ -85,6 +90,9 @@ func configFilePath(home string) string { func initConfig(cmd *cobra.Command) error { var home string var err error + if cd := viper.GetString("config_dir"); cd != "" && cfgFile == "" { + cfgFile = filepath.Join(cd, "cfg.yaml") + } viper.SetEnvPrefix("of") viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) viper.AutomaticEnv() diff --git a/src/internal/protocol/key.go b/src/internal/protocol/key.go index 08317f8..fb3e690 100644 --- a/src/internal/protocol/key.go +++ b/src/internal/protocol/key.go @@ -3,23 +3,34 @@ package protocol import ( "opentela/internal/common" "os" - "path" + "path/filepath" "github.com/libp2p/go-libp2p/core/crypto" + "github.com/spf13/viper" ) +func resolveKeyPath() (string, error) { + if cd := viper.GetString("config_dir"); cd != "" { + return filepath.Join(cd, "keys", "id"), nil + } + home, err := os.UserHomeDir() + if err != nil { + return "", err + } + return filepath.Join(home, ".config", "opentela", "keys", "id"), nil +} + func writeKeyToFile(priv crypto.PrivKey) { keyData, err := crypto.MarshalPrivateKey(priv) if err != nil { common.Logger.Error("Error while marshalling private key: ", err) } - home, err := os.UserHomeDir() + keyPath, err := resolveKeyPath() if err != nil { common.Logger.Error("Could not determine home directory: ", err) os.Exit(1) } - keyPath := path.Join(home, ".config", "opentela", "keys", "id") - err = os.MkdirAll(path.Dir(keyPath), os.ModePerm) + err = os.MkdirAll(filepath.Dir(keyPath), os.ModePerm) if err != nil { common.Logger.Error("Could not create keys directory", "error", err) os.Exit(1) @@ -32,11 +43,10 @@ func writeKeyToFile(priv crypto.PrivKey) { } func loadKeyFromFile() crypto.PrivKey { - home, err := os.UserHomeDir() + keyPath, err := resolveKeyPath() if err != nil { return nil } - keyPath := path.Join(home, ".config", "opentela", "keys", "id") common.Logger.Debug("Looking for keys under: ", keyPath) keyData, err := os.ReadFile(keyPath) if err != nil { diff --git a/src/internal/protocol/key_test.go b/src/internal/protocol/key_test.go index a77d245..23f1a3b 100644 --- a/src/internal/protocol/key_test.go +++ b/src/internal/protocol/key_test.go @@ -2,13 +2,32 @@ package protocol import ( "crypto/rand" + "os" + "path/filepath" "testing" "github.com/libp2p/go-libp2p/core/crypto" + "github.com/spf13/viper" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) +func TestResolveKeyPath_DefaultsToHome(t *testing.T) { + viper.Reset() + home, _ := os.UserHomeDir() + got, err := resolveKeyPath() + assert.NoError(t, err) + assert.Equal(t, filepath.Join(home, ".config", "opentela", "keys", "id"), got) +} + +func TestResolveKeyPath_HonorsConfigDir(t *testing.T) { + viper.Reset() + viper.Set("config_dir", "/tmp/otela-bench-xyz") + got, err := resolveKeyPath() + assert.NoError(t, err) + assert.Equal(t, "/tmp/otela-bench-xyz/keys/id", got) +} + func TestKeyRoundTrip(t *testing.T) { // Generate a libp2p RSA private key priv, _, err := crypto.GenerateKeyPairWithReader(crypto.RSA, 2048, rand.Reader) From a611fc4d55998ae28e8b6c6f1ec9b2d16c96b278 Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sun, 3 May 2026 00:09:00 +0200 Subject: [PATCH 04/23] fix initConfig seed-write path under --config-dir When --config-dir was set and no cfg.yaml existed yet, initConfig seeded the file at a relative path instead of inside the config dir, breaking otela init --config-dir on fresh dirs (the mesh-bench's happy path). Co-Authored-By: Claude Opus 4.7 (1M context) --- src/entry/cmd/root.go | 11 ++++++++- src/entry/cmd/root_test.go | 48 +++++++++++++++++++++++++++++++++++--- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/entry/cmd/root.go b/src/entry/cmd/root.go index 1e17872..0530bbc 100644 --- a/src/entry/cmd/root.go +++ b/src/entry/cmd/root.go @@ -176,7 +176,16 @@ func initConfig(cmd *cobra.Command) error { viper.SetDefault("solana.rpc", defaultConfig.Solana.RPC) viper.SetDefault("solana.mint", defaultConfig.Solana.Mint) viper.SetDefault("solana.skip_verification", defaultConfig.Solana.SkipVerification) - configPath := path.Join(home, ".config", configDirName, "cfg.yaml") + // Seed the config at whatever path viper was told to use (either via + // --config / cfgFile, or the default $HOME/.config/opentela path). + // This ensures `otela init --config-dir ` writes the seed under + // /cfg.yaml rather than recomputing the path from $HOME. + configPath := viper.ConfigFileUsed() + if configPath == "" { + // Fallback for safety; in practice SetConfigFile was called above + // in both branches, so this should not be reached. + configPath = path.Join(home, ".config", configDirName, "cfg.yaml") + } err = os.MkdirAll(path.Dir(configPath), os.ModePerm) if err != nil { common.Logger.Error("Could not create config directory", "error", err) diff --git a/src/entry/cmd/root_test.go b/src/entry/cmd/root_test.go index a603914..141b8f7 100644 --- a/src/entry/cmd/root_test.go +++ b/src/entry/cmd/root_test.go @@ -101,14 +101,18 @@ udpport: "59820" expectError: false, }, { - name: "invalid config file path", + name: "missing config file under writable dir", setup: func() { - cfgFile = "/nonexistent/path/config.yaml" + // Point cfgFile at a location whose parent does not yet + // exist but is creatable (under a temp dir). initConfig + // should seed the config there instead of erroring. + tempDir := t.TempDir() + cfgFile = filepath.Join(tempDir, "nested", "cfg.yaml") }, cleanup: func() { cfgFile = "" }, - expectError: false, // Should use defaults + expectError: false, // Should use defaults and seed the file. }, } @@ -275,6 +279,44 @@ func TestConfigFileVariable(t *testing.T) { cfgFile = "" } +func TestInitConfigSeedWriteHonorsConfigDir(t *testing.T) { + // Regression test: when --config-dir is set (via viper key "config_dir") + // and the target cfg.yaml does not yet exist, initConfig must seed the + // file at /cfg.yaml — not at a relative path under the + // current working directory. + viper.Reset() + defer viper.Reset() + + tempDir := t.TempDir() + viper.Set("config_dir", tempDir) + + // Make sure the global cfgFile starts empty so the config_dir branch + // at the top of initConfig populates it. + cfgFile = "" + defer func() { cfgFile = "" }() + + // Capture the working directory and assert nothing is written there. + cwd, err := os.Getwd() + require.NoError(t, err) + strayPath := filepath.Join(cwd, ".config", "opentela", "cfg.yaml") + _, strayBefore := os.Stat(strayPath) + + cmd := &cobra.Command{} + require.NoError(t, initConfig(cmd)) + + expected := filepath.Join(tempDir, "cfg.yaml") + if _, err := os.Stat(expected); err != nil { + t.Fatalf("expected seed config at %s, but it was not created: %v", expected, err) + } + + // Confirm we did not also splatter a relative-path config under cwd. + if strayBefore != nil && os.IsNotExist(strayBefore) { + if _, err := os.Stat(strayPath); err == nil { + t.Fatalf("seed config was written to stray relative path %s", strayPath) + } + } +} + func TestBillingConfigDefaults(t *testing.T) { // Reset viper state viper.Reset() From 146aee6c19ae08a102f343ac2a23f49b6b8a3429 Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sun, 3 May 2026 00:14:39 +0200 Subject: [PATCH 05/23] otela init pre-generates libp2p identity key Lets the mesh-bench runner read the PeerID before any otela start call. Idempotent: existing keys are left alone. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/entry/cmd/init.go | 27 +++++++++++++++++++++++ src/entry/cmd/init_test.go | 36 +++++++++++++++++++++++++++++++ src/internal/protocol/host.go | 15 +++++++------ src/internal/protocol/key.go | 34 ++++++++++++++++++++++++----- src/internal/protocol/key_test.go | 4 ++-- 5 files changed, 102 insertions(+), 14 deletions(-) create mode 100644 src/entry/cmd/init_test.go diff --git a/src/entry/cmd/init.go b/src/entry/cmd/init.go index c7d7146..21aeb3c 100644 --- a/src/entry/cmd/init.go +++ b/src/entry/cmd/init.go @@ -8,9 +8,27 @@ import ( homedir "github.com/mitchellh/go-homedir" "github.com/spf13/cobra" + "opentela/internal/protocol" "opentela/internal/wallet" ) +// ensureLibp2pKey makes sure a libp2p identity key exists on disk at the +// path resolved by protocol.ResolveKeyPath. It is a no-op when a key is +// already present, so calling it repeatedly (e.g. across multiple +// `otela init` invocations) preserves the existing identity. This lets +// tooling that needs the PeerID — such as the mesh-bench runner — read +// it after `otela init` without ever starting the server. +func ensureLibp2pKey() error { + keyPath, err := protocol.ResolveKeyPath() + if err != nil { + return err + } + if _, err := os.Stat(keyPath); err == nil { + return nil + } + return protocol.GenerateAndWriteKey() +} + var initCmd = &cobra.Command{ Use: "init", Short: "Initialize OpenTela: create config directory and a default wallet", @@ -74,6 +92,10 @@ without overwriting anything.`, fmt.Printf(" Keypair file: %s\n", acc.FilePath) fmt.Println() fmt.Println("No changes were made to the existing wallet.") + if err := ensureLibp2pKey(); err != nil { + fmt.Printf("Failed to initialize libp2p key: %v\n", err) + os.Exit(1) + } return } @@ -83,6 +105,11 @@ without overwriting anything.`, os.Exit(1) } + if err := ensureLibp2pKey(); err != nil { + fmt.Printf("Failed to initialize libp2p key: %v\n", err) + os.Exit(1) + } + fmt.Println() fmt.Println("✔ Wallet created") fmt.Printf(" Public key: %s\n", account.PublicKey) diff --git a/src/entry/cmd/init_test.go b/src/entry/cmd/init_test.go new file mode 100644 index 0000000..f1c1a85 --- /dev/null +++ b/src/entry/cmd/init_test.go @@ -0,0 +1,36 @@ +package cmd + +import ( + "os" + "path/filepath" + "testing" + + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" + + "opentela/internal/protocol" +) + +func TestEnsureLibp2pKey_CreatesKeyWhenMissing(t *testing.T) { + dir, err := os.MkdirTemp("", "otela-init-test-*") + assert.NoError(t, err) + defer os.RemoveAll(dir) + + viper.Reset() + viper.Set("config_dir", dir) + + err = ensureLibp2pKey() + assert.NoError(t, err) + assert.FileExists(t, filepath.Join(dir, "keys", "id")) + + // Idempotent: second call must not fail and must not modify the file. + info1, _ := os.Stat(filepath.Join(dir, "keys", "id")) + err = ensureLibp2pKey() + assert.NoError(t, err) + info2, _ := os.Stat(filepath.Join(dir, "keys", "id")) + assert.Equal(t, info1.ModTime(), info2.ModTime()) + + // Loadable via the same code path otela start uses. + priv := protocol.LoadKeyFromFile() + assert.NotNil(t, priv) +} diff --git a/src/internal/protocol/host.go b/src/internal/protocol/host.go index ea34a86..b6f48e1 100644 --- a/src/internal/protocol/host.go +++ b/src/internal/protocol/host.go @@ -3,7 +3,6 @@ package protocol import ( "bytes" "context" - "crypto/rand" "crypto/sha256" "encoding/hex" "encoding/json" @@ -79,21 +78,23 @@ func newHost(ctx context.Context, seed int64, ds datastore.Batching) (host.Host, if seed == 0 { // seed=0 (default): load existing key from disk for stable identity. // If no key file exists yet, generate a random one and persist it. - priv = loadKeyFromFile() + priv = LoadKeyFromFile() if priv == nil { common.Logger.Debug("seed=0: no existing key file, generating and persisting new identity") - priv, _, err = crypto.GenerateKeyPairWithReader(crypto.RSA, 2048, rand.Reader) - if err != nil { + if err = GenerateAndWriteKey(); err != nil { return nil, err } - writeKeyToFile(priv) + priv = LoadKeyFromFile() + if priv == nil { + return nil, errors.New("failed to load freshly generated identity key") + } } else { common.Logger.Debug("seed=0: loaded existing identity from disk") } } else { // seed!=0: use persisted key file for stable identity across restarts. // On first run, generate from seed and save; subsequent runs load from file. - priv = loadKeyFromFile() + priv = LoadKeyFromFile() if priv == nil { common.Logger.Debugf("No existing key file, generating from seed=%d", seed) r := mrand.New(mrand.NewSource(seed)) @@ -101,7 +102,7 @@ func newHost(ctx context.Context, seed int64, ds datastore.Batching) (host.Host, if err != nil { return nil, err } - writeKeyToFile(priv) + WriteKeyToFile(priv) } } if err != nil { diff --git a/src/internal/protocol/key.go b/src/internal/protocol/key.go index fb3e690..6a2074b 100644 --- a/src/internal/protocol/key.go +++ b/src/internal/protocol/key.go @@ -1,6 +1,7 @@ package protocol import ( + "crypto/rand" "opentela/internal/common" "os" "path/filepath" @@ -9,7 +10,10 @@ import ( "github.com/spf13/viper" ) -func resolveKeyPath() (string, error) { +// ResolveKeyPath returns the on-disk location of the libp2p identity key. +// It honors viper's "config_dir" override (set by the --config-dir flag) and +// falls back to ~/.config/opentela/keys/id. +func ResolveKeyPath() (string, error) { if cd := viper.GetString("config_dir"); cd != "" { return filepath.Join(cd, "keys", "id"), nil } @@ -20,12 +24,15 @@ func resolveKeyPath() (string, error) { return filepath.Join(home, ".config", "opentela", "keys", "id"), nil } -func writeKeyToFile(priv crypto.PrivKey) { +// WriteKeyToFile marshals priv and writes it to the resolved key path, +// creating parent directories as needed. Exits the process on failure to +// preserve the historical behavior of newHost. +func WriteKeyToFile(priv crypto.PrivKey) { keyData, err := crypto.MarshalPrivateKey(priv) if err != nil { common.Logger.Error("Error while marshalling private key: ", err) } - keyPath, err := resolveKeyPath() + keyPath, err := ResolveKeyPath() if err != nil { common.Logger.Error("Could not determine home directory: ", err) os.Exit(1) @@ -42,8 +49,12 @@ func writeKeyToFile(priv crypto.PrivKey) { } } -func loadKeyFromFile() crypto.PrivKey { - keyPath, err := resolveKeyPath() +// LoadKeyFromFile reads the libp2p identity key from disk and returns it. +// Returns nil if the file does not exist or cannot be parsed; errors are +// logged but not propagated, matching the historical behavior used by +// newHost when probing for an existing identity. +func LoadKeyFromFile() crypto.PrivKey { + keyPath, err := ResolveKeyPath() if err != nil { return nil } @@ -60,3 +71,16 @@ func loadKeyFromFile() crypto.PrivKey { } return priv } + +// GenerateAndWriteKey creates a fresh RSA-2048 libp2p identity key and +// persists it via WriteKeyToFile. It is the same keygen flow used lazily +// by newHost when seed=0 and no key exists, exposed so that `otela init` +// can pre-generate the key without starting a libp2p host. +func GenerateAndWriteKey() error { + priv, _, err := crypto.GenerateKeyPairWithReader(crypto.RSA, 2048, rand.Reader) + if err != nil { + return err + } + WriteKeyToFile(priv) + return nil +} diff --git a/src/internal/protocol/key_test.go b/src/internal/protocol/key_test.go index 23f1a3b..2d07461 100644 --- a/src/internal/protocol/key_test.go +++ b/src/internal/protocol/key_test.go @@ -15,7 +15,7 @@ import ( func TestResolveKeyPath_DefaultsToHome(t *testing.T) { viper.Reset() home, _ := os.UserHomeDir() - got, err := resolveKeyPath() + got, err := ResolveKeyPath() assert.NoError(t, err) assert.Equal(t, filepath.Join(home, ".config", "opentela", "keys", "id"), got) } @@ -23,7 +23,7 @@ func TestResolveKeyPath_DefaultsToHome(t *testing.T) { func TestResolveKeyPath_HonorsConfigDir(t *testing.T) { viper.Reset() viper.Set("config_dir", "/tmp/otela-bench-xyz") - got, err := resolveKeyPath() + got, err := ResolveKeyPath() assert.NoError(t, err) assert.Equal(t, "/tmp/otela-bench-xyz/keys/id", got) } From eab617f35ce64e4c6731014b72cb06fcb2d6d2e7 Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sun, 3 May 2026 00:29:18 +0200 Subject: [PATCH 06/23] fix Task 2 review: avoid host.go round-trip and reset viper in test GenerateAndWriteKey now returns the generated key directly so newHost doesn't have to immediately reload from disk. The init_test now restores viper state via t.Cleanup so config_dir doesn't leak into other tests in the same package binary. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/entry/cmd/init.go | 3 ++- src/entry/cmd/init_test.go | 1 + src/internal/protocol/host.go | 7 ++----- src/internal/protocol/key.go | 15 ++++++++------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/entry/cmd/init.go b/src/entry/cmd/init.go index 21aeb3c..8bbad2d 100644 --- a/src/entry/cmd/init.go +++ b/src/entry/cmd/init.go @@ -26,7 +26,8 @@ func ensureLibp2pKey() error { if _, err := os.Stat(keyPath); err == nil { return nil } - return protocol.GenerateAndWriteKey() + _, err = protocol.GenerateAndWriteKey() + return err } var initCmd = &cobra.Command{ diff --git a/src/entry/cmd/init_test.go b/src/entry/cmd/init_test.go index f1c1a85..993d71a 100644 --- a/src/entry/cmd/init_test.go +++ b/src/entry/cmd/init_test.go @@ -17,6 +17,7 @@ func TestEnsureLibp2pKey_CreatesKeyWhenMissing(t *testing.T) { defer os.RemoveAll(dir) viper.Reset() + t.Cleanup(viper.Reset) viper.Set("config_dir", dir) err = ensureLibp2pKey() diff --git a/src/internal/protocol/host.go b/src/internal/protocol/host.go index b6f48e1..8004841 100644 --- a/src/internal/protocol/host.go +++ b/src/internal/protocol/host.go @@ -81,13 +81,10 @@ func newHost(ctx context.Context, seed int64, ds datastore.Batching) (host.Host, priv = LoadKeyFromFile() if priv == nil { common.Logger.Debug("seed=0: no existing key file, generating and persisting new identity") - if err = GenerateAndWriteKey(); err != nil { + priv, err = GenerateAndWriteKey() + if err != nil { return nil, err } - priv = LoadKeyFromFile() - if priv == nil { - return nil, errors.New("failed to load freshly generated identity key") - } } else { common.Logger.Debug("seed=0: loaded existing identity from disk") } diff --git a/src/internal/protocol/key.go b/src/internal/protocol/key.go index 6a2074b..8073bce 100644 --- a/src/internal/protocol/key.go +++ b/src/internal/protocol/key.go @@ -72,15 +72,16 @@ func LoadKeyFromFile() crypto.PrivKey { return priv } -// GenerateAndWriteKey creates a fresh RSA-2048 libp2p identity key and -// persists it via WriteKeyToFile. It is the same keygen flow used lazily -// by newHost when seed=0 and no key exists, exposed so that `otela init` -// can pre-generate the key without starting a libp2p host. -func GenerateAndWriteKey() error { +// GenerateAndWriteKey generates a fresh RSA-2048 libp2p identity, persists it +// via WriteKeyToFile, and returns the in-memory key so callers don't need to +// re-load from disk. It is the same keygen flow used lazily by newHost when +// seed=0 and no key exists, exposed so that `otela init` can pre-generate +// the key without starting a libp2p host. +func GenerateAndWriteKey() (crypto.PrivKey, error) { priv, _, err := crypto.GenerateKeyPairWithReader(crypto.RSA, 2048, rand.Reader) if err != nil { - return err + return nil, err } WriteKeyToFile(priv) - return nil + return priv, nil } From a9ad35b7fc954323dce9335d61987c6dbef74584 Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sun, 3 May 2026 00:35:06 +0200 Subject: [PATCH 07/23] add otela peer-id command Prints the local libp2p PeerID by reading the key from disk. Used by the mesh-bench runner to discover PeerIDs before bringing up the mesh. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/entry/cmd/peerid.go | 36 ++++++++++++++++++++++++++++++++++++ src/entry/cmd/peerid_test.go | 32 ++++++++++++++++++++++++++++++++ src/entry/cmd/root.go | 1 + 3 files changed, 69 insertions(+) create mode 100644 src/entry/cmd/peerid.go create mode 100644 src/entry/cmd/peerid_test.go diff --git a/src/entry/cmd/peerid.go b/src/entry/cmd/peerid.go new file mode 100644 index 0000000..63db55f --- /dev/null +++ b/src/entry/cmd/peerid.go @@ -0,0 +1,36 @@ +package cmd + +import ( + "fmt" + "os" + + "github.com/libp2p/go-libp2p/core/crypto" + "github.com/libp2p/go-libp2p/core/peer" + "github.com/spf13/cobra" + "opentela/internal/protocol" +) + +var peerIDCmd = &cobra.Command{ + Use: "peer-id", + Short: "Print the local libp2p PeerID", + RunE: func(cmd *cobra.Command, args []string) error { + keyPath, err := protocol.ResolveKeyPath() + if err != nil { + return fmt.Errorf("resolve key path: %w", err) + } + data, err := os.ReadFile(keyPath) + if err != nil { + return fmt.Errorf("read key %s: %w", keyPath, err) + } + priv, err := crypto.UnmarshalPrivateKey(data) + if err != nil { + return fmt.Errorf("unmarshal key: %w", err) + } + pid, err := peer.IDFromPublicKey(priv.GetPublic()) + if err != nil { + return fmt.Errorf("derive peer id: %w", err) + } + fmt.Fprintln(cmd.OutOrStdout(), pid.String()) + return nil + }, +} diff --git a/src/entry/cmd/peerid_test.go b/src/entry/cmd/peerid_test.go new file mode 100644 index 0000000..e078ef3 --- /dev/null +++ b/src/entry/cmd/peerid_test.go @@ -0,0 +1,32 @@ +package cmd + +import ( + "bytes" + "os" + "testing" + + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" + "opentela/internal/protocol" +) + +func TestPeerIDCommand_PrintsPeerID(t *testing.T) { + dir, err := os.MkdirTemp("", "otela-peerid-test-*") + assert.NoError(t, err) + defer os.RemoveAll(dir) + + viper.Reset() + t.Cleanup(viper.Reset) + viper.Set("config_dir", dir) + _, err = protocol.GenerateAndWriteKey() + assert.NoError(t, err) + + var out bytes.Buffer + peerIDCmd.SetOut(&out) + err = peerIDCmd.RunE(peerIDCmd, nil) + assert.NoError(t, err) + printed := out.String() + // libp2p PeerIDs (RSA-derived) are base58 with no whitespace, ~46+ chars. + assert.GreaterOrEqual(t, len(printed), 40) + assert.NotContains(t, printed, " ") +} diff --git a/src/entry/cmd/root.go b/src/entry/cmd/root.go index 0530bbc..e0883c6 100644 --- a/src/entry/cmd/root.go +++ b/src/entry/cmd/root.go @@ -65,6 +65,7 @@ func init() { rootcmd.AddCommand(versionCmd) rootcmd.AddCommand(updateCmd) rootcmd.AddCommand(walletCmd) + rootcmd.AddCommand(peerIDCmd) } // configFilePath returns the canonical path for the OpenTela config file. From a43dacab970ceb01c78cf51b0b1d17face9c4ec0 Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sun, 3 May 2026 00:42:50 +0200 Subject: [PATCH 08/23] register libp2p /ipfs/ping/1.0.0 protocol Always-on diagnostic surface: every otela node now responds to libp2p ping. Used by the mesh-bench libp2p_ping probe kind. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/internal/protocol/host.go | 9 +++++++++ src/internal/protocol/host_test.go | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/internal/protocol/host.go b/src/internal/protocol/host.go index 8004841..bc46cf9 100644 --- a/src/internal/protocol/host.go +++ b/src/internal/protocol/host.go @@ -24,6 +24,7 @@ import ( dualdht "github.com/libp2p/go-libp2p-kad-dht/dual" record "github.com/libp2p/go-libp2p-record" relayClient "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/client" + "github.com/libp2p/go-libp2p/p2p/protocol/ping" "github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/host" @@ -69,6 +70,13 @@ func GetP2PNode(ds datastore.Batching) (host.Host, dualdht.DHT) { return *P2PNode, *ddht } +// registerPingProtocol enables the libp2p built-in /ipfs/ping/1.0.0 service +// on the given host. It is a separate function so it can be exercised in tests +// without standing up the full newHost pipeline. +func registerPingProtocol(h host.Host) { + ping.NewPingService(h) +} + func newHost(ctx context.Context, seed int64, ds datastore.Batching) (host.Host, error) { var err error if err != nil { @@ -209,6 +217,7 @@ func newHost(ctx context.Context, seed int64, ds datastore.Batching) (host.Host, if err != nil { return nil, err } + registerPingProtocol(host) // Set hostRef so the autorelay peer source callback can access the host. hostRef = &host diff --git a/src/internal/protocol/host_test.go b/src/internal/protocol/host_test.go index 0f9f4b7..df632f7 100644 --- a/src/internal/protocol/host_test.go +++ b/src/internal/protocol/host_test.go @@ -6,6 +6,7 @@ import ( "testing" "time" + "github.com/libp2p/go-libp2p" "github.com/multiformats/go-multiaddr" "github.com/stretchr/testify/assert" ) @@ -291,6 +292,25 @@ func TestBuildPublicTCPMultiaddr(t *testing.T) { } } +func TestNewHost_RegistersPingProtocol(t *testing.T) { + h, err := libp2p.New() + assert.NoError(t, err) + defer h.Close() + + // Manually run the registration step that newHost does. This proves + // the registration call is correct without spinning up the full node. + registerPingProtocol(h) + + var hasPing bool + for _, p := range h.Mux().Protocols() { + if p == "/ipfs/ping/1.0.0" { + hasPing = true + break + } + } + assert.True(t, hasPing, "expected /ipfs/ping/1.0.0 in registered protocols") +} + func TestAppendUniqueMultiaddrs(t *testing.T) { base := []multiaddr.Multiaddr{ multiaddr.StringCast("/ip4/10.0.0.1/tcp/43905"), From ef584c98e4237ed614accd03064504bff8cb14b0 Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sun, 3 May 2026 00:53:30 +0200 Subject: [PATCH 09/23] add /v1/probe/echo responder endpoint Streams N zero bytes back, capped at 1 GiB. Throughput counterpart for the mesh-bench probe. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/internal/server/probe_handler.go | 51 ++++++++++++++++++ src/internal/server/probe_handler_test.go | 65 +++++++++++++++++++++++ src/internal/server/server.go | 4 ++ 3 files changed, 120 insertions(+) create mode 100644 src/internal/server/probe_handler.go create mode 100644 src/internal/server/probe_handler_test.go diff --git a/src/internal/server/probe_handler.go b/src/internal/server/probe_handler.go new file mode 100644 index 0000000..21ffa62 --- /dev/null +++ b/src/internal/server/probe_handler.go @@ -0,0 +1,51 @@ +package server + +import ( + "io" + "net/http" + "strconv" + + "github.com/gin-gonic/gin" +) + +const maxEchoBytes = 1 << 30 // 1 GiB hard cap + +func echoHandler(c *gin.Context) { + raw := c.Query("bytes") + if raw == "" { + c.JSON(http.StatusBadRequest, gin.H{"error": "missing required query parameter: bytes"}) + return + } + n, err := strconv.ParseInt(raw, 10, 64) + if err != nil || n < 0 || n > maxEchoBytes { + c.JSON(http.StatusBadRequest, gin.H{"error": "bytes must be an integer in [0, 1073741824]"}) + return + } + c.Header("Content-Type", "application/octet-stream") + c.Header("Content-Length", strconv.FormatInt(n, 10)) + c.Status(http.StatusOK) + if n == 0 { + return + } + const chunk = 64 * 1024 + remaining := n + for remaining > 0 { + write := int64(chunk) + if remaining < write { + write = remaining + } + if _, err := io.CopyN(c.Writer, &zeroReader{}, write); err != nil { + return + } + remaining -= write + } +} + +type zeroReader struct{} + +func (zeroReader) Read(p []byte) (int, error) { + for i := range p { + p[i] = 0 + } + return len(p), nil +} diff --git a/src/internal/server/probe_handler_test.go b/src/internal/server/probe_handler_test.go new file mode 100644 index 0000000..fe1f2f3 --- /dev/null +++ b/src/internal/server/probe_handler_test.go @@ -0,0 +1,65 @@ +package server + +import ( + "io" + "net/http" + "net/http/httptest" + "strconv" + "testing" + + "github.com/gin-gonic/gin" + "github.com/stretchr/testify/assert" +) + +func newTestEngine() *gin.Engine { + gin.SetMode(gin.TestMode) + r := gin.New() + probeGroup := r.Group("/v1/probe") + probeGroup.GET("/echo", echoHandler) + return r +} + +func TestEcho_ReturnsRequestedByteCount(t *testing.T) { + r := newTestEngine() + for _, n := range []int64{0, 1, 1024, 1 << 20} { + req := httptest.NewRequest(http.MethodGet, "/v1/probe/echo?bytes="+strconv.FormatInt(n, 10), nil) + w := httptest.NewRecorder() + r.ServeHTTP(w, req) + assert.Equal(t, http.StatusOK, w.Code, "n=%d", n) + body, _ := io.ReadAll(w.Body) + assert.Equal(t, int(n), len(body), "n=%d", n) + assert.Equal(t, strconv.FormatInt(n, 10), w.Header().Get("Content-Length"), "n=%d", n) + } +} + +func TestEcho_RejectsMissingBytes(t *testing.T) { + r := newTestEngine() + req := httptest.NewRequest(http.MethodGet, "/v1/probe/echo", nil) + w := httptest.NewRecorder() + r.ServeHTTP(w, req) + assert.Equal(t, http.StatusBadRequest, w.Code) +} + +func TestEcho_RejectsInvalidBytes(t *testing.T) { + r := newTestEngine() + req := httptest.NewRequest(http.MethodGet, "/v1/probe/echo?bytes=notanumber", nil) + w := httptest.NewRecorder() + r.ServeHTTP(w, req) + assert.Equal(t, http.StatusBadRequest, w.Code) +} + +func TestEcho_RejectsExcessiveBytes(t *testing.T) { + r := newTestEngine() + req := httptest.NewRequest(http.MethodGet, "/v1/probe/echo?bytes=1073741825", nil) // 1 GiB + 1 + w := httptest.NewRecorder() + r.ServeHTTP(w, req) + assert.Equal(t, http.StatusBadRequest, w.Code) +} + +func TestEcho_RejectsNegativeBytes(t *testing.T) { + r := newTestEngine() + req := httptest.NewRequest(http.MethodGet, "/v1/probe/echo?bytes=-1", nil) + w := httptest.NewRecorder() + r.ServeHTTP(w, req) + assert.Equal(t, http.StatusBadRequest, w.Code) +} diff --git a/src/internal/server/server.go b/src/internal/server/server.go index 487f92a..0fc47c9 100644 --- a/src/internal/server/server.go +++ b/src/internal/server/server.go @@ -215,6 +215,10 @@ func StartServer() { StartChallengeCleanup() } } + probeGroup := v1.Group("/probe") + { + probeGroup.GET("/echo", echoHandler) + } v1.GET("/self", getSelf) v1.POST("/sign", signData) p2pGroup := v1.Group("/p2p") From dfd43e3b8948eb004759b3a6d292defb774eb473 Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sun, 3 May 2026 01:04:54 +0200 Subject: [PATCH 10/23] fix Task 5 review: flush per chunk and verify echo body content MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calling c.Writer.Flush() per chunk ensures the libp2p-http transport sees bytes incrementally — without it, throughput measurements would show inflated tail latency. Also adds a debug log on write errors and asserts the echo body is actually zero bytes for small n. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/internal/server/probe_handler.go | 6 +++++- src/internal/server/probe_handler_test.go | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/internal/server/probe_handler.go b/src/internal/server/probe_handler.go index 21ffa62..c2f2051 100644 --- a/src/internal/server/probe_handler.go +++ b/src/internal/server/probe_handler.go @@ -5,6 +5,8 @@ import ( "net/http" "strconv" + "opentela/internal/common" + "github.com/gin-gonic/gin" ) @@ -34,9 +36,11 @@ func echoHandler(c *gin.Context) { if remaining < write { write = remaining } - if _, err := io.CopyN(c.Writer, &zeroReader{}, write); err != nil { + if _, err := io.CopyN(c.Writer, zeroReader{}, write); err != nil { + common.Logger.Debugf("echo: write aborted after %d/%d bytes: %v", n-remaining, n, err) return } + c.Writer.Flush() remaining -= write } } diff --git a/src/internal/server/probe_handler_test.go b/src/internal/server/probe_handler_test.go index fe1f2f3..491058b 100644 --- a/src/internal/server/probe_handler_test.go +++ b/src/internal/server/probe_handler_test.go @@ -29,6 +29,10 @@ func TestEcho_ReturnsRequestedByteCount(t *testing.T) { body, _ := io.ReadAll(w.Body) assert.Equal(t, int(n), len(body), "n=%d", n) assert.Equal(t, strconv.FormatInt(n, 10), w.Header().Get("Content-Length"), "n=%d", n) + if n > 0 && n <= 1024 { + expected := make([]byte, n) + assert.Equal(t, expected, body, "body should be all-zero, n=%d", n) + } } } From 4d989f51c5eed6f9d83edf96ff15e7a853f59ca8 Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sun, 3 May 2026 01:10:44 +0200 Subject: [PATCH 11/23] add /v1/probe/run originator endpoint Three kinds: latency (HTTP-over-libp2p RTT to /v1/health), throughput (byte-stream from /v1/probe/echo), libp2p_ping (raw /ipfs/ping/1.0.0 RTT). Reuses the global libp2p HTTP transport from the proxy handler. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/internal/server/probe_handler.go | 232 ++++++++++++++++++++++ src/internal/server/probe_handler_test.go | 60 ++++++ src/internal/server/server.go | 1 + 3 files changed, 293 insertions(+) diff --git a/src/internal/server/probe_handler.go b/src/internal/server/probe_handler.go index c2f2051..dee2889 100644 --- a/src/internal/server/probe_handler.go +++ b/src/internal/server/probe_handler.go @@ -1,13 +1,22 @@ package server import ( + "context" + "encoding/json" + "fmt" "io" + "math" "net/http" + "sort" "strconv" + "time" "opentela/internal/common" + "opentela/internal/protocol" "github.com/gin-gonic/gin" + libp2ppeer "github.com/libp2p/go-libp2p/core/peer" + "github.com/libp2p/go-libp2p/p2p/protocol/ping" ) const maxEchoBytes = 1 << 30 // 1 GiB hard cap @@ -53,3 +62,226 @@ func (zeroReader) Read(p []byte) (int, error) { } return len(p), nil } + +type probeRequest struct { + Target string `json:"target"` + Kind string `json:"kind"` + Bytes int64 `json:"bytes"` + Count int `json:"count"` + TimeoutMS int `json:"timeout_ms"` +} + +type probeResponse struct { + OK bool `json:"ok"` + Kind string `json:"kind"` + Target string `json:"target"` + Config map[string]any `json:"config"` + Metrics map[string]any `json:"metrics"` + Error string `json:"error,omitempty"` +} + +func runHandler(c *gin.Context) { + var req probeRequest + if err := json.NewDecoder(c.Request.Body).Decode(&req); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid JSON body: " + err.Error()}) + return + } + if req.Target == "" { + c.JSON(http.StatusBadRequest, gin.H{"error": "target is required"}) + return + } + pid, err := libp2ppeer.Decode(req.Target) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid target peer id: " + err.Error()}) + return + } + if req.Count <= 0 { + req.Count = 20 + } + if req.TimeoutMS <= 0 { + req.TimeoutMS = 60000 + } + ctx, cancel := context.WithTimeout(c.Request.Context(), time.Duration(req.TimeoutMS)*time.Millisecond) + defer cancel() + + var resp probeResponse + resp.Target = req.Target + resp.Kind = req.Kind + resp.Config = map[string]any{ + "count": req.Count, + "bytes": req.Bytes, + "timeout_ms": req.TimeoutMS, + } + switch req.Kind { + case "latency": + resp.OK, resp.Metrics, resp.Error = runLatency(ctx, pid, req.Count) + case "throughput": + resp.OK, resp.Metrics, resp.Error = runThroughput(ctx, pid, req.Bytes, req.Count) + case "libp2p_ping": + resp.OK, resp.Metrics, resp.Error = runLibp2pPing(ctx, pid, req.Count) + default: + c.JSON(http.StatusBadRequest, gin.H{"error": "unknown kind: " + req.Kind}) + return + } + c.JSON(http.StatusOK, resp) +} + +func runLatency(ctx context.Context, pid libp2ppeer.ID, count int) (bool, map[string]any, string) { + transport := getGlobalTransport() + client := &http.Client{Transport: transport} + samples := make([]int64, 0, count) + var failed int + var lastErr string + url := "libp2p://" + pid.String() + "/v1/health" + for i := 0; i < count; i++ { + if ctx.Err() != nil { + break + } + req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) + if err != nil { + failed++ + lastErr = err.Error() + continue + } + start := time.Now() + resp, err := client.Do(req) + if err != nil { + failed++ + lastErr = err.Error() + continue + } + _, _ = io.Copy(io.Discard, resp.Body) + resp.Body.Close() + samples = append(samples, time.Since(start).Nanoseconds()) + } + if len(samples) == 0 { + return false, map[string]any{"failed_samples": failed}, "no successful samples: " + lastErr + } + return true, summariseDurations(samples, failed), "" +} + +func summariseDurations(samples []int64, failed int) map[string]any { + sorted := append([]int64(nil), samples...) + sort.Slice(sorted, func(i, j int) bool { return sorted[i] < sorted[j] }) + var sum int64 + for _, v := range sorted { + sum += v + } + pct := func(p float64) int64 { + if len(sorted) == 0 { + return 0 + } + idx := int(math.Round(p * float64(len(sorted)-1))) + return sorted[idx] + } + avg := sum / int64(len(sorted)) + return map[string]any{ + "min_ns": sorted[0], + "avg_ns": avg, + "p50_ns": pct(0.5), + "p95_ns": pct(0.95), + "max_ns": sorted[len(sorted)-1], + "min_ms": float64(sorted[0]) / 1e6, + "avg_ms": float64(avg) / 1e6, + "p50_ms": float64(pct(0.5)) / 1e6, + "p95_ms": float64(pct(0.95)) / 1e6, + "max_ms": float64(sorted[len(sorted)-1]) / 1e6, + "samples_ns": samples, + "failed_samples": failed, + } +} + +func runThroughput(ctx context.Context, pid libp2ppeer.ID, n int64, count int) (bool, map[string]any, string) { + if n <= 0 { + n = 10 * 1024 * 1024 // 10 MiB + } + transport := getGlobalTransport() + client := &http.Client{Transport: transport} + iterations := make([]map[string]any, 0, count) + var failed int + var lastErr string + url := fmt.Sprintf("libp2p://%s/v1/probe/echo?bytes=%d", pid.String(), n) + for i := 0; i < count; i++ { + if ctx.Err() != nil { + break + } + req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) + if err != nil { + failed++ + lastErr = err.Error() + continue + } + start := time.Now() + resp, err := client.Do(req) + if err != nil { + failed++ + lastErr = err.Error() + continue + } + bytesRead, copyErr := io.Copy(io.Discard, resp.Body) + resp.Body.Close() + elapsed := time.Since(start).Nanoseconds() + if copyErr != nil { + failed++ + lastErr = copyErr.Error() + continue + } + mbps := 0.0 + if elapsed > 0 { + mbps = (float64(bytesRead) * 8.0 / 1e6) / (float64(elapsed) / 1e9) + } + iterations = append(iterations, map[string]any{ + "bytes_received": bytesRead, + "elapsed_ns": elapsed, + "mbps": mbps, + }) + } + if len(iterations) == 0 { + return false, map[string]any{"failed_samples": failed}, "no successful iterations: " + lastErr + } + var totalBytes, totalElapsed int64 + var avgMbps float64 + for _, it := range iterations { + totalBytes += it["bytes_received"].(int64) + totalElapsed += it["elapsed_ns"].(int64) + avgMbps += it["mbps"].(float64) + } + avgMbps /= float64(len(iterations)) + return true, map[string]any{ + "bytes_received": totalBytes, + "elapsed_ns": totalElapsed, + "mbps": avgMbps, + "iterations": iterations, + "failed_samples": failed, + }, "" +} + +func runLibp2pPing(ctx context.Context, pid libp2ppeer.ID, count int) (bool, map[string]any, string) { + h, _ := protocol.GetP2PNode(nil) + if h == nil { + return false, nil, "libp2p host not initialized" + } + svc := ping.NewPingService(h) + resCh := svc.Ping(ctx, pid) + samples := make([]int64, 0, count) + var failed int + var lastErr string + for i := 0; i < count; i++ { + select { + case <-ctx.Done(): + return len(samples) > 0, summariseDurations(samples, failed), ctx.Err().Error() + case res := <-resCh: + if res.Error != nil { + failed++ + lastErr = res.Error.Error() + continue + } + samples = append(samples, res.RTT.Nanoseconds()) + } + } + if len(samples) == 0 { + return false, map[string]any{"failed_samples": failed}, "no successful pings: " + lastErr + } + return true, summariseDurations(samples, failed), "" +} + diff --git a/src/internal/server/probe_handler_test.go b/src/internal/server/probe_handler_test.go index 491058b..ef4489c 100644 --- a/src/internal/server/probe_handler_test.go +++ b/src/internal/server/probe_handler_test.go @@ -1,6 +1,8 @@ package server import ( + "bytes" + "encoding/json" "io" "net/http" "net/http/httptest" @@ -67,3 +69,61 @@ func TestEcho_RejectsNegativeBytes(t *testing.T) { r.ServeHTTP(w, req) assert.Equal(t, http.StatusBadRequest, w.Code) } + +func TestRun_RejectsInvalidBody(t *testing.T) { + gin.SetMode(gin.TestMode) + r := gin.New() + r.POST("/v1/probe/run", runHandler) + + req := httptest.NewRequest(http.MethodPost, "/v1/probe/run", bytes.NewReader([]byte("{"))) + req.Header.Set("Content-Type", "application/json") + w := httptest.NewRecorder() + r.ServeHTTP(w, req) + assert.Equal(t, http.StatusBadRequest, w.Code) +} + +func TestRun_RejectsUnknownKind(t *testing.T) { + gin.SetMode(gin.TestMode) + r := gin.New() + r.POST("/v1/probe/run", runHandler) + + body, _ := json.Marshal(map[string]any{ + "target": "12D3KooWPHmsoT1AdLbLUzVDYTk3xx3jSPfFy3Y3FdPzYpbPLyrV", + "kind": "telepathy", + "count": 1, + }) + req := httptest.NewRequest(http.MethodPost, "/v1/probe/run", bytes.NewReader(body)) + req.Header.Set("Content-Type", "application/json") + w := httptest.NewRecorder() + r.ServeHTTP(w, req) + assert.Equal(t, http.StatusBadRequest, w.Code) +} + +func TestRun_RejectsMissingTarget(t *testing.T) { + gin.SetMode(gin.TestMode) + r := gin.New() + r.POST("/v1/probe/run", runHandler) + + body, _ := json.Marshal(map[string]any{ + "kind": "latency", + "count": 1, + }) + req := httptest.NewRequest(http.MethodPost, "/v1/probe/run", bytes.NewReader(body)) + req.Header.Set("Content-Type", "application/json") + w := httptest.NewRecorder() + r.ServeHTTP(w, req) + assert.Equal(t, http.StatusBadRequest, w.Code) +} + +func TestSummariseDurations_ComputesPercentiles(t *testing.T) { + samples := []int64{1_000_000, 2_000_000, 3_000_000, 4_000_000, 5_000_000} + m := summariseDurations(samples, 0) + assert.Equal(t, int64(1_000_000), m["min_ns"]) + assert.Equal(t, int64(5_000_000), m["max_ns"]) + assert.Equal(t, int64(3_000_000), m["avg_ns"]) + assert.Equal(t, int64(3_000_000), m["p50_ns"]) + assert.Equal(t, int64(5_000_000), m["p95_ns"]) + assert.Equal(t, 0, m["failed_samples"]) + assert.Equal(t, 1.0, m["min_ms"]) + assert.Equal(t, 3.0, m["avg_ms"]) +} diff --git a/src/internal/server/server.go b/src/internal/server/server.go index 0fc47c9..6377704 100644 --- a/src/internal/server/server.go +++ b/src/internal/server/server.go @@ -218,6 +218,7 @@ func StartServer() { probeGroup := v1.Group("/probe") { probeGroup.GET("/echo", echoHandler) + probeGroup.POST("/run", runHandler) } v1.GET("/self", getSelf) v1.POST("/sign", signData) From 637ae65349fa56cb8e001fa90856b22779347114 Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sun, 3 May 2026 06:55:54 +0200 Subject: [PATCH 12/23] fix Task 6 review: bandwidth-weighted throughput and stateless ping ping.Ping(ctx, h, pid) avoids re-registering the global stream handler on every probe request (NewPingService overwrites the host's existing handler as a side effect). Throughput's aggregate mbps is now total_bytes * 8 / total_elapsed across all iterations, rather than the mean of per-iteration mbps. The per-iteration array still records each iteration's instant mbps. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/internal/server/probe_handler.go | 12 ++++++------ src/internal/server/probe_handler_test.go | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/internal/server/probe_handler.go b/src/internal/server/probe_handler.go index dee2889..ba55f3b 100644 --- a/src/internal/server/probe_handler.go +++ b/src/internal/server/probe_handler.go @@ -240,17 +240,18 @@ func runThroughput(ctx context.Context, pid libp2ppeer.ID, n int64, count int) ( return false, map[string]any{"failed_samples": failed}, "no successful iterations: " + lastErr } var totalBytes, totalElapsed int64 - var avgMbps float64 for _, it := range iterations { totalBytes += it["bytes_received"].(int64) totalElapsed += it["elapsed_ns"].(int64) - avgMbps += it["mbps"].(float64) } - avgMbps /= float64(len(iterations)) + mbps := 0.0 + if totalElapsed > 0 { + mbps = (float64(totalBytes) * 8.0 / 1e6) / (float64(totalElapsed) / 1e9) + } return true, map[string]any{ "bytes_received": totalBytes, "elapsed_ns": totalElapsed, - "mbps": avgMbps, + "mbps": mbps, "iterations": iterations, "failed_samples": failed, }, "" @@ -261,8 +262,7 @@ func runLibp2pPing(ctx context.Context, pid libp2ppeer.ID, count int) (bool, map if h == nil { return false, nil, "libp2p host not initialized" } - svc := ping.NewPingService(h) - resCh := svc.Ping(ctx, pid) + resCh := ping.Ping(ctx, h, pid) samples := make([]int64, 0, count) var failed int var lastErr string diff --git a/src/internal/server/probe_handler_test.go b/src/internal/server/probe_handler_test.go index ef4489c..9b9a421 100644 --- a/src/internal/server/probe_handler_test.go +++ b/src/internal/server/probe_handler_test.go @@ -127,3 +127,22 @@ func TestSummariseDurations_ComputesPercentiles(t *testing.T) { assert.Equal(t, 1.0, m["min_ms"]) assert.Equal(t, 3.0, m["avg_ms"]) } + +func TestRunThroughput_AggregateIsBandwidthWeighted(t *testing.T) { + // Two iterations, equal bytes, very different elapsed times. + // Per-iteration mbps: 80 and 8. Mean = 44 mbps. + // Bandwidth-weighted: total_bytes=2*1MB=16Mbits, total_elapsed=0.1+1.0=1.1s = 16/1.1 ≈ 14.55 mbps. + // The aggregate should be the bandwidth-weighted number. + iter1 := map[string]any{"bytes_received": int64(1000000), "elapsed_ns": int64(100000000), "mbps": 80.0} + iter2 := map[string]any{"bytes_received": int64(1000000), "elapsed_ns": int64(1000000000), "mbps": 8.0} + iterations := []map[string]any{iter1, iter2} + + var totalBytes, totalElapsed int64 + for _, it := range iterations { + totalBytes += it["bytes_received"].(int64) + totalElapsed += it["elapsed_ns"].(int64) + } + expected := (float64(totalBytes) * 8.0 / 1e6) / (float64(totalElapsed) / 1e9) + // Sanity check the test arithmetic itself. + assert.InDelta(t, 14.545, expected, 0.01) +} From 8089d5206478c66465399ea32f0601597052b7f0 Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sun, 3 May 2026 06:58:52 +0200 Subject: [PATCH 13/23] add otela probe CLI command Thin client over /v1/probe/run on the local node. Used by the mesh-bench runner to dispatch per-pair probes via rcc. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/entry/cmd/probe.go | 83 +++++++++++++++++++++++++++++++++++++ src/entry/cmd/probe_test.go | 62 +++++++++++++++++++++++++++ src/entry/cmd/root.go | 1 + 3 files changed, 146 insertions(+) create mode 100644 src/entry/cmd/probe.go create mode 100644 src/entry/cmd/probe_test.go diff --git a/src/entry/cmd/probe.go b/src/entry/cmd/probe.go new file mode 100644 index 0000000..42d41b2 --- /dev/null +++ b/src/entry/cmd/probe.go @@ -0,0 +1,83 @@ +package cmd + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "time" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var probeCmd = &cobra.Command{ + Use: "probe", + Short: "Run a libp2p latency or throughput probe to a peer", + RunE: func(cmd *cobra.Command, args []string) error { + target, _ := cmd.Flags().GetString("target") + kind, _ := cmd.Flags().GetString("kind") + count, _ := cmd.Flags().GetInt("count") + nbytes, _ := cmd.Flags().GetInt64("bytes") + timeout, _ := cmd.Flags().GetDuration("timeout") + if target == "" { + return fmt.Errorf("--target is required") + } + body, _ := json.Marshal(map[string]any{ + "target": target, + "kind": kind, + "count": count, + "bytes": nbytes, + "timeout_ms": int(timeout / time.Millisecond), + }) + port := viper.GetString("port") + if port == "" { + port = "8092" + } + url := "http://127.0.0.1:" + port + "/v1/probe/run" + ctx := cmd.Context() + if ctx == nil { + if root := cmd.Root(); root != nil { + ctx = root.Context() + } + } + if ctx == nil { + ctx = context.Background() + } + client := &http.Client{Timeout: timeout + 5*time.Second} + req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(body)) + if err != nil { + return err + } + req.Header.Set("Content-Type", "application/json") + resp, err := client.Do(req) + if err != nil { + return fmt.Errorf("contact local node at %s: %w", url, err) + } + defer resp.Body.Close() + respBody, _ := io.ReadAll(resp.Body) + fmt.Fprintln(cmd.OutOrStdout(), string(respBody)) + var parsed struct { + OK bool `json:"ok"` + Error string `json:"error"` + } + if err := json.Unmarshal(respBody, &parsed); err != nil { + return fmt.Errorf("parse response: %w", err) + } + if !parsed.OK { + return fmt.Errorf("probe failed: %s", parsed.Error) + } + return nil + }, +} + +//nolint:gochecknoinits +func init() { + probeCmd.Flags().String("target", "", "target peer id (required)") + probeCmd.Flags().String("kind", "latency", "probe kind: latency | throughput | libp2p_ping") + probeCmd.Flags().Int("count", 20, "number of samples") + probeCmd.Flags().Int64("bytes", 10*1024*1024, "bytes per iteration (throughput only)") + probeCmd.Flags().Duration("timeout", 60*time.Second, "total probe timeout") +} diff --git a/src/entry/cmd/probe_test.go b/src/entry/cmd/probe_test.go new file mode 100644 index 0000000..db9c826 --- /dev/null +++ b/src/entry/cmd/probe_test.go @@ -0,0 +1,62 @@ +package cmd + +import ( + "encoding/json" + "io" + "net/http" + "net/http/httptest" + "net/url" + "strings" + "testing" + + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" +) + +func TestProbeCommand_PostsAndPrintsResponse(t *testing.T) { + var gotBody map[string]any + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, "/v1/probe/run", r.URL.Path) + body, _ := io.ReadAll(r.Body) + _ = json.Unmarshal(body, &gotBody) + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"ok":true,"kind":"latency","metrics":{"avg_ns":1234567}}`)) + })) + defer server.Close() + + u, _ := url.Parse(server.URL) + viper.Reset() + t.Cleanup(viper.Reset) + viper.Set("port", strings.TrimPrefix(u.Host, "127.0.0.1:")) + + var stdout strings.Builder + probeCmd.SetOut(&stdout) + _ = probeCmd.Flags().Set("target", "12D3KooWtarget") + _ = probeCmd.Flags().Set("kind", "latency") + _ = probeCmd.Flags().Set("count", "5") + err := probeCmd.RunE(probeCmd, nil) + assert.NoError(t, err) + assert.Contains(t, stdout.String(), `"avg_ns":1234567`) + assert.Equal(t, "12D3KooWtarget", gotBody["target"]) + assert.Equal(t, "latency", gotBody["kind"]) + assert.Equal(t, float64(5), gotBody["count"]) +} + +func TestProbeCommand_ReturnsErrorOnNotOK(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"ok":false,"error":"unreachable"}`)) + })) + defer server.Close() + + u, _ := url.Parse(server.URL) + viper.Reset() + t.Cleanup(viper.Reset) + viper.Set("port", strings.TrimPrefix(u.Host, "127.0.0.1:")) + + var stdout strings.Builder + probeCmd.SetOut(&stdout) + _ = probeCmd.Flags().Set("target", "12D3KooWtarget") + err := probeCmd.RunE(probeCmd, nil) + assert.Error(t, err) +} diff --git a/src/entry/cmd/root.go b/src/entry/cmd/root.go index e0883c6..7657aed 100644 --- a/src/entry/cmd/root.go +++ b/src/entry/cmd/root.go @@ -66,6 +66,7 @@ func init() { rootcmd.AddCommand(updateCmd) rootcmd.AddCommand(walletCmd) rootcmd.AddCommand(peerIDCmd) + rootcmd.AddCommand(probeCmd) } // configFilePath returns the canonical path for the OpenTela config file. From 0c4ed38f21e168c47b04c7aeb6f956a2763085f7 Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sun, 3 May 2026 09:41:11 +0200 Subject: [PATCH 14/23] add bench config rendering for mesh-bench Pure functions to build per-host opentela cfg.yaml for an isolated bench mesh: ports, bootstrap multiaddrs, feature flags off. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../network_profiler/bench_config.py | 44 +++++++++++++++ contrib/network-profiler/pyproject.toml | 2 +- .../tests/test_bench_config.py | 54 +++++++++++++++++++ 3 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 contrib/network-profiler/network_profiler/bench_config.py create mode 100644 contrib/network-profiler/tests/test_bench_config.py diff --git a/contrib/network-profiler/network_profiler/bench_config.py b/contrib/network-profiler/network_profiler/bench_config.py new file mode 100644 index 0000000..494cbbe --- /dev/null +++ b/contrib/network-profiler/network_profiler/bench_config.py @@ -0,0 +1,44 @@ +from __future__ import annotations + +import re +from typing import Any + +from .model import Machine + +_IPV4_RE = re.compile(r"^\d+\.\d+\.\d+\.\d+$") + + +def build_multiaddr(machine: Machine, libp2p_port: int, peer_id: str) -> str: + if _IPV4_RE.match(machine.address): + return f"/ip4/{machine.address}/tcp/{libp2p_port}/p2p/{peer_id}" + return f"/dns4/{machine.address}/tcp/{libp2p_port}/p2p/{peer_id}" + + +def build_host_config( + self_machine: Machine, + all_machines: list[Machine], + peer_ids: dict[str, str], + run_id: str, + http_port: int, + libp2p_port: int, +) -> dict[str, Any]: + bootstrap = [ + build_multiaddr(m, libp2p_port, peer_ids[m.name]) + for m in all_machines + if m.name != self_machine.name + ] + return { + "port": str(http_port), + "tcpport": str(libp2p_port), + "udpport": str(libp2p_port + 1), + "cleanslate": True, + "bootstrap": {"static": bootstrap}, + "security": {"require_signed_binary": False}, + "scalability": { + "swim_enabled": False, + "crdt_tuned": False, + "weighted_routing": False, + }, + "billing": {"enabled": False}, + "bench": {"run_id": run_id}, + } diff --git a/contrib/network-profiler/pyproject.toml b/contrib/network-profiler/pyproject.toml index 2f5d366..3395c4f 100644 --- a/contrib/network-profiler/pyproject.toml +++ b/contrib/network-profiler/pyproject.toml @@ -3,7 +3,7 @@ name = "network-profiler" version = "0.1.0" description = "Pairwise network profiling over remote-cluster-controller managed machines" requires-python = ">=3.11" -dependencies = [] +dependencies = ["pyyaml>=6.0"] [project.scripts] network-profiler = "network_profiler.cli:main" diff --git a/contrib/network-profiler/tests/test_bench_config.py b/contrib/network-profiler/tests/test_bench_config.py new file mode 100644 index 0000000..63aa40b --- /dev/null +++ b/contrib/network-profiler/tests/test_bench_config.py @@ -0,0 +1,54 @@ +from network_profiler.bench_config import build_host_config, build_multiaddr +from network_profiler.model import Machine + + +def test_build_multiaddr_ipv4(): + m = Machine(name="clariden", address="10.0.0.1", rcc_host="clariden") + assert build_multiaddr(m, libp2p_port=19091, peer_id="12D3KooWAAA") == \ + "/ip4/10.0.0.1/tcp/19091/p2p/12D3KooWAAA" + + +def test_build_multiaddr_dns_fallback(): + m = Machine(name="clariden", address="clariden.cscs.ch", rcc_host="clariden") + assert build_multiaddr(m, libp2p_port=19091, peer_id="12D3KooWAAA") == \ + "/dns4/clariden.cscs.ch/tcp/19091/p2p/12D3KooWAAA" + + +def test_host_config_excludes_self_from_bootstrap(): + machines = [ + Machine(name="a", address="10.0.0.1", rcc_host="a"), + Machine(name="b", address="10.0.0.2", rcc_host="b"), + Machine(name="c", address="10.0.0.3", rcc_host="c"), + ] + peer_ids = {"a": "PIDA", "b": "PIDB", "c": "PIDC"} + cfg = build_host_config( + self_machine=machines[0], + all_machines=machines, + peer_ids=peer_ids, + run_id="run123", + http_port=19090, + libp2p_port=19091, + ) + assert cfg["port"] == "19090" + assert cfg["tcpport"] == "19091" + assert cfg["cleanslate"] is True + bootstrap = cfg["bootstrap"]["static"] + assert len(bootstrap) == 2 + assert any("PIDB" in addr for addr in bootstrap) + assert any("PIDC" in addr for addr in bootstrap) + assert all("PIDA" not in addr for addr in bootstrap) + + +def test_host_config_yaml_serialisable(): + import yaml + machines = [Machine(name="a", address="10.0.0.1", rcc_host="a")] + cfg = build_host_config( + self_machine=machines[0], + all_machines=machines, + peer_ids={"a": "PIDA"}, + run_id="run123", + http_port=19090, + libp2p_port=19091, + ) + out = yaml.safe_dump(cfg) + assert "port: '19090'" in out or "port: \"19090\"" in out From fa9b6a76b541e1f6247dfc081212a4583db96a14 Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sun, 3 May 2026 09:43:44 +0200 Subject: [PATCH 15/23] add bench phases: init and discover Per-host otela init and peer-id discovery for the mesh-bench runner. Pure orchestration over the existing RemoteRunner. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../network_profiler/bench.py | 38 ++++++++++++++ .../tests/test_bench_phases.py | 49 +++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 contrib/network-profiler/network_profiler/bench.py create mode 100644 contrib/network-profiler/tests/test_bench_phases.py diff --git a/contrib/network-profiler/network_profiler/bench.py b/contrib/network-profiler/network_profiler/bench.py new file mode 100644 index 0000000..185b77a --- /dev/null +++ b/contrib/network-profiler/network_profiler/bench.py @@ -0,0 +1,38 @@ +from __future__ import annotations + +from .model import Machine +from .remote import RemoteRunner + + +def bench_dir(run_id: str, host: str) -> str: + """Per-host bench dir. Suffixing by host lets multiple nodes share + one filesystem (e.g. localhost smoke test) without colliding.""" + return f"/tmp/otela-bench-{run_id}-{host}" + + +def phase_init(runner: RemoteRunner | object, machines: list[Machine], run_id: str) -> dict[str, str]: + """Run `otela init --config-dir ` on each host. Returns host -> rendered command.""" + out: dict[str, str] = {} + for m in machines: + d = bench_dir(run_id, m.name) + cmd = f"mkdir -p {d} && otela init --config-dir {d}" + result = runner.run(m, cmd, timeout=60) + if result.returncode != 0: + raise RuntimeError(f"phase_init failed on {m.name}: {result.stderr or result.stdout}") + out[m.name] = result.command + return out + + +def phase_discover(runner: RemoteRunner | object, machines: list[Machine], run_id: str) -> dict[str, str]: + """Run `otela peer-id --config-dir ` on each host. Returns host -> peer id.""" + out: dict[str, str] = {} + for m in machines: + cmd = f"otela peer-id --config-dir {bench_dir(run_id, m.name)}" + result = runner.run(m, cmd, timeout=30) + if result.returncode != 0: + raise RuntimeError(f"phase_discover failed on {m.name}: {result.stderr or result.stdout}") + peer_id = result.stdout.strip() + if not peer_id: + raise RuntimeError(f"phase_discover got empty peer-id from {m.name}") + out[m.name] = peer_id + return out diff --git a/contrib/network-profiler/tests/test_bench_phases.py b/contrib/network-profiler/tests/test_bench_phases.py new file mode 100644 index 0000000..44a3fbf --- /dev/null +++ b/contrib/network-profiler/tests/test_bench_phases.py @@ -0,0 +1,49 @@ +from network_profiler.bench import phase_init, phase_discover +from network_profiler.model import Machine, ProfilerConfig +from network_profiler.remote import RemoteRunner + + +def make_runner(): + config = ProfilerConfig( + machines=[ + Machine(name="a", address="10.0.0.1", rcc_host="a"), + Machine(name="b", address="10.0.0.2", rcc_host="b"), + ], + remote_command=["bash", "-lc", "{command}"], + ping_count=5, + iperf_seconds=5, + iperf_port=5201, + connect_timeout_seconds=10, + ) + return RemoteRunner(config, dry_run=True), config + + +def test_phase_init_runs_otela_init_per_host(): + runner, config = make_runner() + results = phase_init(runner, config.machines, run_id="run123") + assert set(results.keys()) == {"a", "b"} + # Each host gets its own bench dir suffix so multiple nodes on the + # same machine (smoke test) don't collide. + assert "/tmp/otela-bench-run123-a" in results["a"] + assert "/tmp/otela-bench-run123-b" in results["b"] + for cmd in results.values(): + assert "otela init" in cmd + + +def test_phase_discover_parses_peer_id(): + config = ProfilerConfig( + machines=[Machine(name="a", address="10.0.0.1", rcc_host="a")], + remote_command=None, + ping_count=5, + iperf_seconds=5, + iperf_port=5201, + connect_timeout_seconds=10, + ) + + class FakeRunner: + def run(self, machine, command, timeout=None): + from network_profiler.remote import CommandResult + return CommandResult(machine.name, command, 0, "12D3KooWAAA\n", "") + + peer_ids = phase_discover(FakeRunner(), config.machines, run_id="run123") + assert peer_ids == {"a": "12D3KooWAAA"} From 05477017bec5210a3c3e3432521983feb4e6ff6d Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sun, 3 May 2026 10:20:30 +0200 Subject: [PATCH 16/23] add bench phases: configure and push Renders per-host cfg.yaml with bootstrap multiaddrs and pushes via base64-piped stdin. RemoteRunner gains stdin support. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../network_profiler/bench.py | 36 ++++++++++++++++ .../network_profiler/remote.py | 11 +++-- .../tests/test_bench_phases.py | 41 +++++++++++++++++++ contrib/network-profiler/tests/test_remote.py | 12 ++++++ 4 files changed, 96 insertions(+), 4 deletions(-) diff --git a/contrib/network-profiler/network_profiler/bench.py b/contrib/network-profiler/network_profiler/bench.py index 185b77a..57fc15f 100644 --- a/contrib/network-profiler/network_profiler/bench.py +++ b/contrib/network-profiler/network_profiler/bench.py @@ -1,5 +1,10 @@ from __future__ import annotations +import base64 + +import yaml + +from .bench_config import build_host_config from .model import Machine from .remote import RemoteRunner @@ -36,3 +41,34 @@ def phase_discover(runner: RemoteRunner | object, machines: list[Machine], run_i raise RuntimeError(f"phase_discover got empty peer-id from {m.name}") out[m.name] = peer_id return out + + +def phase_configure_and_push( + runner, + machines: list[Machine], + peer_ids: dict[str, str], + run_id: str, + http_port: int, + libp2p_port: int, +) -> dict[str, str]: + """Render per-host cfg.yaml and push via stdin-piped base64.""" + out: dict[str, str] = {} + for m in machines: + d = bench_dir(run_id, m.name) + cfg_path = f"{d}/cfg.yaml" + cfg = build_host_config( + self_machine=m, + all_machines=machines, + peer_ids=peer_ids, + run_id=run_id, + http_port=http_port, + libp2p_port=libp2p_port, + ) + yaml_bytes = yaml.safe_dump(cfg, sort_keys=True).encode("utf-8") + b64 = base64.b64encode(yaml_bytes) + cmd = f"mkdir -p {d} && base64 -d > {cfg_path}" + result = runner.run(m, cmd, timeout=30, stdin=b64) + if result.returncode != 0: + raise RuntimeError(f"phase_configure_and_push failed on {m.name}: {result.stderr or result.stdout}") + out[m.name] = cfg_path + return out diff --git a/contrib/network-profiler/network_profiler/remote.py b/contrib/network-profiler/network_profiler/remote.py index 98ee9a2..933a3dd 100644 --- a/contrib/network-profiler/network_profiler/remote.py +++ b/contrib/network-profiler/network_profiler/remote.py @@ -57,7 +57,7 @@ def build_args(self, machine: Machine, command: str) -> list[str]: for part in template ] - def run(self, machine: Machine, command: str, timeout: int | None = None) -> CommandResult: + def run(self, machine: Machine, command: str, timeout: int | None = None, stdin: bytes | None = None) -> CommandResult: args = self.build_args(machine, command) if self.dry_run: rendered = shlex.join(args) @@ -66,15 +66,18 @@ def run(self, machine: Machine, command: str, timeout: int | None = None) -> Com completed = subprocess.run( args, check=False, - text=True, + text=True if stdin is None else False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + input=stdin, timeout=timeout, ) + stdout = completed.stdout if isinstance(completed.stdout, str) else completed.stdout.decode("utf-8", errors="replace") + stderr = completed.stderr if isinstance(completed.stderr, str) else completed.stderr.decode("utf-8", errors="replace") return CommandResult( host=machine.name, command=shlex.join(args), returncode=completed.returncode, - stdout=completed.stdout, - stderr=completed.stderr, + stdout=stdout, + stderr=stderr, ) diff --git a/contrib/network-profiler/tests/test_bench_phases.py b/contrib/network-profiler/tests/test_bench_phases.py index 44a3fbf..fec1ebd 100644 --- a/contrib/network-profiler/tests/test_bench_phases.py +++ b/contrib/network-profiler/tests/test_bench_phases.py @@ -47,3 +47,44 @@ def run(self, machine, command, timeout=None): peer_ids = phase_discover(FakeRunner(), config.machines, run_id="run123") assert peer_ids == {"a": "12D3KooWAAA"} + + +import base64 + +from network_profiler.bench import phase_configure_and_push + + +def test_phase_configure_and_push_writes_yaml_per_host(): + machines = [ + Machine(name="a", address="10.0.0.1", rcc_host="a"), + Machine(name="b", address="10.0.0.2", rcc_host="b"), + ] + peer_ids = {"a": "PIDA", "b": "PIDB"} + + captured: list[tuple[str, str, bytes]] = [] + + class FakeRunner: + def run(self, machine, command, timeout=None, stdin=None): + captured.append((machine.name, command, stdin or b"")) + from network_profiler.remote import CommandResult + return CommandResult(machine.name, command, 0, "", "") + + phase_configure_and_push( + FakeRunner(), + machines, + peer_ids, + run_id="run123", + http_port=19090, + libp2p_port=19091, + ) + assert {h for h, _, _ in captured} == {"a", "b"} + for host, cmd, stdin in captured: + assert "base64 -d" in cmd + # Per-host bench dir + assert f"/tmp/otela-bench-run123-{host}/cfg.yaml" in cmd + decoded = base64.b64decode(stdin).decode() + assert "bootstrap:" in decoded + if host == "a": + assert "PIDB" in decoded and "PIDA" not in decoded + else: + assert "PIDA" in decoded and "PIDB" not in decoded diff --git a/contrib/network-profiler/tests/test_remote.py b/contrib/network-profiler/tests/test_remote.py index e63c675..cab98a6 100644 --- a/contrib/network-profiler/tests/test_remote.py +++ b/contrib/network-profiler/tests/test_remote.py @@ -18,3 +18,15 @@ def test_remote_command_template_expands_host_and_command() -> None: "cluster/node-a", "hostname", ] + + +def test_remote_runner_accepts_stdin(): + config = ProfilerConfig( + machines=[Machine(name="a", address="x", rcc_host="a")], + remote_command=["sh", "-c", "cat"], + ping_count=1, iperf_seconds=1, iperf_port=5201, connect_timeout_seconds=1, + ) + runner = RemoteRunner(config, dry_run=False) + result = runner.run(config.machines[0], "ignored", stdin=b"hello") + assert result.returncode == 0 + assert result.stdout == "hello" From a9df2c95c690cab5324617ec6b8625b1d6667756 Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sun, 3 May 2026 10:26:10 +0200 Subject: [PATCH 17/23] add bench phases: start and converge Background-launch otela on each host, poll /v1/health for readiness, then poll /v1/dnt/table for full mesh convergence. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../network_profiler/bench.py | 99 +++++++++++++++++++ .../tests/test_bench_phases.py | 51 ++++++++++ 2 files changed, 150 insertions(+) diff --git a/contrib/network-profiler/network_profiler/bench.py b/contrib/network-profiler/network_profiler/bench.py index 57fc15f..aa3655e 100644 --- a/contrib/network-profiler/network_profiler/bench.py +++ b/contrib/network-profiler/network_profiler/bench.py @@ -1,6 +1,8 @@ from __future__ import annotations import base64 +import json +import time import yaml @@ -72,3 +74,100 @@ def phase_configure_and_push( raise RuntimeError(f"phase_configure_and_push failed on {m.name}: {result.stderr or result.stdout}") out[m.name] = cfg_path return out + + +def _http_port_for(m: Machine, default: int) -> int: + return getattr(m, "http_port", None) or default + + +def phase_start( + runner, + machines: list[Machine], + run_id: str, + http_port: int, + max_wait_s: int = 30, +) -> None: + for m in machines: + d = bench_dir(run_id, m.name) + cfg_path = f"{d}/cfg.yaml" + log_path = f"{d}/log" + cmd = ( + f"nohup otela start --config {cfg_path} " + f">>{log_path} 2>&1 &" + ) + result = runner.run(m, cmd, timeout=10) + if result.returncode != 0: + raise RuntimeError(f"phase_start could not launch on {m.name}: {result.stderr}") + + for m in machines: + port = _http_port_for(m, http_port) + deadline = time.monotonic() + max_wait_s + while True: + health = runner.run( + m, + f"curl -fsS http://127.0.0.1:{port}/v1/health", + timeout=10, + ) + if health.returncode == 0: + break + if time.monotonic() > deadline: + raise RuntimeError( + f"phase_start: {m.name} did not become healthy within {max_wait_s}s" + ) + time.sleep(1) + + +def phase_converge( + runner, + machines: list[Machine], + peer_ids: dict[str, str], + http_port: int, + max_wait_s: int = 60, +) -> dict[str, dict]: + out: dict[str, dict] = {} + expected = {p for p in peer_ids.values()} + for m in machines: + port = _http_port_for(m, http_port) + deadline = time.monotonic() + max_wait_s + complete = False + elapsed_s = 0.0 + start_t = time.monotonic() + while time.monotonic() <= deadline: + tbl = runner.run( + m, + f"curl -s http://127.0.0.1:{port}/v1/dnt/table", + timeout=10, + ) + if tbl.returncode == 0: + seen = _extract_peer_ids(tbl.stdout) + if expected - {peer_ids[m.name]} <= seen: + complete = True + break + time.sleep(1) + elapsed_s = time.monotonic() - start_t + out[m.name] = {"complete": complete, "elapsed_s": round(elapsed_s, 2)} + return out + + +def _extract_peer_ids(table_json: str) -> set[str]: + """Tolerant extraction: walk any list/dict and collect string values that + look like libp2p PeerIDs (start with 12D3 or Qm).""" + try: + data = json.loads(table_json) + except json.JSONDecodeError: + return set() + found: set[str] = set() + + def walk(obj): + if isinstance(obj, dict): + for v in obj.values(): + walk(v) + elif isinstance(obj, list): + for item in obj: + walk(item) + elif isinstance(obj, str): + if obj.startswith("12D3") or obj.startswith("Qm"): + found.add(obj) + + walk(data) + return found diff --git a/contrib/network-profiler/tests/test_bench_phases.py b/contrib/network-profiler/tests/test_bench_phases.py index fec1ebd..f223bbd 100644 --- a/contrib/network-profiler/tests/test_bench_phases.py +++ b/contrib/network-profiler/tests/test_bench_phases.py @@ -88,3 +88,54 @@ def run(self, machine, command, timeout=None, stdin=None): assert "PIDB" in decoded and "PIDA" not in decoded else: assert "PIDA" in decoded and "PIDB" not in decoded + + +import json + +from network_profiler.bench import phase_start, phase_converge +from network_profiler.remote import CommandResult + + +class ScriptedRunner: + """Returns canned responses keyed on (host, command-substring).""" + def __init__(self, responses): + self.responses = responses + self.calls = [] + + def run(self, machine, command, timeout=None, stdin=None): + self.calls.append((machine.name, command)) + for substr, payload in self.responses.get(machine.name, []): + if substr in command: + rc, stdout, stderr = payload + return CommandResult(machine.name, command, rc, stdout, stderr) + raise AssertionError(f"unexpected command for {machine.name}: {command}") + + +def test_phase_start_polls_health_then_succeeds(): + machines = [Machine(name="a", address="x", rcc_host="a")] + runner = ScriptedRunner({ + "a": [ + ("nohup otela start", (0, "", "")), + ("curl -fsS http://127.0.0.1:19090/v1/health", (0, '{"status":"ok"}', "")), + ], + }) + phase_start(runner, machines, run_id="run123", http_port=19090, max_wait_s=5) + assert any("nohup otela start" in c for _, c in runner.calls) + assert any("/v1/health" in c for _, c in runner.calls) + + +def test_phase_converge_returns_when_all_peers_seen(): + machines = [ + Machine(name="a", address="x", rcc_host="a"), + Machine(name="b", address="y", rcc_host="b"), + ] + peer_ids = {"a": "12D3PIDA", "b": "12D3PIDB"} + table_a = json.dumps({"peers": [{"id": "12D3PIDB"}]}) + table_b = json.dumps({"peers": [{"id": "12D3PIDA"}]}) + runner = ScriptedRunner({ + "a": [("dnt/table", (0, table_a, ""))], + "b": [("dnt/table", (0, table_b, ""))], + }) + convergence = phase_converge(runner, machines, peer_ids, http_port=19090, max_wait_s=5) + assert convergence["a"]["complete"] is True + assert convergence["b"]["complete"] is True From f9256bfc3acd7e58246c180e344c553ae57cc18b Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sun, 3 May 2026 10:33:59 +0200 Subject: [PATCH 18/23] add bench phase: sweep Pairwise (src, dst, kind) sweep that calls otela probe via rcc and writes one JSONL record per measurement. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../network_profiler/bench.py | 75 +++++++++++++++++++ .../tests/test_bench_phases.py | 45 +++++++++++ 2 files changed, 120 insertions(+) diff --git a/contrib/network-profiler/network_profiler/bench.py b/contrib/network-profiler/network_profiler/bench.py index aa3655e..d17b5ea 100644 --- a/contrib/network-profiler/network_profiler/bench.py +++ b/contrib/network-profiler/network_profiler/bench.py @@ -3,6 +3,8 @@ import base64 import json import time +from datetime import datetime, timezone +from pathlib import Path import yaml @@ -149,6 +151,79 @@ def phase_converge( return out +def phase_sweep( + runner, + machines: list[Machine], + peer_ids: dict[str, str], + run_id: str, + output: Path, + kinds: list[dict], +) -> dict[str, int]: + output = Path(output) + output.parent.mkdir(parents=True, exist_ok=True) + ok = 0 + failed = 0 + for spec in kinds: + kind = spec["kind"] + count = spec.get("count", 20) + nbytes = spec.get("bytes", 0) + for src in machines: + for dst in machines: + if src.name == dst.name: + continue + cfg_path = f"{bench_dir(run_id, src.name)}/cfg.yaml" + cmd = ( + f"otela probe --target {peer_ids[dst.name]} " + f"--kind {kind} --count {count} --bytes {nbytes} " + f"--config {cfg_path}" + ) + result = runner.run(src, cmd, timeout=count * 5 + nbytes // (1 << 20) + 60) + record = _build_record( + src=src, + dst=dst, + src_peer_id=peer_ids[src.name], + dst_peer_id=peer_ids[dst.name], + kind=kind, + count=count, + nbytes=nbytes, + run_id=run_id, + result=result, + ) + with output.open("a", encoding="utf-8") as f: + f.write(json.dumps(record, sort_keys=True) + "\n") + if record["ok"]: + ok += 1 + else: + failed += 1 + return {"ok": ok, "failed": failed} + + +def _build_record(*, src, dst, src_peer_id, dst_peer_id, kind, count, nbytes, run_id, result) -> dict: + parsed = None + if result.returncode == 0 and result.stdout: + try: + parsed = json.loads(result.stdout.strip().splitlines()[-1]) + except json.JSONDecodeError: + parsed = None + ok = bool(parsed and parsed.get("ok")) + return { + "run_id": run_id, + "timestamp": datetime.now(timezone.utc).isoformat(timespec="seconds"), + "kind": kind, + "source": src.name, + "target": dst.name, + "source_peer_id": src_peer_id, + "target_peer_id": dst_peer_id, + "ok": ok, + "config": {"count": count, "bytes": nbytes if kind == "throughput" else None}, + "metrics": (parsed or {}).get("metrics", {}) if ok else {}, + "error": None if ok else ( + (parsed or {}).get("error") if parsed else (result.stderr or result.stdout or "no output") + ), + "command": result.command, + } + + def _extract_peer_ids(table_json: str) -> set[str]: """Tolerant extraction: walk any list/dict and collect string values that look like libp2p PeerIDs (start with 12D3 or Qm).""" diff --git a/contrib/network-profiler/tests/test_bench_phases.py b/contrib/network-profiler/tests/test_bench_phases.py index f223bbd..98d278d 100644 --- a/contrib/network-profiler/tests/test_bench_phases.py +++ b/contrib/network-profiler/tests/test_bench_phases.py @@ -139,3 +139,48 @@ def test_phase_converge_returns_when_all_peers_seen(): convergence = phase_converge(runner, machines, peer_ids, http_port=19090, max_wait_s=5) assert convergence["a"]["complete"] is True assert convergence["b"]["complete"] is True + + +import tempfile +from pathlib import Path + +from network_profiler.bench import phase_sweep + + +def test_phase_sweep_writes_jsonl_record_per_pair_and_kind(): + machines = [ + Machine(name="a", address="x", rcc_host="a"), + Machine(name="b", address="y", rcc_host="b"), + ] + peer_ids = {"a": "PIDA", "b": "PIDB"} + canned = json.dumps({ + "ok": True, "kind": "latency", + "metrics": {"avg_ns": 1234567, "avg_ms": 1.234}, + }) + runner = ScriptedRunner({ + "a": [("otela probe", (0, canned, ""))], + "b": [("otela probe", (0, canned, ""))], + }) + with tempfile.TemporaryDirectory() as tmp: + out_path = Path(tmp) / "measurements.jsonl" + phase_sweep( + runner, machines, peer_ids, + run_id="run123", + output=out_path, + kinds=[ + {"kind": "latency", "count": 10, "bytes": 0}, + {"kind": "throughput", "count": 1, "bytes": 1048576}, + ], + ) + lines = out_path.read_text().splitlines() + assert len(lines) == 4 # 2 ordered pairs × 2 kinds + records = [json.loads(l) for l in lines] + assert {(r["source"], r["target"], r["kind"]) for r in records} == { + ("a", "b", "latency"), + ("b", "a", "latency"), + ("a", "b", "throughput"), + ("b", "a", "throughput"), + } + assert all(r["source_peer_id"] for r in records) + assert all(r["target_peer_id"] for r in records) + assert all(r["ok"] for r in records) From 385784fc8f232be2d0a6e8e57f35c1e6038ee3a6 Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sun, 3 May 2026 10:38:45 +0200 Subject: [PATCH 19/23] add bench phase: teardown pkill matched on the unique bench cfg path, then rm -rf the bench dir. Best-effort: pkill returning 1 (no match) is not a failure. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../network_profiler/bench.py | 8 +++++ .../tests/test_bench_phases.py | 29 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/contrib/network-profiler/network_profiler/bench.py b/contrib/network-profiler/network_profiler/bench.py index d17b5ea..5b101b2 100644 --- a/contrib/network-profiler/network_profiler/bench.py +++ b/contrib/network-profiler/network_profiler/bench.py @@ -224,6 +224,14 @@ def _build_record(*, src, dst, src_peer_id, dst_peer_id, kind, count, nbytes, ru } +def phase_teardown(runner, machines: list[Machine], run_id: str) -> None: + for m in machines: + d = bench_dir(run_id, m.name) + cfg_path = f"{d}/cfg.yaml" + runner.run(m, f"pkill -f 'otela start --config {cfg_path}' || true", timeout=10) + runner.run(m, f"rm -rf {d} || true", timeout=10) + + def _extract_peer_ids(table_json: str) -> set[str]: """Tolerant extraction: walk any list/dict and collect string values that look like libp2p PeerIDs (start with 12D3 or Qm).""" diff --git a/contrib/network-profiler/tests/test_bench_phases.py b/contrib/network-profiler/tests/test_bench_phases.py index 98d278d..7010ad9 100644 --- a/contrib/network-profiler/tests/test_bench_phases.py +++ b/contrib/network-profiler/tests/test_bench_phases.py @@ -184,3 +184,32 @@ def test_phase_sweep_writes_jsonl_record_per_pair_and_kind(): assert all(r["source_peer_id"] for r in records) assert all(r["target_peer_id"] for r in records) assert all(r["ok"] for r in records) + + +from network_profiler.bench import phase_teardown + + +def test_phase_teardown_pkills_and_removes_bench_dir(): + machines = [ + Machine(name="a", address="x", rcc_host="a"), + Machine(name="b", address="y", rcc_host="b"), + ] + runner = ScriptedRunner({ + "a": [("pkill -f", (0, "", "")), ("rm -rf", (0, "", ""))], + "b": [("pkill -f", (0, "", "")), ("rm -rf", (0, "", ""))], + }) + phase_teardown(runner, machines, run_id="run123") + cmds = [(h, c) for h, c in runner.calls] + # pkill matcher and rm path are both per-host + assert any(h == "a" and "pkill -f" in c and "/tmp/otela-bench-run123-a/cfg.yaml" in c for h, c in cmds) + assert any(h == "b" and "rm -rf /tmp/otela-bench-run123-b" in c for h, c in cmds) + + +def test_phase_teardown_warns_but_does_not_fail_on_pkill_returning_1(): + """pkill returns 1 when no processes match. Treat as success.""" + machines = [Machine(name="a", address="x", rcc_host="a")] + runner = ScriptedRunner({ + "a": [("pkill -f", (1, "", "")), ("rm -rf", (0, "", ""))], + }) + # must not raise + phase_teardown(runner, machines, run_id="run123") From f8a52821f039dc402e9c7d4a64e073b6ead5ce78 Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sun, 3 May 2026 10:42:14 +0200 Subject: [PATCH 20/23] wire net-profiler bench subcommand Top-level orchestrator with signal-safe teardown, phase timing, and run.json summary alongside measurements.jsonl. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../network_profiler/bench.py | 111 ++++++++++++++++++ .../network-profiler/network_profiler/cli.py | 29 +++++ .../network-profiler/tests/test_bench_cli.py | 37 ++++++ 3 files changed, 177 insertions(+) create mode 100644 contrib/network-profiler/tests/test_bench_cli.py diff --git a/contrib/network-profiler/network_profiler/bench.py b/contrib/network-profiler/network_profiler/bench.py index 5b101b2..d19e561 100644 --- a/contrib/network-profiler/network_profiler/bench.py +++ b/contrib/network-profiler/network_profiler/bench.py @@ -2,7 +2,10 @@ import base64 import json +import signal +import sys import time +import uuid from datetime import datetime, timezone from pathlib import Path @@ -254,3 +257,111 @@ def walk(obj): walk(data) return found + + +def new_run_id() -> str: + return time.strftime("%Y-%m-%dT%H-%M-%S") + "-" + uuid.uuid4().hex[:6] + + +def run_bench( + *, + runner, + machines: list[Machine], + output_dir: Path, + run_id: str, + http_port: int = 19090, + libp2p_port: int = 19091, + latency_count: int = 20, + throughput_count: int = 3, + throughput_bytes: int = 10 * 1024 * 1024, + keep: bool = False, +) -> int: + output_dir = Path(output_dir) + output_dir.mkdir(parents=True, exist_ok=True) + measurements_path = output_dir / "measurements.jsonl" + run_json_path = output_dir / "run.json" + + started_at = datetime.now(timezone.utc) + phase_timings: dict[str, float] = {} + convergence: dict[str, dict] = {} + peer_ids: dict[str, str] = {} + totals: dict[str, int] = {} + teardown_done = False + + def teardown(): + nonlocal teardown_done + if teardown_done or keep: + return + teardown_done = True + t0 = time.monotonic() + try: + phase_teardown(runner, machines, run_id) + except Exception as e: + print(f"warning: teardown error: {e}") + phase_timings["teardown_s"] = round(time.monotonic() - t0, 2) + + def on_sigint(signum, frame): + print("\ninterrupted, running teardown") + teardown() + sys.exit(130) + + signal.signal(signal.SIGINT, on_sigint) + try: + t0 = time.monotonic() + phase_init(runner, machines, run_id) + phase_timings["init_s"] = round(time.monotonic() - t0, 2) + + t0 = time.monotonic() + peer_ids = phase_discover(runner, machines, run_id) + phase_timings["discover_s"] = round(time.monotonic() - t0, 2) + + t0 = time.monotonic() + phase_configure_and_push( + runner, machines, peer_ids, run_id, + http_port=http_port, libp2p_port=libp2p_port, + ) + phase_timings["configure_s"] = round(time.monotonic() - t0, 2) + + t0 = time.monotonic() + phase_start(runner, machines, run_id, http_port=http_port) + phase_timings["start_s"] = round(time.monotonic() - t0, 2) + + t0 = time.monotonic() + convergence = phase_converge(runner, machines, peer_ids, http_port=http_port) + phase_timings["converge_s"] = round(time.monotonic() - t0, 2) + + t0 = time.monotonic() + totals = phase_sweep( + runner, machines, peer_ids, run_id, + output=measurements_path, + kinds=[ + {"kind": "libp2p_ping", "count": latency_count, "bytes": 0}, + {"kind": "latency", "count": latency_count, "bytes": 0}, + {"kind": "throughput", "count": throughput_count, "bytes": throughput_bytes}, + ], + ) + phase_timings["sweep_s"] = round(time.monotonic() - t0, 2) + finally: + teardown() + + ended_at = datetime.now(timezone.utc) + summary = { + "run_id": run_id, + "started_at": started_at.isoformat(timespec="seconds"), + "ended_at": ended_at.isoformat(timespec="seconds"), + "machines": [ + { + "name": m.name, + "address": m.address, + "peer_id": peer_ids.get(m.name), + "http_port": http_port, + "libp2p_port": libp2p_port, + } + for m in machines + ], + "convergence": convergence, + "phases": phase_timings, + "totals": totals, + } + run_json_path.write_text(json.dumps(summary, indent=2, sort_keys=True)) + return 0 diff --git a/contrib/network-profiler/network_profiler/cli.py b/contrib/network-profiler/network_profiler/cli.py index 504d3b3..908b2ee 100644 --- a/contrib/network-profiler/network_profiler/cli.py +++ b/contrib/network-profiler/network_profiler/cli.py @@ -4,6 +4,7 @@ import argparse import json +from .bench import new_run_id, run_bench from .measure import collect from .model import load_config from .remote import RemoteRunner @@ -28,6 +29,17 @@ def build_parser() -> argparse.ArgumentParser: heatmap.add_argument("--output", type=Path, default=Path("results/network-heatmap.html")) heatmap.add_argument("--kind", choices=["ping", "iperf3"], default="ping") heatmap.add_argument("--metric", default=None, help="Defaults to avg for ping, mbps for iperf3.") + + bench = subparsers.add_parser("bench", help="Bring up an isolated mesh and profile pairwise libp2p latency/throughput.") + bench.add_argument("--config", type=Path, required=True) + bench.add_argument("--output", type=Path, default=None, help="Output directory. Defaults to results//") + bench.add_argument("--run-id", default=None) + bench.add_argument("--http-port", type=int, default=19090) + bench.add_argument("--libp2p-port", type=int, default=19091) + bench.add_argument("--latency-count", type=int, default=20) + bench.add_argument("--throughput-count", type=int, default=3) + bench.add_argument("--throughput-bytes", type=int, default=10 * 1024 * 1024) + bench.add_argument("--keep", action="store_true") return parser @@ -64,4 +76,21 @@ def main(argv: list[str] | None = None) -> int: metric = args.metric or ("avg" if args.kind == "ping" else "mbps") render_heatmap(args.input, args.output, args.kind, metric) return 0 + if args.command == "bench": + config = load_config(args.config) + runner = RemoteRunner(config, dry_run=False) + run_id = args.run_id or new_run_id() + output = args.output or Path("results") / run_id + return run_bench( + runner=runner, + machines=config.machines, + output_dir=output, + run_id=run_id, + http_port=args.http_port, + libp2p_port=args.libp2p_port, + latency_count=args.latency_count, + throughput_count=args.throughput_count, + throughput_bytes=args.throughput_bytes, + keep=args.keep, + ) raise AssertionError(args.command) diff --git a/contrib/network-profiler/tests/test_bench_cli.py b/contrib/network-profiler/tests/test_bench_cli.py new file mode 100644 index 0000000..c57c3c0 --- /dev/null +++ b/contrib/network-profiler/tests/test_bench_cli.py @@ -0,0 +1,37 @@ +import json +import sys +from unittest.mock import patch + +import pytest + +from network_profiler.cli import main + + +def test_bench_cli_help_lists_subcommand(): + with patch.object(sys, "argv", ["net-profiler", "bench", "--help"]): + with pytest.raises(SystemExit) as e: + main() + assert e.value.code == 0 + + +def test_bench_cli_invokes_run_bench(monkeypatch, tmp_path): + cfg = tmp_path / "machines.json" + cfg.write_text(json.dumps({ + "remote_command": ["echo", "{command}"], + "machines": [{"name": "a", "address": "10.0.0.1", "rcc_host": "a"}], + })) + called = {} + + def fake_run_bench(**kwargs): + called.update(kwargs) + return 0 + + monkeypatch.setattr("network_profiler.bench.run_bench", fake_run_bench) + monkeypatch.setattr("network_profiler.cli.run_bench", fake_run_bench) + with patch.object(sys, "argv", [ + "net-profiler", "bench", "--config", str(cfg), + "--run-id", "rTEST", "--output", str(tmp_path / "out"), + ]): + rc = main() + assert rc == 0 + assert called["run_id"] == "rTEST" From 2d45fa738882c63a6b46582c00e644ef399688cd Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sun, 3 May 2026 10:51:15 +0200 Subject: [PATCH 21/23] add bench end-to-end smoke test and per-machine port overrides Local two-node validation runs the full bench pipeline against loopback. Per-machine http_port/libp2p_port overrides allow multiple nodes on a single host. phase_start now passes --config-dir so otela loads the libp2p key from the bench dir (matching what peer-id discovered) rather than the default ~/.config/opentela location. Co-Authored-By: Claude Opus 4.7 (1M context) --- contrib/network-profiler/Makefile | 8 +++ .../network_profiler/bench.py | 2 +- .../network_profiler/bench_config.py | 14 +++-- .../network_profiler/model.py | 4 ++ .../tests/test_bench_smoke.py | 59 +++++++++++++++++++ 5 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 contrib/network-profiler/Makefile create mode 100644 contrib/network-profiler/tests/test_bench_smoke.py diff --git a/contrib/network-profiler/Makefile b/contrib/network-profiler/Makefile new file mode 100644 index 0000000..616c648 --- /dev/null +++ b/contrib/network-profiler/Makefile @@ -0,0 +1,8 @@ +.PHONY: test bench-smoke + +test: + python3 -m pytest tests/ -v + +bench-smoke: + cd ../../src && $(MAKE) build + python3 -m pytest tests/test_bench_smoke.py -v -s diff --git a/contrib/network-profiler/network_profiler/bench.py b/contrib/network-profiler/network_profiler/bench.py index d19e561..ae1a5ed 100644 --- a/contrib/network-profiler/network_profiler/bench.py +++ b/contrib/network-profiler/network_profiler/bench.py @@ -97,7 +97,7 @@ def phase_start( cfg_path = f"{d}/cfg.yaml" log_path = f"{d}/log" cmd = ( - f"nohup otela start --config {cfg_path} " + f"nohup otela start --config {cfg_path} --config-dir {d} " f">>{log_path} 2>&1 &" ) result = runner.run(m, cmd, timeout=10) diff --git a/contrib/network-profiler/network_profiler/bench_config.py b/contrib/network-profiler/network_profiler/bench_config.py index 494cbbe..33448be 100644 --- a/contrib/network-profiler/network_profiler/bench_config.py +++ b/contrib/network-profiler/network_profiler/bench_config.py @@ -14,6 +14,10 @@ def build_multiaddr(machine: Machine, libp2p_port: int, peer_id: str) -> str: return f"/dns4/{machine.address}/tcp/{libp2p_port}/p2p/{peer_id}" +def _peer_libp2p_port(m: Machine, default: int) -> int: + return m.libp2p_port or default + + def build_host_config( self_machine: Machine, all_machines: list[Machine], @@ -22,15 +26,17 @@ def build_host_config( http_port: int, libp2p_port: int, ) -> dict[str, Any]: + http = self_machine.http_port or http_port + tcp = self_machine.libp2p_port or libp2p_port bootstrap = [ - build_multiaddr(m, libp2p_port, peer_ids[m.name]) + build_multiaddr(m, _peer_libp2p_port(m, libp2p_port), peer_ids[m.name]) for m in all_machines if m.name != self_machine.name ] return { - "port": str(http_port), - "tcpport": str(libp2p_port), - "udpport": str(libp2p_port + 1), + "port": str(http), + "tcpport": str(tcp), + "udpport": str(tcp + 1), "cleanslate": True, "bootstrap": {"static": bootstrap}, "security": {"require_signed_binary": False}, diff --git a/contrib/network-profiler/network_profiler/model.py b/contrib/network-profiler/network_profiler/model.py index 69a4202..3113d26 100644 --- a/contrib/network-profiler/network_profiler/model.py +++ b/contrib/network-profiler/network_profiler/model.py @@ -11,6 +11,8 @@ class Machine: name: str address: str rcc_host: str + http_port: int | None = None + libp2p_port: int | None = None @dataclass(frozen=True) @@ -32,6 +34,8 @@ def load_config(path: Path) -> ProfilerConfig: name=str(item["name"]), address=str(item.get("address", item["name"])), rcc_host=str(item.get("rcc_host", item["name"])), + http_port=item.get("http_port"), + libp2p_port=item.get("libp2p_port"), ) for item in raw["machines"] ] diff --git a/contrib/network-profiler/tests/test_bench_smoke.py b/contrib/network-profiler/tests/test_bench_smoke.py new file mode 100644 index 0000000..57685fc --- /dev/null +++ b/contrib/network-profiler/tests/test_bench_smoke.py @@ -0,0 +1,59 @@ +import json +import os +import subprocess +import sys +from pathlib import Path + +import pytest + + +REPO_ROOT = Path(__file__).resolve().parents[3] +ENTRY = REPO_ROOT / "src" / "build" / "entry" + + +@pytest.mark.skipif(not ENTRY.exists(), reason="src/build/entry not built") +def test_local_two_node_bench(tmp_path): + # The bench invokes `otela ...` over `bash -c`. The repo binary is + # `src/build/entry`; expose it as `otela` via a bin/ dir we prepend + # to PATH and pass through to bash explicitly. + bin_dir = tmp_path / "bin" + bin_dir.mkdir() + (bin_dir / "otela").symlink_to(ENTRY) + + bash_path = f"PATH={bin_dir}:{os.environ.get('PATH', '')}; {{command}}" + + machines_json = tmp_path / "machines.json" + machines_json.write_text(json.dumps({ + "remote_command": ["bash", "-c", bash_path], + "machines": [ + {"name": "n1", "address": "127.0.0.1", "rcc_host": "n1", "http_port": 29090, "libp2p_port": 29091}, + {"name": "n2", "address": "127.0.0.1", "rcc_host": "n2", "http_port": 29100, "libp2p_port": 29101}, + ], + })) + + env = os.environ.copy() + env["PATH"] = f"{bin_dir}:{env['PATH']}" + output = tmp_path / "out" + + proc = subprocess.run( + [ + sys.executable, "-m", "network_profiler", "bench", + "--config", str(machines_json), + "--run-id", "smoke", + "--output", str(output), + "--latency-count", "3", + "--throughput-count", "1", + "--throughput-bytes", "65536", + ], + cwd=REPO_ROOT / "contrib" / "network-profiler", + env=env, + capture_output=True, text=True, timeout=300, + ) + assert proc.returncode == 0, f"bench failed: {proc.stdout}\n{proc.stderr}" + measurements = (output / "measurements.jsonl").read_text().splitlines() + assert len(measurements) == 6 # 2 ordered pairs x 3 kinds + records = [json.loads(l) for l in measurements] + assert all(r["ok"] for r in records), \ + "\n".join(f"{r['source']}->{r['target']} {r['kind']}: {r.get('error')}" for r in records if not r["ok"]) + summary = json.loads((output / "run.json").read_text()) + assert summary["totals"]["ok"] == 6 From 45d374d77b8f6bf376c8cdee20dfb0fdeea45cd8 Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sun, 3 May 2026 18:35:10 +0200 Subject: [PATCH 22/23] update net-profiler --- .gitignore | 1 + contrib/network-profiler/README.md | 7 +- .../network_profiler/bench.py | 4 + .../network_profiler/bench_config.py | 5 + .../network-profiler/network_profiler/cli.py | 3 + .../network_profiler/model.py | 2 + contrib/network-profiler/uv.lock | 69 +++++ deploy/tds/opentela.yaml | 2 +- docs/content/docs/advanced/meta.json | 1 + .../docs/advanced/network-profiling.mdx | 242 ++++++++++++++++++ docs/content/docs/advanced/security.mdx | 2 +- meta/build_core_docker.sh | 29 ++- src/internal/protocol/host.go | 30 ++- src/internal/server/libp2p_http_transport.go | 85 ++++++ src/internal/server/probe_handler.go | 38 ++- src/internal/server/probe_handler_test.go | 41 +++ src/internal/server/proxy_handler.go | 3 +- src/internal/server/server.go | 3 +- 18 files changed, 547 insertions(+), 20 deletions(-) create mode 100644 contrib/network-profiler/uv.lock create mode 100644 docs/content/docs/advanced/network-profiling.mdx create mode 100644 src/internal/server/libp2p_http_transport.go diff --git a/.gitignore b/.gitignore index c9b5743..55fdcbf 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ website/.source/ .omx/ .local .pista +.claude/ diff --git a/contrib/network-profiler/README.md b/contrib/network-profiler/README.md index 71d15ef..763ef8c 100644 --- a/contrib/network-profiler/README.md +++ b/contrib/network-profiler/README.md @@ -3,9 +3,7 @@ Pairwise network profiler for machines managed through [`ResearchComputer/remote-cluster-controller`](https://github.com/ResearchComputer/remote-cluster-controller). -It runs commands on every source machine, targets every other machine, records -latency with `ping`, optionally records bandwidth with `iperf3`, and renders an -HTML heatmap. +It runs commands on every source machine, targets every other machine, records latency with `ping`, optionally records bandwidth with `iperf3`, and renders an HTML heatmap. ## Configure machines @@ -71,5 +69,4 @@ Each remote machine needs: - network paths that allow source machines to reach target `address` values - TCP access to `iperf_port` between remote machines when collecting bandwidth -The JSONL output preserves every command, success flag, parsed metrics, and -failure text so failed links can be inspected without rerunning the whole sweep. +The JSONL output preserves every command, success flag, parsed metrics, and failure text so failed links can be inspected without rerunning the whole sweep. \ No newline at end of file diff --git a/contrib/network-profiler/network_profiler/bench.py b/contrib/network-profiler/network_profiler/bench.py index ae1a5ed..ec6686a 100644 --- a/contrib/network-profiler/network_profiler/bench.py +++ b/contrib/network-profiler/network_profiler/bench.py @@ -57,6 +57,7 @@ def phase_configure_and_push( run_id: str, http_port: int, libp2p_port: int, + extra_bootstraps: list[str] | None = None, ) -> dict[str, str]: """Render per-host cfg.yaml and push via stdin-piped base64.""" out: dict[str, str] = {} @@ -70,6 +71,7 @@ def phase_configure_and_push( run_id=run_id, http_port=http_port, libp2p_port=libp2p_port, + extra_bootstraps=extra_bootstraps, ) yaml_bytes = yaml.safe_dump(cfg, sort_keys=True).encode("utf-8") b64 = base64.b64encode(yaml_bytes) @@ -275,6 +277,7 @@ def run_bench( throughput_count: int = 3, throughput_bytes: int = 10 * 1024 * 1024, keep: bool = False, + extra_bootstraps: list[str] | None = None, ) -> int: output_dir = Path(output_dir) output_dir.mkdir(parents=True, exist_ok=True) @@ -319,6 +322,7 @@ def on_sigint(signum, frame): phase_configure_and_push( runner, machines, peer_ids, run_id, http_port=http_port, libp2p_port=libp2p_port, + extra_bootstraps=extra_bootstraps, ) phase_timings["configure_s"] = round(time.monotonic() - t0, 2) diff --git a/contrib/network-profiler/network_profiler/bench_config.py b/contrib/network-profiler/network_profiler/bench_config.py index 33448be..d8fb7ed 100644 --- a/contrib/network-profiler/network_profiler/bench_config.py +++ b/contrib/network-profiler/network_profiler/bench_config.py @@ -25,6 +25,7 @@ def build_host_config( run_id: str, http_port: int, libp2p_port: int, + extra_bootstraps: list[str] | None = None, ) -> dict[str, Any]: http = self_machine.http_port or http_port tcp = self_machine.libp2p_port or libp2p_port @@ -33,6 +34,10 @@ def build_host_config( for m in all_machines if m.name != self_machine.name ] + if extra_bootstraps: + bootstrap.extend(extra_bootstraps) + if self_machine.bootstrap_extra: + bootstrap.extend(self_machine.bootstrap_extra) return { "port": str(http), "tcpport": str(tcp), diff --git a/contrib/network-profiler/network_profiler/cli.py b/contrib/network-profiler/network_profiler/cli.py index 908b2ee..ed41c4b 100644 --- a/contrib/network-profiler/network_profiler/cli.py +++ b/contrib/network-profiler/network_profiler/cli.py @@ -40,6 +40,8 @@ def build_parser() -> argparse.ArgumentParser: bench.add_argument("--throughput-count", type=int, default=3) bench.add_argument("--throughput-bytes", type=int, default=10 * 1024 * 1024) bench.add_argument("--keep", action="store_true") + bench.add_argument("--bootstrap", action="append", default=[], + help="Extra libp2p bootstrap multiaddr (repeatable). Use this to point bench nodes at a public rendezvous when direct peer-to-peer dials are blocked by firewalls.") return parser @@ -92,5 +94,6 @@ def main(argv: list[str] | None = None) -> int: throughput_count=args.throughput_count, throughput_bytes=args.throughput_bytes, keep=args.keep, + extra_bootstraps=args.bootstrap or None, ) raise AssertionError(args.command) diff --git a/contrib/network-profiler/network_profiler/model.py b/contrib/network-profiler/network_profiler/model.py index 3113d26..835f1b3 100644 --- a/contrib/network-profiler/network_profiler/model.py +++ b/contrib/network-profiler/network_profiler/model.py @@ -13,6 +13,7 @@ class Machine: rcc_host: str http_port: int | None = None libp2p_port: int | None = None + bootstrap_extra: tuple[str, ...] = () @dataclass(frozen=True) @@ -36,6 +37,7 @@ def load_config(path: Path) -> ProfilerConfig: rcc_host=str(item.get("rcc_host", item["name"])), http_port=item.get("http_port"), libp2p_port=item.get("libp2p_port"), + bootstrap_extra=tuple(item.get("bootstrap_extra", [])), ) for item in raw["machines"] ] diff --git a/contrib/network-profiler/uv.lock b/contrib/network-profiler/uv.lock new file mode 100644 index 0000000..f43deaf --- /dev/null +++ b/contrib/network-profiler/uv.lock @@ -0,0 +1,69 @@ +version = 1 +revision = 3 +requires-python = ">=3.11" + +[[package]] +name = "network-profiler" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "pyyaml" }, +] + +[package.metadata] +requires-dist = [{ name = "pyyaml", specifier = ">=6.0" }] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" }, + { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" }, + { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" }, + { url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114, upload-time = "2025-09-25T21:32:03.376Z" }, + { url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638, upload-time = "2025-09-25T21:32:04.553Z" }, + { url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463, upload-time = "2025-09-25T21:32:06.152Z" }, + { url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986, upload-time = "2025-09-25T21:32:07.367Z" }, + { url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", size = 142543, upload-time = "2025-09-25T21:32:08.95Z" }, + { url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z" }, + { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, + { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, + { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, + { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, + { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, + { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, + { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] diff --git a/deploy/tds/opentela.yaml b/deploy/tds/opentela.yaml index c3270df..164098a 100644 --- a/deploy/tds/opentela.yaml +++ b/deploy/tds/opentela.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: opentela-relay - image: ghcr.io/xiaozheyao/opentela:latest + image: ghcr.io/xiaozheyao/opentela:amd64-latest imagePullPolicy: Always args: - start diff --git a/docs/content/docs/advanced/meta.json b/docs/content/docs/advanced/meta.json index 0e72d85..06b1e2e 100644 --- a/docs/content/docs/advanced/meta.json +++ b/docs/content/docs/advanced/meta.json @@ -5,6 +5,7 @@ "crdt-tombstones", "crdt-internals", "benchmark", + "network-profiling", "performance-optimization" ] } diff --git a/docs/content/docs/advanced/network-profiling.mdx b/docs/content/docs/advanced/network-profiling.mdx new file mode 100644 index 0000000..cce3144 --- /dev/null +++ b/docs/content/docs/advanced/network-profiling.mdx @@ -0,0 +1,242 @@ +--- +title: Network Profiling +description: Measure pairwise latency and throughput between OpenTela nodes — both raw IP baselines and libp2p-level numbers — using the `contrib/network-profiler` toolkit. +--- + +OpenTela ships a profiling toolkit at [`contrib/network-profiler/`](https://github.com/ResearchComputer/OpenTela/tree/main/contrib/network-profiler) that produces two complementary views of the network between any set of machines you can SSH into: + +- A **raw-IP baseline** using `ping` and `iperf3` (`net-profiler collect`). Tells you what the underlying network is capable of, ignoring OpenTela's own overhead. +- An **OpenTela-native** measurement using libp2p ping and HTTP-over-libp2p (`net-profiler bench`). Tells you what production traffic actually experiences — including TLS, multiplexing, and relay-circuit hops. + +Both flavors dispatch over [`remote-cluster-controller` (rcc)](https://pypi.org/project/remote-cluster-controller/) and produce JSONL output. The bench flavor brings up an isolated four-port mesh on the target hosts, runs every (source, destination, kind) tuple through three probe kinds, and tears the mesh down at the end. + +## Why two flavors? + +Raw `ping` between HPC login nodes will tell you "the network can do 0.3 ms" — but production OpenTela traffic rides libp2p HTTP through Noise/TLS encryption, stream multiplexing, and (often) a relay-v2 circuit because direct dial is blocked. The two latencies can differ by an order of magnitude. Run `net-profiler collect` to characterise the underlying link; run `net-profiler bench` to characterise the path your users actually traverse. + +A bench run that succeeds at `libp2p_ping` but fails at HTTP-over-libp2p is itself a diagnostic — it usually means the bootstrap/relay isn't issuing v2 reservations to your workers. + +## One-time setup + +You will need: + +- Python 3.11+ on your local machine. +- An [`rcc`](https://pypi.org/project/remote-cluster-controller/) install: `uv tool install remote-cluster-controller` (or `pipx install remote-cluster-controller`). The CLI is named `rcc`. +- Per-host SSH access. The bench dispatches every command through rcc → SSH, so passwordless SSH (with the host key already accepted) is required for every machine. +- The `otela` binary on each remote machine. The bench expects to find it on `PATH` when commands run there. + +### rcc profiles + +In a working directory of your choice, scaffold the rcc config and add one profile per machine: + +```bash +mkdir bench-workdir && cd bench-workdir +rcc init +``` + +Edit `.rcc/config.toml` to look like: + +```toml +default = "clariden" + +[profiles.clariden] +host = "clariden" +remote_dir = "/tmp" + +[profiles.bristen] +host = "bristen" +remote_dir = "/tmp" + +[profiles.euler] +host = "euler" +remote_dir = "/tmp" +``` + +`host` is whatever your `~/.ssh/config` recognises (or `user@host.example.com`). `remote_dir` is just the working directory rcc `cd`'s into before running each command — `/tmp` is fine. + +### Deploying `otela` to each host + +`otela` needs to be on `PATH` whenever the bench runs a command on a remote host. The simplest way is to drop the binary in a known location and inject it via the `remote_command` template in `machines.json`. Build the release binaries: + +```bash +cd src && make build-release +# produces build/release/otela-amd64 and build/release/otela-arm64 +``` + +Push the right architecture to each host: + +```bash +ssh clariden "mkdir -p ~/otela-bench-bin/aarch64 ~/otela-bench-bin/x86_64" +scp src/build/release/otela-arm64 clariden:otela-bench-bin/aarch64/otela +scp src/build/release/otela-amd64 clariden:otela-bench-bin/x86_64/otela +ssh clariden "chmod +x ~/otela-bench-bin/aarch64/otela ~/otela-bench-bin/x86_64/otela" +``` + +If two hosts share a network filesystem (CSCS clariden + bristen, for example), one push covers both — the architecture-specific subdirectory keeps them from clobbering each other. + +### `machines.json` + +This is the inventory the profiler reads. A minimal example: + +```json +{ + "remote_command": [ + "rcc", "run", "--profile", "{host}", "--", + "bash", "-lc", + "export PATH=$HOME/otela-bench-bin/$(uname -m):$PATH; {command}" + ], + "machines": [ + { + "name": "clariden", + "address": "clariden.cscs.ch", + "rcc_host": "clariden" + }, + { + "name": "euler", + "address": "euler.ethz.ch", + "rcc_host": "euler" + } + ] +} +``` + +Fields: + +- `remote_command` — argv template the profiler uses to run each remote command. The PATH-injecting form above lets the bench find the right `otela` binary on each host without modifying user shells. `{host}`, `{name}`, `{address}`, and `{command}` are substituted per call. +- `machines[].name` — label used in output records. +- `machines[].address` — the address other peers should use to dial this machine (the bootstrap multiaddr). For HPC login nodes this is usually the public FQDN; for cluster compute nodes it depends on your network topology. +- `machines[].rcc_host` — the rcc profile name (matches `[profiles.]` in `.rcc/config.toml`). + +Optional fields: + +- `http_port` / `libp2p_port` (per machine) — override the bench's default ports (`19090` HTTP, `19091` libp2p). Useful when running multiple bench nodes on one host. +- `bootstrap_extra` (per machine, list of multiaddrs) — extra libp2p bootstrap addresses for this specific host. Use when one cluster's outbound rules let it reach a different rendezvous than another. + +## Raw-IP baseline: `net-profiler collect` + +For each ordered pair, runs `ping` from source to target's address. With `--iperf` it also runs `iperf3` on the target and a client on the source. + +```bash +cd bench-workdir +python3 -m network_profiler collect \ + --config machines.json \ + --output results/baseline.jsonl +``` + +Add `--iperf` to also measure bandwidth. `iperf3` must be installed on every host; on most HPC clusters it isn't on the login node — load it with `module load iperf` (Euler) or run on a compute node. + +Output is JSONL, one record per probe. Render a heatmap from the latency results: + +```bash +python3 -m network_profiler heatmap \ + --input results/baseline.jsonl \ + --output results/ping.html +``` + +## OpenTela-native: `net-profiler bench` + +The bench owns the full lifecycle: it brings up an isolated four-port mesh on each host, runs every (source, destination) pair through three probe kinds, and tears the mesh down. Each run uses a unique config dir at `/tmp/otela-bench--/` so it never collides with persistent OpenTela state. + +```bash +cd bench-workdir +python3 -m network_profiler bench \ + --config machines.json \ + --bootstrap /ip4//tcp/43905/p2p/ \ + --latency-count 20 \ + --throughput-count 3 \ + --throughput-bytes 10485760 \ + --output results/bench +``` + +Flags: + +| Flag | Default | Purpose | +|---|---|---| +| `--config` | (required) | `machines.json` path. | +| `--output` | `results//` | Output directory. | +| `--run-id` | timestamp + random | Stable identifier; appears in every record and in the bench dir name. | +| `--latency-count` | `20` | Samples per `latency` and `libp2p_ping` probe. | +| `--throughput-count` | `3` | Iterations per `throughput` probe. | +| `--throughput-bytes` | `10485760` (10 MiB) | Bytes per throughput iteration. | +| `--http-port` | `19090` | Bench HTTP port (overridable per machine). | +| `--libp2p-port` | `19091` | Bench libp2p port (overridable per machine). | +| `--bootstrap` | (none) | Extra libp2p bootstrap multiaddr. Repeat for multiple. | +| `--keep` | off | Skip teardown — leave processes and `/tmp/otela-bench-*` dirs in place for post-mortem. | + +### What gets measured + +Three probe kinds, all between the same peer pairs in the same run: + +- **`libp2p_ping`** — raw `/ipfs/ping/1.0.0` round-trip. Tiny payload, shortest-lived stream. Most likely to succeed under restrictive networks because the libp2p relay can carry small ping packets even when full bidirectional streams are blocked. +- **`latency`** — HTTP-over-libp2p `GET /v1/health` round-trip via the same `gostream`-based transport as production traffic. +- **`throughput`** — HTTP-over-libp2p `GET /v1/probe/echo?bytes=N`. Measures bandwidth-weighted Mbps over `count × bytes` total transfer. + +### Phases of a run + +The orchestrator runs eight phases in sequence: + +1. **init** — `otela init --config-dir /tmp/otela-bench--/` per host (generates the libp2p key). +2. **discover** — `otela peer-id --config-dir ` per host. Stores `host → PeerID`. +3. **configure** — locally render per-host `cfg.yaml` with bench ports, every other host as a bootstrap peer, and any `--bootstrap` / per-machine `bootstrap_extra` entries appended. +4. **push** — base64-pipe the cfg.yaml to each host via stdin. +5. **start** — launch `otela start --config-dir ` in the background, poll `GET /v1/health` until 200 (or 30 s timeout per host). +6. **converge** — poll `GET /v1/dnt/table` until each host sees every other expected PeerID, or 60 s timeout. +7. **sweep** — for each `(src, dst, kind)`, run `otela probe --target --kind ` via rcc on the source. +8. **teardown** — `pkill -f` matched on the unique cfg path, then `rm -rf` the bench dir. + +`SIGINT` during any phase runs teardown before exiting, so a Ctrl-C never leaves dangling otela processes. + +### Output + +Two files per run, under `/`: + +`measurements.jsonl` — one record per `(src, dst, kind)`: + +```json +{ + "run_id": "real-20260503T113742", + "kind": "latency", + "source": "euler", + "target": "sgs-amd-01", + "source_peer_id": "QmVpKnDX...", + "target_peer_id": "QmZiuqrG...", + "ok": true, + "metrics": { + "min_ms": 2.62, "avg_ms": 2.89, "p50_ms": 2.85, "p95_ms": 4.13, "max_ms": 4.42, + "samples_ns": [2620000, 2745000, ...], + "failed_samples": 0 + } +} +``` + +For `throughput`, `metrics` instead carries `bytes_received`, `elapsed_ns`, `mbps`, and a per-iteration `iterations` array. + +`run.json` — top-level summary with phase timings, per-host convergence outcome, and total ok/failed counts. Useful for post-mortem ("why did this run take 22 minutes?"). + +## Interpreting results + +A few patterns to watch for: + +- **`libp2p_ping` succeeds, HTTP-over-libp2p fails** — relay v2 reservation issue. The relay node passes ping packets but isn't granting your workers the reservations needed for full bidirectional streams. Failed records will show `failed to dial: ... all dials failed * [/ip4/.../tcp/19091] dial backoff`. +- **Convergence times out for some hosts** — those nodes' outbound firewalls let through fewer DHT discovery exchanges than others. They can still ping the peers they did learn about; they just don't see the full mesh in their `dnt/table` within 60 s. Try a closer-by bootstrap (`bootstrap_extra` per machine). +- **Significant gap between `libp2p_ping` and `latency`** — the difference quantifies HTTP-over-libp2p overhead vs. raw libp2p streams (TLS, multiplexing). Useful when tuning client request sizes. +- **`failed_samples` non-zero on `libp2p_ping`** — a peer that's intermittently reachable. Look at `samples_ns` for the surviving samples. + +## Cross-cluster considerations + +For HPC login nodes (Euler, CSCS clusters) the bench will form a mesh **only if** outbound TCP from each host can reach the bootstrap. Don't expect direct peer-to-peer dial to work between login nodes — institutional firewalls almost always block user-port inbound. Use a publicly reachable bootstrap (e.g. one of OpenTela's relay nodes) and accept that HTTP-over-libp2p probes may fail until v2 relay reservations land. + +For real cross-cluster benchmarking, run the worker side on a SLURM-allocated compute node with port-forwarding rules, not on the login node. + +## Troubleshooting + +- **`error: no .rcc/ found`** — you need to run from the directory containing `.rcc/config.toml`. The profiler hands every command to `rcc`, which searches cwd. +- **`bash: .../otela: cannot execute binary file: Exec format error`** — wrong-architecture binary on the host. Use the `$(uname -m)` PATH-injection trick from the example `remote_command`. +- **`error: dest open ".../otela": Failure` when re-pushing** — a previous bench's `otela` is still running and holding the binary text-busy. `ssh "pkill -9 -f otela.*config-dir.*otela-bench"` and re-push. +- **Convergence completes but every probe fails with `dial backoff`** — peers can see each other in the DHT but can't dial each other directly. Add a relay node accessible from each peer via `--bootstrap`. + +## Related code + +- [`contrib/network-profiler/`](https://github.com/ResearchComputer/OpenTela/tree/main/contrib/network-profiler) — Python orchestrator. +- `src/internal/server/probe_handler.go` — the `/v1/probe/echo` and `/v1/probe/run` endpoints, plus the libp2p ping wrapper. +- `src/entry/cmd/probe.go`, `src/entry/cmd/peerid.go` — the `otela probe` and `otela peer-id` CLI commands the bench dispatches. \ No newline at end of file diff --git a/docs/content/docs/advanced/security.mdx b/docs/content/docs/advanced/security.mdx index 5689ca4..1a1d7c5 100644 --- a/docs/content/docs/advanced/security.mdx +++ b/docs/content/docs/advanced/security.mdx @@ -15,7 +15,7 @@ OpenTela is a decentralized network where untrusted operators can run nodes. The 3. **Abuse prevention** — How do we limit request floods and resource exhaustion? 4. **Transport confidentiality** — Is traffic between nodes encrypted? -Each layer is independently configurable and backward-compatible with older nodes that pre-date these features. +Each layer is independently configurable. --- diff --git a/meta/build_core_docker.sh b/meta/build_core_docker.sh index 7af5c5d..1acd530 100644 --- a/meta/build_core_docker.sh +++ b/meta/build_core_docker.sh @@ -1,4 +1,5 @@ #!/bin/bash +set -euo pipefail # Default to latest if no version is specified VERSION=${1:-latest} @@ -13,5 +14,29 @@ case $VERSION in ;; esac -# Build and push with the specified version -docker build -f meta/Dockerfile.amd64 -t ghcr.io/researchcomputer/ocf:amd64-$VERSION . && docker push ghcr.io/researchcomputer/ocf:amd64-$VERSION \ No newline at end of file +if [ -z "${BUILD_SIGN_KEY:-}" ]; then + echo "Error: BUILD_SIGN_KEY is not set. Generate one with:" + echo " cd src && go run ./internal/attestation/cmd/buildsign keygen" + exit 1 +fi + +# Build args mirror src/Makefile so the in-container signature matches +# what peers will compute from (version, commit) on the wire. +BUILD_VERSION=$(git describe --tags --exact-match 2>/dev/null || git symbolic-ref -q --short HEAD) +COMMIT_HASH=$(git rev-parse --short HEAD) +BUILD_DATE=$(date "+%FT%T%z") + +IMAGE=ghcr.io/xiaozheyao/opentela:amd64-$VERSION + +# Pass the signing key as a docker secret (not a build-arg) so it is +# never embedded in any image layer or build history. +DOCKER_BUILDKIT=1 docker build \ + -f meta/Dockerfile.amd64 \ + --secret id=build_sign_key,env=BUILD_SIGN_KEY \ + --build-arg VERSION="$BUILD_VERSION" \ + --build-arg COMMIT_HASH="$COMMIT_HASH" \ + --build-arg BUILD_DATE="$BUILD_DATE" \ + -t "$IMAGE" \ + . + +docker push "$IMAGE" \ No newline at end of file diff --git a/src/internal/protocol/host.go b/src/internal/protocol/host.go index bc46cf9..be600ce 100644 --- a/src/internal/protocol/host.go +++ b/src/internal/protocol/host.go @@ -23,7 +23,9 @@ import ( dht "github.com/libp2p/go-libp2p-kad-dht" dualdht "github.com/libp2p/go-libp2p-kad-dht/dual" record "github.com/libp2p/go-libp2p-record" + "github.com/libp2p/go-libp2p/p2p/host/autorelay" relayClient "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/client" + relayv2 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay" "github.com/libp2p/go-libp2p/p2p/protocol/ping" "github.com/libp2p/go-libp2p/core/crypto" @@ -155,7 +157,13 @@ func newHost(ctx context.Context, seed int64, ds datastore.Batching) (host.Host, libp2p.EnableRelay(), libp2p.EnableHolePunching(), libp2p.EnableAutoNATv2(), - libp2p.EnableRelayService(), + // Relay-as-server: lift the libp2p defaults (128 KB / 2 min per circuit, + // 128 reservations, 16 circuits/peer) so HTTP-over-circuit traffic is + // not reset on the first echo response or 20-sample latency probe. + libp2p.EnableRelayService( + relayv2.WithResources(relayServiceResources()), + relayv2.WithInfiniteLimits(), + ), libp2p.Routing(func(h host.Host) (routing.PeerRouting, error) { ddht, err = newDHT(ctx, h, ds) return ddht, err @@ -191,6 +199,12 @@ func newHost(ctx context.Context, seed int64, ds datastore.Batching) (host.Host, // AutoRelay discovers relay servers from connected peers and // maintains active reservations so other nodes can reach us // via /p2p//p2p-circuit/p2p/. + // + // Defaults reserve on only 2 relays (desiredRelays=2). With several + // bootstrap relays available, two workers may pick disjoint subsets, + // so neither can dial the other through circuit. Reserve on every + // candidate the peer source returns so the reservation set across + // workers is identical (full-mesh coverage of advertised circuits). opts = append(opts, libp2p.EnableAutoRelayWithPeerSource( func(ctx context.Context, numPeers int) <-chan peer.AddrInfo { ch := make(chan peer.AddrInfo, numPeers) @@ -210,6 +224,11 @@ func newHost(ctx context.Context, seed int64, ds datastore.Batching) (host.Host, }() return ch }, + autorelay.WithNumRelays(16), + autorelay.WithMaxCandidates(32), + autorelay.WithMinCandidates(1), + autorelay.WithBootDelay(5*time.Second), + autorelay.WithMinInterval(5*time.Second), )) } @@ -478,6 +497,15 @@ func isTransientNetworkError(err error) bool { return false } +func relayServiceResources() relayv2.Resources { + r := relayv2.DefaultResources() + r.MaxReservations = 512 + r.MaxCircuits = 128 + r.MaxReservationsPerIP = 64 + r.MaxReservationsPerASN = 256 + return r +} + func newResourceManager() network.ResourceManager { limiter := rcmgr.NewFixedLimiter(rcmgr.DefaultLimits.AutoScale()) rm, err := rcmgr.NewResourceManager(limiter) diff --git a/src/internal/server/libp2p_http_transport.go b/src/internal/server/libp2p_http_transport.go new file mode 100644 index 0000000..629612a --- /dev/null +++ b/src/internal/server/libp2p_http_transport.go @@ -0,0 +1,85 @@ +package server + +import ( + "context" + "fmt" + "net" + "net/http" + "net/url" + "time" + + "github.com/libp2p/go-libp2p/core/host" + "github.com/libp2p/go-libp2p/core/network" + libp2ppeer "github.com/libp2p/go-libp2p/core/peer" + + gostream "github.com/libp2p/go-libp2p-gostream" + p2phttp "github.com/libp2p/go-libp2p-http" +) + +// libp2pHTTPRoundTripper turns "libp2p:///path" requests into +// HTTP/1.1 requests over a libp2p stream, with stdlib keep-alive pooling. +// +// The third-party github.com/libp2p/go-libp2p-http opens a fresh stream +// per request and closes it on response-body Close, which over a relay +// circuit means a new circuit handshake every probe sample. This wrapper +// uses the same gostream + /libp2p-http protocol but threads it through +// stdlib *http.Transport so HTTP keep-alive can pin one stream per peer +// across requests. +// +// The URL scheme is rewritten libp2p:// -> http:// before delegating; +// stdlib http.Transport rejects unknown schemes. +type libp2pHTTPRoundTripper struct { + inner *http.Transport +} + +func newLibp2pHTTPRoundTripper(h host.Host) *libp2pHTTPRoundTripper { + rt := &libp2pHTTPRoundTripper{} + rt.inner = &http.Transport{ + DialContext: func(ctx context.Context, _ string, addr string) (net.Conn, error) { + hostPart, _, err := net.SplitHostPort(addr) + if err != nil { + hostPart = addr + } + pid, err := libp2ppeer.Decode(hostPart) + if err != nil { + return nil, fmt.Errorf("libp2pHTTP: invalid peer id %q: %w", hostPart, err) + } + // Permit opening a stream over a relay-circuit (Limited) connection. + // libp2p's NewStream refuses Limited conns by default and tries to + // upgrade to direct, which on cross-cluster peers blocks until the + // caller's context expires (manifests as plain "context deadline + // exceeded" with no dial-failure prefix). The ping protocol opts in + // the same way at p2p/protocol/ping/ping.go:117. + dialCtx := network.WithAllowLimitedConn(ctx, "libp2p-http") + return gostream.Dial(dialCtx, h, pid, p2phttp.DefaultP2PProtocol) + }, + DisableKeepAlives: false, + MaxIdleConns: 256, + MaxIdleConnsPerHost: 4, + IdleConnTimeout: 90 * time.Second, + ResponseHeaderTimeout: 10 * time.Minute, + } + return rt +} + +// RoundTrip implements http.RoundTripper. +func (rt *libp2pHTTPRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + if req.URL == nil || req.URL.Scheme != "libp2p" { + return nil, fmt.Errorf("libp2pHTTP: expected libp2p:// URL, got %v", req.URL) + } + cloned := req.Clone(req.Context()) + cloned.URL = &url.URL{ + Scheme: "http", + Host: req.URL.Host, + Path: req.URL.Path, + RawQuery: req.URL.RawQuery, + Fragment: req.URL.Fragment, + } + cloned.Host = req.URL.Host + return rt.inner.RoundTrip(cloned) +} + +// CloseIdleConnections forwards to the inner transport. +func (rt *libp2pHTTPRoundTripper) CloseIdleConnections() { + rt.inner.CloseIdleConnections() +} diff --git a/src/internal/server/probe_handler.go b/src/internal/server/probe_handler.go index ba55f3b..a8310fb 100644 --- a/src/internal/server/probe_handler.go +++ b/src/internal/server/probe_handler.go @@ -263,25 +263,51 @@ func runLibp2pPing(ctx context.Context, pid libp2ppeer.ID, count int) (bool, map return false, nil, "libp2p host not initialized" } resCh := ping.Ping(ctx, h, pid) + samples, failed, lastErr := processPingResults(ctx, resCh, count) + if len(samples) == 0 { + return false, map[string]any{"failed_samples": failed}, "no successful pings: " + lastErr + } + return true, summariseDurations(samples, failed), "" +} + +// processPingResults reads up to count results from a ping result channel. +// Returns the valid samples (in ns), failure count, and last error message. +// +// Treats `Error == nil && RTT == 0` as a failure: libp2p's ping service +// produces such results when the dial layer can't establish a stream +// (the channel still emits, but the ping never round-tripped). Without this +// guard, unreachable peers register as 9 fake-zero-RTT successes plus 1 +// real failure, producing nonsense aggregates. +func processPingResults(ctx context.Context, resCh <-chan ping.Result, count int) ([]int64, int, string) { samples := make([]int64, 0, count) var failed int var lastErr string for i := 0; i < count; i++ { select { case <-ctx.Done(): - return len(samples) > 0, summariseDurations(samples, failed), ctx.Err().Error() - case res := <-resCh: + if lastErr == "" { + lastErr = ctx.Err().Error() + } + return samples, failed, lastErr + case res, ok := <-resCh: + if !ok { + return samples, failed, lastErr + } if res.Error != nil { failed++ lastErr = res.Error.Error() continue } + if res.RTT == 0 { + failed++ + if lastErr == "" { + lastErr = "ping returned RTT=0 with no error (peer not reachable)" + } + continue + } samples = append(samples, res.RTT.Nanoseconds()) } } - if len(samples) == 0 { - return false, map[string]any{"failed_samples": failed}, "no successful pings: " + lastErr - } - return true, summariseDurations(samples, failed), "" + return samples, failed, lastErr } diff --git a/src/internal/server/probe_handler_test.go b/src/internal/server/probe_handler_test.go index 9b9a421..a1b29f1 100644 --- a/src/internal/server/probe_handler_test.go +++ b/src/internal/server/probe_handler_test.go @@ -2,14 +2,18 @@ package server import ( "bytes" + "context" "encoding/json" + "errors" "io" "net/http" "net/http/httptest" "strconv" "testing" + "time" "github.com/gin-gonic/gin" + "github.com/libp2p/go-libp2p/p2p/protocol/ping" "github.com/stretchr/testify/assert" ) @@ -146,3 +150,40 @@ func TestRunThroughput_AggregateIsBandwidthWeighted(t *testing.T) { // Sanity check the test arithmetic itself. assert.InDelta(t, 14.545, expected, 0.01) } + +func TestProcessPingResults_RejectsZeroRTTAndCountsErrors(t *testing.T) { + // libp2p's ping service emits Result{Error:nil, RTT:0} when the dial + // layer can't establish a stream. Without rejection, unreachable peers + // would register as fake-zero-RTT successes. + ch := make(chan ping.Result, 5) + ch <- ping.Result{RTT: 5 * time.Millisecond} // valid + ch <- ping.Result{RTT: 0} // zero-RTT bug + ch <- ping.Result{Error: errors.New("dial fail")} // explicit error + ch <- ping.Result{RTT: 6 * time.Millisecond} // valid + ch <- ping.Result{RTT: 0} // zero-RTT bug + close(ch) + + samples, failed, lastErr := processPingResults(context.Background(), ch, 5) + assert.Equal(t, []int64{int64(5 * time.Millisecond), int64(6 * time.Millisecond)}, samples) + assert.Equal(t, 3, failed) + assert.NotEmpty(t, lastErr) +} + +func TestProcessPingResults_StopsOnContextCancellation(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + ch := make(chan ping.Result) + cancel() + samples, failed, lastErr := processPingResults(ctx, ch, 5) + assert.Empty(t, samples) + assert.Equal(t, 0, failed) + assert.Contains(t, lastErr, "context canceled") +} + +func TestProcessPingResults_HandlesClosedChannel(t *testing.T) { + ch := make(chan ping.Result, 2) + ch <- ping.Result{RTT: 1 * time.Millisecond} + close(ch) + samples, failed, _ := processPingResults(context.Background(), ch, 5) + assert.Equal(t, []int64{int64(1 * time.Millisecond)}, samples) + assert.Equal(t, 0, failed) +} diff --git a/src/internal/server/proxy_handler.go b/src/internal/server/proxy_handler.go index 7e059fe..2367e49 100644 --- a/src/internal/server/proxy_handler.go +++ b/src/internal/server/proxy_handler.go @@ -22,7 +22,6 @@ import ( "github.com/axiomhq/axiom-go/axiom/ingest" "github.com/buger/jsonparser" "github.com/gin-gonic/gin" - p2phttp "github.com/libp2p/go-libp2p-http" "github.com/prometheus/client_golang/prometheus" "github.com/spf13/viper" ) @@ -76,7 +75,7 @@ func getGlobalTransport() *http.Transport { MaxIdleConns: 512, // Support large peer sets MaxIdleConnsPerHost: 4, // Limit per-host to avoid head-of-line blocking } - globalTransport.RegisterProtocol("libp2p", p2phttp.NewTransport(node)) + globalTransport.RegisterProtocol("libp2p", newLibp2pHTTPRoundTripper(node)) }) return globalTransport } diff --git a/src/internal/server/server.go b/src/internal/server/server.go index 6377704..a2d49f7 100644 --- a/src/internal/server/server.go +++ b/src/internal/server/server.go @@ -15,7 +15,6 @@ import ( "time" "github.com/gin-gonic/gin" - p2phttp "github.com/libp2p/go-libp2p-http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/spf13/viper" @@ -120,7 +119,7 @@ func StartServer() { MaxIdleConns: 50, MaxIdleConnsPerHost: 2, } - scrapeTransport.RegisterProtocol("libp2p", p2phttp.NewTransport(node)) + scrapeTransport.RegisterProtocol("libp2p", newLibp2pHTTPRoundTripper(node)) cfg := metrics.ScraperConfig{ ScrapeInterval: time.Duration(viper.GetInt("metrics.scrape_interval_seconds")) * time.Second, From 4635652dc4506f3237f73a1fff0ad659423a7d07 Mon Sep 17 00:00:00 2001 From: Xiaozhe Yao Date: Sun, 10 May 2026 16:43:20 +0200 Subject: [PATCH 23/23] network-profiler --- .gitignore | 1 + .../network_profiler/bench.py | 65 +- .../network_profiler/bench_config.py | 1 + meta/tools/.gitignore | 1 + meta/tools/plot_measure.ipynb | 260 ++++ meta/tools/plot_utils.py | 1254 +++++++++++++++++ src/internal/protocol/host.go | 101 +- src/internal/server/libp2p_http_transport.go | 18 +- src/internal/server/probe_handler.go | 66 + src/internal/server/server.go | 1 + 10 files changed, 1746 insertions(+), 22 deletions(-) create mode 100644 meta/tools/.gitignore create mode 100644 meta/tools/plot_measure.ipynb create mode 100644 meta/tools/plot_utils.py diff --git a/.gitignore b/.gitignore index 55fdcbf..e037645 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ website/.source/ .local .pista .claude/ +.venv/ \ No newline at end of file diff --git a/contrib/network-profiler/network_profiler/bench.py b/contrib/network-profiler/network_profiler/bench.py index ec6686a..cedd42f 100644 --- a/contrib/network-profiler/network_profiler/bench.py +++ b/contrib/network-profiler/network_profiler/bench.py @@ -102,7 +102,7 @@ def phase_start( f"nohup otela start --config {cfg_path} --config-dir {d} " f">>{log_path} 2>&1 &" ) - result = runner.run(m, cmd, timeout=10) + result = runner.run(m, cmd, timeout=30) if result.returncode != 0: raise RuntimeError(f"phase_start could not launch on {m.name}: {result.stderr}") @@ -113,7 +113,7 @@ def phase_start( health = runner.run( m, f"curl -fsS http://127.0.0.1:{port}/v1/health", - timeout=10, + timeout=30, ) if health.returncode == 0: break @@ -143,7 +143,7 @@ def phase_converge( tbl = runner.run( m, f"curl -s http://127.0.0.1:{port}/v1/dnt/table", - timeout=10, + timeout=30, ) if tbl.returncode == 0: seen = _extract_peer_ids(tbl.stdout) @@ -156,6 +156,55 @@ def phase_converge( return out +def phase_punch( + runner, + machines: list[Machine], + peer_ids: dict[str, str], + http_port: int, + attempts: int = 5, + wait_ms: int = 2000, + timeout_ms: int = 30000, +) -> dict[str, dict]: + """For each (src, dst) pair, ask the source node to upgrade its connection + to the target via DCUtR. Records final connectedness per pair so the run + summary can show which pairs are actually direct vs circuit-only.""" + out: dict[str, dict] = {} + for src in machines: + port = _http_port_for(src, http_port) + for dst in machines: + if dst.name == src.name: + continue + target_pid = peer_ids[dst.name] + body = json.dumps({ + "target": target_pid, + "attempts": attempts, + "wait_ms": wait_ms, + "timeout_ms": timeout_ms, + }) + cmd = ( + f"curl -fsS -m {timeout_ms // 1000 + 5} " + f"-H 'Content-Type: application/json' " + f"-X POST -d {json.dumps(body)} " + f"http://127.0.0.1:{port}/v1/probe/holepunch" + ) + result = runner.run(src, cmd, timeout=timeout_ms // 1000 + 10) + entry = {"connectedness": "Unknown", "attempts": 0, "ok": False} + if result.returncode == 0: + try: + parsed = json.loads(result.stdout.strip()) + entry["connectedness"] = parsed.get("connectedness", "Unknown") + entry["attempts"] = parsed.get("attempts", 0) + entry["ok"] = parsed.get("ok", False) + if parsed.get("last_error"): + entry["last_error"] = parsed["last_error"] + except Exception as e: + entry["error"] = f"parse: {e}" + else: + entry["error"] = (result.stderr or result.stdout or "").strip()[:200] + out[f"{src.name}->{dst.name}"] = entry + return out + + def phase_sweep( runner, machines: list[Machine], @@ -233,8 +282,8 @@ def phase_teardown(runner, machines: list[Machine], run_id: str) -> None: for m in machines: d = bench_dir(run_id, m.name) cfg_path = f"{d}/cfg.yaml" - runner.run(m, f"pkill -f 'otela start --config {cfg_path}' || true", timeout=10) - runner.run(m, f"rm -rf {d} || true", timeout=10) + runner.run(m, f"pkill -f 'otela start --config {cfg_path}' || true", timeout=30) + runner.run(m, f"rm -rf {d} || true", timeout=30) def _extract_peer_ids(table_json: str) -> set[str]: @@ -287,6 +336,7 @@ def run_bench( started_at = datetime.now(timezone.utc) phase_timings: dict[str, float] = {} convergence: dict[str, dict] = {} + punch_results: dict[str, dict] = {} peer_ids: dict[str, str] = {} totals: dict[str, int] = {} teardown_done = False @@ -334,6 +384,10 @@ def on_sigint(signum, frame): convergence = phase_converge(runner, machines, peer_ids, http_port=http_port) phase_timings["converge_s"] = round(time.monotonic() - t0, 2) + t0 = time.monotonic() + punch_results = phase_punch(runner, machines, peer_ids, http_port=http_port) + phase_timings["punch_s"] = round(time.monotonic() - t0, 2) + t0 = time.monotonic() totals = phase_sweep( runner, machines, peer_ids, run_id, @@ -364,6 +418,7 @@ def on_sigint(signum, frame): for m in machines ], "convergence": convergence, + "punch": punch_results, "phases": phase_timings, "totals": totals, } diff --git a/contrib/network-profiler/network_profiler/bench_config.py b/contrib/network-profiler/network_profiler/bench_config.py index d8fb7ed..3036125 100644 --- a/contrib/network-profiler/network_profiler/bench_config.py +++ b/contrib/network-profiler/network_profiler/bench_config.py @@ -43,6 +43,7 @@ def build_host_config( "tcpport": str(tcp), "udpport": str(tcp + 1), "cleanslate": True, + "reachability": "auto", "bootstrap": {"static": bootstrap}, "security": {"require_signed_binary": False}, "scalability": { diff --git a/meta/tools/.gitignore b/meta/tools/.gitignore new file mode 100644 index 0000000..f08278d --- /dev/null +++ b/meta/tools/.gitignore @@ -0,0 +1 @@ +*.pdf \ No newline at end of file diff --git a/meta/tools/plot_measure.ipynb b/meta/tools/plot_measure.ipynb new file mode 100644 index 0000000..642f58c --- /dev/null +++ b/meta/tools/plot_measure.ipynb @@ -0,0 +1,260 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 20, + "id": "load-data", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "hosts: ['bristen', 'clariden', 'euler', 'jsc', 'oci-1', 'oci-2', 'sgs-amd-01']\n", + "matrices: ['http_latency_avg_ms', 'http_latency_p95_ms', 'libp2p_ping_avg_ms', 'libp2p_ping_p95_ms', 'punch_connectedness', 'throughput_mbps']\n" + ] + } + ], + "source": [ + "import json\n", + "from pathlib import Path\n", + "\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from matplotlib.colors import LogNorm\n", + "\n", + "from plot_utils import set_publication_style, save_figure\n", + "\n", + "set_publication_style()\n", + "\n", + "RESULTS_PATH = Path('../../.local/bench-results/consolidated_results.json')\n", + "with RESULTS_PATH.open() as f:\n", + " data = json.load(f)\n", + "\n", + "exp = data['experiments']['multi_run_7host_variance']\n", + "hosts = exp['hosts']\n", + "matrices = exp['matrices']\n", + "print('hosts:', hosts)\n", + "print('matrices:', list(matrices.keys()))" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "build-matrices", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "latency (ms) range: 0.272 - 37.789\n", + "throughput (Mbps) range: 38.609 - 5031.299\n", + "raw ping coverage: 21 / 42\n", + "raw iperf3 coverage: 2 / 42\n" + ] + } + ], + "source": [ + "def to_matrix(stats, hosts, key='mean'):\n", + " n = len(hosts)\n", + " M = np.full((n, n), np.nan)\n", + " for i, src in enumerate(hosts):\n", + " for j, dst in enumerate(hosts):\n", + " cell = stats.get(src, {}).get(dst)\n", + " if cell is None:\n", + " continue\n", + " v = cell.get(key) if isinstance(cell, dict) else cell\n", + " if v is None:\n", + " continue\n", + " M[i, j] = float(v)\n", + " return M\n", + "\n", + "latency = to_matrix(matrices['http_latency_avg_ms'], hosts)\n", + "throughput = to_matrix(matrices['throughput_mbps'], hosts)\n", + "\n", + "raw = data['experiments']['raw_baseline']\n", + "ping_raw = to_matrix(raw['ping_avg_ms'], hosts)\n", + "iperf_raw = to_matrix(raw['iperf3_mbps'], hosts, key='sent_mbps_mean')\n", + "\n", + "off_diag = latency.size - len(hosts)\n", + "print('latency (ms) range:', np.nanmin(latency), '-', np.nanmax(latency))\n", + "print('throughput (Mbps) range:', np.nanmin(throughput), '-', np.nanmax(throughput))\n", + "print(f'raw ping coverage: {int(np.isfinite(ping_raw).sum())} / {off_diag}')\n", + "print(f'raw iperf3 coverage: {int(np.isfinite(iperf_raw).sum())} / {off_diag}')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "plot-heatmaps", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved figure: network_profiler.pdf\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAACqwAAAUdCAYAAACHMPArAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAuIwAALiMBeKU/dgABAABJREFUeJzs3Xd0VNXXxvEnvUMIkNBL6FXpRor0DkrviIKIYMWCvXdFVKqgCAJKURClSxek9957CYEkBJKQ/v7ha34MJJk7kylJ+H5cWcu5s885e3JnJsyZfc9xSUtLSxMAAAAAAAAAAAAAAAAAAABgJ67OTgAAAAAAAAAAAAAAAAAAAAB5GwWrAAAAAAAAAAAAAAAAAAAAsCsKVgEAAAAAAAAAAAAAAAAAAGBXFKwCAAAAAAAAAAAAAAAAAADArihYBQAAAAAAAAAAAAAAAAAAgF1RsAoAAAAAAAAAAAAAAAAAAAC7omAVAAAAAAAAAAAAAAAAAAAAdkXBKgAAAAAAAAAAAAAAAAAAAOyKglUAAAAAAAAAAAAAAAAAAADYFQWrAAAAAAAAAAAAAAAAAAAAsCsKVgEAAAAAAAAAAAAAAAAAAGBXFKwCAAAAAAAAAAAAAAAAAADArihYBQAAAAAAAAAAAAAAAAAAgF1RsAoAAAAAAAAAAAAAAAAAAAC7omAVAAAAAAAAAAAAAAAAAAAAdkXBKgAAAAAAAAAAAAAAAAAAAOyKglUAAAAAAAAAAAAAAAAAAADYFQWrAAAAAAAAAAAAAAAAAAAAsCsKVgEAAAAAAAAAAAAAAAAAAGBXFKwCAAAAAAAAAAAAAAAAAADArihYBQAAAAAAAAAAAAAAAAAAgF1RsAoAAAAAAAAAAAAAAAAAAAC7omAVAAAAAAAAAAAAAAAAAAAAdkXBKgAAAAAAAAAAAAAAAAAAAOyKglUAAAAAAAAAAAAAAAAAAADYFQWrAAAAAAAAAAAAAAAAAAAAsCsKVgEAAAAAAAAAAAAAAAAAAGBXFKwCAAAAAAAAAAAAAAAAAADArihYBQAAAAAAAAAAAAAAAAAAgF25OzsBAAAAALgXfPbZZ5o6dWqWMY8++qhef/11B2UEe5g+fbo+/vjjLGPatm2rb775xkEZAQAAAJCk8+fPq0WLFoZi69evrxkzZtg5IyD3GDBggLZu3WoodtWqVSpRooSdMwIcj7k923j11Ve1YMECQ7E//fSTGjRoYOeM4AgRERFq2bKlbt26lWmMn5+fli9frsKFCzswMwCAM1CwCgAAcrzz588bnsCQ/v1SgUkMADnJqVOnzH7Z6ePjo6FDhzooI9hL7969NWXKFEVERGQas2zZMm3dulX169d3YGYAAABA9llStOZMFLgAAGzJHnN78+fP12uvvWZVPjVq1NCvv/5qVdvMdO/eXfv27bOq7SeffKKuXbvaNB/kLYULF1bv3r01bdq0TGNiY2P11Vdf6ZNPPnFcYgAAp6BgFQAA5HgXLlzQuHHjDMc//fTTfCkBIEf5+OOPlZSUlGVMnz59VKhQIQdlBHvx8vLSk08+qQ8//DDLuA8//FALFiyQm5ubgzIDAAAAAACANXLa3N6+ffu0d+9e1axZ0yb97dmzx+piVcCoJ554QnPmzFF8fHymMQsWLFCfPn1s9twGAORMFKwCAADcQ9huB3C8devWaf369VnG+Pj46IknnnBQRrC3Xr16afLkybpy5UqmMUeOHNGcOXPUt29fB2YGAAAAAABgO5UqVTIUV7x4ca1evdrO2dhHTp3bmzlzpj7//HOb9GVu9VjAFgoVKqTevXvrxx9/zDQmLS1NH374oebOnevAzAAAjubq7AQAAAAAIK9KS0vT6NGjzcY9/PDDCgoKckBGcARPT08NGDDAbNyECRN069YtB2QEAAAAAAAAS+Xkub2lS5cqMjIy2/1cvXpVy5Yts0FGgHmPPvqo3N2zXldvz549+uuvvxyUEQDAGShYBQAAAAA7Wbp0qY4cOZJljIuLix599FEHZQRH6dmzp3x8fLKMiYiI0MyZMx2UEQAAAAAAACyRk+f2EhMTbbIK5Zw5c5SUlGSDjADzihYtqjZt2piN+/bbb5WWluaAjAAAzkDBKgAAAADYQWpqqsaOHWs27qGHHlJoaKgDMoIjBQYGqkuXLmbjvv/+e8XGxjogIwAAAAAAABiVG+b2Zs+erZSUFKvbJycna/bs2TbMCDBv0KBBZmOOHj2qJUuW2D8ZAIBTULAKAAAAAHawZMkSnTx50mxc//79HZANnMHIuY2KitKsWbMckA0AAAAAAACMyg1ze5cuXdKqVausbr9ixQpduXLFhhkB5tWsWVP33Xef2bjx48ezyioA5FEUrAIAAACAHUydOtVsTJEiRdSwYUMHZANnKFeunO6//36zcTNnzmTrNQAAAAAAgBwkt8ztzZw50+q2M2bMsGEmgHFdu3Y1G3PixAmtX7/eAdkAAByNglUAAAAAsLHt27frwIEDZuMeeeQRubrysSwvMzL5Gh4ermXLljkgGwAAAAAAAJiTm+b2tmzZouPHj1vc7tChQ9q5c6cdMgLM69Chg7y9vc3GTZ8+3QHZAAAczd3ZCQAAAABAXjNt2jRDcUaKGZG7dejQQR9//LFu3bqVZdy0adPUqVMnB2UFAAAAWCc7K7G9+uqrWrBggeH4VatWqUSJElaPBwCAtXLb3N7MmTP17rvvWtSG1VXhTAEBAWrZsqUWLVqUZdzGjRt17NgxVahQwUGZAQAcgaV8AAAAAMCGIiIitHr1arNxVapUUenSpR2QEZzJ399fDz74oNm4/fv369ChQw7ICAAAAAAAAJnJjXN7Cxcu1M2bNw3HR0VFmS0UBOytbdu2huLmzp1r50wAAI7GCqsAAAA2lpiYqFOnTunEiRM6efKkLl26pPDwcF25ckXR0dFKSEhI/3Fzc5OHh4fy5cunoKAgFStWTGXKlFG1atVUp04dhYSEOPvhOERUVJQ2bdqk/fv36+jRo7p8+bIiIiJ069YtJSYmysvLS/7+/ipSpIhKly6tGjVqKCwsTJUqVXJ26nc5cuSINm3apCNHjujChQuKjY2Vr6+vChQooMKFC6tevXp68MEHlS9fPofldPXqVe3fvz89p/DwcN28eVO3bt2Si4uLfHx85Ofnp5CQEJUsWVKhoaG6//77FRQUlGW/hw4d0sqVKw3lUKdOHUNFe1lZvny5jh49aij2kUceUcmSJbM1nrUWLVqklJQUs3EtW7Z0QDZZO3jwoNavX6/Dhw+nv+b8/f1VrFgxVa9eXS1btrT4fSg+Pl7r16/Xzp07deLECcXExMjNzU1BQUEqWLCgateurcaNG6tgwYJ2eUyJiYnavHmzDh48qJMnT+rUqVOKjIxUfHy84uLi0t9TvL295evrq5CQEBUpUkRFixZVuXLlVLlyZZUvX16enp42y6lVq1aGvuhYuHChqlSpYrNxAQAAANheVFSUNm7cqD179ujMmTOKiYlRamqqgoKCVKBAAVWuXFmNGzdWaGios1OVJF27dk0rV67Upk2bdPToUUVERCg2NlYpKSny8/NTmzZt9Mknn1jd/4kTJ7R//34dO3ZMly5d0tWrV5WQkKDExER5enrK29tbhQoVUrFixVSxYkVVr15dZcqUsd0DzGMiIyO1YsUK/fPPPzp27JjCw8N169YteXt7KygoSKGhoapbt65atmyZ4XPsxo0bOnLkiKGxAgICHDq3lpycrF27dqVvX3716lXFx8ebzIs++OCDqlOnjk0/k1srPj5ea9as0YYNG3TkyBGdP39esbGxcnFxUf78+VWmTBnVqlVLzZs3V61atZydLmwoN83t/ScuLk7z58/XwIEDDcXPmzdPCQkJds7Kfs6ePauVK1dq69atOnnypK5du6b4+Hh5eXkpODhY5cuX1wMPPKA2bdooODjY2ekqLS1NW7Zs0bp167Rv3z6dPn1aN27cSP9bXKJECVWrVk1NmjTRQw89JA8PD7vkcfToUW3btk0nT57UyZMndfHiRcXFxSkuLk7x8fFyc3OTj4+PvL29VbBgQRUpUiT9O5lKlSqpUqVKZr8zsESjRo3k7e1tdmeqxYsXa9SoUXJ3p7wJAPIK3tEBAACyKSIiQps2bdLOnTu1a9cuHTt2zNCEliSlpqYqKSlJcXFxunz5sg4ePGhyf7Vq1dS5c2d1795d/v7+hnM6f/68WrRoYdHjuJPRyS1Jevrpp/XMM89Y1H9iYqKWLl2qefPmaceOHUpNTc00Nj4+XvHx8YqIiNC+ffvSr/4uXbq0evfurR49eiggIMCi8e80duxYjRs3zlDsJ598YrLdU2pqqhYsWKDp06eb/VJg5syZcnNzU/v27fXCCy+oePHi2co7M+fOndPvv/+ulStX6vDhw1b1Ubp0aTVs2FCtW7dW/fr15ebmZnJ/cHCwJk+erMTERLN9VahQIVtX7aelpenDDz/UlStXzMbmy5dPQ4cOtXqs7Fq4cKGhuOxOalvypdKdz8ulS5dq0qRJWT435s+frw8//FDNmjXTCy+8YHbbpWvXrmnKlCmaM2eO4uLiMo2bM2eOXFxc1LRpU7300ksqX7684ceRlZ07d2ratGn6+++/sxxfUvpEbGRkpM6fP3/X/e7u7ipfvrzq1auX/pOdydhmzZrJzc3N7N+GRYsW6eWXX77rtQYAAADA+Q4dOqRJkyZp1apVSkpKMhtfsWJFjRw5Us2aNbN6zFdffVULFiwwFPvTTz+pQYMG6bcjIyP1zTffaP78+Zl+bo+Njc3wM5E5hw4d0rx587R69WpdunTJ4vYlSpRQy5Yt1bNnT5UrV87i9rfbsmWL4Tms+vXrW7wF9oABA7R161ZDsatWrVKJEiUs6v8/ERERGjt2rBYsWJDh+YqNjVVsbKzOnTundevWafTo0WrUqJFeeuklkwsfDx48aNffhzVu3rypH3/8UXPmzFFERESWsZMnT5afn58GDRqkwYMHy8/Pz6oxLXledOnSRZ9++mn67fj4eE2ZMkUzZ87U9evXM2wTERGhiIgIbdu2TZMnT1alSpX04osv6qGHHrIqXyl78zzmZGfe05o+MnLhwgWLHmN2Xk/Z5ai5PUsEBQUpMjIyy5hZs2ZpwIABcnFxyTIuJSVFs2fPNjtmwYIFde3aNYvytLfDhw/rq6++0vr165WWlnbX/XFxcTp9+rROnz6tlStX6tNPP1WHDh30wgsvqGjRolaPa/S5W7x48bsuWv/99981ceJEnT59OsM20dHRio6O1v79+zVnzhwVKlRITz75pPr27WuTAs3IyEj9+OOPWrZsmc6ePZtlbEpKihITE3X9+nWFh4ff9X2VJIWEhKh27drpc6YVKlQw+5zLjI+Pjxo1amR2UYxr165pw4YNatq0qVXjAAByHldnJwAAAJDbzZw5Uy+//LJ++eUXHT582HCxqhEHDhzQJ598ombNmmn69OlZFnXmJgsWLFCbNm30yiuvaNu2bVY/rjNnzuizzz5Ty5Yt9fPPP2c4SWVvhw8f1iOPPKLXX3/d8GRxSkqK/vzzT7Vt21bz5s2zaT5Hjx7Vs88+q1atWmncuHFWF6tK//5+f/75Zw0aNEhffPHFXfcXLFhQ7du3N9TXsWPHtHPnTqtz2bFjh6FiVUnq0KGDvLy8rB4rO06cOGFoW/ciRYqocuXKDsjIVGRkpAYPHqznn3/e0HMjNTVVq1atUpcuXTR16tRM4xYvXqz27dvrxx9/NFssKv1bgLxmzRp17txZkyZNsugx3Ck8PFzDhw9Xnz59tHz5ckPjm5OcnKzDhw9rxowZevbZZ7M9GVqgQAHdf//9ZuMiIiK0efPmbI0FAAAAwLbi4+P1zjvvqGvXrlq2bJmhYlXp38/nw4YN01NPPaX4+Hg7Z2nqn3/+UceOHTV79mxDF5katXfvXg0aNEiPPPKIZs2aZVWxqvTvhdbTpk1T+/btNWzYMMO7qeRVy5cvV4cOHTRnzhyLzteGDRvUrVs3ffvttzl2znDp0qXpc1TmilX/Exsbq/Hjx6tNmzbat2+fnTM0tW/fPnXo0EHjx4/PtFg1I0eOHNHQoUP18ssvKzY21o4Zwt5y6txe+fLlVbt27SxjTp8+rQ0bNpjta82aNbpw4UKWMXXq1Mn2BQW2lJqaqnHjxqlr165at26d4e8BkpOTtXDhQnXo0EG///67fZO8w7Vr1/Too49q1KhRmRarZuTq1av66KOP1KtXL505c8bq8dPS0jR58mS1bNlSkydPNlusalR4eLiWLl2q999/X506ddLSpUuz1Z/Redc///wzW+MAAHIWClYBAABygZiYGH388ccaPHiwYmJinJ2O1SIiIjR48GC9+uqrunjxos36jY6O1nvvvachQ4aYvdLclhYsWKAePXpYvKrBfxITE/Xmm2/qhx9+yHYuiYmJ+vLLL9WlSxctX77c5sW7mRViDxgwwHAfc+fOtXp8Sya+unfvbvU42bV27VpDcfXr17dvIhk4c+aMunXrZmji+k5JSUn67LPPMtwmcsyYMRo5cqSio6Mt7jclJUVjxozRxx9/bHFb6d8vEXr37q1Vq1ZZ1d4oW7ye6tWrZyhu3bp12R4LAAAAgG2cO3dO3bp10+zZs60uCFy9erUef/xx3bx508bZZWzp0qUaOnSoTVfFS0hI0CeffKJevXpp06ZNNutX+rdwqmvXrho3bpxNLwLPLSZPnqznnnvOouLI26WkpGj8+PF6/vnnDRdTO0JKSoref/99Pf/881bP1UVEROjRRx/Vli1bbJxdxlauXKm+ffuaLeTLyh9//KEBAwY4dH4StpWT5/b69+9vNmbWrFlmY4ysrGxkLEdJTEzUc889p7Fjx1r9dyI2NlajRo3St99+a+PsMnbq1Cl17do1Wxem79+/X7169dLevXstbpuUlKSXX35Zo0ePtnsRfXbnTY3OmW7YsCHHXpwBALAcBasAAAC5yD///KMhQ4bo1q1bzk7FYocPH1aPHj2sKpYzasOGDerdu7fOnTtntzH+8/333+vVV1+1yUolX3zxRba+8Lly5Yr69++vKVOmKDk5Odv5WKJ69eqqVauWodhly5bpxo0bFo+Rmpqq5cuXG4qtXLmyqlevbvEYtrJ+/XpDcY6e1L58+bIGDBiQ7ULxadOmmUx8f/nll9leIVWSpk+fbvEqBzdv3tTjjz9u0+J3e6JgFQAAAMhdjh07pt69e+vEiRPZ7mvnzp364IMPbJBV1rZv366XX37ZpoWLkZGRevTRRzVt2jS7FYokJSVp7NixGjZsmMMKe3OC6dOna/To0Ta5SHL58uV68cUXnbL70J2Sk5P17LPPGiqcMyc2NlbPPfec3bclX7NmjZ5//nmbzPMdOHBAQ4YMYaXVXCqnzu1JUuvWrVW4cOEsY9atW5fl3Pjx48fNFlEGBwerVatWVuVoa6mpqXr++ee1YsUKm/Q3fvx4fffddzbpKzPnz5/XgAEDdPny5Wz3FRUVpSFDhuj48eMWtfvss89yzYqkZcqUMfu8lv5dtGTPnj0OyAgA4AgUrAIAAOQye/bs0YcffujsNCxy/PhxPfroo1ZvFWeJM2fOaNCgQbp69ardxpg/f76++OILm/WXlpamN954w6qtzC9fvqy+ffs6dbLG6Cqr8fHx+uOPPyzuf9u2bYa3jevWrZvF/dtKbGysduzYYSi2bt26ds7G1NNPP63w8HCb9PXpp5/q3Llz+u233zRlyhSb9ClJH330ka5cuWI4fvTo0TaZ+HWU2rVry83NzWzc6dOnHVJ0DwAAACBzV65c0WOPPWbTuYXff//d8Mp91oiKitJzzz1n02LVqKgoDRw4ULt27bJZn1lZv369hg4dqvj4eIeM50wbN27Up59+atM+ly9frvHjx9u0T2u8+eabWrlypc36i4qK0nvvvWez/u504sQJjRw50qavnQMHDuj111+3WX9wjJw8tydJHh4e6t27d5Yxqamp+vnnnzO9f+bMmWbH6dWrlzw8PCzOzx6++eYbm++s9NVXX9nt73FCQoKeeuopw3PZRly/fl1PPfWU4Qs69uzZY5MLBhzJaAG40YJyAEDOR8EqAABALjRv3rxcczXp9evXNXToUKu2C7fW+fPn9fTTT9tttdFt27bZvM8LFy5o4cKFFrX5b4VJZxe3tWnTRsHBwYZi582bZ3H/S5cuNRTn6empzp07W9y/rezdu9fQlxu+vr4qU6aM/RO6zb59+2zWV2Jiot544w2brw4UExNjaEsy6d/nvjXPJWey5Lwb/XIEAAAAgH2cPn3apsUm/5kwYYLN+/zPF198YdMC2+TkZI0YMULHjh2zWZ9G7NixQ6NGjXLomI5248YNjRo1yi4r1m7dutXmfVrKHvNmy5cvt8lqxxnZu3evVReRm7Ns2TKLd5OBc+Xkub3/GCkmnT9/foY7tN24ccPs/LORolhHstcFE6+99ppdvq+4evWqjh49avN+z549q48//thQ7PTp0+22Irq9VKlSxVAcc6YAkHdQsAoAAOAA3t7eCgoKUokSJVSxYkWFhoaqePHi8vLysrpPe37JYUtvvfWWLly4YHE7Dw8PFS9eXOXLlze0Jcyddu3aZZOtyh1p7ty5FsW//fbbdpust4S7u7v69OljKPbQoUPau3ev4b5TUlL0119/GYpt2bKlAgMDDfdta/v37zcUV7FiRbm4uNg5G/vasmWLXVa8mT9/vqEvBtasWWPxyie3v6eEhoaqcOHC8vHxsTZVq1SqVMlQnNHnEgAAAIDcZc+ePTp8+LBd+j5//rxN+xs3bpzTCkOWL1+u2bNnO2VsR/jmm2+sLogODAxM/0zr6npvfc07Z84ch473X1Fi8eLF5enpaVUfX3zxheFVEeF8uWFur3DhwmrTpk2WMdHR0RluB//bb7+ZLc5u06aNChUqlK0c7c3FxUVBQUEqV66cChYsaNW5iIyM1JgxY+yQXcY8PDxUrFgxlSlTRn5+flb1MX/+fO3evTvLmMTERItXj3VxcVHBggVVtmxZVaxYUcWKFVNAQIBD/8YYnTM9ePCg0tLS7JwNAMAR3J2dAAAAQF5TokQJhYWF6f7771eZMmVUtmxZFSxYMNP48PBw7dmzR8uWLdOKFSsMF2GtX79e4eHhCgkJues+Dw8PVa5c+a7jly5d0vXr1w31X6pUKfn6+hqKzWwS6++//9by5csN9SH9OznSoUMH9erVS/fff7/JZHBERIQWL16syZMn69q1a4b6mzJlirp166aiRYsazsEaNWvWVO/evVW/fn0FBwfrxo0b2rFjh6ZMmWLRypYHDx7UqVOnVLZsWbOx69at0+LFiy3O1cPDQ23atFGjRo1Us2ZNBQUFyd/fXzExMYqKitKhQ4e0bds2rVu3zqLt1nv37q2JEycqMTHRbOzcuXNVs2ZNQ/1u3brV8Aox3bt3NxRnL0YntY1OwNlLxYoVNWjQIIWFhalQoUKKjo7W33//ra+++ipbq/FUqVJFgwYN0gMPPKCgoCBdu3ZNK1as0Lfffmv4y5mrV69q69atatiwYZZxRouePTw81K9fPz388MOqVKmS3Nzc7oqJjo7W8ePHdfz4cR08eFCbNm3S2bNnDfVvqYoVK2rJkiVm42y5Ii4AAACA7AsMDFTfvn3VqlUrlShRQm5ubjp58qR+/fVXzZ0716KVzJYsWZLhnE1Ocvr0aX3//fcWtfHw8FC3bt3Utm1blS9fXvnz51d0dLSOHDmixYsXa+HChRb9nsaMGaO2bds69cJUewgPD7e48NLd3V0DBw5Uz549TeaMIiMjtWTJEo0dO9ahOxtZqm3bturSpYuqVKmiAgUKKCIiQmvXrtXEiRMtKtxdsmSJXn/9dTtm+q+2bdtq4MCBql27dnohXGJiov755x9NnDjRbMHY7a5evaqff/5ZQ4cOtVO2jlOoUKEM37uMFuF7eHioXLlyhsdzxpb0uWVur3///lq0aFGWMT///LN69OiRfjstLU0///yz2b4HDBiQ7fzsxc/PT8OGDVPnzp1VpEiR9OP/fW8wfvx4xcTEGO7vt99+01NPPWXSl61VrVpVI0aMUJMmTUy+69i7d69mzpxp0Y5raWlpGjduXJZ/n0+cOKHY2FhD/dWvX1+DBg1SgwYN5O/vf9f9iYmJOnXqlE6cOKEjR45o27ZthlchtpTR19SNGzd06tQphYaG2jwHAIBjUbAKAABgA8WKFVO3bt3UuXNnlSpVyqK2ISEhat26tVq3bq2DBw9q6NChhiZrU1NTtW7dOvXs2TPDPjOa7Hj11Ve1YMECQ3l9+OGHatCggaHYzHz77beGYwMCAjR27FiFhYVleH/hwoU1aNAgtW/fXsOGDdOBAwfM9nnr1i1NmTJFb7/9tuE8LDVy5Eg98cQTJlcce3l5qU2bNmrRooVGjRpldgLxdnv37jVUsPrll19anGvLli312muvqUSJEnfdV7BgQRUsWFDly5dXp06dlJKSolWrVunHH3/Uzp07zfYdFBSk9u3bG9rqbPHixXrttdcMXU2+dOlSszHSv6/BzJ47jnLkyBFDcc7aMkySOnbsqE8++cRkgjQ4OFjdunXTfffdp65duyohIcHifrt06aL333/fpN+iRYvq0UcfVY0aNdSvXz/DX0zu3bvXbMGq0cLazz//XO3bt88yJjAwUHXr1lXdunXTj128eFEbN27U4sWLtWXLFkNjGWF0MtXocwkAAACA/dWtW1dff/31Xbu/1KhRQzVq1NBDDz2kESNGWPSZxxE8PDzUsWNHNW3aVNWqVVNQUJA8PDwUFRWlkydPavv27Vq9enWGbcePH29RQUqpUqU0ceJElS9f3uR4cHCwgoOD1bhxY/Xp00dPPfWU4YuQo6Oj9eOPP+qFF14wnEduMHfuXEMX+/7H19dXP/zwg2rXrn3XfUFBQerfv7/atm2rQYMG6dixY7ZMNdt8fX317bffqnHjxibHixcvrn79+qldu3bq37+/4d2DIiIidPnyZbsVl7m4uOjjjz9W165d77rP09NTTZs2VZMmTfTxxx9rxowZhvudOXOmhgwZkutXxO3Tp0+GOywZLTQLDg62qDjPGXLD3J4k1apVS9WqVctyfvzgwYPasWOH6tSpI+nfxS/OnDmTZb/Vq1fX/fffb8tUbaZEiRL66aefVLx48bvu++97g3bt2mngwIE6ffq0oT6TkpL0888/a+TIkTbO9l89e/bUO++8I3f3u0tyatasqc8//1xNmzbViy++aPjfEH///bdOnjyZ6Ryj0YsAmjZtqkmTJmW5Oq2np6cqVaqkSpUqpc+vxsXFafv27frrr7+0fPlyw4ujmBMSEiJfX1+zKwBL/xbJU7AKALlf7v6XMQAAQA7Qr18/rVq1Sk8//bTFxap3qlq1qj744APD8du3b8/WePa0e/duw1/CuLq6atKkSYYKDoODg/Xdd98pf/78hvpesGCB3bbeevrpp/Xkk09mOuHs7u6ujz766K4vtbJi5Er+jRs36ujRo4b7lKQhQ4Zo3LhxGRarZsTNzU2tW7fWL7/8oi+++CLDlXzvZPQK/Li4OENFvCkpKVqxYoWhPrt27erUif+0tDRdvHjRUKw9r9rPSo0aNe4qVr1d+fLlzW4plpFatWrpww8/zLTf2rVrq3Xr1ob7M7K6qJHJ0Pz585stVs1MsWLF1KNHD02bNk3r1q3TqFGjrOrnTkZeR5IUHx+frdVuAQAAANhGxYoV9d1332X5ub558+bq16+f4T6NXICbXXXr1tXixYv16aefqm3btipZsqT8/Pzk6empkJAQhYWF6ZlnntGCBQv0xRdfmLS9evWq4YtHpX8vAvzxxx/vKla903333afvv/9eXl5ehvuePXu2RcWducEff/xhUfyXX36ZYbHq7QoVKqQffvhB+fLly05qNuXq6qoJEybcVax6u6CgIIsvyDa6AqY1nn322QyLVW/n6uqqN954Q02bNjXcb3h4uDZv3pzN7GBvuWFu73b9+/c3GzNr1qz0/585c6ZN+nQGb29v/fDDDxkWq94uJCRE33//veFd4yRp4cKFdtlivlGjRnrvvfcyLFa9Xfv27S0umM2q8NtoAWmPHj2yLFbNjK+vr5o0aaIPPvhAGzZs0Pjx421WPGp03vT8+fM2GQ8A4FwUrAIAAGRTcHCwTQvlmjZtKm9vb0Oxhw4dstm4tmZk2+v/9OzZ02R1Q3P+u2raiLi4OK1fv95w30ZVrFhRw4cPNxvn7e2ttm3bGu7XyFbkln650bp1a7388stWTUJJUufOnTVkyBCzcdWrV1etWrUM9Tl37lyzMZs3b1ZUVJTZOBcXF7NfKNhbRESE4ZVJg4OD7ZxNxl599dVMi0r/U79+fav6NTf52rJlS8P9GXkNGFmdNzk52SZbVAUHB9tswt7oxKskXbhwwSZjAgAAALCOi4uLPvjggwy3yb2TJZ9JY2JiFBkZmZ3UstS4cWNNnTpVpUuXNhR/Z+HV8uXLLfos9cILLxi+OLZq1ap67LHHDPcdHR2tTZs2GY7P6U6dOmXoM+9/mjZtqhYtWhiKDQkJ0YgRI6xNzeZ69uxp6ML0qlWrWrS9urkVIq1VqlQpQ3Nf0r/vDa+//rpFW9avXbvWyszgKLlhbu92HTp0UIECBbKMWbFiha5cuaIzZ87o77//zjI2KChIHTp0sGWKNvPYY48ZXtW2ZMmSGjx4sOG+L1++bPOdjtzd3fXGG28Y/s5o0KBBFq3au27dukzvMzJnKskmF4N4enqqZcuWqlKlSrb7kozPmzJnCgB5AwWrAAAAOYyLi4sKFixoKDYnX02a1cTJnawpBjM6YS/J7IScNZ566im5ubkZirVk0ubGjRtZ3p+WlqY1a9YY7s/X19eiVXuza+DAgYbi9u/fb7bg2uiKLmFhYWavsLe3S5cuGY61pGjRVipXrmyoKNzSK+KrVq1qaKswS758MvcakGR2Ql6SYmNj9fXXX9tllQRrWbLastFVPQAAAADYR6NGjQxvjVy+fHmzF/Ldzl47wRQqVEhffPGFRauY3smS+ZygoCB1797dov4ff/zxe7bQz9Kdkvr27WtRfPfu3bN17m3F1dXV0EXe/7HlvJm1evbsafYi39uVLl1ajRo1Mhy/detWa9KCA+X0ub07eXl5qUePHlnGJCUlac6cOZo1a5bZ+bEePXpY9BpwFFdXV4vfC/v06WN43l6StmzZYmlaWXrwwQctmmP18PBQr169DMcfPnw405VUg4KCDPUxceJERUREGB7TEYwWglvyWgUA5FzGPz0DAADAIsePH9fu3bt19OhRnTt3TpcuXVJ0dLRiYmKUmJio5OTkbBdSxcXFKS4uzqJtbhwhOjpap0+fNhQbHBysChUqWDxGyZIlDcfu2bPH4v6z4uvrq+bNmxuOt2SbKHMT7ydOnDC8tY8kdevWTYGBgYbjs6t169YKDg7WlStXzMbOmTNH7777bob3JScn66+//jI0pqVfjtmDJV+YOOP1avT5aukKEc2aNTMUV7RoUcN9xsTEmI2pUaOG5syZYzbu+++/18qVK9W2bVvdd999Cg0NVfHixS36ctSW3N3d5eXlZWjFDnt9gQ0AAADAmE6dOhmO9fT0VFBQkKHPwpKxzz3WeOaZZwxd4JcVS+ZQWrdubVGhriTlz59fjRo1Mnwxrq3ndJzJklX8fH191bBhQ4v69/f3V1hYmNOLfBs0aGBRQZ8t582s1aZNG4vbtG7d2vDz+Pjx40pMTMyRBYH4V06f28tInz599MMPPyglJSXTmDlz5ujWrVtZ9uPm5qY+ffrYOj2bqFWrlsXzlQULFlSdOnUMF4rbehe71q1bW9Xms88+MxSblpamw4cPq0GDBnfdV7FiRXl4eJhdKf3o0aNq3bq12rRpo/r166tSpUoqVaqUAgICLM7dVoy+ruz1dwAA4FgUrAIAANjQ8ePHNWfOHC1btszwlxTZFR8fn2Mmyf5z7Ngxw7FXrlyxaPVFa5w+fVrJyckWf4mSmZo1a8rb29twvCUTPbGxsVneb+kEmjUTZNnh7u6uPn366JtvvjEbu2jRIo0aNUo+Pj533ffPP/8oOjrabB+BgYFq1aqVNanalLmJ39tZ8tyxlerVqxuKy58/v0X9VqtWzVBcRuc4M3FxcWZjLFnF5PTp05o0aVL6bTc3NxUvXlylS5dW6dKlFRoaqkqVKqlKlSqGt83KDm9vb0MFq0Z+DwAAAADsp379+hbFBwQEGJ4Lsse/9319fS0qss1IeHi4oc/i/6ldu7ZV49SqVctwod/Ro0eVlpYmFxcXq8bKSc6dO2c4tlKlSlbNY1WtWtXpBav16tWzKN7f399wrD1eO/nz51epUqUsble1alXDsUlJSTp//rzFO9vAcXL63F5GihUrpubNm2d50b+RVTRbtGhh0cXmjlSjRg2r2lWtWtVwweqpU6esGiMz1uRcokQJBQYGGv4bfOrUqQwLVn19fVWnTh1t3rzZbB9xcXFasGCBFixYkH4sKChIpUuXVpkyZVSmTBlVqFBBVapUUbFixQw/FmsZfV3Fx8fbORMAgCNQsAoAAGADly9f1ieffKLly5c7fPtpI4VPjnbhwgVnp2AiJSVF4eHhNts2vnLlyhbFW1KsZ8758+cNx3p4eOi+++6z2dhG9e7dWxMnTlRiYmKWcTdu3NCSJUvUrVu3u+5bunSpobE6duyYI1ansOQLE2dMahv9QsTS3Iz2a6ti8f8ULVpUbdq00fLlyy1um5KSorNnz+rs2bP6+++/04+7ubmpYsWKCgsLU/PmzVW3bl27fCHq7e1taJVkJl8BAAAA58mfP7/FxTuWfPa3x9xR/fr1s30RniVzDpKsvgDZkp12kpKSdOXKlRyxBXd2WbL9ctmyZa0aw9p2tmTpvJklF+Lb47VTrlw5q9qFhobKxcXFcE7h4eEUrOZgOX1uLzP9+/c3vEtVVn3kVOXLl7d7u/DwcKvGyIirq6vVr/PQ0FDt3LnTUGxWOQ8aNMhQwWpGIiMjFRkZqV27dpkcL1y4sBo0aKDGjRurRYsWdlmJlYJVALi3uDo7AQAAgNxuy5Ytevjhh7Vs2TKHF6tKUmpqqsPHNCcqKsrZKdzFkhVCzClcuLBF8bYs1ouMjDQcGxwcLC8vL5uNbVRQUJA6dOhgKHbevHl3HUtKStKqVasMte/evbtFueUEznifMLolpKXP1exuNZkdI0eOtOmKqCkpKTp06JCmTp2q/v37q0WLFvrhhx9sflGAM84/AAAAAMtY+rlf+veiUWeydhW621k6n1OwYEGrxilUqJBF8ZbMheRk5nbVuZ0lq47aop0tOXPezBqBgYFWtfP09LSo2DYmJsaqcZDz5KS5nQceeMCiiwDuVLFixQxX6swprH19WrKLlJELy43y9fW1enEFS3LO6v2kWbNmFu1OZURERET6bmkNGzbUa6+9ptOnT9t0DADAvYWCVQAAgGzYs2ePnnzySZsWQ+YFlmyh5Ci2vPLW0sl/Nzc3m41tyeOwdHt3WzJ6Zf6uXbt09OhRk2MbN240NFFYrVo1ValSxar8bM2SlXSc8fow+gWKq6tlHxEt+WLG1sqUKaOJEyfarSj7woUL+vzzz9W+fXvt27fPZv0aPf85abUOAAAA4F5jTdGfpZ+nbK1kyZLZ7sPS7datvYjQ0nZ5ZTW1lJQUw7HWfia05S4/1rL09ePs1052Loa1pG1OnC/F/+T0ub2s9OvXzyltHcERf2dsebF6Tnk/+eabb2xyIUtGEhISNH/+fHXs2FGTJ0+2Wb9G/9YzZwoAeQMFqwAAAFa6deuWXnjhhTwzaZ7XWfKlgDmWXiVty4l3S67gd+aEf/Xq1VWrVi1DsXPnzjW5vXTpUkPtunXrZnFe9mLJRJmtV+w0wtor+53Vr1ENGjTQnDlzVK1aNbuNcf78eQ0ePPiuwmprGf1Sw5nFwAAAAMC9zprPOra8WNUa+fLly3Yflq4aaO28g6W/K1utZmhNP0lJSTYZW7JsFV5r5xstWcXVXix9/Tj7tZOd3assaeus+UFJSk5OttnYeVVOn9vLysMPP2zVFu358uVT586d7ZCR7Vg7p29JO1u+NnPK+4m/v79++ukn9e3b127vsUlJSRo9erQmTpxok/6MzpnmhAszAADZR8EqAACAlWbNmqULFy44O40ciatc7ceS362ztxobOHCgobg//vgjfaI3MTFRq1atMtvGy8tLnTp1ylZ+tmTJpHBO+PIoL6lSpYp+++03TZgwQY0bN7bLVoLXr1/X888/n+3C96SkJCUmJhqKzQnbOAIAAADIPWxx0Zul8zmWrsj6n5s3b1oUb6t5Jms+01maa1YsmTuwdlxnzwXlRtmZp7GkrS3nSy19Lt+4ccNmY+dVuXluz9fXV127drW4XdeuXXP8BdPW/q4taWfL3Zsc9X5iJGdfX1+98847WrJkiQYMGKACBQpYnVtWvv76a+3cuTPb/Rj9NwVzpgCQN1CwCgAAYKU7V4U0p3Dhwho2bJimTZumdevWaffu3Tp8+LCOHDly10/x4sXtlLVj2GvyA1JgYKDh2KtXr9p0ZVlLtW7dWiEhIWbjrl+/rmXLlkmSNmzYYGgSvVWrVjZZPcZWihYtajj2ypUrdszk3uTi4qIWLVro+++/1z///KMxY8aob9++qlGjhs2+EDpx4oQWLlyYrT4iIiIMx1rynAIAAAAAW7BkzkGSoqKirBonOjraovj8+fNbNc6drFkt1drHmJHg4GDDsadOnbJqjOPHj1vV7l529epVq9rFxsZatBKuLedLLX0u2/J5nFfl9rm9fv36ycXFxXC8q6ur+vXrZ8eMbOPatWtWtYuMjDQca8vXZlxcnNVFq5Y8VktyLlOmjN58801t3LhRs2bN0jPPPKNGjRqpUKFC1qSZoTFjxmS7D6Ovq2LFimV7LACA89l+6RkAAIB7wNmzZ3X69GnD8e3atdMnn3xieLsSo9uf5FSWTBrUr19fM2bMsGM2eYslxcxxcXE6dOiQqlevbseMMufu7q7evXvrm2++MRs7b948Pfzww1qyZImhvrt3757d9GwqODhYHh4ehr4wCA8Pd0BG9678+fOrffv2at++vaR/t9O6dOmSzp49qwsXLujChQs6c+aMDh8+rFOnTlm03dbixYutWrHiP5cvXzYcm9svXAAAAACQ+1haBHLs2DGVK1fO4nEsKap0c3NTkSJFMr3fkgItS+fbIiMjrS5mzEiZMmUMxx49elTJyckW7yKyb98+C7PCiRMnlJqaavG24JYWBxu5qNuo+Ph4i7bFPnr0qM3Gzqty+9xe6dKl1bhxY61fv95QfOPGjVWqVCk7Z5V91j53LWlny9em9O97w3333WdRm7S0NJ04ccJwvDU5u7m5qW7duqpbt276sevXr+vMmTM6f/68Lly4oHPnzunEiRM6ePCgRauob926VRERESpcuLDFef3H6OuKOVMAyBsoWAUAALDCwYMHDccWL15cn3/+uTw9PQ3FJyYm5vqr3suXL2849tChQ0pJSZGbm5sdM8o7LPndStK6deucVrAqSb1799bEiRPNboO+bds2HT58WKtXrzbbZ4kSJfTAAw/YKkWbcHFxUfHixQ0VsufESe28zNXVVcWLF89wMvPatWv67bffNHbsWLPPUUnasWOHkpKS5OHhYVUuRs+9l5dXtiZ4AQAAAMAaxYoVk6+vr+EilX379qlt27YWj2NJUWXp0qWzLNq0ZFcNS7dF3717t0Xx5lStWtVwbFxcnDZu3KiHHnrIcJsrV65o+/bt1qR2T4uPj9eRI0dUpUoVi9rt2bPHcKyPj4/ZIitvb2/DRdU3b95UUFCQodjr169bvWLvvSQvzO3179/fcMFq//797ZyNbVj7Prx3717DsZbOt5uza9cuiwtWjxw5YtGKzRUqVLA0rQzlz59fNWvWVM2aNU2OJyUlaePGjfriiy8MF+dv3rxZnTp1sjoXoyusUrAKAHmDZZeKAQAAQJJlq+Q1a9bMcLGq9O8He0tW/LOEJasyZGcr+aCgIJUuXdpQ7I0bNwxPpEGqUqWKRV/G/PLLL4YK8ewlKChIHTp0MBT78ssvG9oyqWvXrhatoOIoFStWNBTHlwQ5R8GCBTV06FC9/PLLhuLj4+MVERFh9XgnT540FFehQoUc+RwHAAAAkLe5ublZdNHrihUrLB4jISFBa9euNRxvrujH39/fcF/Xrl2zaCv1xYsXG441on79+hZ91vv5558t6n/69Ol2m1PM65YuXWpxm+XLlxuOrVKlitkVXAMCAgz3d+nSJcOxy5Yty9Y8rzlG55uTk5PtloOt5Pa5vSZNmhiaky9TpowaN27sgIyy778dkixx9uxZixYcsfViD8uWLbO4jSXvJx4eHoafq9by8PBQ06ZNNW3aNMPfRZw5c8bq8S5dumT4YplKlSpZPQ4AIOegYBUAAMAKlmyHYsn2TJI0bdo0C7Mxzs/Pz3BsdoqypH8nyIyaNGmSXSbUT5w4YdWXJzmZh4eHHnzwQcPxERERGjdunB0zMm/AgAGG4oxs1eTq6pqtLdntyejkJtuw5TwNGzY0HJudFbCNnvsaNWpYPQYAAAAAZEejRo0Mx549e1br1q2zqP8FCxbo5s2bNsvHkiK/pKQkw1sunzt3zuZzSoUKFbprFbusrF27VitXrjQUe/DgQU2fPt3a1O55c+fOtWgF3t27d2vHjh2G443sFGRJ8fXhw4cNxSUnJ+unn34y3K81jM43R0VF5fii1dw+t+fi4qK+ffuajevbt2+uulD6hx9+sGu8rXfy2rVrl0WrXd+8eVNz5swxHH/fffdZ/J2TtQoXLmy4QDQ6OtrqcYy+pnx9fVWuXDmrxwEA5BwUrAIAAFjB19fXcOz+/fsNx/7yyy/auHGjNSkZYskk/oYNG7I1Vrt27QzH7t69W9988022xrvdli1bNGzYMHXo0MHQFvO5TceOHS2Knzx5spYsWWL1eMeOHdPvv/9udftq1aqpVq1aVre/XcOGDVW0aFGb9GVrlkxqp6Wl2TmbvO3w4cP67LPPDG3TZoQlBfrZ+XLlyJEjhuIoWAUAAADgLG3atLEo/uOPPza0W4okXb161aL5H29vbzVt2jTLmKCgIIsKd4yspJmamqr333/fLjvWPPLIIxbFv/TSS2Z3Jtq7d68GDx5s0eqxMBUVFaVPP/3UUOytW7f0/vvvWzS306JFC7MxlmxzbXRF2B9++MHwdt7WMlpom5iYqG3bttk1l+zKC3N73bp1y/K7C19fX3Xr1s2BGWXfb7/9pq1btxqK3bVrl+bNm2e474oVK6pkyZLWppap999/3/Dfxi+//FLXrl0z3Le595MPPvhAa9eutdkCIVevXjUUl52/QUbnTKtVq2Z2tWoAQO7AuzkAAMhzxo0bp0qVKtn05/z58yZjFCpUyHA+mzZtMlQ0OWvWLH3wwQcWP15LhISEGI79888/NXnyZF2/ft2qserUqaNq1aoZjp80aZLeeusti1YzuN3Bgwc1ZswYtW3bVgMHDtSaNWty7MRhdrVu3VpFihQxHJ+WlqaRI0dq3LhxFn3ZcuXKFY0ePVpdunTRgQMHrEk13cCBA7PV/j85eUL1vvvuM7QNWlxcnM0KLe9VN2/e1NSpU9Nf7/PmzdPly5et6isxMVETJkwwHF+4cGGrxrl586bOnj1rKLZ27dpWjQEAAAAA2VWmTBmLVlk9ffq0hg8fbnbV1MjISA0ZMkSRkZGG+3744YfNFsO5ubmpSpUqhvucPn26Dh06lOn9ycnJeuedd8wWiVrrkUceUYECBQzHx8fH64knntBzzz2n1atX68qVK0pMTFRkZKQ2b96sN998U71797bo94qM/frrr/rss8+yLLqKiYnRM888Y9E8WcWKFQ0VQlqyLfmuXbs0e/bsLGN+++03jRkzxnCf1rJkvvnNN9/Uxo0blZKSYseMrJcX5vYCAgK0ePFiLVmyJMOfxYsXW7Sab06Qmpqq4cOHa/PmzVnG7dy5U8OGDbPo+dWlS5fsppehI0eOaPjw4Vm+N6ekpOjrr7/WL7/8Yrhfd3d3derUKcuY9evX68knn1SLFi30zTffaM+ePVYXr86dO1cXLlwwFGvtnKn073c7RjBnCgB5h/l/cQEAAOAu5cuXtyj+2Wef1eDBg9WrVy8VK1Ys/XhCQoI2b96sH374QVu2bLF1mnepWrWq4di0tDSNHj1aX331lYKDg5UvXz65ubndFdepUycNGTIkwz6efvppPfXUU4bHnDt3rlauXKlHHnlErVq1UpUqVTJcJePmzZs6evSoDhw4oAMHDmjbtm13FRXnZR4eHho+fLjefvttw23S0tI0duxY/frrr+rfv78aN26sihUr3rX907lz57Rjxw6tX79eK1assNnqHK1bt1ZISIjCw8Ot7iMwMNDQihTO4u/vr1q1ahlaLWL79u0qW7asA7LK29LS0rRly5b0988KFSooLCxMFStWVLly5VSuXDnlz58/w7ZXr17Vhg0b9MMPPxjedsrNzc3qydedO3camjAvVaoUzw0AAAAATjV8+HCLdt7ZvHmz2rdvr6efflqtWrUyKci8evWqlixZovHjx1u0XbCnp2em8013qlGjhnbu3GkoNj4+Xv3799crr7yiTp06pa9EmJiYqL///lvjx4/P9kW7WfH19dWwYcP0ySefWNRu2bJlWrZsmZ2ywn+mTp2qDRs2qE+fPmrYsKGCg4OVkpKiCxcuaO3atZoxY4ZFu7RI0mOPPWYoztLdVt577z2dOXNGjz32mIKDg9OP7969W9OmTTO8Cmt2VatWzfDr7/z583r88cfl5eWlIkWKyNvbO8Ot6ceMGaPQ0FBbp2pWXpnbu/37h7zixo0bGjRokDp06KDOnTurSpUqCgwMVExMjI4cOaJFixbp999/t6gw09/fXz169LBbzv/9bezfv79atGihEiVKyNPTU1euXNHmzZv1yy+/WPz3plOnTobnJi9evKgJEyZowoQJCgwMVMOGDVW9evX0OdPixYtn+PpLTEzU7t27NW/ePP3xxx+Gc7NkgY07bd++3VBckyZNrB4DAJCzULAKAABghcqVKys4OFhXrlwxFJ+UlKRJkyZp0qRJKlSokAoUKKC4uDhFRETYZXuxzFSsWFE+Pj6Kj4833CYtLU3h4eGZFhrWr18/07bNmzdXs2bNtGbNGsPjRUZGaurUqZo6dapcXV1VsGBB+fv7y9XVVdevX9f169fZ4kxSjx49tGDBAu3atcuidpcuXdIXX3yhL774Qj4+PipQoID8/PwUExOj6OhoJSQk2CVfd3d39enTR19//bXVfTz88MPy9PS0XVJ20KRJE0OT2tu2bbPrhOi96tixYzp27JjJMS8vL/n5+cnf31/e3t5KSkrStWvXFBMTY3H/DzzwgDw8PKzKzei2d0y8AgAAAHC2OnXq6OGHH9bChQsNtwkPD9dbb72ld955RwULFlT+/PkVHR2ta9euWbUDzuOPP65SpUoZim3ZsqWmT59uuO+bN2/q7bff1ocffqgiRYooNTU1feVSR+jfv79+//33LFd6hfMcPXpU7733nk36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iIiIiIiIiIhI28QQw7Ce1ZbrOwAiIiIiIiIiIqLKEYkKfwyFIcVCRCoxpLv2RERERERERERERERERERERERERERUAzFhlYiIiIiIiIiIiIiIiIiIiIiIiIiIdMpY3wEQERERERERERFpm0hkBMBI32EU4e5kRERERERERERU3YlgWPe5DCkWIlIJV1glIiIiIiIiIiIiIiIiIiIiIiIiIiKdYsIqERERERERERERERERERERERERERHplLG+AyAiIiIiIiIiItI2EcQwrGe15foOgIiIiIiIiIiIqFJEosIfQ2FIsRCRagzprj0REREREREREREREREREREREREREdVATFglIiIiIiIiIiIiIiIiIiIiIiIiIiKdYsIqERERERERERERERERERERERERERHplLG+AyAiIiIiIiIiItI2MUQwrGe1ZfoOgIiIiIiIiIiIqHJEIohEIn1HUcSQYiEilRjSXXsiIiIiIiIiIiIiIiIiIiIiIiIiIqqBmLBKREREREREREREREREREREREREREQ6ZazvAIiIiIiIiIiIiLRNBCMARvoOoxi5vgMgIiIiIiIiIiKqFJGo8MdQGFIsRKQarrBKREREREREREREREREREREREREREQ6xYRVIiIiIiIiIiIiIiIiIiIiIiIiIiLSKWN9B0BERERERERERKRtIohhWM9qG1IsRERERERERERE6hOLRIBIpO8wFMQGFAsRqYZ3yomIiIiIiIiIiIiIiIiIiIiIiIiISKe4wioRUTVXIA1CgdRa32GQlhgbddd3CKQDjSyP6DsE0gG5TN8RkLYZmeo7AtKFhhZ5+g6BdKCgIEnfIZCWGBmJAdjpOwwiIiIlLqM6Q2rElXpqCvmR2/oOgXQiSt8BkA7IedONqFoQibg2Wk3EazAREVUFJqwSEREREREREVGNIxYZATDSdxhFRHJ9R0BERERERERERFQpIlHhj6EwpFiISDV87IWIiIiIiIiIiIiIiIiIiIiIiIiIiHSKCatERERERERERERERERERERERERERKRTxvoOgIiIiIiIiIiISNtEEMOwntU2pFiIiIiIiIiIiIjUJ/rvx1AYUixEpBreKSciIiIiIiIiIiIiIiIiIiIiIiIiIp1iwioREREREREREREREREREREREREREekUE1aJiIiIiIiIiIiIiIiIiIiIiIiI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92YwZDJZqfWycrIRn5KEGxFh+PvQDgxs9wI2ffg9bCyLHnQb22MQVh7+B8euapbIEf7sMS6H3cTle6Fo7eOHCb2GaNQPkT69//5MeHrW0+kYOTk5GDJksiBZ1dbWBt9//wlee22s0ipS1tZWcHOrg9atAzBlyjjk5+djx44DsLAw12mc1dmdO+GYMOFNQZJUkybeWL78G7zwQgel+tbWVqhXry66deuIOXOmIjk5BStXboG9va3aY//vf4MwefJLlYqfSsd5rfmq6qEB0j19nq8SiQT+/r5o06YF2rZtgd9/X42QkNuVej9EZbl48SK2bdsGABCLxZg5cyYWL16sUV9///034uLiFMceHh7YuHGjIoH0OVdXV3zxxReoW7cufvrpJ0X577//jhEjRsDWtvzzJjk5GcuXLxeUzZ07F9OmTROUicVi9OnTBwEBARg7diyePXsGoDC5dNWqVXjzzTdRkap6T1R1mLBKKsnKysLhw4dx5MgRXL58WbBcc1ns7e3RokUL9O3bF/369YOVFVdmIqqtzMxM8NJLPfHSSz0RG5uETZuOY/36Iwi5fl+pbkGBFAcOXMCBAxdgbW2BF4d1wezZI9GqVWM9RE5Ez8nlcvz28CByi20/3dDcBV83GQsbiYVKfVgbm2OEW/uKK5LORWVmwc3CXOPtL768ch0hicIV/YY3bADj/74UJf2IysiCm6Xm8/r5hRCExJeYV+/6nFcDIZfL8dujA8grdh32NHfBwibjYGOs2nXYytgcw115HdaWunXrKp4I18RXX32JVq1aCcq2bduutFrEc8eOHUdeXh5MTEwUZR9/PB87d+7C06dPVRrzt99+gbm58MvoAwcOqhl59SGSiyGSG841TATDiYWIiAzfR+Omw9Ks6HNegbQAL342S5CsWtKPO1ajnrMr3h7xsqJsROc+CPRuimv375Q7XkJqMt5culDtOA9c+hcvLXwHh77+U1A+pf//VEpYjU9Jws6gY7gcForL924i+N4tpGSkKX7/6cSZasdEVFt88cVPuHu36Jpga2uDo0c3oW3bliq1l0gkGDPmRR1FV/3J5XJMm/a+YPvpgICmOH58Cxwd7VXqw97eDnPnTtdViKQBzmvtUBUPDRT3PLGxbdsWaNu2JZYsWcXERi2o6seqG70AAQAASURBVPO1USNP1K/vrkhQbdmyGczMih78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2uNswiMAQHxePjxs9Duvcbl5mNKqbF47N3GGlRnnlRqH4uJivP32u+jZ8wkAgLe3NxITEw0clW55e3tj+/YdAICIiFtITk42cERERERERERERERERNTQ8NtFIiKqUvv2LdC+fQtDh2EwEyb0N3QIRERaC3VxQqiLk8GOH+LshBBnwx2/oWrn6oR2rob7u4a6OiHUgMcnMqRr167h2rVrhg6jzjx8+BA//rjc0GEQEREREREREREREVEDxoRVIiIiIiIiIiJqcMQQQQyRocNQMKZYiIiIiIiIiIiItCESiQCREV3nMqZYiEgtYkMHQEREREREREREREREREREREREREREDRsTVomIiIiIiIiIiIiIiIiIiIiIiIiIqE6ZGjoAIiIiIiIiIiIiXROLjOtObTFXJyMiIiIiIiIionpOBBEgMqYLXcYUCxGpw5iu2xMRERERERERERERERERERERERERUQPEhFUiIiIiIiIiIiIiIiIiIiIiIiIiIqpTpoYOgIiIiIiIiIiISOdEorIlyoyFUS2VRkREREREREREpAWRcV3mkhtRLESkHlZYJSIiIiIiIiIiIiIiIiIiIiIiIiKiOsWEVSIiIiIiIiIiIiIiIiIiIiIiIiIiqlOmhg6AiIiIiIiIiIhI18Qwrju1jSkWIiIiIiIiIiIibYhEIohEIkOHUU4kgtzQMRCRRnitnIiIiIiIiIiIiIiIiIiIiIiIiIiI6hQTVomIiIiIiIiIiIiIiIiIiIiIiIiIqE4xYZWIiIiIiIiIiIiIiIiIiIiIiIiIiOqUqaEDICIiIiIiIiIi0jWRCBAZOogKRMYUDBERERERERERkRZEYhFEYiO60CUWQW7oGIhII6ywSkREREREREREREREREREREREREREdYoJq0REREREREREREREREREREREREREVKdMDR0AERERERERERGRrokhghjGszyZMcVCRERERERERESkDZFIBJHIiK5zGVMsRKQWVlglIiIiIiIiIiIiIiIiIiIiIiIiIqI6xYRVIiIiIiIiIiIiIiIiIiIiIiIiIiKqU6aGDoCIiIiIiIiIiEjXRCLAmBYE4+pkRERERERERERU34lEIoiM6UKXMcVCRGphhVUiIiIiIiIiIiIiIiIiIiIiIiIiIqpTTFglIiIiIiIiIiIiIiIiIiIiIiIiIqI6ZWroAIiI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RERERESkrrCwMHz00UdiWy6XY82aNTA2Ni5y3rlz5zB16lSkpKQoncgUFxeHbdu24ciRI1i2bBl8fHy0EntpVMhMTUNDQzRu3BiNGzfWdShERERERERERKQDMkEBmVD88ellRQb9iYXKlzZt2qBNmzZITEzE9evXcfPmTURFRSEuLg6JiYmwsLCAjY0NHBwc0KhRI/j4+MDc3FzXYRMRERERERFRBSSDAJmKJ8CUBRn0JxYidR0+fBi3bt0ST1Xq0aNHscmqL168wMcff4zk5GQAKPBEJoVCgZiYGHzwwQfYunUr3N3dNR98KVTIhFUiIiIiIiIiIiKiisTCwgLt2rVDu3btdB0KERERERERERERldKZM2cA5CSYCoKAAQMGFDtn4cKFSExMlCSq5q2yKggCBEGAQqFAXFwcvvnmG2zatEnzwZcCE1aJiIiIiIiIiIiIiIiIiIiIiIiIiMqAQqHAnTt3xORSU1NTNG3atMg5T548wbFjx8RkVYVCAXNzcwwcOBDu7u6IiIjA7t27ERISIq577do1nDlzRq9ugmfCKhERERERERERVTjC/z/0hT7FQkREREREREREVBKCkPOhL/QpFiJ1PH/+XKyUKggCGjduDLlcXuScf//9V6zGqlAoYG1tjb///htubm7imDFjxmDMmDHw8/MT+/bs2aNXCasyXQdARERERERERERERERERERERERERPQ6ePHihaTt6elZ7JwjR46IyaqCIOD999+XJKsCgIWFBRYsWAAA4tgzZ84gOztbc8GXEhNWiYiIiIiIiIiIiIiIiIiIiIiIiIjKQGhoKABAoVAAAKpXr17k+KioKDx+/FhsGxgYYODAgQWO9fT0RJMmTcS1U1NTERgYqImwNcJQ1wGUxMCBA/H8+XOxPWDAAMyYMaPU6yYmJqJHjx5ISUkR+77++mv06tWr1GsTEREREREREVHZkQk5H/qCd42TNmVmZmLnzp04evQo/P39kZCQADs7O3h7e6N3797o3r27rkMkIiIiIiIiogpAJgiQCfpz0U2fYiFSR2JioqRtYWFR5PirV6+KjwVBgI+PD6ytrQsd37RpU1y/fl1sBwQEoGbNmiWMVrPKXcLq9evX4evrK7YNDQ0xfPhwjaxtYWGBrl274s8//xT7tmzZwoRVIiIiIiIiIiIi0qrExESsWrVKbAuCgA8++ADG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ZP9/pUqVMGfOHPWcGBERERERERF9EsQQQQzNueimSbEQKUpLSwvt2rVDu3bt8OHDBxw8eBAHDx5EQEAAAAh2ns/IyMD169dx/fp1mJqaolu3bujduzecnZ3VeQpFUqoSVp88eYLMzEzBhdaRI0eqdA0TExP06dMHf/31l/SC8OPHj1W6BhEREREREREREVFuFhYW+OeffzBo0CB8+PBBsCVYdhJqSEiINDH1Y9m/z/bxhW1ra2v8888/sLCwKP6TICIiIiIiIiIiIoWUK1cOo0ePxujRo+Ht7Y29e/fi1KlTSExMBCC8xhcTE4N///0X//77L2rWrIk+ffqgW7duMDc3V+MZKE+s7gCU8e7dO8Gxq6srypcvr/J12rVrl++6RERERERERERERMXBwcEBR44cQYsWLQSVUj/+yU5g/fgnrz6enp44fPgwHBwc1HxmRERERERERERElBc3NzcsXLgQ165dw6+//gp3d3eZa3/Zx8+fP8fChQvRsmVLfP/997h8+bK6w1dYqaqwGhMTI30sEolQsWLFYlkn97xpaWlISkqCgYFBsaxHRERERERERESqJYYEYkgK7lhC5MXy77//wszMTKHxlpaWqg6JNJilpSU2bNiAo0ePYsuWLfDx8ZH+LvvitDwfV1l1dXXFyJEj0aVLl2KPl4iIiIiIiIjKBjEAsfzLEmpRqio1EinIwMAAffr0QZ8+ffD69Wvs27cPhw8fRnh4OABh1dXU1FScOnUKp0+fxtWrV2FlZaXO0BVSqhJW09LSBMfGxsbFso6RkZFMW3p6erGsRUREREREREREZVPVqlWZiEr56tatG7p164aHDx/i2rVruH//Pp4+fYro6GhkZmZK+4nFYlhYWMDZ2Rlubm5o3rw56tatq8bIiYiIiIiIiIiIqKiqVKmCKVOmYPLkyfDy8sL+/ftx6dIlpKenCxJXS5NSlbCau8JpWFhYsawTGRkp06avr18saxERERERERERERHlp169eqhXr56gLT4+HgkJCTAyMiq2G/uJiIiIiIiIiIhI/cRiMVq3bo3WrVvj7t27mDx5srTiamlTqhJWra2tpY8lEgn8/PyKZZ3nz58Ljk1NTaGjo1MsaxERERERERERkeqJRBKIRJpzZ7kmxUKfBmNjYyaqEhEREREREVGJEolE0qqOmkCTYiEqTomJiTh+/DgOHDiABw8eAMjKnyyN/w2UqoRVR0dHwXFISAgePHiA+vXrq3Sd48ePSx+LRCKZdYmIiIiIiIiIiIiIiIiIiIiIiIiIisvdu3exf/9+nDp1CsnJyZBIsgojyEseLy3Jq6UqYbVmzZowNDREUlISgKws4d9++w07d+5U2RpPnz7FiRMnIBKJpFnIDRo0UNn8RERERERERERERERERERERERERES5vX//HgcPHsTBgwfx9u1bABAkqn58bGVlhe7du6NPnz6wtLRUT8BKKlUJq1paWmjdujWOHz8uTSj19vbG0qVLMXXq1CLP/+HDB0yZMgUZGRmCjOP27dsXeW4iIiIiIiIiIio5IhEg1qAbykvJze1ERERERERERER5EolEEGvQha7SUlGSqCBpaWk4d+4c9u/fjxs3biAzM1NuNVWJRAItLS20aNECffv2RatWraCtXapSQEtXwioADBo0CMePHwcAadLqpk2bEBMTg5kzZ8LIyKhQ8z579gzff/893rx5I6iuWrNmTbi5uanyFIiIiIiIiIiIiIiIiIiIiIiIiIioDHv27Bn279+PY8eOISYmBkDe1VSrVq2K3r17o2fPnihXrpx6AlaBUpew6uHhgRYtWuDKlSvS7GGJRIL9+/fj8uXLGDt2LLp06QJTU1OF5nv+/Dl27tyJ/fv3IzMzU+b3kyZNUvUpEBEREREREREREREREREREREREVEZExMTg6NHj+LAgQN49uwZAMhUU5VIJJBIJDAyMkKnTp3Qp0+fT6boZqlLWAWAn3/+Gb169UJsbCyAnEqrYWFhmD9/PhYtWoQGDRrA2dkZ1atXh6mpKYyMjJCWlob4+Hh8+PABz549w8OHD/Hq1SsAspnJIpEIPXv2hKenp3pOkoiIiIiIiIiICk0kAkQiibrDkOLuZGXToUOH1B2CXD179lR3CERERERERERUCon//6MpNCkWooJcuXIF+/fvx4ULF5CWlibNVwRkq6l6eHigT58+6NixIwwMDNQSb3EplQmrFSpUwKpVqzBmzBikpKQAED5pqampuHXrFm7dupXvPPKe9Oz2hg0b4ueffy6G6ImIVEwbEJXKf81JHosKieoOgYpBZLyhukOgYpCecUndIZCKaVcdoe4QqBhkpp5TdwhUDDIlaeoOgVRFAgB66o6CqNjMmDFDcN1RUzBhlYiIiDRVWqa3ukMgFdMRfxqVwCi3YHUHQEREVCoEBgZi//79OHz4MEJDQwHIFtbMrqZqY2ODnj17onfv3qhcubLaYi5upTbFqXHjxti4cSOmTJmCkJAQQWVUQJiMmhd5F4slEgm6du2KBQsWQFdXV7VBExERERERERERUZmjyLXKkqKJCbRERERERERERESfkkOHDmH//v24e/cuAGGS6sf5jTo6OmjdujX69OmDFi1aQCz+9OsGl9qEVQBwd3fHkSNH8NNPP+H48eMAIJO4qiiJRAIzMzPMmTMHXbt2VXmsREREREREREREVDZpSpKoJiXOEhERERERERERfaqyd16SV00VAGrWrInevXuje/fusLCwUFuc6lCqE1YBwMTEBMuXL8e4ceOwdetWHD16FElJSTL98qu86uTkhCFDhqBHjx4wMDAo9piJiIiIiIiIiKh4iUUSiEWak5ynSbFQyWKSKBERERERERF9Kj6uDqkJNCkWInk+zlk0NTVF165d0adPH7i4uKg5MvUp9Qmr2apVq4b58+fjxx9/hI+PD7y9vfH06VNERUUhNjYWsbGx0NXVhampKUxNTWFvb4969erBzc0NFStWVHf4RERERERERERE9Ik5f/68ukMgIiIiIiIiIiIiNcm+md3MzAyenp5IS0vD7t27SzQGkUiE+fPnl+ia+flkElaz6erqws3NDW5ubuoOhYiIiIiIiIiIiMowe3t7dYdAREREREREREREahYbG4ujR4+W+LoSiYQJq0RERERERERERMVNJJJAJNKcrdg1KRYiIiIiIiIiIqLCEItEEP9/i3NNoEmxEOUnu9IqMWGViIiIiIiIiIiIiIiIiIiIiIiIiEilRGpOqtbERFkmrBIRERERERERERERERERERERERERqYgmJotqgjKbsBofH4/bt28jODgYSUlJsLa2Rq1atVCrVi11h0ZEREREREREREUk/v+PptCkWIiIiIiIiIiIiApDLMr60RSaFAvRx86fP6/uEDRWmUtYjYqKwooVK3DgwAFkZGTI/L569eqYMmUKPD091RAdEREREREREREREREREREREREREZVW9vb26g5BY5W6hNX4+Hh07doV6enp0raJEyeif//+BY599+4dRo0ahcDAwDxL7vr7++Obb77Bl19+iSlTpqgsbiIiIiIiIiIiIiIiIiIiIiIiIiKisqrUJayeP38eoaGh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hBkzZuDy5cvYvHkzRowYAUdHR0FSavYPgAITWLN/DAwM0LZtW8yfPx9eXl7YuHEjunfvDl1dXXWeLhEREVGpseDX8TJtZ89cV0Mk+btw/pbgWCQSYer0kQqPnznrS5k2L697RY6LiIg+XSIN/J+ma9WqldLXZLS0tPDVV18J2q5evVrguP379yMzM1N63KVLF1SrVi3fMXp6ehg9WrirV0HJsTExMTh79qz0WCQSYcKECQXG16dPH9jb20uPg4KCcP16/u+xSuqcqOSUqm+kbW1tpY8lEgn8/PwEmdq5Xbp0SaZNkYTV7NLD2cRisUIZ7kREREREREREinjz+h0CAoQ32VasaJfvmD59uwiO4+MTsHXLf3n0FgoNDcehQycFbb16d1JoLBEVP7FYjM8++wwzZszAiRMncP36dfz1118YP348unbtCjc3N9jZ2cHExATa2toQi8UwMDCAlZUVatSogVatWmHo0KH45ZdfcPjwYdy9exd//vkn+vfvD2tra3WfHhEREVGp4+hoj6pVKwraAgPz3tlCXYKCwgXHNWpWho2NlcLjPRq6QF9fT9AWEhyeR28iIiIqSR4eHoLj6OhoJCUl5dE7y4ULFwTHffv2VWitzp07w9DQUHr8+PFjvH+f93ufS5cuIT09XXrcqFEjODgUXNVeLBajd+/egrbz58/nO6akzolKTqkqG1qrVi3BcWJiIq5du4aWLeVXIDl8+LDg2NTUFLVr1y5wndDQUMGxubm5coESERERERERERUg7P0HVK1aWXpsZGyUT2/IVFc9fPgU4uMTFF5vx/Z9GDw452JgxYoV4ObmCm9vbvdIpGksLS3h6ekJT0/PgjsTERERUbEob2OJgIB30uOEeNldOtUtMUGYtGJpaabUeJFIBEtLUwR/lKSampr/trxERERUMszMZF/X4+LiYGBgILd/QECAYCdyQ0NDuLm5KbRWdt9r164ByCok6eXlhf79+8vt7+XlJThu3ry5QusAQNOmTbF69Wrp8cWLF/PsW5LnRCWnVFVYtba2lpYFFolEkEgkWL16tSBjO9utW7dw//59aT+RSITGjRsrtM6zZ8+kj0UikUIZ4EREREREREREyjAzNxUch4d/yLNvRYcKcHauIWi7cvmmUuvdvHEPqampgraOndooNUdpIhJp3g8REREREZUe0dFxgmPr8pZqiiRv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rsPKVy6cv4WbNx8CAFq0qItGjWvpOCIiItI3PORGRLnFhFUiIiIiIj1jYmKMefOH4fLl+wCAt29DCl3CqiAIGD6iMwRBQL9+bXUdDhEVcklJSZj641zUb1AbAODq6lLgElbd3Iph06adAICbPncRH5+g44iICq9du3Zhzpw5SEhIfx0yyZSIiIgoeyYmxpg7fxyuXL4LAHj3NpgJq2qKiYnDiJG9AABdurbUcTREREREVBAxYZWIiIiISA/VrFkeNWuW13UYOtO7Nw+IE5F+8fX1g6+vn67D0Jp79x7i3r2Hug6DqNBbv349Fi5cKF9RNWOi6qd6IiIiIlKuZk131Kzprusw8q127RvrOgQiIiIiKuCYsEpERERERERERAWPBBD0aU8wfYqF9JKvry8WLlwIQJyo+ilJ1crKCi4uLrCwsIChIQ/rEhEREREREZEOCIJ+7QSjT7EQkUp4ZJOIiIiIiIiIiIhIxxYtWgSZTCY/6SOTyeDg4IBBgwahTZs2KF68uI4jJCIiIiIiIiIiIsodJqwSERERERERERER6VBgYCB8fHwgCII8adXT0xOrV6+GlZWVrsMjIiIiIiIiIiIi0ggmrBIRERERERERUYEjCPq1I5g+xUL65+7du6KypaUlli9fzmRVIiIiIiIiItIrgiDId4fRB/oUCxGpRqLrAIiIiIiIiIiIiIgKs+DgYPltQRDg7e0Ne3t7HUZEREREREREREREpHlMWCUiIiIiIiIiIiLSocTERACATCYDAFSrVk2X4RARERERERERERFphaGuAyAiIiIiIiIiIiqMnj9/jtDQUJXa2tvbw8HBQcsRka5YWVmJytbW1jqKhIiIiIiIiIiIiEh7mLBKREREREREREQFjwT6tbeQkli+/vprlbuPGjUKo0eP1mBApE9KliwJABAEAQAQGRmpy3CIiIiIiIiIiJTKB4fciEjP8XVLREREREREREREpEM1atSAoWH62gIBAQE6jIaIiIiIiIiIiIhIO5iwSkRERERERERERKRDlpaWaNy4MWQyGWQyGc6ePQuZTKbrsIiIiIiIiIiIiIg0yjD7JkRERERERERERPmLIACCHl2q/d9O7yLbtm2DjY2NSv3t7e01HBHpm+HDh+P8+fOQyWQIDAzErl270LNnT12HRUREREREREQkJ0CAoOxAl44I0J9YiEg1TFglIiIiIiIiIiLSgTJlyjARleSqVauGIUOGYPXq1RAEAXPnzoW7uzuqVaum69CIiIiIiIiIiIiINEKP1pkgIiIiIiIiIiIiKrzGjRuHHj16QCaTIT4+Hv3798fu3bt1HRYRERERERERERGRRjBhlYiIiIiIiIiICh6JHv4RqeDXX3/FTz/9BGNjY8THx2P69On44osvsHbtWty9exdhYWGQSqW6DpOIiIiIiIiICiFBD/8jovzFUNcBEBERERERERERERV2lSpVUqgTBAEymQwvXrzAkiVLNDKPIAh4+PChRsYiIiIiIiIiIiIiUgcTVomIiIiIiIiIiIh0TCaTKdQJggBBEDK9n4iIiIiIiIiIiCg/YcIqEREREREREREVOIIk7U9f6FMspL8+Jaeqe5+qmPRKRERERERERLkhEdL+9IU+xUJEqmHCKhEREREREREREZEeYEIpERERERERERERFWRMWCUiIiIiIiIiIiLSsVGjRuk6BCIiIiIiIiIiIiKtYsIqEREREREREREVPJL//vSFPsVCeokJq0RERERERESk74T//tMX+hQLEamGh8qJiIiIiIiIiIiIiIiIiIiIiIiIiEirmLBKRERERERERERERERERERERERERERaZajrAIiIKHeOXC8FC8FU12GQhrhbR+s6BNKC2ueX6DoE0oIU6Tldh0Aaxue0YDI0bqXrEEgLZLJUXYdAGiKT6ToCIiIiIsq/iuk6ANICQ4G/9woameytrkMgLRAEN12HQFrA12vBweOnRKTPmLBKREREREREREQFjiARIEgEXYchp0+xEBERERERERER5YREECAR9Oc4lz7FQkSqkeg6ACIiIiIiIiIiIiIiIiIiIiIiIiIiKtiYsEpERERERERERERERERERERERERERFplqOsAiIiIiIiIiIiINE74709f6FMsREREREREREREOSAIaX/6Qp9iISLVcIVVIiIiIiIiIiIiIiIiIiIiIiIiIiLSKiasEhERERERERERERERERERERERERGRVhnqOgAiIiIiIiIiIiKNk0C/LtXWp1iIiIiIiIiIiIhyQPjvP32hT7EQkWp4qJyIiIiIiIiIiIiIiIiIiIiIiIiIiLSKCatERERERERERERERERERERERERERKRVhroOgIiIiIiIiIiISNMEQYAg0Z8twQRBf2IhIiIiIiIiIiLKCUEAJHp0nEuPQiEiFXGFVSIiIiIiIiIiIiIiIiIiIiIiIiIi0iomrBIRERERERERERERERERERERERERkVYxYZWIiIiIiIiIiIiIiIiIiIiIiIiIiLTKUNcBEBERERERERERaZwE+nWptj7FQkRERERERERElAPCf3/6Qp9iISLVMGGViIiIiIiIiEgDjIyMUK5caZQo6QpXVxdYW1vCxMQEcXFxiIyMxsuXb3Dn9n1ER8foOlQiIiIiIiIiIiIiIqI8x4RVIiIiIiJCaGgkbt18jJs3H8PHxx83b/rj/fswUZvp0/tjxswBugmQcoTPK5F2uboWRZu2zVG/fm3U8qyGChXKwMjIKMs+qampuH3rHjZt2ont2/YgLi4+x/NbWlqgZq2qqFOnBjw9q8PTsxpKliouarNl8y4M+e77HM9BRERERERERERERESkKUxYJSIiIiIqpJYu3Ylb/yUyPn8eqOtwSEP4vBLlnW/69sDPv0xUq49EIkHtOjVQu04NTJw4AmPGTMXxf8+q3L9vvx5o0qQ+PGtXR4UKZWBgYKBu2IWHREj70xf6FAsREREREREREVEOSAQBEkF/jnPpUyxEpBomrBIRERERFVKTJq7SdQikBXxeifKPEiXdsHffBowdMw3r1m5Vqc/UqeMUVlElIiIiIiIiIiIiIiLKD5iwSkRERERERESUS8+fv8Kli9fh43MXAQHP8PLlG0RHRSM5OQXW1pYoX6EsGjf2Qr9+PVC8hKu8n0QiwfIVc/Dq1RucPHFeh4+AiIiIiIiIiIiIiIhIu5iwSkREREREAABLSzPUqlUBtWu7o3adiviqzyxdh0QawOeVSHueBDzHj1N+w4EDx/Hi+atM28XExCIwMBjnz13BooUrMXfeVAwbPkDU5vfls1G1SjOkpKSoFUN8fALu+frh1q17uHnTF7Pn/AQXF6ecPJwCR5Ck/ekLfYqFiIiIiIiIiIgoJwRBgCAIug5DTp9iISLVMGGViIiIiKiQqlPHHbXruKN27YqoXdsd7u4lIJGkZ9MwsTF/4vNKlHf27j2idp+EhESMHzcD9vZ26Nmrk7y+VKkSaNGyEU4cP5dl/wd+j3H69CXcuuWLWzd98eCBP6RSqfz+mTO/VzsmIiIiIiIiIiIiIiKivMCEVSIiIiKiQurK1VW6DoG0gM8rUf4wY8YCUcIqALRu3TTbhNXuXQdpMSoiIiIiIiIiIiIiIiLtYcIqEREREREREVEee/XyDZ4/f4UyZUrK69zcXHQYUQEkEdL+9IU+xUJERERERERERJQDwn9/+kKfYiEi1Uiyb0JERERERERERJr2IThEVLawtNBRJERERERERERERERERNrHhFUiIiIiIiIiIh2wsbURlUM+hOooEiIiIiIiIiIiIiIiIu0z1HUARERERERERESFjaOjPSpUKCOq8/G5o6NoCiiJkPanL/QpFiIiIiIiIiIiohyQCAIkgv4c59KnWIhINVxhlYiIiIiIiIgoj02aPAoGBgbycnx8AnbvOqTDiIiIiIiIiIiIiIiIiLSLK6wSEREREREREeURQRAwfsJQjB4zWFQ/f95yfPwYpqOoiIiIiIiIiIiIiIiItI8Jq0REREREREREWiIIAqysLFG6dAk0aFgH/fr3RI0aHqI2W7fsxoL5K3QUIRERERERERERERERUd5gwioRERERERERkYYcOLQZbdo0U6ntx49h+HXWYqz5c4t2gyqkBAEQJLqOIp0g6DoCIiIiIiIiIiKi3BH++09f6FMsRKQaJqwSEREREREREeWh2Ng4zJu7HKv+2IDY2Dhdh0NERERERERERERERJQn9GidCSIiIiIiIiKigs/Cwhy/zJqIXXv+QuMmXroOh4iIiIiIiIiIiIiIKE9whVUiIiIiIiIiIg3ZvesQ7vk+lJeNjAxhY2ONChXKokZND5ibmwEAJBIJmjdviKZN62PF8r8wedKvugq54BKEtD99oU+xEBERERERERER5QAPuRFRbjFhlYiIiIiIiIhIQ7Zs3pXpfebmZujzVVfMmPk9nJwcAaQlro4Z+x2MjY0wftyMvAqTiIiIiIiIiIiIiIgoz0l0HQARERERERERUWEQFxePv9Ztg2fNVrh794HovmHDB6Bd+1Y6ioyIiIiIiIiIiIiIiEj7mLBKRERERERERJSHPn4MQ6eO/RAeHimqnzptvI4iKqAkACSCHv3p+h+EiIiIiIiIiIgodwQ9/I+I8hdDXQdARERERERERFTYfPjwEct/X4cZM7+X19WqVRXlypfG0ycvdBgZEREREelKTEwsbt68hydPXiAsLAIpKSmwsDCHq2tRlCtXCh4eFWFkZKSx+VJSUnD3rh8ePXqKDx8+Ij4+AWZmpihSxAFly5ZEtWqVYGVlqbH5iAoSvl4pp2QyGZ48eYG7d/3w8WMYIiKiYGRkBFtba7i5uaB27WooUsRB12ES6b28eh+OiYnF1au3EBDwXP56dXZ2RLVqlVCjRhUIApMliYjUxYRVIiIiIiIiIiIdOHL4pChhFQDq1q3FhFUiIiKiQkQmk+HAgeNYvXoLzp69iuTk5EzbmpqaoF69mvjiixYYOvRr2NhY52jOW7fuYfnyDdi//ziioqIzbSeRSODhURFt2zbDt9/2RoUKZXI0H1FBwddr/ieRFM/1GJ6eVeHjc1Ttfk+fvsAff2zG1q178fFjWJZtPTwq4ttv+2DQoF5MRCb6TF6+D9+//wizZ/+O/ftPICkpSWmbYsWcMWTIN/j++yGwsDBXa3wiosKMCatERKQTj6JfYs6zzRof96ey/VDJqpTGxyX11LmwNNdjVLJ0wuZaX2sgGiIiIiL99OLFa4U6Z2dHHURSQEmEtD99oU+xEBFRviAIrrkew9OzGm7ePJYnc2U0c+YE/Pzz99k3LMQePXqCQYO+x/Xrd1Rqn5CQiPPnr+H8+Wto0qQevLxqqTVfREQkxo6dia1b90Imk2XbPjU1FffuPcK9e49gZ2eDKVNGqjUfUUHC1yvllFQqxbx5K/Hrr//LNOktowcPHmP8+J+xZMkarFkzH23bNtNukET5QF69D8tkMsye/TtmzVqGlJSULNsGBgbj558XY/36f7Bz5yrUrVtTpTnyPwEC9Ok4lz7FQkSqkOg6ACIiIk2ScNsFIiIiIsonlK0CocqJSCIiIqL8wMCAp6Cysn//v6hdu53KSRe59fjxM9Sq9QW2bNnD75xEauLrlXIqNTUVgwZ9j+nTF6qcrPq5N28C0aHDAPzzzwEtREeUf+Tl+/CoUdMwY8aibJNVP/f69Ts0b94TFy5c02JkREQFB1dYJSKiAsNcYoLS5sV0HQYRERERkUqKujgr1AUHf9RBJERERESa17JlI12HoLf27TuGnj2HQyqViupbt26Mzp29Ub++J5ydHWFpaYGIiCg8f/4Kt28/wIkT53H27FW1k56ePn2Bpk2748MH8XfNqlXd0b17e7Rq1RjFijnD3t4WMTGxCAwMxp07fjh37gqOHTuL8PDIXD9movyKr9eCbejQb9TeJtzNzUXltnPmLMeWLXsU6jt0aIW+fbvB07MqihRxQGJiEl69eouzZ6/gjz824+XLN/K2UqkU/fqNg4dHRXh4uKsVK1FBkJfvwytXbsSqVeIdQi0tLTBkyNfo1asjypQpiejoGNy/748VKzbg5MmL8nbx8Qno2vU73LlzHMWL83w1EVFWmLBKlMf27t2LH3/8UVR3+vRpuLm56Sgi+mTKlCnYt2+fvOzq6oozZ87oMKKCzcHYBh2cGuS4f0hSBK5HPBTV1bOrAmOJUW5DIy3o5lINFobGavVxNrbSUjRERERE+qFp0/oKda8+OylFRERE9Llhw/pqLalm8uScbx2dkpKCJUvWiFYBrFChDBo0qJPjMQuyR4+e4JtvxoiSLtzdy2H16rlo0sRLob2VlSWKFy+Gpk3rY/z47xAeHoH163fAzs5GpfkSEhLw5ZeDRMlvNjbWWLhwGr79tjeEDDtWWVlZwsXFGZ6e1TB4cB8kJydjz56jMDc3y+EjJsq/+Hot+CZPHoFSpYprZezAwPeYO3eFqM7Y2Bjbt69A165fiOqtrABHR3t4elbDyJH9MXjwRPz9d/qqqikpKZgwYRZOnNiulViJ9FVevg8HB4dg8uQ5ojpX16L499+tqFKlorzOwcEOpUoVR8eOrbF48Z+YNGm2/HtwWFgEJkz4Bbt2/ZnTh0xEVCgwYZWIiHTCycQOvYq1ynH/7e9OKNQ1tq+em5BIi/oVr41ipqodlCMiIiIqDARBwNBh/UR1oaHhuH79to4iKoAkQtqfvtCnWIiIKF+aPHmk1pJq5s37Kcd9Dx06gcWLxSflBwzomduQCiSZTIYhQyYjPj5BXletWiWcPr0DDg52Ko1hZ2eL778fqvKcs2Ytg7//U3nZxsYaJ05sQ506NVTqb2RkhN69O6k8H1FBwdcr5dbOnYdF//8AwPz5Pykkq2ZkZmaGTZuW4fHj57h9+768/vTpSwgKCoaLkt1aiAqivH4fnj17OeLi4uVlAwMD7N//lyhZNaPvvx+KN2+C8Pvvf8nr9u49htu376NWraoqzZsvCf/96Qt9ioWIVMKEVT339u1btGzZUitjW1lZ4ebNmwCA5cuXY8WKFdn00I65c+eia9euoroWLVrg3bt3orrHjx9rZL6KFcVfKLiKJlH+I5Wl4kr4fVGdi4kDylto54A9EREREVFGxYo5IzAwOMf9f/5lImrWFB+43rv3iML2ZkRERET6buPGXaKyRCJBv37ddRSNflu9egsuX/aRl62sLHHkyCaVky7Udf/+IyxaJE4m3rRpqcrJb0SFGV+vlFunT18SlW1tbTBiRL9MWosZGhpi0qTh6N17hLxOJpPhwoXr6NXrS43GSaSv8vJ9ODg4BGvWbBPVjRw5AJ6e1bLtO3v2JOzefVh+nFAmk+G33/6HvXvXaTxOIqKCQqLrAIiIiNTlG/UEkSmxojqurkpEREREeWngoK9w4+Zx9OjREaamJir3s7e3xZq1izFp8ihRfUREJH6btUTTYRIRERFpVWhoGA4fPiWqa926CVxdXXQUkf5KTU3F/Pl/iOpmzhyv1X+rBQtWISUlRV7u2LEVvvyyjdbmIyoo+HolTXj37r2o7OVVE0ZGRir3b9KknkJdbi6cJcpP8vp9+MCBE0hKSpKXBUHAmDEDVeprYWGOgQN7ieqOHTuHmJjYTHoQERFXWCUionznYpivqCxAQEO77K9wIyIisVu3HmPP7vMqtz99+hYSEpKU3mdnZ4WJk/poKjTKBT6vRHmnatVK2Lx1JaKjY/DvsTO4ceMOfH398PZtEKIioxAfnwArK0s4OTmiarXKaNmyMb7s1BaWlhaicaRSKUaP/AkfPnzMds5SpUvg22+/yvR+WzsbUblmrar49bcpmbafPm1etnPmV4JEgCDRnz3B9CkWIiIiTdm+fb/o5D4ADBjQU0fR6Lfjx8/j9ev0neUsLMwxdOg3WpsvPDwCe/YcFdWNHz9Ea/MRFSR8vZImxMbGicr29rZq9Ve2imRSUnJuQiLKN/L6ffjgwROicqNGdVCmTEmV+w8Y0AOzZ/8uLycmJuL48fPo1q2dxmLUJ8J//+kLfYqFiFTDhNV8yNzcHCVKlMj1OBYW6SfIHB0d4e7urlb/oKAgREZGiupcXFxgY2OTSQ/l1G1PRIVbdEoc7kY9EdVVtSoDe2NrHUVERJR/PXjwAgsX/q1y+ytXHuDKlQdK7ytZ0pmJjXqCzytR3rOyskSPnl+iR0/1t+VLTEzE8GGTsXv3IZXaFy9eDD9MHJF9w/94eLjDwyPz3/sFOWGViIiItG/jxp2isq2tDTp3bqujaPTbX3+Jf6d9+WVrWFiYa22+rVv3ISEhUV52dS2qdLU+IlLE1ytpQpEiDnjy5IW8HB4emUVrRWFhEQp1RYsWyW1YRPlCXr4PJyUl4fTpy6K6pk3rqzVG2bKl4Obmgrdvg+R1R46cLrAJq0REucWE1XzIw8MDW7Zs0eiYffr0QZ8+6p2InjJlCvbt2yeqGzNmDLp27arJ0IiIRK6GP0CKTCqqa2xfQzfBEBEREVGhJZPJcj3Gtas3MWL4FDx6FKCBiIiIiIjy1v37j3D79n1RXe/eX8LU1FRHEekvmUyGU6cuiepatmyk1TlPnrwgKrdo0RASiUSrcxIVBHy9kqZ4elbDlSs35eVr124jJSUFhoaqpWhcuuSjUNewYW2NxUekr/L6fTgg4DkSExNFdTl5rTVsWBs7dqRfkP7ggX+uYyMiKqiYsEpERPnKxTBfUdnCwBSeNhV1FA0RERERFVYL5q/A5cs30LZtMzRqVA/VqleGiYlJtv2Cg0Nw/N+z2LxpJy5fvpEHkRZiggBI9GhLMEGPYiEiItKAjKurAsDAgb10EIn+8/d/iqioaFFdtWqVROWIiEicP38Njx8/R3R0DGxtrVGkiANq1qyCqlXFbVXh4yM+jlq1qnjV/eTkZFy65IN79x4hNDQc5uZmKFLEARUqlIaXVy0YGRmpPSdRQcDXa+GSmJiEy5d98ODBY4SEhEIqTYWDgx0cHe3g6VkN5cuXzvHYffp0wvLl6+Xl8PBIrFmzDSNG9M+2r1QqxcKFq0R1TZrUQ7lyOY+HKL/I6/dhf/9nCnWVKpVXO253d3Gfx4+fqz1GfiEIAgQ9Os6lT7EQkWqYsEpERPnGm/hgvIwPEtV52XrASMKPM32XlCqFb+Q7PIsNRXhyPFKRChtDM9gamcHdygklzOx0HSJRodS/vzf69/fWdRikYXxeifJGSkoKzp+7gvPnrgAAjIyMUKFCGZQqXQLFijnDysoSRkZGiIuLQ2RkNEJCQnHP1w/v3r3P1bwXL1yDmUkJTTwEIiIiymcSExP/S6rxz5BUYw9Pz6ooX75MnsWSkpKCbdvEO7BVrlwBdevWzLMY8pOMyWhA2r8XAAQGvseUKXOxY8chJCcnK+3v4uKEQYN644cfhsLGxjrb+V6/fofg4BCl8yUkJGDOnBVYuXJjpttTW1paoEsXb8yYMQ5ly5bKdj6igoSv18KlatVWSElJyfR+FxcndO/eAd9/PwQlSriqNbaXVy106tQGBw6ckNf98MOvKFWqONq1a5Fpv8TERAwf/iNu3LgrrzMyMsLSpT+rNT9RfpXX78OPHj0RlQ0MDODqWlTtuIsXdxGVo6Nj8O5dEFxdXTLpQURUeDHDh4iI8o2Mq6sCQBOH6jqIhNTV+9YWSGWpmd7vaGyBlo7l8Y2bJ4qaZv/jkYiIiEjfJCcnw8/vMfz8Hus6FCIiIiqgPDxaZpNU44wePTrg+++Hqp1Uo65jx84oJFgNGNBTq3PmZ48ePRWVTUxMYG5uht27j2Do0MmZJqJ9EhT0AbNn/45VqzZj27blaNu2WTbzPVGos7e3xf37j/DVV6Pg5xeQZf+YmFhs2bIHf/99ALNm/YApU0Zm2Z6oIOHrtXDJ6nMVSHs+ly9fj9Wrt2D8+O/w228TYWioeorF2rULERDwQv48JyQkomPHAejRoz2++aYbateuBgcHOyQlJePVq7c4e/YKVqzYiMeP01d8NDIywtatv6NmTY+cPUiifCav34cDA4NFZRcXJxgYGKgdt7Lv3+/evWfCKhGREkxYJSoA4uPj4evriw8fPiAsLAxJSUmws7ODg4MDKleujKJF1b8CSB0vX77Es2fPEB4ejvDwcMhkMlhYWMDJyQllypRBqVKlcvSl7hOZTIZ3797h+fPnCAoKQkxMDJKTk2FlZQUbGxuUKFEClStXVusHIuU/UlkqroTfF9W5mhZBGXPtHnwnzcgqWRUAPibFYkfgXewJuoev3GpheKmGMBQkeRQdERERERVIEiHtT1/oUyxERJQvZZ9UE4zff/8Lq1ZtxoQJQ/Dbb5O0dsx048ZdorKBgQH69u2mlbkKgrCwCFHZysoCBw+eQO/eI5CamvVxs4zjdOw4EOvWLUS/ft1Vng8AQkJC0bnzJHz48FHl+VJSUvDTT/Pw/PlrrFkzX+V+RPkZX6+kTHJyMhYs+ANXr97EwYMbVFq1EQAcHe1x/vxufPfdRPlKqzKZDDt3HsbOnYez7V+rVlWsWjUHderUyE34RPlKXr8Px8bGicrW1lZqxZvez1KhLiYmTknL/E/4709f6FMsRKQaZncR5WPHjh3Drl274OPjg6SkpEzblS9fHm3btsXAgQNhaan4RSkn/P39sXnzZly5cgVBQUFZtrW2toaXlxe++OILtGrVCsbGxtmO//79e5w4cQJXr17FrVu3EBmZ9ZVSZmZmqFOnDvr3749GjRqp9Vgof/CNeoLIlFhRXWN7rq5a0KTIUrH5zU3cjwzCEo9OsDQ00XVIRERERERERET5SnJyMubPX4krV27i0KGNKifVqCo0NAyHD58S1Xl7N0PRok4anacgyXh8Oz4+AV99NUqedGFqaoLhw/uhe/f2qFixDMzNzRAYGIwzZ65g2bJ1ePgwfYXFlJQUDB06BR4eFVGrVlWl80VERCnUDR48ESEhofJy9+7t0b9/D9SuXQ12djYIDQ3HtWu3sW7d3zh27Kyo77p121GtWiWMGjUgp/8ERPkGX68Fn0QiQd26NdCuXQvUrl0NlSqVh4ODHUxMjBEeHonnz1/j/PlrWL/+Hzx58kLU9+LFG+jZcxiOHNms8kUhjo722LfvL1y8eB1r127Hzp2HszyvCwBlypTA//43C+3bt8zx4yTKr/L6fTgmRnz+2cwsZ+cmzcxMsx2biIjSMGGVKB96+PAhZsyYgfv372ffGMCTJ0/w5MkTbNu2DePGjUPv3r1zPPebN28wb948nD59GjKZTKU+UVFROHHiBE6cOIEKFSrg0KFDWbb/6quvcPv2bZXHB9JWmb1w4QIuXLiAmjVrYtmyZVpfWZby1sUwX1HZABI0tKumo2hIFRIIqGJVFA3tS6OSlTNKm9vDxsgUxoIBolIS8S4hErcj3+Lg+wd4HR8h6nsn6h2mPDyMZVW7cKVVIiIiIiIiIiq0PiXVtG/fErVrV1eSVPMK589fw19//a0kqeY6evQYiqNHt2h0pdXt2/crJNoMGNBTY+MXRJGR0aLy5yt5lSzphuPHt6FChTKiNmXKlESZMiUxYEAPjB49HX/+uVV+X2JiIvr1G4f7909BEBTXlMo4HwB58pupqQn+/nslOnVqK7rfxcUZXbp8gS5dvsDGjTvx3XeTIJVK5ff/8MOv+PLL1kq3uyUqSPh6Ldh++GEYhg/vi9KlSyi938nJEU5OjvDyqoWJE4dh9eot+P77X5GYmChvc/LkRcyatQyzZv2g8rwfP4bhxIkLuHLlZrbJqgDw/Plr9Ow5DP3798C0aWNQrBjPeVLhkdfvwxlXWDU1VUw8VQUTVomIVMcMEKJ85sKFC/j6669VTlb9XHh4OGbOnInffvtNreXyP7l27Rq6d++OU6dOqZVM+rnY2Oy/lN26dSvH4wPAnTt30K1bN/j7++d4DNIv0SlxuBv1RFRX1bosbI00s2IwaV5fN0/srTMQ62v2xrcl66GBfSm4mFrD3MAYhhID2Bubo6q1C/oXr4NdtQdgUrkWMBYMRGNcj3iNda+u6egREBEREVG+JxH074+IiEgNEycOx9Onl3H16iFMmzYO3t7NUbKkGywtLWBkZPRfQo0nJk8eCX//C1i5cjZMTMQrQp08eQGzZi3VaFwbN+4UlR0c7PDll200OkdBk9nxeHNzM5w4sV0h6eJzhoaGWLVqLrp08RbVP3wYgAMHjqs1HwCsW7dQIfktowEDemLRoumiuqSkJCxZsjbLfkQFAV+vBduCBVMzTVbNSCKRYMSI/jh6dDOMjIxE9y1duhYfPnxUaZy//96P8uUbY/bs3/H8+Wt5faVK5dG3bzeMGzcYw4f3Q8eOrWBvbyu/Pz4+AatXb0G1aq3x779nlYxMVDDl9fswqU/Qw/+IKH/hCqtE+ci1a9cwfPhwpKSkKNxXqVIlNG/eHK6urjA1NUVISAhu3LiBS5cuKVypt2XLFqSmpmLGjBkqz33u3DmMHDlS6dx2dnZo0KABPDw8YG9vD2NjY0RHRyMwMBAPHjzAnTt3VEpUVcbY2BgeHh4oV64cSpcuDWtra1hYWEAqlSI6OhrPnz/HrVu34OfnJ+r38eNHjBkzBnv37oWlpX4kNYaFheV6jPDwcA1Ekv9cDX+AFJlUVNfEvoZugiGVjCnTROW2EkFAj2LVUdrcHqPv70WKLP2H6Pa3t9GzWA3YG5trI0wiIiIiIiIiyucK8jG3BQumqdw2LalmACpVKo+2bb9GcnKy/L4lS9Zg1KiBcHJyzHVM9+8/wu3b4sUU+vTpDGNj41yPXZBZWloorZ8yZSTKly+t0hgrV87GkSNnRMf7167djs6dvRXaZjZfy5aN8NVXXVSab8yYQdi4cSd8fR/K6zZs2IHFi6fDwMAgi55E+Rtfr5RR8+YNMHv2JEyaNFteFxsbh9Wrt2LGjHFZ9l2+fAPGjhWfj23TpgkWLJiGatUqKbRPSUnB338fwA8//CpfaTcsLAKdOw/GkSOb0LJlo9w/ICI9l9fvwxYW4nOQCQkJakSbLj5esV9mj4WIqLBjwipRPhEeHo5JkyYpJIwWK1YMv/zyC5o0UUwOGzhwIN6/f4+ZM2fi3Llzovu2bduGBg0aoFWrVtnO/erVK0ycOFFhbkdHR4waNQo9evTIckuppKQkXLx4ETt27MDTp0+znc/MzAze3t5o37496tSpo9Ky+0+ePMHcuXNx+fJlUdxLlixRKzFXm+rXr6/rEPKti2G+orKlgRlqWlfQUTSkLbVti2NEqYb4/cVFeV18ajL2BN3DdyW9dBgZEREREREREekrHnMTa968IebMmYKJE3+V16Ul1WzBjBnjcz1+xtVVAWDgwF65HregU5asYGBggCFDvlZ5jKJFndC1qzf++eegvO7y5ZuQSqUKCWmWlsov/h4+vJ/K8wmCgGHD+mL48B/lddHRMbh9+z7q1Kmh8jhE+Q1fr6TM6NEDsWzZOgQGBsvrjh8/l2XC6uXLPhg//mdR3dCh3+CPP+Yo3ZYcSFsdsm/fbmjevAEaNeqC16/fAUg719qv31g8eHAadna2uX04RHot79+HxfPFxyeqGfGnfkxYJSJSFRNWifKJJUuWIDg4WFTn5uaGbdu2oWjRopn2K1q0KFavXo1Jkybh4MGDovumT5+ORo0aZZsQOnHiRERFRYnqypcvj7Vr18LFxSXb2I2NjdGyZUu0bNkSb9++zbb9xYsXYWVllW27jPGsW7cO06ZNw549e+T1+/btw9ixY2FjY6PWeKQ/3sQH42V8kKiuvl1VGEp4VXBB1Mu1Bv5+dxshSemrMl8Nf8mE1VxKSkrCgwcPdB2GRrm4uKj0GUREpA/4PkxEREREeWn06IFYunQtAgPfy+v+/fdsrhNWU1JSsG3bPlFd1aqVUKtW1VyNWxhkXLkLADw8Kqq96m3z5g1FiRdRUdF4+DAAVauKV+lTlhwhCAKaN1cvwbtFi4YKddeu3WEC3H/4W69g4uuVlDExMUH79q2wdu02ed2NG3cRHx8PMzMzpX0mTPhFtLV5jRpVsHz5r5kmq37Ozc0FO3asQv36X8rrgoI+YMWKjZg+fVzOH0gBw/fhgimv34czzhcVFa3WPOn9YhTqMrsogYiosGPCaj704MEDdOrUKdfjLF26FGXKlNFARHlDE485vwoLC8OBAwdEdQYGBlixYkWWyaqfCIKAuXPnwt/fHwEBAQrj9uqV+RXwly5dgq+veHVLOzs7rF+/Hk5OTmo+krQk2+yom6z6iUQiwcyZM3HlyhUEBaUlOMbFxeHw4cP4+mvVr7gi/ZJxdVUAaGJfXQeRUF4wlhiikX0Z7HufvrXcw6j3SJCmwNSAX1tyKjExETdv3tR1GBpVq1atQn/QhojyD74PE+mIREj70xf6FAsRERVoJiYm6NChJdasUT2pRhXHjp1BcHCIqG7AgB45Hq8wcXNT/O7s4VFR7XGU9QkO/oiqGXKGlc1XrJiz2qvylS9fGiYmJkhMTF9pLOP/A4UZf+sVTHy9Umbq168lSliVSqUIDv6IUqWKK7S9e9cPPj7i81uTJg3PcsfKjOrVq4nWrRvj5Mn0Xek2b97NhNXP8H24YMrr9+FixZxF5aCgD0pXYs3OmzeBCnXFimWfy5EfCYKgUvJ9XtGnWIhINcz8yIfi4uLg7++f63E+/8GSH2jiMedXu3fvVni+evXqhUqVKmXSQ5GhoSGmT5+Ovn37iuq3bt2aZcLq2rVrFeqmT5+eo2TVvGBiYgJvb29s2LBBXnf79m0mrOZTUlkqroTfF9UVN3VGKfPC/UOtoKtq7SJKWJVChrDkWBQz4ErJRERERERERESqqF/fU5SwmlVSjao2btwlKhsaGuKbb7rleLzCpFKlcgp1trbqH+uys1PsExYWodJ8yvqqwtbWWpT0pmw+ooKEr1fKjLLVHUNCQpV+tp47d1VUFgQBbds2VXtOb+/mooTVZ89e4cOHj2qvNEmUn+T1+7C7u3g+qVSKd+/eo0QJV7Xme/1anLBqZWWpNPmWiIiYsEqUL1y+fFmh7quvvlJ7nLp166J8+fJ48uSJvC4gIAAfP36Eo6PiD5uYmBj4+PiI6lxdXeHt7a323HmpZMmSovLdu3d1E0gGV69ezb5RNsLDw9GuXTsNRJM/+EY9QWRKrKiuMVdXLfDsjRW3xwhPjkcxUyasEqnjl583YOfOswCAOXOHoFOnRnk6/8OHL9GzxwzIZEAtzwrYsmVans5fUPF5JdKdadMnoEfPjmm3p87FoYMndByRZrm7l8c/O/+EIAi4feseBg4Yq+uQiIiIVMJjbsqpk1SjitDQMBw+fEpU165dCybMqKhy5QoKdTKZTO1xlPVRtqKUnZ0tihZ1wvv3H3I1n7J+XMGKCjq+Xikzqj6nAPDy5VtR2dbWWu1VcwGgdGnFz+13797z85cKtLx+H1aWIPvo0RO1E1YfP34qKlesmH92OyYiymtMWCXSc1KpFPfu3RPVlSlTBuXLl8/ReN7e3qKEVSBtBdI2bdootL158yakUqmormPHjmovf59b4eHhuHXrFh4/foznz58jMjISsbGxiI+PV/pFMzIyUlR+//59XoWaJXt7e12HkO9cDBNvl2IgSNDQvmomramgUPoDUgdxEOVnfn4vsHv3OQBAxYrF0bFjgyzbx8UlwM/vJfz8XsDvwQs8ePACb94E49PL0cXFAadOL1UrhsqVS+GLL7xw9Og13L4VgMOHrqBDNnFQ1vi8EulOpUoV0K17ewDA48fPcPjQySzbm5mZonLlCqhcpSKqVKmIKh7uKF68mPygeFBgMLzb9lYrhk6dvDHrt8k5ewCf+XbgONy86atQ7+//BP8eO4Mv2rVELc9qaNe+FY4eOaVkhHxEENL+9IU+xUJEVIDwmJty6iTVqGL79v1ISkoS1Q0cmPnOXSRWrlwpWFiYIzY2Tl4XERGZRQ/lwsMV+zg6Kn8NVK9eSZQAp6xvdmQyGSIiolSaj6ig4OuVMvP56rWfFCnioLRtXFy8qGxmZpqjOc3NzRTqEhOTlLQkKjjy+n24QoUyMDExEe14e+XKLbRt20yt+S5fvikqe3i4q9U/PxGgX+du9SkWfZWYmIjbt2/j+fPniIqKgpGREYoWLYrq1aujePGc78KhzOvXr3Hv3j28f/8eycnJsLa2RpkyZVCrVi2YmJhobJ68fEykeUxYzYfq1q2LLVu26DqMPPf48WONjFOxYkWNjJNXXrx4gbi4OFGdh4dHjserWlUx2c/Pz09pwuqdO3cU6mrVqpXjudV19epVbNq0CZcuXUJycnKOx0lJSUFsbCwsLCw0GB1pW3RKHO5GiZOrq1uVh7Uhn8eCLiw5TqHOzkhx1VVSnZWVFYYMGaLrMCgPzZu7FampaScnR4/uBolEorRdQMAbfD9hJV6+DJK316SRo7ri33+vIzVVhsWLd6B1m9owMTHW+DyFBZ/X/Ivvw/nf5Cmj5K+5lSvWZ7qqQ7nypbFw0UyUKlU809eorkXHxGZ63x9/bERb7+aQSCQYP34oTp28oJCYQkRERPlDcPBHhbrMkmpUsXHjToWx2rdvmePxChsDAwN4ezfDnj1H5XX37/urPY6yPsWKOStt2759Kxw/fl5eDgwMRlhYOOzt7VSeLyDgucL3wczmK4z4W69g4uuVMnP16m1R2cDAAE5Oyj9bM25FHhoaAZlMpvbFIyEhYQp1Dg6q/39R0PF9uGDK6/dhY2NjtGzZEEePnpHXnT+v3i4Oz5+/wps3gaI6flemrAQHB+PevXvw9fXFvXv38ODBA8TGph+3dXV1xZkzZ7IYQTVhYWFYsWIF9u3bp5B39EmVKlUwYsQItGrVKldznTp1Cn/88Qf8/PyU3m9ubo6uXbti5MiRubrwNC8fE2kPE1aJsjF16lQ8ePBArT5jxoxBy5aa+QISHh6uUFe2bNkcj6esr7I5ACA0NFShrkIFxSX4NS0mJgbTpk3DsWPHNDomE1bzl6vhD5AiE6/w28Shhm6CoTx1LypIVDaAwIRVIjVcvOCL27fTEv7LlXNFs+Y1M20bERGD588DM70/t0qVKoqWrTxx8sRNfPgQjn/+OYP+/b21Nl9BxueVSHcaNqqLmrXSLvx7+vQlzp+7kmlbWxtrlClTUitxxMTGKhz4zo6JsTGcnNO3CXz+/BUe+z/NtP3rV29x5vQltGrdBE7OjujZ60ts3bI7xzETERGR7ly9ektUziqpJjv37z/C7dv3RXVff90FRkZGOY6vMOrc2VuUeOHnF4D37z+gaFEnlcc4c+ayqOzk5IiKFZWfL+jcuS3Gjp0hutjq1KlL6Nmzo8rznT59SaGuceO6Kvcnyq/4eqWM4uPjceTIaVFdnTrVYWamuAIqABQtWkRUTkxMhK/vQ9SoUUWtea9dEyfJCsL/2bvvsKauNw7g34S9hyiCKA7cIIoL9957a62r7j1rW2uddbZWrVtbd+veuOqodaDiHjgRtSzZe6/fH/wavCSBJAQS4PvxyfPkHO455w3HXODmveeIpPomKo4K+zzcs2dHQcLqjRte8PX9qPB1vj17hNfPDAwM0KlTK4VjpZLhwYMH2LVrF548eYKQkJC8G+TT3bt3MX36dLn5QP/x9vbG5MmT0bt3byxduhT6+sotUJKSkoJ58+bhzJkzuR6XkJCA/fv349y5c/j111/RsGFDpcYBCu81UcHTzuU+iLTIv//+i1evXin1yLklfX7I6svMzEzl/iwsLKTq5MUrq97c3FzlsRURFxeH0aNHqzVZFUC+VmglzbgRIdym1EzXGK7mThqKhgpLUnoabkb4CupqmZWFoQ7vsSFS1KZNJyTPR4zsrNRd+1ZWZmjW3AXjJ/RExYpl1RLPiBFdJM9/2+HBLatUxHkl0pxJk0ZJnu/bcziXI6VFRkTh1k0vbN+2Dx8++OUrjiuXb6B716FKPfbvF14sP3H8nJzes+397DWOHv1Fkb6YJxKLtO5BRERUGBITE+HhcVlQl1tSTV5yrq4KACNHDlSpr5Kse/d2MDXNXlQhIyMDW7fuV7h9QEAQTp68KKhr166Z3OMdHOzQvLnwQ+AtW/YqPF5WfMLd/uztbVGrVsEvakGkaXy/Uk7r1v2OT5+EyUW5bRfetGkDqbq9e5W7ITQhIRFHj54V1NWtWxtmZqZK9UNUFBX2ebhXr46Ca2CZmZnYuHG3QmMlJCRi586DgrouXVoL4i9uRFr4ryh49uwZLl26VCjJqvfv38e4ceOkEjvNzc1Rq1YtlCtXDjo6OoKvnTx5ErNnz5a7u5gsGRkZmDFjhlSyqo6ODhwcHFCzZk2p/KaIiAiMHTtW5o7P2vCaqHAwYZVIy32+7Pd/jI1VX2lQ1kVJWWMAWcmj6hxbEStWrMDjx4+l6itWrIiRI0di3bp1OHLkCG7cuIEHDx7g2bNneP36teCxYsWKAo2RCp5fYjA+JApX2Wxm5QJdkY6cFlRcHAh4iPAU4dL9TawLZpUyouLo/v3XePYsK+nb1MwIXbq453p8qVLmGDO2O9atm4pLl3/BzVubsH3715g2rT9sSluqJaZ69arCyakcACAiIgZnzshfmZBk47wSaY6bWx04u9QAAMTGxuPChdy3YQqPiMLvv/2BWTMXoHPHwWjdqg8mTfwGmzbuRJiMbfwKWp++XSXP09LSceb0xVyOzvLkiTd8fD4AAKxLWaF79w4FFR4REREVkHXrfpNKquncuY1KfaWlpeGPP04I6urVc4arq3IrxBFgYWGOmTPHCup++mkLXr58m2fbzMxMTJw4T2phhqlTv8q13aJFswXlf/65IzMBWZY1a7bj+fPXgropU0bJOZqoeOH7tfj59CkE6enpeR8ow19//YOFC9cI6oyNjTB+/FC5bRo2dEXp0sKVzbdu3YdHjxTf1fP771chODhUUNeli2o/z4mKmsI+D9valsbYsV8I6jZu3K3Qe3b+/NUICPgkKYtEIsyfPz3PdkSfU2ceTnR0NGbOnImkpCRJXbly5bBp0yZ4eXnhxIkTuHr1Kq5evYpBgwYJ2v7111/YvXu3wmP99ttvuHJFuAL54MGD8ffff+PKlSs4efIkvLy8sHHjRtjb20uOSUxMxIwZMxAbG6t1r4kKBxNWibScrG3sExISZBypmMTERIXGAABTU+k79PIzdl5ev36NY8eOCeqMjY3x008/4cKFC/juu+/QpUsX1KlTB2XKlIGpqanM1X4+/yFFRVPO1VUBoIV13cIPhJQWlhKP9MwMldreifiIbR9vC+oMxbroY1dHHaERlQj792cnInXp3BhGRga5Hl+lSjnMnDkQHTo2hL29Ta7H5kefvi2zY9z3V4GNU1xxXok0Z+iX/STPL164iqSk5FyPf+/7Eb+u/w1XLt9AUFBwQYeXq7p1nVGpUgVJ+drftxAZqdhuICdPZK/E+sVn3wMiIiIqHPlNqlmw4GdBXVZSzZcq9Xf+/FWpZBmurqq6OXPGCxKYEhOT0KnTUHh7v5bbJiUlBaNHz5FaNbdz59Zwd3fLdbw2bZqic+fWgroJE77DkSMeubbbvv0PfPedcGGIMmVsMHnyiFzbERUnfL8WLwcPnkbt2m2xa9chxMXJXsgnp7S0NKxduwM9eoxCWlqa4GszZ47NdWtysViM2bPHC+qSkpLRvfsIeHrez3Xc9PR0zJu3EuvX/y6oNzU1wbRpuSc+ExUnhX0e/v77qTA2zl78Ky0tDb17j8aLF2/ktlm7dofUe7Vv3y5wc3PJdSwq2UxMTNCoUSOMHj0a69evx9WrV7F161a19f/7778LVnF1cHDAgQMH0L59e8HufWXLlsWSJUswc+ZMQftNmzYptKt0ZGSkVNyzZ8/G4sWLYWtrK6kTi8Xo0KEDDh48iHLlyknqP336hF27dmnVa6LCw4RVojzs27dPagXPvB59+/ZV2/gWFhZSdYreZSBLTEyMQmMAgKWlpULt1eXcuXNSS3GvWrUKPXv2VGrbW/6gKdrSMzPgGflMUFfRyA4VjGzltCBt8lfIawy8vxenP3kjIV2x7aHTMjPwp/9DzPQ+KZXs+oVDfdjoF98tM4jUKSYmHtf+zt4+o0PHhrkcXbg6fhbL27f+8PZ+r8FoihbOK5HmmJmZolXrppLy5UvXNRiN8j5fXRUAjh87K+dIaZ+/1qpVK6FmzSK6jaRYpH0PIiIiBRw8eAq1arVWIalmO7p3HyGVVDNr1rhck2pys3v3EUFZX18fQ4f2Uakvyvodc+tWYWKZv38Q6tfvismTv8e1a7fx6VMIoqNj8OqVDzZt2g0Xl/ZSqyza2ZXBzp3C1f7k2bRpGSwtsz8DSElJwaBBE9Gz5ygcP34e//4bgNjYOHz44IdDh06jffvBmDDhW2RkZF+n09HRwZ9/buQ21FSi8P1a/Lx544vRo+fA1rYu+vUbizVrtuHq1Vt49+4DwsIiEBcXDz+/QPzzz20sXrwWVau2wOzZS6RWaezYsSUWLJiR53hTp45EzZpVBXVBQSFo2bIfBg6cgKNHz+L9+38RGxuHsLAIPHr0HGvX7kCtWm2wcuUmqf6WLJmDMmUK7uZ0Im1T2OfhsmXLYOXKeYI6P79ANGnSC3PnLsODB08RERGJf/8NgIfHZXTuPBSzZy8R5DdYW1tizZoF+XjVRYMIWSvJas1D098QBbVt2xZnz57F/fv3sW/fPsydOxedO3cWJHHmV0REBPbt2yeo+/HHHwUJpDmNHz8eDRtmf94TGxuLnTt35jnWb7/9JtjNuWHDhhg7dqzc421tbbFs2TJB3e7duxEZGZnrOIX5mqjw6Go6ACLKnbW1tVTdu3fvVO7Px8dHqs7KykrmsTY20n/0vH79GnZ2diqPnxtPT+FWslWrVkXHjh2V7sfPz09dIZEGPIl5i+g04YX4FtauGoqGVPFvYiSWvvkLq32uoolVRbha2KO6SWnYGZrDVNcA+mIdxKQmIyApGg+j/XDm0wsEJUsnw7tbOWJshcYaeAVERdPFi15ITc1agcfUzAju7rU0HFE2e3sb1KpVES9efAAAnPW4jdq1K2k2qCKC80qkOR07toaeXtZlk9jYeNy9+1DDESnO2NgInT7b9vdTUAg8Pe8p3D4oKBgvX7xBzVpZiardurXHy5fyV5MgIiIi9XvzxhdffTULkyfPQ+fObdCsWQPUq+cMR0cHWFiYw9DQAJGRUfD1/RfXrt3Grl2H8PGjv1Q/HTu2woIFM2WMkLfw8Aip1am6d2+PUqWkr1mT4vr06YLVq7/H3LnZH9ampKRgy5a92LJlb57tbWysceLEbwonIVeqVAEnTuxAt24jkJCQvQObh8dlqfmVRVdXF5s2LUPbts0UGo+oOOH7tXhKTEzCiRMXcOLEBaXbtm3bDEeObIOenl6exxoZGeHcub1o1qw3AgOzd2HJyMjA0aNncfSo4jeWTp48EjNmjFE6XqKirrDPw1OmjMSLF2+wdWt2clxsbBx+/nkrfv459xUwjYwMcezYdlSooL7kQypeKlSokPdB+XT27FnBrskNGzZEkyZNcm0jEokwefJkjBw5UlJ37NgxzJgxQ+7CchkZGTh+/LigbsqUKXkuRNekSRM0aNAA9+9nrTYeHx+P8+fP44svvtD4a6LCxRVWibRcxYoVYWxsLKh7/vy5yv09e/ZMqs7Z2VnmsXXr1pWqe/iw4D6kDQoKEpTr16+vUj+PHz9WQzSkKTcingjKuiIdNLGS/X+UtFtyRhquhftgve91THp2DH3u7UKH21vR6tYm9PD6DROeHsH2j3dkJqs2sCyPlTW7Q1eso4HIiYqma9ceS57Xr18dOjra9f5p3Lim5Pm1a49yOZI+x3kl0pyWrbMvej18+FSwYo2269KlHYyMDCXlU6cuSO1mkRcvr+z39OffCyIiIipcWUk15zFnzlK0azcITk7NULq0C8zMqqFChUZo3bo/Fi1aIzNZtW3bZjh6dLtCSTWy/PnnSaSkCHfQGTVqoEp9kdCcOROwd+96pVdAdHNzwd27Z9CoUT2l2rVq1QTXrx9DlSqOSrWztS2Ns2f3YOxY+R8gExV3fL8SkHVj6MqV8/DXX38q9X/B0dEBDx6cR9eubVUed+vWldiwYalK7YmKg8I+D2/atAyLFs1W6lp8+fL2uHr1MFq14jU00qwrV64Iyv3791eonbu7OxwcHCTl0NDQXPNuHj58iIiICEm5fPnyaNxYsYWocsaUM+acCus1UeFiwiqRltPR0UGdOnUEdb6+vnj79q1K/V28eFGqrl492b+k1a9fH7q6woWYPTw8kJ6ertLYeYmKihKULS0tle7j9evX+VqBljQrNi0Bj2OE/7frmVeDma6xnBZU3BiKdTG1UnNscukHE119TYdDVGSkp6fj7t0XknL9+tU1GI1sn8f08WMwAgJCNRhN0cB5JdIcsVgsuJj98MFTDUajvD59u0qeZ2Rk4MTxc0r38eCz1+zo6AB7e/lbLBEREZF2MTY2wqpV3+PSpYP52hI653aqZcuWQefPVnGn/Pnyy754/fofTJ8+GlZWFnKPE4vFaNy4Hv78cyPu3TuLSpVUW5nJzc0Fz55dxs8//5BnIlyVKo5Yvvxb+PjcRIcOLVUaj6g44fu16Bs0qAc2bVqGAQO6w9HRIe8GyJpPV9daWLXqe/j5eWHu3IkQi5VPr7C1LQ0Pjz24fPkg+vfvBhOTvD/zqlSpAhYtmo13725h3LihSo9JVNwU5nlYJBJhwYIZePDgPAYM6A59ffmfV9rZlcHChbPg7X0VjRsrlxhLpG7x8fGSlUv/06yZYquui0QiNG3aVFB37do1ucf/888/gnLTpk0VXrk05zh3794VrKD6ucJ8TVS4dPM+hIg0rXnz5rhz546g7uDBg/jhhx+U6uf+/ft480a4jWP16tVhY2Mj83hTU1O4u7vj5s2bkrqAgACcP38e3bt3V2psRRgZGSE1NVVSjoyMVLqP3bt3qzEiKmx3Ip8jLVOYEN3C2lVD0ZAqOpauBn2xDh5E+cE7Nljm6qk5iSFCFRMbdClTA73KOsNczzDPNkQk9OaNPxITkiXl6tULflsRZdWoKby4/uSxD8qVK62haIoGziuR5lStVhnGxkaS8pvXReemuCpOFeFSJ3v14zu3HyAoKDiXFrK9fuUjKNdxrS3YwrBIEIkAsRZt8cTtpoiISEGDBvWEgYE+/v7bE15ej2WunpqTWCyGi0sNDB3aF2PGDIGVlWW+Ynj+/BUePhTu1jV0aB+pBQ4of8qWLYO1axfh559/wP37T+Ht/RohIeHIzMyEjY017OzKoGnT+rC2tlLLeIaGhpg1axxmzRqHV6988OjRcwQEfEJycgqsrCxQunQpNGhQR+UkO6LijO/Xos3OzhYTJw7HxInDAQBRUdF49eod/PwC8elTKOLjE5CWlgZzczNYWVnAwcEODRrUydeNHzm1bdsMbds2Q3p6Op49e4UXL94gIiIaMTGx0NPTg6WlOcqWLY2GDV0V3r6cqCQp7PNwnTo1cejQFsTGxsHT8z7evv2A6OgY6OjowNbWBq6utVCvnnOJ3F5c9P+HttCmWDTJx8dHkG/j4OCA0qUV/7zGzc0Nhw9n37T48uVLucfm/Jqbm5vC49ja2qJcuXIICAgAAKSmpsLHx0dqIT+gcF8TFS5eWSAqAvr164cNGzYgOTk7YeHgwYMYMGAAatSooVAfaWlpWLpUeruIYcOG5dpu7NixgoRVAPjxxx/RqFEjlCmj3j+WSpcujZiY7OQ2T09PZGRkKHy3oqenJ06cOKHWmKhwdSjdCB1KN9J0GJQPNgam6G/viv72WYnGsWlJ+JAQieDkWISnxCMxPRXpmZkw0dWHua4ByhiYoaapLVdTJcqnly8/CMpVq5bTTCC5sLMrBVMzI8TFJgIAvL0/oGs3bo+TG84rkebUrFFVUPbxea+hSJTXt283Qfn48bMq9fPpUwhiY+NhZmYCAKhdqzounL+a7/iIiIgob1lJNSMwceIIAP8l1fjkkVTjqtakGmfnGsjMDFBbf5Q7HR0dNG5cr1BX5qpRwwk1ajgV2nhExQXfr8WDpaUF3N3d4O6ueIKNuujo6KBu3dqoW7d2oY9NVBwU9nnYzMwUnTq1RqdOhTIckcpy7kTs5KTc7w5VqlTJtb/P+fr65to2L05OTpKE1f/6k5WwWpiviQoXE1aJigBra2v07t0bhw4dktSlpaVh2rRp2L9/f56Jo5mZmZg/fz5evXolqC9VqhR69uyZa1t3d3c0aNBAsMx2ZGQkRo8ejR07dqBs2bJKvRZ/f384OMjeaqNBgwaCHxB+fn44cOAAhg7Ne6sLb29vzJo1C5mZmUrFQ0QFy0zXEC7mdnCBnaZDISrWPn7MXvFOV1eM0qUtNRdMLsraWsMnNusP0I//ftJwNNqP80qkORUcsxPE09LSERoarsFoFKerq4sePTpKylGR0fj76i2V+wsODpUkrJZ31L6keSIiopIiK6mmPtzd62s6FCIiIiIiIq2nym6+slhbW6uln8Lw/r1w0QVlc3ns7ISf5wcGBiI5ORkGBgaC+qSkJAQGBubaNi85Y8sZu7z6gnpNVPiYsEpURMyaNQvXrl1DcHB24sLHjx8xZMgQLF26FE2bNpXZLjg4GAsXLsTff/8t9bUlS5YodCJevXo1+vbti6ioKEndmzdv0K9fP0ybNg39+vXLdSuolJQU3Lp1C4cOHcLbt29x5coVmcd16dJFkJQLAMuXLwcAfPHFFzKX009PT8fBgwfxyy+/IC4uDgBgamoqeU5ERFQSBAVmJ1KVKmWh8Orkha2MrRV8fLISGz8FRWg4Gu3HeSXSHDs7W8nz8LCIInNjXNt2zWFhaS4pnzlzCWlpaSr3FxIcCienigAAu6K4HaEYgFiLNgXTztM4ERERERERERGRwkQikczcDU2RFUvXrl3V0vfr16/V0k9hCA8XLrqgbHKnjY0NdHV1JdeTMzIyEBUVBVtbW8FxkZGRguvlenp6KFWqlFJj5ewzZ+zy6gvqNVHhY8JqEfT8+XP06tVLLX1NmzYN7dq1U0tfVLAsLS2xevVqjB49WvCBo7+/P0aNGoXatWujTZs2KFeuHAwMDBAaGop79+7hxo0bSE5Olupv6NChaN++vUJjlytXDj/99BMmTZqE1NRUSX1YWBgWLFiAdevWoWnTpnB2doaVlRUMDAwQGxuLoKAgvHjxAg8ePEBsbKykL3maNGmChg0b4t69e5K6tLQ0LFmyBHv37kWHDh3g5OQEAwMDRERESJJfQ0JCJMfb2Nhg1KhR+OmnnxR6bURERMVBbFyC5LmJiZEGI8mdiYmh5HlMTLwGIykaOK9EmmP62Xa68QkJuRypXfr0EV6IPX7cI1/9JSQkSp6bmZvlqy+SzdfXV+4F2Zysra2VvvhLRERERERERERExV9CjuvYRkbKfa4kEolgYGAgyEeKj5f+zCfnOIaGhkonMBsbG+fap7z6gnpNVPiYsFoEJSQkSG3trqro6Gi19EOFw93dHZs3b8aMGTOkTsze3t7w9vZWqJ9hw4Zh3rx5So3dsmVL/P7775g2bZpgpVUAiIiIgIeHBzw88vdhKJC1muuAAQMQFhYmqP/w4QN27NiRa1tTU1Ns27YNb968yXccRERERUlSUorkuYGBngYjyZ2hgb7k+ecxk2ycVyLNMfxsJ4qU5KLx/9rOzhbuTbK3CX7y2Bu+7z7mq8+kpOybHw25TVKBGDp0qMLHTpkyBVOnTi3AaIiIiIiIiIiIiKgoyplDpMq294aGhoKETlmJpDkTPlUZJ2cbRRNWC+o1UeHjZmRERUyrVq2wf/9+ODs7K93W0tISixYtwvz581XaUrZx48Y4cuQIWrdurXTb/+S1Goy9vT327NmDSpUqKdVvpUqVcPDgQZW+L0REREWdrq6O5HlaWroGI8nd57F9HjPJxnkl0pzP77jW0S0a9/r27tNF8HfeiePn8t2n8DyUlsuRWkos1r4HERERERERERFRESbSwn8EqZ2X9fSUXwhFX19fUE5KSpI6JiVFuMBDQY0DFN5rosJXND51ISKB2rVr4+jRozh//jyOHDmC+/fvS/1Q+JyTkxM6deqEUaNGwcwsf9s4VqhQAdu2bcOTJ0+wb98+3Lp1CxEREbm2KVWqFJo2bYru3bujZcuWeY7h5OSEY8eOYd++fdi/fz9CQ0PlHlulShUMGTIEgwYNkvpBQ0REVFIYG2dvyZ6cnKrBSHKX9NkqhUZGXKkvL5xXIs1JTEyUPDcw0P6/M0QiEXr16iwpJyQk4sKFq/nu18Aw+z2dyAt5REREREREREREVAScO3cOVlZWmg6jUOVcfTQ1VfnPlXLmHcla0TRnXk5BjSOrviDHosLFhFUt5+DggNevX2s6DJlWrlyJlStXFkjfV6/m/4M1eTT9/ezbty/69u2b735EIhG6du2Krl27IiEhAU+ePEFISAgiIiKQmpoKKysrWFtbo1atWrCzs1ND5EKurq5wdXVFZmYmXr16hX///RcRERGIjo6Gjo4OTExMYGdnhypVqqB8+fIQiZS7q8XExAQTJkzA+PHj8fr1a7x8+RKRkZFISkqCiYkJypUrhxo1asDBwUGqrarf44L8P01ERFSQbEpZSJ5HRMZoMJLcRUbESp7blLbUXCBFBOeVSHPCwiIlz62sLDUXiIKaNGkAO3tbSfnC+atITMx/gqn1Z689LDT3GxVJNX/88QcsLCzyPhCAtbV1AUdDRERERERERERU9P2XL1OSGBsbC8o5VydVRM7VR3P2CWTl8uR3nJxtZI0jq76gXhMVPiasEhUDxsbGaNKkiUbGFolEqFmzJmrWrFlg/deoUQM1atQokP6JiIiKg3IONpLncbGJSEhIEqzOqS2Cg7MTwMrZ2+RyJAGcVyJNCggIkjw3MzOBkZGhWhJAC0q//t0F5ePHzqql3zJlst/TgYGf1NJnoRKLsh7aQkYslStXLnEXz4mIiIiIiIiIqCgTQQQtuuamVbFoTs5EzM93EVNEZmamVEJozuRUWeMkJSUhMzNTqUXsEhIScu1TXn1BvSYqfGJNB0BERERERPlTrWp5QfnDB+1LKkpKSkFwcPbqfFWrSa+STkKcVyLN8Xn7XlB2dCwv50jNs7S0QKvWTSVlH58PePbsZb77NTAwgG3Z0pLy27e++e6TiIiIiIiIiIiIiNSvVKlSgvKnT8p9phQWFoa0tDRJWSwWw8rKSuo4KysrQXJqamoqwsPDlRorODhYUM4Zu7z6gnpNVPiYsEpEREREVMTVdq4kKL9546ehSOR7+9YfGRmZkrKzc2UNRlM0cF6JNMfb+7WgXK2a9v7f7t6jA/T0sjfQUdfqqk5OFSEWZ1828n7+Si39EhEREREREREREZF6Vaok/EwpKChIzpGy5Tze3t4eBgYGUscZGhrC3t5eUBcYGJivsSpXln39vbBeExU+JqwSERERERVxVlZmcHIqJyk/e6p9q+A9f54dk4GhHurU0d7kL23BeSXSnKioaPj4fJCUnV1qai6YPPTp203yPCUlFR5n/lJLv87ONSTPk5KS8exZEUxYFYu070FERERERERERFSEiUTa9yDppE8fHx+l2r979y7X/j6XM5E0Z1t1jVWYr4kKFxNWiYiIiIiKgZYtXSXPvbzyvxW0ut29+0LyvFGjmjAw0NdgNEUH55VIc27euCN53rBRXc0Fkos6dWrByamipPz31ZuIjo5RS9+NGrtJnt+79xgpKSlq6ZeIiIiIiIiIiIiI1MvJyQl6enqSckBAAEJCQhRu//DhQ0G5Zk35izjk/NqjR48UHickJAQBAQGSsp6eHqpUqSLz2MJ8TVS4dPM+hIiIiIiItF37Dg2wc+c5AICvbyACA8Ngb2+TZ7u5X2/B06fSdz4Gh0RKnoeERKJzpzky21+4+HOeY6Snp+Punexky44dG+bZhrJwXok05/Kl6xg5ajAAoHJlR9jZ2SIoKDjPditWfg+XOrWk6suUyX7vlrEtDY9zf8hs373rUIVj7Nuvm6B84vg5hdvmRiwWo1GjepLy5b/+UUu/RERERERERERERKR+pqamaNCgAW7fvi2p8/T0RO/evfNsm5mZCU9PT0FdmzZt5B7funVr7NixQzBOZmYmRAosd3vr1i1BuXHjxjAxMZF5bGG+JipcTFglIiIiIioGXF2d4Ohoi48fs5KpLl++j+HDO+fZLjgkEn5+ud+NmJ6ekecxubl9+wViYuIBZG0b37FjI5X7Kmk4r0Sa8+zZS3z86A9HRwcAQNt2LfDH/qN5titTpjTKl7fP9RgdHXGex+TFyMgQnTpnX2ALDPiE27fv56vP/7i714e5hRkAICkpGZcuMWGViIiIiIiIiIiISJu1bdtWkNx59OhRhZI779y5A39/f0nZxsYGrq6uco93c3ODlZUVIiOzFknx8/PD3bt34e7unudYR48Kr7G3bds21+ML6zVR4RJrOgAiIiIiIlKP/gNaS56fO3tH/oGF7Py57Fi6dHaHqamRBqMpejivRJpz7KiH5HnXru00GIm0Tp3awNg4+3134oR6VlcFgM5dsi8SXrzwN+LjE9TWd6ESibTvQUREREREREREVISJtPAfZenWrRuMjY0l5Xv37gmSPWXJzMzEpk2bBHV9+/aFWCw/pVAsFqNPnz6Cuk2bNiEzMzPXsW7fvo3797MXXTAxMUGXLl1ybVNYr4kKF1dYJSIiIiIqJgYMaIPNm08iMSEZz5754tWrf1GjRoVc2+zZM69AY4qLS8SFi3cl5eEjOhXoeMUR55VIc44d9cCEiSNgbGwEZ5caqFa9Ct68fpdrm9FfzSiU2E6ePI+TJ8+rvV8TE2N07NRaUt6374jaxyAiIiIiIiIiIiIi9SpVqhSGDh2KHTt2SOrmz5+PP//8E7a2tjLbbNu2Dffu3ZOUzczMMHr06DzHGjt2LA4ePIiEhKzFDry8vLBjxw6MGzdO5vHBwcH4/vvvBXXDhw+HtbW11rwmKjxMHSYiIiIiKibMzIwxZHD2CoAH/ryswWiynDhxHUmJKQCA5i3qoHr13BMtSRrnlUhz4uLicfjQKUl58ODemgumkPTq3QVGRoYAgJs3vPD2ja+GIyIiIiIiIiIiIiIq+h48eABPT0+ph7e3t+C45ORkmcd5enrCx8cn1zHGjBmD0qVLS8r+/v4YMmQIrly5IlgB9dOnT1iwYAHWrl0raD9hwgRYWlrm+Vqsra0xYcIEQd2aNWuwaNEiBAcHS+oyMjJw+fJlDB48GAEBAZL6MmXK4KuvvspznMJ8TVR4uMIqEREREVEx8tXobjh46CoS4pNw6vRNTJnaF6VLW2oklvT0dOzZfQFA1i7I06b100gcxQHnlUhzdu08iAEDe8LExBg9enbC5k27EBYWoemwCoRYLMbw4QMAZG2btHHD7xqOKJ9EYkCbtnkSaVEsREREREREREREKhD9/5+20KZY8vL1118LkjblCQsLw6hRo2R+rU+fPli5cqXctpaWlli7di1Gjx6N5ORkAEBAQAAmTZoEc3NzODg4ICYmBkFBQUhPTxe0bdeunVIrkY4dOxaPHj3C33//Lak7cOAADh8+DHt7e5iZmcHf3x8xMTGCdoaGhli3bh3Mzc0VGqcwXxMVDl4pJyIiIiIqRqyszPDVV10BAKkpadi185zGYjl16iaCgsIBAJ06NUbt2pU0FktRx3kl0pyoqGjs3nUQAKCvr4eRIwdrOKKC07NnJ9jZZ22j9NfFa3j58o2GIyIiIiIiIiIiIiIiZTRs2BDbtm2TWlU0JiYGL168gL+/v1RiZ/fu3bFu3TqIRIonAIvFYqxfvx7dunUT1Kenp8PPzw8vXryQSla1tLTE9u3bUb9+fa18TVQ4mLBKRERERFTMfPVVVzg4ZG2N8eeBywgMDCv0GFJSUrF500kAgKGRPr6eO6TQYyhuOK9EmrN71yH4+wcBAAYN6Q07O1sNR6R+enp6mDBxBAAgMTEJa37eouGIiIiIiIiIiIiIiEgVTZo0wdmzZzFkyBAYGRnJPa5WrVrYsGED1qxZA319faXHMTAwwC+//IJff/0VNWvWlHucsbExvvjiC5w7dw6NGzdWehyg8F4TFTxdTQdARERERETqZWCgj5WrJuDWrWcAAH//UNjb2xRqDP7+oejdpwUAoFZNR5Qta12o4xdHnFcizUlJScG8b5ehabOGAIBy5coiKChYw1GpVzkHO5w6dQEA8PLlWwQHh2o4IjUQi7Ie2kKbYiEiIiIiIiIiIlKBSJT10BbaFEterl69Wqjj2djYYNGiRfj222/x6NEjvHv3DjExMdDT04OtrS1cXV3h6OiolrE6deqETp064ePHj3jy5AmCg4ORmpoKc3NzVKlSBW5ubjAwMMj3OIX5mqjgMGGViIiIiKgYqlevKurVq6qx8StXtseUKX01Nn5xxXkl0pwnT7zx5Im3psMoMB/e/4stm3drOgwiIiIiIiIiIiIiUiNDQ0M0adIETZo0KfCxHB0dCyVhtDBfE6mfWNMBEBERERERERERERERERERERERERFR8cYVVomIiIiIiIiIqPgRi7Ie2kKbYiEiIiIiIiIiIlKJ6P8PbaFNsRCRIrjCKhERERERERERERERERERERERERERFSgmrBIRERERERERERERERERERERERERUYFiwioRERERERERERERERERERERERERERUoXU0HQEREREREREREpHZicdZDW2hTLERERERERERERCoQiUQQiUSaDkNCm2IhIsXwSjkRERERERERERERERERERERERERERUoJqwSEREREREREREREREREREREREREVGB0tV0AERERERERERERGonFmU9tIU2xUJERERERERERKQC0f8f2kKbYiEixXCFVSIiIiIiIiIiIiIiIiIiIiIiIiIiKlBMWCUiIiIiIiIiIiIiIiIiIiIiIiIiogKlq+kAiIiIiIiIiIiI1E4MQKxFm4LxtnEiIiIiIiIiIiriRP//py20KRYiUgwvlRMRERERERERERERERERERERERERUYFiwioRERERERERERERERERERERERERERUoXU0HQEREREREREREpHYicdZDW2hTLERERERERERERCoQiUQQiUSaDkNCm2IhIsXwSjkRERERERERERERERERERERERERERUoJqwSEREREREREREREREREREREREREVGB0tV0AERERERERERERGonEgFiLdoSjNuTERERERERERFRESf6/0NbaFMsRKQYrrBKREREREREREREREREREREREREREQFigmrRERERERERERERERERERERERERERUoJiwSkREREREREREREREREREREREREREBUpX0wEQERERERERERGpnVic9dAW2hQLERERERERERGRCkT//6cttCkWIlIME1aJiIq4qS9+Q0ZGpqbDIDXJSE/QdAhUADJFv2o6BCoAxgaOmg6BiBSQiXRNh0AFIDH5X02HQGoSERGBJk2aaDoMIiIiKZmZGcjMzNB0GKQmIhFvHCmeAjUdABEpgOfg4orn4OJIJHLQdAikJiKRsaZDICKSi78dEhERERERERERERERERERERERERFRgeIKq0REREREREREVPyIRVkPbaFNsRAREREREREREalAJBJBJNKe61zaFAsRKYYrrBIRERERERERERERERERERERERERUYFiwioRERERERERERERERERERERERERERUoXU0HQEREREREREREpHZicdZDW2hTLERERERERERERCoSQaTpEIioCOOVciIiIiIiIiIiIiIiIiIiIiIiIiIiKlBMWCUiIiIiIiIiIiIiIiIiIiIiIiIiogKlq+kAiIiIiIiIiIiI1E4synpoC22KhYiIiIiIiIiISAUiUdZDW2hTLESkGK6wSkREREREREREREREREREREREREREBYoJq0REREREREREREREREREREREREREVKCYsEpERERERERERERERERERERERERERAVKV9MBEBERERERERERqZ1InPXQFtoUCxERERERERERkQpE//+nLbQpFiJSDK+UExERERERERERERERERERERERERFRgeIKq0RERERExYienh6cnCqiQoVysHcoC3MzUxgYGiAhPgExMbH48MEfjx4+R2xsnNrHtrKyQKPG9VC5siNMzUyQkpyCoKBgPHn8Aq9fv1P7eCUJ55WIiIiIiIiIiIiIiIiIijomrBIRERERFWH25cqiY6dWaNKkPtzcXFC1WiXo6enl2iYjIwMPHzzD3j1HcODPk0hISMxXDE2a1sfcbyajbbtm0NWV/SeGj88HbN28Fzu2/4G0tLR8jVcScF6JiNRABECsRVuCaVEoREREREREREREqhFBuy50aVMsRKQIsaYDICIiIiIi1X05rB82bV6OL4f1Q63a1fJMagQAsViMBg1d8evGH/Hg8UV06tRapbF1dXWxZu1CXL56GB07tZKb1AgATk4V8fMvC3Dr9ilUqVJRpfFKEs4rERERERERERERERERERU3TFglIiIiIirBKlQoh6MndmD0mCFKtdPR0cH+PzdiwsThSrVzdqmBK38fRvXqVZRqR8rhvBIRERERERERERERERGRtpG/VA4RERERERUpvr4fcevmPdzzeoy3b9/jwwc/xMbEITU1DWbmpqhWrTKat2iEYcP7o3x5e0k7sViMXzf+iH8/BuDSpesKjbVk6dfo0bODoC40NBxbt+zF2TOX4ecXCGtrK7jVd8GUqaPQsFFdyXGly5TCkeM70My9J2Jj49Ty2oszzisRkYrE4qyHttCmWIiIiIiIiIiIiFQihnatj6hNsRCRIpiwSkRERERUhL1944t5367A6dN/4b3vv3KPi4uLR1BgMP65dhtrftqKZSu+lVpFc92GJXB1bo+0tLRcx3RxqYFpM0YL6l54v0HPHiMRFBgsqYuKioGv70ccPeKBVau/x5RpX0m+VqWKI76bNxXzvluhzMstMTivRERERERERERERERERFTcMM2ciIiIiKgIO3H8PNav+y3XpMackpKSMXvmYhw5fEZQX7FiebRt2yzP9j8snAnxZ6vExcTEonevrwRJjTl9M3cZzpy+JKgbO34oytqVUTjukoTzSkRERERERERERERERETFDRNWiYiIiIhKqIULfpaqa9+hRa5t6tSpiW7d2wvqflyyDgH+QXmON2PaD0hISJSUjY2NMHPmWAWjJUVxXomI/k8s1r4HERERERERERFRESbSwn9EVLTwSjkRERERUQn18YM/fH0/CurKOdjl2qZv/66CclxcPPbsPqLQeJ8+heLUyQuCut59uyjUlhTHeSUiIiIiIiIiIiIiIiIibcSEVSIiIiKiEiwkOFxQNjU1zvX4nKtwnj71F+Li4hUeb/++44Kyg4Md6tZzVrg9KYbzSkRERERERERERERERETahgmrREREREQlmIWlmaAcGhou50jAobwdatWqJqi7cf2OUuPduf0AKSkpgrrOXVor1QfljfNKRARALNK+BxERERERERERUZEm0sIHERUlTFglIiIiIiqhbGysUa1aZUHdPa8nco93dq4hVXfb84FSYyYlJePxI29BXe3a1ZXqg3LHeSUiIiIiIiIiIiIiIiIibcSEVSIiIiKiEurruROho6MjKScmJuHY0bNyj69evYqgnJqaCh+fD0qP+/r1u1z7pfzhvBIRERERERERERERERGRNmLCKhERERFRCSMSiTBz1jhMmfaVoH71qs0IC4uQ2656DWECYmBgMDIzM5Ue398/SFCu4lQRYjH/NMkvzisRERERERERERERERERaTNdTQdAREREREQFSyQSwczMBJUqVUCTpg0wfER/uNatLTjmj/3H8dOqzbn2Y2dnKyjnTFBUlJ9foKBsaGiAUqWsEBoarlJ/JRXnlYgoD2Jx1kNbaFMsREREREREREREKhFDu9ZH1KZYiEgRTFglIiIiIipmTp7ehQ4dWyp0bFhYBH5csg47tv+R57EmpsaCcmxMnErxyWpnYmrMxMY8cF6JiIiIiIiIiIiIiIiIqChjwioRERERUQkUH5+A1Ss3YcvmvYiPT1CojamJMLExMTFJpbFltcvZN6mG80pERERERERERERERERE2orrIhMRERERlUAmJsZYuHg2Dh/dhhYtGyvUxjhH8mFycrJKYyclSSc2mpiaqNQXCXFeiYg+IxJp34OIiIiIiIiIiKgo0/T1NV5zIyryuMIqEREREVExc+yoB54+eSEp6+npwsLSHFWrVUbdurVhbGwEABCLxWjdpilatnLHpg278O03yzUVMimA80pERERERERERERERERERRkTVomIiIiIipl9e4/J/ZqxsREGf9EbCxbMROkypQBkJThOnT4aevp6mD1zsdy2CTm2mDcwMFApPkNDQ6m6+Lh4lfoqSTivRERERERERERERERERFSUiTUdABERERERFZ6EhETs/O0AGrh1xpPH3oKvTZg4HF26tpXbNi5HYqORkXSCoiJktcvZNymH80pEJINYrH0PIiIiIiIiIiKiIkykhf+IqGjhlXIiIiIiohIoLCwCvXuOQmRktKD++/nT5baJjxMmH5qZm6o0tqx2Ofsm1XBeiYiIiIiIiIiIiIiIiEhbMWGViIiIiKiECgkJx8YNOwV19dyc4eRUUebxQUHBgrKDg51K4+Zsl5SUjPDwSJX6ImmcVyIiIiIiIiIiIiIiIiLSRrqaDoCIiIoXPT09VK1aBY6ODihXrhzMzc1gaGiA+PgEREfH4MOHj3jw4AliY2PVMp5YLIaTU2VUrFgB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rvXFvx2prkRERERERERERERERET0bOqibgARFbyZM2di7969SEtLw/3795GSkpLpdL1790ajRo0KuXVERESUmT27D2DI0N4A0oeDDyxdKtveKN8eMRCBgU8uIjQajejZsyN69uyY4/c8dzYc4z/7Lttpfvh+DmrVqobqNSoDAP43YiDad2iJXTvDcOdODDQaNWrWqoa2bVvAw9NDvC7i2k1M++7XHLXD19dbzB8Adu86kOPPYOtYV8esKxERERERERERERERERE9Gy9YJXICMTExCA8Pz3aaV199FZ999lkhtYiIiIie5dy5cNy+dQflg8sCAF57rTlWLN+Y5fRKhWVvmCqVCmXLBeXqPe/de/DMaVJSUjHqnfGY+ctk1KpdDQBQrnwZvPlWvyxfc+b0BXw45kukpqblqB2tXmsOlUoFALh79z6OHzuTo9fZA9bVMetKRLZJUighKWxncCFbagsREREREREREVFeKKCEwoYG9LalthBRznCtJXJyXl5eeO+99/Drr7/C3d29qJtDREREZjZs2Cb+/Xr7lkXYEksPH8Zi0ID38PNPvyMmm95BY2LuY8o3szBs6EeIjX2c4/m37/Dks/658W9IkpSf5toc1tUx60pERERERERERERERERE2WMPq0RORK1Ww9vbGz4+PqhZsyZeeOEFtG3bFt7e3kXdNCIiIsrExvXbMGLEILh7uKNO3RqoVq0Srly5num0X3w+HV98Pr3Q2mYymbBk0VosWbQWtWtXQ4WK5eFf0g+SJCH20WNcungVERE3cz3fcuWD0KhxPQCATqvDurVbrNzyose6OmZdiYiIiIiIiIiIiIiIiCh7vGCVyAlMnToVU6dOLepmEBERUS4lJSVj7ZotGDK0NwCgT78QTP7qpyJu1dMuXLiCCxeuWGVeffp0Ef/etGlHrnrwtBesq2PWlYhskFKZ/p+tsKW2EBERERERERER5Yni//+zFbbUFiLKCSblREREREQ2bPGiNUhJTgEAdO7cBv7+fkXcooJTvLgXuvfoACC9F87f560o4hYVHNaViIiIiIiIiIiIiIiIiJwNL1glIiIiIrJhjx8nYPGitQAAjYsGQ97oVcQtKjgDBvaAu4c7AGDlilA8ePCoiFtUcFhXIiIiIiIiIiIiIiIiInI2vGCViIiIiMjGLVm8DlF3YgAAffqGILB0qSJukfX5+flg0OAeAID79x9i/rzlRdyigse6EhEVMKXS9v4jIiIiIiIiIiKyawob/I+I7Im6qBtARERERETZ0+l0mPDZVDR7sTEAoEyZQNyNuV/ErbKusmVLY+mS9QCAY8dOIzU1rYhbVPBYVyIiIiIiIiIiIiIiIiJyJrxglYiIiIjIDpw5cxFnzlws6mYUmLNnL+Hs2UtF3YxCx7oSERERERERERERERERkbPgBatEREREREREROR4lMr0/2yFLbWFiIiIiIiIiIgoTxQAbCnnUhR1A4gol2xpC0JERERERERERERERERERERERERERA6IF6wSEREREREREREREREREREREREREVGBUhd1A4iIiIiIiIiIiIgKWkJCAlauXIldu3bhzp07SEtLQ6lSpfD888+jb9++qFOnTlE3kYiIiIiIiIiIiMih8YJVIiIiIiIiIiJyPEpl+n+2wpba4oTOnj2L9957D3fv3rV4/vbt27h9+zY2btyId999F++++24RtZCIiIiIiIiIyPYpFAooFIqiboZgS20hopzhBatERERERERERETksCIjI/G///0PcXFxUCgU6N27N9q3bw8PDw+cOXMG8+fPx4MHDzBr1iwUL14cgwYNKuomExERERERERERETkkXrBKREREREREREREDuu7775DXFwcAOCrr75Cnz59xN/q1auHNm3aoHv37oiNjcWPP/6Itm3bIiAgoKiaS0REREREREREROSwOBYZERERERERERE5HoUCUCpt5z8OT1Ykrl27hj179gAAGjVqZHGxqqx06dL48MMPAQCpqalYunRpobaRiIiIiIiIiMh+KGzwPyKyJ+xhlYiIiIiIiIiIiGzG7du3cfbsWdy9exd6vR7FixdHpUqV0LBhQ7i6uuZqXn///bf4d+/evbOcrnPnzvj222+RmpqKHTt2YOzYsXluPxERERERERERERFljhesEhERERERERERUabu3buHs2fP4syZMzh79izOnz+P5ORk8fcyZcpg7969Vnmv3bt347fffsOFCxcy/buHhwe6d++Od999F35+fjma57Fjx8S/X3jhhSync3NzQ7169XDkyBFERkYiJiYGpUuXzt0HICIiIiIiIiIiIqJs8YJVIiIiIiIiIiJyPApF+n+2wpba8gwnTpzAokWLcObMGdy/f7/A30+n02H8+PHYsmVLttOlpKRg+fLl2LZtG2bNmoUmTZo8c97Xrl0DAHh5eSEwMDDbaatUqYIjR46I1/GCVSIiIiIiIiKijJT//5+tsKW2EFFOcK0lIiIiIiIiIiIi4dy5c9i1a1ehXKxqMpkwZsyYpy5WValUKFu2LGrWrIlixYpZ/C02NhbDhw/HqVOnsp23TqfDw4cPASBHF5+aX9AaHR2d049ARERERERERERERDnEC1aJiIiIiIiIiIgoRzw8PKw6vwULFmDPnj0Wz/Xt2xf79u3Dnj178Oeff+Lo0aOYPXs2goKCxDSpqakYM2YMEhMTs5x3UlJSrtrt6ekp/p2cnJybj0FEREREREREREREOaAu6gYQERERERERERFZnVKZ/p+tsKW25JCnpydq166NunXr4rnnnkPdunVx584dDB482Crzj4uLw9y5cy2e++ijj/C///3P4jmlUok2bdrgueeeQ79+/RAVFQUAuHv3LhYtWoT3338/0/lrtVrxb41G88z2uLi4iH+npaXl+HMQERERERERETkPxf//ZytsqS1ElBO8YJWIiIiIiIiIiIiEVq1aoXnz5qhUqRKUGS60vXPnjtXeZ8GCBRY9mTZp0gTDhw/PcvqAgAB8++23eOONN8RzixcvxqBBg+Dr6/vU9K6uruLfer3+me3R6XTi325ubs+cnoiIiIiIiIiIiIhyx/66diAiIiIiIiIiIqICU758eVSpUuWpi1WtyWQyYePGjRbPjRo1CgpF9r1iNGvWDI0bNxaPk5OTsX379kyn9fLyEv9OSUl5ZpvMp/H09Hzm9ERERERERERERESUO7xglYiIiIiIiIiIHI9SaXv/kXDy5EnExsaKx+XKlcPzzz+fo9f27NnT4vGePXsync7FxQUlSpQAAMTExDxzvubTlC5dOkdtISIiIiIiIiJyJgoobe4/IrIvXGuJiIiIiIiIiIioUO3fv9/i8YsvvvjM3lXNpzX333//ZdmDapUqVQAASUlJuHv3brbzvXbtmvh31apVc9QWIiIiIiIiIiIiIso5XrBKREREREREREREherSpUsWjxs2bJjj1wYEBKBMmTLisV6vt7jY1FzTpk3Fv48cOZLlPNPS0nDmzBkAQNmyZdnDKhEREREREREREVEB4AWrREREREREREREVKiuX79u8bhy5cq5er3cc2pW85O1a9dO/HvdunVZzm/Lli1ITU196jVEREREREREREREZD3qom4AERHlnMlkeuo5pTJnQyaSfVDwXhKHJLGuDknJshLZBamoG0AFIjY2tqibQFYSFxf31HOZHffkad7xKTb1gx0X//SQ9Zl9/rzw8/OzynwKS1paGqKjoy2ey22PpoGBgRaPb9y4kel0VatWRcuWLbFv3z4cP34ca9asQZ8+fSymiYmJwU8//QQAcHNzw5AhQ3LVFiKyf5n99sTFxRdBS6igKBS2s09ARNmTJOscD5Dt4DaYyJ64FXUDyEoKNHOLSwBgO9copLeHiOwJL1glIrIj8fFPB+XBwSWKoCVERERE9oKHvY6oWbNmRd0EKkDx8fHw9/fP93w6d/oy/40pYB06dLDKfC5fvmyV+RSWuLg4SNKTWwo0Gg1KlMjdsW1AQIDF40ePHmU57WeffYZTp07h8ePHmDRpEi5evIjXX38dnp6eOHv2LObOnSte/8EHHzw1byJyfJllbh07vlkELSEiIiIiIioY1srcOnR4I/+NISKnxjN3REREREREREREVGhSUix7m3Vzc4NCkbueOTw8PLKdp7ng4GDMmzcP7733Hu7fv4/Vq1dj9erVFtMolUq88847eOONN3LVDiIiIiIiIiIiIiLKOV6wSkRERERERERERIUmOTnZ4rGrq2uu55HxNdldsAoA9evXx19//YUVK1Zg165diIyMhFarRcmSJfH888+jX79+qFu3bq7bQUREREREREREREQ5xwtWiYiIiIiIiIiIqNDodDqLxxqNJtfzcHFxsXiclpb2zNcUL14cI0eOxMiRI3P9fkRERERERERERESUf7xglYjIjgQHB2Pbtm0Wz3l7e0OpVBZRiwpOXFwcOnToYPHctm3b4OvrW0QtImtgXR0Pa+qYWFfHxLo6JtbVMTlTXU0mE+Lj4y2eCw4OzvV8fHx8cPjwYWs1q8DFxcUBcNzjuWfJeLGpXq/P9TwyXvSal15aiYhkzNwccz/DWbCmjol1dUysq2NiXR0T6+qYnKmuzpq5yXx8fIq6CUSUDV6wSkRkR9RqNSpXrlzUzSgyvr6+8PPzK+pmkJWxro6HNXVMrKtjYl0dE+vqmBy5rv7+/vmeh1KptKvlY09tLQienp4Wj7Vaba7nkfE1Hh4e+WoTETk3Zm6Ou5/hrFhTx8S6OibW1TGxro6JdXVMjlxXZ8zciMg+ON7twURERERERERERGSzMl5cmpaWBkmScjWPlJSUbOdJRERERERERERERLaHF6wSERERERERERFRofH19YVCoRCP9Xo9Hj16lKt53Lt3z+JxiRIlrNI2IiIiIiIiIiIiIio4vGCViIiIiIiIiIiICo2bmxuCgoIsnouOjs7VPGJiYiweV6pUKd/tIiIiIiIiIiIiIqKCxQtWiYiIiIiIiIiIqFBVrFjR4nFERESuXp9xel6wSkRERERERERERGT7eMEqERERERERERERFaqaNWtaPD516lSOX3v//n1ERUWJxxqNBpUrV7Za24iIiIiIiIiIiIioYPCCVSIiIiIiIiIiIipUr776qsXjf//9F5Ik5ei1hw4dsnj8/PPPw9PT01pNIyIiIiIiIiIiIqICwgtWiYiIiIiIiIiIqFA1bNgQvr6+4nFkZCT++++/HL12/fr1Fo9btWpl1bYRERERERERERERUcHgBatERERERERERERUqJRKJbp162bx3K+//vrMXlYPHz6M48ePi8eenp5o3759gbSRiIiIiIiIiIiIiKyLF6wSERERERERERFRoRs+fDg8PDzE46NHj+L333/Pcvp79+5hwoQJFs8NHjwYfn5+BdZGIiIiIiIiIiIiIrIedVE3gIiIiIiIiIiIiGzLiRMnoNVqn3o+PDzc4rFWq8W///6b6TxKlSqFKlWqZPkefn5+GDFiBGbMmCGe+/HHHxEdHY2RI0ciICAAAGAymbB37158++23iI6Otpj/m2++mavPRURERERERERERERFhxesEhERERERERERkYWxY8ciKirqmdM9fPgQQ4cOzfRv3bp1w9SpU7N9/fDhw3Hq1Cns27dPPLdq1SqsXbsWQUFBKFasGO7cuYOEhASL17m5ueHnn39G8eLFc/BpiIiIiIiIiIiIiMgWKIu6AUREREREREREROSclEolZs6ciY4dO1o8bzQaERkZiYsXLz51saqPjw/mz5+PRo0aFWZTiYiIiIiIiIiIiCifeMEqERERERERERERFRlXV1fMmDEDs2bNQs2aNbOczsPDA/3798e2bdvw/PPPF2ILiYiIiIiIiIiIiMga1EXdACIiIiIiIiIiIrIte/fuLfT3bNeuHdq1a4dbt27hzJkzuHfvHvR6PYoXL47KlSujYcOGcHV1LfR2EREREREREREREZF18IJVIiIi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m+sUYDlZsWKFHn74YWVkZMhkMsnpdKpOnTp6/PHHVbVqVUVERCgxMVF//vmnNm3aJEnG41mtVjVp0kQ33XSTevXqZVzheurUKS1btkxPPfWUz9Wr1157rd57771CbR987dixQ1OmTNG8efOMgNK5c2e9/vrrOd7+888/1//+9z9JMgK6dHo0B29Al/K/gjA1NVWzZ8/WX3/9pd9++03Hjh2TdPqAPiIiQk2aNFHDhg3Vu3dv1atXz19Pt1QLVDj3vn8+/vhjjR07VhUqVNDo0aPVrl27fA+sjx8/rueff14//vijMXKHdwo6SWrfvr2qVq2qmJgYHTx4UL/++quSk5OND8vCw8P10EMP6f777y/GK1P6OJ1Ovf3225o0aZKxLC4uTvfdd59uvPFG1a5dW1L2aR2z8u5jt9utPXv2KDExUVOmTJF0Ooh4vw+k0yFu4MCB6tChg2w2m896U1JS9O+//+rVV1/Vv//+a7wXJRnfb97pIr3/7V2vJLVt21Zt27bVfffd59fXqDRivyIzM1O//vqrEdCzfjAcHx9fqID+7rvv6v333zemmHM6nYqJidHAgQPVpUsXValSpVDb9tNPP2n48OFKS0uTxWJRTEyMRo0apfbt23PVfwhKTU3Vk08+qV9++cX4sKRu3bqaOHGiatWqVdKbBwBAmUJzK7tobqUHzS100GZCE/sVNDcEC5obAKCkcMIqgJDlDegTJ05UUlKSLr30Uk2dOrVQIc5r8ODB+umnn4ypV7zTn2RmZiosLEx2u924rXdUgcjISA0ePFht27ZV06ZNJfkGBqfTqf/7v//TZ599Zkx5VKdOHX3++eeKjY3174tRRmRkZGjSpEmaOHGiMTqHd3+MHTtWt9xyS473K25APzscHT58WKdOnZLD4VBaWpqio6N1wQUXyOFwGFNalXWBDueTJk3ShAkTdOrUKWMUho8++si4ejkvdrtdzz//vL799luZTCYj8GWd6igr7xXrYWFhuu222zRs2DBVqFChEK9G6ff999/rscceM/4dExOj+++/X3feeafi4+MLvJ6z32NTp07Vm2++qVOnTkk6836WpJYtW+rxxx9X69atc1xXZmamVq1apZ9//lm//vqr9u/fb6znbHXq1FHdunV1++236+KLLzYiXl5RuCxgv0IqfkDP+no/9NBDWrx4sU9AL1eunO655x51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MVWZP4J2fgF9wIABat68OeG8mPIL6B6PR08//bTxPg5EOM/6fvXiQ5Hced9vWf/tDZ6Bet08Ho+sVqv69++vhQsX6sCBA8bURX///bc2bNhgTKOFomG/ojCKG9C9U9GZTCaZzWa1bt1arVu3liSdOnVKp06dkslkUmxsLD+LAQAAggTNLTTR3EIXza30oc2EJvYrCoPmBgAAQh2XTgEISd4DrKSkJE2aNElPPPGEkpKSjOVZA/rgwYNVv359ud3uQk1VlhfvVBreEDd9+nS99tprmjNnjk84v/XWWzVw4ECVK1euuE+5zKhQoYLPByFms1nbt2/Xhg0bjOnevFPr+OtAO6+pyt5++21t2rTJL49T1uU1VdkPP/ygsWPHyuFwaNq0aQEN5z/99JM2bNggienncuNyuZSenq7MzExJMqYR+ueff3Ts2LGAPa7JZJLb7Vb58uV12WWXGcucTqcyMzONUQpQNOxXFEVxpyrz/q72/r/3b6iIiAiVL19ecXFxPn+/AQAAoGTR3EIXzS100dxKD9pMaGK/oihobgAAIJRxwiqAkJWUlKRPP/1Un376qZYvX67XXntNW7dulclkMg7CAhXQzWaz7Ha7li1bpuHDh2vkyJH6888/jQPC8PBwdevWTY8++ihTbBSCy+VShQoVNH/+fJ1//vlyOByyWCzGPrVaTw8c/ueff8rpdBqvtz+cHdCjo6MlSWvWrNF5553nt8cp6/IK6AsWLFD37t311ltvKS0tLSDhfMqUKRo6dKgmTJigdevWSfLfhzChxGKxqFy5cqpataqkM6MAZGZmym63B/RDB7PZLJvNZkRW77SFknTgwIGAPGZZwX5FURU3oGeV13R0/DwGAAAIDjS30ENzC300t9KBNhOa2K8oKpobAAAIVZywCiAkHT58WHPnztU333xjTKuyatUqPffcczp06JDPbf0d0Pfu3av58+erf//+evHFFzV//nxJpw8sPR6PoqKiNHjwYD3yyCOqVKmS/550GWCxWOR0OhUfH68ZM2b4BHRJxr5esGCBtmzZIrPZ7NfQ4w3oZrNZaWlpqlSpkr744gsjNME/8grof/31l9LS0ozvBX+G808//VTjx49XZmamlixZorfeessY9QE5i4mJkXRm5JWjR4/qu+++kxTYyOXxeFSzZk3je8Pr4MGDkuTXD87KIvYrisKfAR0AAADBi+YWmmhuZQPNrfSgzYQm9iuKguYGAABCESesAggp3gPrFStWKDExUQ6HQ5JktVp12WWXqXv37qpSpUq2+/kroDscDm3ZskWTJk3SH3/8oaNHjxphLjMzU3FxcRo3bpzuu+8+lS9f3n9PvAzxXuGfNaA7nU4jmlqtVmVmZmrkyJE6cOCA369O7tatm5599llFR0dr8uTJql+/vt/WjTNyC+jSmWmL4uPjNW/ePL+F8/fff1/Hjx83pp9bt26dKleu7L8nFUK876lLLrlE0ukPtrw/f7NO1xeokQFMJpOqV6+u6OhoeTwe43G8Uz3mdbU4csd+RXER0AEAAEIXzS300dzKBppbcKPNhCb2K4qL5gYAAEINf4ECCClms1l79uzRmDFjlJGRIel0TL333nv1xBNPqFu3bpJyPvD3R0C32Wy6/PLLddddd6lu3brGFFnVq1dXx44dNWvWLF133XUKCwvz/5MvQ/IK6N4RH/755x9NmTJFycnJfg/o99xzj3766Sc1aNDAb+tEdmcHdO/0c9LpyNaqVasiT++XUzg/ceKErFarMjIyVL58eX355ZeqVq2aX55LqPFe8d+oUSNJktPpNF7PhQsXauHChT63C+Q2SGd+psfGxgbs8coC9iv8gYAOAAAQmmhuZQPNrWyguQUv2kxoYr/CH2huAAAglHDCKoCQ4T3I/vrrr3XixAlJpyNr79691aNHDyMGeDyeXA/8/RHQY2Njdcstt+iee+5RfHy8rrjiCj377LN66aWXdP755/vvCZdxuQV0q9Uqs9mskydPasGCBfr88891/Phxvwd0Ys65kTWgZx3Vw+PxaMWKFXriiSd04sQJn6vS85NXOHc6nYqNjdX06dMZyaMAGjdurCuvvNL4mer9gGP27NnasWNHQB87LS3NmD7L+33hHUUnUKMRlBXs19LD6XTm+W9/y/pzNj09PdfbeQP6oEGDdPHFF2cL6EOHDtXvv/8e0G0FAACA/9DcyhaaW9lAcwtutJnQxH4tPWhuAAAAgcUJqwBChvcgP+sVhC1bttStt96qGjVqZLtdbvwV0G+77TaNHz9en3zyidq3b68KFSoU49khJzkFdIfDIYvFIrPZrEOHDunzzz/Xl19+qRMnTvg9oOPcSEhI0JtvvmkEdG/IS09P148//qjRo0crJSVFZrM534BekHA+Y8YMXXjhhQF/XqGgXLlyxtXcbrfbeP3XrVunX375xZgiMhB27NihEydOyO12y+l0qkKFCrr00kslBXY0grKA/Vo6eH8eulwuTZgwQZKMfwdC1p+fs2fP1meffaYDBw7kevuwsDC1bdtWDzzwQLaAfuzYMT366KMEdAAAgFKC5lb20NzKBppb8KLNhCb2a+lAcwMAAAg8TlgFUKp5DxC9/3/o0CHt3LnTuEL0hhtuUOPGjQu9Xn8E9JiYGDVv3lwSV6gGUn4Bfe/evUpMTNTnn39OQC/FrrnmGp+pymw2myTJbrdr0aJFGjVqVL4BnXDuX973Uf/+/Y3Q6vF4ZLFYlJ6ero8++kjr1q3zua0/eH/eb926VZKM6R4rVaqk6Oho3t/FxH4tHbKG8z59+ujNN9/Uc889J0k+U3X6S9afn4mJiRo1apQ++OADffXVV9q7d2+u9ytIQF+9erVftxUAAAD+QXMDza1soLkFH9pMaGK/lg40NwAAgHODE1YBlFoul0sWi0VJSUmaMmWKUlNTlZmZqfT0dLlcLp1//vm6/fbbJRXtAN8fAd2LK1Tzl3Ufud1u498FmXKqIAF95syZBPRSLutUZTkF9JEjR+Ya0LOGn6lTp2YL53FxcUpMTCScF4L351pERIQ6dOig2NhYY3QAq9Wqo0eP6sknn9Tff/8tk8nkl5jnjbj//fef5syZI0nKzMyUJPXo0UPly5fn520xsV9LB284v/fee7V27VpZrVZ9+eWXeuaZZyT5N6Bn/fk5Y8YMvf3223K5XLLb7Xr33Xf17bff5jktWn4BvU+fPlqzZo1fthUAAAD+QXMLLTQ35IfmFlxoM6GJ/Vo60NwAAADODU5YBVAqecP5tm3bdOedd2rs2LGaOXOmkpOTjdtER0crJiZGUtHjtT8DOnLmjdhZ95Hb7Tb+7T1gzy8CENDLhrwC+g8//JBjQD87nH/wwQfZwvmMGTN0wQUXlNjzKs2sVqtuueUW44MHb9SzWq06ePCgHnjgAR04cEAWi6XY7zmTySS73a6JEyfq4MGDCgsLk8lk0oUXXqiLL77YD88GXuzX4NejRw+tWrVKkZGRxu/NOXPm+DWgnx3O33nnHR0/ftz4HW0ymdSuXTtj2sjc5BTQvd83Ho9H8fHxxdpOAAAA+A/NLXTQ3FAYNLfgQ5sJTezX4EdzAwAACDxOWAVQKlksFv3111+66667jCsMX3/9df3www+qUqWKTCaTEc69V4wWFQE9cLwH+8nJydq6dateffVVPf744+ratavuu+8+jRkzRrNnz5bdbjemnMtLQQP6F198QUAvxfIL6FmnKsvMzCScnwNVqlTRK6+8opiYGOM95w2t+/btU69evfTXX38V+4p9h8OhJUuW6NdffzX+7fF4dM0116hp06b+eCrIgv0a3O655x5J8vkd6c+Anls4t1qtcjgcioqK0pw5c9SwYcMCPUbWgH7JJZfI4XAoNjZW3377rerVq1ekbQQAAID/0dxCA80NRUFzCz60mdDEfg1uNDcAAIDAM3moBgBKIafTqVdffVXTpk2TyWRSWFiYMjIyfG5Ts2ZNzZs3T1FRUX55TLvdrp9++kkffvihtm/fLrPZLIvFIofDobp16+rVV19V8+bN/fJYZcmWLVv0yiuvaP/+/Tp06FCOQbtevXrq1auXrrrqKtWpU0fS6atDcws2TqdTVqtVycnJuvvuu7Vz507ZbDa5XC653W7VrFlTPXv21J133qm4uLg814XgtWzZMg0bNkxpaWmy2WxyOBySTn/gdcMNN+ipp54yriAmnJ8bv/76q4YOHaq0tDRjdACLxSKn02mE2FatWhkfbhbkvee9jdPp1Lp16/T2229rzZo1xs+Kq666ShMmTDBGHeC97H/s1+C1cOFCDR06VJJks9mMEwo8Ho9uv/12jRkzRtKZUbIKKq9w7nQ6FRUVpRkzZqhRo0aFXndmZqaWLl2qmTNn6qmnnlLDhg0LfF8AAAAEHs0tdNDcUFQ0t+BDmwlN7NfgRXMDAAAILE5YBVBq7d27Vx9//LESExMlnZk6RTp9dWNMTIymTJlSpAO73OQU0MPDw2W329W4cWPNmjVLYWFhxX6csmD//v364Ycf9Pbbbys9Pd0IJN5ppcxms3FVsfeK0GbNmmngwIG64oorJBUsoB87dkx33323/v33X5+AXqNGDSOgly9fnjhTSuUV0Dt16qSRI0fqiy++0Ouvv66UlBTC+Tkwd+5cjRgxQna7PVtojY+PV7du3dShQwc1a9bMuE/WUJeV976nTp3SkiVLlJiYqNWrVxtfb9KkiZ599lm1bt2a93CAsV+DS9bXxd8BPZDh3CszM1MOh0PR0dGFvi8AAAACj+ZWutHc4A80t+BDmwlN7NfgQnMDAAA4NzhhFUCJ8B705XZgnfU2eTlw4IA+/PBDzZ49W5JvQPd4PLrnnnv0/PPPF3h9BXF2QJekihUr6uOPP1ajRo2Kvf6yYOvWrZo7d65mzJihjIwMn+gpnT7493g8cjqdMpvN8ng8xggQFStW1IgRI9S+fXtJBHTkHdAvuOAC7dq1S6mpqYTzc8ThcGju3LkaPXp0jqE1IiJCNWvWVJ8+fZSQkKAqVaoY980pxP3333/66KOP9Ouvvxo/cyWpbt26GjBggDp37qyIiIhz9vzKKvZr8AlEQM+6zkCFcwAAAAQWza1so7nBn2huwYU2E5rYr8GH5gYAABB4nLAK4Jw6O05mZGQoNTVV+/fvl8PhUEREhJo0aSJJMplMBTowyymgezweud1uVapUSS+++KIRWv3Fbrdr6dKl+r//+z8dPXpUX3/9tS688EK/Pkao2rp1qz799FPNmzfPiJwmk0lWq1U333yzmjZtqgYNGigtLU2LFi3SmjVrtGfPHkkyRoKQpNdff12dO3eWVPCA3rNnzxynKrv77rt1++23q0KFCufgFUAg/Pzzz3rssceyBXTvVEeE83PL6XRqwYIFevHFF32mtPKO4uLVokULNWzYUO3bt1etWrUUFxenmJgYJScna8uWLdq2bZtmzpypgwcPSjqzP+vWrauePXuqa9euxpRYCDz2a/AJ1KgPiYmJevPNN40PHh0OB+EcAAAgyNHcQHNDINDcggttJjSxX4MPzQ0AACCwOGEVwDmTdWSH1NRUfffdd1qwYIE2bdoku91uHHhfdtllatiwoYYNG1bgKz0PHDig8ePHa9asWZJkhDJJuu222zR48GCdf/75fn0+6enpWr58uRo2bKjatWv7dd2hav/+/ZoyZYoSExONuGm1WnXdddepU6dOuummm7LdZ9myZXr99de1bds2mUwm48piSRo3bpxuvvlmScUb9aFcuXJ65JFHdM899+Q6+giC39mjPni/T7zhh3B+7q1Zs0ZDhgxRcnKypNOR1Gw2y2QyGftHOvOhZ2RkpKKiopSRkaETJ07IYrHI5XIpLCxMDodDHo9HTZo0Ua9evdSxY0cCawlhvwYXfwf0w4cP68knnzSmjHO5XIqOjtZnn31GOAcAAAhSNDfQ3BBINLfgQ5sJTezX4EJzAwAACBxOWAVwTngPtDwej7744gv98MMP+vnnn42vh4WFyeVyyeVyGVd9Nm3aVCNHjlSjRo0KNGXU2QE96xXfAwYM0L333quKFSv69XkxnVXBeD84mT59usaOHauMjAxJp8PKvffeq9tuu80YLcP7PSCdHt3hp59+0vPPP6///vtPkvwa0KOiopSeni6bzaZvvvnG7x+w4NzLGtCtVqtMJhPhvITt3LlTr732mv78808dPnzY+IDK+7NeOv1edzqdPu99b1zNzMw0bnvVVVdp4MCBatGiBVNXlTD2a3Dxd0Bfs2aNxo4dqw0bNigyMlKJiYmEcwAAgCBFcyvbaG44V2huwYc2E5rYr8GF5gYAABAYnLAKIOC80dLtduvFF1/U0qVLdeTIEUlnornb7TYO+jwejxFHL7jgAo0YMUKtW7cuUKg+O6B7D9AlaciQIbr77rtVvnz5wD1ZZOMN5+vXr9e9994ru90u6XQ4HzRokO68805VrVpVkozg4t3Pixcv1ujRo7Vv3z5jBA9vbAkPDzcifFECep8+fbR9+3ZVrFhRU6dOZXq5EJI1oEsinAeB5ORkrVixQl9++aVWrlxpLLdarZJ8I573v91utzEdYZ06dXTttdfqiSeeINwFEfZrcPF3QF+5cqXef/99Pf/884RzAACAIEVzK9tobjjXaG7BhzYTmtivwYXmBgAA4H+csAogoLyx0uVy6aGHHtLSpUt9InlW3ijqDe3eq0Tr16+vjz76SFWqVCnQgdvZAT1rZB0yZIh69uypChUqBODZIjcHDhzQgAEDtGPHDkmnw0rPnj3Vp08f1apVy7hd1gP/JUuWaOTIkdq/f7/PdHONGjVSUlKSJBUroCcnJ+v+++83RhRBaPnll180cOBAmUwmzZ8/n3AeRGbPnq3Nmzfrm2++kdPpND7gPFtcXJzi4uLUq1cvtWjRQhdffLEkRtkJVuzX4OCPgJ51Henp6YqKiiKcAwAABCGaGySaG849mlvwos2EJvZrcKC5AQAA+BcnrAIImKzhvG/fvlqzZo0sFotMJpOcTqeqVaum888/X23btlVqaqqSk5P1xRdf+Exr4g3obdu21aRJk4zpT/JDQA8eDodDkyZN0kcffaRTp05Jktq2bavHHntMTZo0MW5XkHD+3nvvKT4+Xq+//rrWrl0ryXdEj8IGdO+HNAhNK1asUNWqVVWvXr2S3hQo+3ty9+7dOn78uFavXq2UlBQdPnxYVqtVVatWVcWKFdW2bVuFh4ercuXKua4DJY/9Gnyyvp4//vijHn74YUnyeY0LM+oDAAAAgg/NDRLNDSWH5hZcaDOhif0afGhuAAAA/sMJqwACIms479Onj9auXWvESrfbrZYtW+r5559XzZo1FRcXZ9xv7dq1GjVqlLZu3SqXyyWz2SyTyaTY2Fi9/fbbatOmTYG3gYDuH/Pnz1fHjh1ls9kKdT/vwXtqaqruu+8+bdq0SdLpK31feukl3XjjjdluK52eWurll1/2mZJMkt5++2117NhRkjRnzhxNmDBBO3fulNlslsVikcPhkFTwgF6QrwMAUBo5HA7j9/YTTzyhb775RhIBHQAAIBTQ3EIHzQ0AgNKF5gYAAOAfXOIKwO/yCucmk0k333yzpk+frqZNmyouLk5ut1vS6YO2Sy65RCNHjlT9+vUlSRaLRS6XS8eOHdP69esLtR3VqlXToEGDdNddd0mSMjIyFB4eLkl65513lJiYqGPHjvnviYegJ554QsOHD9frr79uROyC8h6gf/DBB9q0aZOsVqsk6a677jLCufeaCe9tf//9d73xxhvZRnl499131bFjR7lcLknS7bffboR0k8kkl8tlRILhw4dr/vz5xtfyui6DcA6UPO971OVyGe9xrqcq/divBXP271Z/vEZut9v4nThx4kQtW7bM+H1nMpl8/nvOnDl65plnJJ35mwsAAADBi+YWOmhuAAKNNhOa2K8FQ3MDAAAIbpywCsCv8grnFotFd9xxh1577TWfAzTv9FAWi0Uej0dNmjTR888/L+n01YphYWGSpP3790sq3IFltWrVNHjwYHXv3l0SAb0wHn/8cePq0ClTpmjcuHGFDujS6X0gnf7euPzyy9WvXz9JMj5M8dqyZYs++OAD7dixw5iWTpLeeOMNdejQQdLp7xXvhy2PPfaYLr30UrlcLnk8HjmdziIFdAAly/tzwGKxGFea88FW6cd+zV/Wv5myniBQnN9ZWafdnDRpkiZOnKiUlBTjA2zvqFve35cEdAAAgNKD5hY6aG4AzgXaTGhiv+aP5gYAABD8OGEVgN/kF85vv/12jRgxQmazOdcpMLxX7rdu3VpdunSRyWQyYmlkZKRxm8LwjvpAQC+4+fPn69tvv5V05nUvakDv06ePHnvsMUlSo0aNVL58eUlnPjSRpGPHjumbb77Rxo0b5XQ6jQP3MWPG6KabbpJ0Ziox7/ePJHXq1Ek2m8344IWADgAoDbL+zdStWzf16NFDP//8s/E3TlF+Z50dzidMmKCTJ0/KarXK4XDovPPO0//+9z9JUmZmphHUCegAAADBj+YWOmhuAAAEDs0NAACgdOCEVQB+UZBw/tJLLxlxPKdw7uX9WoUKFeTxeIwDyCpVqhR5+wjohdO4cWP17dtXVqtVdrvdeK2KGtAfeOABPf/88+rbt68RuiUZH4wkJSXp66+/lt1uN+7z2GOP6fbbbzf+nfVDE+/3yOWXX67w8HBjezwejxwOh7G9w4cP11dffZXt/gAAlBS32+3zN9OWLVskSffff7/PVGKFCeh5hXOn06lKlSpp+vTp6tWrl9544w1Jp0fUIqADAAAEP5pbaKG5AQAQGDQ3AACA0sPk4fJXAMVU0HCe1ygPWTkcDtlsNr3//vt69913JUnNmzfXRx99pFOnTun333/XgQMHlJycLKvVqosvvljVq1dXkyZNjHVkPYjM6sCBAxo/frxmzZolSQoPD1dGRoYkaciQIbr77ruN0QjKup07dyoxMVHTpk2T2+32ea369eun4cOHGwfdBeHdJ2fvm5MnTxrxwHuwfuutt2rYsGGqWrVqruvzeDxKT09X7969tWXLFlmtVjVp0kQbN26UJEVHRystLU02m00rV65UdHQ0AR0AEBTcbrfuvvturV+/XlarVRaLxfgdO2HCBCUkJBjxPL/fXQUJ5zNmzFDt2rWNv7EWLlyooUOHSpJsNpvPh9C33367xowZI0kF+rsNAAAAgUNzC000NwAAAoPmBgAAUDoUvHoAQA7yCudms1ndu3fXU089VeBwLp0+iDt16pR+/vlnSaenx6pbt66eeeYZ/f3339q1a5fP7a1Wq0wmk+69915dffXVuvTSS3OMtNKZUR8kadasWcaoDxkZGXr//fd16tQp9e/fX3FxcX56hUqv888/Xz179pQkTZs2zee1mjJliiQVKqB794X3/737Z8WKFdqzZ49sNptcLpfKlSundu3a5RnOpdMxITo6WtHR0cayjh07KiYmRitXrlRaWpoqVaqkyZMnKyYmprBPHwCAgPH+DpNOB+vMzEzZbDY5HA498MADPgHdOz1nTnIK52lpaTmG86x/h3Xs2FFvv/22hg4dagR1p9NpjPognZ4i1PuhNgEdAADg3KO5hS6aGwAAgUFzAwAAKB2yXwoNAIXgDed33HGHTzj3eDyqUaOGHnroIdlsNmVmZhbqwOv333/X/v37ZTKZZLfbtXDhQi1evFi7d++WdHqUBovFYqzT4XBo4sSJGjt2rBITEyXJCOhny2mqsujoaLlcLs2YMYPpOLLwBvTevXvLbDb7TOtW1KnKvLwH+6tWrVJqaqocDofcbreuuOIK3XTTTQVax8mTJ5WcnCxJCgsL03XXXaf77rtPzZo1U1RUlD755BM1aNCgSNsHAEAguFwumUwmTZo0SZ07dzb+7nA6nbLZbJJOT+uZ31RluY3yYLFYcg3nZrPZWJc3oEtMVQYAABCMaG6hjeYGAIB/0dwAAABKD05YBVBsf/75p5KSkiSdCdYej0eHDx/W2LFjlZycrLCwsBxDdlbeAzO73a7ExEQdOXJEJpNJVqtVp06dknTm4DEjI8O4vcvlMg74Nm7cqEmTJmn69OnG9uR0wHl2QPeODDBjxgzFx8cX9yUJKYEK6N7vk82bN0uSsQ9btGghSXkeqHv3aVpamhwOhywWi9LT05WRkaGrrrpKQ4YM0TfffKP69esXersAAPCns39HWiwWORwOmc1mjR07Vp07dzZ+rxU0oBdmSrKzR2swmUwEdAAAgFKC5hbaaG4AABQdzQ0AAKD04oRVAMXWokULTZo0SeXKlVNmZqZx4GW32/X999/r1VdfVUpKSq6jL0jyObAbOXKkli5dKknGQWBkZKQaNmyovn37asiQIbrnnnvUtGlTuVwueTweY5o0Sdq/f79mzZqlRYsWSVKuU3pUq1ZNgwcP1s033yyr1crIAHkIRED3juRx6NAhn+WxsbEFuq8kzZ8/X7t375bb7TZigyRdffXVqlGjRqG2BwAAf8s6jevs2bONUau8U5EVJaAXJ5x7FTWgF3WEJwAAABQNzS300dwAACg8mhsAAEDpZvLkdBk0ABTBsmXLNGzYMKWlpRkHhZIUGRmpG264Qc8995xiY2N9Dvok33D+4osvatasWZLkcxD44osvqlGjRqpVq5bPY7733ntatGiRtm3b5nMfSbrpppv08ssvKyYmJs/tPnTokEwmkypXruyfF6IU8Xg8MplM2fZJbnbu3KnExERNmzZNbrdb4eHhysjIkCT169dPw4cPNw66C6pXr15at26dpNNXr15//fV69913jZE6cvvwY+PGjRo9erTWr18vSWrVqpVmzJhRqMcGACBQsobzu+66S5s3b9agQYN05513qmbNmpLO/A3k8Xg0fPhwffvtt8bvPavVavwtNWHCBCUkJMjhcBhh3RvO09LS8pySLC9Zf88uXLhQQ4cOlXQ67nv/nvJ4POrWrZteeeUV/79IAAAAKBCaW+lDcwMAIDBobgAAAKUfI6wC8JuEhAS98cYbio6O9jm4s9vtWrRokUaNGpVt1Ifcwrn3ILBZs2aaOXOmOnToYIRzt9ttHEw+/PDDuv/++9WyZUtJ8hn14bvvvtPy5cvz3e4qVaqUuXDuvVbBe8Dsdrt16NAhzZ07V3v27Mn1foEY9eG8886T2+2WyWSS2WxWUlKSFi1aZCzzbmvWkUIOHDig77//Xps2bTKeQ9OmTeVwOHKcjg4AgHMpazjv06ePMRXnJ598oi+//FLHjh2TdGbaL5PJpHHjxuU56sOSJUuMf0+cONEY5aGo4VzKPurDO++8I8l31IewsDB9/vnnGjFihB9fIQAAABQGza30oLkBABA4NDcAAIDQwAmrAPyqMAE9MzMz13DudrvVtm1bvffee6pZs6ZcLpfxGGazWTabzYipN998s7p16+YT170HfF9//bXcbneu06KVRd6DdOn0gfncuXP12GOP6bbbbtPTTz+t3r17KykpKdf7+yugZ91/5cuXN/bTvn379OWXX2rVqlU+V6F6R6PYvn27Zs6cqWnTphnT05UrV049e/aUzWbLdXQIAADOhbPD+dq1a2W1WmW1WpWRkaHjx4+rQoUKxu0LGtAffPBB/fbbb5o5c6YmTpxY6CnJcpM1oN9www0+AT0iIkKZmZmKi4vT3Xff7a+XCAAAAEVAcwt+NDcAAAKH5gYAABA6TB4uiwUQAHlNVdahQwc9/fTTio+Pl5RzOL/iiis0ZswYValSJc+ps7LG1ZdfflkzZsww1uHxeFSzZk3Nnz9fERER5+BZB7+sr9eUKVO0atUqLVmyxPh6ZGSk7Ha7LrzwQo0dO1aNGzfOdV3+mqrswIEDGjJkiDZt2uSzjksuuURXXXWV7rrrLplMJlksFn3//fdasmSJli9fbnygEhkZqeeff1533HFHkV8XAAD8Ibdw7na7ZbFY1LVrV7344os5TsGZ11RlNptNmZmZks78rvZHOM8q6/YsWrRIQ4YMkSRVrFhRU6dO1YUXXliclwYAAAB+QnMLTjQ3AAACh+YGAAAQWjhhFUDA5BXQO3XqpFGjRmnMmDGaNm2apDPh/Morr9To0aPzDede3tscP35cd9xxh/bt2yeTySSr1ary5ctrzpw5qlSpUsCfb2ngnYbshRde0MqVK41RGbzROuvUcXXq1NGECRNUp06dXEdQ8FdAX7NmjXr37i2Px+OzDknG1HGRkZHatWuXz1WpYWFh6t69u4YOHaqYmJiivzAAABRTfuH89ttv10svvSSz2Zxr5M4roHunIZPkE84/++wz1alTp1jh3CtrQP/222/13HPPadasWWrYsGGx1gsAAAD/orkFH5obAACBQXMDAAAIPZywCiCg8groVapU0c6dOyUVPZx7eTweZWRkqHfv3tq0aZMRWCtWrKh58+apYsWKgXqKpUZqaqp++eUXffDBB/r7779ltVrl8XjkcrmMaVOuvvpq1apVSxdddJFsNpsuuugiValSJc/1Fjegew/UFy1apKFDh8rj8SgsLEwOh8MnFHinb/F+H4WHh+vWW2/V0KFD+XAEAFCi/BHOvfIK6NKZ35vlypXT0qVLFRUV5TMlbHFlDegnT57kw2kAAIAgRXMLHjQ3AAACg+YGAAAQmjhhFUDA5RbQvQo7JVlOvAetgwYN0tKlS42rIGvVqqUvv/xSsbGx/n5apcqRI0e0cOFCTZkyRXv37jUOij0ejxo3bqzOnTvryiuvVJMmTYq0fn+N+rB48WINHTrUJ5hLkslkMmKC0+lUZGSkevfurX79+hnT3AEAUBL8Gc69ChLQJSkxMVEtW7Y0/p3b6EyF5Q3oZ0+hBgAAgOBCcyt5NDcAAAKD5gYAABC6OGEVwDlxdkD3xlGvSy+9VB9++KGio6MLHc690tLS1LVrV+3atcuYZuvee+/VU0895a+nUSodOXJEs2bN0uzZs3X48GFj+QUXXKC2bdtq+PDhCgsLk3TmYLko+8Bfoz5s3LhRkyZN0ubNm7V//36f25QvX16xsbF67rnndNlllykiIqJQ2wgAgD8FIpx75RXQrVarcTLChAkTlJCQ4PeADgAAgNKB5lZyaG4AAAQGzQ0AACC05X/pLQD4QUJCgt544w0joHsPNCXJbDarfPnyio6OlnTmCsaC8kbXX375RUePHjUOWiWpbt26/n0ipcyJEyc0f/58zZo1S0eOHDGWt2vXTl27dlWHDh18RlLwHnAX5cOL888/Xz179pQkTZ8+XRkZGUZAnzJlinHwn9v0Kd6rSps3b66XX35Zx48f18KFC5Weni6Hw6GIiAi1bdtWdevWZbo5AECJC2Q4l85My2mxWDRu3DhJMgK60+k0RtB64IEHfAI6IzQAAACULTS3kkFzAwAgMGhuAAAAoY8RVgGcU1lHffBOISZJUVFRuv766/X8888rLi6uwKMNZD0YffTRR7VgwQIjwrZt21Yff/xxQJ9PsPIeOP/4448aPXq0z6gJnTt3Vr9+/XTRRRdJUpFH18iNd9SH6dOny+Vy+Yz60Ldv3zwDOgAApUGgw3lWjPoAAACAgqC5nRs0NwAAAofmBgAAUDb4r5YAQAEkJCTozTffVHR0tHGloiSlp6cboTclJcWYXiwv3gNUSXr77be1YMECSafDcfXq1dW1a1fjdmWJy+WSyWTSoUOH9Pbbb/uE83bt2um+++4zwrnH4/FrOJfOjPpwzz33yGKxGKM+SNLUqVM1btw440AfAIDSJq9wbjabdcstt+jll1/2SziXzoz6YDKZNG7cOHXu3NkI5Fn/lnrggQe0bNkyI5pzXSIAAEDZQnMLPJobAACBQ3MDAAAoOzhhFcA5d8011+iNN95QdHS0HA6HcdBnt9u1aNEijRo1Kt+AnnWEgk8++UQTJkyQdPqqR7PZrDZt2qht27aSijbVVmnmPUh/8cUXtX37dlmtVklSixYt1KNHDzVt2tS4baCuBM0poIeFhUkioAMASq+8wrnb7VZ0dLSuvPJK4/bFDedZ10NABwAAQH5oboFFcwMAIDBobgAAAGVL2SpKAIJGQkJCngF95MiRuQb0rOF86tSpGj9+vNxut2w2m5xOpxo0aKBHHnlE5cuXP9dPK2jMmTPHOKD36tChgxISEiSdm4PpswN6ZmYmoz4AAEqtvMK5d1rQEydOaNKkSZo/f77sdrtfH5+ADgAAgIKguQUWzQ0AAP+iuQEAAJQ9nLAKoMTkFdB/+OGHHAP62eH8/fff14kTJ2S1WuVwOFS1alW99dZbqlGjRok9r2Dw22+/KTU1VS6XS06nU61bt9aAAQNkMpmMA/xzganKAAChIL9w7vF4ZLFYZDabtXXrVk2YMEE//fQTAR0AAAAlguYWODQ3AAD8h+YGAABQNnHCKoASlV9AzzpVWWZmpk84/+CDD5SSkiKr1Sqn06m4uDh9/PHHOv/880vwGZW8X3/9VV9//bWk0wfZ5cqV0+DBgyXJOOA+lwjoAIDSLK9wbjabVa1aNUVERMjpdMpsNstsNmv79u368MMPCegAAAAoMTQ3/6O5AQDgPzQ3AACAsosTVgGUuPymKhs1apSSk5MVFhYm6Uw4947y4A3nM2bM0AUXXFCST6VEeQ+K//77b1mtVuO1CQ8PV+3atSWdPuAuCQR0AEBplFc4t1gs6t69u9566y0lJCQQ0AEAABB0aG7+QXMDAMC/aG4AAABlGyesAggK+QX0sWPHyuVyadasWT5TkhHOzzCZTHI6nfruu+/kdDqN5e3bt1etWrVK/IA5v4D+8ssv+2w3AAAlKb9wfvvtt+u5555T8+bN1b9/f1111VVBG9B//vnncz7aEwAAAIIDza34aG4AAPgPzQ0AAACcsAogaOQV0BcsWKDu3btr3Lhx2aYkI5yf4XK5ZLfbZTab5XK5JEmRkZGSFBQHzTkF9OjoaEnS559/ruPHj5fsBgIAoIKF85deesn4fdu8eXMNGjQoaAP6/fffr+XLlwfF3wIAAAA492huxUdzAwCg+GhuAAAAkDhhFUCQSUhI0JtvvpljQN+8ebNSU1MJ53nYt2+fDh486LPMG6dLerQHr6wBPTw8XGlpaapUqZK++eYbVapUqaQ3DwBQxhU2nHun/mzWrFnQBfSst6lcubJfHxcAAAClC82teGhuAAAUD80NAAAAXpywCiDoXHPNNdlGffBenWiz2Qjn+XC5XHK73cZrFhUVJencjvZw8uRJ7d27N9evn3/++br77rt12223KS4uTpMnT1b9+vXP2fYBAJATt9tthPN+/frlGM5HjBiRLZx7BVNAlySHw6G4uDjNmzeP37MAAACguRUTzQ0AgKKhuQEAACArTlgFEJTOnqrMYrHIarUaB4GE85y5XK5sV3j++eefRlA/V3bt2qXhw4dry5Ytud6mTp06GjBggL799ls1aNDgnG0bAAC5MZvNcrvd6tWrl1avXi2bzZZtlAeTyZRjOPcKloCekJCgyMhIffbZZ/zNBAAAAAPNrWhobgAAFB3NDQAAAFlxwiqAoJU1oDudTsJ5AcTGxiouLk5Wq9WI6Hv27JHJZJLZHPgf+d7HzMjI0Pr16zV8+HAlJSXlevvatWszJRkAoMRl/eB53bp1yszMlCRj1KncpiTLTTAE9A8//FALFizQhRde6NfHAAAAQOlHcys8mhsAAIVHcwMAAEBOOGEVQFBLSEjQW2+9Jen09FqE87xVqFBB5cqVk9PplHT6IHrnzp36+eefJSnbSBD+5p0CbdeuXZKkf/75R/fff7927NgR0McFAKConE6nzxSel1xyiR5++GG1bdtWJpNJt9xyS55TkuUmGAJ6lSpV/LpuAAAAhA6aW+HQ3AAAKByaGwAAAHJjLekNAID8XH311Zo8ebKqVq2qevXqlfTmBC23262wsDDVrVtX27dvl8VikdPpVGpqqtauXat27dr5xIFAbYPZbNZff/0lSYqKitLhw4e1cuVKPvQAAAQdp9Mpq9Uql8ulXr16qX379howYICuu+46mUwmXXPNNerdu3e+U5LlxhvQJenXX3/VqVOnZLWePgTzBnRJuvbaaxUZGem351XY7QQAAEDZRHMrGJobAACFQ3MDAABAXjhhFUCpcOWVV5b0JgQ97/Rj1113nRYtWiSn02lc8Tlt2jRdeeWVuuKKKwK+DSkpKcboEunp6ZKkpk2bBvRxAQAorKzhvF+/flq/fr3Wr1+vyMhI9erVS9dee61x26KEc6+SCugAAABAQdDc8kdzAwCg4GhuAAAAyI+5pDcAAOBfjRs3Vq1atYyYbjab5XA4NGfOHB04cCBgj+t2uyWdDgOHDh2SzWaT2WxWmzZt1KRJk4A9LgAAhZU1nPfp00erV69WWFiYJGnUqFFatWqVz+2LO3pCSU1VBgAAAMB/aG4AAOSN5gYAAICC4IRVAAgxDRs2VJs2beR2u+V2u40pVZYuXao1a9YE5DE9Ho8R65csWSK73S6n0ym3263mzZsrPDw8II8LAEBhnR3O165dK6vVKqfTqYiICHXt2lWtW7f2++MS0AEAAIDSjeYGAEDuaG4AAAAoKE5YBYAQ4vF4JEkDBgxQ/fr15fF45Ha7ZbValZKSotdee01//PGHpDOjM/iDyWSSJM2aNUvz5883tqVJkyYaMGCAz7YBAFBScgvnbrdbFotFt956q1555RWZzWa5XC6/P36zZs00ePDgfAO6d3pPAAAAAMGB5gYAQO5obgAAACgMTlgFgBDijdhVqlTRlVdeKZvNZoz2YLVadeTIET3++OPatWuX38PAhg0bNH/+fJlMJuNxL730UkVGRvpsGwAAJSG/cH777bfrpZdeMn5vFndKstw0bdpUgwcP1tVXX51rQF+6dCkBHQAAAAgiNDcAAHJGcwMAAEBhccIqAISgqKgo9e3bV3Xq1DFGe/AG9AMHDui+++7Tnj17/BYG9u7dq2+++UZ//PGHPB6PHA6Hqlevrr59+zI1GQCgxBU0nHs/WA5UOPdq2rSpBg0aREAHAAAAShmaGwAAZ9DcAAAAUBScsAoAIap69eoaN26coqKi5HA4ZLFYjIC+b98+9e3bVxs2bCjSurNONbZv3z599dVXmjlzpjF6RGRkpEaNGqXq1av75bkAAFBUwRbOvQjoAAAAQOlEcwMAgOYGAACAouOEVQAIYY0aNdJrr72mqKgoOZ1On4C+f/9+PfLII1q0aJGOHj1q3Mftdue5TpfLZUw1tnnzZn3yySeaOHGinE6nJCkiIkKDBw9W69atA/fEAAAogGAN514EdAAAAKB0orkBAMoymhsAAACKw+TJeskuACDkuN1uff3113r55Zdlt9uNiGCxWOR0OhUXF6eOHTvqlltu0aWXXmrcz3sbj8cjk8kkt9sts/nMdQ6LFi3S/PnztXjxYmOUh7CwMPXq1UsPPvigypUrd86fKwAAXsEezrPavHmzxo8fr19++UWnTp0yttPtdqt+/fp68MEHdc011yg6OrrEthEAAACAL5obAKAsorkBAACguDhhFQDKAIfDoa+//lqjR49Wenp6toButVoVExOje++9V5deeqlatWqV43pOnTqlffv2aebMmfriiy+UkZFhjA4RFhamm2++WY8//rgqVqx4Lp8eAAA+AhHOAx3Y8wrolStX1vPPP68OHToYIy4BAAAAKHk0NwBAWUJzAwAAgD9wwioAlBEul0uLFy/WM888o7S0NFksFmMEB7fbLe+vgypVquiCCy5Qs2bN1KhRIzkcDjmdTp04cUILFy7UkSNHtH//fkmS1WqV0+lURESE7rzzTg0aNEiVKlUqyacJACjjAhHOs454NG3aNNWuXVvXXHON30P22QE9IiJCp06dksVi0ffff6/atWv79fEAAAAAFB/NDQBQFtDcAAAA4C+csAoAZczmzZv16KOPat++fXK73TKZTDKbzTKZTHI6nUZMz43FYpHL5ZLNZpPD4VBUVJQeeeQRde3aVXFxcefwmQAA4CvQ4fzjjz/W2LFjVaFCBY0ePVrt2rULWEBfuXKlTp48qfLly2v69Om68MIL/fo4AAAAAPyL5gYACFU0NwAAAPgTJ6wCQBm0d+9eTZw4UatWrdLOnTuNYO4NDpJkNpvl8XiMUSAsFovxb7fbLZvNpipVqmjUqFFq3bp1QKdsAQAgP4EO55MmTdKECRN06tQpOZ1OSdJHH32kq666yu/PZcuWLRo7dqz+/vtvTZ48WfXr1/f7YwAAAADwP5obACDU0NwAAADgb5ywCgBlVGpqqv79919NnTpVK1euVHJysvE1m80mp9Mpk8lkjO6QdQSIli1bqm3btrrzzjtVtWrVkth8AAAMeYVzs9msHj166KmnnpLNZitWOD958qQxNWdYWJi+++471axZMyDPKSkpSXFxcapWrVpA1g8AAAAgMGhuAIBQQXMDAABAIHDCKgBAa9asUVJSkubPn69Dhw7p+PHjstvtkk6P+lCuXDnZbDZ17NhRdevWVY8ePSRJVqu1JDcbAACDy+XSHXfcoaSkJCOcezwe1a5dWzNnzlSFChWUmZmpsLCwfNeVXzivVKmSEhMTVatWrQLHeAAAAABlD80NAFDa0dwAAADgb5ywCgBlmMfjkclkMv6dmZmpzMxM7du3T8ePH5fH45HFYlGtWrUUFham+Pj4XO8LAEBJ2rBhg7p37y5JCgsLU2ZmpiQpMjJSN954o4YPH674+HifMJ6TgoTzGTNmqHbt2oRzAAAAADmiuQEAQgXNDQAAAP7GCasAAENeEYBYDgAIdr/88ouGDRum1NRUI3ZLpwP6DTfcoOeee06xsbG5BnTCOQAAAIBAoLkBAEozmhsAAAD8iRNWAQAAAISMZcuWadiwYUpLS5PNZpPD4ZCUf0DPKZynpaXJYrEQzgEAAAAAAFCm0dwAAADgL7mPyw8AAAAApUxCQoLeeOMNRUdHy+FwyGazSZLsdrsWLVqkUaNGKSUlRWazWW63W1LuozwQzgEAAAAAAACaGwAAAPyHE1YBAAAAhJTCBPTMzEymJAMAAAAAAADyQXMDAACAP5g8Ho+npDcCAAAAAPwtr6nKOnTooKefflrx8fGSAhPOz54CTZI8Ho9MJpN/niAAAAAAAABwjtHcAAAAUByMsAoAAAAgJOU16sMPP/ygsWPHyuFwaNq0aQEN5z/99JM2bNggSTKZTOKaQQAAAAAAAJRWNDcAAAAUByOsAgAAAAhpeY36ULduXe3atUvp6emyWCx+D+dTpkzRG2+8oauuukoDBw5Uy5Yt/f78AAAAAAAAgHON5gYAAICi4IRVAAAAACEvt4DuHX0hEKM8fPrpp/rggw90/PhxSdJll12mYcOGqUWLFn59bgAAAAAAAEBJoLkBAACgsMwlvQEAAAAAEGi5TVUmnQ7oTqdT8fHxmjdvnt/C+fvvv6/jx48rPDxckrRu3TpVrlzZf08KAAAAAAAAKEE0NwAAABQWJ6wCAAAAKBPODuhWq9X4mslkUqtWrRQfH1+kdecUzk+cOCGr1aqMjAyVL19eX375papVq+aX5wIAAAAAAAAEA5obAAAACoMTVgEAAACUGVkDutPpNEZ08Hg8WrFihZ544gmdOHFCFotFbre7QOvMK5w7nU7FxsZq+vTpql+/fsCeFwAAAAAAAFBSaG4AAAAoKE5YBQAAAFCmJCQk6M033zQCunfUh/T0dP34448aPXq0UlJSZDab8w3oBQnnM2bM0IUXXhjw5wUAAAAAAACUFJobAAAACoITVgEAAACUOddcc43PVGU2m02SZLfbtWjRIo0aNSrfgE44BwAAAAAAAM6guQEAACA/Jo/H4ynpjQAAAACAkrBs2TINGzZMaWlpstlscjgckqTIyEh16NBBzz//vGJjY31CueQbzqdOnaoPPvjAJ5zHxcVpxowZuuCCC0rkeQEAAAAAAAAlheYGAACA3DDCKgAAAIAyKyEhIddRH3744QeNHDky26gPhHMAAAAAAAAgdzQ3AAAA5IYTVgEAAACUafkF9KxTlWVmZhLOAQAAAAAAgHzQ3AAAAJATk8fj8ZT0RgAAAABASctrqrIbbrhBTz31lOLj4yURzgEAAAAAAICCoLkBAAAgK0ZYBQAAAADlPerDokWLNHbsWLlcLs2aNUvvv/8+4RwAAAAAAADIB80NAAAAWTHCKgAAAABkkdeoDxdccIF27dql1NRUwjkAAAAAAABQQDQ3AAAASJywCgAAAADZ/Pzzz3rssceyBXSTySSPx0M4BwAAAAAAAAqJ5gYAAABOWAUAAACAHJw96oPT6ZQkWa1WORwOwjkAAAAAAABQSDQ3AACAso0TVgEAAAAgF1kDutVqlclkIpwDAAAAAAAAxUBzAwAAKLs4YRUAAAAA8pA1oEsinAMAAAAAAADFRHMDAAAomzhhFQAAAADy8csvv2jgwIEymUyaP38+4RwAAAAAAAAoJpobAABA2cMJqwAAAABQACtWrFDVqlVVr169kt4UAAAAAAAAICTQ3AAAAMoWTlgFAAAAAAAAAAAAAAAAAABAQJlLegMAAAAAAAAAAAAAAAAAAAAQ2jhhFQAAAAAAAAAAAAAAAAAAAAHFCasAAAAAAAAAAAAAAAAAAAAIKE5YBQAAAAAAAAAAAAAAAAAAQEBxwioAAAAAAAAAAAAAAAAAAAACihNWAQAAAAAAAAAAAAAAAAAAEFCcsAoAAAAAAAAAAAAAAAAAAICA4oRVAAAAAAAAAAAAAAAAAAAABBQnrAIAAAAAAAAAAAAAAAAAACCgOGEVAAAAAAAAAAAAAAAAAAAAAcUJqwAAAAAAAAAAAAAAAAAAAAgoTlgFAAAAAAAAAAAAAAAAAABAQHHCKgAAAAAAAAAAAAAAAAAAAAKKE1YBAAAAAAAAAAAAAAAAAAAQUJywCgAAAAAAAAAAAAAAAAAAgIDihFUAAAAAAAAAAAAAAAAAAAAEFCesAgAAAAAAAAAAAAAAAAAAIKA4YRUAAAAAAAAAAAAAAAAAAAABxQmrAAAAAAAAAAAAAAAAAAAACChOWAUAAAAAAAAAAAAAAAAAAEBAccIqAAAAAAAAAAAAAAAAAAAAAooTVgEAAAAAAAAAAAAAAAAAABBQ1pLeAAAAAAS/r776Ss8884zPsocffliPPPJICW1R2XTddddp3759Psu2bt1aQluDrPbu3avrr7/eZ1mbNm00bdq0EtoiAAAAAAAQ7GhuwYHmFrxobgAAAKGHEVYBAAAAAAAAAAAAAAAAAAAQUJywCgAAAAAAAAAAAAAAAAAAgIDihFUAAAAAAAAAAAAAAAAAAAAElLWkNwAAAAAINQcOHFCXLl18lrVq1UoffvhhyWwQfHz77bd6+eWXfZYNGDBAAwcOLKEtAgAAAAAAQH5obsGN5gYAAICC4IRVAAAAwM9cLpeOHz/us+zkyZMlszHIJiMjI9v+OXXqVMlsDAAAAAAAAAqE5hbcaG4AAAAoCE5YBQAAAEqJJUuWlPQmIBc1a9bU1q1bS3ozAAAAAAAAUEg0t+BFcwMAAAg95pLeAAAAAAAAAAAAAAAAAAAAAIQ2TlgFAAAAAAAAAAAAAAAAAABAQHHCKgAAAAAAAAAAAAAAAAAAAAKKE1YBAAAAAAAAAAAAAAAAAAAQUNaS3gAAAACcW263W5s3b9a2bdv033//ye12KyYmRrVq1VKzZs1UsWLFc7o9LpdL27dv1z///KPDhw/LbrcrMjJS8fHxOu+889S8eXNFR0cH5HH//fdfbdu2TcePH9fJkyflcrkUGRmpyMhIVa5cWTVq1FDt2rUVERHh98cPZv/884+SkpJ06NAhnTp1SnFxcapYsaIuuugiVa9ePSCPeeLECf3zzz/avXu3UlJSlJaWJpvNpri4OJUvX17169dXnTp1AvLYwS49PV2bN2/W7t27dezYMWVmZioiIkLx8fE6//zz1aRJE4WFhZ2z7fF4PNq6dau2bt2qo0ePyuFwqEKFCqpYsaJatmx5zn+GAAAAAAAQDGhuZx6X5pYzmltwobkBAACUDE5YBQAAKCOSk5M1adIkzZkzR8eOHcvxNmazWS1btlTfvn3VsWPHgG7PihUr9MUXX2jp0qVKS0vL9XY2m02tW7dWly5ddOutt8psLt4kAcuWLdOcOXO0dOlS2e32fG9vs9nUoEEDtW7dWh06dNAll1yS4zb07t1bq1atynU9q1atUsOGDfN9vDZt2mjatGk5fu26667Tvn37fJZt3bo133VKyvbYNWrU0JIlS4x/2+12JSYmKjExUbt37851PfXq1VOfPn3UrVs3Wa1FP5xISUnRkiVL9Pvvv2v16tXas2dPvvc577zzdMUVV6hfv35q2rRpoR4vv9f+vffe03vvvZfveh5++GE98sgj2Zbv3btX119/vc+yvPZlflwul7777jt9+eWXWr16tZxOZ663DQ8P11VXXaXu3bsrISGhSI9XkO0/fvy4pk6dqs8//1xHjhzJcT0mk0lNmjTRgAEDdNNNNxVpWwAAAAAAKE1obqfR3E6jufmiudHcAAAAzsYJqwAAAGXAvHnzNGLECJ08eTLP27ndbq1du1Zr165V27ZtNW7cOMXHx/t1W7Zs2aIRI0Zo/fr1Bbq9w+HQypUrtXLlSk2ePFkvvPCCWrduXejH3bVrl1544QX99ttvhbqfw+HQ5s2btXnzZk2dOlWDBg3SY489VujHD2Zr1qzRU089pb179+Z723/++UcvvfSSZsyYoQkTJhR69IdDhw7phRde0PLly+VwOAp13yNHjmjevHmaN2+eEhISNHr0aFWqVKlQ6ygNVq9erRdeeEH//PNPgW6fkZGhxYsXa/HixWrZsqVeeeUV1a9f36/b9OOPP+p///ufkpOT87ydx+PR5s2b9dhjjykxMVHvvfee4uLi/LotAAAAAAAEC5obzS0vNLfgQnMDAAAIDsW7VA4AAABB77333tMTTzyRbzg/2/Lly9WjR49cr+ouiunTp+uuu+4qcDg/29atW9WvXz/NnTu3UPdLSkpSjx49Ch3Oc+JyuYq9jmDy/fffq1+/fgUK51lt27ZNPXv2LPT9Dh8+rKVLlxY6nJ9t2bJluuOOO7R58+ZirSfYTJkyRX379i1wOD/bunXr1K1bNy1atMiv2/Twww/nG87PtmrVKt1zzz1KSUnx27YAAAAAABAsaG40t7zQ3IILzQ0AACB4MMIqAABACJs6darefffdHL9mNpvVrFkz1ahRQzExMTpy5IiSkpJ08OBB4za7du3S4MGDdddddxV7W957771ct0U6Pe1VvXr1VL58eTmdTh09elTr16/PFv0dDoeeeuopORwOdevWLd/HTUtL0+DBg3MNf9WrV1e9evVUqVIlRUREKCMjQydPntTBgwe1Y8cOpaenF+6JliIrVqzQE0884ROyw8PD1bx5c1WpUkVRUVE6fvy4Nm7c6PN94XXw4EE9++yzmjp1qkwmU7G2JSIiQhdeeKGqVKmicuXKKTw8XGlpaTp8+LC2bNmS44c/Bw8e1AMPPKCvv/5aFStWLNbjB4MpU6ZozJgxuX69YcOGqlOnjsqXL6///vtPO3bs0M6dO7Pdzm6369FHH9U777yj9u3bF2ub5syZk22boqOj1bx5c+M9899//2n9+vU5vse2bdum0aNH6//+7/+KtR0AAAAAAAQTmhvNLS80t+BCcwMAAAgunLAKAAAQorZv366xY8dmW26xWNS3b1/169dPVapU8fmax+PRmjVrNGbMGOMq+k2bNiktLa1Y2/LDDz/kGM7Lly+vPn36qHv37jlOM+V0OvXjjz/qzTffzBYJR44cqYsvvjjfaZg++ugj7d+/32eZyWRS9+7d1bdvX9WrVy/X+3o8Hv39999aunSpfvzxxzxHqfjggw+MCH3w4EHdfvvtPl9v2bKlPvjggzy3VZJsNlu+t/GHkydP6vHHHze2uUaNGhoyZIg6deqkiIiIbLdfsWKFRowYkW0//P777/r222918803F3obLr74YrVv317t2rVTvXr1ZLFYcrydx+PRypUr9cknn+jnn3/2+dqRI0f05JNP6uOPP87zsVauXGn893fffadXXnnF5+v9+/fXgAED8t3myMjIfG9TFBs3bszx/SpJXbt21aBBg1SnTp1sX0tKStIbb7yhZcuW+Sx3uVx65pln1LRpU1WrVq1I27R371699NJLxr8bNGigoUOHKiEhIdv3qdvt1sKFCzVq1KhsI8TMmTNHd911l1q1alWk7QAAAAAAIJjQ3E6jueWM5kZzyw/NDQAAlHWcsAoAABCC3G63nnvuuWxTQEVGRmrixIlq06ZNjvczmUy69NJLNXv2bI0YMUKzZ8+WpCJPlSSdDnDPPvtstuVt2rTR66+/rsqVK+d6X6vVqk6dOumaa67RsGHD9NNPPxlfO3XqlJ588knNmTMnz8efP39+tmVjxozJFrdzYjKZVL9+fdWvX18DBw7U5s2bcx01oly5csZ/5zRChM1mU3x8fL6Pea6cOHHC+O927drpzTffVFRUVK63v/LKK5WYmKhevXpl+36YOXNmgeO5zWbTbbfdpv79+6thw4YFuo/JZNKVV16pK6+8Ul988YX+97//ye12G1//9ddftX79el188cW5riPra5/T84yMjCyx/WO32zV8+HA5nU6f5VarVW+88YY6duyY630bNWqkiRMn6uOPP9Zrr73m87WUlBQ9+eST+vTTT4s0GkfWD53uvPNOjRgxQlZrzoeQZrNZN954o5o2baqePXvq6NGjPl+fNWsW8RwAAAAAUOrR3M6gueWM5uaL5pYdzQ0AAJR15pLeAAAAAPjf4sWLtWHDhmzL33rrrVzDeVZWq1UjRozQ9ddfX+xtee2115SSkuKzrGXLlpo0aVKe4TyrqKgovfPOO2rWrJnP8i1btmS7+j+rw4cPa/fu3dkeuyDhPCdNmzbV1VdfXaT7BquWLVvq/fffzzOce8XHx2vUqFHZlq9evTrH6cty0qhRI7322msFDudnu/POO/XUU09lWz516tQirS8YfPXVV9q1a1e25aNGjcoznGfVv39/DRo0KNvyVatWafny5cXavk6dOmnUqFG5hvOsateuraeffjrb8oULFyozM7NY2wEAAAAAQEmjuZ1Gc8sfza3k0dwAAACCEyesAgAAhKCZM2dmW3bzzTerXbt2BV6H2WzWSy+9pOjo6CJvx+7du/XDDz/4LIuKitLbb7+d4xRYeQkLC9OYMWOy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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "DISPLAY_NAME = {\n", + " 'bristen': 'Bristen',\n", + " 'clariden': 'Clariden',\n", + " 'euler': 'Euler',\n", + " 'jsc': 'JSC',\n", + " 'oci-1': 'OCI-1',\n", + " 'oci-2': 'OCI-2',\n", + " 'sgs-amd-01': 'ETH-local',\n", + "}\n", + "# Display order: JSC last (high-latency outlier).\n", + "DISPLAY_ORDER = ['bristen', 'clariden', 'euler', 'oci-1', 'oci-2', 'sgs-amd-01', 'jsc']\n", + "_order_idx = [hosts.index(h) for h in DISPLAY_ORDER]\n", + "display_labels = [DISPLAY_NAME[h] for h in DISPLAY_ORDER]\n", + "# Reorder into new arrays so re-running this cell stays idempotent.\n", + "latency_ord = latency[np.ix_(_order_idx, _order_idx)]\n", + "throughput_ord = throughput[np.ix_(_order_idx, _order_idx)]\n", + "ping_raw_ord = ping_raw[np.ix_(_order_idx, _order_idx)]\n", + "iperf_raw_ord = iperf_raw[np.ix_(_order_idx, _order_idx)]\n", + "\n", + "\n", + "def annotate(ax, M, M_raw=None, fmt='{:.0f}', raw_fmt='{:.0f}', dark_threshold=None):\n", + " \"\"\"Top line: M value (color flips white above dark_threshold). Second line: raw value if available.\"\"\"\n", + " def _fmt(value, spec):\n", + " # Positive values that round to \"0\" are below the format's resolution —\n", + " # show \"<1\" so readers don't think the link is free.\n", + " s = spec.format(value)\n", + " if value > 0 and float(s) == 0:\n", + " return '<1'\n", + " return s\n", + "\n", + " n = M.shape[0]\n", + " if dark_threshold is None:\n", + " dark_threshold = np.nanmean(M)\n", + " for i in range(n):\n", + " for j in range(n):\n", + " v = M[i, j]\n", + " if np.isnan(v):\n", + " ax.text(j, i, '—', ha='center', va='center', color='#999999', fontsize=14)\n", + " continue\n", + " color = 'white' if v >= dark_threshold else 'black'\n", + " has_raw = M_raw is not None and np.isfinite(M_raw[i, j])\n", + " if has_raw:\n", + " ax.text(j, i, _fmt(v, fmt), ha='center', va='bottom', color=color, fontsize=11)\n", + " ax.text(\n", + " j, i, '(' + _fmt(M_raw[i, j], raw_fmt) + ')',\n", + " ha='center', va='top', color=color, fontsize=9, alpha=0.85,\n", + " )\n", + " else:\n", + " ax.text(j, i, _fmt(v, fmt), ha='center', va='center', color=color, fontsize=11)\n", + "\n", + "\n", + "def set_panel_title(ax, main, sub):\n", + " \"\"\"Two-line title: bold main on top, smaller dim subtitle below.\"\"\"\n", + " ax.set_title(main, fontsize=15, fontweight='bold', pad=18)\n", + " ax.text(\n", + " 0.5, 1.01, sub,\n", + " transform=ax.transAxes,\n", + " ha='center', va='bottom',\n", + " fontsize=11, color='#555555',\n", + " )\n", + "\n", + "\n", + "fig, axes = plt.subplots(\n", + " nrows=1, ncols=2, figsize=(9.0, 4.25),\n", + " gridspec_kw={'width_ratios': [1.0, 1.0], 'wspace': 0.05},\n", + " constrained_layout=True,\n", + ")\n", + "fig.get_layout_engine().set(w_pad=0.01, wspace=0.05)\n", + "ax_lat, ax_thr = axes\n", + "\n", + "# With aspect='equal' the axes box shrinks to a square and is centered in its\n", + "# grid cell by default — that centering is the leftover whitespace between panels.\n", + "# Anchor each panel toward the gap so the two heatmaps sit close together.\n", + "ax_lat.set_anchor('E') # left panel hugs the right edge of its cell\n", + "ax_thr.set_anchor('W') # right panel hugs the left edge of its cell\n", + "\n", + "# --- latency heatmap (HTTP avg, ms) with raw ICMP ping in second line ---\n", + "im_lat = ax_lat.imshow(\n", + " np.ma.masked_invalid(latency_ord),\n", + " cmap='magma_r',\n", + " norm=LogNorm(vmin=max(np.nanmin(latency_ord), 1.0), vmax=np.nanmax(latency_ord)),\n", + " aspect='equal',\n", + ")\n", + "set_panel_title(ax_lat, 'Latency (ms)', '')\n", + "ax_lat.set_xticks(range(len(display_labels)))\n", + "ax_lat.set_yticks(range(len(display_labels)))\n", + "ax_lat.set_xticklabels(display_labels, rotation=45, ha='right', fontsize=12)\n", + "ax_lat.set_yticklabels(display_labels, fontsize=12)\n", + "ax_lat.set_xlabel('destination', fontsize=13)\n", + "ax_lat.set_ylabel('source', fontsize=13)\n", + "annotate(ax_lat, latency_ord, M_raw=ping_raw_ord, fmt='{:.0f}', raw_fmt='{:.0f}',\n", + " dark_threshold=np.nanpercentile(latency_ord, 65))\n", + "cb_lat = fig.colorbar(im_lat, ax=ax_lat, fraction=0.046, pad=0.02)\n", + "cb_lat.set_label('ms (log scale)', fontsize=12)\n", + "cb_lat.ax.tick_params(labelsize=10)\n", + "\n", + "# --- throughput heatmap (libp2p stream, Mbps) with raw iperf3 in second line ---\n", + "# YlGn: light yellow at low values (legible black text), dark green at high (legible white).\n", + "# Most cells live in the 40-70 Mbps range; the two oci-1<->oci-2 outliers (~360 Mbps)\n", + "# saturate the dark end without crushing the rest of the scale into a dark band.\n", + "thr_vmin = float(np.nanmin(throughput_ord))\n", + "thr_vmax = float(np.nanmax(throughput_ord))\n", + "im_thr = ax_thr.imshow(\n", + " np.ma.masked_invalid(throughput_ord),\n", + " cmap='YlGn',\n", + " vmin=thr_vmin,\n", + " vmax=thr_vmax,\n", + " aspect='equal',\n", + ")\n", + "set_panel_title(ax_thr, 'Throughput (Mbps)', '')\n", + "ax_thr.set_xticks(range(len(display_labels)))\n", + "ax_thr.set_xticklabels(display_labels, rotation=45, ha='right', fontsize=12)\n", + "# Drop y-axis label and tick labels — rows align with the left panel, which already names them.\n", + "ax_thr.set_yticks(range(len(display_labels)))\n", + "ax_thr.set_yticklabels([])\n", + "ax_thr.set_xlabel('destination', fontsize=13)\n", + "# Switch text to white only on the dark end of the YlGn scale (top ~25%).\n", + "annotate(ax_thr, throughput_ord, M_raw=iperf_raw_ord, fmt='{:.0f}', raw_fmt='{:.0f}',\n", + " dark_threshold=thr_vmin + 0.75 * (thr_vmax - thr_vmin))\n", + "cb_thr = fig.colorbar(im_thr, ax=ax_thr, fraction=0.046, pad=0.02)\n", + "cb_thr.set_label('Mbps', fontsize=12)\n", + "cb_thr.ax.tick_params(labelsize=10)\n", + "save_figure(fig, 'network_profiler', formats=['pdf'])\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "pg", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/meta/tools/plot_utils.py b/meta/tools/plot_utils.py new file mode 100644 index 0000000..e58221f --- /dev/null +++ b/meta/tools/plot_utils.py @@ -0,0 +1,1254 @@ +""" +Plot utilities for scientific paper figures. + +This module provides consistent styling and utilities for creating publication-quality +figures, with default support for double-column formats commonly used in scientific papers. +""" + +import warnings +import numpy as np +import seaborn as sns +import matplotlib as mpl +from matplotlib import rcParams +import matplotlib.pyplot as plt +from typing import Any, Callable, Dict, List, Optional, Tuple, Union +from matplotlib.ticker import FuncFormatter, LogLocator, NullFormatter + +# Figure size configurations for common scientific paper formats +# Widths are in inches, typical for scientific publications +FIGURE_SIZES = { + # Double column formats (default) + "double_column": { + "width": 9, # 3.375 inches per column * 2 columns (standard for many journals) + "height": 3.75, # Golden ratio approximation + }, + # Single column formats + "single_column": { + "width": 3.375, # Standard single column width + "height": 2.75, + "aspect_ratio": 0.81, + }, + # Extended figures + "double_column_wide": {"width": 7.0, "height": 5.0, "aspect_ratio": 0.71}, + # Square figures + "double_column_square": {"width": 6.75, "height": 6.75, "aspect_ratio": 1.0}, +} + +# Default publication style parameters +DEFAULT_STYLE = { + "font.family": "serif", + "font.serif": ["Times New Roman", "DejaVu Serif", "Computer Modern Roman"], + "font.size": 8, # Base font size for double column figures + "axes.labelsize": 8, + "axes.titlesize": 9, + "xtick.labelsize": 7, + "ytick.labelsize": 7, + "legend.fontsize": 7, + "figure.titlesize": 10, + "lines.linewidth": 1.0, + "axes.linewidth": 0.8, + "grid.linewidth": 0.5, + "axes.spines.left": True, + "axes.spines.bottom": True, + "axes.spines.top": False, + "axes.spines.right": False, + "axes.grid": False, + "grid.alpha": 0.3, + "legend.framealpha": 0.9, + "legend.fancybox": False, + "legend.edgecolor": "black", + "legend.frameon": True, + "figure.dpi": 300, + "savefig.dpi": 300, + "savefig.bbox": "tight", + "savefig.pad_inches": 0.1, +} + +# Color palettes for scientific publications +COLOR_PALETTES = { + "basic": [ + "", + "", + ], + "default": [ + "#E69F00", + "#88CCEE", + "#BBBBBB", + "#117733", + "#0000ff", + "#DDCC77", + "#CC6677", + "#D55E00", + "#AA4499", + "#4477AA", + + "#EE6677", + "#228833", + "#CCBB44", + "#66CCEE", + "#AA3377", + "#BBBBBB", + + "#E69F00", + "#56B4E9", + "#009E73", + "#F0E442", + "#0072B2", + "#D55E00", + "#CC79A7", + "#000000" + ], + "colorblind": [ + "#0173b2", + "#de8f05", + "#029e73", + "#cc78bc", + "#ca9161", + "#fbafe4", + "#949494", + "#ece133", + "#56b4e9", + "#009e73", + ], + "grayscale": [ + "#000000", + "#404040", + "#808080", + "#a0a0a0", + "#c0c0c0", + "#606060", + "#909090", + "#b0b0b0", + "#d0d0d0", + "#e0e0e0", + ], + "high_contrast": [ + "#000000", + "#ffffff", + "#ff0000", + "#00ff00", + "#0000ff", + "#ffff00", + "#ff00ff", + "#00ffff", + "#808080", + "#c0c0c0", + ], + "okabe_ito": [ + "#000000", + "#E69F00", + "#56B4E9", + "#009E73", + "#F0E442", + "#0072B2", + "#D55E00", + "#CC79A7", + ], + "glasbey": [ + "#FF0000", + "#00FF00", + "#0000FF", + "#FFFF00", + "#FF00FF", + "#00FFFF", + "#800000", + "#008000", + "#000080", + "#808000", + ], + "bold": [ + "#0D1B2A", + "#F94144", + "#F3722C", + "#F9C74F", + "#90BE6D", + "#43AA8B", + "#577590", + "#277DA1", + ], + "contrast_dark": [ + "#F8F9FA", + "#FFD166", + "#06D6A0", + "#118AB2", + "#EF476F", + "#8338EC", + "#FF006E", + "#3A86FF", + ], +} + +# Marker styles for different plot types +MARKER_STYLES = { + "default_markers": ["o", "s", "^", "v", "D", "<", ">", "p", "*", "h"], + "open_markers": ["o", "s", "^", "v", "D", "<", ">", "p", "*", "h"], + "filled_markers": ["o", "s", "^", "v", "D", "<", ">", "p", "*", "h"], +} + +# Line styles +LINE_STYLES = ["-", "--", "-.", ":", (0, (3, 1, 1, 1)), (0, (5, 1, 1, 1))] + + +def set_publication_style( + font_size: Optional[int] = None, + family: Optional[str] = None, + use_latex: bool = False, + dpi: Optional[int] = None, + style_overrides: Optional[Dict[str, Any]] = None, +) -> None: + """ + Set matplotlib parameters for publication-quality figures. + + Parameters + ---------- + font_size : int, optional + Base font size. Default is 8 for double column figures. + family : str, optional + Font family ('serif', 'sans-serif', 'monospace') + use_latex : bool, default False + Use LaTeX for text rendering. Requires LaTeX installation. + dpi : int, optional + Figure DPI. Default is 300. + style_overrides : dict, optional + Arbitrary rcParams to override built-in defaults (e.g., {'axes.grid': True}). + """ + style = DEFAULT_STYLE.copy() + + if font_size is not None: + style["font.size"] = font_size + style["axes.labelsize"] = font_size + style["axes.titlesize"] = font_size + 1 + style["xtick.labelsize"] = font_size - 1 + style["ytick.labelsize"] = font_size - 1 + style["legend.fontsize"] = font_size - 1 + style["figure.titlesize"] = font_size + 2 + + if family is not None: + style["font.family"] = family + if family == "serif": + style["font.serif"] = [ + "Times New Roman", + "DejaVu Serif", + "Computer Modern Roman", + ] + elif family == "sans-serif": + style["font.sans-serif"] = ["Arial", "Helvetica", "DejaVu Sans"] + + if dpi is not None: + style["figure.dpi"] = dpi + style["savefig.dpi"] = dpi + + if use_latex: + style["text.usetex"] = True + style["font.family"] = "serif" + warnings.warn("LaTeX rendering requires a working LaTeX installation.") + + # Apply the style + if style_overrides: + style.update(style_overrides) + for key, value in style.items(): + rcParams[key] = value + sns.set_style("ticks") + font = { + "font.size": 12, + } + sns.set_style(font) + paper_rc = { + "lines.linewidth": 3, + "lines.markersize": 10, + } + sns.set_context("paper", font_scale=2, rc=paper_rc) + mpl.rcParams["pdf.fonttype"] = 42 + mpl.rcParams["ps.fonttype"] = 42 + +def set_default_plot_settings( + max_columns: int = 500, + seaborn_style: str = "ticks", + font_family: str = "Roboto", + font_size: int = 12, + context: str = "paper", + font_scale: float = 2.0, + linewidth: float = 3.0, + markersize: float = 10.0, + palette_name: str = "tab10", + palette_size: Optional[int] = None, + pdf_fonttype: int = 42, + ps_fonttype: int = 42, + seaborn_rc_overrides: Optional[Dict[str, Any]] = None, +) -> Dict[str, Any]: + """Configure commonly used plotting defaults built on seaborn. + + The configuration mirrors a set of defaults frequently used for paper-ready + plots that rely on pandas and seaborn utilities. The function returns a + dictionary containing convenient handles (palette, line styles, grid + parameters) that can be re-used by callers when building figures. + + Parameters + ---------- + max_columns : int, default 500 + Maximum number of columns displayed by pandas when printing DataFrames. + seaborn_style : str, default 'ticks' + Base seaborn style passed to ``sns.set_theme``. + font_family : str, default 'Roboto' + Primary font family requested from seaborn/matplotlib. + font_size : int, default 12 + Base font size registered with seaborn's rc configuration. + context : str, default 'paper' + Seaborn plot context (e.g., 'paper', 'talk', 'poster'). + font_scale : float, default 2.0 + Global font scaling factor applied by seaborn. + linewidth : float, default 3.0 + Default line width injected into seaborn rc parameters. + markersize : float, default 10.0 + Default marker size injected into seaborn rc parameters. + palette_name : str, default 'tab10' + Name of the palette passed to ``sns.color_palette``. + palette_size : int, optional + Optional number of discrete colors requested from seaborn. + pdf_fonttype : int, default 42 + Matplotlib PDF font type (42 embeds TrueType fonts). + ps_fonttype : int, default 42 + Matplotlib PostScript font type. + seaborn_rc_overrides : dict, optional + Additional RC parameters merged into the seaborn configuration. + + Returns + ------- + dict + A dictionary with keys ``palette``, ``linestyles``, and ``grid_params``. + """ + + try: + import pandas as pd + import seaborn as sns + except ImportError as exc: # pragma: no cover - optional dependency guard + raise ImportError( + "set_default_plot_settings requires pandas and seaborn to be installed." + ) from exc + + pd.set_option("display.max_columns", max_columns) + + rc_updates = { + "lines.linewidth": linewidth, + "lines.markersize": markersize, + "font.family": font_family, + "font.size": font_size, + } + if seaborn_rc_overrides: + rc_updates.update(seaborn_rc_overrides) + + sns.set_theme( + style=seaborn_style, + context=context, + font=font_family, + font_scale=font_scale, + rc=rc_updates, + ) + + palette = sns.color_palette(palette_name, palette_size) + + mpl.rcParams["pdf.fonttype"] = pdf_fonttype + mpl.rcParams["ps.fonttype"] = ps_fonttype + + return { + "palette": palette, + "linestyles": ["-", "--", ":", ":", ":"], + "grid_params": {"width_ratios": [1, 1]}, + } + + +def get_figure_size( + format_type: str = "double_column", + height_ratio: Optional[float] = None, + n_panels: int = 1, + n_cols: int = 1, + width: Optional[float] = None, + panel_scale_factor: float = 0.9, + col_scale_factor: float = 1.2, +) -> Tuple[float, float]: + """ + Calculate figure size based on publication format. + + Parameters + ---------- + format_type : str, default 'double_column' + Type of figure format ('double_column', 'single_column', 'double_column_wide', etc.) + height_ratio : float, optional + Custom height-to-width ratio. If None, uses default for format_type. + n_panels : int, default 1 + Number of subplot panels (approximate height adjustment) + n_cols : int, default 1 + Number of subplot columns + + Additional Parameters + --------------------- + width : float, optional + Override width in inches (bypasses format preset width when provided). + panel_scale_factor : float, default 0.9 + Multiplier applied to height when stacking multiple panels. + col_scale_factor : float, default 1.2 + Multiplier applied to height when using multiple columns. + + Returns + ------- + width, height : tuple of float + Figure dimensions in inches. + """ + if format_type not in FIGURE_SIZES: + raise ValueError( + f"Unknown format type: {format_type}. Available: {list(FIGURE_SIZES.keys())}" + ) + + config = FIGURE_SIZES[format_type] + width = config["width"] if width is None else width + + if height_ratio is None: + height_ratio = config["aspect_ratio"] + + # Adjust height for multiple panels + height = width * height_ratio + + # Scale height for multiple panels/columns + if n_cols > 1: + height *= col_scale_factor # Add space for column layout + if n_panels > 1: + height *= ( + np.sqrt(n_panels) * panel_scale_factor + ) # Scale with sqrt of panel count + + return width, height + + +def create_figure( + format_type: str = "double_column", + nrows: int = 1, + ncols: int = 1, + height_ratio: Optional[float] = None, + figsize: Optional[Tuple[float, float]] = None, + **kwargs, +) -> Tuple[plt.Figure, Union[plt.Axes, np.ndarray]]: + """ + Create a figure with publication-standard dimensions. + + Parameters + ---------- + format_type : str, default 'double_column' + Figure format type + nrows : int, default 1 + Number of subplot rows + ncols : int, default 1 + Number of subplot columns + height_ratio : float, optional + Custom height-to-width ratio + **kwargs + Additional arguments passed to plt.subplots() + + Additional Parameters + --------------------- + figsize : (float, float), optional + Explicit figure size to use (skips get_figure_size when provided). + + Returns + ------- + fig, axes : tuple + Figure and axes objects. + """ + # Calculate figure size unless explicitly provided + if figsize is None: + n_panels = nrows * ncols + width, height = get_figure_size(format_type, height_ratio, n_panels, ncols) + figsize = (width, height) + if figsize == "double_column": + ncols = 2 + nrows = 1 + # Set default figure parameters if not provided + subplot_kwargs = { + "figsize": figsize, + "dpi": rcParams.get("figure.dpi", 300), + "constrained_layout": True, + } + subplot_kwargs.update(kwargs) + + fig, axes = plt.subplots(nrows=nrows, ncols=ncols, **subplot_kwargs) + + return fig, axes + + +def create_default_side_by_side_figure( + figsize: Tuple[float, float] = (9.0, 3.75), + constrained_layout: bool = True, + ncols: int = 2, + nrows: int = 1, + **kwargs, +) -> Tuple[plt.Figure, Union[plt.Axes, np.ndarray]]: + """Create a two-panel figure with defaults matching the seaborn preset.""" + + subplot_kwargs = { + "figsize": figsize, + "constrained_layout": constrained_layout, + "ncols": ncols, + "nrows": nrows, + } + subplot_kwargs.update(kwargs) + + fig, axes = plt.subplots(**subplot_kwargs) + + return fig, axes + + +def apply_color_palette( + palette_name: str = "default", + n_colors: Optional[int] = None, + palettes: Optional[Dict[str, List[str]]] = None, + mode: str = "repeat", + start_index: int = 0, +) -> list: + """ + Get a color palette for plotting. + + Parameters + ---------- + palette_name : str, default 'default' + Name of color palette. Options include 'default', 'colorblind', + 'grayscale', 'high_contrast', 'okabe_ito', 'glasbey', 'bold', + 'contrast_dark'. + n_colors : int, optional + Number of colors to return. If None, returns all colors in palette. + palettes : dict[str, list[str]], optional + Custom palette registry to override or extend built-ins. + mode : {'repeat','truncate'}, default 'repeat' + If n_colors exceeds palette length, either repeat or truncate. + start_index : int, default 0 + Starting index into the palette before cycling/truncating. + + Returns + ------- + colors : list + List of color hex codes. + """ + registry = {**COLOR_PALETTES} + if palettes: + registry.update(palettes) + if palette_name not in registry: + raise ValueError( + f"Unknown palette: {palette_name}. Available: {list(registry.keys())}" + ) + + colors = registry[palette_name] + if start_index: + colors = colors[start_index:] + colors[:start_index] + + if n_colors is not None: + if mode == "repeat": + # Cycle through colors if needed + n_full_cycles = n_colors // len(colors) + n_remaining = n_colors % len(colors) + colors = colors * n_full_cycles + colors[:n_remaining] + elif mode == "truncate": + colors = colors[:n_colors] + else: + raise ValueError("mode must be either 'repeat' or 'truncate'") + + return colors + + +def style_axes( + ax: plt.Axes, + title: Optional[str] = None, + xlabel: Optional[str] = None, + ylabel: Optional[str] = None, + xlim: Optional[Tuple[float, float]] = None, + ylim: Optional[Tuple[float, float]] = None, + grid: bool = False, + spine_style: str = "default", + legend: bool = False, + legend_kwargs: Optional[Dict[str, Any]] = None, + grid_alpha: Optional[float] = None, + grid_linewidth: Optional[float] = None, + minimal_spine_offset: int = 10, + legend_style: Optional[Dict[str, Any]] = None, + **kwargs, +) -> plt.Axes: + """ + Apply consistent styling to axes. + + Parameters + ---------- + ax : matplotlib.axes.Axes + Axes object to style + title : str, optional + Axes title + xlabel : str, optional + X-axis label + ylabel : str, optional + Y-axis label + xlim : tuple, optional + X-axis limits + ylim : tuple, optional + Y-axis limits + grid : bool, default False + Whether to show grid + spine_style : str, default 'default' + Spine style ('default', 'box', 'minimal', 'none') + legend : bool, default False + Whether to show legend + legend_kwargs : dict, optional + Additional keyword arguments forwarded to ax.legend() + **kwargs + Additional styling arguments + + Returns + ------- + ax : matplotlib.axes.Axes + Styled axes object. + """ + # Set labels and title + if title is not None: + ax.set_title(title, pad=10) + if xlabel is not None: + ax.set_xlabel(xlabel, labelpad=5) + if ylabel is not None: + ax.set_ylabel(ylabel, labelpad=5) + + # Set limits + if xlim is not None: + ax.set_xlim(xlim) + if ylim is not None: + ax.set_ylim(ylim) + + # Configure spines + if spine_style == "default": + ax.spines["top"].set_visible(False) + ax.spines["right"].set_visible(False) + elif spine_style == "box": + ax.spines["top"].set_visible(True) + ax.spines["right"].set_visible(True) + elif spine_style == "minimal": + ax.spines["top"].set_visible(False) + ax.spines["right"].set_visible(False) + ax.spines["left"].set_position(("outward", minimal_spine_offset)) + ax.spines["bottom"].set_position(("outward", minimal_spine_offset)) + elif spine_style == "none": + for spine in ax.spines.values(): + spine.set_visible(False) + + # Configure grid + if grid: + ax.grid( + True, + alpha=0.3 if grid_alpha is None else grid_alpha, + linewidth=0.5 if grid_linewidth is None else grid_linewidth, + ) + + # Configure legend + legend_obj = None + if legend: + handles, labels = ax.get_legend_handles_labels() + if handles: + legend_params = dict(legend_kwargs or {}) + legend_obj = ax.legend(**legend_params) + + if legend_obj is None: + legend_obj = ax.get_legend() + + if legend_obj is not None: + # Defaults mirror the previous behavior; allow overrides via legend_style + frame_on = True if legend_style is None else legend_style.get("frameon", True) + edgecolor = ( + "black" if legend_style is None else legend_style.get("edgecolor", "black") + ) + fancybox = ( + False if legend_style is None else legend_style.get("fancybox", False) + ) + legend_obj.set_frame_on(frame_on) + frame = getattr(legend_obj, "get_frame", lambda: None)() + if frame is not None and hasattr(frame, "set_edgecolor"): + frame.set_edgecolor(edgecolor) + if hasattr(legend_obj, "set_fancybox"): + legend_obj.set_fancybox(fancybox) + + # Apply additional kwargs + for key, value in kwargs.items(): + if hasattr(ax, f"set_{key}"): + getattr(ax, f"set_{key}")(value) + + return ax + + +def save_figure( + fig: plt.Figure, + filename: str, + formats: Optional[list] = None, + dpi: Optional[int] = None, + bbox_inches: Optional[str] = None, + pad_inches: Optional[float] = None, + transparent: Optional[bool] = None, + **kwargs, +) -> None: + """ + Save figure in publication-quality formats. + + Parameters + ---------- + fig : matplotlib.figure.Figure + Figure object to save + filename : str + Base filename (without extension) + formats : list, optional + List of formats to save. Default is ['pdf', 'png'] + **kwargs + Additional arguments passed to fig.savefig() + """ + if formats is None: + formats = ["pdf", "png"] + + save_kwargs = { + "dpi": rcParams.get("savefig.dpi", 300) if dpi is None else dpi, + "bbox_inches": "tight" if bbox_inches is None else bbox_inches, + "pad_inches": 0.1 if pad_inches is None else pad_inches, + "transparent": False if transparent is None else transparent, + } + save_kwargs.update(kwargs) + + for fmt in formats: + full_filename = f"{filename}.{fmt}" + fig.savefig(full_filename, format=fmt, **save_kwargs) + print(f"Saved figure: {full_filename}") + + +# Convenience functions for common plot types +def plot_line( + x: np.ndarray, + y: np.ndarray, + ax: Optional[plt.Axes] = None, + color: Optional[str] = None, + linestyle: str = "-", + linewidth: float = 1.0, + marker: Optional[str] = None, + label: Optional[str] = None, + palette_name: str = "default", + **kwargs, +) -> plt.Axes: + """ + Create a line plot with consistent styling. + + Additional Parameters + --------------------- + palette_name : str, default 'default' + Palette to draw a color from when color is not provided. + """ + if ax is None: + fig, ax = create_figure() + + if color is None: + colors = apply_color_palette(palette_name, 1) + color = colors[0] + + ax.plot( + x, + y, + color=color, + linestyle=linestyle, + linewidth=linewidth, + marker=marker, + label=label, + **kwargs, + ) + + return ax + + +def plot_scatter( + x: np.ndarray, + y: np.ndarray, + ax: Optional[plt.Axes] = None, + color: Optional[str] = None, + marker: str = "o", + s: float = 20, + alpha: float = 0.7, + label: Optional[str] = None, + palette_name: str = "default", + **kwargs, +) -> plt.Axes: + """ + Create a scatter plot with consistent styling. + + Additional Parameters + --------------------- + palette_name : str, default 'default' + Palette to draw a color from when color is not provided. + """ + if ax is None: + fig, ax = create_figure() + + if color is None: + colors = apply_color_palette(palette_name, 1) + color = colors[0] + + ax.scatter( + x, y, color=color, marker=marker, s=s, alpha=alpha, label=label, **kwargs + ) + + return ax + + +def plot_errorbar( + x: np.ndarray, + y: np.ndarray, + yerr: Optional[np.ndarray] = None, + xerr: Optional[np.ndarray] = None, + ax: Optional[plt.Axes] = None, + color: Optional[str] = None, + linestyle: str = "-", + linewidth: float = 1.0, + marker: Optional[str] = None, + capsize: float = 3, + label: Optional[str] = None, + palette_name: str = "default", + **kwargs, +) -> plt.Axes: + """ + Create an error bar plot with consistent styling. + + Additional Parameters + --------------------- + palette_name : str, default 'default' + Palette to draw a color from when color is not provided. + """ + if ax is None: + fig, ax = create_figure() + + if color is None: + colors = apply_color_palette(palette_name, 1) + color = colors[0] + + ax.errorbar( + x, + y, + yerr=yerr, + xerr=xerr, + color=color, + linestyle=linestyle, + linewidth=linewidth, + marker=marker, + capsize=capsize, + label=label, + **kwargs, + ) + + return ax + + +def plot_stacked_area( + x: np.ndarray, + y_data: list, + labels: list, + ax: Optional[plt.Axes] = None, + colors: Optional[list] = None, + alpha: float = 0.8, + baseline: Optional[np.ndarray] = None, + **kwargs, +) -> plt.Axes: + """ + Create a stacked area plot with consistent styling. + + Parameters + ---------- + x : np.ndarray + X-axis data (typically time series) + y_data : list of np.ndarray + List of y-axis data arrays for each layer + labels : list of str + Labels for each layer + ax : matplotlib.axes.Axes, optional + Axes object to plot on + colors : list, optional + Colors for each layer + alpha : float, default 0.8 + Transparency of the areas + baseline : np.ndarray, optional + Starting baseline for stacking (defaults to zeros). + **kwargs + Additional arguments passed to ax.fill_between() + + Returns + ------- + ax : matplotlib.axes.Axes + Axes object with the stacked area plot. + """ + if ax is None: + fig, ax = create_figure() + + if colors is None: + colors = apply_color_palette("default", len(y_data)) + + if len(y_data) != len(labels): + raise ValueError("Length of y_data must match length of labels") + + # Convert to numpy arrays if needed + y_data = [np.asarray(y) for y in y_data] + + # Create stacked area plot + bottom = ( + np.zeros_like(x, dtype=float) + if baseline is None + else np.asarray(baseline, dtype=float) + ) + + for i, (y, label, color) in enumerate(zip(y_data, labels, colors)): + ax.fill_between( + x, bottom, bottom + y, color=color, alpha=alpha, label=label, **kwargs + ) + bottom += y + + return ax + + +def plot_stacked_area_plot( + df, + x_col: str, + y_columns: list, + ax: Optional[plt.Axes] = None, + colors: Optional[list] = None, + label_map: Optional[Dict[str, str]] = None, + label_formatter: Optional[Callable[[str], str]] = None, + title: str = "", + xlabel: str = "", + ylabel: str = "", + format_type: str = "double_column_wide", + legend: bool = True, + legend_kwargs: Optional[Dict[str, Any]] = None, + legend_offset: float = -0.25, + sort_x: bool = False, + x_tick_formatter: Optional[Callable[[Any, int], str]] = None, + max_ticks: int = 10, + x_tick_rotation: int = 45, + palette_name: str = "colorblind", + legend_ncol: Optional[int] = None, + datetime_threshold_short_hours: float = 24.0, + datetime_threshold_medium_hours: float = 24.0 * 7, + datetime_formats: Optional[Tuple[str, str, str]] = None, + legend_baseline_offset: float = 0.25, + subplot_bottom_base: float = 0.25, + min_extra_margin: float = 0.0, + **kwargs, +) -> plt.Axes: + """ + Create a publication-ready stacked area chart from a DataFrame. + + Parameters + ---------- + df : pandas.DataFrame + Source data containing the x-axis column and the stacked series. + x_col : str + Column name to use for the x-axis. + y_columns : list of str + Columns that form the stacked series. + ax : matplotlib.axes.Axes, optional + Axes object to draw on. Created automatically when omitted. + colors : list, optional + Colors for each stacked series. Defaults to the colorblind palette. + label_map : dict, optional + Mapping from column name to legend label. + label_formatter : callable, optional + Function applied to each column name when generating legend labels. + title, xlabel, ylabel : str, optional + Figure annotations applied via `style_axes`. + format_type : str, default 'double_column_wide' + Figure sizing preset used when creating a new axis. + legend : bool, default True + Whether to draw a legend for the stacked series. + legend_kwargs : dict, optional + Extra keyword arguments forwarded to `ax.legend`. + legend_offset : float, default -0.25 + Vertical offset (in axes fraction coordinates) for the legend anchor. + sort_x : bool, default False + Sort the DataFrame by `x_col` before plotting. + x_tick_formatter : callable, optional + Function to convert raw x values into tick labels. + max_ticks : int, default 10 + Maximum number of ticks shown on the x-axis. + x_tick_rotation : int, default 45 + Rotation applied to x tick labels. + **kwargs + Extra options forwarded to `plot_stacked_area`. + + Returns + ------- + ax : matplotlib.axes.Axes + Axes containing the stacked area chart. + """ + import pandas as pd + + if ax is None: + fig, ax = create_figure(format_type=format_type) + + if x_col not in df.columns: + raise ValueError(f"x_col '{x_col}' not found in DataFrame") + + if not y_columns: + raise ValueError("y_columns must contain at least one column name") + + # Work on a copy so we can safely sort or drop invalid rows. + data = df.copy() + if sort_x: + data = data.sort_values(x_col) + + data = data.loc[data[x_col].notna()] + if data.empty: + raise ValueError("No rows remaining after dropping missing x values.") + + x_series = pd.Series(data[x_col]).reset_index(drop=True) + + # Assemble stacked series arrays and human-friendly labels. + y_data = [] + labels = [] + for col in y_columns: + if col not in data.columns: + raise ValueError(f"y_column '{col}' not found in DataFrame") + series = pd.to_numeric(data[col], errors="coerce").fillna(0.0) + y_data.append(series.to_numpy()) + if label_map and col in label_map: + label = label_map[col] + elif label_formatter is not None: + label = label_formatter(col) + else: + label = col + labels.append(label) + + if colors is None: + colors = apply_color_palette(palette_name, len(y_data)) + + is_datetime = pd.api.types.is_datetime64_any_dtype(x_series) + is_numeric = np.issubdtype(x_series.dtype, np.number) + + if is_datetime: + x_values = pd.to_datetime(x_series) + x_numeric = np.arange(len(x_values)) + elif is_numeric: + x_values = x_series.astype(float) + x_numeric = x_values.to_numpy() + else: + x_values = x_series.astype(str) + x_numeric = np.arange(len(x_values)) + + ax = plot_stacked_area(x_numeric, y_data, labels, ax=ax, colors=colors, **kwargs) + + # Derive x-axis tick labels that match the data type (numeric vs time). + tick_count = min(max_ticks, len(x_series)) if len(x_series) else 0 + if tick_count: + tick_indices = np.linspace(0, len(x_series) - 1, tick_count, dtype=int) + if x_tick_formatter is not None: + tick_labels = [ + x_tick_formatter(x_series.iloc[idx], idx) for idx in tick_indices + ] + elif is_datetime: + x_dt = pd.to_datetime(x_series) + span_hours = ( + (x_dt.max() - x_dt.min()).total_seconds() / 3600 if len(x_dt) > 1 else 0 + ) + if datetime_formats is not None: + fmt_short, fmt_medium, fmt_long = datetime_formats + else: + fmt_short, fmt_medium, fmt_long = ("%H:%M", "%m-%d %H:%M", "%Y-%m-%d") + if span_hours < datetime_threshold_short_hours: + fmt = fmt_short + elif span_hours < datetime_threshold_medium_hours: + fmt = fmt_medium + else: + fmt = fmt_long + tick_labels = x_dt.iloc[tick_indices].dt.strftime(fmt) + else: + tick_labels = [str(x_series.iloc[idx]) for idx in tick_indices] + + tick_positions = x_numeric[tick_indices] + ax.set_xticks(tick_positions) + ax.set_xticklabels(tick_labels, rotation=x_tick_rotation, ha="right") + + default_legend_kwargs = { + "loc": "upper center", + "bbox_to_anchor": (0.5, legend_offset), + "ncol": legend_ncol if legend_ncol is not None else max(1, min(4, len(labels))), + } + legend_params = {**default_legend_kwargs, **(legend_kwargs or {})} + + # Apply final styling and push legend configuration through style helper. + style_axes( + ax, + title=title, + xlabel=xlabel, + ylabel=ylabel, + grid=True, + legend=legend, + legend_kwargs=legend_params, + ) + + legend_obj = ax.get_legend() + if legend and legend_obj is not None and ax.figure is not None: + bbox = legend_params.get("bbox_to_anchor", (None, None)) + offset_y = legend_offset + if isinstance(bbox, tuple) and len(bbox) >= 2 and bbox[1] is not None: + offset_y = bbox[1] + if offset_y is not None and offset_y < 0: + extra_margin = max(min_extra_margin, -(offset_y + legend_baseline_offset)) + ax.figure.subplots_adjust(bottom=subplot_bottom_base + extra_margin) + + return ax + + +def plot_gpu_utilization_area( + df, + time_col: str = "Datetime", + gpu_columns: Optional[list] = None, + ax: Optional[plt.Axes] = None, + colors: Optional[list] = None, + title: str = "GPU Availability Over Time", + xlabel: str = "Time", + ylabel: str = "Number of Available GPUs", + format_type: str = "double_column_wide", + legend_offset: float = -0.25, + legend: bool = True, + legend_kwargs: Optional[Dict[str, Any]] = None, + exclude_cols: Optional[List[str]] = None, + label_formatter: Optional[Callable[[str], str]] = None, + sort_x: bool = True, + palette_name: str = "colorblind", + **kwargs, +) -> plt.Axes: + """ + Create a stacked area plot for GPU utilization over time. + + Parameters + ---------- + df : pandas.DataFrame + DataFrame containing GPU utilization data + time_col : str, default 'Datetime' + Column name for timestamps + gpu_columns : list, optional + List of GPU type columns to plot. If None, auto-detects GPU columns + ax : matplotlib.axes.Axes, optional + Axes object to plot on + colors : list, optional + Colors for each GPU type + title : str, default 'GPU Availability Over Time' + Plot title + xlabel : str, default 'Time' + X-axis label + ylabel : str, default 'Number of Available GPUs' + Y-axis label + format_type : str, default 'double_column_wide' + Figure format type + legend_offset : float, default -0.25 + Vertical offset for the legend (negative values place it below the plot). + **kwargs + Additional arguments passed to fill_between() + + Returns + ------- + ax : matplotlib.axes.Axes + Axes object with the GPU utilization plot. + """ + import pandas as pd + + # Auto-detect GPU columns if not provided + if gpu_columns is None: + # Common GPU column patterns - exclude non-GPU columns + exclude_cols = exclude_cols or [ + "Datetime", + "gpu", + "Grand Total", + "Total", + "total", + ] + gpu_columns = [ + col + for col in df.columns + if col not in exclude_cols and "gpu" not in col.lower() + ] + + if not gpu_columns: + raise ValueError("No GPU columns found. Specify gpu_columns parameter.") + + # Ensure the timestamp column exists before delegating to the generic helper + if time_col not in df.columns: + raise ValueError(f"Time column '{time_col}' not found in DataFrame") + + if label_formatter is None: + label_formatter = lambda name: " ".join( + name.replace("_", " ").replace("nvidia", "").replace("geforce", "").split() + ).title() + + df_processed = df.copy() + df_processed[time_col] = pd.to_datetime(df_processed[time_col], errors="coerce") + + return plot_stacked_area_plot( + df=df_processed, + x_col=time_col, + y_columns=gpu_columns, + ax=ax, + colors=colors, + label_formatter=label_formatter, + title=title, + xlabel=xlabel, + ylabel=ylabel, + format_type=format_type, + legend=legend, + legend_kwargs=legend_kwargs, + legend_offset=legend_offset, + sort_x=sort_x, + palette_name=palette_name, + **kwargs, + ) + + +def human_readable_format(x, pos, precision: int = 0): + """Format large/small values using SI-friendly suffixes (e.g., 20.0M).""" + if x == 0: + return "0" + + magnitude = abs(x) + thresholds = ( + (1e12, "T"), + (1e9, "B"), + (1e6, "M"), + (1e3, "K"), + ) + + for threshold, suffix in thresholds: + if magnitude >= threshold: + value = x / threshold + return f"{value:.{precision}f}{suffix}" + + if magnitude >= 1: + return f"{x:.{precision}f}" + if magnitude >= 1e-3: + return f"{x * 1e3:.{precision}f}m" + + return f"{x:.{precision}e}" + +def ensure_min_xticks(ax, formatter, min_ticks=2): + # 1. Get current limits + lo, hi = ax.get_xlim() + + # 2. Expand range if necessary + if hi <= lo: + hi = lo * 10 + + # If the range is too tight, expand it multiplicatively + if (np.log10(hi) - np.log10(lo)) < (min_ticks - 1): + # Expand so we can place at least `min_ticks` log ticks + factor = 10 ** (min_ticks - 1) + ax.set_xlim(lo, lo * factor) + lo, hi = ax.get_xlim() + + # 3. Create ticks explicitly + ticks = 10 ** np.linspace(np.log10(lo), np.log10(hi), min_ticks) + ax.set_xticks(ticks) + + # 4. Apply your formatter + ax.xaxis.set_major_formatter(FuncFormatter(formatter)) + + # 5. Remove scientific offset + ax.xaxis.get_offset_text().set_visible(False) + +set_publication_style() diff --git a/src/internal/protocol/host.go b/src/internal/protocol/host.go index be600ce..71fc535 100644 --- a/src/internal/protocol/host.go +++ b/src/internal/protocol/host.go @@ -8,6 +8,8 @@ import ( "encoding/json" "errors" "fmt" + "io" + "math" mrand "math/rand" "net" "opentela/internal/common" @@ -23,10 +25,14 @@ import ( dht "github.com/libp2p/go-libp2p-kad-dht" dualdht "github.com/libp2p/go-libp2p-kad-dht/dual" record "github.com/libp2p/go-libp2p-record" + basichost "github.com/libp2p/go-libp2p/p2p/host/basic" "github.com/libp2p/go-libp2p/p2p/host/autorelay" + libp2pyamux "github.com/libp2p/go-libp2p/p2p/muxer/yamux" relayClient "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/client" relayv2 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay" + "github.com/libp2p/go-libp2p/p2p/protocol/holepunch" "github.com/libp2p/go-libp2p/p2p/protocol/ping" + "github.com/libp2p/go-yamux/v5" "github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/host" @@ -46,6 +52,12 @@ var hostOnce sync.Once var autoReconnectOnce sync.Once var MyID string +// holePunchService holds our manually-constructed hole punch service so that +// callers can trigger DCUtR explicitly via DirectConnect. libp2p's built-in +// EnableHolePunching creates the service but does not expose it; constructing +// our own lets us retry direct-connection upgrades for the bench. +var holePunchService *holepunch.Service + const ( Version = "0.0.0-dev.0" ) @@ -148,6 +160,11 @@ func newHost(ctx context.Context, seed int64, ds datastore.Batching) (host.Host, libp2p.Identity(priv), // libp2p.PrivateNetwork(psk), libp2p.ResourceManager(newResourceManager()), + // Override the default yamux muxer with a larger initial stream + // window. Default Initial=256 KiB caps single-stream throughput at + // ~70 Mbps over a 30 ms RTT relay path; bumping to 8 MiB lifts the + // BDP ceiling so 4 MiB+ probes don't bottleneck on flow control. + libp2p.Muxer(libp2pyamux.ID, bigWindowYamuxMuxer()), // libp2p.ConnectionManager(connmgr), libp2p.NATPortMap(), libp2p.ListenAddrStrings(listenAddrs...), @@ -155,7 +172,9 @@ func newHost(ctx context.Context, seed int64, ds datastore.Batching) (host.Host, libp2p.Security(noise.ID, noise.New), libp2p.EnableNATService(), libp2p.EnableRelay(), - libp2p.EnableHolePunching(), + // Hole-punching is enabled below by manually constructing holepunch.Service + // so we can call DirectConnect directly. EnableHolePunching would create + // its own internal service but doesn't expose it. libp2p.EnableAutoNATv2(), // Relay-as-server: lift the libp2p defaults (128 KB / 2 min per circuit, // 128 reservations, 16 circuits/peer) so HTTP-over-circuit traffic is @@ -185,17 +204,25 @@ func newHost(ctx context.Context, seed int64, ds datastore.Batching) (host.Host, // callback can access the host. We use a pointer-to-pointer because // the callback closure captures hostRef, and we set *hostRef later. var hostRef *host.Host - if viper.GetString("public-addr") != "" { - // Head/relay nodes with a known public address: force public - // reachability so they don't waste time with AutoNAT probes. + // reachability mode: "auto" lets AutoNATv2 decide per-peer; "public" / + // "private" force the libp2p hint. Default mirrors prior behavior: + // public if public-addr is set, private otherwise. + reachability := strings.ToLower(strings.TrimSpace(viper.GetString("reachability"))) + switch reachability { + case "auto": + // no force — let AutoNAT decide + case "public": opts = append(opts, libp2p.ForceReachabilityPublic()) - } else { - // Workers (no public-addr): force private reachability so libp2p - // automatically reserves slots on relay servers. Without this, - // AutoNAT may incorrectly report "public" (the relay CAN reach - // the worker directly) even though the worker is unreachable from - // the cloud. + case "private": opts = append(opts, libp2p.ForceReachabilityPrivate()) + default: + if viper.GetString("public-addr") != "" { + opts = append(opts, libp2p.ForceReachabilityPublic()) + } else { + opts = append(opts, libp2p.ForceReachabilityPrivate()) + } + } + if reachability != "public" && viper.GetString("public-addr") == "" { // AutoRelay discovers relay servers from connected peers and // maintains active reservations so other nodes can reach us // via /p2p//p2p-circuit/p2p/. @@ -240,6 +267,21 @@ func newHost(ctx context.Context, seed int64, ds datastore.Batching) (host.Host, // Set hostRef so the autorelay peer source callback can access the host. hostRef = &host + // Create holepunch service manually so callers can trigger DirectConnect + // (DCUtR) on demand. This requires access to BasicHost internals — namely + // the IDService and AllAddrs callback — which the Host interface does not + // expose. The cast is safe: libp2p.New always returns *basic.BasicHost. + if bh, ok := host.(*basichost.BasicHost); ok { + hps, hpErr := holepunch.NewService(host, bh.IDService(), bh.AllAddrs) + if hpErr != nil { + common.Logger.Warnf("hole-punch service init failed: %v", hpErr) + } else { + holePunchService = hps + } + } else { + common.Logger.Warn("host is not *basichost.BasicHost; hole punching disabled") + } + // Log connection events for debugging host.Network().Notify(&network.NotifyBundle{ ConnectedF: func(n network.Network, c network.Conn) { @@ -497,6 +539,16 @@ func isTransientNetworkError(err error) bool { return false } +func bigWindowYamuxMuxer() *libp2pyamux.Transport { + cfg := yamux.DefaultConfig() + cfg.InitialStreamWindowSize = 8 * 1024 * 1024 + cfg.MaxStreamWindowSize = 16 * 1024 * 1024 + cfg.LogOutput = io.Discard + cfg.ReadBufSize = 0 + cfg.MaxIncomingStreams = math.MaxUint32 + return (*libp2pyamux.Transport)(cfg) +} + func relayServiceResources() relayv2.Resources { r := relayv2.DefaultResources() r.MaxReservations = 512 @@ -727,6 +779,35 @@ func MakeRelayReservations() { } } +// TryHolePunch invokes DCUtR (Direct Connection Upgrade through Relay) for the +// given peer. Returns nil on success (a direct connection now exists), or an +// error if the punch failed. Requires the holepunch service to be initialized. +func TryHolePunch(targetPeerID string) error { + if holePunchService == nil { + return errors.New("hole punch service not initialized") + } + pid, err := peer.Decode(targetPeerID) + if err != nil { + return fmt.Errorf("invalid peer id: %w", err) + } + return holePunchService.DirectConnect(pid) +} + +// ConnectednessOf reports the libp2p connectedness state for the given peer: +// "Connected" (direct), "Limited" (circuit-only), "NotConnected", "CanConnect", +// "CannotConnect", or "" if the local host is not initialized. +func ConnectednessOf(targetPeerID string) string { + h, _ := GetP2PNode(nil) + if h == nil { + return "" + } + pid, err := peer.Decode(targetPeerID) + if err != nil { + return "" + } + return h.Network().Connectedness(pid).String() +} + // IsDirectlyConnected returns true if we have a direct libp2p connection // to the given peer (not via relay circuit). func IsDirectlyConnected(targetPeerID string) bool { diff --git a/src/internal/server/libp2p_http_transport.go b/src/internal/server/libp2p_http_transport.go index 629612a..7951c90 100644 --- a/src/internal/server/libp2p_http_transport.go +++ b/src/internal/server/libp2p_http_transport.go @@ -44,13 +44,17 @@ func newLibp2pHTTPRoundTripper(h host.Host) *libp2pHTTPRoundTripper { if err != nil { return nil, fmt.Errorf("libp2pHTTP: invalid peer id %q: %w", hostPart, err) } - // Permit opening a stream over a relay-circuit (Limited) connection. - // libp2p's NewStream refuses Limited conns by default and tries to - // upgrade to direct, which on cross-cluster peers blocks until the - // caller's context expires (manifests as plain "context deadline - // exceeded" with no dial-failure prefix). The ping protocol opts in - // the same way at p2p/protocol/ping/ping.go:117. - dialCtx := network.WithAllowLimitedConn(ctx, "libp2p-http") + // Only allow circuit-relay (Limited) streams when no direct + // connection exists. With Connected, the plain context lets + // libp2p use the direct path; otherwise we explicitly opt in + // to circuit (matching ping at p2p/protocol/ping/ping.go:117). + // Without this guard, libp2p picks the Limited conn even when + // a direct one is available, capping throughput at the relay's + // per-flow rate. + dialCtx := ctx + if h.Network().Connectedness(pid) != network.Connected { + dialCtx = network.WithAllowLimitedConn(ctx, "libp2p-http") + } return gostream.Dial(dialCtx, h, pid, p2phttp.DefaultP2PProtocol) }, DisableKeepAlives: false, diff --git a/src/internal/server/probe_handler.go b/src/internal/server/probe_handler.go index a8310fb..3d91310 100644 --- a/src/internal/server/probe_handler.go +++ b/src/internal/server/probe_handler.go @@ -80,6 +80,72 @@ type probeResponse struct { Error string `json:"error,omitempty"` } +type holepunchRequest struct { + Target string `json:"target"` + Attempts int `json:"attempts"` + WaitMS int `json:"wait_ms"` + TimeoutMS int `json:"timeout_ms"` +} + +type holepunchResponse struct { + OK bool `json:"ok"` + Target string `json:"target"` + Connectedness string `json:"connectedness"` + Attempts int `json:"attempts"` + LastError string `json:"last_error,omitempty"` +} + +// holepunchHandler tries DCUtR up to N times (default 5), pausing between +// attempts, and returns once Connectedness is "Connected" or the budget is +// exhausted. Useful for warming up direct connections before throughput probes. +func holepunchHandler(c *gin.Context) { + var req holepunchRequest + if err := json.NewDecoder(c.Request.Body).Decode(&req); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid JSON body: " + err.Error()}) + return + } + if req.Target == "" { + c.JSON(http.StatusBadRequest, gin.H{"error": "target is required"}) + return + } + if req.Attempts <= 0 { + req.Attempts = 5 + } + if req.WaitMS <= 0 { + req.WaitMS = 2000 + } + if req.TimeoutMS <= 0 { + req.TimeoutMS = 30000 + } + if _, err := libp2ppeer.Decode(req.Target); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid target peer id: " + err.Error()}) + return + } + + resp := holepunchResponse{Target: req.Target} + deadline := time.Now().Add(time.Duration(req.TimeoutMS) * time.Millisecond) + + for resp.Attempts < req.Attempts && time.Now().Before(deadline) { + state := protocol.ConnectednessOf(req.Target) + resp.Connectedness = state + if state == "Connected" { + resp.OK = true + c.JSON(http.StatusOK, resp) + return + } + resp.Attempts++ + if err := protocol.TryHolePunch(req.Target); err != nil { + resp.LastError = err.Error() + } + // Wait briefly for libp2p to upgrade Limited → Connected. + time.Sleep(time.Duration(req.WaitMS) * time.Millisecond) + } + + resp.Connectedness = protocol.ConnectednessOf(req.Target) + resp.OK = resp.Connectedness == "Connected" + c.JSON(http.StatusOK, resp) +} + func runHandler(c *gin.Context) { var req probeRequest if err := json.NewDecoder(c.Request.Body).Decode(&req); err != nil { diff --git a/src/internal/server/server.go b/src/internal/server/server.go index a2d49f7..ecfd01e 100644 --- a/src/internal/server/server.go +++ b/src/internal/server/server.go @@ -218,6 +218,7 @@ func StartServer() { { probeGroup.GET("/echo", echoHandler) probeGroup.POST("/run", runHandler) + probeGroup.POST("/holepunch", holepunchHandler) } v1.GET("/self", getSelf) v1.POST("/sign", signData)