智能合约语言(eDSL)—— proc_macro实现合约init函数

        我们通过属性宏来实现合约的init函数,call函数其实和init是类似的;

        GitHub - XuHugo/xwasm

        构建属性宏,要在cargo.toml里面设置一些参数,这是必须的。一般来说,过程宏必须是一个库,或者作为工程的子库,不能单独作为一个源文件存在。

[dependencies]
syn = { version = "1.0.63", features = [ "full", "extra-traits" ] }
quote = "=1.0.0"
proc-macro2 = "1.0"

[lib]
proc-macro = true

而编写过程宏,在stable版本里,我们需要借助三个crate:

  • syn,这个是用来解析语法树(AST)的。各种语法构成
  • quote,解析语法树,生成rust代码,从而实现你想要的新功能。
  • proc_macro(std) 和 proc_macro2(3rd-party)
实现init的属性宏

        函数的签名如下,这个格式除了函数名字,其他的都不要修改;

#[proc_macro_attribute]
pub fn init(attr: TokenStream, item: TokenStream) -> TokenStream {

        需要加一个关键字proc_macro_attribute;由两个参数,一个attr,一个item;对应到合约里就是如下图;

        下一步解析attr,找到contract对应的合约名称放到contract变量中;

let attrs = parse_macro_input!(attr as AttributeArgs);
let contract = get_attribute(attrs.clone(), "contract").unwrap().unwrap();

        然后处理payable,之前没有讲解这个标记的作用,其实就是标记,合约函数是否可以接口币;

let mut setup_function_args = proc_macro2::TokenStream::new();
    let mut function_args = vec![];
    let amount_ident = format_ident!("amount");

    if contains_attribute2(attrs.clone(), "payable") {
        function_args.push(quote!(#amount_ident));
    } else {
        setup_function_args.extend(quote! {
            if #amount_ident != 0 {
                return -1;
            }
        });
    };

        就是通过contains_attribute2判断是否包含,payable,如果有,就会将用户传入的代币的数量记录,否则就判断,用户传入代币数量不为零,就返回-1;

        然后就是结合合约名字,给函数重新命令,我们设定,init函数的名字为,init_合约名称,如果单单用这个做标识会有冲突,先不管这个;

let ast = parse_macro_input!(item as Item);
    let init_function_name = format_ident!("init_{}", contract.value());
    let init_name = format!("init_{}", contract.value());

        现在开始处理item了,首先判断是否是函数;不是就返回错误了;

let function_name = if let syn::Item::Fn(itemfn) = ast.clone() {
        itemfn.sig.ident
    } else {
        return syn::Error::new(Span::call_site(), format!("#[init] must be function."))
            .into_compile_error()
            .into();
    };

        最后重新组合init函数,

let output = quote! {
        #ast
        #[export_name = #init_name]
        pub extern "C" fn #init_function_name(amount:u64)->i32{
            use xq_std::{ContractContext,serde_json};
            let initctx =  ContractContext;
            #setup_function_args
            match #function_name(initctx, #(#function_args),*){
                Ok(o)=>{
                    let r = serde_json::to_string(&o).unwrap();
                    ContractContext.return_data(r.clone());
                    return 1
                }
                Err(e)=>{
                    let err = e.to_string();
                    ContractContext.error(err.clone());
                    return 0
                }
            }
        }
    };

        pub extern "C" fn 需要注意,虽然我们用rust写合约,但是写完之后,是编译成wasm格式的,相当于一个库文件了,最终谁会调用并不明确,所以需要使用这FFI的形式。

        这部分其实还是最终调用了我们item部分的函数,只是再调用之前添加一些检测和前置工作,例如payable的检测;调用之后呢,也添加了一些工作,例如,将返回值转化为json的字符串。有点类似与python的修饰符。

        call函数的实现其实和这个是一样,有细微的差别,大家可以自己去对比一下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/441749.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Git】项目源码迁移到另一个gitlab(保留原来提交历史记录)

目录 前情提要迁移方案IDEA远程仓库管理团队其他成员切换gitgit命令操作界面 前情提要 公司原来是自己私有部署的gitlab。有了研发云后就希望将代码推送到研发云的代码仓库上。这时候需要迁移并保留原来提交的历史记录。 迁移方案 登录新的gitlab(代码仓库)新建空白项目获取…

DEAP:利用生理信号进行情绪分析的数据库【DEAP数据集】

文章目录 摘要引言刺激选择实验环境参与者步骤参与者自我评估 主观评价分析EEG频率与参与者评分之间的相关性单次试验分类结果 结论 点击下载原文 摘要 ● DEAP:用于分析人类情感状态的多模态数据集。 ● 32名参与者观看了40个一分钟长的音乐视频。 ● 参与者根据唤…

Postman(注册,使用,作用)【详解】

目录 一、Postman 1. Postman介绍 2. 安装Postman 3. 注册帐号再使用(可保存测试记录) 4. 创建workspace 5. 测试并保存测试记录 一、Postman postman工具可以发送不同方式的请求,浏览器只能发送get请求(所有用这个工具) 在前后端分离开发模式下,前端技术人员…

简历–工作经历–通用

