Rust Holochain开发工具包hdk_derive的使用,简化HDK宏派生与WASM智能合约开发
hdk_derive
Holochain HDK的派生宏。
安装
在项目目录中运行以下Cargo命令:
cargo add hdk_derive
或者在Cargo.toml中添加以下行:
hdk_derive = "0.5.4"
使用示例
下面是一个完整的示例,展示如何使用hdk_derive简化HDK宏派生和WASM智能合约开发:
// 导入必要的宏和类型
use hdk::prelude::*;
use hdk_derive::*;
// 定义一个将被序列化/反序列化的Entry
#[hdk_entry(id = "my_entry")]
pub struct MyEntry {
content: String,
}
// 定义一个将被注册为Zome函数的函数
#[hdk_extern]
pub fn create_entry(input: MyEntry) -> ExternResult<HeaderHash> {
create_entry(&input)
}
// 定义一个将被注册为Zome函数的查询函数
#[hdk_extern]
pub fn get_entry(header_hash: HeaderHash) -> ExternResult<Option<MyEntry>> {
get_entry(&header_hash)
}
// 使用hdk_derive的入口注册宏
entry_defs![
MyEntry::entry_def()
];
这个示例展示了如何:
- 使用
#[hdk_entry]
宏定义一个Entry类型 - 使用
#[hdk_extern]
宏定义Zome函数 - 使用
entry_defs!
宏注册Entry类型
完整示例demo
基于上述示例,下面是一个更完整的Holochain WASM智能合约开发示例:
// 导入必要的宏和类型
use hdk::prelude::*;
use hdk_derive::*;
// 定义Person Entry类型
#[hdk_entry(id = "person")]
pub struct Person {
name: String,
age: u32,
email: String,
}
// 创建Person Entry的Zome函数
#[hdk_extern]
pub fn create_person(input: Person) -> ExternResult<HeaderHash> {
// 验证输入数据
if input.age > 150 {
return Err(WasmError::Guest("Age must be less than 150".into()));
}
// 创建Entry并返回其HeaderHash
create_entry(&input)
}
// 查询Person Entry的Zome函数
#[hdk_extern]
pub fn get_person(header_hash: HeaderHash) -> ExternResult<Option<Person>> {
get_entry(&header_hash)
}
// 更新Person Entry的Zome函数
#[hdk_extern]
pub fn update_person(input: (HeaderHash, Person)) -> ExternResult<HeaderHash> {
let (original_header_hash, updated_person) = input;
// 删除旧Entry
delete_entry(original_header_hash)?;
// 创建更新后的Entry
create_entry(&updated_person)
}
// 删除Person Entry的Zome函数
#[hdk_extern]
pub fn delete_person(header_hash: HeaderHash) -> ExternResult<HeaderHash> {
delete_entry(header_hash)
}
// 注册所有Entry定义
entry_defs![
Person::entry_def()
];
这个完整示例展示了:
- 定义更复杂的Entry类型
Person
- 添加了数据验证逻辑
- 实现了完整的CRUD操作
- 展示了错误处理
主要功能
hdk_derive提供的主要派生宏包括:
#[hdk_entry]
- 用于定义Holochain Entry类型#[hdk_extern]
- 用于定义Zome外部函数- 其他简化HDK开发的派生宏
许可证
Apache-2.0
所有者
- holochain/Core Dev团队
- Stefan Junker
- Eric Harris-Braun
- Holochain Release Automation
分类
密码学(Cryptography)
1 回复
Rust Holochain开发工具包hdk_derive的使用
介绍
hdk_derive
是Holochain开发工具包(HDK)中的一个派生宏工具,它简化了Holochain WASM智能合约的开发过程。通过提供一系列过程宏,它可以帮助开发者更轻松地定义和使用Holochain中的各种数据类型和函数。
hdk_derive
主要解决了HDK中重复性代码编写的问题,通过宏派生自动生成必要的样板代码,让开发者能更专注于业务逻辑的实现。
主要功能
- 简化入口函数的定义
- 自动派生Holochain数据类型的序列化/反序列化
- 提供便捷的宏来定义zome函数
- 自动生成必要的WASM导出
使用方法
基本设置
首先在Cargo.toml
中添加依赖:
[dependencies]
hdk = "0.2"
hdk_derive = "0.2"
serde = { version = "1.0", features = ["derive"] }
定义入口函数
use hdk_derive::zome;
#[zome]
mod my_zome {
#[init]
fn init() {
Ok(())
}
#[validate_agent]
fn validate_agent(validation_data: EntryValidationData<AgentId>) {
Ok(())
}
}
定义入口类型
use hdk_derive::entry_defs;
#[entry_defs]
#[unit_enum(UnitEntryTypes)]
enum EntryTypes {
#[entry_def(required_validations = 5)]
BlogPost(BlogPost),
#[entry_def]
Comment(Comment),
}
#[hdk_entry(id = "blog_post")]
pub struct BlogPost {
title: String,
content: String,
author: AgentPubKey,
}
#[hdk_entry(id = "comment")]
pub struct Comment {
post_hash: HeaderHash,
content: String,
author: AgentPubKey,
}
定义zome函数
use hdk_derive::zome_fn;
#[zome_fn("hc_public")]
fn create_blog_post(blog_post: BlogPost) -> ExternResult<HeaderHash> {
let header_hash = hdk::create_entry(&blog_post)?;
Ok(header_hash)
}
#[zome_fn("hc_public")]
fn get_blog_post(header_hash: HeaderHash) -> ExternResult<Option<BlogPost>> {
let element = hdk::get(header_hash, GetOptions::default())?;
match element {
Some(element) => {
let blog_post: BlogPost = element.entry()
.to_app_option()?
.ok_or(WasmError::Guest("Could not deserialize element to BlogPost".into()))?;
Ok(Some(blog_post))
}
None => Ok(None),
}
}
完整示例
use hdk::prelude::*;
use hdk_derive::{zome, entry_defs};
#[entry_defs]
#[unit_enum(UnitEntryTypes)]
enum EntryTypes {
#[entry_def]
Post(Post),
}
#[hdk_entry(id = "post")]
pub struct Post {
title: String,
content: String,
}
#[zome]
mod blog_zome {
use super::*;
#[init]
fn init() {
Ok(())
}
#[zome_fn("hc_public")]
fn create_post(post: Post) -> ExternResult<HeaderHash> {
hdk::create_entry(&post)
}
#[zome_fn("hc_public")]
fn get_post(header_hash: HeaderHash) -> ExternResult<Option<Post>> {
let element = hdk::get(header_hash, GetOptions::default())?;
match element {
Some(element) => {
let post: Post = element.entry()
.to_app_option()?
.ok_or(WasmError::Guest("Could not deserialize element to Post".into()))?;
Ok(Some(post))
}
None => Ok(None),
}
}
}
完整示例demo
下面是一个更完整的博客系统示例,展示了如何使用hdk_derive
构建一个简单的Holochain应用:
use hdk::prelude::*;
use hdk_derive::{zome, entry_defs};
// 定义入口类型
#[entry_defs]
#[unit_enum(UnitEntryTypes)]
enum EntryTypes {
#[entry_def(required_validations = 3)]
BlogPost(BlogPost),
#[entry_def]
Comment(Comment),
}
// 博客文章结构体
#[hdk_entry(id = "blog_post")]
pub struct BlogPost {
title: String,
content: String,
author: AgentPubKey,
timestamp: u64,
}
// 评论结构体
#[hdk_entry(id = "comment")]
pub struct Comment {
post_hash: HeaderHash,
content: String,
author: AgentPubKey,
timestamp: u64,
}
// 定义zome模块
#[zome]
mod blog_zome {
use super::*;
// 初始化函数
#[init]
fn init() {
Ok(())
}
// 验证代理函数
#[validate_agent]
fn validate_agent(validation_data: EntryValidationData<AgentId>) {
Ok(())
}
// 创建博客文章
#[zome_fn("hc_public")]
fn create_blog_post(title: String, content: String) -> ExternResult<HeaderHash> {
let author = hdk::agent_info()?.agent_latest_pubkey;
let timestamp = sys_time()?.as_seconds();
let blog_post = BlogPost {
title,
content,
author,
timestamp,
};
hdk::create_entry(&blog_post)
}
// 获取博客文章
#[zome_fn("hc_public")]
fn get_blog_post(header_hash: HeaderHash) -> ExternResult<Option<BlogPost>> {
let element = hdk::get(header_hash, GetOptions::default())?;
match element {
Some(element) => {
let blog_post: BlogPost = element.entry()
.to_app_option()?
.ok_or(WasmError::Guest("Could not deserialize element to BlogPost".into()))?;
Ok(Some(blog_post))
}
None => Ok(None),
}
}
// 添加评论
#[zome_fn("hc_public")]
fn add_comment(post_hash: HeaderHash, content: String) -> ExternResult<HeaderHash> {
let author = hdk::agent_info()?.agent_latest_pubkey;
let timestamp = sys_time()?.as_seconds();
let comment = Comment {
post_hash,
content,
author,
timestamp,
};
hdk::create_entry(&comment)
}
// 获取文章的所有评论
#[zome_fn("hc_public")]
fn get_comments_for_post(post_hash: HeaderHash) -> ExternResult<Vec<Comment>> {
let query = QueryFilter::new()
.entry_type(EntryTypes::Comment(Comment::entry_def_id()?))
.include_entries(true);
let elements = hdk::query(query)?;
let mut comments = Vec::new();
for element in elements {
if let Some(entry) = element.entry().to_app_option::<Comment>()? {
if entry.post_hash == post_hash {
comments.push(entry);
}
}
}
Ok(comments)
}
// 辅助函数:获取系统时间
fn sys_time() -> ExternResult<Timestamp> {
Ok(hdk::sys_time()?)
}
}
注意事项
- 使用
hdk_derive
时,确保你的项目是针对WASM目标编译的 - 派生宏生成的代码会处理大部分Holochain特定的样板代码,但开发者仍需理解基本的Holochain概念
- 在定义入口类型时,
required_validations
参数可以控制该条目需要多少验证才能被网络接受 hc_public
属性标记的函数可以被其他zome或前端调用
hdk_derive
极大地简化了Holochain应用开发流程,让开发者能够更专注于业务逻辑而非底层细节。