Dapp后端架構(gòu),安全性和設(shè)計(jì)模式
本文轉(zhuǎn)載自微信公眾號(hào)「區(qū)塊鏈研究實(shí)驗(yàn)室」,作者鏈三豐。轉(zhuǎn)載本文請(qǐng)聯(lián)系區(qū)塊鏈研究實(shí)驗(yàn)室公眾號(hào)。
去中心化應(yīng)用程序(DApps)需要特殊的系統(tǒng)設(shè)計(jì),以實(shí)現(xiàn)高安全性和可靠性。
在本文中,我將以以太坊為主要示例,介紹如何為去中心化應(yīng)用程序正確設(shè)計(jì)、實(shí)現(xiàn)后端和智能合約的幾個(gè)主要原則,盡管其中大部分將適用于Eos、Tron和其他去中心化數(shù)據(jù)平臺(tái)。
文章重點(diǎn):
- 如何在不考慮安全性的情況下將私鑰存儲(chǔ)在后端
- 如何正確設(shè)計(jì)智能合約以及“去中心化”的內(nèi)容
- 分散式和半分散式應(yīng)用程序架構(gòu)示例
- 如何處理網(wǎng)絡(luò)負(fù)載和故障等底層問(wèn)題
讓我們開(kāi)始吧!
1.去中心化程序和區(qū)塊鏈
盡管如今區(qū)塊鏈面臨著許多采用和監(jiān)管方面的困難,但無(wú)論采用哪種算法,無(wú)論區(qū)塊鏈,哈希圖,速度還是其他任何分布式賬本技術(shù),它都是一種永存的技術(shù)。
區(qū)塊鏈和其他類(lèi)似技術(shù)帶來(lái)的主要價(jià)值可以概括如下:它們使人們能夠編寫(xiě)和運(yùn)行程序,這些程序?qū)嶋H上在創(chuàng)建后就不能更改,在執(zhí)行過(guò)程中也不能篡改。換句話(huà)說(shuō),這些程序始終按設(shè)計(jì)運(yùn)行,并且任何一方都不能影響其行為。如果我們將它們視為定義如何來(lái)回轉(zhuǎn)移硬幣的程序,則此定義對(duì)當(dāng)今存在的許多加密貨幣均有效。這也解釋了為什么加密貨幣和多種令牌具有真正的價(jià)值:它們不能通過(guò)定義的“底層程序”憑空產(chǎn)生。
與比特幣相反,以太坊/ EOS / Tron /…平臺(tái)實(shí)現(xiàn)了一個(gè)更復(fù)雜的程序?qū)?,該層又?shí)現(xiàn)了執(zhí)行環(huán)境,允許任何人在平臺(tái)之上編寫(xiě)自己的去中心化程序。用戶(hù)定義的程序始終按設(shè)計(jì)運(yùn)行,沒(méi)有任何異常,并且平臺(tái)保證了其安全性。
2.分散應(yīng)用
這些在分散式網(wǎng)絡(luò)上運(yùn)行的安全且不可更改的程序與傳統(tǒng)的前端和后端技術(shù)相結(jié)合,今天被稱(chēng)為分散式應(yīng)用程序(DApps)。通過(guò)其中的一些可以半集中,真正去中心化的應(yīng)用程序中的大部分活動(dòng)應(yīng)該發(fā)生在中央的控制之下。
如果有人要求我繪制DApps今天的工作方式,我可能會(huì)繪制此圖
想象一下我們今天所說(shuō)的去中心化應(yīng)用程序,以_YouTube_或_instagram_之類(lèi)的任何現(xiàn)有集中式Web資源為例,并想象將您的“加密身份”綁定到Web /移動(dòng)資源,而不是受密碼保護(hù)的集中式帳戶(hù)。
這就是電子錢(qián)包軟件為您提供的。此身份的私鑰(秘密,您可以代表此身份進(jìn)行操作)存儲(chǔ)在本地設(shè)備上,并且永遠(yuǎn)不會(huì)在線(xiàn),因此沒(méi)有人可以控制此身份。有了這個(gè)身份,你可以在兩個(gè)執(zhí)行不同的操作集中 和(由中央管理機(jī)構(gòu)控制網(wǎng)絡(luò)資源)分散(這是從傳統(tǒng)的WWW不同的網(wǎng)絡(luò),目標(biāo),其中是消除中央機(jī)關(guān))網(wǎng)絡(luò),將網(wǎng)站用作訪(fǎng)問(wèn)點(diǎn)和/或圖形用戶(hù)界面。這種“密碼身份”的全部意義在于,您的操作是通過(guò)密碼保護(hù)的,沒(méi)有人能夠更改您簽名的內(nèi)容或簽名。
如今,容錯(cuò)分散網(wǎng)絡(luò)(如以太坊,EOS或Tron)的計(jì)算和存儲(chǔ)能力受到限制。如果它們是可擴(kuò)展的,我們可以使用分散的網(wǎng)絡(luò)來(lái)存儲(chǔ)整個(gè)分散的應(yīng)用程序,包括其圖形用戶(hù)界面,數(shù)據(jù)和業(yè)務(wù)邏輯。在這種情況下,我們將這些應(yīng)用程序稱(chēng)為真正的分散/分布式應(yīng)用程序。
但是,由于這些網(wǎng)絡(luò)目前無(wú)法擴(kuò)展,因此我們結(jié)合了不同的方法來(lái)為我們的應(yīng)用程序?qū)崿F(xiàn)最大的分散級(jí)別。我們知道,“傳統(tǒng)”后端沒(méi)有任何發(fā)展。
例如:
- 我們使用后端來(lái)托管分散應(yīng)用程序的前端。
- 我們使用后端與任何其他現(xiàn)有技術(shù)和服務(wù)進(jìn)行集成。真正的世界一流的應(yīng)用程序不能生活在孤立的環(huán)境中。
- 我們使用后端存儲(chǔ)和處理足以分散網(wǎng)絡(luò)(尤其是區(qū)塊鏈)的任何事物。實(shí)際上,整個(gè)應(yīng)用程序及其業(yè)務(wù)邏輯存儲(chǔ)在世界的某個(gè)地方,僅不包括區(qū)塊鏈部分。更不用說(shuō),IPFS和類(lèi)似的存儲(chǔ)層不能保證文件的可訪(fǎng)問(wèn)性,因此我們也不能依靠它們而不自己托管文件。換句話(huà)說(shuō),始終需要專(zhuān)用的運(yùn)行服務(wù)器。
到目前為止,如果不使用可靠的后端,就無(wú)法構(gòu)建安全且部分分散的應(yīng)用程序,本文的重點(diǎn)是解釋如何正確地做到這一點(diǎn)。
3.(去中心化)和代幣
碰巧的是,當(dāng)今幾乎所有分散式應(yīng)用程序都是圍繞所謂的令牌構(gòu)建的,令牌是驅(qū)動(dòng)特定分散式應(yīng)用程序的定制(或只是簡(jiǎn)單克隆)的加密貨幣。令牌僅僅是一種可編程的貨幣或資產(chǎn),僅此而已。
令牌智能合約決定了用戶(hù)如何傳輸令牌,而應(yīng)用程序智能合約可以擴(kuò)展令牌智能合約中缺少的所有內(nèi)容。兩種智能合約都運(yùn)行在去中心化網(wǎng)絡(luò)之上通常,令牌是寫(xiě)在像以太坊這樣的去中心化平臺(tái)之上的“智能合約”。通過(guò)擁有一些令牌,您基本上可以在Web資源或移動(dòng)應(yīng)用程序上獲得不同的服務(wù),并將該令牌換成其他東西。這里的關(guān)鍵點(diǎn)是令牌本身是存在的,并且不受中央機(jī)構(gòu)的控制。
有許多圍繞令牌構(gòu)建的應(yīng)用程序示例:從諸如CryptoKitties(ERC721令牌)之類(lèi)的眾多可收藏游戲到諸如LOOM Network等面向服務(wù)的應(yīng)用程序,甚至是諸如Brave之類(lèi)的瀏覽器以及諸如DreamTeam(與ERC20兼容的令牌)之類(lèi)的游戲平臺(tái)。開(kāi)發(fā)人員自己確定并決定他們將(或不會(huì))對(duì)其應(yīng)用程序進(jìn)行多少控制。他們可以在智能合約的基礎(chǔ)上構(gòu)建整個(gè)應(yīng)用程序的業(yè)務(wù)邏輯(就像CryptoKitties所做的那樣),或者,他們根本不使用智能合約,將服務(wù)器上的所有內(nèi)容集中在一起。但是,最好的方法是居中。
4.分散網(wǎng)絡(luò)的后端
從技術(shù)角度來(lái)看,必須有一個(gè)將令牌和其他智能合約與Web /移動(dòng)應(yīng)用程序連接的橋梁。
在當(dāng)今的完全去中心化的應(yīng)用程序中,客戶(hù)端直接與智能合約進(jìn)行交互,此橋被縮小為公共API或Infura之類(lèi)的節(jié)點(diǎn)池的JSON RPC API功能,由于并非每個(gè)設(shè)備都可以運(yùn)行并支持其單獨(dú)的網(wǎng)絡(luò)節(jié)點(diǎn)。但是,此API僅提供了一組基本且非常狹窄的功能,這些功能僅允許進(jìn)行簡(jiǎn)單查詢(xún)或有效地聚合數(shù)據(jù)。因此,最終會(huì)引入自定義后端,從而使應(yīng)用程序成為半集中式。
與分散網(wǎng)絡(luò)的整個(gè)交互可以縮小到一兩個(gè)點(diǎn),具體取決于應(yīng)用程序的需求:
- 偵聽(tīng)網(wǎng)絡(luò)事件(例如令牌傳輸) /讀取網(wǎng)絡(luò)狀態(tài)。
- 發(fā)布交易(調(diào)用狀態(tài)更改智能合約功能,如令牌轉(zhuǎn)移)。
這兩個(gè)方面的實(shí)現(xiàn)都非常棘手,特別是如果我們要構(gòu)建一個(gè)安全可靠的后端解決方案時(shí)。以下是我們要分解的要點(diǎn):
- 首先,在以太坊中,事件檢索不是開(kāi)箱即用的。由于多種原因:網(wǎng)絡(luò)節(jié)點(diǎn)在提取大量事件時(shí)可能會(huì)失敗,事件可能會(huì)由于網(wǎng)絡(luò)派生而消失或發(fā)生更改等。我們必須構(gòu)建一個(gè)抽象層,以同步網(wǎng)絡(luò)中的事件并確保其可靠傳遞。
- 與交易發(fā)布相同,我們必須抽象以太坊的低端內(nèi)容,例如隨機(jī)數(shù)計(jì)數(shù)器和天然氣估算值,以及交易重新發(fā)布,以提供可靠且穩(wěn)定的界面。此外,事務(wù)發(fā)布意味著使用私鑰,這需要高級(jí)后端安全性。
- 安全。我們將認(rèn)真對(duì)待它,并面對(duì)無(wú)法保證私鑰在后端永遠(yuǎn)不會(huì)受到損害的問(wèn)題。幸運(yùn)的是,有一種設(shè)計(jì)去中心化應(yīng)用程序的方法,甚至不需要高度保護(hù)后端帳戶(hù)。
在我們的實(shí)踐中,所有這些使我們?yōu)橐蕴粍?chuàng)建了一個(gè)強(qiáng)大的后端解決方案,我們將其命名為Ethereum Gateway。它從以太坊的樂(lè)趣中抽象出了其他微服務(wù),并提供了一個(gè)可靠的API來(lái)使用它。
以太坊的后端監(jiān)控。監(jiān)控器演示的活動(dòng)主要與我們的循環(huán)計(jì)費(fèi)功能有關(guān)(盡管您可以看到每小時(shí)都有峰值)。
5.分散式應(yīng)用架構(gòu)
這部分高度依賴(lài)于特定的去中心化應(yīng)用程序的需求,我們將嘗試在構(gòu)建這些應(yīng)用程序的基礎(chǔ)上梳理一些基本的交互模式(D平臺(tái)=去中心化平臺(tái)=以太坊/ EOS / Tron / Whatever):
客戶(hù) 平臺(tái):完全分散的應(yīng)用程序。
客戶(hù)端(瀏覽器或移動(dòng)應(yīng)用程序)在以太坊“錢(qián)包”軟件(如Metamask,Trust)或硬件錢(qián)包(如Trezor或Ledger)的幫助下,直接與分散平臺(tái)進(jìn)行對(duì)話(huà)。以這種方式構(gòu)建DApp的示例包括CryptoKitties,Loom的 Delegated Call,加密錢(qián)包本身(Metamask,Trust,Tron Wallet等),分散式加密交易所(如Etherdelta)等。
D平臺(tái)?客戶(hù)?后端?D平臺(tái):集中式或半集中式應(yīng)用程序。
客戶(hù)端與分散平臺(tái)和服務(wù)器的交互幾乎沒(méi)有共同點(diǎn)。一個(gè)很好的例子是當(dāng)今的任何(集中式)加密貨幣交易所,例如BitFinex或Poloniex:您在交易所交易的貨幣只記錄在傳統(tǒng)數(shù)據(jù)庫(kù)中。您可以通過(guò)將資產(chǎn)發(fā)送到特定地址(“平臺(tái)?客戶(hù)端”)來(lái)“充值”數(shù)據(jù)庫(kù)余額,然后在應(yīng)用程序中執(zhí)行某些操作后(后臺(tái)?D平臺(tái))撤回資產(chǎn),但是,您所做的一切都取決于“應(yīng)用程序”本身(客戶(hù)端?后端)并不意味著您與D平臺(tái)直接交互。
另一個(gè)示例是Etherscan.io,它使用半集中式方法:您可以在其中執(zhí)行所有有用的去中心化操作,但是沒(méi)有它們的綜合后端,應(yīng)用程序本身就沒(méi)有任何意義(Etherscan持續(xù)同步事務(wù),解析數(shù)據(jù)并存儲(chǔ)它,最終提供全面的API / UI)。
介于兩者之間的內(nèi)容:靜止, 集中式或半集中式應(yīng)用程序。
結(jié)合以上方法。例如,我們可以有一個(gè)應(yīng)用程序,該應(yīng)用程序提供各種服務(wù)以換取加密,從而使您可以使用加密身份登錄并簽名信息。
希望完全分散的應(yīng)用程序(客戶(hù)端Client平臺(tái))的交互模式不會(huì)引起任何問(wèn)題。依靠Infura或Trongrid等令人贊嘆的服務(wù),您可以簡(jiǎn)單地構(gòu)建根本不需要服務(wù)器的應(yīng)用程序。像幾乎所有的客戶(hù)端庫(kù)Ethers.js為復(fù)仇或特隆的Web為特隆可以連接到這些公共服務(wù)和與網(wǎng)絡(luò)進(jìn)行通信。但是,對(duì)于更復(fù)雜的查詢(xún)和任務(wù),您可能仍然需要分配自己的服務(wù)器。
其余涉及后端的交互模式使事情變得更加有趣和復(fù)雜。為了將所有這些圖景化,讓我們想象一下后端對(duì)網(wǎng)絡(luò)中的某些事件做出反應(yīng)的情況。例如,用戶(hù)發(fā)布了一項(xiàng)配額交易,該交易允許我們向他們收取費(fèi)用。要收取費(fèi)用,我們必須針對(duì)發(fā)出的配額事件發(fā)布費(fèi)用交易:
分散網(wǎng)絡(luò)中服務(wù)器對(duì)用戶(hù)操作的反應(yīng)的示例流程從后端的角度來(lái)看,會(huì)發(fā)生以下情況:
- 我們通過(guò)不斷輪詢(xún)網(wǎng)絡(luò)來(lái)監(jiān)聽(tīng)特定的網(wǎng)絡(luò)事件。
- 收到事件后,我們將執(zhí)行一些業(yè)務(wù)邏輯,然后決定發(fā)布一個(gè)事務(wù)作為響應(yīng)。
- 在發(fā)布交易之前,我們要確保將有可能被開(kāi)采(在以太坊中,成功的交易氣體估計(jì)意味著沒(méi)有相對(duì)于當(dāng)前網(wǎng)絡(luò)狀態(tài)的錯(cuò)誤)。但是,我們不能保證交易將被成功開(kāi)采。
- 使用私鑰,我們簽署并發(fā)布交易。在以太坊中,我們還必須確定交易的天然氣價(jià)格和天然氣限額。
- 發(fā)布交易后,我們會(huì)連續(xù)輪詢(xún)網(wǎng)絡(luò)以了解其狀態(tài)。
- 如果花費(fèi)的時(shí)間太長(zhǎng)而我們無(wú)法獲得交易的狀態(tài),則必須重新發(fā)布它或觸發(fā)“失敗情況”。交易可能由于各種原因而丟失:網(wǎng)絡(luò)擁塞,對(duì)等體掉落,網(wǎng)絡(luò)負(fù)載增加等。在以太坊中,您還可以考慮以不同的(實(shí)際)汽油價(jià)格重新簽署交易。
- 在我們最終確定交易事項(xiàng)之后,如果需要,我們可以執(zhí)行更多的業(yè)務(wù)邏輯。例如,我們可以通知其他后端服務(wù)有關(guān)交易已完成的事實(shí)。另外,考慮在做出有關(guān)交易的最終決定之前等待幾次確認(rèn):網(wǎng)絡(luò)是分布式的,因此結(jié)果可能會(huì)在幾秒鐘內(nèi)發(fā)生變化。
如您所見(jiàn),發(fā)生了很多事情!但是,您的應(yīng)用程序可能不需要其中的某些步驟,具體取決于您要實(shí)現(xiàn)的目標(biāo)。但是,構(gòu)建強(qiáng)大而穩(wěn)定的后端需要解決上述所有問(wèn)題。讓我們分解一下。
6.分散的應(yīng)用程序后端
在這里,我想強(qiáng)調(diào)一些出現(xiàn)大多數(shù)問(wèn)題的要點(diǎn),即:
- 偵聽(tīng)網(wǎng)絡(luò)事件并從網(wǎng)絡(luò)讀取數(shù)據(jù)
- 發(fā)布交易以及如何安全地進(jìn)行交易
7.收聽(tīng)網(wǎng)絡(luò)事件
在以太坊以及其他去中心化網(wǎng)絡(luò)中,智能合約事件(或事件日志,或僅是日志)的概念使鏈外應(yīng)用程序可以了解區(qū)塊鏈中正在發(fā)生的事情。這些事件可由智能合約開(kāi)發(fā)人員在智能合約代碼的任何位置創(chuàng)建。
例如,在眾所周知的ERC20令牌標(biāo)準(zhǔn)中,每個(gè)令牌轉(zhuǎn)移都必須記錄Transfer事件,從而使鏈下應(yīng)用程序知道發(fā)生了令牌轉(zhuǎn)移。通過(guò)“監(jiān)聽(tīng)”這些事件,我們可以執(zhí)行任何(重新)操作。例如,當(dāng)令牌轉(zhuǎn)移到您的地址時(shí),某些移動(dòng)加密錢(qián)包會(huì)向您發(fā)送推送/電子郵件通知。
實(shí)際上,沒(méi)有可靠的解決方案可以開(kāi)箱即用地監(jiān)聽(tīng)網(wǎng)絡(luò)事件。不同的庫(kù)允許您跟蹤/偵聽(tīng)事件,但是,在許多情況下,某些事情可能出錯(cuò),從而導(dǎo)致事件丟失或未處理。為了避免丟失事件,我們必須構(gòu)建一個(gè)自定義后端,該后端將維護(hù)事件同步過(guò)程。
根據(jù)您的需求,實(shí)現(xiàn)方式可能會(huì)有所不同。但是在這里給你一個(gè)圖片是如何根據(jù)微服務(wù)架構(gòu)構(gòu)建可靠的以太坊事件交付的選項(xiàng)之一:
將以太坊事件可靠地傳遞給所有后端服務(wù)這些組件以以下方式工作:
- 事件同步后端服務(wù)不斷輪詢(xún)網(wǎng)絡(luò),以嘗試檢索新事件。一旦有一些新事件可用,它將把這些事件發(fā)送到消息總線(xiàn)。將事件成功提交到消息總線(xiàn)后,就區(qū)塊鏈而言,我們可以保存上一個(gè)事件的塊,以便下次從該塊中請(qǐng)求新事件。請(qǐng)記住,一次檢索太多事件可能會(huì)導(dǎo)致請(qǐng)求始終失敗,因此您必須限制從網(wǎng)絡(luò)請(qǐng)求的事件/塊的數(shù)量。
- 消息總線(xiàn)(例如Rabbit MQ)將事件路由到為每個(gè)后端服務(wù)分別設(shè)置的每個(gè)隊(duì)列。在事件發(fā)布之前,事件同步后端服務(wù)指定路由密鑰(例如,智能合約地址+事件主題),而使用者(其他后端服務(wù))創(chuàng)建僅訂閱特定事件的隊(duì)列。
結(jié)果,每個(gè)后端服務(wù)僅獲取所需的那些事件。此外,消息總線(xiàn)可確保將所有事件發(fā)布到事件總線(xiàn)后再進(jìn)行傳遞。
當(dāng)然,您可以使用其他方式代替消息總線(xiàn):HTTP回調(diào),套接字等。在這種情況下,您需要弄清楚如何確保自己提供回調(diào):管理指數(shù)/自定義回調(diào)重試,實(shí)現(xiàn)自定義監(jiān)視。
8.發(fā)布交易
為了將事務(wù)發(fā)布到分散網(wǎng)絡(luò),我們必須執(zhí)行幾個(gè)步驟:
- 準(zhǔn)備交易。與交易數(shù)據(jù)一起,此步驟意味著請(qǐng)求網(wǎng)絡(luò)狀態(tài),以查明此交易是否有效并且是否將要開(kāi)采(以太坊中的gas估計(jì))和交易的序號(hào)(以太坊中的nonce)。一些庫(kù)試圖在后臺(tái)進(jìn)行此操作,但是,這些步驟很重要。
- 簽署交易。此步驟暗示私鑰的使用。最有可能的是,您將在此處嵌入自定義私鑰組裝解決方案。
- 發(fā)布和重新發(fā)布事務(wù)。這里的關(guān)鍵點(diǎn)之一是,您已發(fā)布的交易始終有機(jī)會(huì)從分散的網(wǎng)絡(luò)中丟失或丟失。例如,在以太坊中,如果網(wǎng)絡(luò)的天然氣價(jià)格突然上漲,則已發(fā)布的交易可能會(huì)被丟棄。在這種情況下,您必須重新發(fā)布事務(wù)。此外,您可能希望重新發(fā)布具有其他參數(shù)的交易(至少在汽油價(jià)格較高的情況下),以便盡快進(jìn)行交易。因此,如果替換交易之前未進(jìn)行預(yù)簽名(使用不同的參數(shù)),則重新發(fā)布該交易可能意味著對(duì)其重新簽名。
以上有關(guān)以太坊交易發(fā)布的要點(diǎn)可視化通過(guò)使用上述方法,您可以最終構(gòu)建類(lèi)似于以下序列圖中所示內(nèi)容的內(nèi)容。
在這個(gè)特定的序列圖上,我將演示(大體上!)區(qū)塊鏈循環(huán)計(jì)費(fèi)的工作原理:
- 用戶(hù)執(zhí)行智能合約中的功能,該功能最終允許后端執(zhí)行成功的費(fèi)用交易。
- 負(fù)責(zé)特定任務(wù)的后端服務(wù)偵聽(tīng)收費(fèi)限額事件并發(fā)布收費(fèi)交易。
- 一旦挖掘到收費(fèi)交易,負(fù)責(zé)特定任務(wù)的后端服務(wù)就會(huì)從以太坊網(wǎng)絡(luò)接收事件,并執(zhí)行一些邏輯(包括設(shè)置下一個(gè)收費(fèi)日期)。
區(qū)塊鏈循環(huán)計(jì)費(fèi)工作原理的一般序列圖,展示了后端服務(wù)與以太坊網(wǎng)絡(luò)之間的交互后端安全和智能合約。
事務(wù)發(fā)布始終涉及使用私鑰。您可能想知道是否可以保護(hù)私鑰安全。有許多的、復(fù)雜的策略和不同類(lèi)型的軟件這樣可以非常安全地將私鑰存儲(chǔ)在后端。一些私鑰存儲(chǔ)解決方案使用地理分布的數(shù)據(jù)庫(kù),而另一些甚至建議使用特殊的硬件。但是,在任何情況下,半集中式應(yīng)用程序最容易受到攻擊的地方是私鑰被組裝并用于簽署交易的地方(或者在使用特殊硬件的情況下,觸發(fā)交易簽署過(guò)程的地點(diǎn))。因此,從理論上講,沒(méi)有100%可靠的解決方案可以使防彈保護(hù)免受損害存儲(chǔ)的私鑰。