BIP: 44 Layer: Applications Title: Multi-Account Hierarchy for Deterministic Wallets Author: Marek Palatinus <slush@satoshilabs.com> Pavol Rusnak <stick@satoshilabs.com> Comments-Summary: Mixed review (one person) Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0044 Status: Proposed Type: Standards Track Created: 2014-04-24
Abstract
This BIP defines a logical hierarchy for deterministic wallets based on an algorithm described in BIP-0032 (BIP32 from now on) and purpose scheme described in BIP-0043 (BIP43 from now on).
這個BIP定義了一個基於BIP-0032和BIP-0043中描述的目的方案的邏輯層次結構。
This BIP is a particular application of BIP43.
這個BIP就是BIP43的一個特殊應用
Motivation
The hierarchy proposed in this paper is quite comprehensive. It allows the handling of multiple coins, multiple accounts, external and internal chains per account and millions of addresses per chain.
本文提出的層次結構比較全面。它允許處理多個硬幣、多個帳戶、每個帳戶的外部和內部鏈以及每個鏈的數百萬個地址。
Path levels
We define the following 5 levels in BIP32 path:
定義BIP32路徑中的5個層次
m / purpose' / coin_type' / account' / change / address_index
Apostrophe in the path indicates that BIP32 hardened derivation is used.
Each level has a special meaning, described in the chapters below.
路徑中的撇號表示使用了經過硬化(hardern)處理的BIP32派生。
每個層次都有一個特殊的含義,在下面的章節中描述。
Purpose
Purpose is a constant set to 44' (or 0x8000002C) following the BIP43 recommendation. It indicates that the subtree of this node is used according to this specification.
根據BIP43建議將Purpose常量設置為44'(或0x8000002C),表示該節點的子樹是根據本規范使用的。
Hardened derivation is used at this level.
硬化的派生在這個級別上使用。(所以右上角有'標記)
⚠️BIP-43 提出使用第一個強化子索引作為特殊的標識符表示 樹狀結構的“purpose”。基於 BIP-43,HD 錢包應該使用且只用第一層級的樹的分支,而且有索引號碼去識別結構並且有命名空間來定義剩余的樹的目的地。舉個 例子,HD 錢包只使用分支 m/i’/是 為了表明那個被索引號“i”定義的特殊為目地。
所以Purpose常量設置為44'是為了表示該錢包遵循的是 BIP-44 的 HD 錢包依據
Coin type-表示你存儲的數字貨幣的類型
比如:index 0 表示的是比特幣
index | hexa | symbol | coin |
---|---|---|---|
0 | 0x80000000 | BTC | Bitcoin |
One master node (seed) can be used for unlimited number of independent cryptocoins such as Bitcoin, Litecoin or Namecoin. However, sharing the same space for various cryptocoins has some disadvantages.
一個主節點(seed)可以用於無限數量的獨立加密貨幣,如比特幣、Litecoin或Namecoin。然而,為不同的加密幣共享相同的空間有一些缺點。
This level creates a separate subtree for every cryptocoin, avoiding reusing addresses across cryptocoins and improving privacy issues.
這個級別為每個加密幣創建一個單獨的子樹,避免在加密幣之間重用地址,並改善了隱私問題。
Coin type is a constant, set for each cryptocoin. Cryptocoin developers may ask for registering unused number for their project.
硬幣類型是一個常量,為每個加密硬幣設置。加密幣開發人員可能會要求為他們的項目注冊未使用的號碼。
The list of already allocated coin types is in the chapter "Registered coin types" below.
已分配硬幣類型的列表在下面“注冊硬幣類型”一章中。
Hardened derivation is used at this level.
硬化的派生在這個級別上使用。(所以右上角有'標記)
Account-一類coin下能夠有多個賬戶,就相當於你的人民幣會存在多張銀行卡中
This level splits the key space into independent user identities, so the wallet never mixes the coins across different accounts.
這個級別將密鑰空間分割為獨立的用戶身份,因此錢包不會將硬幣混合到不同的賬戶中。
Users can use these accounts to organize the funds in the same fashion as bank accounts; for donation purposes (where all addresses are considered public), for saving purposes, for common expenses etc.
用戶可以使用這些賬戶以與銀行賬戶相同的方式組織資金;捐款用途(所有地址均屬公開地址)、儲蓄用途、一般開支等。
Accounts are numbered from index 0 in sequentially increasing manner. This number is used as child index in BIP32 derivation.
以順序遞增的方式從索引0開始編號。這個數字在BIP32派生中用作子索引。
Hardened derivation is used at this level.
硬化的派生在這個級別上使用。(所以右上角有'標記)
Software should prevent a creation of an account if a previous account does not have a transaction history (meaning none of its addresses have been used before).
如果以前的帳戶沒有交易歷史記錄(這意味着以前沒有使用過它的地址),軟件應該防止創建帳戶。
Software needs to discover all used accounts after importing the seed from an external source. Such an algorithm is described in "Account discovery" chapter.
軟件需要在從外部源導入種子之后發現所有使用過的帳戶。在“帳戶發現”一章中描述了這種算法。
Change-表明為外部鏈0或內部鏈1
Constant 0 is used for external chain and constant 1 for internal chain (also known as change addresses). External chain is used for addresses that are meant to be visible outside of the wallet (e.g. for receiving payments). Internal chain is used for addresses which are not meant to be visible outside of the wallet and is used for return transaction change.
常量0用於外部鏈,常量1用於內部鏈(也稱為更改地址)。外部鏈用於在錢包外部可見的地址(例如用於接收付款)。內部鏈用於不在錢包外部可見的地址,用於返回交易更改。
Public derivation is used at this level.
在這個級別使用Public派生。
Index
Addresses are numbered from index 0 in sequentially increasing manner. This number is used as child index in BIP32 derivation.
Public derivation is used at this level.
地址以順序遞增的方式從索引0開始編號。這個數字在BIP32派生中用作子索引。
在這個級別使用Public派生。
⚠️該級的作用是:
被HD錢包衍生的真正可用的地址是第四層級的子級,就是第五層級的樹的“address_index”。
比如,第三個層級的主賬戶如M/44'/0'/1'收到比特幣真正支付的地址是 M/44'/0'/0'/0/2
Account discovery
When the master seed is imported from an external source the software should start to discover the accounts in the following manner:
當主seed從外部源導入時,軟件應該開始以以下方式發現帳戶:
- derive the first account's node (index = 0)導出第一個帳戶的節點
- derive the external chain node of this account 導出該帳戶的外部鏈節點
- scan addresses of the external chain; respect the gap limit described below 掃描外鏈地址(只有外鏈地址外部可見);遵守下面描述的gap = 20的限制
- if no transactions are found on the external chain, stop discovery 如果在外部鏈上沒有發現交易,則停止發現
- if there are some transactions, increase the account index and go to step 1如果有一些交易,增加帳戶索引並轉到第1步(直到發現所有的賬戶)
This algorithm is successful because software should disallow creation of new accounts if previous one has no transaction history, as described in chapter "Account" above.
這個算法是成功的,因為軟件應該不允許創建新帳戶,如果之前的帳戶沒有交易歷史記錄,如上面的“Account”一章所述。
Please note that the algorithm works with the transaction history, not account balances, so you can have an account with 0 total coins and the algorithm will still continue with discovery.
請注意,該算法是根據交易歷史而不是賬戶余額來工作的,因此您可以擁有一個總共只有0枚硬幣的賬戶,並且該算法仍將繼續使用discovery。
Address gap limit
Address gap limit is currently set to 20. If the software hits 20 unused addresses in a row, it expects there are no used addresses beyond this point and stops searching the address chain. We scan just the external chains, because internal chains receive only coins that come from the associated external chains.
地址gap限制目前設置為20。如果軟件連續訪問了20個未使用的地址,它就會認為在此之后的也是沒有使用過的地址,並停止搜索地址鏈。我們只掃描外部鏈,因為內部鏈只接收來自相關外部鏈的硬幣。
Wallet software should warn when the user is trying to exceed the gap limit on an external chain by generating a new address.
當用戶試圖通過生成一個新地址來超過外部鏈的間隙限制時,錢包軟件應該發出警告。
Registered coin types
These are the default registered coin types for usage in level 2 of BIP44 described in chapter "Coin type" above.
All these constants are used as hardened derivation.
以上是BIP44第2級使用的默認注冊硬幣類型,見上文“硬幣類型”一章。
所有這些常數都用作強化派生。
index | hexa | coin |
---|---|---|
0 | 0x80000000 | Bitcoin |
1 | 0x80000001 | Bitcoin Testnet |
This BIP is not a central directory for the registered coin types, please visit SatoshiLabs that maintains the full list:
這個BIP不是注冊硬幣類型的中心目錄,請訪問SatoshiLabs,它維護完整的列表:
SLIP-0044 : Registered coin types for BIP-0044
To register a new coin type, an existing wallet that implements the standard is required and a pull request to the above file should be created.
要注冊新的投幣類型,需要一個實現該標准的現有錢包,並創建對上述文件的pull request。
Examples
coin | account | chain | address | path | subscriptions |
---|---|---|---|---|---|
Bitcoin | first | external | first | m / 44' / 0' / 0' / 0 / 0 | 第一個用於接收比特幣支付的主賬戶的公鑰 |
Bitcoin | first | external | second | m / 44' / 0' / 0' / 0 / 1 | |
Bitcoin | first | change | first | m / 44' / 0' / 0' / 1 / 0 | |
Bitcoin | first | change | second | m / 44' / 0' / 0' / 1 / 1 | |
Bitcoin | second | external | first | m / 44' / 0' / 1' / 0 / 0 | |
Bitcoin | second | external | second | m / 44' / 0' / 1' / 0 / 1 | |
Bitcoin | second | change | first | m / 44' / 0' / 1' / 1 / 0 | |
Bitcoin | second | change | second | m / 44' / 0' / 1' / 1 / 1 | |
Bitcoin Testnet | first | external | first | m / 44' / 1' / 0' / 0 / 0 | |
Bitcoin Testnet | first | external | second | m / 44' / 1' / 0' / 0 / 1 | |
Bitcoin Testnet | first | change | first | m / 44' / 1' / 0' / 1 / 0 | |
Bitcoin Testnet | first | change | second | m / 44' / 1' / 0' / 1 / 1 | |
Bitcoin Testnet | second | external | first | m / 44' / 1' / 1' / 0 / 0 | |
Bitcoin Testnet | second | external | second | m / 44' / 1' / 1' / 0 / 1 | |
Bitcoin Testnet | second | change | first | m / 44' / 1' / 1' / 1 / 0 | |
Bitcoin Testnet | second | change | second | m / 44' / 1' / 1' / 1 / 1 |
實例:
npm install ethereum-bip44 bitcore-lib --save
Create a new wallet:
var bitcore = require('bitcore-lib'); var EthereumBip44 = require('ethereum-bip44'); // create a new master private key var key = bitcore.HDPrivateKey(); // create the hd wallet var wallet = new EthereumBip44(key); // output the first address console.log(wallet.getAddress(0)); //0x6f22a64f04956935202008e5c48f6a8549c9b687 // output the second address console.log(wallet.getAddress(1)); //0x7641ef062d0123361d52a6a2b37eec4721093b75
node incex.js運行出錯:
userdeMBP:test-hd-wallet user$ node index.js /Users/user/test-hd-wallet/node_modules/ethereum-bip44/node_modules/bitcore-lib/index.js:12 throw new Error(message); ^ Error: More than one instance of bitcore-lib found. Please make sure to require bitcore-lib and check that submodules do not also include their own bitcore-lib dependency.
將/Users/user/test-hd-wallet/node_modules/ethereum-bip44/node_modules下的bitcore-lib庫刪掉即可
查看wallet中的xprivkey為'xprv9s21ZrQH143K2fGrRNUdtYfVwgMF2AHtC4FfcFdVXyvXj2qZ373UUp1eDsT86YVpJ1PEzBzWdUjWkept79WaFpbXM6H3N7dXrHswUwPYNbW'
所以也可以用下面的方法:
Initialize from an existing private seed:
// create the hd wallet var wallet = EthereumBip44.fromPrivateSeed('xprv9s21ZrQH143K2fGrRNUdtYfVwgMF2AHtC4FfcFdVXyvXj2qZ373UUp1eDsT86YVpJ1PEzBzWdUjWkept79WaFpbXM6H3N7dXrHswUwPYNbW'); // output the first address console.log(wallet.getAddress(0)); // output the second address console.log(wallet.getAddress(1));
得到的結果是相同的
Initialize it from a public seed, for example on hot wallets that don't hold private keys:
var key = new bitcore.HDPrivateKey(); var derivedPubKey = key.derive("m/44'/60'/0'/0").hdPublicKey; // create the hd wallet var wallet = EthereumBip44.fromPublicSeed(derivedPubKey.toString()); // output the first address console.log(wallet.getAddress(0)); //0x3e7d28a1b8b73a04e8559a77d5422a04e1f0719e // output the second address console.log(wallet.getAddress(1)); //0x48635b1e9ad7e3d622310dc2dddeaa7b32597118