rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 heartwood12af1497ef6824068ad93d3029dad894945f24ba
{
"request": "trigger",
"version": 1,
"event_type": "patch",
"repository": {
"id": "rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5",
"name": "heartwood",
"description": "Radicle Heartwood Protocol & Stack",
"private": false,
"default_branch": "master",
"delegates": [
"did:key:z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT",
"did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM",
"did:key:z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz"
]
},
"action": "Created",
"patch": {
"id": "f689d6e9d5357b6dcae0ff0413c8d683a5a44e2a",
"author": {
"id": "did:key:z6MktaNvN1KVFMkSRAiN4qK5yvX1zuEEaseeX5sffhzPZRZW",
"alias": "cloudhead"
},
"title": "node: Add connection limits",
"state": {
"status": "merged",
"conflicts": []
},
"before": "a48081f2717f069d456ec09f31d9e639b232dbed",
"after": "12af1497ef6824068ad93d3029dad894945f24ba",
"commits": [
"12af1497ef6824068ad93d3029dad894945f24ba"
],
"target": "7e1cb406bb935c3de008d2171e8961f57b4336ea",
"labels": [],
"assignees": [],
"revisions": [
{
"id": "f689d6e9d5357b6dcae0ff0413c8d683a5a44e2a",
"author": {
"id": "did:key:z6MktaNvN1KVFMkSRAiN4qK5yvX1zuEEaseeX5sffhzPZRZW",
"alias": "cloudhead"
},
"description": "The limits are roughly modeled after the Bitcoin network.",
"base": "a48081f2717f069d456ec09f31d9e639b232dbed",
"oid": "12af1497ef6824068ad93d3029dad894945f24ba",
"timestamp": 1709546374
},
{
"id": "27da48fa6b1e6271beca2b1b9f1b98f98a44af90",
"author": {
"id": "did:key:z6MktaNvN1KVFMkSRAiN4qK5yvX1zuEEaseeX5sffhzPZRZW",
"alias": "cloudhead"
},
"description": "Rebase.",
"base": "a48081f2717f069d456ec09f31d9e639b232dbed",
"oid": "92d0236fb06fb4b3f0ff9929ad089bd0d7c7b3de",
"timestamp": 1709936646
},
{
"id": "a7957e041da0c5848b64d95c9dc7b2ccbc5ab2ec",
"author": {
"id": "did:key:z6MktaNvN1KVFMkSRAiN4qK5yvX1zuEEaseeX5sffhzPZRZW",
"alias": "cloudhead"
},
"description": "Rebase.",
"base": "5bdc2ad1fba5346005e6e97ae0161d602d890163",
"oid": "786ce40f9563d9ee8d8946708ed39f9b5a70b87f",
"timestamp": 1709936678
}
]
}
}
{
"response": "triggered",
"run_id": {
"id": "a2f6f9ca-4c7e-4f4e-8ed1-2cbc46f14bda"
},
"info_url": "https://cci.rad.levitte.org//a2f6f9ca-4c7e-4f4e-8ed1-2cbc46f14bda.html"
}
Started at: 2026-09-09 01:44:03.733069+02:00
Commands:
$ rad clone rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 .
✓ Creating checkout in ./...
✓ Remote cloudhead@z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT added
✓ Remote-tracking branch cloudhead@z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT/master created for z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT
✓ Remote fintohaps@z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM added
✓ Remote-tracking branch fintohaps@z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM/master created for z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM
✓ Remote lorenz@z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz added
✓ Remote-tracking branch lorenz@z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz/master created for z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz
✓ Repository successfully cloned under /opt/radcis/ci.rad.levitte.org/cci/state/a2f6f9ca-4c7e-4f4e-8ed1-2cbc46f14bda/w/
╭────────────────────────────────────╮
│ heartwood │
│ Radicle Heartwood Protocol & Stack │
│ 189 issues · 39 patches │
╰────────────────────────────────────╯
Run `cd ./.` to go to the repository directory.
Exit code: 0
$ rad patch checkout f689d6e9d5357b6dcae0ff0413c8d683a5a44e2a
✓ Switched to branch patch/f689d6e at revision f689d6e
✓ Branch patch/f689d6e setup to track rad/patches/f689d6e9d5357b6dcae0ff0413c8d683a5a44e2a
Exit code: 0
$ git config advice.detachedHead false
Exit code: 0
$ git checkout 12af1497ef6824068ad93d3029dad894945f24ba
HEAD is now at 12af1497 node: Add connection limits
Exit code: 0
$ rad patch show f689d6e9d5357b6dcae0ff0413c8d683a5a44e2a -p
╭────────────────────────────────────────────────────────────────────────────────╮
│ Title node: Add connection limits │
│ Patch f689d6e9d5357b6dcae0ff0413c8d683a5a44e2a │
│ Author cloudhead z6MktaN…hzPZRZW │
│ Head 12af1497ef6824068ad93d3029dad894945f24ba │
│ Base a48081f2717f069d456ec09f31d9e639b232dbed │
│ Target master │
│ Branches patch/f689d6e │
│ Commits ahead 1, behind 1586 │
│ Status merged │
│ │
│ The limits are roughly modeled after the Bitcoin network. │
├────────────────────────────────────────────────────────────────────────────────┤
│ 12af149 node: Add connection limits │
├────────────────────────────────────────────────────────────────────────────────┤
│ ● Revision f689d6e @ a48081f..12af149 by cloudhead z6MktaN…hzPZRZW 2 years ago │
│ ↑ Revision 27da48f @ a48081f..92d0236 by cloudhead z6MksFq…bS9wzpT 2 years ago │
│ ↑ Revision a7957e0 @ 5bdc2ad..786ce40 by cloudhead z6MksFq…bS9wzpT 2 years ago │
│ └─ ✓ merged by cloudhead z6MksFq…bS9wzpT │
╰────────────────────────────────────────────────────────────────────────────────╯
commit 12af1497ef6824068ad93d3029dad894945f24ba
Author: Alexis Sellier <self@cloudhead.io>
Date: Mon Mar 4 10:59:15 2024 +0100
node: Add connection limits
The limits are roughly modeled after the Bitcoin network.
diff --git a/radicle-cli/examples/rad-config.md b/radicle-cli/examples/rad-config.md
index 3a60c80a9d..8fcbf4d9f1 100644
--- a/radicle-cli/examples/rad-config.md
+++ b/radicle-cli/examples/rad-config.md
@@ -43,6 +43,10 @@ $ rad config
"fillRate": 1.0,
"capacity": 64
}
+ },
+ "connection": {
+ "inbound": 128,
+ "outbound": 16
}
},
"policy": "block",
diff --git a/radicle-node/src/service.rs b/radicle-node/src/service.rs
index 22f6c38bef..0df45c6656 100644
--- a/radicle-node/src/service.rs
+++ b/radicle-node/src/service.rs
@@ -1059,10 +1059,15 @@ where
/// Inbound connection attempt.
pub fn accepted(&mut self, addr: Address) -> bool {
- // Always accept trusted connections.
+ // Always accept trusted connections, even if we already reached
+ // our inbound connection limit.
if addr.is_trusted() {
return true;
}
+ // Check for inbound connection limit.
+ if self.sessions.inbound().count() >= self.config.limits.connection.inbound {
+ return false;
+ }
let host: HostName = addr.into();
if self
@@ -1912,6 +1917,10 @@ where
error!(target: "service", "Attempted connection to self");
return false;
}
+ if self.sessions.outbound().count() >= self.config.limits.connection.outbound {
+ error!(target: "service", "Outbound connection limit reached when attempting {nid} ({addr})");
+ return false;
+ }
let persistent = self.config.is_persistent(&nid);
let time = self.time();
@@ -2345,6 +2354,16 @@ impl Sessions {
})
}
+ /// Iterator over connected inbound peers.
+ pub fn inbound(&self) -> impl Iterator<Item = (&NodeId, &Session)> + Clone {
+ self.connected().filter(|(_, s)| s.link.is_inbound())
+ }
+
+ /// Iterator over outbound peers.
+ pub fn outbound(&self) -> impl Iterator<Item = (&NodeId, &Session)> + Clone {
+ self.connected().filter(|(_, s)| s.link.is_outbound())
+ }
+
/// Iterator over mutable fully connected peers.
pub fn connected_mut(&mut self) -> impl Iterator<Item = (&NodeId, &mut Session)> {
self.0.iter_mut().filter(move |(_, s)| s.is_connected())
diff --git a/radicle/src/node/config.rs b/radicle/src/node/config.rs
index da28ab501f..6c235340bc 100644
--- a/radicle/src/node/config.rs
+++ b/radicle/src/node/config.rs
@@ -93,6 +93,9 @@ pub struct Limits {
/// Rate limitter settings.
#[serde(default)]
pub rate: RateLimits,
+ /// Connection limits.
+ #[serde(default)]
+ pub connection: ConnectionLimits,
}
impl Default for Limits {
@@ -104,6 +107,27 @@ impl Default for Limits {
fetch_concurrency: 1,
max_open_files: 4096,
rate: RateLimits::default(),
+ connection: ConnectionLimits::default(),
+ }
+ }
+}
+
+/// Connection limits.
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ConnectionLimits {
+ /// Max inbound connections.
+ pub inbound: usize,
+ /// Max outbound connections. Note that this is higher than the *target* number
+ /// in [`TARGET_OUTBOUND_PEERS`].
+ pub outbound: usize,
+}
+
+impl Default for ConnectionLimits {
+ fn default() -> Self {
+ Self {
+ inbound: 128,
+ outbound: 16,
}
}
}
Exit code: 0
shell: 'cargo --version rustc --version cargo fmt --check cargo clippy --all-targets --workspace -- --deny clippy::all cargo build --all-targets --workspace cargo doc --workspace cargo test --workspace --no-fail-fast '
Commands:
$ podman run --name a2f6f9ca-4c7e-4f4e-8ed1-2cbc46f14bda -v /opt/radcis/ci.rad.levitte.org/cci/state/a2f6f9ca-4c7e-4f4e-8ed1-2cbc46f14bda/s:/a2f6f9ca-4c7e-4f4e-8ed1-2cbc46f14bda/s:ro -v /opt/radcis/ci.rad.levitte.org/cci/state/a2f6f9ca-4c7e-4f4e-8ed1-2cbc46f14bda/w:/a2f6f9ca-4c7e-4f4e-8ed1-2cbc46f14bda/w -w /a2f6f9ca-4c7e-4f4e-8ed1-2cbc46f14bda/w -v /opt/radcis/ci.rad.levitte.org/.radicle:/${id}/.radicle:ro -e RAD_HOME=/${id}/.radicle rust:trixie bash /a2f6f9ca-4c7e-4f4e-8ed1-2cbc46f14bda/s/script.sh
+ cargo --version
info: syncing channel updates for '1.74-x86_64-unknown-linux-gnu'
info: latest update on 2023-12-07, rust version 1.74.1 (a28077b28 2023-12-04)
info: downloading component 'cargo'
info: downloading component 'rust-std'
info: downloading component 'rustc'
info: installing component 'cargo'
info: installing component 'rust-std'
info: installing component 'rustc'
cargo 1.74.1 (ecb9851af 2023-10-18)
+ rustc --version
rustc 1.74.1 (a28077b28 2023-12-04)
+ cargo fmt --check
error: 'cargo-fmt' is not installed for the toolchain '1.74-x86_64-unknown-linux-gnu'.
To install, run `rustup component add --toolchain 1.74-x86_64-unknown-linux-gnu rustfmt`
Exit code: 1
{
"response": "finished",
"result": "failure"
}