以太坊錢包安全性保證

開發以太坊錢包的基本思路與安全
第08課:開發以太坊錢包的基本思路與安全
前面的章節帶領你們一步步完成了以太坊的基本操做和代幣的發放,本篇爲本系列課程最後一篇內容了,也是重頭戲,將帶你們聊聊中心化存儲錢包的設計以及研發過程當中的坑和業務處理。算法

以太坊錢包的分類
以太坊錢包的分類在第01課的時候就已經介紹過了,還舉例說明了一下,咱們知道其實不管 Geth 節點或 Ethereum Wallet 均可以稱做錢包,由於它們均可以存儲以太幣、均可以發送交易指令等。但這裏講的錢包分類是另一個維度,基於 Geth 節點上層再次開發出來的移動端 App 錢包。根據私鑰存儲的位置可分爲兩類:數據庫

中心化私鑰存儲的錢包,好比火幣的錢包;
去中心化錢包,私鑰存儲在用戶端,好比 imtoken 錢包。
去中心化錢包
去中心化錢包不是本節要講的重點,這裏只給你們簡單介紹一下。不管是中心化的錢包或去中心化的錢包,在 App 層面都是很輕量級的,App 內是不會內置一個 Geth 節點,交易的查詢或發送都是經過服務器來進行操做,不一樣點是交易簽名的私鑰由誰來保管和負責。json

去中心化的錢包有個關鍵詞:助記詞。能夠用下面的表達式來形容助記詞的做用:安全

私鑰 = 助記詞 = keystore+密碼
經過上面的公式能夠看出助記詞的重要做用,也是去中心錢包功能的一個亮點。當在這類錢包中建立一個帳戶以後,錢包會根據生成的私鑰文件,生成一套助記詞,可爲英文可爲中文,經過助記詞能夠反向計算出 keystore + 密碼。助記詞由用戶手抄存放在安全的地方,當進行交易時,輸入助記詞對交易進行簽名,發送交易。當助記詞丟失,也就意味着失去了私鑰,而錢包通常不會保存用戶的私鑰信息,資產將永久丟失。服務器

去中心化錢包的好處是不用擔憂平臺從中做梗,不用擔憂平臺被黑客攻擊而致使資產損失,但要求我的有必定的私鑰保存能力。網絡

中心錢包
所謂中心化錢包就是將全部的私鑰文件存儲在錢包服務商的服務器內,由服務商來保管這些私鑰文件,也就是說資產屬於你,但私鑰不禁你保管。這樣作的好處是用戶根本不用記住私鑰,只用記住在平臺所開設的帳戶、登陸密碼和支付密碼便可。即便忘記了密碼,仍是能夠經過平臺提供的忘記密碼進行找回,固然,這樣就不具備去中心化錢包的優勢了。架構

下面就帶你們瞭解一下開發這樣一個去中心化錢包的幕後技術工做和思路,後面所提到的錢包若是未作特殊說明,均指中心化錢包。負載均衡

錢包的核心功能
錢包對外呈現可能有不一樣的功能,充值、提現、轉帳等,但從本質上來講只有一個功能,那就是轉帳。區塊鏈本質上就是一個帳本,記錄着一筆筆交易,錢包固然離不開這個本質。性能

充值是錢包的外部帳戶向錢包的地址轉帳;
提現是錢包的帳戶向錢包以外的地址轉帳;
轉帳功能包括錢包內地址互轉和向錢包外地址轉帳;
在這個過程中也對應着錢包帳戶資金的增長與減小。區塊鏈

用戶地址如何分配
用戶在使用錢包的時候確定須要有一個屬於當前帳戶對應在區塊鏈上的地址,這個地址如何生成呢?在技術交流羣中,很多開發人員是這樣實現的:每次當用戶註冊時就調用 Geth 節點的personal_newAccount方法生成一個地址,並將地址存放在 Geth 節點默認的位置。這種方式能夠實現,但從技術上和安全上來說是不可取的。

性能瓶頸之一,調用 Geth 節點生成地址很是耗時,特別是當節點在處理一些同步或高消耗的工做時。
性能瓶頸之二,當 Geth 節點下的私鑰愈來愈多,Geth 啓動會變得漫長。
安全問題,Geth 節點對外要廣播交易,又要保存敏感的私鑰信息,安全問題巨大。
優化以後的作法是事先批量生成地址,當用戶註冊時只用把地址分配給用戶便可。這樣作的好處是:

私鑰的存儲與 Geth 節點相隔離,確保私鑰與外網的隔離性,從而確保私鑰的安全;
性能的保障,當用戶註冊時只是將數據庫的數據創建了一個關聯,而不用去執行費時的加密算法來生成私鑰和文件。
此種方法生成 Web3j 提供了相應的建立方法,可在無 Geth 節點的狀況下經過代碼直接生成符合私鑰規則的公私鑰。固然,若是有開發能力也能夠經過 Geth 的源代碼中的私鑰生成方法抽離出一個單獨的與網絡無關的生產私鑰程序。

充值交易
在比特幣的錢包中,有子帳戶的概念,只須要在一個總帳戶下建立 N 多子帳號,用戶充值到此子帳號的比特幣一樣的會顯示在錢包上,同時又提供了查詢一個地址全部交易的方法。遺憾的是以太幣並無提供此類接口,只能經過遍歷區塊交易的方法來判斷是否有對應帳戶的充值交易。

相關操做:

查詢區塊高度,比對是不是新生成的區塊,eth_blockNumber;
查看區塊內容及詳細交易,eth_gethBlockByNumber;
比對交易的 toAddress 是否爲本錢包的地址,若是是則記錄此筆交易到數據庫,並記錄交易狀態(pending、確認次數等);
保證入庫和記帳的冪等性,由於會屢次查詢到同一筆交易。
確認次數
並非咱們查詢區塊鏈中的交易就說明這邊交易已經成功了,比特幣是默認確認12此以後,此交易幾乎不會被篡改,以太坊默認6次,那麼怎麼計算確認次數呢?

