溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么實現(xiàn)區(qū)塊鏈中的JVM

發(fā)布時間:2021-06-12 11:18:31 來源:億速云 閱讀:242 作者:小新 欄目:互聯(lián)網(wǎng)科技

這篇文章主要介紹了怎么實現(xiàn)區(qū)塊鏈中的JVM,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

虛擬機是區(qū)塊鏈中的一個關(guān)鍵組件,用來執(zhí)行智能合約,需要滿足安全性和一致性,所謂的安全性一般是指合約代碼需要在隔離的沙箱環(huán)境中運行,以免錯誤或惡意代碼造成對區(qū)塊鏈系統(tǒng)的損害。而一致性是指區(qū)塊鏈網(wǎng)絡(luò)中任意誠實的節(jié)點執(zhí)行同一個合約,如果輸入?yún)?shù)一致,輸出結(jié)果都應(yīng)該是一致的。目前比較主流的虛擬機實現(xiàn)包括EVM、WASM,其他的實現(xiàn)還有如星云鏈的谷歌V8,Nervos的RISC-V,SOLANA的BPF等,設(shè)計如此眾多不同虛擬機的目的,主要是對區(qū)塊鏈系統(tǒng)互操作性、安全性、執(zhí)行性能、硬件兼容性等因素的考量。如EVM更注重的是安全性,雖然Solidity設(shè)計是圖靈完備的語言,但是通過自身限定的最小語法集,來保證合約的安全可控,而星云鏈采用V8,更多的一方面也是考慮智能合約的互操作性,使用javascript降低了合約的編寫門檻。盡管Solidity也是類javascript語言,并且入門門檻也不是很高,但是對于很多想入行區(qū)塊鏈的程序員來說,學(xué)習(xí)一門新的語言還是需要一些成本的。

JVM 為何在區(qū)塊鏈中使用的較少
JVM本身就是一種虛擬機,而且java語言又是最為流行的幾大語言之一,為什么區(qū)塊鏈中使用的較少呢?個人總結(jié)主要包含如下幾個原因:

1、語言的可控性,同c++/golang/rust等主流開發(fā)語言類似,java也是系統(tǒng)級語言,可以訪問嘉盛中文網(wǎng)http://www.jiasheng-chn.com操作系統(tǒng)的任意資源,例如讀寫文件、訪問網(wǎng)絡(luò)等
2、執(zhí)行性能,java是解釋性語言,jvm載入的class文件是一種中間語言,真正執(zhí)行的時候才會進一步解釋成機器碼執(zhí)行,所以主流的jvm都會引入JIT對熱點代碼進行及時編譯來提高執(zhí)行效率
3、語言的復(fù)雜性,java有很多復(fù)雜的語法,比如支持OOP的接口、多態(tài)、反射和多線程控制等,對于更注重過程化執(zhí)行的智能合約用處不大,而且容易影響合約執(zhí)行的一致性。
那如果能解決這些問題,針對jvm做一個自定義的最小集合裁剪,那對于很多java開發(fā)者來說,還是比較有吸引力的。

區(qū)塊鏈中的jvm方案應(yīng)如何實現(xiàn)?

如何傳遞參數(shù)
java是OOP的,如果編寫合約,需要先定義一個合約類,合約類中定義的類方法就是合約能夠執(zhí)行的方法。區(qū)塊鏈上合約執(zhí)行都是通過交易觸發(fā)的,而合約地址、輸入?yún)?shù)需要通過交易攜帶,首先要解決的問題就是如何傳遞這些信息給合約,對于基本類型處理比較簡單,可以都編碼成字符串進行傳遞,合約執(zhí)行的時候根據(jù)方法的參數(shù)類型解析成對應(yīng)的結(jié)果,而對于自定義類的對象如何處理呢?可以使用json、xml、proto等編碼方式對類對象進行逐字段編碼,如果字段也是個自定義類對象,那就遞歸進行編碼。這幾種編碼方式的有點是利于閱讀,但是缺點就是空間占用較大,對于區(qū)塊鏈這種冗余分布式存儲機制來講,占用空間越少越好,所以可以采用以太坊中使用的RLP(遞歸長度前綴)編碼方式。

如何載入java系統(tǒng)類

