1. 字节雪球爱好者社区首页
  2. 技术应用

多币种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-libbitcore-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路径中purpose49',且通常采用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/

发表评论

登录后才能评论

联系我们

加入ByteBall技术群请添加

QR code