星际文件系统(IPFS):使用 ipfsapi 进行交互
1. IPFS 简介
IPFS 使用 S/Kademlia,它是 Kademlia 的扩展版本。与原始的 Kademlia 算法不同,S/Kademlia 有一些安全要求。并非所有节点加入 Kademlia 分布式哈希表都有正当目的,因此在 S/Kademlia 中,节点生成 ID 时需要生成一个加密密钥对,这使得篡改节点间的通信变得非常困难。此外,节点在生成 ID 之前需要进行工作量证明(类似于比特币和以太坊)。同时,路由算法也有一些调整,以确保节点在存在恶意节点(如向网络发送垃圾信息的节点)的情况下仍能与其他节点通信。
IPFS 虽然不是区块链技术的一部分,但它与区块链类似,因为它可以补充区块链技术。存储在 IPFS 文件系统中的内容的数据结构是基于 Merkle 树的 Merkle 有向无环图(DAG)。Merkle 树便于检查部分数据的完整性,而 Merkle DAG 则用于保存包含文件的目录并保留文件名。Kademlia 分布式哈希表的点对点网络方面,节点间的距离基于异或(XOR)距离,节点被存储在对应于位寻址的桶中,节点可以通过桶来查找其他节点。
2. 使用 ipfsapi 与 IPFS 交互
2.1 安装 IPFS 软件及其库
目前,IPFS 只有两种实现:用 Go 语言编写的 go - ipfs 和用 JavaScript 编写的 js - ipfs,尚无用 Python 编写的实现。由于 go - ipfs 更受欢迎,我们将使用它。
操作步骤如下:
1. 访问 https://dist.ipfs.io/#go - ipfs,为你的平台下载软件。对于 Ubuntu Linux,文件名为 go - ipfs_v0.4.18_linux - amd64.tar.gz。
2. 使用以下命令解压缩文件:
$ tar xvfz go - ipfs_v0.4.18_linux - amd64.tar.gz
- 使用以下命令安装二进制文件:
$ cd go - ipfs
$ sudo./install.sh
- (可选步骤)将 IPFS_PATH 环境变量导出到 shell:
$ export IPFS_PATH=/path/to/ipfsrepo
你可以将此语句存储在 ~/.bashrc 中。默认情况下(不设置此环境变量),IPFS 将使用 ~/.ipfs(主目录中的 .ipfs 目录)来存储数据。
5. 设置环境变量后,初始化 IPFS 本地存储库(此步骤只需执行一次):
$ ipfs init
如果你在云端(如亚马逊网络服务、谷歌云平台、数字海洋或 Azure)运行 IPFS,应使用服务器配置文件标志:
$ ipfs init --profile server
否则,你可能会收到云服务提供商的警告,因为默认情况下(不使用服务器配置文件标志),IPFS 守护进程的行为类似于端口扫描。
6. 启动守护进程:
$ ipfs daemon
默认情况下,API 服务器监听端口 5001,我们将通过此端口以编程方式与 IPFS 交互。默认情况下,它仅监听本地主机。如果要将此端口开放给外部网络,请谨慎操作,因为 IPFS 没有访问控制列表(ACL),任何有权访问此端口的人都可以向 IPFS 上传数据。
默认情况下,网关服务器监听端口 8080,我们通过此端口从 IPFS 点对点文件系统下载文件。Swarm 默认监听端口 4001,其他节点通过此端口从我们的存储中下载文件。所有这些端口都可以更改。
IPFS 有一个仪表盘,可通过以下链接访问:http://localhost:5001/webui。
2.2 安装 IPFS Python 库
打开一个新的终端,以避免干扰 IPFS 守护进程,然后运行以下命令:
$ virtualenv -p python3.6 ipfs - venv
$ source ipfs - venv/bin/activate
(ipfs - venv) $ pip install ipfsapi
之前,IPFS Python 库名为 py - ipfs - api,现在已更名为 ipfsapi。
2.3 内容哈希
在 IPFS 快速入门文档中,首先会教你下载可爱的猫图片。可以使用以下代码完成:
$ ipfs cat /ipfs/QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ/cat.jpg > cat.jpg
$ eog cat.jpg
运行上述代码后,猫图片将被下载。eog 是 Ubuntu 中的图像查看器。
为了遵循传统,我们创建一个 Python 脚本以编程方式下载上述图像,脚本名为 download_cute_cat_picture.py:
import ipfsapi
c = ipfsapi.connect()
cute_cat_picture = 'QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ/cat.jpg'
c.get(cute_cat_picture)
执行此脚本后,图像将以 cat.jpg 的名称保存在你的目录中。
我们还可以创建一个脚本下载包含可爱猫图片的目录,脚本名为 download_a_directory_of_cute_cat_picture.py:
import ipfsapi
c = ipfsapi.connect()
directory = 'QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ'
c.get(directory)
执行此脚本后,你将在包含该脚本的目录中得到一个名为 QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ 的目录,查看该目录可以找到猫图片文件。
以下是对 ipfsapi 库使用的详细解释:
- 导入库:
import ipfsapi
- 获取与 IPFS 守护进程的连接对象:
c = ipfsapi.connect()
connect
方法接受几个参数,其中最重要的两个参数是
host
和
port
:
c = ipfsapi.connect(host="ipfshost.net", port=5001)
默认情况下,我们连接到本地主机的 5001 端口。
get
方法用于下载文件,而
cat
方法用于获取文件的内容。以下是使用
cat
方法的脚本 cat_cute_cat.py:
import ipfsapi
c = ipfsapi.connect()
result = c.cat('QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ/cat.jpg')
with open('cat.jpg', 'wb') as f:
f.write(result)
cat
方法返回文件内容的字节对象,它接受两个可选参数
offset
和
length
。
offset
是文件中开始获取内容的起始位置,
length
是从
offset
位置开始要获取的内容长度。这些参数对于构建具有暂停和恢复功能的下载管理器或视频流播放器非常重要,因为你可能并不总是想下载整个文件。
接下来,我们向 IPFS 添加一个文件。首先创建一个简单的文件 hello.txt,内容如下:
I am a good unicorn.
确保字符串后有一个换行符。可以使用以下命令检查:
$ cat hello.txt
I am a good unicorn.
$
如果命令提示符在字符串行之后,则表示一切正常。如果命令提示符在字符串右侧,则表示缺少换行符,需要在字符串后添加。
创建一个脚本 add_file.py 将此文件添加到 IPFS:
import ipfsapi
c = ipfsapi.connect()
result = c.add('hello.txt')
print(result)
执行此代码将输出:
{'Name': 'hello.txt', 'Hash': 'QmY7MiYeySnsed1Z3KxqDVYuM8pfiT5gGTqprNaNhUpZgR', 'Size': '29'}
我们可以使用
cat
或
get
方法检索文件内容。以下是使用
cat
方法的脚本 get_unicorn.py:
import ipfsapi
c = ipfsapi.connect()
result = c.cat('QmY7MiYeySnsed1Z3KxqDVYuM8pfiT5gGTqprNaNhUpZgR')
print(result)
运行此脚本将输出:
b'I am a good unicorn.\n'
2.4 关于 protobuf
在将
b'I am a good unicorn.\n'
传递给 IPFS 之前,我们需要将数据包装在一个数据结构中。以下是一个证明此说法的脚本 get_unicorn_block.py:
import ipfsapi
c = ipfsapi.connect()
result = c.block_get('QmY7MiYeySnsed1Z3KxqDVYuM8pfiT5gGTqprNaNhUpZgR')
print(result)
运行此脚本,你会看到文件内容被其他内容包裹:
b'\n\x1b\x08\x02\x12\x15I am a good unicorn.\n\x18\x15'
我们可以看到文件内容
b'I am a good unicorn.\n'
位于这些加密字符串之间,左右的字符是 IPFS 中数据节点的数据结构。
在反序列化此序列化数据之前,我们先快速学习如何使用 protobuf:
1. 使用以下命令安装 protobuf 编译器:
$ sudo apt - get install protobuf - compiler
使用以下命令检查 protobuf 编译器版本:
$ protoc --version
libprotoc 2.6.1
- 使用以下命令安装 Python protobuf 库:
(ipfs - venv) $ pip install protobuf
- 在使用 protobuf 序列化数据之前,需要先创建一个数据结构格式,并将其保存到文件中。我们将格式文件命名为 crypto.proto,内容如下:
syntax = "proto2";
package crypto;
message CryptoCurrency {
required string name = 1;
optional int32 total_supply = 2;
enum CryptoType {
BITCOIN = 0;
ERC20 = 1;
PRIVATE = 2;
}
required CryptoType type = 3 [default = ERC20];
}
- 在 Python 中使用 protobuf 序列化数据之前,需要将 .proto 文件转换为 Python 模块文件:
$ protoc crypto.proto --python_out=.
你将得到生成的 crypto_pb2.py 文件。
以下是测试序列化和反序列化过程的 Python 脚本 serialize_crypto_data.py:
import crypto_pb2
cryptocurrency = crypto_pb2.CryptoCurrency()
cryptocurrency.name = 'Bitcoin Cash'
cryptocurrency.total_supply = 21000000
cryptocurrency.type = crypto_pb2.CryptoCurrency.BITCOIN
serialized_data = cryptocurrency.SerializeToString()
print(serialized_data)
cryptocurrency2 = crypto_pb2.CryptoCurrency()
cryptocurrency2.ParseFromString(serialized_data)
print(cryptocurrency2)
执行此脚本将输出:
b'\n\x0cBitcoin Cash\x10\xc0\xde\x81\n\x18\x00'
name: "Bitcoin Cash"
total_supply: 21000000
type: BITCOIN
序列化输出
b'\n\x0cBitcoin Cash\x10\xc0\xde\x81\n\x18\x00'
类似于我们在 IPFS 中的独角兽数据块。
回到 IPFS 中的块数据,我们需要获取相关的 .proto 文件来反序列化数据。需要两个 .proto 文件:unixfs.proto 和 merkledag.proto。
- unixfs.proto 可以从 https://github.com/ipfs/go - unixfs/blob/master/pb/unixfs.proto 下载。
- merkledag.proto 可以从 https://github.com/ipfs/go - merkledag/blob/master/pb/merkledag.proto 下载。
unixfs.proto 文件内容如下:
syntax = "proto2";
package unixfs.pb;
message Data {
enum DataType {
Raw = 0;
Directory = 1;
File = 2;
Metadata = 3;
Symlink = 4;
HAMTShard = 5;
}
required DataType Type = 1;
optional bytes Data = 2;
optional uint64 filesize = 3;
repeated uint64 blocksizes = 4;
optional uint64 hashType = 5;
optional uint64 fanout = 6;
}
message Metadata {
optional string MimeType = 1;
}
merkledag.proto 文件内容如下:
package merkledag.pb;
import "code.google.com/p/gogoprotobuf/gogoproto/gogo.proto";
option (gogoproto.gostring_all) = true;
option (gogoproto.equal_all) = true;
option (gogoproto.verbose_equal_all) = true;
option (gogoproto.goproto_stringer_all) = false;
option (gogoproto.stringer_all) = true;
option (gogoproto.populate_all) = true;
option (gogoproto.testgen_all) = true;
option (gogoproto.benchgen_all) = true;
option (gogoproto.marshaler_all) = true;
option (gogoproto.sizer_all) = true;
option (gogoproto.unmarshaler_all) = true;
// An IPFS MerkleDAG Node
message PBNode {
// refs to other objects
repeated PBLink Links = 2;
// opaque user data
optional bytes Data = 1;
}
为了简化过程,需要从 merkledag.proto 文件中删除以下行:
import "code.google.com/p/gogoprotobuf/gogoproto/gogo.proto";
option (gogoproto.gostring_all) = true;
option (gogoproto.equal_all) = true;
option (gogoproto.verbose_equal_all) = true;
option (gogoproto.goproto_stringer_all) = false;
option (gogoproto.stringer_all) = true;
option (gogoproto.populate_all) = true;
option (gogoproto.testgen_all) = true;
option (gogoproto.benchgen_all) = true;
option (gogoproto.marshaler_all) = true;
option (gogoproto.sizer_all) = true;
option (gogoproto.unmarshaler_all) = true
然后使用以下命令编译两个 .proto 文件:
$ protoc unixfs.proto merkledag.proto --python_out=.
编译后将得到生成的 unixfs_pb2.py 和 merkledag_pb2.py 文件。
创建一个脚本 unserialize_unicorn.py 来解码块数据:
import unixfs_pb2
import merkledag_pb2
outer_node = merkledag_pb2.PBNode()
outer_node.ParseFromString(b'\n\x1b\x08\x02\x12\x15I am a good unicorn.\n\x18\x15')
print(outer_node)
unicorn = unixfs_pb2.Data()
unicorn.ParseFromString(outer_node.Data)
print(unicorn)
运行此脚本将输出:
Data: "\010\002\022\025I am a good unicorn.\n\030\025"
Type: File
Data: "I am a good unicorn.\n"
filesize: 21
操作步骤总结
| 操作 | 步骤 |
|---|---|
| 安装 IPFS 软件 | 1. 下载对应平台的软件;2. 解压缩文件;3. 安装二进制文件;4. (可选)设置环境变量;5. 初始化本地存储库;6. 启动守护进程 |
| 安装 IPFS Python 库 | 1. 创建虚拟环境;2. 激活虚拟环境;3. 安装 ipfsapi 库 |
| 下载文件 |
1. 使用
ipfs cat
命令或 Python 脚本
get
方法
|
| 添加文件 |
1. 创建文件;2. 使用 Python 脚本
add
方法添加文件
|
| 使用 protobuf | 1. 安装 protobuf 编译器和 Python 库;2. 创建 .proto 文件;3. 编译 .proto 文件为 Python 模块;4. 进行序列化和反序列化操作 |
流程图
graph LR
A[安装 IPFS 软件] --> B[安装 IPFS Python 库]
B --> C[内容哈希操作]
C --> D[使用 protobuf 处理数据]
C --> E[下载文件]
C --> F[添加文件]
以上就是使用 ipfsapi 与 IPFS 进行交互的详细介绍,通过这些步骤和代码示例,你可以更好地掌握如何在 Python 中使用 IPFS。
3. 深入理解 IPFS 交互的技术细节
3.1 IPFS 节点通信安全机制
IPFS 使用的 S/Kademlia 算法在节点通信安全方面有独特的设计。节点生成 ID 时,需要生成加密密钥对,这一机制大大增强了节点间通信的安全性,使得篡改通信内容变得极为困难。此外,节点在生成 ID 之前还需进行工作量证明,这进一步提高了网络的安全性和可靠性。
3.2 Merkle 树和 Merkle DAG 在 IPFS 中的应用
Merkle 树和 Merkle DAG 是 IPFS 中重要的数据结构。Merkle 树可以方便地检查部分数据的完整性,通过对数据块进行哈希计算,构建树状结构,只需验证根哈希值,就能确认数据是否被篡改。而 Merkle DAG 则适用于保存包含文件的目录,并能保留文件名,它在处理复杂的文件组织时发挥着重要作用。
3.3 IPFS 端口及服务说明
| 端口 | 服务 | 说明 |
|---|---|---|
| 5001 | API 服务器 | 用于以编程方式与 IPFS 交互,默认仅监听本地主机,开放到外部需谨慎 |
| 8080 | 网关服务器 | 用于从 IPFS 点对点文件系统下载文件 |
| 4001 | Swarm | 其他节点通过此端口从本地存储中下载文件 |
3.4 ipfsapi 库方法详解
-
connect 方法
:用于建立与 IPFS 守护进程的连接,可指定
host和port参数。
import ipfsapi
# 默认连接本地主机 5001 端口
c = ipfsapi.connect()
# 连接指定主机和端口
c = ipfsapi.connect(host="ipfshost.net", port=5001)
- get 方法 :用于下载文件,将文件保存到本地。
c = ipfsapi.connect()
cute_cat_picture = 'QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ/cat.jpg'
c.get(cute_cat_picture)
-
cat 方法
:用于获取文件的内容,返回字节对象,可指定
offset和length参数。
c = ipfsapi.connect()
result = c.cat('QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ/cat.jpg')
with open('cat.jpg', 'wb') as f:
f.write(result)
- add 方法 :用于向 IPFS 添加文件,返回文件的相关信息,如文件名、哈希值和大小。
c = ipfsapi.connect()
result = c.add('hello.txt')
print(result)
3.5 protobuf 序列化和反序列化流程
3.5.1 安装和配置
- 安装 protobuf 编译器:
$ sudo apt - get install protobuf - compiler
- 检查 protobuf 编译器版本:
$ protoc --version
libprotoc 2.6.1
- 安装 Python protobuf 库:
(ipfs - venv) $ pip install protobuf
3.5.2 创建 .proto 文件
syntax = "proto2";
package crypto;
message CryptoCurrency {
required string name = 1;
optional int32 total_supply = 2;
enum CryptoType {
BITCOIN = 0;
ERC20 = 1;
PRIVATE = 2;
}
required CryptoType type = 3 [default = ERC20];
}
3.5.3 编译 .proto 文件为 Python 模块
$ protoc crypto.proto --python_out=.
3.5.4 序列化和反序列化操作
import crypto_pb2
# 序列化
cryptocurrency = crypto_pb2.CryptoCurrency()
cryptocurrency.name = 'Bitcoin Cash'
cryptocurrency.total_supply = 21000000
cryptocurrency.type = crypto_pb2.CryptoCurrency.BITCOIN
serialized_data = cryptocurrency.SerializeToString()
print(serialized_data)
# 反序列化
cryptocurrency2 = crypto_pb2.CryptoCurrency()
cryptocurrency2.ParseFromString(serialized_data)
print(cryptocurrency2)
3.6 IPFS 数据存储和检索流程
graph LR
A[创建文件] --> B[使用 ipfsapi add 方法添加文件到 IPFS]
B --> C[获取文件哈希值]
C --> D[使用 ipfsapi get 或 cat 方法根据哈希值检索文件]
D --> E[将文件保存到本地或获取文件内容]
4. 总结与展望
通过上述内容,我们详细了解了如何使用 ipfsapi 与 IPFS 进行交互,包括安装 IPFS 软件和 Python 库、进行内容哈希操作、使用 protobuf 处理数据以及文件的下载和添加等。IPFS 作为一种分布式文件系统,具有数据持久化、内容寻址和去中心化等优点,在数据存储和共享领域有着广阔的应用前景。
未来,随着区块链技术的不断发展,IPFS 有望与区块链更好地结合,为去中心化应用提供更强大的支持。同时,IPFS 的隐私保护功能也在不断发展,相信在不久的将来,IPFS 将在更多领域发挥重要作用。我们可以进一步探索 IPFS 的高级功能,如分布式应用开发、数据加密存储等,以充分发挥其潜力。
超级会员免费看
1092

被折叠的 条评论
为什么被折叠?



