Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

DAGX钱包详解

一夜雨十年灯潞
164 0 0
钱包结构
7 q7 H2 S  M8 i$ b) Z9 O顾名思义,钱包是用来保存钱的。但在数字货币的世界中,钱包里面并没有“钱”。钱包账户里有多少“钱”都是记录在区块链上的,钱包里只是存储了账户对应的私钥,账户是从私钥相应的公钥衍生出来的。只要有了私钥,你就可以在数字货币世界里证明你的身份,发送区块链上属于你的资产。因此,钱包实际上是管理和存储私钥的工具。1 |8 h9 m- B9 R1 L" W
Dagx钱包结构与Bitcoin类似,Bitcoin对管理和存储私钥以及通过私钥生成地址制定了一系列标准(BIP, Bitcoin Improvement Proposals),主要包括:- C3 \/ s1 p2 I+ L& r6 u: x9 H
· BIP32:定义了HD钱包(Hierarchical Deterministic Wallet),允许从单一种子产生一树状结构储存多组私钥和公钥,可以方便的备份、转移以及分层权限控制等。HD钱包包含以树状结构衍生的密钥,使得父密钥可以衍生一系列子密钥,每个子密钥又可以衍生出一系列孙密钥,以此类推,无限衍生。下图展示了HD钱包的树状结构:
& M! ~  ^' H3 d8 x  o/ d4 c3 P% l& v/ V7 E  ?5 I
BIP39:将种子用方便记忆和书写的单词表示,一般由12个单词组成,称为助记词或助记码。由一系列单词生成种子是个标准化的方法,这样易于在钱包中转移、导出和导入。比如shrimp make call path pink draw gym song select brother social base,其相应的私钥为
- j! b& d3 P" j" f; D3 fxprv9s21ZrQH143K4HQ8sBPNNkXHNuVYfivR96gtpJzMWCJVF5hdYjzT5nVQu6GfHAQLPstQtFp9GTWADUcKgzaV5EyL5JxT2rxkyg51ReGTVg8。
& h! r" {8 j$ W6 S3 Q( g' DBIP43:为HD钱包路径引入purpose字段,路径记作m / purpose’ / *,比如m / 0’ / *表示BIP32的默认账户。+ i( Q  K2 ^9 _
BIP44:定义HD钱包路径字段,赋予树状结构中的各层特殊的意义,从而支持多币种、多账户,路径定义为:8 A; K$ q' |- b2 Y. j
m / purpose' / coin_type' / account' / change / address_index7 t& p  k: Q9 v. m. D1 v; C3 i
其中,purpose’固定是44’,代表使用BIP44;coin_type’用来表示不同币种,例如Bitcoin就是0’,Bitcoin Testnet是1’,Ethereum是60’;account’表示账户编码;change用来表示该地址是否为找零地址;address_index为地址编号。+ a/ |0 \; i; u  e) P! S
BIP45:定义多签名HD钱包路径字段,从而支持多签名地址,路径定义为:4 F- d9 r0 k" X
m / purpose' / cosigner_index / change / address_index
# j0 R: \. I9 O) _5 _' J7 c0 F. N) K" ?其中,purpose固定是45’,代表使用BIP45;cosigner_index表示多签名用户编号;其余字段与BIP44相同。- W2 E  Z; V! F
Dagx钱包采用的是符合BIP44标准的HD钱包,其采用的路径结构为:
$ E: }, N6 x! g" Q# @. Y3 E1 Y5 N0 e7 Am / 44’ / 0’ / account’ / change / address_index% g+ l  R$ j* V

