HD Wallets的全称是Hierachical Deterministic Wallets, 对应中文是 分层确定性钱包。

这种钱包能够使用一组助记词来管理所有的账户的所有币种,在比特币的BIP32提案中提出,通过种子来生成主私钥,然后派生海量的子私钥和地址。种子很长,为了方便记录,转换为一组单词记录,这是BIP39提出的。

生成钱包地址的基本流程:1 生成一组助记词 2 助记词转化成种子(通过PBKDF2) 3 种子生成根私钥(通过HMAC-SHA512) 4 通过根私钥生成子私钥

本文的目的是带着读者用代码实现一个HD钱包开发。

开发过程中要用到两个第三方库,一个是Hooked-Web3-Provider,一个是LightWallet。

Hooked-Web3-Provider使用HTTP与geth通信,可以使用秘钥来签署调用交易sendTransaction的实例,因此不需要创建交易数据部分。直接调用sendTransaction完成生成交易数据,发送交易,广播给全网。

LightWallet是一个实现BIP32、BIP39和BIP44的HD钱包。
LightWallet提供API来创建和签署交易,或者使用LightWallet生成的地址和密钥加密和解密数据。它的主要目的是为Hooked-Web3-Provider提供一个签名提供方。它的命名空间有四个,即keystore、signing、encryption和txutils。

signing、encryption和txutils三个命名空间分别用来签名,非对称加密,生成交易,它们的名字大概能反应出各自的功能。keystore命名空间用来生成种子,keystor,这是一个存储加密种子和秘钥的对象。keystore对于其中发现的地址可以自动签名。

HD 钱包中的密钥是用"路径"命名的,且每个级别之间用斜杠(/)字符来表示。由主私钥衍生出的私钥起始以"m"打头。因此,第一个母密钥生成的子私钥是 m/0。第一个公共钥匙是 M/0。第一个子密钥的子密钥就是 m/0/1,以此类推。

密钥的"祖先"是从右向左读,直到你达到了衍生出的它的主密钥。举个例 子,标识符 m/x/y/z 描述的是子密钥 m/x/y 的第 z 个子密钥。而子密钥 m/x/y 又是 m/x 的第 y 个子密钥。m/x 又是 m 的第 x 个子密钥。

代码实现

1. 启动geth网络

假设已经安装好geth。使用命令启动geth网络:

geth --networkid 15 --dev --dev.period 1 --rpc --rpcapi "db,eth,net,web3,miner,personal"   --rpccorsdomain "*" --rpcaddr "0.0.0.0" --rpcport "8545"   console 2>>log

这个命令指定了networkid是15,当然这是随便取的。 --dev --dev.period 1  --dev是开发网络,但是geth后面的版本中为了方便开发,如果不加--dev.period 1 不会自动挖矿。 --rpcaddr "0.0.0.0" 这样设置是为了让所有的网络都能连上geth。 指定端口8545. console表明启动玩登录到控制台。

2.构建前端

项目代码结构(参考《区块链项目开发指南》):

app.js内容如下:

var express = require("express");
var app = express();  app.use(express.static("public"));app.get("/", function(req, res){res.sendFile(__dirname + "/public/html/index.html");
})app.listen(8080);

构建前端的一个node服务。

index.html  页面:

<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><meta http-equiv="x-ua-compatible" content="ie=edge"><link rel="stylesheet" href="/css/bootstrap.min.css"></head><body><div class="container"><div class="row"><div class="col-md-6 offset-md-3"><br><div class="alert alert-info" id="info" role="alert">Create or use your existing wallet.</div><form><div class="form-group"><label for="seed">Enter 12-word seed</label><input type="text" class="form-control" id="seed"></div><button type="button" class="btn btn-primary" οnclick="generate_addresses()">Generate Details</button><button type="button" class="btn btn-primary" οnclick="generate_seed()">Generate New Seed</button></form><hr><h2 class="text-xs-center">Address, Keys and Balances of the seed</h2><ol id="list"></ol><hr><h2 class="text-xs-center">Send ether</h2><form><div class="form-group"><label for="address1">From address</label><input type="text" class="form-control" id="address1"></div><div class="form-group"><label for="address2">To address</label><input type="text" class="form-control" id="address2"></div><div class="form-group"><label for="ether">Ether</label><input type="text" class="form-control" id="ether"></div><button type="button" class="btn btn-primary" οnclick="send_ether()">Send Ether</button></form></div></div></div><script src="/js/web3.min.js"></script><script src="/js/hooked-web3-provider.min.js"></script><script src="/js/lightwallet.min.js"></script><script src="/js/main.js"></script></body>
</html>

重点在main.js

