跳转到主要内容

一个用Python实现的区块链玩具项目

项目描述

toychain

toychain是一个用Python实现的非常简化的区块链节点建模。虽然代码是我的改编,但实现来自Daniel van Flymen非常好的教程。这个改编使用FastAPI作为Web框架,使用uvicorn作为ASGI服务器,而不是van Flymen教程中的Flask应用。

运行

此存储库使用Poetry作为构建工具。通过VCS获取本地副本,然后使用poetry install进行设置。

预定义的poetry run node命令用于启动节点,默认在localhost:5000。此外,您可以使用带有--host--port标志的命令指定要运行节点的主机和端口。然后,您可以使用相同的命令在不同的端口上启动多个节点。

Docker

可以以Docker容器运行节点。为此,克隆存储库,然后使用docker build -t blockchain .构建镜像。

然后,您可以通过将节点的端口映射到您的机器上localhost的期望端口来运行容器。要将节点映射到端口5000,请运行

$ docker run --init --rm -p 5000:5000 blockchain

为了模拟额外的节点,更改公共端口号

$ docker run --init --rm -p 5001:5000 blockchain
$ docker run --init --rm -p 5002:5000 blockchain
$ docker run --init --rm -p 5003:5000 blockchain

然后,您可以通过向/nodes/register发送POST请求来添加所有运行实例到彼此的网络中,通过POST事务,挖掘新的区块,并解决区块链。

功能

区块链是一个简单的区块列表。区块链中的一个区块由以下键的字典组成

  • 在链中的索引位置,
  • 区块被添加到链中的时间戳
  • 记录在区块中的交易列表,
  • 自身有效性的证明
  • 一个指向链中前一个区块哈希的previous_hash标签,用于不可变性。

一个简单的区块示例(包含一个交易),作为一个JSON有效载荷,看起来是这样的

block = {
    "index": 1,
    "timestamp": 1506057125.900785,
    "transactions": [
        {
            "sender": "8527147fe1f5426f9dd545de4b27ee00",
            "recipient": "a77f5cdfa2934df3954a5c7c7da5df1f",
            "amount": 5,
        }
    ],
    "proof": 324984774000,
    "previous_hash": "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
}

节点实现

区块链功能由toychain.blockchain模块中的一个名为BlockChain的单个类提供。使用BlockChain类的实例来运行一个节点。每个节点存储完整的区块链、当前交易(尚未写入链中)和网络中其他节点的列表。它可以

  • 将交易添加到当前交易列表中,
  • 将一个新的(验证过的)区块添加到链中,
  • 运行工作量证明算法(这里简单,为了计算时间),
  • 验证区块的证明
  • 注册网络上的其他节点,
  • 推断任意节点的区块链的有效性,
  • 通过共识算法解决冲突,检查网络中所有节点的链,并采用最长有效链。

节点作为使用FastAPI网络框架的REST API运行,并在启动时分配一个UUID。实现位于toychain.node模块中,节点的可用端点如下

  • GET 端点 /mine 用于触发向链中添加新区块,
  • POST 端点 /transactions/new 用于将交易添加到节点的列表中,
  • GET 端点 /chain 用于拉取完整链,
  • POST 端点 /nodes/register 用于将其他节点的地址注册为网络的一部分,
  • GET 端点 /nodes/resolve:用于触发共识算法的运行和解决冲突:使用网络中所有节点的最长有效链作为参考,替换本地链,并返回。

一旦服务器启动(例如使用python -m toychain),将在/docs/redoc端点提供自动文档。

假设我们的节点正在运行在localhost:5000。使用cURL将交易POST到节点的transactions/new端点如下

curl -X POST -H "Content-Type: application/json" -d '{
 "sender": "d4ee26eee15148ee92c6cd394edd974e",
 "recipient": "someone-other-address",
 "amount": 5
}' "http://localhost:5000/transactions/new"

现在假设我们已经启动了一个第二个节点在localhost:5000。使用cURL将有效载荷POST到注册这个新节点到第一个节点的网络中如下

curl -X POST -H "Content-Type: application/json" -d '{
 "nodes": ["http://127.0.0.1:5001"]
}' "http://localhost:5000/nodes/register"

如果您想使用httpie,相应的命令分别是

echo '{ "sender": "d4ee26eee15148ee92c6cd394edd974e", "recipient": "someone-other-address", "amount": 5 }' | http POST http://localhost:5000/transactions/new
echo '{ "nodes": ["http://127.0.0.1:5001"] }' | http POST http://localhost:5000/nodes/register

项目详情


下载文件

下载您平台上的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。

源分发

toychain-0.2.0.tar.gz (8.3 kB 查看哈希)

上传时间

构建分发

toychain-0.2.0-py3-none-any.whl (8.4 kB 查看哈希)

上传时间 Python 3

由以下支持