文章目录 底层逻辑导图要做到:避免出现:爽文模版:逆境努力逆袭:娱乐 底层逻辑 写作底层逻辑: 简历是给面试者/老师看的,要让人家看起来轻松。 工作经历方面,时间一般是倒着写的(考官…

基于SSM的党务政务服务热线平台(有报告)。Javaee项目。ssm项目。

演示视频: 基于SSM的党务政务服务热线平台(有报告)。Javaee项目。ssm项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构,通过Spri…

机器学习笔记 计算机视觉中的测距任务常见技术路线

一、计算机视觉中的测距任务 测距是计算机视觉中的一项关键任务,涉及测量物体和相机之间的距离。这些信息可用于多种应用,包括机器人、自动驾驶汽车和增强现实。测距技术有很多种,包括主动式和被动式,每种技术都有自己的优点和局限性。主动测距技术,例如飞行时间、结构光和…

推荐一款go语言的开源物联网框架-opengw

推荐一款go语言的开源物联网框架,设计思想不错,值的学习。 技术交流 QQ群1028704210 官网及驱动下载 http://www.opengw.cn http://www.opengw.cn/col.jsp?id104 可执行文件下载 https://gitee.com/my_iot/goAdapter/releases 码云地址 https:/…

大语言模型如何充分理解人类自然语言指令

经过海量数据预训练后的语言模型虽然具备了大量的知识,但是由于其训练的目标仅是进行下一个词的预测,此时的模型还不能够理解并遵循人类自然语言的指令。指令微调(Instruction Tuning),是指在已经训练好的语言模型的基础上,通过使…

Linux命令详解——mkdir创建文件夹与touch创建文件

在windows图形化系统中想要通识创建多个文件夹似乎是一件比较困难的事情,但在linux系统下,这将变得简单 mkdir参数,-p,递归创建文件夹 mkdir创建多个文件 touch可以创建文件,以及修改文件时间

政安晨:【深度学习处理实践】(三)—— 处理时间序列的数据准备

在深度学习中,对时间序列的处理主要涉及到以下几个方面: 序列建模:深度学习可以用于对时间序列进行建模。常用的模型包括循环神经网络(Recurrent Neural Networks, RNN)和长短期记忆网络(Long Short-Term M…

防火墙配置实验

配置 配置IPSec FW1 FW3 NAT策略 FW1 FW3 安全策略 FW1 FW3 最后测试

数字音频工作站(DAW)fl studio 21 for mac 21.2.3.3586中文版图文安装教程

随着音乐制作行业的不断发展,越来越多的音乐人和制作人开始使用数字音频工作站(DAW)来创作和制作音乐。其中FL Studio 21是一个备受欢迎的选择,因为它提供了强大的音乐制作工具和易于使用的界面。 然而,一直以来&…

java数据结构与算法刷题-----LeetCode208. 实现 Trie (前缀树)

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846 文章目录 解题思路 就是一种数据结构,一般自动补完&#xff0c…

go切片实现原理

近日一直在学习golang,已经产出如下博客一篇 GO闭包实现原理(汇编级讲解) 引言 最近在使用go语言的切片时,出现了一些意料之外的情况,遂查询相关文档学习后写下此篇博客 正文 首先,我们思考,go在通过函数传递一个切片时,是通过引用传递的吗,还是通过值传递的呢(答案将会很…

Axure Cloud如何给每个原型配置私有域名

需求 在原型发布之后,自动给原型生成一个独立访问的域名,类似http://u591bi.axshare.bushrose.cn,应该如何配置呢? 准备事项 已备案域名 如何备案?阿里云备案流程 已安装部署Axure Cloud 如何安装部署,请…

Redis系列之持久化机制RDB和AOF

Redis系列之持久化机制RDB和AOF 文章目录 1. 为什么需要持久化?2. 持久化的方式3. RDB机制3.1 RDB机制介绍3.2 配置RDB3.3 什么时候触发3.4 操作实例3.5 RDB优势和不足 4. AOF机制4.1 什么是AOF机制?4.2 同步机制4.3 重写机制4.4 AOF的优势和不足 混合模…

SQL注入攻击 - update注入

环境准备:构建完善的安全渗透测试环境:推荐工具、资源和下载链接_渗透测试靶机下载-CSDN博客 一、MySQL UPDATE语句复习: UPDATE语句用于修改表中的数据,基本形式为:UPDATE 表名称 SET 列名称新值 WHERE 更新条件;语…

SpringCloud Ribbon 负载均衡服务调用

一、前言 接下来是开展一系列的 SpringCloud 的学习之旅,从传统的模块之间调用,一步步的升级为 SpringCloud 模块之间的调用,此篇文章为第三篇,即介绍 Ribbon 负载均衡服务调用 二、概述 2.1 Ribbon 是什么 Spring Cloud Ribbon…

云计算 3月8号 (wordpress的搭建)

项目wordpress 实验目的: 熟悉yum和编译安装操作 锻炼关联性思维,便于以后做项目 nginx 编译安装 1、安装源码包 [rootlinux-server ~]# yum -y install gcc make zlib-devel pcre pcre-devel openssl-devel [rootlinux-server ~]# wget http://nginx.…

PCL不同格式点云读取速度(Binary和ASCII )

首先说明一点:Binary(二进制)格式点云文件进行读取时要比Ascll码格式点云读取时要快的多,尤其是对于大型的点云文件,如几百万、甚至几千万个点云的情况下。 今天遇到了一种情况,在写项目的时候进行点云读取,读取的时候…