generate_seed函数:
function generate_seed()
{var new_seed = lightwallet.keystore.generateRandomSeed();  //生成一个随机的种子document.getElementById("seed").value = new_seed;   //放到页面generate_addresses(new_seed);
}var totalAddresses = 0;function generate_addresses(seed)
{if(seed == undefined){seed = document.getElementById("seed").value;}if(!lightwallet.keystore.isSeedValid(seed))  //判断种子是否是有效的种子{document.getElementById("info").innerHTML = "Please enter a valid seed";return;}totalAddresses = prompt("How many addresses do you want to generate");  //用户输入想生成的账户的个数if(!Number.isInteger(parseInt(totalAddresses)))   //确保输入是一个数字{document.getElementById("info").innerHTML = "Please enter valid number of addresses";return;}var password = Math.random().toString();   //随机生成一个密码   这个密码可以由用户输入,也可以自动生成。这里为了方便,提升体验,自动生成一个。lightwallet.keystore.createVault({     
//     使用createVault方法创建keystore实例。createVault用一个对象和//     一个回调函数作为参数。对象可以有4种属性:password、seedPharse、// salt和hdPathString。password是必选项,其他的都是可选项。如果不提//     供seedPharse,它会生成和使用一个随机seed。拼接salt与password,以//     提高对称密钥加密技术的安全性,因为攻击者不仅要找到password还得//     找到salt。如果不提供salt,它就会随机生成。keystore命名空间存储未加//     密的salt。hdPathString用于为keystore命名空间提供默认衍生路径,即生//     成地址、签署交易等。如果不提供衍生路径,则使用该衍生路径。如果//     不提供hdPathString,则默认值为m/0'/0'/0'。这个衍生路径的默认目的是//     签名。可以创建新的衍生路径或者使用keystore实例的//     addHdDerivationPath()方法重写当前衍生路径的purpose。还可以使用//     keystore实例的setDefaultHdDerivationPath()方法改变默认衍生路径。// 最后,一旦keystore命名空间被创建,就通过回调函数返回实例。所//     以,这里仅用keyword和seed创建了一个keystore。
password: password,seedPhrase: seed}, function (err, ks) {ks.keyFromPassword(password, function (err, pwDerivedKey) {  //使用这个方法生成对应数量的地址和秘钥if(err){document.getElementById("info").innerHTML = err;}else{ks.generateNewAddress(pwDerivedKey, totalAddresses);var addresses = ks.getAddresses();    var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));  //创建web3和本地的连接,如果是远程把localhost改成对应的ip即可。var html = "";for(var count = 0; count < addresses.length; count++){var address = addresses[count];var private_key = ks.exportPrivateKey(address, pwDerivedKey);  //使用该方法解码和检索地址私钥。var balance = web3.eth.getBalance("0x" + address);html = html + "<li>";html = html + "<p><b>Address: </b>0x" + address + "</p>";html = html + "<p><b>Private Key: </b>0x" + private_key + "</p>";html = html + "<p><b>Balance: </b>" + web3.fromWei(balance, "ether") + " ether</p>";html = html + "</li>";}document.getElementById("list").innerHTML = html;}});});
}

发送eth:

function send_ether()
{var    seed = document.getElementById("seed").value;if(!lightwallet.keystore.isSeedValid(seed)){document.getElementById("info").innerHTML = "Please enter a valid seed";return;}var password = Math.random().toString();lightwallet.keystore.createVault({password: password,seedPhrase: seed}, function (err, ks) {ks.keyFromPassword(password, function (err, pwDerivedKey) {if(err){document.getElementById("info").innerHTML = err;}else{ks.generateNewAddress(pwDerivedKey, totalAddresses);ks.passwordProvider = function (callback) {callback(null, password);};var provider = new HookedWeb3Provider({host: "http://localhost:8545",transaction_signer: ks}); //利用ks做交易的签署者。它调用ks的hasAddress方法和signTransactions方法
var web3 = new Web3(provider);var from = document.getElementById("address1").value;var to = document.getElementById("address2").value;var value = web3.toWei(document.getElementById("ether").value, "ether");web3.eth.sendTransaction({from: from,to: to,value: value,gas: 21000}, function(error, result){if(error){    document.getElementById("info").innerHTML = error;}else{document.getElementById("info").innerHTML = "Txn hash: " + result;}})}});});
}

测试:

到项目根目录,执行 npm install 加载相关库。

执行  node app.js 启动前端服务。端口8080.  访问 localhost:8080

点击 generate new seed  ,输入2,生成两个账户。

然后进入到一开始打开的geth客户端,通过 eth.accounts 查看geth下的账号。复制地址,通过eth.getBalance("XX") 来获取地址余额。

转入一部分余额到上面生成的地址中,例如0xb4c7cf322956f0345b613f246d5d2f4ba03028f6.

eth.sendTransaction({from: "0x8d1c1dd6f48c33c97924e5f310905e1822a6cbd0", to: "0xb4c7cf322956f0345b613f246d5d2f4ba03028f6", value: web3.toWei(100, "ether")})

点击页面的 generate details 刷新,同样的seed会生成同样的账户。

这个时候会发现账户多出100eth。然后可以测试钱包内地址,钱包对钱包外地址转账。

项目giithub地址:https://github.com/figo050518/wallet

转载于:https://www.cnblogs.com/gzhlt/p/10027796.html

分层确定性钱包开发的代码实现(HD钱包服务)相关推荐

  1. 分层确定性钱包 HD Wallet 介绍

    分层确定性钱包 HD Wallet 介绍 文章来源:ConsenLabs 以太坊,区块链(Blockchain), 2017/10/20 14:06 3296 钱包是用于发送和接受代币的客户端,就像我 ...

  2. 分层确定性钱包 HD Wallet 钱包归集

    分层确定性的概念早在 BIP32 提案提出.根据比特币核心开发者 Gregory Maxwell 的原始描述和讨论,Pieter Wuille 在2012 年 02月 11日整理完善提交 BIP32, ...

  3. 数字货币 分层确定性钱包(HD Wallets)

    HD Wallets的全称是Hierachical Deterministic Wallets, 对应中文是 分层确定性钱包. 分层确定性的概念在BIP32提案提出. 根据比特币核心开发者 Grego ...

  4. 分层确定性钱包(HD Wallets)

    HD Wallets的全称是Hierachical Deterministic Wallets, 对应中文是 分层确定性钱包. 分层确定性的概念在BIP32提案提出.根据比特币核心开发者 Gregor ...

  5. 分层确定性钱包-以太坊创建钱包

    基本概念 所有问题大体可以分为三类:区块链基本概念,钱包安全知识以及钱包转账交易 区块链的基本特性 去中心化 因为整个网络没有中心统治者.系统依靠的是网络上多个参与者的公平约束,所以任意每几个节点的权 ...

  6. 代码结构设计得最好的多链支持的 HD 钱包服务端代码

    代码库地址: https://github.com/SavourDao/savour-hd Savour HD 是 Savour 项目的钱包的 HD. 后端服务,使用 golang 编写,提供 grp ...

  7. 数字货币钱包开发需要注意哪些问题?

    10月24日,也就是上周五,国家明确提出要把区块链作为未来科技的主攻方向,从国家层面上,区块链被钦点成未来核心技术创新的突破口,可以肯定的是,区块链技术将在之后加大投入与研究.今日,区块链概念股百股涨 ...

  8. 数字货币HD钱包 BIP32、BIP44、BIP39 简介

    数字钱包概念 钱包用来存钱的,在区块链中,我们的数字资产都会对应到一个账户地址上, 只有拥有账户的钥匙(私钥)才可以对资产进行消费(用私钥对消费交易签名). 私钥和地址的关系如下: (图来自精通比特币 ...

  9. 以太坊钱包开发系列 - 创建钱包账号

    想知道更多关于区块链技术知识,请百度[链客区块链技术问答社区] 链客,有问必答!! 以太坊去中心化网页钱包开发系列,将从零开始开发出一个可以实际使用的钱包,本系列文章是理论与实战相结合,一共有四篇:创 ...

最新文章

  1. 37 windows_37_Thread_InterLock 线程-原子锁
  2. 使用泛型查询数据小例
  3. C/C++中宏使用总结
  4. android call require api level
  5. 递推:Ybtoj: D.4 序列个数
  6. 【渝粤教育】电大中专学前儿童科学教育 (14)作业 题库
  7. 分享GitHub上一些嵌入式相关的高星开源项目
  8. JAVA Swing GUI设计 WindowBuilder Pro Container使用大全2——JPanel使用
  9. 这个“猫窝”太豪华?硅谷宠物猫住1500美元公寓
  10. 两种模式的资源管理器代码之———— 重命名文件夹
  11. myeclipse svn 删除文件或者文件夹
  12. JavaWeb公交调度系统的设计与实现
  13. 泰坦尼克号数据_泰坦尼克号数据分析案例实战
  14. 微信html 全屏显示,关于微信上网页图片点击全屏放大效果
  15. 中国货币供应量全球第一的反思
  16. Hyperf基础使用
  17. 小花经过春雨的一番滋润
  18. 南理工计算机学院贾修一,南京理工大学考研研究生导师简介-贾修一
  19. 视觉中国财报背后的版权门余波
  20. 记录一次Specified key was too long的问题

热门文章

  1. Android 打造万能圆点指示器
  2. Google Calendar 跨平台同步方案(随时同步手机与电脑的日程安排)
  3. gazebo学习时遇到的问题(PX4篇)
  4. 量化交易面临的十大难题,你遇到几个?
  5. html5 容器上下居中显示,移动端常见问题(水平居中和垂直居中)
  6. 2022年信息安全工程师考试知识点:电子商务安全
  7. SVGEdit——SVG在线编辑器
  8. C#使用ODAC向Oracle数据库插入海量实时数据
  9. CT影像中肺结节自动检测算法的验证、比较和组合:The LUNA16 challenge
  10. BAL数据集格式解读