9 M3 l1 ^% E. T7 l9 S$ S此外,除了使用account来标识账户外,还使用了该账户公钥的哈希值对账户进行唯一表示,表示方法为:
$ P6 M; k$ b; D5 F' pvar wallet = crypto.createHash(“sha256”).update(xPubKey, “utf8”).digest(“base64”);
: ^/ ~6 g+ x. U4 mDagx中还有一类特殊的地址,即设备地址,其采用的路径结构为:$ u, ]9 r% @9 C/ [* _+ y
m / 1’ / *( I, M/ R7 y' L" ?  Z8 Z+ _) m
Dagx钱包使用了bitcore-lib和bitcore-mnemonic两个库进行钱包管理,简单的使用方法如下:
5 \; s# o6 H( d4 q' l  p var Mnemonic = require('bitcore-mnemonic');5 e+ P9 M3 r% X
    var Bitcore = require('bitcore-lib');6 P( ^, c, U6 H  i& {
// 生成助记词6 ~- O/ {! t# o; A9 X
 , |1 X. M( w1 }+ Q3 m" [
// 'fee decorate step culture autumn game social very lemon drum embrace much'3 }( J2 h. @8 N! t
 
2 C! A9 c0 {+ B- K9 E: ?# \var mnemonic = new Mnemonic();
6 p6 t$ @. w+ ?: Z4 i4 d0 f5 G 
7 g8 E/ a* P4 U2 z( ]8 f// 生成HD钱包私钥. r$ ~2 t0 y- Y: r% y9 J
 4 |6 m- q. h! N7 }! K
//
5 T. w6 s( G; y8 G. d0 v2 Y . f2 |. D2 K+ k' k+ ~6 |
var xPrivKey = mnemonic.toHDPrivateKey(); ) y! [' ^# e. w* y" C. i
 1 v! v' V' k5 i" ~" C0 W
// 生成HD钱包公钥,account=0
$ S0 D' u, V4 |) E 
4 H4 Q5 @& D/ K  x8 H4 n// + ^5 ^/ R# d$ c+ g, y
 
: v- D* q3 \6 \0 _0 `5 b2 z! Tvar xPubKey = Bitcore.HDPublicKey(xPrivKey.derive("m/44'/0'/0'")); . i5 `3 V) M/ P$ d; }: d- h1 o
 ! b( e" a5 [0 b5 h$ Y( E1 G
// 生成设备私钥,用于产生设备地址( ?) H( G5 V1 S  W
 $ }1 P" ?8 r. [6 A
//
" q1 m; o9 o$ I+ `1 U9 f0 P 7 }1 z: |7 ^3 X( ]! r# p2 F2 _
var devicePrivKey = xPrivKey.derive("m/1'");
' l1 ~) t& F$ b, V( j 4 O/ O4 [3 z" U2 W* }
地址生成
7 u) _# q2 ?1 B/ G2 u' a; D# ODagx中包括三类地址:
5 i, O) N1 l/ D( r: d( y· 普通地址
) M' Z5 h9 K' s: v/ o8 a· 共享地址' G2 p, F2 A! j
· 设备地址
% I  I1 ]# j7 m' q其中,普通地址和共享地址都是通过地址定义脚本生成的,二者的区别类似于Bitcoin中的P2PKH地址和P2SH地址,具体细节可参考《Dagx原理解析(三)地址、脚本及合约》;设备地址是采用设备公钥生成的,地址格式和校验规则与普通地址相同,只是前缀添加了0。( w% J6 F& B! z2 v& c7 f4 l
给定需要生成地址的对象,Dagx生成地址时采用的是ripemd160哈希,并给地址加上校验,使用的是Dagxcore/object_hash.js中的函数getChash160()函数。
, c3 _8 d8 L" B具体来说,设备地址生成方法:  _6 D0 y- j6 ^2 D" t1 s
var ecdsa = require('secp256k1'); // 椭圆曲线非对称加密7 w7 v' r2 P( I7 H. n! A1 z, y: q
 
' [! r7 Z1 `) g) [// 获取设备公钥2 C3 s+ S2 O* [2 t9 s6 ^8 _; d
 
' Z$ R0 l& s) n8 y' A4 lvar pubkey = ecdsa.publicKeyCreate(devicePrivKey.privateKey.bn.toBuffer({size:32}), true).toString('base64');
/ R" g- \7 J  P3 e' T4 `5 q 
9 U1 u0 Q1 q$ e+ A// 生成设备地址
4 V3 X5 Q" D& c8 Z" @( F 
& q: h+ |) R- Jvar objectHash = require('Dagxcore/object_hash.js');
5 ?/ g& ~, c7 n# i( p 
3 U9 z/ b& p/ A2 t" ~& S- avar device_address = '0' + objectHash.getChash160(pubkey);
2 H0 w9 s8 ^  X  f* ^: y普通地址生成方法:6 U' t- g$ ~5 ^4 p  Q
// change=0 address_index=0,生成公钥3 q9 d& G9 G( `0 f7 O. X- V( o8 v
 * X" H  ^& g8 K/ k! p6 ]
var pubkey = xPubKey.derive('m/0/0').publicKey.toBuffer().toString('base64');
- d, V2 T6 J2 E; W, s" U 
2 X; `1 I; |: w4 E7 ]5 a. j- Q// 设定地址定义脚本,为单签名
& H2 x! h1 z& B 1 S# i' o/ n# ?/ ]
var arrDefinition = ["sig", {"pubkey": pubkey}];
" G9 }% n! m# O  A' ~* h7 B# x+ Y 
  S$ E" m* N* @$ H, ~4 }5 w' D# x// 生成地址
( ^, o2 E8 [. H2 _5 H0 V1 V 
( j/ j- C8 f) O. U: m3 i$ a6 fvar address = objectHash.getChash160(arrDefinition);
! h: d, w; _+ B! f# k% A共享地址的生成方法与普通地址基本一致,唯一的差别在于地址定义脚本要更加复杂一些。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

一夜雨十年灯潞 初中生
  • 粉丝

    0

  • 关注

    7

  • 主题

    11