知世金融网专注于股票行情,期货开户,外汇储备等最新相关资讯信息提供投资者参考学习!

当前位置:网站首页 > 区块链 > 正文

聊聊Ontology上三种合约“交相辉映”的故事

原创
文章作者
知世-金融领域资深作者
知名金融领域作者,从事金融超过十余年,在行业内有一定影响力。
金融风险管理师认证证书 常识职业资格认证 特许金融分析师 国际金融理财师认证证书
发布时间:2020-02-16 19:33:32 发布来源:本体研究院 文章点击:97

10月29日,Ontology v1.8.0重磅发布!经过数月在测试网上的稳定运行,Wasm 功能也正式登陆了主网。目前为止,Ontology v1.8.0已支持 Native、NeoVM 和 Wasm 三种类型的合约,不同类型的合约之间可...

目录

    本文标题聊聊Ontology上三种合约“交相辉映”的故事,作者:知世,本文有1769个文字,大小约为7KB,预计阅读时间5分钟,请您欣赏。知世金融网众多优秀文章,如果想要浏览更多相关文章,请使用网站导航的搜索进行搜索。本站虽然不乏优秀之作,但仅作为投资者学习参考。

    10月29日,Ontology v1.8.0重磅发布!经过数月在测试网上的稳定运行,Wasm 功能也正式登陆了主网。目前为止,Ontology v1.8.0已支持 Native、NeoVM 和 Wasm 三种类型的合约,不同类型的合约之间可以无缝交互。

    1. Native 合约

    也是 Ontology 的原生合约,直接由 Golang 语言实现,目前已有的原生合约均在创世块中部署,执行速度快。

    2. NeoVM 合约

    运行于 NeoVM 虚拟机上,具有合约文件小、字节码简单及高性能的特点。

    3. Wasm 合约

    这种合约支持多种高级语言开发的程序直接编译成 Wasm 字节码,功能更加丰富,可以直接引用很多优秀的第三方库,且 Wasm 社区也十分活跃。

    今天我们来聊聊 Ontology 上的这三种合约是如何“交相辉映”的。你将会了解到 Wasm 合约与 Native 合约及 NeoVM 合约调用的实现。在介绍下面的调用过程中,大家可以先把我们的合约模板 clone 下来,然后修改lib.rs文件,进行测试。

    Runtime 模块中跨合约调用接口介绍

    ontology-wasm-cdt-rust 库中封装了跨合约调用的一个通用接口,如下:

    pub fn call_contract(addr: &Address, input: &[u8]) -> Option<Vec<u8>>
    该方法需要两个参数,第一个是addr目标合约地址,第二个是input调用的目标合约的方法名和方法参数。在跨合约调用的过程中,要按照正确的方式序列化方法名和方法参数。其中调用 NeoVM 合约和调用 Native 合约序列化方法名和方法参数是不一样的,下面我们会详细介绍如何正确地序列化方法名和方法参数。

    Wasm 合约调用 Native 合约

    ontology-wasm-cdt-rust 库中封装了ont和ong合约调用接口,只需要通过use ostd::contract::ont;引入即可。调用比较简单,现仅列出ont转账的合约调用示例:

    use ostd::contract::ont;
    ...
    let (from, to, amount) = source.read().unwrap();
    sink.write(ont::transfer(from, to, amount));

    现在,我们看一下ont::transfer方法的实现源码:

    pub fn transfer(from: &Address, to: &Address, val: U128) -> bool {
    let state = [TransferParam { from: *from, to: *to, amount: val }];
    super::util::transfer_inner(&ONT_CONTRACT_ADDRESS, state.as_ref())
    }

    由上面的源码可以看到,我们先构造了一个TransferParam类型的实例,然后构造了一个数组,这一步是为了支持一笔交易中的多笔转账功能。最后将ont的合约地址和构造好的数组引用传给util::transfer_inner方法,我们接着看util::transfer_inner的实现源码如下:

    pub(crate) fn transfer_inner(
    contract_address: &Address, transfer: &[super::TransferParam],
    ) -> bool {
    let mut sink = Sink::new(64);
    sink.write_native_varuint(transfer.len() as u64);

    for state in transfer.iter() {
    sink.write_native_address(&state.from);
    sink.write_native_address(&state.to);
    sink.write(u128_to_neo_bytes(state.amount));
    }
    let mut sink_param = Sink::new(64);
    sink_param.write(VERSION);
    sink_param.write("transfer");
    sink_param.write(sink.bytes());
    let res = runtime::call_contract(contract_address, sink_param.bytes());
    if let Some(data) = res {
    if !data.is_empty() {
    return true;
    }
    }
    false
    }

    由之前的教程可知,在合约中进行参数序列化的工具是Sink实例,因此需要先构造一个Sink实例。由于要序列化的参数是个数组,所以要先序列化该数组的长度。在序列化数组长度时,要将数组长度转换成u64的数据类型,然后调用sink.write_native_varuint方法进行序列化。数组长度序列化完成后,开始序列化数组中的每个元素。对于Address类型的数据,需要调用sink.write_native_address方法进行序列化;对于U128类型的数据,需要先将其转换成 bytearray 类型,然后进行序列化;而对于U128转换成 bytearray 类型的数据,需要调用u128_to_neo_bytes方法。至此,方法参数序列化完成。

    下面我们要开始序列化方法名,此时需要重新构造一个序列化实例,用这个新的实例序列化方法名。在序列化方法名之前,先序列化Version。该字段默认是0,然后序列化方法名,最后再序列化刚才已完成序列化的方法参数。至此,调用 Native 合约方法的参数构造过程已完成,可以调用runtime接口中的方法进行调用了。

    Wasm 合约调用 NeoVM 合约

    Wasm 合约调用 NeoVM 合约时,要求传递的参数类型实现VmValueEncoder和VmValueDecoder接口,ontology-wasm-cdt-rust 库已经为常用的数据类型实现了该接口,例如:&str、&[u8]、bool、H256、U128和 Address。contract模块中封装好了neo模块,开发者可以直接使用neo模块来调用 NeoVM 合约,使用示例如下:

    use ostd::contract::neo;
    ...
    let res = neo::call_contract(&NEO_CONTRACT_ADDR, ("init", ()));
    match res {
    Some(res2) => {
    let mut parser = VmValueParser::new(res2.as_slice());
    let r = parser.bool();
    sink.write(r.unwrap_or(false));
    }
    _ => sink.write(false),
    }

    neo::call_contract需要两个参数,第一个是调用的目标合约地址,第二个是调用的合约方法需要的方法名和方法参数。在上面的例子中,方法名是init,方法参数是一个空的 Tuple 类型的数据。Wasm 合约中调用 NeoVM 合约时,得到的返回值需要使用VmValueParser进行反序列化,拿到合约返回结果。下面我们看一下neo::call_contract的实现源码,示例如下:

    pub fn call_contract<T: crate::abi::VmValueEncoder>(
    contract_address: &Address, param: T,
    ) -> Option<Vec<u8>> {
    let mut builder = crate::abi::VmValueBuilder::new();
    param.serialize(&mut builder);
    crate::runtime::call_contract(contract_address, &builder.bytes())
    }

    从上面的源码可以看到neo::call_contract方法需要两个参数,第一个参数是目标合约地址,第二个就是方法名和方法参数,并且要求方法名和方法参数必须实现VmValueEncoder接口。此外,在对方法名和方法参数序列化时用的是VmValueBuilder而不是Sink,这一点值得开发者注意。得益于 Rust 强大的宏功能,我们使用宏为 Tuple 类型的数据实现VmValueEncoder和VmValueDecoder接口,所以在调用的时候,我们传进来的是 Tuple 类型的数据 ("init",())。

    结语

    本文主要讲了 Ontology Wasm 合约如何调用 Native 合约和 NeoVM 合约。其中以ont::transfer为例讲解了 Wasm 调用 Native合约的实现源码;以neo::call_contract为例讲解了 Wasm 合约调用 NeoVM 合约的实现源码。在跨合约调用的过程中,参数的序列化是本文的重点。尤其在调用不同合约时,采用的序列化方法不一样,这一点需要特别注意。

    重点划完啦~你是否有所收获呢?如果你有任何疑问,欢迎扫描文末二维码,加入本体技术社区,与技术爱好者共同学习探讨哦!

    本文相关推荐:

    以上便是知世金融网给大家分享的关于聊聊Ontology上三种合约“交相辉映”的故事/qkl/28081.html的相关信息了,希望能帮助到大家,更多金融相关信息,敬请关注知世金融网!

    网站内容均来自互联网,如侵害您的利益联系客服进行删除!

    关键词:交相辉映
    (0)
    (0)

    上一篇:亚瑟王的「随机」挑战:从交互到非交互式零知识证明

    下一篇:吴忌寒与Bitcoin.com CEO谈挖矿和行业增长

    本文标题:聊聊Ontology上三种合约“交相辉映”的故事

    本文地址:/index.php?s=article&c=search&keyword=%E4%BA%A4%E7%9B%B8%E8%BE%89%E6%98%A0

    金融知名领域

    南方财富网 | 金融界 | 金融界 |

    更多推荐

    • 茅台吃饱,经销商哭倒
      茅台吃饱,经销商哭倒
    • 汇金的五次增持从短期看具有一定的“稳定器“作用,但从市场表现看效果逐次递减
      汇金的五次增持从短期看具有一定的“稳定器“作用,但从市场表现看效果逐次递减
    • 158亿元!比亚迪收购!
      158亿元!比亚迪收购!
    • 9月价格回落近五成 “冷静期”酒店业备战“十一”市场
      9月价格回落近五成 “冷静期”酒店业备战“十一”市场
    • 2023哈马博览会哈尔滨银行展区精彩纷呈
      2023哈马博览会哈尔滨银行展区精彩纷呈
    • 大额解禁撂倒股价 医疗影像龙头跌出千亿俱乐部 葛兰二季度大幅减仓
      大额解禁撂倒股价 医疗影像龙头跌出千亿俱乐部 葛兰二季度大幅减仓
    • A股,又上了热搜!数字要素概念走高多股涨停,锂电池板块走低恩捷股份大举跌停
      A股,又上了热搜!数字要素概念走高多股涨停,锂电池板块走低恩捷股份大举跌停
    • 最新!巨头出手,加仓宁王51%
      最新!巨头出手,加仓宁王51%
    • 600亿巨头暴雷
      600亿巨头暴雷
    • 一天32家!科创板回购潮涌来
      一天32家!科创板回购潮涌来
    • 提振信心实招来了!30余家上市公司密集出手 最高要买10亿
      提振信心实招来了!30余家上市公司密集出手 最高要买10亿
    • 高盛再发50年后预测:2075年印度股市全球市值占比将升4倍 中国升3成
      高盛再发50年后预测:2075年印度股市全球市值占比将升4倍 中国升3成

    新闻资讯栏目

    站长QQ: 2397470084