以太坊錢包安全性保證
開發以太坊錢包的基本思路與安全
第08課:開發以太坊錢包的基本思路與安全
前面的章節帶領大家一步步完成了以太坊的基本操作和代币的發放,本篇為本系列課程最後一篇内容了,也是重頭戲,将帶大家聊聊中心化存儲錢包的設計以及研發過程中的坑和業務處理。
以太坊錢包的分類
以太坊錢包的分類在第01課的時候就已經介紹過了,還舉例說明了一下,我們知道其實無論 Geth 節點或 Ethereum Wallet 都可以稱作錢包,因為它們都可以存儲以太币、都可以發送交易指令等。但這裡講的錢包分類是另外一個次元,基于 Geth 節點上層再次開發出來的移動端 App 錢包。根據私鑰存儲的位置可分為兩類:
中心化私鑰存儲的錢包,比如火币的錢包;
去中心化錢包,私鑰存儲在使用者端,比如 imtoken 錢包。
去中心化錢包
去中心化錢包不是本節要講的重點,這裡隻給大家簡單介紹一下。無論是中心化的錢包或去中心化的錢包,在 App 層面都是很輕量級的,App 内是不會内置一個 Geth 節點,交易的查詢或發送都是通過伺服器來進行操作,不同點是交易簽名的私鑰由誰來保管和負責。
去中心化的錢包有個關鍵詞:助記詞。可以用下面的表達式來形容助記詞的作用:
私鑰 = 助記詞 = 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
節點孤立是什麼情況?在上面圖中,第1、2區塊成功打包記入區塊鍊,當到第3塊時,有兩個節點同時挖出第3塊,整個區塊鍊中有一部分認同了上面的鍊,有一部分認同了下面的鍊,此時因為都隻有3塊,沒辦法确認哪個是主鍊。但此時區塊已經出現了分叉情況。當更多的塊被挖出,在某一時間節點,上面的鍊的長度比下面的長了,此時所有的節點都會認為最長的為正确的鍊,下面的第3、4塊打包的交易将會被復原,等待重新打包。此時,第3、4塊的狀況叫做被孤立。
套入簽名的業務邏輯,我們的節點處于被孤立的鍊上時,我們之前掃描到的交易所在區塊高度是可變的,在那個區塊上已經沒有我們的交易了,如果此時對賬戶進行增減記賬,會發生資産的不一緻。
那麼如何檢測孤立區塊呢?
監控區塊的高度變化,并記錄在本地資料庫,同時,每收到一筆新的交易,都對比一下此交易記錄的前一塊交易 hash 是否一緻,如果不一緻說明差別已經被孤立,遞歸判斷找到被孤立的前一塊,然後從那塊繼續掃描,重新整理判斷交易情況。
此處特别注意確定幂等性。
區塊被孤立同時需要更新本地資料中此筆交易狀态為被孤立狀态。
測試環境模拟孤立
備份資料,發送簽名(eth_sign)之後的交易;
挖礦3個區塊;
恢複備份資料;
再挖5個塊;
查詢業務是否正常處理孤立情況。
節點熱備
由于每個節點同步到的資料進度差距太大,沒辦法像中心化的業務一樣做負載均衡,隻能通過熱備的形式來保證當一個節點出現故障時能夠快速切換到另外一個節點。因為區塊打包本身就比較耗時,是以此處的時效性要求還是可以容忍的。
enter image description here
節點安全
之前很多朋友因為将 Geth 節點公網開放而導緻資産損失,正是因為沒有正确的認識到 json-rpc 不同權限的接口的問題。在前面的章節中我們已經介紹了不同的節點的權限。這裡再次聲明一下,以下節點慎重對外往開放:
personal
net
txpool
miner
admin
等我們不需要的
其實最安全的模式就是 geth 節點隻對外進行廣播交易。
私鑰管理
上面已經穿插着講了此塊内容,将私鑰單獨存放甚至進行二次加密。
錢包的整體架構
錢包可以通過此種架構來達到高可用和安全性兼顧。
enter image description here
總結
感謝大家的支援,此系列課程到此結束,正是因為大家的支援才讓我有動力在工作之外創造出這套課程,對本人來說也是一個巨大的收獲,後面在時間允許的情況下會為大家推出更多的課程,希望能夠幫到大家,再次感謝!
個人分類: ETH
發表于
2018-08-09 19:28
猴子哥669
閱讀(327)
評論(0)
編輯
收藏
舉報