【Bitcoin系列】HD钱包
通过“Tiny熊”的文章弄明白了BIP32, BIP39提议,我再用自己的语言讲一下HD钱包,并添加一些其他内容。
HD钱包的英文是Hierarchical deterministic wallets[1],它保存的密钥呈树形结构,只要保存seed就能生成所有地址的密钥,给钱包的管理带来了很大方便。
避免重用地址
使用dumpwallet
命令将bitcoin core的钱包导出明文后,可以看到有2000多个密钥和地址。
为什么我们需要这么多的地址呢?
避免地址重用。
地址重用是指在多次交易使用相同的地址,因为区块链的账本是公开的,重用地址会暴露自己的信息[2],跟你发生过交易的人只要记住你的地址,就能查到你的交易记录和账户余额。
和银行不同的是,创建比特币地址是不花钱的,电脑分分钟就能创造成千上万个地址,甚至不需要连接到网络。不过由于比特币分散在多个地址,转账时可能需要输入多个地址来凑够数。从而交易在区块中会占用更多空间,交易费会更高,现在的交易费是 7 sat/B ($0.05) 。
钱包管理
每次交易都使用新地址,那就需要很多地址,这会给管理带来一些麻烦。比如:
-
“冷钱包”的备份:
“冷钱包”是一种很安全的保管方式,但是一堆私钥,抄写很麻烦,而且可能会抄错。即使用打印机打印出来了,导入到电脑也很困难。 -
钱包的导入:
bitcoin的钱包有很多种[3],比如我现在用的是bitcoin core,但我想换一种钱包试试,比如Electrum或者Armory或者Bitcoin Knots。我该怎么把现在钱包中的密钥列表导入到新的软件呢?
bitcoin core的密钥都保存在wallet.dat
文件,但是其他钱包并不一定能解析这个文件。而手动输复制粘贴不仅麻烦,也容易出错。
BIP32——Hierarchical Deterministic Wallets
为了解决密钥管理的问题,有了BIP32提议,即Hierarchical Deterministic Wallets(HD钱包)。
这个方案提出使用种子生成树形结构的密钥,备份钱包时只需要记录种子,导入钱包时也只需要输入种子。
生成树形结构的密钥的过程是:
- 将一个种子通过HMAC-SHA512算法生成512位的hash
- 将hash拆成左右2半,作为2个私钥
- 得到的2个私钥再分别用HMAC-SHA512算法得到512位的hash
- 再将hash拆成左右2半,作为2个私钥
- 不断重复,就能得到无数个私钥
有了这些私钥后,可以通过椭圆曲线生成公钥,再用公钥生成地址。
需要备份的话,只需要将种子抄在纸上就可以了。
导入钱包时,也只需要将种子输入钱包,钱包可以通过上面的过程得到所有的密钥。
种子是一段几百位的二进制数,如果用Base58编码的话其实也挺短的。不过为了进一步适应人的习惯,提高可读性,社区又提出了BIP39提议,将种子转换成一串单词,称为助记词(Mnemonic code)[4]。
BIP39——Mnemonic code
比如可以将下面32位的16进制数,编码成12个单词。
// 随机数种子
090ABCB3A6e1400e9345bC60c78a8BE7
// 助记词种子
candy maple cake sugar pudding cream honey rich smooth crumble sweet treat
这些单词是有范围的,并不是所有的单词都会出现在编码结果中。BIP39挑选了2048个区分度够大的单词/字,中文版、英文版的都有。
每个单词/字都对应一个0~2047的数字,可以转换成11位的二进制数,12个单词则可以转换成12*11=132个二进制数。
反过来,132位二进制数也可以转换成12个单词(单词范围是2048个)。
32位的16进制数,可以转换成32*4=128个二进制数。
132比128多出了4个,为什么呢?这是对前面128数的hash的前4个数,用于提高可靠性。
bitcoin-qt
打开bitcoin-qt,可以看到右下角显示HD,表示启用了HD钱包。
使用bitcoin-qt转账时,只需要输转入地址,不需要填转出地址。bitcoin-qt会自动帮你从地址列表中挑选出有足够余额的地址转账,或者将几个地址凑够数转账。挑选地址时,会考虑尽量减少在区块中占用的空间,减少交易费。
bitcoin-qt会显示当前的余额,这个余额指的是钱包中所有地址总共的余额。