引子

正文

hash160 字符串

SHA256

RIPEMD160

錢包是 keystore 的擴展,管理着交易和餘額,提供創建交易的能力。它有幾個特別重要的屬性,現在解釋如下:

hdChain,HD 數據模型,它包含了一個 hash160 的種子,一個內部鏈的數量和一個外部鏈的數量。

setInternalKeyPool,內部密鑰池的集合。

setExternalKeyPool,外部密鑰池的集合。

set_pre_split_keypool,一個預分割的密鑰池集合。

m_max_keypool_index,最大密鑰池的索引。

m_pool_key_to_index

mapKeyMetadata,公鑰元數據的映射集合。鍵爲一個 hash160 字符串,值爲一個公鑰元數據。

m_script_metadata

mapMasterKeys,

mapWallet

mapAddressBook

錢包說完了,我們來看 keystore。keystore 顧名思議它代表了密鑰的存儲,自然而然提供了一些管理密鑰的方法,比如:添加一個密鑰(私鑰和公鑰)到 store中、檢查給定地址對應的密鑰是否在 store中、添加及檢查一般腳本與只讀腳本的功能等。根據是否加密,keystore 分爲基礎的和加密的兩種。錢包繼承自加密的 keystore,而加密的 keystore 又繼承了基礎的 keystore。

我們先來看下 基礎 keystore ,它有以下幾個重要的屬性:

mapKeys,一個私鑰映射集合。鍵爲一個 hash160 字符串,值爲一個私鑰。

mapWatchKeys,一個只讀的公鑰映射集合。鍵爲一個 hash160 字符串,值爲一個公鑰。

mapScripts,一個腳本映射集合。鍵爲一個 hash160 字符串,值爲一個用在交易輸入和輸出的序列化的腳本。

setWatchOnly,一個用在交易輸入和輸出的序列化的腳本集合。

加密 keystore 在基礎 keystore 上增加了幾個與加密相關的屬性,它們分別爲:

fUseCrypto,一個標誌錢包是否爲加密的變量。

vMasterKey,一個在加密情況下使用的私鑰集合。當加密時 mapKeys集合就會爲空,而vMasterKey集合不空;當不加密時,情況正好反過來,即mapKeys集合不空,而vMasterKey集合爲空。

mapCryptedKeys,一個映射集合。鍵爲一個 hash160 字符串,值爲一個公鑰和加密後私鑰組成的 pair 。

說完錢包與 keystore,下面我們就來看下密鑰池。其實密鑰池這個名字不準確,因爲它僅包含了一個公鑰,初次之外,還包含了兩個布爾變量:fInternal、m_pre_split,前者表示密鑰池是內部還是外部的,後者功能暫時不清楚,英語備註爲:For keys generated before keypool split upgrade。m_pre_split屬性默認爲假。

當創建錢包時,會執行如下幾個動作:

首先,生成一個私鑰,根據私鑰通過橢圓曲線算法生成對應的公鑰;

其次,也會生成對應的密鑰元數據,並且把公鑰的內容用 hash160 (先 SHA256,再RIPEMD160)算法生成的 20個字節的字符串保存爲密鑰元數據的種子,然後把私鑰元數據保存在 mapKeyMetadata集合中;

然後,私鑰被保存在 mapKeys,或mapCryptedKeys與vMasterKey集合中;當公鑰是壓縮的(通常是)時,通過公鑰生成腳本,腳本進而被保存在mapScripts集合中;同時,私鑰、公鑰及密鑰元數據都被保存在數據庫中。

再然後,公鑰被作爲種子,生成 HD 鏈對象,保存在錢包中。

最後,當前面一切完成後,使用前面 3步生成的公鑰做爲種子,開始衍生用戶指定數量的子私鑰/公鑰對,如果用戶沒有指定則默認衍生 3000 個子私鑰/公鑰對。 衍生的私鑰、公鑰及元數據的處理與第 2、3 步相同;同時,用公鑰生成的密鑰池也被保存在數據庫中;根據生成的私鑰屬於內部或外部,對應的索引保存在 setInternalKeyPool、或setExternalKeyPool集合中;不區分地,索引被保存在m_pool_key_to_index映射集合中,其中鍵爲公鑰對應的 hash160 字符串。其中,2000 個子私鑰的路徑從 m/0'/0'/0到m/0'/0'/1999,1000 個子私鑰的路徑從m/0'/1'/0到m/0'/1'/999。其中的m代表私鑰,m/0'代表主私鑰的第 1 個強化子私鑰,m/0'/0'/0代表主私鑰的第 1 個強化子私鑰的外部鏈的第 1 個強化孫私鑰,同理,m/0'/0'/1999代表主私鑰的第 1 個強化子私鑰的外部鏈的第 1999 個強化孫私鑰;m/0'/1'/0代表主私鑰的第 1 個強化子私鑰的內部鏈的第 1 個強化孫私鑰,同理,m/0'/1'/999代表主私鑰的第 1 個強化子私鑰的內部鏈的第 999 個強化孫私鑰。

在上面過程中,1-3 步是 GenerateNewSeed方法的主要內容,第 4 步是SetHDSeed的主要內容,第 5 步是TopUpKeyPool的主要內容。

最後,用兩張圖來概述 HD 錢包的創建。

創建錢包

創建錢包

後記

查看原文 >>
相關文章