學(xué)著使用AssemblyScript書寫只能合約(js開發(fā)者適用)
WebAssembly虛擬機(jī)已經(jīng)成為越來越多區(qū)塊鏈智能合約執(zhí)行引擎的選擇。WebAssembly之所以能夠在這幾年受到越來越多人的關(guān)注,除了其卓越的性能以外更重要的是它的包容性,WebAssemby現(xiàn)階段已經(jīng)支持越來越多的語言,也讓寫合約的門檻變得更加的低。
試想一下,當(dāng)我們想編寫一個區(qū)塊鏈的合約的時候,我們不需要去學(xué)習(xí)Solidity的語法,C語言的開發(fā)人員可以用他們最熟悉的C開發(fā)合約,Rust的開發(fā)可以用Rust直接編寫,Nodejs的開發(fā)可以直接用JS來編寫,那么對于構(gòu)建區(qū)塊鏈合約的生態(tài)就有了重要的意義。
什么是AssemblyScript?
AssemblyScript 是一個把 TypeScript 轉(zhuǎn)換到 WebAssembly 的編譯器。
Typescript是微軟開發(fā)的編程語言,通過在JavaScript的基礎(chǔ)上添加類型定義構(gòu)建而成,現(xiàn)在TypeScript已經(jīng)變得相當(dāng)受歡迎。由于AssemblyScript只允許TypeScript的有限功能子集,對新人十分友好,開發(fā)者不需要花太多時間就可以上手。
AssemblyScript具有以下特點(diǎn):
AssemblyScript是專門針對WebAssembly而集成的功能集,使開發(fā)人員可以通過代碼進(jìn)行底層控制;
AssemblyScript作為TypeScript的變體,可以輕松地將其編譯為WebAssembly,而無需學(xué)習(xí)新的語言;
集成在現(xiàn)有的Web生態(tài)中,無需安裝環(huán)境和工具鏈,只需npm install它即可;
如何配置AssemblyScript環(huán)境?
【預(yù)置條件】
首先我們需要下載最新的穩(wěn)定的Node.js以及npm包管理工具。
【新建項目】
我們首先創(chuàng)建一個新的目錄并且像往常一樣初始化Node.js的模塊:
npm init
然后我們需要安裝AssemblyScript的編譯器:
npm install --save-dev assemblyscript
當(dāng)安裝完成以后,編譯器提供了非常便捷的方法來新建AssemblyScript項目:
npx asinit
【目錄結(jié)構(gòu)解析】
在上述完成項目的構(gòu)建以后,我們可以看到項目下會自動生成一些文件和文件夾,下面會對這些生成的目錄結(jié)構(gòu)進(jìn)行一個解析:
./assembly
所有需要被編碼成wasm的相關(guān)代碼都需要放在該文件夾下。
./assembly/tsconfig.json
TypeScript的配置文件,其中集成了一些推薦的AssemblyScript的配置。
./assembly/index.ts
將被編譯成wasm的入口文件
./build
所有最終生成的wasm以及相關(guān)文件都會被存放在該目錄下
./build/.gitignore
Git配置文件
./asconfig.json
配置文件,定義了release版本和Debug版本的相關(guān)配置
./package.json
相關(guān)的包信息,同時提供了能夠編譯WebAssembly的命令
./tests/index.js
項目測試的入口文件
./index.html
能夠加載模塊的網(wǎng)頁文件.
【編譯項目】
從上面的項目目錄我們可以看到我們需要在assembly/index.ts中編寫自己的wasm模塊,在編寫完模塊之后,我們就可以將整個項目編譯成wasm文件了:
npm run asbuild
生成的編譯好的二進(jìn)制文件將會被存放在build目錄下,如果想要對整個模塊進(jìn)行測試,可以運(yùn)行命令:
npm test
如何編寫合約?
前文我們介紹了「如何用AssemblyScript編寫代碼和編譯生成wasm文件」,那么,如何利用wasm虛擬機(jī)將AssemblyScript結(jié)合到區(qū)塊鏈體系里呢?
首先要處理的是合約方法的生成,在AssemblyScript中,如果我們想要一個加法的合約方法,可以在AssemblyScript中添加如下代碼:
export function add(a: i32, b: i32): i32 {
return a + b;
}
這樣編譯出的wasm文件就會直接提供add的方法讓合約調(diào)用者調(diào)用來做加法。
AssemblyScript也提供了wasi的接口,利用這個接口來給方法提供字符串或者字節(jié)數(shù)組的輸入和輸出。例如:我們可以直接通過操作虛擬機(jī)的內(nèi)存給合約傳遞參數(shù):
export function allocate(size: usize): usize {
return heap.alloc(size);
}
export function allocate(size: usize): usize {
return heap.alloc(size);
}
這段代碼中我們就是向虛擬機(jī)堆上申請?zhí)囟ù笮〉膬?nèi)存空間,返回的是申請的內(nèi)存的地址,可以在虛擬機(jī)外向這塊內(nèi)存輸入上下文,從而達(dá)到輸入輸出字符串的目的。
總結(jié)
AssemblyScript編寫合約為廣大JS開發(fā)提供了編寫合約的可能,也極大程度上豐富了區(qū)塊鏈合約的生態(tài)環(huán)境。
同時經(jīng)過實(shí)際應(yīng)用我們發(fā)現(xiàn)通過AssemblyScript編譯出來的wasm合約比rust和golang等編譯出來的wasm合約體積更小,這樣也能極大的減緩區(qū)塊鏈鏈上存儲的壓力,大幅度提升虛擬機(jī)加載合約的速度,提高了合約交易的性能。