多币种HD钱包地址生成方法
目前,多币种HD钱包十分流行,比如bitpie、imtoken、cobo wallet等。用户可以使用一组助记词同时管理多个币种的地址。那么,这些不同币种的地址是如何通过同一组助记词获得的呢?这是本文将主要讨论的问题。
多币种HD钱包通常采用BIP44定义HD钱包路径字段,赋予树状结构中的各层特殊的意义,从而支持多币种、多账户。BIP44中定义的路径含义为:
m / purpose' / coin_type' / account' / change / address_index
其中,purpose'
固定是44'
,代表使用BIP44;coin_type'
用来表示不同币种,例如Bitcoin就是0'
,Bitcoin Testnet是1'
,Ethereum是60'
;account'
表示账户编码;change
用来表示该地址是否为找零地址;address_index
为地址编号。特别地,Bitcoin Segwit(隔离验证)中purpose'
固定是49'
。
下面,我们将基于bitcore-lib
和bitcore-mnemonic
两个库来演示如何生成Bitcoin普通地址、Bitcoin隔离验证地址、Ethereum地址以及OByte地址。
首先,我们引入相关的库文件,并生成HD钱包的助记词及扩展私钥:
var Mnemonic = require('bitcore-mnemonic');
var Bitcore = require('bitcore-lib');
var KeccakHash = require('keccak');
var ObjectHash = require('ocore/object_hash');
// 生成助记词
var mnemonic = new Mnemonic();
// HD钱包扩展私钥、扩展公钥
var xPrivKey = mnemonic.toHDPrivateKey();
var xPubKey, pubKey, address;
Bitcoin普通地址
只需要根据BIP44路径生成相应的公钥,并获取相应的地址即可,具体细节可以参考Mastering Bitcoin 2nd Edition第4章。
// Bitcoin普通地址,change=0,address_index=0
xPubKey = Bitcore.HDPublicKey(xPrivKey.derive("m/44'/0'/0'"));
pubKey = xPubKey.derive('m/0/0').publicKey;
address = pubKey.toAddress();
console.log('Bitcoin普通地址:' + address.toString());
Bitcoin隔离验证地址
与Bitcoin普通地址不同,隔离验证地址所使用的BIP44路径中purpose
为49'
,且通常采用P2SH地址来表示。P2SH脚本的构成为OP_0
加上公钥哈希,具体细节可以参考Mastering Bitcoin 2nd Edition第7章
// Bitcoin隔离见证地址,change=0,address_index=0
xPubKey = Bitcore.HDPublicKey(xPrivKey.derive("m/49'/0'/0'"))
pubKey = xPubKey.derive('m/0/0').publicKey;
var script = new Bitcore.Script();
script.add(Bitcore.Opcode.OP_0);
script.add(pubKey.toAddress().hashBuffer);
address = Bitcore.Address.payingTo(script);
console.log('Bitcoin隔离见证地址:' + address.toString());
Ethereum地址
Ethereum地址的生成过程与Bitcoin类似,只有以下几个方面有所区别:
- BIP44路径中
coin_type'
为60'
; - 只使用未压缩的公钥;
- 哈希采用的是keccak256。
具体细节可以参考Mastering Ethereum第4章。
// Ethereum地址,change=0,address_index=0
xPubKey = Bitcore.HDPublicKey(xPrivKey.derive("m/44'/60'/0'"))
pubKey = xPubKey.derive('m/0/0').publicKey;
var pubUnCompressed = pubKey.point.x.toString('hex') + pubKey.point.y.toString('hex');
var pubKeyHash = KeccakHash('keccak256').update(Buffer.from(pubUnCompressed, 'hex')).digest('hex');
address = '0x' + pubKeyHash.slice(-40);
console.log('Ethereum地址:' + address);
OByte地址
OByte地址的公钥与Bitcoin一样,只是采用了不同的哈希方法,且地址采用Base64编码。具体细节可以参考ByteBall钱包详解。
// Obyte普通地址,change=0,address_index=0
xPubKey = Bitcore.HDPublicKey(xPrivKey.derive("m/44'/0'/0'"));
var pubKey = xPubKey.derive('m/0/0').publicKey;
var arrDefinition = ["sig", {"pubkey": pubKey.toBuffer().toString('base64')}];
address = ObjectHash.getChash160(arrDefinition);
console.log('OByte地址:' + address);
版权所有。发布者:Alan During,转载请注明出处:https://bbfans.org/2019/04/14/hd-wallet-address/