万事开头难啊,经历了几天的反复试错和各种尝试终于成功实现了JSON-RPC接口,获取Bitcoin的数据。可以开开心心的获取数据进行分析研究了,下面记录一下我的心路历程。
比特币开发者的 API
首先明确我的目是要获取Bitcoin区块链中的数据。一开始理所当然的想,会不会有第三方的接口可以直接调取,得到这些数据呢?这非常符合一个程序员的思维(其实就是懒)。于是我找到了 blockchain.info,果然里面提供了丰富的获取区块链数据的工具:
- Blockchain钱包API
- Blockchain 钱包 API。用API从 Blockchain 的钱包账户来发送和接收付款。
- Bitcoin-Qt 兼容的 JSON RPC。Blockchain.info 能够协助商户使用钱包账户从事商业活动的比特币化 RPC 服务器。
- 创建钱包。以编程方式为您的用户创建钱包,您亦能加载和兑换资金。
- 在交易记录和区块上的数据
- Blockchain 数据 API。查询 json 区块上的数据和交易。您在此网站看到的几乎所有的数据都可用以 JSON 格式。
- 简单查询 API。为查询区块链数据的简单纯文本 API。
- Websocket。低延迟流套接字通道提供了新的区块和交易数据。订阅新区块、交易记录、某个地址和接收JSON描述某个事件发生时的交易或区块的消息。
并且Blockchain.info提供多种语言的 官方API库。可以说到此,我们已经完美的解决了如何获取Bitcoin区块链中的数据这一目标。但是好奇的我在想能不能自己本地也起一个RPC-Server,这样即使离线也可以获取区块数据进行数据分析。那么接下来目标就改为如何运行一个本地的RPC-Server并从中获取区块链数据。
运行Bitcoin完全节点
我最终采用的是Go语言实现的bitcoin完全节点 btcsuite。由于比较心疼我的笔记本,所以找了一台的曙光的服务器起了一个虚拟来运行btcd。
- 笔记本 MacBook Pro OS X Yosemite, 用做实现客户端
- 服务器 曙光 虚拟机 Ubuntu 14.04, 用做运行Bitcoin完全节点
首先需要在服务器安装go,安装指导详见 http://golang.org/doc/install。
安装完后可以确认是否安装成功,顺便记录一下我的安装路径:
1 | go version |
GOROOT
和GOPATH
最好不要是同一个路径,然后记得把$GOPATH/bin
添加到系统PATH
中。下一步安装btcd。
1 | go get -u github.com/Masterminds/glide |
安装完后在$GOPATH/bin
下面会多出addblock
、btcctl
、 btcd
、findcheckpoint
、gencerts
这几个命令。使用 xx –help可以方便的了解使用方法。
btcd
比较常用,参考手册
在控制台运行btcd &
,就会发现一个bitcoin的全节点成功运行起来了,但接下来是一个漫长的过程,100G+的区块链数据花了我近一周的时间才下载完成,存储路径:/home/demontf/.btcd/data/mainnet/ peers.json中记录了所有节点信息。blocks_ffldb中存储了所有区块数据。
1 | ~/.btcd/data/mainnet/blocks_ffldb$ ls -lh |
配置开启RPC-Server
btcd默认是关闭RPC服务的, 需要在/home/demontf/.btcd/btcd.conf中作如下配置才能开启。
1 | [Application Options] |
RPC服务默认监听8334端口,更多配置详情可以参考 RPC服务配置。
btcd 按照Bitcoin API 标准调用列表(版本0.8.0) 兼容实现各个接口,并对每个接口是否访问安全设置了user和limituser。
btcd采用TLS提供基于HTTP POST
和WebSockets
的API访问方式。相比较于HTTP
,WebSockets
拥有三个优势:允许一个连接中有多个请求,支持异步通知,大规模发送请求。但是,HTTP
的方式在我的经历中更加常见,我也更加熟悉。Btcd 除了提供了 标准API 之外,针对WebSockets
设计了 扩展API。
完成配置之后,再启动btcd就会发现RPCServer 已经启动并监听8334端口。
1 | demontf@ubuntu:~/.btcd$ btcd |
访问Client的实现
btcd 提供了两个官方的实现都是针对WebSockets
的Go版本、Nodejs版本。按照官网指导可以正确的实现获取数据的功能,基本没有问题。
1 | var fs = require('fs'); |
起初我尝试用nodejs的方式获取并分析数据。注意需要使用npm install ws
安装websocket。 由于对nodejs的不熟悉感觉用起来总是怪怪的不舒服,最终决定使用Java来实现。这一过程中遇到了不少坑。
起初为了挑战没有选择用Http协议实现,选择陌生的WebSocket协议也算是学习啦。
WebSocketClientEndpoint.java
1 | package com.demontf; |
测试T.java
1 | package com.demontf; |
一开始写Java版WebSocket实现的时候,我以为和Nodejs一样需要在Header中添加Certification,结果后台一直返回Unknown certificate,并且在文档中也没有查到传certification的key名称用什么。在Go中用的是Certification在Nodejs中用的是Cert。
进过一番研究才知道Java提供了密钥和证书管理工具Keytool
。SSL(Secure Sockets Layer,安全套接层)/TLS(Transport Layer Security,传输层安全)保证了客户端和web服务器的连接安全。客户端通过HTTPS连接使用web资源。为创建与客户端的安全连接,以加密格式发送/接受信息,Java提供了完善的安全体系API类库。
- JCA(Java Cryptography Architecture,Java加密体系结构)
- JCE(Java Cryptographic Extension,Java加密扩展包)
- JSSE(Java Secured Socket Extension,Java安全套接字扩展包)
SSL连接要求web服务器持有数字证书,该证书使客户端信任该web应用的可靠性。需要发送加密信息的应用从CA(Certificate Authority,数字证书认证机构)申请数字证书。CA验证应用所有者的详细信息和其他身份信息,并签发数字证书。
在PKI(Public Key Infrastructure,公钥基础设施)体系中,数字证书由CA签发,它包括识别名(DN,Distinguished Name)/所有者名称/使用者(Subject),唯一识别证书的序列号,所有者公钥,签发日期,到期时间,CA识别名,签发机构(CA)的数字签名,签名的创建算法。CA签发的数字证书发布在CA的注册库中,这样认证用户就可以使用所有者的公钥。
在/home/user/.btcd/目录下 已经生成了数字证书rpc.cert。如果本机挖矿那么需要将btcd RPC的证书添加到系统的CA列表里。
1.拷贝 rpc.cert 到 /usr/share/ca-certificates:
1 | cp /home/user/.btcd/rpc.cert /usr/share/ca-certificates/btcd.crt |
- 添加 btcd.crt 到 /etc/ca-certificates.conf:
1 | echo btcd.crt >> /etc/ca-certificates.conf |
- 更新 CA 列表:
1 | update-ca-certificates |
在Nodejs和Go中需要将证书读取并添加近请求头中随着请求一起发送
GO中
1 | ... |
Nodejs中
1 | ... |
将证书添加到 cacerts 存储
参考文章 将证书添加到 Java CA 证书存储
然而在java中需要将证书颁发机构 (CA) 证书添加到 Java CA 证书 (cacerts) 存储。
在设置为 JDK 的 jdk\jre\lib\security 文件夹的命令提示符下,运行以下命令可查看将安装的证书:1
keytool -list -keystore cacerts
系统将提示你输入存储密码。默认密码为 changeit。(如果您想要更改密码,请参阅 keytool 文档,网址为 http://docs.oracle.com/javase/7/docs/technotes/tools/windows/keytool.html。) 此示例假定 MD5 指纹为 67:CB:9D:C0:13:24:8A:82:9B:B2:17:1E:D1:1B:EC:D4 的证书未列出,并且你想要导入该证书(这是 Twilio API 服务所需的特定证书)。
获取 GeoTrust 根证书上列出的证书列表中的证书。右键单击序列号为 35:DE:F4:CF 的证书的链接,并将该证书保存到 jdk\jre\lib\security 文件夹。在此示例中,该证书已保存到名为 Equifax_Secure_Certificate_Authority.cer 的文件。
通过以下命令导入证书:1
keytool -keystore cacerts -importcert -alias equifaxsecureca -file Equifax_Secure_Certificate_Authority.cer
当系统提示信任此证书时,如果证书的 MD5 指纹为 67:CB:9D:C0:13:24:8A:82:9B:B2:17:1E:D1:1B:EC:D4,请通过键入 y 进行响应。
运行以下命令可确保已成功导入 CA 证书:
1
keytool -list -keystore cacerts
压缩 JDK 并将其添加到 Azure 项目的 approot 文件夹。
有关 keytool 的信息,请参阅 http://docs.oracle.com/javase/7/docs/technotes/tools/windows/keytool.html。
意外的惊喜
当所有坑都趟完,不论是直接访问在线的API接口还是使用自己的RPC-Server,都可以很方便的获取区块链中的数据。我惊奇的发现在github上有个大牛封装了一套支持Java语言实现的基于HTTP协议的JSON-RPC接口,简直欣喜若狂,果断成为github的搬运工将其运转了起来,目前来看效果良好并且省的自己再封装,其实现逻辑值得学习。
使用心得后面慢慢再总结吧~
如果你觉得有帮助,欢迎鼓励。
Bitcoin: 1F4W7beHieYtubSc3ngrozWz5QkRMnMh4J
PPC: PRfRev7MLYdVyBtN8hpaBfPDcG558trjc8