
編者按:區塊鏈涉及到的技術很多,從互聯網底層到不明覺厲的密碼學,可是往往關注幣價者多而研究技術的人少。牛市的時候,大家為了炒幣也會努力學習,熊市的時候,反正也沒啥事,我覺得可以更加努力學習。作為一個文科生,我當然會有很多理科生看起來覺得很白痴的問題。作為一個記者,我不難找到業內懂的人用人話給我解釋,而且他們往往不會當面嫌棄我。
我寫下我的學習筆記大家分享。圖片描述圖片描述
這篇筆記真的長得超出我意料之外
智能合約是目前公鏈需要完善的一大方向。
以太坊的智能合約多次出現漏洞,業界普遍認為與智能合約太過靈活有關,即以太坊想把智能合約做成圖靈完備。此前在我採訪ArcBlock CEO 冒志鴻的時候,他總結,以太坊智能合約漏洞,一是因為太過靈活了;二是由於虛擬機和語言是新做的,不太成熟。 “前段時間發出溢出的問題(美圖幣的問題,都是整數溢出導致的),本來應該在語言層面就解決。”
基於以太坊存在的這兩個問題,致力於“做更好的以太坊”或者“垂直版的以太坊”的項目,會在原來的基礎上改進,或發明自身的智能合約語言,我報導過的有以分片落地為特色的公鏈Zilliqa,還有電商公鏈CyberMiles。
CyberMiles 的虛擬機(CVM)及高級編程語言Lity 是在最近發布的,我藉此機會向他們首席科學家Michael Yuan 請教了一些關於虛擬機的基礎知識,並將我們的對話整理了出來。
記憶中,我最初接觸到虛擬機是在學校網絡中心做網管(此處省略一萬字關於文科生在網絡中心被碾壓的悲慘故事),因為權限比較高,會在學校數據中心有個虛擬機上的賬號;後來是我在財新實習時,一位同事為了在Mac 系統上裝萬得而裝了一個Win 虛擬機;然後是在我報導阿里雲和Docker 合作時二級標題
二級標題
什麼是虛擬機?
虛擬機顧名思義是相對於物理機而言,比如你們明明在用同一台電腦,我讓你們覺得自己分別有一台電腦;你明明在用很多台電腦,讓你覺得自己在用一台電腦。定義這種東西當然問度娘很容易找到,當往往似懂非懂——虛擬指通過軟件模擬的具有完整硬件系統功能的、運行在一個完全環境中的完整計算機系統。但是操作系統之上的虛擬機似乎就不是那麼回事了。
小明:
小明:虛擬機的作用究竟是什麼?最早什麼時候出現?
Michael:“最開始大型計算機是很多用戶共用的,就是你用十秒,我用十秒,你覺得這台機器一直都是你的,我覺得它一直都是我的,但我其實不停地在等它十秒。在計算機從你切換到我的時候,必須重新把你剛剛計算的那些東西,全部給restore 回來給你看,然後十秒鐘之後,把你的去掉,把我的東西全部露出來給我看。”
“我們用的是同一台硬件,但上面有不同的虛擬機,每個人覺得這個硬件是自己的,但其實是用軟件方法實現的,就是在大型機上實現虛擬機的做法。後來個人虛擬機的作用就小了,就沒有必要去用。直到1997 年Java 出現的時候,虛擬機又變的特別重要。因為那個時候有Windows、Unix各種各樣的操作系統。Java 是第一個說我用虛擬機把這些全部統一起來,你們就不用專門在Windows寫一個,在Unix寫一個了,你們就用Java 寫,我上面有虛擬機。”
“虛擬機就是一個抽象化的作用,我虛擬機有自己的語言,然後你可以在虛擬機裡面寫東西,但是虛擬機下面可以有不同的硬件、不同的軟件,甚至同一個硬件我怎麼分成不同的時間片。虛擬機為什麼叫做虛擬機?就是他把下面的東西給抽象掉了,你不需要管你的下面是什麼。”
最早的虛擬機大概是1965 年前後,IBM 的發明:一個單一的計算機系統可以通過IBM 模型來模擬多個裝有不同操作系統的計算機。這使得用戶可以在一個計算機上創建和管理多個不同的虛擬機拷貝。 IBM 模型的一個主要特徵就是通過分割計算機資源和完全隔離程序來使程序共享同樣的硬件。 (copy 自《虛擬機總結》)
到上世紀90 年代時,Java 程序語言開始流行,這打開了虛擬機應用的重頭戲。因為當時網絡跨越了不同的操作系統,不同的瀏覽器,不同的設備,要想運行同一個應用程序是何等困難,Java 正好滿足這種需求(Java 虛擬機的最主要特徵就是程序只要書寫一次就可依托JAVA 虛擬機在多個平台上執行),就順應時代需要流行起來了,當時宣傳的口號是“一處編譯,到處運行”。 (copy 自《虛擬機歷史》)
二級標題二級標題》)
為什麼區塊鏈需要虛擬機?
理解了虛擬機“統一”的作用之後,原來的認知告訴我,虛擬機的性能肯定比不過你直接調用物理機,當中會有些損耗,按理來說層級越多損耗越大。為什麼區塊鍊為什麼需要給自己增加一層虛擬機,它需要統一什麼?
簡單來說就是:區塊鏈有共識機制,所以要求所有人的計算結果是一樣的,但是傳統的虛擬機不支持這樣,後者可能會因為底層硬件的不同輸出不同的結果,所以V 神要再寫一個。小明:一致性。”
小明:區塊鏈上的跟我們傳統接觸的虛擬機有什麼不同?為什麼需要虛擬機?
Michael :Mainframe 大型機的虛擬機是在操作系統下面的,Java 虛擬機在操作系統上面,所以就是不同的虛擬機。區塊鏈的虛擬機到底統一了什麼?區塊鏈的虛擬機統一了不同的節點,每個節點都是不一樣的。
底層語言用比如C++構起來,虛擬機要么就是Vyper 或Solidity ,要么就是虛擬機有自己的語言。第一代區塊鍊是沒有虛擬機的,比特幣是沒有虛擬機的。比特幣就是交易,把錢從A打到B,但是以太坊的天才想法是,我為什麼交易一定是要把錢從A打到B呢?為什麼我不能讓A 到B 這個過程是一段代碼?但是要執行這段代碼,需要在上面有一個執行代碼的層面,這個層面就是虛擬機。
這時候,區塊鏈的作用也從打錢不會出錯變成執行代碼不會出錯,這需要所有的節點執行同一代碼都是同樣的結果。
所有的節點在這個執行的代碼上有同樣的結果,這個要求很高。因為在傳統的虛擬機,比如Java虛擬機裡面,是達不到這一點的。因為有些機器是64位的,有些機器是32位的,10 的負十次方,在A 機上表示和B機上表示是不一樣的,這樣計算的話,各個節點不容易發生共識,所以他必須要寫自己的虛擬機。因此,Vitalik就寫了第一版以太的虛擬機。
小明:
小明:那以太坊虛擬機改變什麼?它做到了這個有什麼壞處嗎?
Michael:他犧牲了性能,Java 虛擬機性能後來大幅提高,是因為所謂Just-in-time (JIT,即時編譯),虛擬機會根據現在的這段代碼來預測下一段代碼是什麼。 Java虛擬機是非常非常聰明的,因為在裡面花了大量的錢,搞了大量的優化。以太坊虛擬機首先從來沒有乾過這個事,因為在2016 年以前沒有人花任何錢去幹這事,大家都認為這是個小孩做的事情,這是其一。
其二,優化過程也很複雜, Java 虛擬機裡面可以容忍不同的虛擬機裡面出來的結果有少量的差別,這個是可以的。但是在區塊鏈裡不行,區塊鏈裡所有的結果都必須一樣。
二級標題
二級標題
為什麼有的鏈需要發明一套新語言?
正如我開篇所言,有的項目會開發新的虛擬機,往往也會伴隨著新的虛擬機語言。這說的是什麼意思?
離題一會,講一下虛擬機、虛擬機語言(高級語言)和編譯器的關係。
至於
至於
至於編譯器的常見作用,有點像把人能看懂的語言,翻譯成計算機能懂的語言。
計算機語言有三種,機器語言、彙編語言、高級語言(推薦閱讀《深入理解計算機系統(3.1)------彙編語言和機器語言》)。只有第一種是計算機能直接識別和執行的,它用二進制代碼表示,對人來說很難記。於是有了彙編語言,把一些指令抽像出來方便人記憶和理解。
不過,這兩種都是直接面對硬件/處理器的,都跟處理器種類有綁定。高級語言則不然,比如Java、C、C++、C#、python等等,是高度封裝的編程語言,更易學也意味著更不靈活。用其所編寫的軟件源代碼也能被編譯器翻譯為不同處理器的語言。
可見,“低級語言”可能更“高級”,因為靈活(越低級的語言實現的效果越強大),更難掌握,懂的人也更少。
回到正題,要開發新語言,其實就是要做新的虛擬機,做以太坊虛擬機沒做的事。
CyberMiles 主要是針對垂直場景做優化。 CyberMiles 的虛擬機(CVM)是基於以太坊的虛擬機改的,所以兼容以太坊虛擬機語言Solidity,同時支持一些以太坊虛擬機所不支持的功能。這意味著如果你本來就懂Solidity,你可以用Solidity 寫,但是如果你想用到CVM 的一些功能,這部分你就可以用Lity 寫,CVM 兩者都能“看得懂”。
Michael :Lity 和CVM,對於CyberMiles 最重要的一點就是,讓我們做以太坊不能做的事。其實我們是以太坊社區裡面的。我們不認為我們跟以太坊是一種競爭關係,我們跟他們是不同的哲學。他們在追求另外一個目標,他們在追求世界計算機的目標,我們不是。我們承認90%的事我們幹不了,我們就把10%的事乾了,所以我們Lity 和CVM,是把以太坊的一個圖靈完備的系統,針對特定場景優化。
二級標題
二級標題
CyberMiles 基於EVM 做了哪些優化?
那麼,CyberMiles 的虛擬機CVM,跟EVM 相比優化在哪?通過CyberMiles 做的一些優化,也可以幫助我們理解以太坊的特性。
第一,可動態擴展,CyberMiles 所開發的語言可以針對不同的業務場景做優化,提高性能。
據CyberMiles 官方介紹:“Lity的靈活性源自其添加新的語言OTA架構。這個版本中,LibENI函數是亮點。通過CyberMiles 虛擬機中新的OPCODE,使用者現在可以在Lity 語言中添加更多功能。這種擴展可以在不停止或者升級區塊鏈軟件的情況下,通過超級節點共識,動態部署到CyberMiles 區塊鏈上。”
給看不懂的官方介紹加點註釋(詳細可看最後參考文章):
OTA 是Over the air,就是在虛擬機不重啟的情況下,動態地升級系統本身的軟件。手機的無線升級系統也用到的類似的技術。
OPCODE 即operation code,操作碼,是一堆機器語言的指令集,簡單來說就是指令序列號,用來告訴CPU需要執行哪一條指令。 CVM 在EVM 裡加了後者沒有的OPCODE 以實現自己的功能。
Michael :在一邊運營的情況下,我可以一邊往裡加些新的功能和特性,這是很重要的一點。比如我有個新的加密算法,在以太坊的實現非常非常貴,我就用C++ 能夠把它加進去,在我機器不下檔的情況下,我可以往裡面加東西。
作為電商公鏈,我們開發出來的虛擬機,或者我們開發出來的語言是能擴展的。其他人要做一個外賣公鍊或金融公鏈,完全可以用,這也是我們做開源共享的原因。
第二,在Lity 編譯器和CVM 上安裝代碼檢查模式。簡單來說,對已知的以太坊Solidity智能合約引起的安全問題,CyberMiles 團隊進行了分類並提取了常見模式。通過編譯器和虛擬機優化,Lity 可以主動防止Solidity 中常見的安全問題,如整數溢出和通證被意外轉到不受支持的合約地址。
Michael :我們有一個building feature,比如剛剛講了BEC 的安全漏洞,就是忘了加safemath,所以就會有整數溢出的問題,後來掉了幾億美金。 BEC 的合約可以在CyberMiles compile,可以在我們虛擬機上運行。但用同樣的問題不會發生在我們虛擬機上,因為我們虛擬機在runtime 的時候會查整數是不是被溢出,會報錯。我覺得這個就顯示了EVM 的成熟。這種東西在Java 裡面都出現過,1997年Java 開始,Java 裡面也沒有check,後來就加進去。
第三,基於時鐘的長期智能合約。 Lity就可以執行一些發生在未來的事情。
Michael :以太裡面還有一個大問題:以太的合約是不能自己啟動的。你不能設計一個鬧鐘讓合約在未來某天啟動。但在電商裡面經常有這事,比如匯款和發貨。在以太乾不了這件事,在以太坊專門有一個東西叫以太坊鬧鐘,這是一個線下的機構,專門收錢,幫你到了某個時間,來實施以太坊的合約。我們把它做進虛擬機了。
這個東西聽起來是很小的事。你去看Java的發展歷史,這些事情都發生過,就是因為你在企業應用中,要是沒有這個功能,你做不到分期付款。
二級標題
二級標題
這些“優化”有什麼代價?
跟Michael 聊完,其實會發現,很多CVM 針對垂直行業的優化,以太坊真的是“非不能也,是不為也”。如果一條通用計算公鏈,要實現這些功能可能會犧牲一些東西,最直接的就是治理機制。 CVM 之所以能實現高性能,需要一定程度上與底層操作系統做溝通,但是以太坊不可能要求加入網絡的節點都用特定的系統,可是用DPOS 的CyberMiles 可以;虛擬機層面實現的模塊化、可擴展,也需要基於DPOS 超級節點全體同意
換言之,CyberMiles 的語言跟跟他採用DPOS 的共識機制分不開,這是以太坊不願意採用的。
小明:
小明:我們這次的幾個特性,LibENI函數,還有剛剛提到的代碼檢查,我感覺這個好像主要是在虛擬機本身上面,因為語言本身無法決定我是否被檢查?
Michael :語言包括語言的語法和它的編譯器,檢查的東西放在編譯器裡面,這個是語言系統的一部分。但是LibENI 必須要在語言領域實現。小明:
小明:那回到我一開始最初問的問題,我感覺虛擬機所在的層級越高,損耗其實越大。
小明:
小明:所以我們虛擬機也是一樣的?
小明:
小明:這樣如果我們底層操作系統不一樣,或者低層的硬件也不一樣,不會導致你剛剛說的不一致嗎?
小明:
小明:可以總結一下LibENI 嗎?
小明:
小明:所以我們有些東西很快,是LibENI 決定的?
Michael :就是LibENI往裡加東西。小明:
小明:既然這是一個調用底層C++ 語言的接口,為什麼那個函數不能讓所有的東西都調用它呢?
小明:
小明:能舉一個普通人能感知到的例子?不能通過函數完成的。
小明:
小明:所以函數很多時候是單一的東西。
Michael :單一的東西,就是給個輸入,給個輸出。
小明:
小明:CyberMiles 強調是面向電商場景定制的,但又強調擴展性比較強,我有一點不是很理解這裡。
Michael:因為可擴展性比較強,所以CyberMiles 的鏈使用跟CVM 裡面加的功能全是跟電商有關的。但是,我可以用LibENI 跟CVM 造另外一個公鏈出來,那個公鏈可以是外賣的、打車的,或者是發證券代幣的。在技術上我們提供這個,可以按照你自己的需求去擴展CVM。
小明:
小明:你提到我們的語言擴展性強,那什麼樣的語言擴展性不強呢?或者定義一個語言強或不強的標準是什麼?
Michael :EVM和Solidity就是沒有擴展性的,就是你不能改,你需要改的話,你是要把整個軟件系統都更新。 EVM軟件大概一年要更新一次。你在EVM上更改東西的話,你基本上必須要自己認識Vitalik,所有的核心開發他都會參與。
小明:
小明:這是你剛剛提到的,我們有很多功能可以讓開發者自己提,讓節點去接受。
小明:
小明:所以其實我們擴展性強,並不是由語言決定,而是由我們治理機制決定的?
Michael :我們語言跟虛擬機和治理機制是一起工作的,不可分割的。因為我們這個語言裡面可以去加這種關鍵詞,我有個模塊化的方法,可以把這個關鍵詞的功能直接加到虛擬機裡來,這在現在來講以太坊都做不到,因為不支持。
小明:
小明:很多人批評現在以太坊智能合約本身有很多漏洞,包括整數溢出這些,都是因為虛擬機本身設計可能沒有做好?
Michael :我覺得是這樣,寫虛擬機或者寫語言的人,會說是寫智能合約的人的問題,你們程序員太差,所以有這個問題。如果所有人都犯一樣的錯誤,那就說明你這個東西設計的不行,所以你就要想辦法去改設計。之前我們在Java的時候,也遇到這種問題。這個Bug出現是不是因為程序員的問題呢?是因為程序員的問題,也是因為你的語言沒有防止這個問題,所以一直以為有這個問題。
這就是工程解法跟科學解法的區別,或者叫學院派思維跟工程思維的區別。
我以前在大學很清楚,學院派思維會說,我們設計出來東西是圖靈完備的、數學可以證明的。比如說整數溢出這件事,你憑什麼說它是個bug?因為我的語言裡面允許這樣寫。程序員把它寫成這樣,就是證明他想幹這個事。但是,在現實生活中,99.99%的情況下,程序員不是要幹這件事,而是把它寫錯了。
小明:
小明:以前Java 的虛擬機是允許這個事情的?
小明:
小明:靈活的“壞處”。既然虛擬機又是在操作系統之上的,那就意味著操作過程中,其實操作系統可能也有虛擬機,下層不能知道發生這件事嗎?不能阻止嗎?
小明:
小明:參考文章:
參考文章:
我是Odaily編輯盧曉明,探索真實區塊鏈,爆料、交流請加微信lohiuming,煩請備註姓名、單位、職務和事由。
參考文章:
虛擬機概論(九)——虛擬機總結:簡單介紹了當今正在使用的四種虛擬機概念模型
虛擬機概論(四)——虛擬機的歷史:虛擬機重大歷史事件附錄
虛擬機的歷史:簡單的虛擬機歷史