选型
c/c++ 语言,bitcoin最核心的版本是用c/c++实现,但由于最初版本源码结构太差,现在比以前好了很多,但还是在继续调整。由于c/c++语言本身的问题,库引入都是比较麻烦的事情。它的有点相对其他实现比较稳定
golang语言,有bitcoin的实现btcd,但最近没有更新,有些bip也没有实现;另外有开发者尝试用golang实现的例子,如这个,这个,借鉴的内容会多一些。
其他如js,但并不是个人擅长,也不是区块链的核心语言系列,就不考虑。上面两种选哪种都ok,看个人擅长,这边就选择使用golang。
接口选择方面,直接调用bitcoin core的rpc接口或者使用blockchain.com的api。这里选择了第一种。
实现方法
一般来说要实现交易所或者交易网站的功能,要实现三块功能:地址管理、充值、提现
地址管理
- 目标:
- 方便管理用户的地址
- 保存好私钥的安全性
- 实现:
- 一般来说使用HD钱包的方式生成地址
- 地址类型一般用着两种:P2PKH和p2sh-p2wpkh,后台生成用统一用一种即可,第二种打包费用更低
- 公钥和私钥都使用压缩格式
- 私钥的存储需要隔离,有几个维度
- 存储的数据库要独立
- 对数据库中的内容需要加密
- 启动的时候,从root启动,解密私钥的秘钥从环境变量读取或者从文件读取(启动完成后把文件删除)
- 目标:
充值
- 目标:
- 玩家充值:玩家充值后,应立即感知到充值行为
- 充值到某个帐号,就无法识别出是哪个玩家进行了充值,所以需要对每个帐号生成一个区块链地址,玩家向这个地址充值
- 充值服务可随时更新
- 玩家充值:玩家充值后,应立即感知到充值行为
- 实现:
- 用一个goroutine监控交易池,一旦发现交易池中有游戏中玩家的对应地址,就记录玩家充值状态到缓存,设置超时60分钟;遍列过的交易不再重复查看
- 用一个goroutine监控[1,3)个确认的区块,如果发现其中有玩家的对应地址,就记录玩家充值状态到缓存,设置超时30分钟;遍列过的区块不在查看,遍列过的交易不再重复查看;防止交易池漏查、重启过程中漏查
- 用一个goroutine监控3个确认以上的区块,如果发现其中有玩家的对应地址,就记录玩家充值状态到数据库;并记录到扫描高度,以防止重启丢失充值记录。
- 注意点
- 玩家的充值地址需要同步到内存中,方便快速查找;有新帐号创建的时候,要先同步过来,在创建成功
- 目前2018-08-30每个区块大约有100-3000个交易不等
- 交易池中大约有4000+的交易
- 提取交易信息接口getrawtransaction “txid” ( verbose “blockhash” ) ,需要在bitcoind启动的时候添加-txindex,获取所有的交易索引
- 风险控制:
- 软分叉,忽略
- 硬分叉,使用网络接口监控异常,一旦出现警告,停止服务
- getnetworkinfo 提取warnings信息
- 目标:
提现
- 目标:
- 玩家提现,将中心的对应货币转到链上,且收取一定的手续费用
- 将玩家的充值,全部转到某个Master帐号上
- Master帐号充值后,能发现其未使用的UTXO,并录入库
- 实现:
- 玩家的提现
- 发起请求,将玩家的提现请求录入到提现队列,如NSQ,并入库
- 处理请求,每一个Master帐号对应一个goroutine,每个goroutine从队列中提取请求,处理后发到链上。所有的转账处理的goroutine由Manager goroutine创建,当发现新帐号的时候,立即开启一个新的goroutine
- 当账户金额不足时,告警
- 未确认数提现达到一定值时,此账号停止提现
- 可重发所有请求
- 确认请求,单独起一个goroutine,监控这些提现行为,达到3个确认后,就同步入库
- 玩家的充值
- 单独起一个goroutine,检查充值量和充值额度,当达到一定条件,就将用户的比特币转到一个Master帐号
- 录入Master帐号的UTXO
- 单独起一个goroutine,检查Master帐号的充值和玩家的充值的合并,方法跟充值服务的实现差不多
- 玩家的提现
- 目标: