智能合約是指可以自動執行合約條款的計算機程序,它的概念最先是由密碼學家尼克薩博於 1994 年提出的,幾乎與互聯網同齡。因爲缺乏可信的執行環境,智能合約並無被普遍應用。html
2008 年一位自稱 Satoshi Nakamoto 的人發佈了比特幣,並提出了區塊鏈的概念。在比特幣系統中,Nakamoto 使用了一套腳本系統來幫助用戶更加靈活地控制本身的帳戶和轉帳流程,這套腳本系統成爲了基於區塊鏈的智能合約系統的雛形。算法
2014 年一位叫作 Vitalik Buterin 的少年發佈了以太坊,它提供了一套基於區塊鏈的、圖靈完備的智能合約系統,使用這套系統能夠建立各類基於區塊鏈的分佈式應用。跨域
NEO 是一個基於區塊鏈的數字資產及應用平臺,它提供了一套全新的智能合約系統 NeoContract,並在系統底層提供了數字資產 NeoAsset 與數字身份 NeoID 等功能,使得人們能夠很是方便地開展資產數字化業務,而不只僅是在區塊鏈上建立原生代幣。數組
本文將詳細介紹 NeoContract 的特色與非技術細節。技術細節請參考技術文檔:Docs.neo.org。緩存
若是一個程序在不一樣的計算機、或者在同一臺計算機上的不一樣時刻屢次運行,對於相同的輸入可以保證產生相同的輸出,則稱該程序的行爲是肯定性的,反之則稱該程序的行爲是非肯定性的。安全
區塊鏈是一個經過多方存儲、多方計算的方式來實現數據不可篡改、計算結果可信的分佈式系統,智能合約會在區塊鏈網絡的多個節點中運行。若是一個智能合約是非肯定性的,那麼不一樣節點運行的結果就可能不一致,從而致使共識沒法達成,網絡陷入停滯。所以,在設計智能合約系統的時候,須要排除一切可能致使非肯定性的因素。服務器
獲取系統時間是一個很經常使用的系統函數,可能會被大量應用在一些具備時效性合約程序中。可是獲取時間是一個非肯定性的系統函數,不一樣的節點調用返回的結果也會不一致,在分佈式系統中很難得到統一的精確時間。所以,NeoContract 只提供了基於區塊時間戳的系統調用,能夠將整個區塊鏈當作一個時間戳服務器,並取得任意一個區塊被構造時的時間戳。因爲 NEO 平均每 15 秒產出一個區塊,那麼合約運行時的時間大約等於最新的區塊時間加上 15 秒左右。網絡
不少智能合約程序會用到隨機數的功能,好比對賭合約和一些小遊戲等,可是隨機函數是一個典型的非肯定性函數,每次調用都會獲得不一樣的結果。在分佈式系統中,解決這個問題的辦法有不少:可讓全體節點採用相同的隨機種子,這樣整個隨機函數的返回序列都是肯定性的,可是這種方法會提早暴露整個隨機結果,使得這種隨機數的實用價值大大下降;另外一種方法是讓全體節點進行通訊以協做的方式來生成隨機數,它能夠採用一些密碼學技巧來產生公平的隨機數,但缺點是性能很是差,須要額外的通訊開銷;還有一種方法是引入一箇中心化的隨機數提供者,由它來提供隨機數並保證一致性,可是這種方法的缺點是顯而易見的,用戶必須無條件地信任這個提供者。數據結構
運行在 NEO 上的智能合約有兩種方式來獲取隨機數:第一是每一個區塊在被構造時,共識節點都會對一個隨機數達成共識並填充到區塊的 Nonce 字段中,合約程序能夠讀取到任意區塊的 Nonce 字段;第二是合約程序能夠利用區塊的散列值做爲隨機數的生成手段,因爲區塊的散列值具備必定的隨機性,這種方式能夠獲得一個較弱的隨機數。併發
若是一個程序在運行時獲取數據,而數據源提供的是非肯定性的數據,那麼該程序也可能會變成非肯定性的程序。例如,經過搜索引擎來獲取某個關鍵詞的前 10 條搜索結果——搜索引擎針對不一樣的 IP 地址來源可能會返回不一樣的排序結果。
NEO 向智能合約提供了兩種肯定性的數據源:
區塊鏈帳本
合約程序能夠經過互操做服務來訪問到整個區塊鏈上的全部數據,包括完整的區塊和交易,以及它們的每個字段。區塊上的數據都具備肯定性和一致性,因此能夠安全地被智能合約訪問。
合約存儲空間
部署在 NEO 上的每個合約都有一個僅可由該合約自己來存取的私有存儲區,NEO 的共識機制確保了每個節點上的存儲狀態都是一致的。
對於須要訪問鏈外數據的狀況,NEO 沒有提供直接的方式,須要經過交易來將鏈外數據發送到鏈內,從而轉化成以上兩種類型的數據源,才能被智能合約所訪問。
NeoContract 的智能合約具備相互調用的能力,但不能遞歸調用。遞歸能夠在合約內部實現,但不能跨越當前合約的邊界。此外合約之間的調用關係必須是靜態的:即沒法在運行時指定調用的目標。這樣作使得程序的行爲在運行前就能夠被徹底肯定,其調用關係也可在運行前徹底肯定,以此爲依據能夠對多個合約進行動態分區,從而實現並行化執行的能力。
智能合約的執行環境會對合約的性能起到很是重要的做用。當咱們分析執行環境的性能時,有兩個指標是很是關鍵的:第一是指令的執行速度,第二是執行環境自己的啓動速度。對於智能合約而言,執行環境的啓動速度每每要比指令的執行速度更爲重要。智能合約中較可能是一些甚少涉及 IO 操做的邏輯判斷指令,這些指令的執行速度很容易獲得優化。而智能合約每次被調用,都必須啓動一個新的虛擬機 / 容器。所以執行環境自己的啓動速度(啓動一個虛擬機 / 容器)對智能合約系統的性能影響更大。
NEO 採用了輕量級的 NeoVM(NEO Virtual Machine)做爲其智能合約的執行環境,它的啓動速度很是快,佔用資源也很小,適合像智能合約這樣短小的程序。經過 JIT(即時編譯器)技術對熱點智能合約進行靜態編譯和緩存能夠顯著提高虛擬機的執行效率。
當談及一個系統的擴展性時,會涉及到兩個方面:垂直擴展和水平擴展。垂直擴展是指對處理流程進行優化使得系統可以充分利用現有設備的能力,這種方式很容易就會碰上天花板,一個串行系統的處理能力取決於單臺設備的硬件極限。當咱們須要對系統進行擴展時,若是有辦法將串行系統改形成並行系統,那麼理論上咱們只須要增長設備的數量,就能夠得到近乎無限的擴展性,這種方式就是橫向擴展。咱們在考慮對區塊鏈系統進行擴展時,是否有無限擴展的可能?換言之,區塊鏈可否並行地對業務進行處理?
區塊鏈是一個分佈式的大帳本,裏面記錄了各式各樣的狀態數據,同時也記錄了這些狀態如何變化的規則,智能合約正是用來記錄這些規則的載體。區塊鏈可否並行地對業務進行處理,就取決於多個智能合約可否併發執行——即合約的執行是不是順序無關的。從根本上來講,若是合約之間不會相互影響,或者說若是合約不會同時對相同的狀態數據進行修改,那麼它們的執行就是順序無關的,能夠併發執行,不然就只能串行執行,沒法橫向擴展。
基於上面的分析,咱們能夠很容易設計出一個具有「無限擴展」能力的智能合約系統。只須要簡單地規定:
一個智能合約只能修改屬於該合約本身的狀態記錄;
同一個事務批次(區塊)中,一個合約只能被運行一次;
這樣一來,全部的智能合約之間都是順序無關能夠平行處理了。可是,若是「一個智能合約只能修改屬於該合約本身的狀態記錄」,就意味着合約間沒法相互調用,每一個合約都是一個孤島;若是「一個區塊中,一個合約只能被運行一次」,就意味着用智能合約發行的某種數字資產在一個區塊裏只能處理一筆交易。這顯然和「智能」二字的設計初衷截然不同。畢竟合約間的相互調用,同一區塊中屢次調用同一個合約,都是咱們想要的設計目標。
好在,NEO 的智能合約之間的調用關係是靜態的,沒法在運行時指定調用的目標。這樣作使得程序的行爲在運行前就能夠被徹底肯定,其調用關係也可在運行前徹底肯定。咱們要求每個合約都顯式地申明自身可能會調用哪些合約,從而使運行環境可以在運行合約程序以前,先計算出完整的調用樹,並根據這個調用樹來對合約的執行進行分區,讓可能會對相同狀態記錄進行修改的合約在同一個分區中串行執行,而分區與分區之間能夠併發執行。
耦合是指兩個或兩個以上的實體相互依賴於對方的一個量度。NeoContract 的系統採用低耦合的設計,合約程序在 NeoVM 中執行,並經過互操做服務層與外部通訊。所以,對智能合約功能的絕大部分升級,均可以經過增長互操做服務的 API 來實現。
與比特幣的公鑰帳戶體系不一樣,NEO 的帳戶系統採用了合約帳戶體系。NEO 中的每個帳戶都會對應一個驗證合約,驗證合約的散列值即爲帳戶地址;而驗證合約的程序邏輯則控制着該帳戶的全部權。當從一個帳戶中轉帳時,須要執行該帳戶所對應的驗證合約。驗證合約能夠接受一組參數(一般是數字簽名或者其它判斷條件),並在驗證後返回一個布爾值,用於向系統代表本次驗證是否成功。
用戶能夠事先將驗證合約部署到鏈上,也能夠在轉帳的過程當中直接在交易中公佈合約內容。
應用合約經過一種特殊的交易來觸發,且能夠在運行時訪問和修改系統的全局狀態及合約的私有狀態(存儲區)。例如,能夠在合約中建立全局數字資產、投票、保存數據等,甚至在合約運行時動態建立一個新的合約。
應用合約的執行須要按指令進行計費,當交易中的手續費被所有消耗完以後,合約將會失敗並中止執行,同時回滾全部的狀態變化。合約執行的成功與否,不影響其所在交易的有效性。
函數合約用於提供一些公共或者經常使用的功能,以供其它合約來調用。它使得智能合約的代碼能夠被重用,從而使開發者能夠編寫出更復雜的業務邏輯。每個函數合約在被部署的時候,能夠選擇是否擁有一個私有的存儲區,該存儲區可在往後被受權的合約讀取或者寫入數據,從而實現狀態持久化的功能。
函數合約必須事先部署到鏈上才能被調用,並經過「自毀」的系統函數來從鏈上刪除,刪除後將沒法再被使用,且它的私有存儲區也會被銷燬。能夠經過合約遷移的方式,將舊合約的數據在銷燬以前自動遷移到子合約中。
NeoVM 提供了虛擬硬件層來對智能合約的執行提供支持,它們包括:
CPU
CPU 負責讀取並按順序執行合約中的指令,根據指令的功能進行流程控制、算數運算、邏輯運算等。將來能夠對 CPU 的功能進行擴展,引入 JIT(即時編譯器)的功能,從而提升指令的執行效率。
調用棧
調用棧用於保存每一次函數調用時程序執行的上下文信息,以便在函數執行完畢並返回後,可以繼續在當前的上下文中執行。
計算棧
NeoVM 中全部的運行時數據都存放在計算棧中,當執行不一樣的指令時,會對計算棧中的數據元素進行相應的操做。例如執行加法指令時,會將參與相加的兩個操做數從計算棧中彈出,並將相加後的運算結果壓入棧頂。函數調用的參數也必須按從右到左的順序壓入計算棧,函數執行完畢後能夠從棧頂取回函數返回值。
備用棧
當須要對計算棧中的元素進行調度或從新排列時,能夠臨時將計算棧中的元素存入備用棧,並在未來取回。
NeoVM 提供了一套簡單而實用的指令集,用於構造智能合約程序。按功能劃分,主要包含如下幾類:
常數指令
流程控制指令
棧操做指令
字符串指令
邏輯運算指令
算數運算指令
密碼學指令
數據操做指令
值得注意的是,NeoVM 的指令集中內建提供了一系列的密碼學指令,如 ECDSA、SHA 等算法,以優化智能合約中用到密碼學算法時的執行效率。此外,數據操做指令直接對數組及複雜數據結構提供支持。
智能合約運行所在的虛擬機是一個沙箱環境,當合約須要訪問沙箱外的數據或者將運行時數據持久化保存時,就須要用到互操做服務層,它爲虛擬機中運行的智能合約提供了對外溝通的媒介。NeoContract 在互操做服務層中,向智能合約程序公開了一系列的系統函數和服務,合約能夠像調用普通函數同樣訪問它們,全部系統函數都是可併發的,因此無需擔憂擴展性問題。
一般,智能合約的開發過程是很是困難的,由於沒有良好的調試和測試方法。NeoVM 在虛擬機層面提供了程序調試功能的支持,能夠對合約代碼設置斷點,還能夠單步、單過程執行等。得益於虛擬機與區塊鏈之間的低耦合設計,能夠很方便地將 NeoVM 與各類 IDE 直接集成,從而提供一個與最終生產環境一致的測試環境。
開發者能夠直接使用幾乎任何他們擅長的高級語言來進行 NeoContract 的開發工做。第一批被支持的語言是 C#、VB.Net、F# 等,咱們提供了這些語言的編譯器和插件,用於將高級語言編譯成 NeoVM 所支持的指令集。因爲編譯器會針對 MSIL(微軟中間語言)來進行編譯,因此理論上任何 .Net 中的語言或者可被轉譯成 MSIL 的語言均可以直接被直接支持。
這些語言的開發者人數衆多,且具備很是強大的集成開發環境,開發者能夠在 Visual Studio 中進行代碼的編寫、生成、測試、調試等一系列的開發工做,同時還能夠利用咱們提供的智能合約開發模板來進行快速入門。
Java、Kotlin 等語言是第二批被支持的語言,咱們提供這些語言的編譯器和 IDE 插件,來幫助開發者使用基於 JVM 的語言來開發 NEO 的智能合約應用。
Java 的使用很是普遍,而 Kotlin 最近也成爲了 Google 官方推薦的 Android 開發語言,相信它們能爲 NEO 帶來大量的智能合約開發者。
後續,NeoContract 將依據難易程度來分批次開發各類其它高級語言的編譯器,可能會有這些語言:
C, C++, GO
Python, JavaScript
將來會陸陸續續增長新的高級語言支持,使得 90% 的開發者無需學習新的語言便可參與到 NeoContract 的開發中來,甚至可將現有業務系統中的代碼直接移植到區塊鏈上。
NEO 的智能合約能夠在運行時經過互操做服務提供的系統函數,獲取 NEO 區塊鏈的完整帳本數據,包括完整的區塊和交易,以及它們的每個字段。具體能夠查詢到這些數據:
區塊鏈的高度;
區塊頭、區塊;
交易;
交易的類型、屬性、輸入、輸出等;
透過這些數據,能夠開發出一些有意思的應用,好比自動權益分成、基於智能合約的工做量證實等。
經過互操做服務提供的數字資產接口,智能合約不但能夠查詢到 NEO 區塊鏈上各類數字資產的屬性和統計信息,還能夠在運行時建立新的數字資產。由智能合約所建立的數字資產,能夠在合約外部進行發行、轉帳、交易等操做,它們與 NEO 上的原生資產同樣,能夠用任何與 NEO 兼容的錢包軟件來管理。具體的接口主要有這些:
資產屬性查詢;
資產統計數據查詢;
資產生命週期管理:建立、修改、銷燬等;
資產管理:多國語言的名稱、總量變動、精度變動、管理員變動等;
每個被部署到 NEO 區塊鏈上的智能合約程序,都會擁有一個只有該合約自己能夠讀寫的私有存儲區。智能合約對本身存儲區中的數據擁有徹底的操做權限:能夠讀取、寫入、修改、刪除。數據以鍵值對的形式來存放,並提供這些接口:
遍歷存儲區中的全部記錄;
根據指定鍵返回特定記錄;
根據指定鍵來修改或寫入新的記錄;
根據指定鍵來刪除記錄;
通常,合約只能對本身存儲區中的數據進行讀寫,但有一個例外:當發生合約相互調用的時候,被調用合約能夠經過跨域請求來訪問調用者的存儲區,前提是調用者向其提供了受權。此外,對於在合約運行時動態建立的子合約,父合約會即時得到其存儲區的讀寫權限。
跨域請求使得 NeoContract 能夠實現更加豐富的庫功能,這些庫能夠爲調用者提供高度封裝的數據管理能力。
NEO 的分佈式結構提供了高冗餘的存儲能力,對這種能力的使用不是無償的。在 NEO 上部署智能合約須要支付一筆費用,這筆費用目前固定爲 500GAS,由系統收取併成爲系統收益。將來可能會根據系統運行的實際狀況來調整價格。部署在區塊鏈上的智能合約能夠被屢次使用,直到該合約被部署者銷燬。
NEO 爲智能合約提供了一個可信的執行環境,而合約的執行也須要消耗各個節點的計算資源,所以用戶須要爲智能合約的執行支付費用。費用的數量由每一次執行所消耗的計算資源決定,計價單位也是 GAS。若是執行過程當中因爲費用不足致使智能合約執行失敗的,已被消耗的費用不會退回,這能夠防止惡意攻擊對全網算力的消耗。
對於大多數簡單的合約,它們均可以在 10GAS 的免費額度內順利執行完畢,從而大大下降了用戶的使用成本。
區塊鏈上的數字資產天生具備流動性的需求,一般點對點的交易沒法提供足夠高的流動性,所以須要由交易所來爲用戶提供交易服務。數字資產的交易所通常會分爲兩類:第一類是中心化交易所,用戶須要將數字資產充值到交易所,而後在網站上掛單進行撮合交易;第二類是去中心化交易所,它的交易系統內置在區塊鏈系統中,由系統提供撮合服務。
中心化交易所可以提供很是高的性能和多樣化的服務,但須要有較強的信用保證,不然將會出現道德風險,好比挪用用戶資金、跑路等。相對的,去中心化交易所雖然沒有道德風險,可是用戶體驗較差,性能上也有較大的瓶頸。有沒有辦法將二者的優勢結合起來,提供一個一箭雙鵰的方法?
超導交易就能夠作到這一點,它是這樣一種機制:用戶無需充值,就能夠直接使用本身在區塊鏈上的資產來進行交易,交易的結算在鏈上完成,但撮合的過程在鏈外進行,由一箇中心化的交易所來提供撮合服務。因爲撮合在鏈外,它的效率能夠像中心化交易所同樣高,但資產還在用戶的控制之下,交易所能夠根據用戶的交易意願來進行撮合服務,卻沒法挪用資金或者跑路,沒有道德風險。
目前,NEO 社區中已經出現一些利用智能合約來實現區塊鏈超導交易的項目,例如藍鯨淘。
基於區塊鏈的智能基金具備去中心化、公開透明、隨時加入和退出等特色,相比傳統的基金模式,具備更高的安全性和自由度,還可以跨越國界,接受全世界投資者的資金,以及投資全世界的優秀項目。
Nest 是一個基於 NeoContract 的智能基金項目,它和基於以太坊的 TheDAO 項目很是類似,但試圖經過一些方法來提升安全性,避免重蹈 TheDAO 的覆轍(被黑客攻破)。
能夠預見,在將來較長的一段時間內,世界上將會有若干公有鏈以及成千上萬的聯盟鏈和私有鏈共存。這些獨立的區塊鏈系統都是價值與信息的孤島,彼此之間沒法互聯互通。經過跨鏈互操做機制,能夠將無數個孤立的區塊鏈鏈接起來,使得不一樣的區塊鏈上的價值能夠相互交換,造成真正的價值互聯網。
NeoContract 爲跨鏈互操做的實現提供支持,不但能夠實現跨鏈資產交換,還能夠運行跨鏈分佈式事務,在不一樣區塊鏈上運行智能合約,並保證它們的一致性。
一部預言機能夠視爲是與一個預言者(oracle)相鏈接的圖靈機。所謂預言者的概念,是一個能夠回答特定問題集合的一個實體。在區塊鏈中,預言機爲智能合約打開了外部世界的大門,使得智能合約能夠將真實世界的信息做爲合約執行的條件。
NeoContract 沒有提供直接訪問外部數據的能力,好比訪問互聯網上的資源等,由於這樣作會引入非肯定性,使得各個節點對合約執行的結果出現不一致。在 NeoContract 中實現預言機,須要由可信的第三方將外部數據經過交易的形式發送到區塊鏈上,使得這些信息成爲帳本數據的一部分,從而消除非肯定性。
前文中提到的可信第三方,能夠是一個由合約締造者雙方共同信任的人或機構,也能夠是一個去中心化的由經濟激勵來保證的數據提供程序,能夠用 NeoContract 來實現這樣一個預言機。
比特幣開創了區塊鏈及電子現金的時代,以太坊則開創了智能合約的時代。以太坊做爲區塊鏈智能合約的先驅,爲智能合約系統的設計思想、經濟模型、技術實現等方面均作出了巨大的貢獻。同時,以太坊平臺上也已經存在了大量的 DAPP(分佈式應用程序),這些 DAPP 的功能各異,有對賭協議、數字資產、電子黃金、遊戲平臺、醫療保險、婚戀平臺,覆蓋各行各業。全部這些 DAPP,理論上均可以很方便地移植到 NeoContract 平臺上,成爲 NEO 的應用。