參考jvm.go代碼庫,可以在目標(biāo)節(jié)點上預(yù)安裝一個jdk環(huán)境,然后在節(jié)點應(yīng)用啟動時把需要用到的java系統(tǒng)類包預(yù)加載入內(nèi)存的一個map中。這里可以根據(jù)實際情況對導(dǎo)入進來的系統(tǒng)類包做一些選擇裁剪,同時過濾掉容易造成執(zhí)行結(jié)果不一致的包,比如隨機數(shù)、多線程,IO操作等。
如何模擬離線沙盒執(zhí)行環(huán)境
筆者采用的是如上裁剪系統(tǒng)類包的做法,限制了用戶合約直接引用網(wǎng)絡(luò)、讀寫、cmd等操作權(quán)限,同時不允許用戶合約直接引用第三方j(luò)ar包或native執(zhí)行第三方庫等,保證合約的安全性。這種方式比較簡單粗暴并不是特別好的方案,對于惡意代碼跳過系統(tǒng)包,自己實現(xiàn)類似的訪問資源的操作,就無法檢測出來,并不是一個好的方案,如果有好的方案可以一起討論。
如何屏蔽隨機數(shù)、多線程等容易造成執(zhí)行結(jié)果不一致的語法執(zhí)行
同上也是限制引入包的做法屏蔽,對于惡意代碼自己實現(xiàn)隨機數(shù),這個也同樣無法檢測出來。

如何啟動合約執(zhí)行

jvm執(zhí)行是需要找到Main入口,而合約代碼可以不提供Main函數(shù),我們可以在生成合約包的工具中自動生成相應(yīng)的Main函數(shù),添加new合約對象,然后調(diào)用對應(yīng)方法的代碼。

如何讀寫合約狀態(tài)變量
java存取的指令碼主要是load和store系列指令。但是對于合約啟動執(zhí)行時,需要先從數(shù)據(jù)庫中讀取到歷史的狀態(tài),比如合約中的余額變量,如上自動生成的Main函數(shù)中會先new一個合約對象,于是我們可以捕獲到合約對象的構(gòu)造函數(shù),注入讀取數(shù)據(jù)庫代碼,并將合約對象的成員變量全部恢復(fù)。這里也可以參考solidity的方法,區(qū)分內(nèi)存和存儲變量,可以通過注解來實現(xiàn)。jvm可以解析變量的注解,如果注解是Storge,就存取數(shù)據(jù)庫,否則從當(dāng)前內(nèi)存獲取。

如何返回執(zhí)行結(jié)果

用戶合約代碼可能會執(zhí)行失敗,比如余額不足,權(quán)限不匹配等,我們可以將交易回執(zhí)的指針關(guān)聯(lián)到合約執(zhí)行的主Thread中,這樣在執(zhí)行失敗的地方,都可以隨時返回,并且自定義相關(guān)錯誤信息。

如何回退交易
可以參考以太坊的方案,利用MPT保存狀態(tài)變量的歷史值,狀態(tài)變量的修改是實時修改本地存儲,如果交易失敗回滾,直接修改為上一個歷史狀態(tài)即可。

如何提升執(zhí)行性能
我們可以用native實現(xiàn)類似以太坊的系統(tǒng)合約的功能或替換掉java中比較耗時的操作,比如hashmap。參考jvm.go的實現(xiàn),我們可以定制很多native方法來提升執(zhí)行效率,例如合約中執(zhí)行sha256,如果用java自帶的方法,會增加幾千條指令。我們也可以利用native方法來完成自定義的一些功能,比如零知識證明、同態(tài)加密庫等。

如何解決停機問題

參考以太坊的gas機制,按照指令粒度統(tǒng)計燃燒的gas,對于涉及到存儲的指令,根據(jù)存儲的數(shù)據(jù)大小增加gas比例。這樣實現(xiàn)的好處是gas統(tǒng)計比較精確,但是java指令較多,代碼實現(xiàn)繁瑣,執(zhí)行性能也會影響。另外看到業(yè)內(nèi)使用WASM的主流方案都是統(tǒng)計指令注入到了編譯生成的機器碼中,這個方案也可以嘗試,但需要自己實現(xiàn)javac。

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“怎么實現(xiàn)區(qū)塊鏈中的JVM”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI