DEP 0007: Network Profiles

status: draft

Motivation

Currently, network settings such as seeds, peers, inbound, outbound_connection_timeout, and others are not configured per transport.

This leads to several UX issues. For instance, it's not possible to specify different outbound connection timeouts for different transports. As a result, a tcp+tls connection might be forced to use the timeout configured for a tor transport, and similar limitations apply to other settings.

Additionally, it's easier to misconfigure the setup—for example, a user might inadvertently connect to clearnet seeds while using the tor transport, since all seed addresses are grouped under a single field without transport separation.

Proposal

The current toml config for net settings looks like the following. Note, only the parts that are proposed to be changed are shown here.

allowed_transports = ["tcp+tls"]

mixed_transports = []

inbound = ["tcp+tls://0.0.0.0:26661", "tcp+tls://[::]:26661"]

external_addrs = ["tcp+tls://my.resolveable.address:26661"]

seeds = [
    "tcp+tls://lilith0.dark.fi:25551",
    "tcp+tls://lilith1.dark.fi:25551",
    #"tor://g7fxelebievvpr27w7gt24lflptpw3jeeuvafovgliq5utdst6xyruyd.onion:25552",
    #"tor://yvklzjnfmwxhyodhrkpomawjcdvcaushsj6torjz2gyd7e25f3gfunyd.onion:25552",
]

peers = []

outbound_connect_timeout = 60
channel_handshake_timeout = 55
channel_heartbeat_interval = 9

We propose introducing network profiles, allowing each supported transport to be configured individually.

active_profiles = ["tor"]

mixed_profiles = []

[net.profiles."tcp+tls"]
seeds = ["tcp+tls://lilith0.dark.fi:25551", "tcp+tls://lilith1.dark.fi:25551"]

peers = []

inbound = ["tcp+tls://0.0.0.0:26661", "tcp+tls://[::]:26661"]

external_addrs = ["tcp+tls://my.resolveable.address:26661"]

[net.profiles."tor"]
seeds = [
    "tor://g7fxelebievvpr27w7gt24lflptpw3jeeuvafovgliq5utdst6xyruyd.onion:25552",
    "tor://yvklzjnfmwxhyodhrkpomawjcdvcaushsj6torjz2gyd7e25f3gfunyd.onion:25552",
]

peers = []

inbound = ["tor://127.0.0.1:26661"]

outbound_connect_timeout = 60
channel_handshake_timeout = 55
channel_heartbeat_interval = 90

[net.profiles."i2p"]
seeds = [
    "i2p://6l2rdfriixo2nh5pr5bt555lyz56qox2ikzia4kuzm4okje7gtmq.b32.i2p:5262"
]

peers = []

inbound = ["tcp://127.0.0.1:25551"]

external_addrs = ["i2p://youraddress.b32.i2p:25551"]

outbound_connect_timeout = 60
channel_handshake_timeout = 55
channel_heartbeat_interval = 90

[net.profiles."socks5"]
seeds = [
    "socks5://127.0.0.1:9050/g7fxelebievvpr27w7gt24lflptpw3jeeuvafovgliq5utdst6xyruyd.onion:25552",
    "socks5://127.0.0.1:9050/yvklzjnfmwxhyodhrkpomawjcdvcaushsj6torjz2gyd7e25f3gfunyd.onion:25552",
]

peers = []

outbound_connect_timeout = 60
channel_handshake_timeout = 55
channel_heartbeat_interval = 90

[net.profiles."socks5+tls"]
seeds = [
    #"socks5+tls://127.0.0.1:9050/lilith0.dark.fi:25551",
    #"socks5+tls://127.0.0.1:1080/lilith1.dark.fi:25551"
]

peers = []

outbound_connect_timeout = 60
channel_handshake_timeout = 55
channel_heartbeat_interval = 90

[net.profiles."tor+tls"]
seeds = [
    "tor+tls://lilith0.dark.fi:25551",
    "tor+tls://lilith1.dark.fi:25551"
]

