10 个不稳定版本 (4 个破坏性更改)
0.5.0 | 2023年8月27日 |
---|---|
0.4.2 | 2023年8月5日 |
0.4.0 | 2023年7月28日 |
0.3.0 | 2023年7月12日 |
0.1.1 | 2020年5月29日 |
#826 in 编码
123 每月下载量
在 3 crates 中使用
670KB
14K SLoC
fog-pack
一个用于内容寻址、去中心化存储的序列化库。
雾包序列化格式是从头开始设计的,旨在有效地用于内容寻址存储系统,并在去中心化网络中有效工作。鉴于这些是格式最高的优先级,它不得不做出一些其他序列化格式不会做出的艰难选择。以下是简要概述
- 它是一种自描述的二进制序列化格式
- 它基于
serde
对 Rust 结构的序列化 - 它对所有数据都有一个规范形式。相同的数据将只有一个有效的序列化版本。
- 它支持用于验证序列化数据的数据模式
- 数据模式可以序列化
- 数据可以封装到文档中,这些文档可以标记为符合数据所遵循的数据模式。文档始终具有一个独特的加密哈希,用于标识数据。
- 数据还可以封装到条目中,这些条目始终与父文档关联,并有一个字符串用于将它们与类似的条目分组。
- 文档和条目可以 加密签名,这将更改它们的标识哈希。
- 文档和条目可以 使用 zstandard 压缩,这不会更改它们的标识哈希。当使用数据模式时支持 zstandard 字典。
- 文档和条目根据设计具有大小限制和有限嵌套深度。
- 提供了加密对象,使用
fog-crypto
库。
关键概念
Schemas
: 一个数据模式,它验证文档和相关条目,并且可以压缩它们两者Documents
: 一个经过哈希处理的序列化数据块,它可能遵循数据模式并可以进行加密签名。Entries
: 一个经过哈希处理的序列化数据块,它具有关联的父文档和键字符串。它还可以进行加密签名。Queries
: 一个查询,它可以用来查找附加到文档的条目。
这四种类型构成了 fog-pack 的核心概念,并用于构建内容寻址存储系统中的复杂、相互关联的数据。
那么,在使用中它会是什么样子呢?让我们从一个简单的想法开始:我们想要制作一系列的小文本帖子。这就像是一种博客,所以我们可以有一个作者、博客标题和可选的网站链接。帖子可以作为条目附加到博客上,这些条目将有一个创建时间戳、可选的标题和帖子内容。
我们将首先声明文档和模式
// Our Blog's main document
#[derive(Serialize, Deserialize)]
struct Blog {
title: String,
author: String,
// We prefer to omit the field if it's set to None, which is not serde's default
#[serde(skip_serializing_if = "Option::is_none")]
link: Option<String>,
}
// Each post in our blog
#[derive(Serialize, Deserialize)]
struct Post {
created: Timestamp,
content: String,
#[serde(skip_serializing_if = "Option::is_none")]
title: Option<String>,
}
// Build our schema into a completed schema document.
let schema_doc = SchemaBuilder::new(MapValidator::new()
.req_add("title", StrValidator::new().build())
.req_add("author", StrValidator::new().build())
.opt_add("link", StrValidator::new().build())
.build()
)
.entry_add("post", MapValidator::new()
.req_add("created", TimeValidator::new().query(true).ord(true).build())
.opt_add("title", StrValidator::new().query(true).regex(true).build())
.req_add("content", StrValidator::new().build())
.build(),
None
)
.build()
.unwrap();
// For actual use, we'll turn the schema document into a Schema
let schema = Schema::from_doc(&schema_doc)?;
现在我们已经有了模式和结构体,我们可以创建一个新的博客并为其制作帖子。我们将使用加密密钥签名所有内容,这样人们就可以知道是我们在制作这些帖子。我们甚至可以创建一个查询,用于搜索特定的帖子!
// Brand new blog time!
let my_key = fog_crypto::identity::IdentityKey::new();
let my_blog = Blog {
title: "Rusted Gears: A programming blog".into(),
author: "ElectricCogs".into(),
link: Some("https://cognoscan.github.io/".into()),
};
let my_blog = NewDocument::new(my_blog, Some(schema.hash()))?.sign(&my_key)?;
let my_blog = schema.validate_new_doc(my_blog)?;
let blog_hash = my_blog.hash();
// First post!
let new_post = Post {
created: Timestamp::now();
title: Some("My first post".into()),
content: "I'm making my first post using fog-pack!".into(),
};
let new_post = NewEntry::new(new_post, "post", &blog_hash)?.sign(&my_key)?;
// We can find entries using a Query:
let query = NewQuery::new("post", MapValidator::new()
.req_add("title", StrValidator::new().in_add("My first post").build())
.build()
);
// To complete serialization of all these structs, we need to pass them through the schema one
// more time:
let (blog_hash, encoded_blog): (Hash, Vec<u8>) =
schema.encode_doc(my_blog)?;
let (post_hash, encoded_post): (Hash, Vec<u8>) =
schema.encode_new_entry(new_post)?.complete()?;
let encoded_query =
schema.encode_query(query)?;
// Decoding is also done via the schema:
let my_blog = schema.decode_doc(encoded_blog)?;
let new_post = schema.decode_entry(encoded_post, "post", &blog_hash)?;
let query = schema.decode_query(encoded_query)?;
许可证
根据您的要求,许可方式可以是以下之一
- Apache许可证,版本2.0 (LICENSE-APACHE 或 http://www.apache.org/licenses/LICENSE-2.0)
- MIT许可证 (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
由您选择。
贡献
除非您明确声明,否则您按照Apache-2.0许可证定义的方式有意提交给作品的所有贡献,将按照上述方式双重许可,没有任何额外的条款或条件。
依赖项
~9–12MB
~240K SLoC