1 个不稳定版本

0.1.0 2023年5月14日

#peer-connection 中排名第22

GPL-2.0 许可证

1MB
20K SLoC

swarm-host

swarm-host 是一个用于对等(P2P)程序进行协议模拟和网络流量分析的工具。它指定了应用程序必须实现的一个特质,该特质定义了其网络协议的工作方式,并暴露了一个用于编程这些协议的 Python 框架。它还暴露了一个简单的启发式后端,该后端提供网络流量的可视化。

swarm-host 允许对 P2P 网络的实时节点进行协议模拟,并提供在模拟期间分析网络行为和流量模式的能力。它可以用来评估,例如,对协议实现的函数更改或对等连接中做出的选择如何影响网络的安全性和带宽使用。

swarm-host 通过在网络中生成 Sybil 节点(称为接口)来工作,这些节点伪装成正常的 P2P 节点,诚实节点可以连接到。这些接口中的流量可以用 Python 编程,允许进行广泛的模拟。可以通过安装一个在每个网络事件(如传入的对等节点或区块请求)接收时被调用的过滤器来编程协议。例如,它可以决定丢弃接收到的消息、延迟或修改它,或者仅将其转发给连接的某些对等节点。过滤器也可以在运行时进行调整,并在需要时重新安装。

除了对网络协议泛型之外,swarm-host 对过滤器执行器也是泛型的,因此如果出于某种原因 Python 不合适,可以实现另一个执行器,前提是它能够执行后端定义的类型所需的必要转换,并且可以从 Rust 中调用它。

图1展示了 swarm-host 的高级架构以及一个具有5:2诚实节点多数的示例测试场景

以下 Python 代码显示了如何实现上述测试场景,用于带有针对 /block-announces/1 协议的自定义过滤器的 Substrate

from swarm_host.swarm_host import SwarmHost
from swarm_host.filter import NotificationFilter
from swarm_host.backend.substrate.node import SubstrateNode

import time

swarm_host = SwarmHost(
    rpc_port = 8888,
    backend = "substrate",
    genesis_hash = "0x36d171b4279dc05f16e8960afd9ae9e28cd620b610b84d6374949c099231c585"
)

preinit = open("swarm_host/backend/substrate/filters/preinit.py").read()
context = open("swarm_host/backend/substrate/filters/context.py").read()

id1 = swarm_host.create_interface(6666, context, preinit)
id2 = swarm_host.create_interface(7777, context, preinit)

swarm_host.link_interface(id1, id2)

# create custom filter for the `/block-announces/1` protocol
# which stops forwarding block announcements after block 10
class CustomBlockAnnounceFilter(NotificationFilter):
    def inject_notification(ctx, peer, protocol, notification):
        from swarm_host.backend.substrate.primitives.block_announce import BlockAnnounce
        from swarm_host.backend.substrate.primitives.block_announce import init_runtime_config

        if ctx.runtime_config is None:
            ctx.runtime_config = init_runtime_config()

        try:
            block_announce = BlockAnnounce(ctx.runtime_config, bytes(notification))
        except Exception as e:
            print("failed to decode block announce:", e)
            return

        number = block_announce.number()
        hash = block_announce.hash(ctx.runtime_config)
        ctx.peers[peer].known_blocks.add(hash)

        # stop forwarding block announcements after block 10
        if number > 10:
            return

        forward_table = []
        for peer in ctx.peers:
            if hash not in ctx.peers[peer].known_blocks:
                forward_table.append(peer)

        if len(forward_table) != 0:
            ctx.forward_notification(protocol, forward_table, notification)

swarm_host.install_notification_filter(
    id1,
    "/sup/block-announces/1",
    CustomBlockAnnounceFilter().export()
)
swarm_host.install_notification_filter(
    id2,
    "/sup/block-announces/1",
    CustomBlockAnnounceFilter().export()
)

# start Substrate nodes
nodes = []
nodes.append(SubstrateNode([
    "--in-peers", "3",
    "--out-peers", "2",
    "--port", "0",
    "--chain=dev",
    "--alice",
    "--force-authoring",
    "--tmp",
]))

for i in range(0, 4):
    nodes.append(SubstrateNode([
        "--in-peers", "3",
        "--out-peers", "2",
        "--port", "0",
        "--chain=dev",
        "--tmp",
    ])) 

time.sleep(100)

或者您也可以以二进制形式启动 swarm-host

export PYTHONPATH=<path to swarm-host/framework>
cargo run -- --rpc-port 8888 substrate --genesis-hash 0x36d171b4279dc05f16e8960afd9ae9e28cd620b610b84d6374949c099231c585

在不启动 SwarmHost 对象的情况下编写 Python 测试代码。这样您需要通过 RPC 向正在运行的 swarm-host 二进制文件发送命令。调用约定在 src/rpc.rsframework/swarm_host/swarm_host.py 中有文档说明。

依赖项

~58–97MB
~1.5M SLoC