《精通以太坊》預言機

買賣虛擬貨幣
在本章中,我們將討論預言機(oracle),它是可以為以太坊智慧合約提供外部資料來源的系統。 “oracle”一詞來自希臘神話,代表能夠與神靈交流的人,他們可以看到未來的願景。在區塊鏈的上下文中,預言機是一個可以回答以太坊外部問題的系統。在理想情況下,預言機是無信任的系統,這意味著它們不需要被信任,因為它們是按照去中心化的原則執行的。為什麼需要預言機?以太坊平臺的一個關鍵元件是EVM,它能夠在分散網路中的任何節點上執行程式並更新受共識規則約束的以太坊狀態。為了保持共識,EVM的執行過程必須完全確定,並且僅基於以太坊狀態和簽名交易的共享上下文。這產生了兩個特別重要的後果:一個是EVM和智慧合約沒有內在的隨機性來源;另一個是外部資料只能作為交易的資料載荷引入。讓我們進一步分析這兩個後果。首先我們要理解為什麼在EVM中需要禁止真正的隨機函式,不讓它們為智慧合約提供隨機性。請考慮在執行此類函式後對嘗試達成共識的影響:節點A將執行命令並代表智慧合約儲存3在其儲存中,而節點B執行相同的智慧合約,將儲存7。因此,節點A和節點B就結果狀態應該是什麼將得出不同的結論,儘管在相同的上下文中執行完全相同的程式碼。實際上,每次評估智慧合約時,可能會達到不同的結果狀態。因此,由於其眾多節點在世界各地獨立執行,網路將無法就結果狀態應該是什麼達成去中心化的共識。在實踐中,它會比這個例子複雜得多,因為包括以太幣轉移在內的連鎖效應會以指數方式增長。注意,偽隨機函式,例如加密安全雜湊函式(它們是確定性的,因此實際上也是EVM的一部分),對於許多應用來說是不夠的。假想一個猜硬幣決勝負的遊戲場景,這個遊戲依賴於扔硬幣正反面的隨意性。礦工可以輕易破解這個遊戲:他們只需要打包那些對其有利的隨機結果即可。那麼我們如何解決這個問題呢?既然所有節點都可以就簽名交易的內容達成一致,那麼我們就可以引入外部資訊,包括隨機性、價格資訊、天氣預報等,作為傳送到網路的交易的資料部分。但是,這些資料本身無法信任,因為它的來源無法核實。因此,我們剛剛並沒有完全解決這個問題。我們使用預言機嘗試解決這些問題,在本章的其餘部分將詳細討論這些問題。預言機的應用場景和示例
理想情況下,預言機提供了一種無信任(或至少近乎無信任)的方式來獲取外在的(即“真實世界”或“鏈外”)資訊,例如足球比賽的結果、黃金的價格或真正的隨機數字,用於以太坊平臺上的智慧合約。它們還可用於直接將資料安全地中繼到DApp前端。因此,可以將預言機視為彌合鏈外世界與智慧合約之間差距的機制。允許智慧合約基於真實世界的事件和資料來強制執行合約關係,從而大大擴充套件了它們的範圍。但是,這也會給以太坊的安全模型帶來外部風險。考慮一個“智慧遺囑”合約——當一個人去世時分配資產。這是智慧合約領域中經常討論的內容,並突出了可信任的預言機的風險。如果由這樣的合約控制的繼承金額足夠高,那麼在所有者死亡之前攻擊預言機(發出假的死訊)並觸發資產分配的動機是非常強烈的。請注意,某些預言機提供針對特定私有資料來源的資料,例如學術證書或政府ID。這些資料的來源,如大學或政府部門,是完全可信的,資料的真實性是主觀的(真相只能透過來源的權威來確定)。因此,不能無信地提供這樣的資料,即不信任來源,因為沒有獨立可驗證的客觀事實。因此,我們將這些資料來源包含在我們對預言機的定義中,因為它們還為智慧合約提供了資料橋樑。它們提供的資料通常採用證明的形式,如護照或成就記錄。“證言”將成為未來區塊鏈平臺成功的重要組成部分,特別是在驗證身份或聲譽的相關問題方面,因此探索區塊鏈平臺如何為其提供服務非常重要。可能由預言機提供的更多資料示例包括:· 物理隨機數源或熵源(例如量子現象或熱現象):如在彩票智慧合約中公平地選出獲獎者。· 與自然災害相關的引數觸發器:觸發大型自然災害債券智慧合約(例如地震的里氏震級測量債券)。· 匯率資料:例如讓加密貨幣與法定貨幣精確掛鉤。
· 資本市場資料:例如為一攬子代幣化資產或證券定價。· 指標引用資料:例如將利率納入智慧金融衍生品合約。· 統計與準統計資料:安全標識、國家代號、貨幣代號等。· 時間和間隔資料:基於精準的SI(國際單位制)時間度量的事件觸發器。·天氣資料:例如基於天氣預報的保險費計算器。· 政治事件:預測市場的走勢。·運動事件:預測市場走勢以及體育博彩相關的合約。·地理定位資料:例如供應鏈跟蹤。· 損壞程度核驗:保險合約。
· 其他區塊鏈上發生的事件:可互操作函式。· 以太幣市場價格:例如gas價格預言機。· 航班統計資料:例如用於團體和俱樂部的機票合同。在接下來的部分,我們將研究可以實現預言機的一些方法,包括基本的預言機的設計模式、計算性預言機、去中心化的預言機以及Solidity中的預言機客戶端實現。預言機的設計模式根據定義,所有的預言機都提供了一些關鍵功能。這些能力包括:
從鏈外的資料來源收集資料。使用簽名訊息在鏈上傳輸資料。將資料放入智慧合約的儲存空間,使資料可用。一旦資料在智慧合約的儲存中可用,其他智慧合約就可以透過呼叫預言機智慧合約的“檢索”功能來訪問它;它也可以透過“檢視”預言機的儲存直接由以太坊節點或支援網路的客戶端訪問。設定預言機的三種主要方式可以分為請求與響應、釋出與訂閱和立即讀取。讓我們從最簡單的“立即讀取”式預言機開始,這種預言機提供即時決策所需的資料,例如“ethereumbook.info的地址是什麼”或“這個人是否超過18歲”。那些希望查詢此類資料的人傾向於在“即時”的基礎上這樣做;查詢是在需要資訊時完成的,可能永遠不會再次查詢。這種預言機的例子包括那些持有組織資料或由組織釋出資料(例如學術證書、撥號程式碼、機構會員資格、機場識別符號、自主ID等)的預言機。這種型別的預言機一旦將資料儲存在其合約儲存中,其他智慧合約就可以使用對預言機合約的請求呼叫來查詢。它可能會更新。預言機儲存中的資料也可用於透過區塊鏈啟用(即,以太坊客戶端連線)應用程式直接查詢,而無須透過調整併產生髮布交易的gas成本。想要檢查買酒顧客年齡的商店可以這樣使用預言機。這種型別的預言機對於可能需要執行和維護伺服器來回答此類資料請求的組織或公司具有吸引力。注意:由預言機儲存的資料可能不是預言機正在服務的原始資料,例如,出於效率或隱私原因,大學可能會為過去學生的學業成績證書設立一個預言機。但是,儲存證書的完整詳細資訊(細緻到所修的課程和達到的成績)是多餘的。相反,證書的雜湊就足夠了。同樣,政府可能希望將公民身份證放入以太坊平臺,其中顯然包含的細節需要保密。再次,雜湊資料(更仔細的做法是,在默爾克樹中使用Salt)並且僅將根雜湊儲存在智慧合約的儲存中將是組織這種服務的有效方式。
下一個設定方式是釋出與訂閱,在這種預言機中,要對預期改變的資料(可能是定期和頻繁地)提供有效的廣播服務,預言機要麼由鏈上的智慧合約輪詢,要麼由鏈外守護程序監視和更新。此類別具有類似於RSS摘要或WebSub的模式,其中預言機使用新資訊進行更新,並用標記表示新資料可供“訂閱”的人使用。感興趣的人必須將預言機輪詢到檢查最新資訊是否已更改,或監聽預言機合約的更新並在發生時採取行動。示例包括價格饋送、天氣資訊、經濟或社會統計、交通資料等。在Web伺服器領域,輪詢效率非常低,但在區塊鏈平臺的對等環境中卻不是這樣:以太坊客戶必須跟上所有狀態更改,包括對合約儲存的更改,因此輪詢資料更改是對同步客戶端的本地呼叫。以太坊事件日誌使應用程式特別容易注意預言機更新,因此這種模式在某些方面甚至可以被視為“推送”服務。但是,如果輪詢是透過智慧合約完成的——這對於某些去中心化的應用可能是必要的(例如,在無法啟用激勵的情況下),則可能產生大量的gas支出。“請求/響應”類別是最複雜的:這是資料空間太大而無法儲存在智慧合約中的情況,並且使用者每次只需要整個資料集的一小部分。它也是資料提供商業務的適用模型。實際上,這樣的預言機可以實現為鏈上智慧合約系統,以及用於監視請求和檢索、返回資料的鏈外基礎結構。來自去中心化應用的資料請求通常是涉及許多步驟的非同步過程。在這種模式中,首先,EOA與去中心化應用進行互動,從而與預言機智慧合約中定義的功能進行互動。此函式啟動對預言機的請求,除了可能包含回撥函式和排程引數的補充資訊之外,還使用相關引數詳細說明所請求的資料。一旦驗證了此事務,就可以將預言機請求視為預言機合約發出的EVM事件,或者作為狀態更改;可以檢索引數並用於執行鏈外資料來源的實際查詢。預言機可能還需要付款來處理請求,回撥的gas支付以及訪問所請求資料的許可權。最後,結果資料由預言機所有者簽名,證明在給定時間內的資料有效性,並在事務中傳遞給直接或透過預言機合約發出請求的去中心化應用。根據排程引數,預言機可以定期廣播進一步更新資料的事務(例如,日終定價資訊)。請求與響應預言機的步驟可以總結如下:· 接收來自DApp的查詢。· 解析查詢。· 檢查是否提供了付款和資料訪問許可權。
· 從鏈外資料來源檢索相關資料(並在必要時加密)。· 使用包含的資料對事務進行簽名。· 將事務廣播到網路。· 安排任何進一步必要的交易,例如通知等。一系列其他方案也是可能的,例如,可以從EOA請求資料並直接返回資料,從而無須使用預言機智慧合約。類似地,可以向支援物聯網的硬體感測器發出請求和響應。因此,預言機可以是人、軟體或硬體。此處描述的請求與響應模式常見於客戶端與伺服器體系結構。雖然這是一種有用的訊息傳遞模式,允許應用程式進行雙向對話,但在某些情況下這可能是不合適的。例如,在請求與響應模式下,需要預言機利率的智慧債券可能必須每天請求資料,以確保利率始終是正確的。鑑於利率不經常變化,釋出與訂閱模式可能更合適這種情況,尤其是考慮到以太坊的有限頻寬。
在釋出與訂閱模式中,釋出者(在此上下文中是指預言機)不直接向接收者傳送訊息,而是將釋出的訊息分類到不同的類中。訂閱者能夠表達對一個或多個類的興趣並僅檢索那些感興趣的訊息。在這種模式下,預言機可能會在每次更改時將利率寫入其自己的內部儲存。多個訂閱的DApp可以簡單地從預言機合約中讀取它,從而減少對網路頻寬的影響,同時最大限度地降低儲存成本。在廣播或多播模式中,預言機會將所有訊息釋出到通道,訂閱合約將在各種訂閱模式下收聽通道。例如,預言機可能會將訊息釋出到加密貨幣匯率通道。訂閱智慧合約如果需要時間序列,例如移動平均計算,則可以請求通道的全部內容;另一個可能只需要現貨價格計算最新利率。在預言機不需要知道訂閱合約的身份的情況下,廣播模式是合適的。資料認證即便我們假設被去中心化應用查詢的資料來源是權威的和值得信任的,仍然存在一個突出的問題:鑑於預言機以及“請求/響應”機制可能由多個實體來操作,我們如何才能信任這個機制呢?資料在傳輸過程中被篡改的可能性顯然是存在的,所以,讓鏈外方法可以證明返回資料的完整性是非常關鍵的。兩種常見的資料認證方法是真實性證明(authenticity proof)以及可信執行環境(Trusted Execution Environment,TEE)。真實性證明是用密碼學證據證明資料沒有被篡改過。基於許多證明技術(例如,數字簽名證明),它們將需要的信任從資料傳輸者高效地轉移到證明人(證明方法的提供者)。透過鏈上驗證證據,智慧合約可以在使用資料前驗證資料的完整性。Oraclize(現已加入Chainlink網路)http://www.oraclize.it/就是一個利用多種真實性證明的預言機服務的例子。現在以太坊主網查詢資料時可以使用的其中一種證明方式是TLSNotary Proof。TLSNotary Proof允許客戶端向第三方提交證據,證明客戶端與某伺服器之間發生了HTTPS網路流量。雖然HTTPS自身是安全的,但它並不支援資料簽名。因此,TLSNotaryProof依賴於TLSNotary簽名方案(透過PageSigner)。TLSNotaryProof利用了傳輸層安全協議(Transport Layer Security,TLS),這讓TLS可以掌控金鑰,在獲取資料後給資料簽名,並將資料分配給三方:伺服器(預言機)、受審單位(Oraclize)以及審計方。Oraclize使用亞馬遜網路伺服器(AWS)虛擬機器例項作為審計方,可以驗證自例項化以來它沒有被修改過。這一AWS例項儲存著TLSNotary密文,密文讓它可以提供誠實性證明。雖然這套方案在資料篡改上提供了比純粹的“請求/響應”機制更高的安全保證,我們仍然需要假設亞馬遜自己不會篡改虛擬機器例項。Town Crier(http://www.towncrier.org/)是一個基於可信執行環境的驗證資料饋送預言機系統;這些方法採用基於硬體的安全區(security enclave)來驗證資料完整性。Town Crier使用英特爾的SGX(Software Guard eXtensions)來保證對HTTPS查詢的響應可以被驗證為可信的。SGX也提供了完整性保證,使得在安全區中執行的應用受到CPU保護,不被其他程序篡改。它也提供了機密性,保證應用程式在安全區中執行時,其狀態對其他程序來說是不可知的。最後,SGX透過生成應用程式確定在安全區中執行的數字簽名(透過其構建結果的雜湊值來安全地確定),讓證明成為可能。透過驗證這一數字簽名,去中心化應用就可以證明Town Crier例項正在SGX安全區內安全地執行。這樣就反過來證明了該例項沒有被篡改過,由Town Crier發出的資料是可信的。此外,這種機密屬性還讓Town Crier可以處理隱私資料:使用Town Crier例項的公鑰來加密資料查詢請求。在安全區(如SGX)中執行預言機的“請求/響應”機制,我們完全可以認為Town Crier是在可信第三方硬體中安全地執行,保證了所請求的資料不受篡改地返回(假設我們相信Intel/SGX)。
計算機性的預言機迄今為止,我們只討論請求和分發資料情境下的預言機。但是,預言機也可以用來執行任意計算。給定以太坊內在的區塊gas上限和相對較貴的計算成本,是一個特別有用的功能。不只是傳遞資料請求的結果,計算預言機也可以用來執行帶有一組輸入的相關計算並返回計算結果,而這種計算可能無法在鏈上進行。舉個例子,我們可以使用計算預言機來執行計算密集型的迴歸計算,以估計某個債券智慧合約的收益。如果你願意信任集中而可審計的服務,你可以再次訪問Oraclize。它們提供的服務允許去中心化應用請求在沙盒AWS虛擬機器中執行的計算結果。AWS例項從包含在存檔中的使用者配置的Dockerfile建立可執行容器,該存檔上載到星際檔案系統(IPFS,參見第12章“資料儲存”一節)。根據請求,Oraclize使用其雜湊檢索此存檔,然後在AWS上初始化並執行Docker容器,傳遞將作為環境變數提供給應用程式的任何引數。容器化應用程式根據時間限制執行計算,並將結果寫入標準輸出,Oraclize可以對其進行檢索並返回到去中心化應用。Oraclize目前在可審計的t2.microAWS例項上提供此服務,因此如果計算具有一些非常重要的值,則可以檢查是否執行了正確的Docker容器。儘管如此,這不是一個真正去中心化的解決方案。作為可驗證預言機事實上的標準,“Cryptlet”的概念已經被規範化為微軟更廣泛的ESC框架的一部分。Cryptlet在一個密封安全區中執行,該密封安全區是從基礎設施比如I/O中抽象出來的,並且附加上了CryptoDelegate,所以輸入和輸出訊息都會自動簽名、驗證和證明。Cryptlet支援分散式交易,所以合約邏輯可以用具備ACID屬性的方式來處理複雜的多步驟、多區塊鏈交易以及外部系統交易。開發者因此可以建立用於智慧合約中的可移植的、獨立且具隱私性的事實解析。Cryptlet遵循下列格式:public class SampleContractCryptlet : Cryptlet    {
        public SampleContractCryptlet(Guid id, Guid bindingId, string name,            string address, IContainerServices hostContainer, bool contract)            : base(id, bindingId, name, address, hostContainer, contract)        {            MessageApi = new CryptletMessageApi(GetType().FullName,                new SampleContractConstructor())
TrueBit(https://truebit.io)是一個可擴充套件和可驗證的鏈外計算解決方案。它引入了一個解決者和驗證者系統,它們被激勵各自執行計算和驗證這些計算。如果一個計算結果受到挑戰,鏈上就會相應執行對該計運算元集的迭代驗證程序——這是一種型別的“驗證遊戲”。驗證遊戲會進行幾輪,每一輪都會遞迴地查驗相關計算的更小子集。挑戰充分細分之後,遊戲的終局便到來,法官(以太坊礦工)便可在鏈上最終裁定相關挑戰是否合理。實際上,TrueBit是計算市場的一種實現,去中心化應用因此可以為可驗證計算支付;計算雖然是在鏈外執行的,但依靠以太坊來強制執行驗證者遊戲的規則。理論上來說,這讓免信任型智慧合約安全地執行任意計算任務。像TrueBit這樣的系統有很多應用,從機器學習到任意工作量證明的驗證。後者的其中一個例子是Doge Ethereum橋接,它利用TrueBit來驗證狗狗幣(Dogecoin)的工作量證明演算法Scrypt,這是一種強記憶體需求且計算密集的函式,它不可能在以太坊區塊gas上限內計算完成。透過在TrueBit執行這種驗證,在以太坊Rinkeby測試網路上用智慧合約安全地驗證狗狗幣交易便成為可能。去中心化預言機上面列舉出的所有機制描述的都是中心化的預言機系統,都需要依賴可信的權威。雖然它們可以為許多應用服務,它們的存在仍然意味著以太坊網路中的單點故障。圍繞著去中心化預言機,人們已經提出了很多計劃:去中心化預言機可以用於保證資料可得性,還可搭配鏈上資料彙總系統建立獨立資料提供者網路。Chainlink(https://chain.link)已經提出了一種去中心化預言機網路,由三個關鍵智慧合約(聲譽合約、訂單匹配合約、資料彙總合約)以及資料提供者的鏈外登錄檔組成。聲譽合約用來跟蹤資料提供者的表現。聲譽合約中的分數會更新到鏈外登錄檔中。訂單匹配合約會從使用聲譽合約的預言機中選擇競標者,並最終確定服務層級要約(Service Level Agreement,SLA),其中包含了查詢引數和要求的預言機數量。這也意味著資料購買者不會直接與個體預言機交易。資料彙總合約會從多個預言機處收集響應(使用“commit reveal”模式提交),計算查詢的最終總結果,然後將結果反饋回聲譽合約。這樣的去中心化方案要面臨的其中一個重大挑戰是:構建資料彙總函式。Chainlink提議計算響應附加權重,這樣就可以為每一個預言機響應記錄有效性分數。此處,發現一個“無效”的分數並不是毫無價值的,因為它建立在:(以對統計提供的響應的偏離來度量)過於偏遠的資料點是不正確的這一前提之上。基於某一預言機響應圍繞響應分佈的位置來計算有效性分數有一定風險,具體表現為懲罰偏離平均值的正確答案。因此,Chainlink提供彙總函式的標準集合,但也支援使用定製化的彙總合約。
一個相關的想法是謝林幣協議。其中,多個參與者記錄數值,這些數值的中位數會被當成“正確”答案。記錄者必須先質押保證金,這些保證金會根據它與中位數的接近程度重新分配,由此可以激勵人們記錄與其他人提供的值相近的值。這樣共同的數值,也就是所謂的“謝林點”,預計會接近真實值,因為真實數值是響應者協作中所圍繞的自然而明顯的目標。Jason Teutsch最近提出一種新型的去中心化鏈外資料可得性預言機。這種設計利用了一條專用的工作量證明區塊鏈,後者可以在給定時間內正確地記錄登記過的資料是否可得。礦工會嘗試下載、儲存和傳播所有新近登記的資料,因此保證資料在本地是可得的。這樣的系統是昂貴的,因為每一個挖礦節點都要儲存和傳播所有登記過的資料。該系統可以透過在登記期結束後釋放資料來重複利用儲存空間。Solidity中的預言機客戶端介面程式碼11-1是一個Solidity示例,展示了Oraclize如何從API不斷獲取ETH/USD價格並以可用的方式儲存結果。程式碼11-1:使用Oraclize從外部來源更新ETH/USD匯率/*
    ETH/USD price ticker leveraging CryptoCompare API    This contract keeps in storage an updated ETH/USD price,    which is updated every 10 minutes.    */pragma solidity ^0.4.1;import "github.com/oraclize/ethereum-api/oraclizeAPI.sol";
/*    "oraclize_" prepended methods indicate inheritance from "usingOraclize"    */contract EthUsdPriceTicker is usingOraclize {    uint public ethUsd;    event newOraclizeQuery(string description);
    event newCallbackResult(string result);    function EthUsdPriceTicker() payable {        // signals TLSN proof generation and storage on IPFS        oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS);        // requests query        queryTicker();
    }    function __callback(bytes32 _queryId, string _result, bytes _proof) public {        if (msg.sender != oraclize_cbAddress()) throw;        newCallbackResult(_result);        /*            * Parse the result string into an unsigned integer for on-chain use.
            * Uses inherited "parseInt" helper from "usingOraclize", allowing for            * a string result such as "123.45" to be converted to uint 12345.            */        ethUsd = parseInt(_result, 2);        // called from callback since we're polling the price        queryTicker();
    }    function queryTicker() public payable {        if (oraclize_getPrice("URL") > this.balance) {            newOraclizeQuery("Oraclize query was NOT sent, please add some ETH                to cover for the query fee");        } else {
            newOraclizeQuery("Oraclize query was sent, standing by for the                answer...");            // query params are (delay in seconds, datasource type,            // datasource argument)            // specifies JSONPath, to fetch specific portion of JSON API result            oraclize_query(60 * 10, "URL",
                "json(https://min-api.cryptocompare.com/data/price?\                fsym=ETH&tsyms=USD,EUR,GBP).USD");        }    }}為結合Oraclize,EthUsdPriceTicker合約必須是usingOraclize合約的子合約;後者是在oraclizeAPI檔案中定義好的。資料請求會由usingOraclize合約內建的oraclize_query函式發起。這是一個過載函式,預計至少需要兩個引數:
支援使用的資料來源,如URL、WolframAlpha、IPFS或計算。為給定資料來源設定的引數,可能包括JSON或XML解析助手的使用。資料查詢的價格會由queryTicker函式執行。為執行資料查詢請求,Oraclize要求用支付一小筆費用,用於補償傳輸和處理結果到_callback函式過程中發生的gas費用以及為服務支付的額外費用。費用的數額視資料來源和要求的可信證明型別(如果有所指定的話)而定。一旦檢索了資料,_callback函式就會由Oraclize控制的許可賬戶呼叫;這一過程會傳入響應值和唯一的queryId引數,後者可以用於處理和跟蹤來自Oraclize的多個待定的回撥。金融資料提供者ThomsonReuters也為以太坊提供了一項名為“BlockOneIQ”的預言機服務,讓執行在私有或許可網路上的智慧合約可以請求市場和參考資料。程式碼112是該預言機的互動介面,以及用於發起請求的客戶端智慧合約。程式碼11-2:合約呼叫BlockOneIQ服務以獲取市場資料pragma solidity ^0.4.11;
contract Oracle {    uint256 public divisor;    function initRequest(        uint256 queryType, function(uint256) external onSuccess,        function(uint256    ) external onFailure) public returns (uint256 id);
    function addArgumentToRequestUint(uint256 id, bytes32 name, uint256 arg) public;    function addArgumentToRequestString(uint256 id, bytes32 name, bytes32 arg)        public;    function executeRequest(uint256 id) public;    function getResponseUint(uint256 id, bytes32 name) public constant        returns(uint256);
    function getResponseString(uint256 id, bytes32 name) public constant        returns(bytes32);    function getResponseError(uint256 id) public constant returns(bytes32);    function deleteResponse(uint256 id) public constant;}contract OracleB1IQClient {
    Oracle private oracle;    event LogError(bytes32 description);    function OracleB1IQClient(address addr) public payable {        oracle = Oracle(addr);        getIntraday("IBM", now);    }
    function getIntraday(bytes32 ric, uint256 timestamp) public {        uint256 id = oracle.initRequest(0, this.handleSuccess, this.handleFailure);        oracle.addArgumentToRequestString(id, "symbol", ric);        oracle.addArgumentToRequestUint(id, "timestamp", timestamp);        oracle.executeRequest(id);    }
    function handleSuccess(uint256 id) public {        assert(msg.sender == address(oracle));        bytes32 ric = oracle.getResponseString(id, "symbol");        uint256 open = oracle.getResponseUint(id, "open");        uint256 high = oracle.getResponseUint(id, "high");        uint256 low = oracle.getResponseUint(id, "low");
        uint256 close = oracle.getResponseUint(id, "close");        uint256 bid = oracle.getResponseUint(id, "bid");        uint256 ask = oracle.getResponseUint(id, "ask");        uint256 timestamp = oracle.getResponseUint(id, "timestamp");        oracle.deleteResponse(id);        // Do something with the price data
    }    function handleFailure(uint256 id) public {        assert(msg.sender == address(oracle));        bytes32 error = oracle.getResponseError(id);        oracle.deleteResponse(id);        emit LogError(error);
    }}使用initRequest函式啟動資料請求,該函式允許指定查詢型別(在此示例中是對日內價格的請求)以及兩個回撥函式。這將返回一個uint256識別符號,然後可用於提供其他引數。addArgumentToRequestString函式用於指定路透程式碼表(RIC),此處為IBM庫存,addArgumentToRequestUint允許指定時間戳。現在,傳入block.timestamp的別名將檢索IBM的當前價格。然後由executeRequest函式執行該請求。處理完請求後,預言機合約將使用查詢識別符號呼叫onSuccess回撥函式,從而允許檢索結果資料;如果檢索失敗,onFailure回撥函式將返回錯誤程式碼。成功檢索的可用欄位包括open(開盤價)、high(最高價)、low(最低價)、close(收盤價)和bid/ask(買/賣價)。總結正如你所看到的,預言機為智慧合約提供了至關重要的服務:它們將外部事實帶入合約執行。當然,預言機也會帶來很大的風險:如果它們是受信任的來源並且可能受到損害,可能導致它們提供的智慧合約的執行受損。一般來說,在考慮使用預言機時要非常小心信任模型。如果你認為預言機可以信任,那麼你可能會透過將其暴露給潛在的錯誤輸入來破壞智慧合約的安全性。也就是說,如果仔細考慮安全假設,那麼預言機會非常有用。
去中心化的預言機可以解決其中一些問題,併為以太坊智慧合約提供無信任的外部資料。謹慎選擇,你就可以開始探索以太坊與預言機提供的“真實世界”之間的橋樑。(希)安德烈亞斯·M.安東波羅斯. 精通以太坊:開發智慧合約和去中心化應用 (OReilly精品圖書系列) (Chinese Edition) (Kindle Locations 5007-5013). Kindle Edition.

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读

;