peers = []

outbound_connect_timeout = 60
channel_handshake_timeout = 55
channel_heartbeat_interval = 90

[net.profiles."tcp"]
seeds = ["tcp://127.0.0.1:25551"]

peers = []

inbound = ["tcp://127.0.0.1:26661"]

external_addrs = ["tcp://127.0.0.1:26661"]

Each profile will have the following fields seeds, peers, inbound, external_addrs, outbound_connect_timeout, channel_handshake_timeout, channel_heartbeat_interval.

The SettingsOpt struct will be updated to include a new profiles field of type NetworkProfileOpt. The fields in NetworProfileOpt are moved from SettingsOpt. Additionally, the allowed_transports field will be renamed to active_profiles, and mixed_transports will be renamed to mixed_profiles.

#[derive(Clone, Debug, serde::Deserialize, structopt::StructOpt, structopt_toml::StructOptToml)]
#[structopt()]
pub struct SettingsOpt {
    // --- REMOVED START ---
    #[serde(default)]
    #[structopt(long = "accept")]
    pub inbound: Vec<Url>,

    #[serde(default)]
    #[structopt(long)]
    pub external_addrs: Vec<Url>,

    #[serde(default)]
    #[structopt(long)]
    pub peers: Vec<Url>,

    #[serde(default)]
    #[structopt(long)]
    pub seeds: Vec<Url>,

    #[structopt(skip)]
    pub outbound_connect_timeout: Option<u64>,

    #[structopt(skip)]
    pub channel_handshake_timeout: Option<u64>,

    #[structopt(skip)]
    pub channel_heartbeat_interval: Option<u64>,
    // --- REMOVED END ---

    // --- MODIFIED START ---
    #[serde(default)]
    #[structopt(long = "profiles")]
    pub active_profiles: Option<Vec<String>>,

    #[serde(default)]
    #[structopt(long = "mixed-profiles")]
    pub mixed_profiles: Option<Vec<String>>,
    // --- MODIFIED END ---

    // --- NEWLY ADDED START ---
    #[serde(default)]
    #[structopt(skip)]
    pub profiles: HashMap<String, NetworkProfileOpt>,
    // --- NEWLY ADDED END ---
}

#[derive(Clone, Debug, serde::Deserialize, structopt::StructOpt, structopt_toml::StructOptToml)]
#[structopt()]
pub struct NetworkProfileOpt {
    #[serde(default)]
    #[structopt(long = "accept")]
    pub inbound: Vec<Url>,

    #[serde(default)]
    #[structopt(long)]
    pub external_addrs: Vec<Url>,

    #[serde(default)]
    #[structopt(long)]
    pub peers: Vec<Url>,

    #[serde(default)]
    #[structopt(long)]
    pub seeds: Vec<Url>,

    #[structopt(skip)]
    pub outbound_connect_timeout: Option<u64>,

    #[structopt(skip)]
    pub channel_handshake_timeout: Option<u64>,

    #[structopt(skip)]
    pub channel_heartbeat_interval: Option<u64>,
}

The Settings struct will also be updated to include a profiles field of type NetworkProfile. The NetworkProfile struct will correspond to and map the three fields defined in NetworkProfileOpt.

#[derive(Debug, Clone)]
pub struct Settings {
    //...
    pub profiles : HashMap<String, NetworkProfile>,
    //...
}

#[derive(Debug, Clone)]
pub struct NetworkProfile {
    pub outbound_connect_timeout: u64,

    pub channel_handshake_timeout: u64,

    pub channel_heartbeat_interval: u64,
}

We construct the Settings struct from SettingsOpt by filtering the profiles hashmap using the active_profiles list. The seeds, peers, inbound_addrs, and external_addrs fields are aggregated from the filtered profiles and assigned to the corresponding fields in Settings. These fields are not retained in NetworkProfile, as they are not transport-specific.