確認次數 = 當前區塊高度 - 交易所在區塊高度 + 1
此處注意事項:交易有可能會被孤立,在執行此公式時須要驗證一下區塊中此交易是否仍是在那個區塊上,是否已經被回滾。一樣的,要作好冪等性保障。

提現交易
提現交易一樣涉及到上提到的知識點,同時它又有須要額外注意的事項。

提現地址的合法性檢查,可參考源代碼中的校驗,此合法性檢查能夠避免後續不少問題的出現,好比 nonce 值的維護。
交易的金額檢查,nonce 值檢查(nonce 值會遇到的問題前面已經提到過),特別是私鑰與 Geth 節點分離以後本身來維護私鑰時 nonce 值會是一個很大的問題,好比前一筆交易失敗,nonce 值須要回退,此時後一筆交易已經發出,由於前一筆 nonce 沒有被補齊,後一筆遲遲不會被交易。這些都須要業務進行特殊判斷和處理。
查詢一個地址 nonce,eth_getTransactionCount。
提現與轉帳
提現與轉帳都是發起一筆交易,在以太坊的 json-rpc 中已經提到能夠經過 eth_sendTransaction 和 personal_sendTransaction 直接進行轉帳,這是 Geth 節點所支持的。轉帳前能夠經過 unlock 方法先將帳戶解鎖,這些以前章節都有提到過。

但針對私鑰單獨存儲的狀況,上面的方式並不適用,可經過將交易先簽名再廣播的模式:

簽名交易(可自主開發,可利用節點自己),eth_sign。
廣播交易,可經過 eth_sendRawTransaction 進行廣播。
錢包的內部轉帳只不過是 from 和 to 地址都是錢包的地址而已,業務層進行適當的處理。
經過這種模式,節點與外界打交道,僅有的功能就是廣播交易,在此以前的全部操做均可以經過內網進行操做,極大的確保的私鑰和交易的安全性。

轉帳手續費
轉帳的手續費算是常識性的內容,可給用戶一些參考值,讓用戶選擇願意支付的手續費,也可經過節點提供的eth_estimateGas來進行預估。

最笨拙而又有效的方法是按期觀察一下區塊鏈上交易成功的交易的 gasPrice 的大概範圍,動態的調整一下價格,而 gasLimit 在不影響交易(太大帳戶餘額檢查時不足)的狀況下,儘量稍微多一些,由於此部分若是未使用還會退換到交易發起帳戶中。

節點孤立
在發起或檢查以太坊交易是否成功不只僅要檢查確認次數,還須要檢查交易是否被孤立。孤立的狀況用下面的圖來展現分析一下:

enter image description here

節點孤立是什麼狀況?在上面圖中,第一、2區塊成功打包記入區塊鏈,當到第3塊時,有兩個節點同時挖出第3塊,整個區塊鏈中有一部分認同了上面的鏈,有一部分認同了下面的鏈,此時由於都只有3塊,沒辦法確認哪一個是主鏈。但此時區塊已經出現了分叉狀況。當更多的塊被挖出,在某一時間節點,上面的鏈的長度比下面的長了,此時全部的節點都會認爲最長的爲正確的鏈,下面的第三、4塊打包的交易將會被回滾,等待從新打包。此時,第三、4塊的情況叫作被孤立。

套入簽名的業務邏輯,咱們的節點處於被孤立的鏈上時,咱們以前掃描到的交易所在區塊高度是可變的,在那個區塊上已經沒有咱們的交易了,若是此時對帳戶進行增減記帳,會發生資產的不一致。

那麼如何檢測孤立區塊呢?

監控區塊的高度變化,並記錄在本地數據庫,同時,每收到一筆新的交易,都對比一下此交易記錄的前一塊交易 hash 是否一致,若是不一致說明區別已經被孤立,遞歸判斷找到被孤立的前一塊,而後從那塊繼續掃描,從新整理判斷交易狀況。
此處特別注意確保冪等性。
區塊被孤立同時須要更新本地數據中此筆交易狀態爲被孤立狀態。
測試環境模擬孤立
備份數據,發送簽名(eth_sign)以後的交易;
挖礦3個區塊;
恢復備份數據;
再挖5個塊;
查詢業務是否正常處理孤立狀況。
節點熱備
因爲每一個節點同步到的數據進度差距太大,沒辦法像中心化的業務同樣作負載均衡,只能經過熱備的形式來保證當一個節點出現故障時可以快速切換到另一個節點。由於區塊打包自己就比較耗時,所以此處的時效性要求仍是能夠容忍的。

enter image description here

節點安全
以前不少朋友由於將 Geth 節點公網開放而致使資產損失,正是由於沒有正確的認識到 json-rpc 不一樣權限的接口的問題。在前面的章節中咱們已經介紹了不一樣的節點的權限。這裏再次聲明一下,如下節點慎重對外往開放:

personal
net
txpool
miner
admin
等咱們不須要的
其實最安全的模式就是 geth 節點只對外進行廣播交易。

私鑰管理
上面已經穿插着講了此塊內容,將私鑰單獨存放甚至進行二次加密。

錢包的總體架構
錢包能夠經過此種架構來達到高可用和安全性兼顧。

enter image description here

總結
感謝你們的支持,此係列課程到此結束,正是由於你們的支持才讓我有動力在工做以外創造出這套課程,對本人來講也是一個巨大的收穫,後面在時間容許的狀況下會爲你們推出更多的課程,但願可以幫到你們,再次感謝!

我的分類: ETH

相關文章
相關標籤/搜索