Skip to content

Commit 7f8463f

Browse files
feat: iroh-gossip (#1149)
* feat: iroh-gossip initial commit This commit imports iroh-gossip into the repo. See n0-computer/iroh-sync#1 for the prehistory. * From that original PR comes my IO-less implementation of the gossip protocol (Plumtree broadcast trees and HyParView cluster membership). The implementations are quite strict according to the papers [1](https://asc.di.fct.unl.pt/~jleitao/pdf/dsn07-leitao.pdf) and [2](https://asc.di.fct.unl.pt/~jleitao/pdf/srds07-leitao.pdf). If you find any deviations that are not documented, please report, this is likely a bug. * The combined protocol for Plumtree and Hyparview is additionally namespaced with a 32-byte topic ID to allow multiple broadcast trees (one per topic) to coexist. This means: Each topic is a seperate broadcast tree with seperate swarm membership and active connections (connections to the same peers are still shared on the network layer) This IO-less protocol implementation is in the `proto` module. This PR *also* adds my work from the past week: A `net` module that provides networking for the IO-less protocol impl, through the `MagicEndpoint` from iroh-net, with a (I think) quite straightforward actor implementation. The `net` module has a smoke test, and the PR also includes a `chat` example that adds signed messages on the trustless base layer. What this mostly needs is, I think, more testing and validation of the protocol implementation. For this to be practical, I think we should formulate some base usecase scenarios. The `proto` module has a very simple simulator and some tests that can take environment variables to increase the cluster size. They passed with 10.000 nodes. They also report some stats. The numbers look OK-ish, but I'd love to compare them properly with either other implementations or estimations from the original paper or other resoures. However, those are hard to find. * fix(gossip): make util pub * fix(gossip): better naming of cli arguments in chat example * chore: make clippy happy * feat: transmit opaque PeerData on join, forward and neighbor ... and wire it up in net module to transmit your endpoint addresses * example: improve gossip chat example * chore: clippy * fix(gossip): update dep version after rebase * fix: changes after rebase * change(gossip): cleanup and better debug impls * fix(gossip): disconnect handling * change: do not error on connect without addrs Before MagicEndpoint::connect would error if called without addrs or derp_region. This commit changes this by only warning and not bailing. This allows to connect to peers by peer id only if addresses or a derp_region were provided previously. The downside is that we lose a valuable error case. A more proper fix will need to move the check if a peer is dialable into the actor. * fix: adapt for changes in iroh-net, and use genawaiter * chore: clippy * docs: document public items in iroh-gossip also renames mod.rs files to modname.rs * tests: move gossip simulator into tests module * tests: make simulation tests work with top level protocol state * change: use derive_more::Debug * feat: add command to leave a topic * docs: document default plumtree config * docs: default values for hyparview * docs: add high-level description of iroh-gossip protocol * test/refactor: add unit test for plumtree optimization step * refactor: improve chat example and address review * fix: do not stop actor if conn closes before event is processed * docs: more links * fix: changes after rebase * change: remove unneeded serialize in iroh-net added earlier * fix: make tests work and cleanup some namings * chore: clippy * refactor: improve and cleanup chat example * refactor: remove unneeded InEvent variant in plumtree * refactor: improve gossip example further * docs for le people and le me * fmt * docs: plumtree * docs: hyparview * feat: validate gossip message ids on receive * chore: cleanup * feat: metrics, and backport fixes from sync-gossip-bytes branch * feat: expose which peer sent us a gossip message * fix: postcard is required * fix: only graft lazy peers in optimize_tree * chore: remove leftover comment * docs(hyparview): improve with divma's suggestions * refactor: impl IntoIterator for IndexSet * fix(hyparview): only trigger ForwardJoin if peer is not yet active * fix(hyparview): reply to shuffle if active_view.len() is 1 or 0 * refactor: rename methods for clarity * fix: do not auto-join topics on external requests * docs: typos * docs: fix * refactor: rename GossipHandle to just Gossip * refactor: less code, more derive * docx: fix * refactor: add util module for base32 parse/fmt * refactor: make PeerData optional * refactor: do not use shift_remove in indexset, not needed * test: add unittests for IndexSet * test: TimerMap and base32 utils * refactor: rename trait PeerAddress to PeerId an generic PA to PI * feat: evict messages after some time * chore: clippy & fmt * fix: renames in doc comments * fix: use rand_chacha in tests for predictable cross-arch results * chore: fmt * chore: remove unneeded line * test: try to fix cross-arch rngs * test: always recreate RNG for cross-arch compat * fix: change after rebase on main * chore: remove debug leftovers --------- Co-authored-by: Diva M <divma@protonmail.com>
1 parent 80c54aa commit 7f8463f

18 files changed

Lines changed: 5133 additions & 3 deletions

File tree

Cargo.lock

Lines changed: 44 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ members = [
33
"iroh",
44
"iroh-net",
55
"iroh-bytes",
6+
"iroh-gossip",
67
"iroh-metrics",
78
]
89

iroh-gossip/Cargo.toml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
[package]
2+
name = "iroh-gossip"
3+
version = "0.4.1"
4+
edition = "2021"
5+
readme = "README.md"
6+
description = "gossip messages over broadcast trees"
7+
license = "MIT/Apache-2.0"
8+
authors = ["n0 team"]
9+
repository = "https://github.com/n0-computer/iroh-sync"
10+
11+
[dependencies]
12+
# proto dependencies (required)
13+
anyhow = { version = "1", features = ["backtrace"] }
14+
blake3 = "1.3.3"
15+
bytes = { version = "1.4.0", features = ["serde"] }
16+
data-encoding = "2.4.0"
17+
derive_more = { version = "1.0.0-beta.1", features = ["add", "debug", "display", "from", "try_into"] }
18+
ed25519-dalek = { version = "=2.0.0-rc.3", features = ["serde", "rand_core"] }
19+
indexmap = "2.0"
20+
postcard = { version = "1", default-features = false, features = ["alloc", "use-std", "experimental-derive"] }
21+
rand = { version = "0.8.5", features = ["std_rng"] }
22+
rand_core = "0.6.4"
23+
serde = { version = "1.0.164", features = ["derive"] }
24+
tracing = "0.1.37"
25+
iroh-metrics = { path = "../iroh-metrics", version = "0.5.0" }
26+
27+
# net dependencies (optional)
28+
futures = { version = "0.3.25", optional = true }
29+
iroh-net = { path = "../iroh-net", optional = true }
30+
quinn = { version = "0.10", optional = true }
31+
tokio = { version = "1", optional = true, features = ["io-util", "sync", "rt", "macros", "net", "fs"] }
32+
tokio-util = { version = "0.7.8", optional = true, features = ["codec"] }
33+
once_cell = "1.18.0"
34+
genawaiter = { version = "0.99.1", default-features = false, features = ["futures03"] }
35+
36+
[dev-dependencies]
37+
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
38+
clap = { version = "4", features = ["derive"] }
39+
url = "2.4.0"
40+
rand_chacha = "0.3.1"
41+
42+
[features]
43+
default = ["net"]
44+
net = ["futures", "iroh-net", "quinn", "tokio", "tokio-util"]
45+
46+
[[example]]
47+
name = "chat"
48+
required-features = ["net"]

iroh-gossip/README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# iroh-gossip
2+
3+
This crate implements the `iroh-gossip` protocol.
4+
It is based on *epidemic broadcast trees* to disseminate messages among a swarm of peers interested in a *topic*.
5+
The implementation is based on the papers [HyParView](https://asc.di.fct.unl.pt/~jleitao/pdf/dsn07-leitao.pdf) and [PlumTree](https://asc.di.fct.unl.pt/~jleitao/pdf/srds07-leitao.pdf).
6+
7+
The crate is made up from two modules:
8+
The `proto` module is the protocol implementation, as a state machine without any IO.
9+
The `net` module connects the protocol to the networking stack from `iroh-net`.
10+
11+
The `net` module is optional behind the `net` feature flag (enabled by default).
12+
13+
14+
# License
15+
16+
This project is licensed under either of
17+
18+
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
19+
http://www.apache.org/licenses/LICENSE-2.0)
20+
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
21+
http://opensource.org/licenses/MIT)
22+
23+
at your option.
24+
25+
### Contribution
26+
27+
Unless you explicitly state otherwise, any contribution intentionally submitted
28+
for inclusion in this project by you, as defined in the Apache-2.0 license,
29+
shall be dual licensed as above, without any additional terms or conditions.

0 commit comments

Comments
 (0)