比特币及衍生币种的开发技术学习

比特币及衍生币种的开发技术学习笔记

一、背景和环境准备


背景介绍

比特币是第一种得到广泛承认的区块链虚拟货币。莱特币可以不严谨的看作对比特币的一次“参数调优”的 产物。它的设计和技术实现几乎完全一样,包括RPC数据结构、api体系,甚至默认实现的文件存储结构 都几乎完全一样,比特币的java版节点项目 bitcoinj 的代码,可以直接用来解析莱特币“官方”实现 Litecoin QT/Litecoind的数据文件——它本设计为解析比特币“官方”实现 Bitcoin Core 。

而 BCC (又称 BTH, 即 Bitcoin Cash)是基于 bitcoin 协议的硬分叉产物,两者甚至共享分叉 前的账目。

可以说这三种常见货币,以及若干衍生货币,在使用层面上几乎毫无差别。我们以比特币(BTC)为例,简 单介绍一下从无到有的建立开发环境,完成简单的自动化交易打包和账号管理的过程。

本文只是官方教程 Developer Examples - Bitcoin 的学习笔记,除了整理为 jupyter notebook ,并没有做什么额外工作。

环境准备

在正式开始学习之前,我们先确认一下所需的环境和工具。

操作系统和技术工具

首先我们准备一个 ubuntu linux,我建议最好是最新发布版的 ubuntu。

然后是 Python ,文档中采用的是最新的 python 3.6.2 。如果在开发环 境中使用,建议自行安装 pyenv 并使用它管理Python环境。

如果使用 pyenv ,请现在安装并激活一个基于 Python 3.6.2 的环境,从 现在开始使用它。我在我的开发服务器上使用的环境名为 workshop 。

然后是 Jupyter Notebook 。然后启动 jupyter notebook ,在其中使用本文作为 notebook 文档。

原则

上我们还需要一些 python 的依赖库,比如 bitcoin-python 。实际上 它们大多基于 rpc 调用,而比特币族系使用的 http json rpc 是一个非常 简单无脑的协议,自己写也没大问题。我在 Scala 里就是自己封装了 rpc 访 问,后续我们视情况需要来决定有哪些依赖需要安装。

一些问题

一份政治正确的 Introduction ,使用这个英文单词并不表示作者对其他语言 有高下之分的判断。

本文中并没有 Python 3.6.2 以外的编程语言受到伤害。

Python 也没有。

为什么要 Linux ?

其实在 mac 下面一样可以做,没有问题。如果你熟悉你的计算机,用 windows 也完全没有问题,这里选 Linux 主要是为了一致性。linux 下的 bitcoind/litecoind 很适合自动化操作,仅此而已。MacOS 的话预编译版本 几乎只能找到 Bitcoin QT 这样的实现,再加上 MacOS 的 app 机制,使用 起来并不直观,徒增很多信息干扰。Windows 上也有类似的问题。所以这里以最 直观的 Linux 为例,架设 Linux 环境比较麻烦的读者,可以考虑弄个 vagrant 之类的虚拟环境,windows 10专业版用户还可以考虑使用内置的 linux 子系统 和 bash shell 。更进一步说,熟练用户完全可以读完文档以后直接基于自己熟 悉的环境重现文档中的内容。

为什么要 ubuntu linux ?

就算决定了要用 Linux ,也总得挑一个版本。Ubuntu 属于对个人用户比较友好 的版本,默认的桌面环境可用度高,服务环境也比较容易配置。这并不表示只能用 Ubuntu。既然有自己钟爱的选择,但用无妨。

为什么要最新发布版而不是 LTS?

一般来说我总是建议用比较新的版本,算是个人爱好吧。应用类软件的开发功跟底层 系统的要求还是不太一样,应该充分享受技术发展带来的好处。何况就算采用新的版 本,等产品发布以后,它早晚也会趋于落后。 所谓旧版本更稳定的说法,纯属幻觉,在我近二十年的工作生涯中从没有生效过。代 码又不是酒,可以窖藏陈年。倒是经历了不止一次,若干年后突然发现旧项目无法升 级的情况。

为什么是 Python 3 而不是更稳定的 Python 2?

理由如前。

管理结构

这里我们假设有一个用于此专题的目录 /data 。我们在 /data 目录下建立 /data/bitcoin/regtest 目录作为数据存储区。而当前您阅读的这份文档 放在 /data/notebook/bitcoin 目录下——现在提到这个希望不会太晚。

Bitcoin

我偷懒,用了 apt 源里的 bitoind ,当然更好的办法是从官方下载对应的版本,解压后加入 PATH。 推荐的习惯是解压到 /data/bitcoind/$VERSION 目录。

工具代码和配置文件

为了一致,我们在下面的代码中建立环境配置和必要的工具函数。

import subprocess
import os.path

def command(*args, stdout=subprocess.PIPE):
    return subprocess.Popen(args, stdout=stdout, encoding="UTF8")

PORT = "8432" # 比特币节点RPC默认端口 8332,这里我们刻意避开了此端口

BASE = "/data/bitcoin"
DATA_AREA = os.path.join(BASE, "regtest") # regtest 是bitcoin默认的手动挖块选项,用于开发环境
os.makedirs(DATA_AREA, exist_ok=True)

CONFIG = os.path.join(BASE, "regtest.conf")
with open(CONFIG, "w+") as conf:
    conf.write("""
server=1
rpcbind=0.0.0.0
rpcuser=bitcoin
rpcpassword=bitcoin
rpcport=8432
txindex=1
""".strip())
    


运行比特币节点

下面我们启动一个支持手工挖块的私链节点:

In [2]:


cmd = command("bitcoind", "-regtest", '-datadir={}'.format(DATA_AREA), '-conf={}'.format(CONFIG))



下面部分演示命令直接用了bash,如果在windows下使用有问题,可以改用command函数调用。我们先看看这个节点是否正常工作。

In [3]:


%%bash

bitcoin-cli -regtest -rpcport=8432 -rpcuser=bitcoin -rpcpassword=bitcoin getinfo



{
"version": 140200,
"protocolversion": 70015,
"walletversion": 130000,
"balance": 5199.99978480,
"blocks": 204,
"timeoffset": 0,
"connections": 0,
"proxy": "",
"difficulty": 4.656542373906925e-10,
"testnet": false,
"keypoololdest": 1505141031,
"keypoolsize": 100,
"paytxfee": 0.00000000,
"relayfee": 0.00001000,
"errors": ""
}

挖矿

一旦拥有了一个挖矿节点,我们就可以专注于节点操作。比如我们先看看账目情况:

In [4]:


%%bash

bitcoin-cli -regtest -rpcport=8432 -rpcuser=bitcoin -rpcpassword=bitcoin getbalance



5199.99978480

当然创建的私链还没有区块,可用的比特币也就无从说起。我们先生成几个块试试看:

In [16]:


%%bash

bitcoin-cli -regtest -rpcport=8432 -rpcuser=bitcoin -rpcpassword=bitcoin generate 15



[
"……"
]

此时再调用 getbalance,我们会发现 balance 仍然为 0 。这是因为在 regtest 模式下,UTXO 要确认一百次以上才能使用。现在我们再生成 86 个块,让最初的块被确认一百次以上:

In [19]:


%%bash

bitcoin-cli -regtest -rpcport=8432 -rpcuser=bitcoin -rpcpassword=bitcoin generate 86



[
"……"
]

此时再调用 getbalance ,会发现我们真的得到了一批比特币。接下来,我们可以在自己的私链上挥霍它们了!