1个稳定版本
1.0.3 | 2023年7月16日 |
---|
#10 in #gossip
27每月下载量
110KB
2.5K SLoC
HyPar P2P Gossip
最初作为anoma节点代码库的一部分开发。提取为一个独立的crate。
此crate实现了一种通用感染式Gossip协议,可用于形成对等拓扑并在节点之间传播任意数据。此协议可扩展到单个主题内的数千个节点。
对等节点之间的通信使用安全的节点到节点通道加密。节点身份基于每个节点生成的非对称加密密钥对。主题使用字符串标识符进行识别,并通过连接到已经是主题成员的引导节点来加入。节点可以不指定任何引导节点,在这种情况下,它可以作为主题上其他节点的引导节点。
此crate的公共API是
// API entry point:
pub struct Network { ... }
impl Network {
pub fn new(config: network::Config, keypair: Keypair) -> Result<Self>;
pub fn join(&mut self, config: topic::Config) -> Result<Topic>;
pub async fn runloop(mut self);
}
// after joining a topic:
pub struct Topic { ... }
impl Topic {
pub fn gossip(&self, data: Bytes);
}
// polling on new data gossiped by other peers
impl Stream for Topic {
type Item = Bytes;
fn poll_next(...) -> Poll<Option<Self::Item>>;
}
P2P交互的基本单元是主题。单个主题是HyparView成员协议的独立实例,该协议维护一个主题内的对等覆盖。节点可以是多个主题的成员,在这种情况下,它将拥有多个并发实例的HyparView,每个实例都有自己的对等节点和不同的覆盖。主题可能重叠,如果需要在不同主题之间路由消息,请查看单向跨主题桥接和双向跨主题桥接示例。
网络API故意不公开任何关于任何主题的P2P拓扑中的单个对等节点或其他事件的信息,除了来自其他节点的Gossip协议接收到的去重Gossip字节之外。这是在库之上构建的更高级结构携带此类信息的任务。
用法
在您的Cargo.toml
中添加
[dependencies]
hypar = "1.0"
常见用例
完整的Gossip示例
// drives all networking across topics
let mut network = Network::default();
// join some topic by its name and a set of bootstrap nodes
let topic1 = network.join(topic::Config {
name: "/example/topic1".into(),
bootstrap: vec![ // Multiaddr
"/ip4/1.2.3.4/tcp/12345".parse()?,
"/ip6/2002:102:405::/tcp/12345".parse()?,
"/dnsaddr/bootstrap.example.com/tcp/12345".parse()?
],
})?;
// create a background task that will print all
// incoming gossip messages on this topic to stdout.
tokio::spawn(async move {
let mut topic1 = topic1;
while let Some(msg) = topic1.next().await {
println!("topic1 message: {msg:?}");
}
});
// gossip a message on the topic every second to all peers
tokio::spawn({
let topic1 = topic1.clone();
async move {
let mut counter = 1u64;
loop {
tokio::time::sleep(Duration::from_secs(1)).await;
topic1.gossip(counter.to_be_bytes().to_vec().into());
counter += 1;
}
}
});
// run the network runloop forever.
tokio::spawn(network.runloop()).await?;
单向跨主题桥接
// drives all networking across topics
let mut network = Network::default();
// join two different topics/overlays
let topic1 = network.join(...)?;
let topic2 = network.join(...)?;
// listen on all incoming gossip from topic1
// and gossip a copy to topic2 overlay:
tokio::spawn(async move {
let mut topic1 = topic1;
while let Some(msg) = topic1.next().await {
topic2.gossip(msg);
}
});
// run the network runloop forever.
tokio::spawn(network.runloop()).await?;
双向跨主题桥接
// drives all networking across topics
let mut network = Network::default();
// join two different topics/overlays
let topic1 = network.join(...)?;
let topic2 = network.join(...)?;
// listen on all incoming gossip from topic1
// and gossip a copy to topic2 overlay:
tokio::spawn(async move {
let mut topic1 = topic1;
let mut topic2 = topic2;
tokio::select! {
Some(msg) = topic1.next() => {
topic2.gossip(msg);
}
Some(msg) = topic2.next() => {
topic1.gossip(msg);
}
};
});
// run the network runloop forever.
tokio::spawn(network.runloop()).await?;
依赖项
~18–56MB
~1M SLoC