[币严BIZZAN区块链]数字货币交易所钱包对接之比特币(BTC)
在币严BIZZAN开发数字货币交易所的过程中,一共有两大难点,一个是高速撮合交易引擎,另一个是钱包对接,这两者是我们团队以前没有接触过的。这个系列的文章主要介绍数字货币交易所钱包对接实现技术。第一个要对接的是比特币BTC,因为BTC的提现过程比较简单,用户在交易所提交提币需求,然后由交易所进行审核,接着进行系统打币或者人工打币。
交易所对接比特币钱包的方式
交易所对接比特币钱包的方式有两种:
1. 自建BTC节点
BTC的节点支持通过RPC的方式进行访问,因此自建一个节点可以很快速对区块和交易进行查询。但是因为BTC节点会同步所有区块,截至到现在(2018/09/10)的区块高度已达500000,因此这需要大量的硬盘存储空间,16年就已需要至少160G。如果每个币种都自建节点,耗费的硬盘存储空间会很大,并且要承担维护节点的工作。而初创团队对资金的合理利用要求比较高,因此,我们舍弃了这种方式,而采用了第二种方式。
2. 第三方API+区块链浏览器
通过第三方API可以对比特的钱包进行操作,如生成密钥对、打币等。同时通过区块链浏览器提供的开放接口也可以进行交易的查询。因此我们团队采用了这种方式对接比特币钱包。
比特币钱包知识点
1.比特币钱包密钥生成
这里需要了解的知识点是比特币钱包:首先、比特币钱包可以离线生成,通过一系列的加密运算过程,如果你不嫌麻烦也可以自己去实现,但是没必要重复造轮子;其次、比特币钱包离线生成也可以保证不重复。你不用担心比特币地址会用完,因为理论上比特币钱包可以生成地址数量比宇宙中所有原子加起来的数量都多,所以担心离线生成的钱包地址与别人重复这种担心是完全没必要的。
2.比特币网络中没有账户概念
如果你接触过以太坊,就知道以太坊有账户概念,账户这个概念更加贴近于我们现实生活,有了账户就可以看到余额。但是比特币没有这样的概念,感兴趣的可以去研究一下比特币里的UTXO。比特币只有交易,那你很好奇,只有流水账那怎么知道一个地址的余额的?比特币是通过计算你的钱包地址所有转入与所有转出之间的差值来计算出来的。你可能还想问,要转账给某个地址10个比特币的过程是怎样的?首先比特币网络会将你当前余额计算出来,看看够不够转,如果够,那么比特币网络会把以前转入你地址的交易所谓输入,也就是input,再把你转入到其他地址的交易作为输出,也就是output。我们从区块链浏览器blockchain.info提供的API可以查询到下面这样的结果:
{
"hash":"b6f6991d03df0e2e04dafffcd6bc418aac66049e2cd74b80f14ac86db1e3f0da",
"ver":,
"vin_sz":,
"vout_sz":,
"lock_time":"Unavailable",
"size":,
"relayed_by":"64.179.201.80",
"block_height, 12200,
"tx_index":"",
"inputs":[
{
"prev_out":{
"hash":"a3e2bcc9a5f776112497a32b05f4b9e5b2405ed9",
"value":"",
"tx_index":"",
"n":""
},
"script":"76a914641ad5051edd97029a003fe9efb29359fcee409d88ac"
}
],
"out":[
{
"value":"",
"hash":"29d6a3540acfa0a950bef2bfdc75cd51c24390fd",
"script":"76a914641ad5051edd97029a003fe9efb29359fcee409d88ac"
},
{
"value":"",
"hash":"17b5038a413f5c5ee288caa64cfab35a0c01914e",
"script":"76a914641ad5051edd97029a003fe9efb29359fcee409d88ac"
}
]
}
查询链接:https://blockchain.info/rawtx/b6f6991d03df0e2e04dafffcd6bc418aac66049e2cd74b80f14ac86db1e3f0da
上面是查询一个交易(Transaction)查询到的结果,可以看到其中int和out包含多条结果。
交易所充值逻辑设计
上图是交易所充值逻辑的设计图,下面简单说一下流程:
首先、我们通过比特币钱包API批量生成如10000个比特币钱包地址。当用户在交易所中获取自己的BTC充值地址时,我们从这10000个地址中为他分配一个(地址绑定UID)
然后、我们会事先运行一个监听任务程序,这个程序负责从比特币区块链浏览器获取最新的区块信息,然后解析其中的交易涉及到的地址,当发现output中出现我们已分配的地址时,我们就为这个地址绑定的用户资产表中添加BTC余额。
最后、提醒用户充值到账。
实现方法代码演示(Java)
1. 通过第三方钱包API生成比特币地址:
这里我们使用的是开源代码bitcoinj,通过maven导入这个库,示例代码如下
import java.io.File;
import java.io.IOException; import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.params.TestNet3Params;
import org.bitcoinj.wallet.Wallet;
/**
* 演示生成/保存密钥对和钱包地址到文件
* @author bizzan.com
*
*/
public class GenerateKeyPair { public static void main(String[] args) { // 如在主网中生成钱包密钥对,需要改为MainNetParms
NetworkParameters params = TestNet3Params.get(); Wallet wallet = null;
// 创建一个文件用于保存钱包文件
final File walletFile = new File("test.wallet"); wallet = new Wallet(params); // 循环生成10个密钥对并添加到钱包
for(int i = 0; i < 10000; i++) {
ECKey key = new ECKey();
wallet.importKey(key);
}
try {
// 保存钱包文件
wallet.saveToFile(walletFile);
// 打印钱包内容信息
System.out.println(wallet.toString(true, true, true, null)); } catch (IOException e) {
e.printStackTrace();
}
}
}
通过这段代码就可以生成10000个钱包地址,你可以把它保存在文件里。实际应用时,你还需要把10000个钱包地址保存到数据库中,但是私钥千万不要保存到联网数据库中。
通过下面的代码可以读取你保存到文件里的钱包内容:
import java.io.File; import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.params.TestNet3Params;
import org.bitcoinj.wallet.UnreadableWalletException;
import org.bitcoinj.wallet.Wallet; /**
* 从文件导入钱包,注意需要先运行GenerateKeyPair生成钱包文件
* @author bizzan.com
*
*/
public class ImportWalletFromFile { public static void main(String[] args) {
// 如在主网中生成钱包密钥对,需要改为MainNetParms
NetworkParameters params = TestNet3Params.get(); Wallet wallet = null;
// 创建一个文件用于保存钱包文件
final File walletFile = new File("test.wallet"); try {
// 从文件加载钱包
wallet = Wallet.loadFromFile(walletFile);
// 打印钱包信息
System.out.println(wallet.toString(true, true, true, null)); // 获取钱包第一个密钥对
ECKey firstKey = wallet.getImportedKeys().get(0);
// 打印密钥对信息
System.out.println("The first key is: \n" + firstKey.toString());
// 打印密钥对中的私钥(HEX)
System.out.println("The first key Private Key(HEX) is: " + firstKey.getPrivateKeyAsHex());
// 打印密钥对中的私钥(WIF=Wallet Import Format)
System.out.println("The first key Private Key(WIF) is: " + firstKey.getPrivateKeyAsWiF(params));
// 打印密钥对中的公钥:
System.out.println("The first key Public Key is: " +firstKey.getPubKey());
// 打印密钥对中的公钥(HEX)
System.out.println("The first key Public Key(HEX) is: " + firstKey.getPublicKeyAsHex());
// 打印密钥对中的公钥(Hash)
System.out.println("The first key Public Key(Hash) is: " + firstKey.getPubKeyHash());
// 打印密钥对钱包地址
System.out.println("The first key Wallet Address is: " + firstKey.toAddress(params)); // 通过公钥查找密钥对:findKeyFromPubHash(byte[] pubkeyHash)
ECKey resultKey1 = wallet.findKeyFromPubHash(firstKey.getPubKeyHash());
System.out.println("Find Key From PubHash: " + resultKey1.toString());
// 判断公钥是否在钱包:isPubKeyHashMine(byte[] pubkeyHash)
System.out.println("Is PubKeyHash Mine: " + wallet.isPubKeyHashMine(firstKey.getPubKeyHash()));
// 通过公钥查找密钥对:findKeyFromPubKey(byte[] pubkey)
ECKey resultKey2 = wallet.findKeyFromPubKey(firstKey.getPubKey());
System.out.println("Find Key From PubKey: " + resultKey2.toString());
// 判断公钥是否在钱包:isPubKeyMine(byte[] pubkey)
System.out.println("Is PubKey Mine: " + wallet.isPubKeyMine(firstKey.getPubKey()));
} catch (UnreadableWalletException e) {
e.printStackTrace();
}
}
}
2. 通过区块链浏览器监听钱包地址:
通过轮询的方式,如每隔1个小时查询一次区块链浏览器,获取最新的区块信息,再对其中的地址信息进行解析,示例代码如下:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream; import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; /**
* 演示通过Blockchain.info提供的JSON Http获取比特币区块信息
* @author bizzan.com
*
*/
public class ApiApp { private final static String requstHttpUrl = "https://blockchain.info/"; public static void main(String[] args) {
String param = "block-height/500000?format=json";
String result = sendGet(requstHttpUrl, param); JSONObject jsonObject = JSONObject.parseObject(result);
JSONArray arr = jsonObject.getJSONArray("blocks"); JSONArray txList = arr.getJSONObject(0).getJSONArray("tx");
for(int i = 0; i < txList.size(); i++) {
JSONObject txObj = txList.getJSONObject(i);
JSONArray outs = txObj.getJSONArray("out");
for(int j = 0; j < outs.size(); j++) {
JSONObject outObj = outs.getJSONObject(j);
// 这里已获取交易信息(包含收币地址信息),由此可将此地址与充值地址库对比,进行充值后续工作
System.out.println("tx_index:" + outObj.getIntValue("tx_index") + " - addr:" + outObj.getString("addr"));
}
}
} public static String sendGet(String url, String param) {
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
String result = "";
try {
httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url + param);
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)
.setConnectionRequestTimeout(35000)
.setSocketTimeout(60000)
.build();
httpGet.setConfig(requestConfig);
response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
result = EntityUtils.toString(entity);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != response) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != httpClient) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
}
上面的代码是获取高度为500000的区块信息,并对其中的地址进行解析。
BIZZAN(币严) 数字货币交易所官方网址:
www.bizzan.com
[币严BIZZAN区块链]数字货币交易所钱包对接之比特币(BTC)的更多相关文章
- [币严BIZZAN区块链]Java生成ETH钱包助记词、私钥、地址
本文主要介绍在Java工程中如何生成ETH钱包的助记词.私钥.地址. 一.在之前创建的spring boot 项目中的 pom.xml文件中加入需要的依赖 <dependency> < ...
- [币严区块链]数字货币交易所之比特币(BTC)钱包对接 | 自建节点JSON-RPC访问
BTC钱包对接流程 一. 部署BTC钱包节点 二. 分析BTC钱包的API 三. 通过JSON-RPC访问BTC钱包API 四. 部署测试 一.部署钱包节点 交易平台对接BTC之前,要 ...
- [币严区块链]数字货币交易所之以太坊(ETH)钱包对接(四) 使用web3j对接以太坊钱包
本文给大家介绍了 Web3j Java 版本的框架的基本使用,大家可根据本文的内容进行扩展性的练习,对其他 API 的使用进行尝试. 使用web3j对接以太坊钱包 一.开发准备事项 启动 Geth 此 ...
- [币严区块链]数字货币交易所之瑞波(XRP)钱包对接
对接Ripple(XRP),不需要本地部署钱包,直接访问Ripple API,本文包括访问Ripple API及如何免费获取测试的XRP. 对接流程 安装Ripple API Ripple API 接 ...
- 重磅!Panda Global获悉立陶宛下周将发行区块链数字货币!
近日,Panda Global从路透社获悉,立陶宛将在下周开始预售2.4万枚由央行发行的数字货币.该名为LBCoin的数字货币基于区块链技术生产,也是该国试点具有国家支持背景的数字货币和区块链技术的项 ...
- 数字货币交易所(火币为例)如何使用二次验证码/虚拟MFA/两步验证/谷歌验证器?
一般点账户名——设置——安全设置中开通虚拟MFA两步验证 具体步骤见链接 数字货币交易所(火币为例)如何使用二次验证码/虚拟MFA/两步验证/谷歌验证器? 二次验证码小程序于谷歌身份验证器APP的优 ...
- 免费开源数字货币交易所——基于Java开发的比特币交易所 | BTC交易所 | ETH交易所 | 数字货币交易所
本项目是基于Java开发的比特币交易所 | BTC交易所 | ETH交易所 | 数字货币交易所 | 交易平台 | 撮合交易引擎.本项目基于SpringCloud微服务开发,可用来搭建和二次开发数字货币 ...
- 程序员的自我救赎---12.2.3: 虚拟币交易平台(区块链) 下 【C#与以太坊通讯】
<前言> (一) Winner2.0 框架基础分析 (二)PLSQL报表系统 (三)SSO单点登录 (四) 短信中心与消息中心 (五)钱包系统 (六)GPU支付中心 (七)权限系统 (八) ...
- 全球数字货币交易所TOP20安全性评级报告
链塔智库2018-05-03 10:28 分析师:常昊.王婧雯 来源: 链塔智库 全球加密数字货币市值超2.5万亿元,单日交易额超2000亿元,全球超过3000万人已投入加密数字货币领域. ...
随机推荐
- pikachu
题目链接:http://127.0.0.1/pikachu-master/vul/sqli/sqli_id.php 题目来源:pikachu-->SQL-inject-->数字型注入(po ...
- (七)c#Winform自定义控件-进度条
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...
- 章节十六、1-TestNG简介
一.TestNG 介绍 1.TestNG 是一个来自 JUnit 和 NUnit 的测试框架,它具拥有更多的功能,提高了 执行的效率. 2.TestNG 是一个开源的自动化测试框架 去除了老框架的大部 ...
- 决策树ID3原理及R语言python代码实现(西瓜书)
决策树ID3原理及R语言python代码实现(西瓜书) 摘要: 决策树是机器学习中一种非常常见的分类与回归方法,可以认为是if-else结构的规则.分类决策树是由节点和有向边组成的树形结构,节点表示特 ...
- Linux云计算高端架构师+DevOps高级虚拟化高级进阶视频
课程大纲 1.开班典礼(1)_rec.mp4 2.开班典礼(2)_rec.mp4 3.开班典礼(3)_rec.flv 4.Linux操作系统系统安装及启动流程(1)_rec.flv 5.Linux操作 ...
- Redis集群环境下的键值空间监听事件实现方案
一直想记录工作中遇到的问题和解决的方法,奈何没有找到一方乐土,最近经常反思,是否需要记录平时的点滴,后台还是决定下定决心记录一些,以便以后用到的时候找不着,实现这样的一个功能主要也是业务所需要的. 需 ...
- HBase 系列(六)——HBase Java API 的基本使用
一.简述 截至到目前 (2019.04),HBase 有两个主要的版本,分别是 1.x 和 2.x ,两个版本的 Java API 有所不同,1.x 中某些方法在 2.x 中被标识为 @depreca ...
- 剑指Offer(二十一):栈的压入、弹出序列
剑指Offer(二十一):栈的压入.弹出序列 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/b ...
- 配置Office Excel运行Python宏脚本
基本环境 名称 版本 操作系统 Windows 10 x64 Office 2016 安装Python 1.下载Python安装包 登录https://www.python.org/downloads ...
- Leetcode之二分法专题-852. 山脉数组的峰顶索引(Peak Index in a Mountain Array)
Leetcode之二分法专题-852. 山脉数组的峰顶索引(Peak Index in a Mountain Array) 我们把符合下列属性的数组 A 称作山脉: A.length >= 3 ...