Ontology Wasm 合約開發工具庫 ontology-wasm-cdt-rust 裡面 Runtime 模組封裝了合約與 Ontology 鏈互動的 API 方法。透過這些 API 方法,合約可以獲得鏈上的資料,或者將合約中的資料儲存到鏈上,以下是這些 API 方法的簡單描述。
接下來,我們來具體講述下這些 API 的使用方法。在此之前,開發者可以從 GitHub 上 clone 下來我們的合約模板,然後在lib.rs檔案中新增合約邏輯程式碼。
Runtime API 使用方法
首先,開發者僅需要透過下面的方式將 Runtime 模組引入到當前合約中:
use ontio_std::runtime;
然後就可以透過 Runtime 引用以上所有的 API 介面。
1. timestamp()
timestamp()方法獲得當前的時間戳,即返回撥用該函式的 Unix 時間,單位為秒。呼叫示例:
let t = runtime::timestamp();
一個簡單的示例程式碼如下:
#![no_std]
extern crate ontio_std as ostd;
use ostd::abi::{Sink, Source};
use ostd::prelude::*;
use ostd::runtime;
fn hello() -> u64 {
runtime::timestamp()//取得當前時間戳
}
#[no_mangle]
fn invoke() {
let input = runtime::input();//獲得輸入方法名和方法引數
let mut source = Source::new(&input);//構造反序列化例項
let action = source.read().unwrap_or_default();//讀取方法名
let mut sink = Sink::new(16);//構造序列化例項
match action {
"hello" => {
sink.write(hello());//將hello()返回的結果序列化
}
_ => panic!("unsupported action!")
}
runtime::ret(sink.bytes());//將序列化後的結果返回給呼叫方
}
在下面的 API 方法講述中,我們將省略具體例子,只介紹 API 方法的作用。小夥伴們可以採用類似於上述例子的程式碼進行試驗。
2. block_height
block_height函式獲得當前區塊鏈網路的區塊高度,呼叫示例:
let t = runtime::block_height();
3. address
address 獲得當前合約的地址,呼叫示例:
let t = runtime::address();
4. caller
caller 獲得呼叫方的合約地址,主要用於跨合約呼叫的場景,比如合約 A 呼叫合約 B 的應用場景, 在合約 B 中就可以呼叫該方法獲得呼叫方合約 A 的地址:
let t = runtime::caller();
5. entry_address
entry_address 獲得入口合約地址,比如有這樣的應用場景,合約 A 透過合約 B 呼叫合約 C的方法,此時,在合約 C 中就可以透過該方法拿到合約 A 的地址,呼叫示例:
let t = runtime::entry_address();
6. current_blockhash
current_blockhash 獲得當前區塊的 hash,示例如下:
let t = runtime::current_blockhash();
7. current_txhash
current_txhash獲得當前交易的 hash,示例如下:
let t = runtime::current_txhash();
8. sha256
sha256計算輸入引數的 hash256值:
let h = runtime::sha256("test");
9. check_witness
check_witness(from)校驗是否含有該地址的簽名:
· 驗證當前的函式呼叫者是不是含有 from 的簽名 。若是(即簽名驗證透過),則函式返回 true;
· 檢查當前函式呼叫者是不是一個合約。若是合約,且是從該合約發起去執行函式,返回 true。即,驗證 from 是不是caller的返回值。其中,caller()函式可以得到呼叫當前智慧合約的合約雜湊值。
assert!(runtime::check_witness(from));
10. notify
notify函式將合約中事件推送到全網,並將其內容儲存到鏈上,呼叫方法如下:
runtime::notify("notify".as_bytes())
在合約中推送事件時,可以自定義一個事件函式,加上#[event]註解即可。我們的工具庫中提供了該屬性巨集,需要透過use ostd::macros::event;引入。示例如下:
use ostd::macros::event;
mod notify {
use super::*;
#[event]
pub fn transfer(from: &Address, to: &Address, amount: U128) {}
}
fn transfer(from: &Address, to: &Address, amount: U128) -> bool {
...
notify::transfer(from, to, amount);
}
11. panic
panic方法可以在合約執行發生致命錯誤的時候立即終止交易的執行,然後回滾當前的交易。該方法在跨合約呼叫的場景很重要,比如在如下的應用場景中,合約 A 中的方法 a 呼叫合約 B 中的方法 b,其中合約 A 的 a 方法在呼叫合約 B 的 b 方法之前會儲存一些資料到鏈上,但是在呼叫合約 B 的 b 方法時,發生了致命的錯誤,需要回滾合約 A 中 a 方法執行過程中儲存的資料,此時就需要在合約 B 的 b 方法中應用panic方法實現該功能。
runtime::panic("test");
結語
本文主要講解了 Runtime 模組的 API,該模組提供了與鏈互動的功能,其中 notify 用於合約中推送事件,開發者可以使用自定義事件的方式推送事件,而不是直接使用 notify 方法。use ostd::macros::event屬性巨集提供了更加友好的事件推送機制。在跨合約呼叫的過程中,panic方法在異常處理中具有非常重要的。下一期我們將介紹如何實現 Wasm 合約與 NeoVM 合約及 Native 合約之間的相互呼叫,歡迎大家關注學習。
Ontology 率先支援 Wasm 合約將會大大提高混合虛擬機器的效能,也將吸引眾多不同語言的技術開發者加入本體社羣,共同推進區塊鏈技術的研發,豐富本體強大的技術生態。同時,基於本體強大的技術研發團隊,也可將現有的優秀技術整合到本體生態上來,為合約開發者增加更多選項。歡迎各位技術夥伴與我們共同前行!