[TOC]
比特币介绍
历史
比特币(bitcoin)由中本聪于2009年提出并开源。它具有分布式、去中心化、加密数字化等特点,采用工作量证明机制解决共识问题,所以,它又是安全的。
它诞生与全球经济危机(2008年)时期,是奥地利经济学派观点的实践。
比特币定义
通常所说的比特币指的是一种加密数字货币,由比特币网络发行(实际是给矿工的奖励)、并在比特币网络上流通。数字签名是目前数字货币的首选方案,其可以有效验证货币所有权。对于双清问题,比特币采用工作量证明机制解决双清问题。
交易
交易是参与者之间价值转移的过程。
比特币交易的基础单元是交易输出。未被使用的输出被称为UTXO。一个UTXO是最小的不可分割的。一个UTXO是一聪(satoshi)的任意整数倍。
密钥及比特币地址
比特币采用公钥加密方案对交易进行签名,算法为椭圆曲线乘法算法。交易通常会包含一个公钥、数字签名和地址。
私钥、公钥、比特币地址三者间关系,如下图:
[图片上传失败...(image-31ce69-1520689362124)]
私钥
比特币对私钥并没有强制规定。用户可以自行选择私钥。私钥目前是一个256位的数字,通常从一个安全的随机数序列中产生。加密安全的伪随机数生成器推荐使用CSPRNG。生成一个私钥的通常流程为:选择随机数生成器->选择随机数种子->生成一个随机数->SHA256哈希算法生成256位的数。
使用比特币客户端生成私钥的方法如下:
$ bitcoin-cli getnewaddress
1J7mdg5rbQyUHENYdx39WVWK7fsLpEoXZy
$ bitcoin-cli dumpprivkey 1J7mdg5rbQyUHENYdx39WVWK7fsLpEoXZy
KxFC1jmwwCoACiCAWZ3eXa96mBM6tb3TYzGmf6YwgdGWZgawvrtJ
或者使用bitcoin explorer的cli工具:
$ bx seed | bx ec-new | bx ec-to-wif
5J3mBbAH58CpQ3Y5RNJpUKPE62SQ5tfcvU2JpbnkeyhfsYB1Jcn
比特币私钥通常使用WIF(Wallet Import Format)显示私钥。
公钥
Public Key是从私钥计算而来的,计算方法采用椭圆曲线密码学的第二个标准secp256k1。
生成公式:
K = k * G
k为私钥。K为生成的公钥。G为预定义的点(被称为generator point G)。k * G生成曲线上的另外一个点,该点即为公钥K。
比特币地址
根据公钥生成的比特币地址以数字1开头。生成公式为:
A = RIPEMD160(SHA256(K))
上述公式生成的地址A为160位,共20个字节。比特币通常使用Base58Check编码格式编码比特币地址A。
Base58的详情信息参见链接。
Base58Check的过程如下:
Bitcoin Address = PREFIX + A + Checksum
checksum = sha256(sha256(PREFIX + A)
prefix定义
Type | Version Prefix(Hex) | Base58 result prefix |
---|---|---|
Bitcoin Address | 0x00 | 1 |
Pay-to-Script-Hash Address | 0x05 | 3 |
Bitcoin Testnet Address | 0x6F | m or n |
Private Key WIF | 0x80 | 5,K, or L |
BIP-38 Encrypted Private Key | 0x0142 | 6P |
BIP-32 Extended Public Key | 0x0488B21E | xpub |
私钥的编码格式
Type | Prefix | 描述 |
---|---|---|
Raw | None | 32字节 |
Hex | None | 64个16进制数字 |
WIF | 5 | Base58Check |
WIF-compressed | K or L | As above, with added suffix 0x01 before encoding |
BIP-38 | 6P | BIP-38标准加密的私钥 |
密钥和地址强化
加密密钥
BIP-38标准是一个通用的私钥加密标准。它使用AES加密算法。用户需要提供私钥和一个passphrase。BIP-38标准生成的私钥以6P开头。
P2SH和多签名地址
P2SH全称为Pay-to-Script Hash,又称为Multisig Addresses(多重签名地址),地址前辍为3。目前,最为普遍的P2SH功能应用是多签名地址脚本。这种脚本要求用户提供一到多个签名来证明控制权(Ownership),然后才可以花费这笔资金。
生成P2SH地址的过程一般如下:
graph LR
A[script]-->B(script-encode)
B --> C(sha256)
C --> D(ripemd160)
D --> E(base58check-encode)
代码示例如下
$ echo \
'DUP HASH160 [89abcdefabbaabbaabbaabbaabbaabbaabbaabba] EQUALVERIFY CHECKSIG' > script
$ bx script-encode < script | bx sha256 | bx ripemd160 \
| bx base58check-encode --version 5
3F6i6kwkevjR7AsAd4te2YB2zZyASEm1HM
靓号地址(Vanity Addresses)
靓号地址是一个有效的比特币地址,它含有一部分有意义的信息。如地址1LoveBPzzD72PUXLzCkYAtGFYmK5vYNR33
。该地址包含词"Love"。
纸钱包
所谓纸钱包就是把私钥和地址打印一张纸上。这是一种廉价的离线存储手段。离线存储的钱包也叫冷钱包。直接将私钥原样做成纸钱包并不安全(盗贼)。通常,冷存储的是BIP-38加密过的私钥。这就要求用户要记住一个passphrase或将passphrase另行存储。
钱包
钱包(wallet)是一个应用程序,用于管理密钥、地址,跟踪余额以及签名交易。
从技术的角度来看,钱包是一种数据结构,用于存储和管理用户的密钥。
小提示:比特币钱包并不含有比特币,他只包含密钥。所谓的币是记录在比特币网络的区块链里的,'币'是交易输出的一种形式(通常称为vout或txout)。
钱包有两种类型:非确定性钱包和确定性钱包。区分的标准是密钥间是否有关联。
非确定性钱包里的密钥们没有相关性,是独立的。
确定性钱包里的密钥由一个主私钥衍生而来(被称为seed,即种子)。最常见的实现方式是一种类树状结构,被称为分层确定性钱包(HD wallet),标准为BIP-32/BIP-44。
确定性钱包从一个种子初始化而来。为便于使用,种子通常编码为英文单词,又称助记码(Mnemonic Codes,标准为BIP-39)。
现在,基本上都是HD钱包了,除了Bitcoin core。
钱包最佳实践
- 基于BIP-39的助记码
- 基于BIP-32的HD钱包
- 基于BIP-43的多用途HD钱包
- 基于BIP-44的多币种、多帐号钱包
助记符(BIP-39)
BIP-39是助记码的当前工业标准。它是Trezor硬件钱包公司提出的。目前,BIP-39有两个实现版本:Trezor版本和Electrum钱包。两者因为使用不同的词典集合而不能互通。
助记符生成示例如下
$bx mnemonic-new ea3138a05e18f4f68f345a40b0e4e264
tuition mean chimney rotate monster kitten devote mercy doll mango decade since
交易
交易是比特币系统最重要的部分。系统的其他部分都是为了保证交易的创建、验证以及记入全球帐薄。
交易输出和输入
比特币交易的基石是交易输出(vout)。交易输出是不可分割的比特币货币(类似于有面额的纸币),记录在区块链上并由全网络验证有效。比特币全节点跟踪所有的可用、可花费的输出,这些输出被称为UTXO(未花费的交易输出)。
原始的交易解码后,一般是下面样子:
{
"version": 1,
"locktime": 0,
"vin": [
{
"txid": "7957a35fe64f80d234d76d83a2a8f1a0d8149a41d81de548f0a65a8a999f6f18",
"vout": 0,
"scriptSig" : "3045022100884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4ae24cb02204b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e3813[ALL] 0484ecc0d46f1918b30928fa0e4ed99f16a0fb4fde0735e7ade8416ab9fe423cc5412336376789d172787ec3457eee41c04f4938de5cc17b4a10fa336a8d752adf",
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.01500000,
"scriptPubKey": "OP_DUP OP_HASH160 ab68025513c3dbd2f7b92a94e0581f5d50f654e7 OP_EQUALVERIFY OP_CHECKSIG"
},
{
"value": 0.08450000,
"scriptPubKey": "OP_DUP OP_HASH160 7f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a8 OP_EQUALVERIFY OP_CHECKSIG",
}
]
}
每一个区块的第一个交易被称为coinbase交易,即比特币网络给矿工的奖励。所以,coinbase交易是没有input的。
交易输出
交易输出包括两部分:
- 一定量的比特币,单位是聪(satoshis)
- 一个加密迷题(花费该UTXO的必要条件),又被称为锁定脚本(locking script)、见证脚本(witness script)或scriptPubKey。
输出的序列化结构(开发人员关注)
Size | Field | Description |
---|---|---|
8 bytes(小端) | 总量 | 比特币总量,单位聪(satoshis) |
1-9 bytes | Locking Script的大小 | Locking Script的字节大小 |
可变部分 | Locking Script | 定义花出该输出的前提条件的脚本 |
交易输入
交易输入标识哪个UTXO将被消费(花出)并通过unlocking script证明其所有权。
其主要包含如下几部分:
- 一个交易id, txid
- 一个UTXO的索引(从0开始)
- 一个scriptSig,用于unlocking花费
- 一个序列号
示例如下:
"vin": [
{
"txid": "7957a35fe64f80d234d76d83a2a8f1a0d8149a41d81de548f0a65a8a999f6f18",
"vout": 0,
"scriptSig" : "3045022100884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4ae24cb02204b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e3813[ALL] 0484ecc0d46f1918b30928fa0e4ed99f16a0fb4fde0735e7ade8416ab9fe423cc5412336376789d172787ec3457eee41c04f4938de5cc17b4a10fa336a8d752adf",
"sequence": 4294967295
}
]
交易费
大部分交易是包含交易费的。交易费用于激励矿工维护比特币网络。交易费用是隐含在交易中的,其数值为Fees = Sum(Inputs) – Sum(Outputs)
。
交易脚本
比特币的交易脚本(script)是一种类似于Forth语言的、逆波兰式、基于堆栈的语言。
比特币的脚本语言不是图灵完备的,不支持loop操作
比特币脚本语言是无状态的
比特币脚本语言简单,但并不友好。看起来,像是汇编语言
脚本构建
比特币交易验证引擎依赖于两种脚本:一个锁定脚本和一个解锁脚本。
锁定脚本通常称为scriptPubKey。解锁脚本通常称为scriptSig。
交易验证时,引擎执行流程是:scriptSig -> scriptPubKey。
示例如下:
[图片上传失败...(image-ec046-1520689362124)]
具体执行流程如下:
[图片上传失败...(image-ec5c92-1520689362124)]
数字签名
比特币使用的数字签名算法为ECDSA。该算法是一种公钥加密算法。
数字签名有三个作用:
- 所有权证明
- 授权是不可否认的(即交易一旦生成,不可否认)
- 一旦签名,则交易不可修改(或特定部分不可修改)
高级交易和脚本
隔离见证的核心部分
比特币网络
区块链
区块链数据结构是一种后向链接的有序链表。比特币客户端使用Google LevelDB存储区块链的元数据。
Block数据结构
Block Structure
Size | Field | Description |
---|---|---|
4字节 | 块大小 | 随后的块大小,字节单位 |
80 bytes | Block Header | 由多个field构成 |
1–9 bytes (VarInt) | 交易计数器 | 该block包含的交易数目 |
可变部分 | 交易的集合 | 记录在该区块上的交易 |
区块头(Block Header)
Size | Field | Description |
---|---|---|
4 bytes | Version | 协议的版本号 |
32 bytes | Previous Block Hash | 父区块的Hash |
32 bytes | Merkle Root | Merkle树的root |
4 bytes | 时间戳 | 区块的创建时间,秒(是个近似值) |
4 bytes | Difficulty Target(难度目标) | 该区块的PoW难度 |
4 bytes | Nonce | PoW算法的一个计数器 |
区块标识 (Block Identifier)
Block的标识是一个哈希值(Hash),使用sha256算法对区块头(Block Header)执行两次哈希操作而来。
创世区块的哈希值是:000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
区块的Hash值并没有存储在区块上。当节点收到一个区块时,节点需要去计算该节点的Hash。
另一种标识则是区块高度(block height)。创世区块从0开始。一个区块一定有一个高度。但一个高度并不唯一对应一个区块。这涉及到区块竞争问题。常见场景是forks(即分叉)。Block Height也不是区块数据结构的一部分。节点需要在收到区块时计算。
创世区块(Genesis Block)
比特币区块链上的第一个区块被称为创世区块,创建于2009年。它是所有区块的祖宗。创世区块的UTXO是50BTC,至今未花。创世区块上写有一条信息(已经是非常出名了):"The Times 03/Jan/2009 Chancellor on brink of second bailout for banks."。
Merkle Tree
每一个区块均使用Merkle Tree记录该区块上所有交易的摘要。Merkle Tree生成过程如下图所示。
[图片上传失败...(image-79a62-1520689362124)]
区块上存储Merkle Tree Root节点的hash。每个节点的hash算法均为double-sha256。
SPV (Simplifiled Payment Verification)
SPV节点不需要全部的交易数据也不需要下载全部区块,只需要区块头数据即可。SPV节点使用merkle path来验证一个节点是否被包含在该区块内。
SPV节点验证交易A被包含于区块Block_b的基本过程如下:
- SPV节点向向周边节点(peers)广播其感兴趣的交易(以bloom filter形式)
- 当一个peer节点发现一条交易包含在bloom filter中,该节点则返回该区块(区块头和一条merkle path)
- SPV节点使用merkle path验证交易A是否在Block_b中
merkle path如下图所示:
[图片上传失败...(image-26d469-1520689362124)]
如果要验证交易Hk是否包含在区块内,只需要获知H(L), H(IJ), H(MNOP),H(ABCDEFGH)这四个哈希值即可。
Merkle Tree的效率
交易数量 | 区块大小 | Merkle Path哈希数 | Path字节数 |
---|---|---|---|
16条交易 | 4KB | 4 hashes | 128B |
512条交易 | 128KB | 9 hashes | 288B |
2048条交易 | 512KB | 11 hashes | 352B |
65535条交易 | 16MB | 16 hashes | 512B |
比特币测试链(Test Blockchains)
比特币是有多条链的。由中本聪同学创建于2009年1月3日的区块链为主网络(mainnet
)。还有其他测试目的的区块链:testnet(测试网络), segnet(隔离见证网络), regtest。
- testnet
testnet拥有主网络的所有特征。通常,testnet网络上的币是没有价值的(因为其挖矿难度比较低),但事实并非如此。因为总是有玩家使用asic来挖矿,从而导致测试网络挖币也是一件困难的事情。目前的解决方案是从一个新的创世区块重启测试网络,并重设难度。
目前的测试网络为testnet3(重启于2011年)。
bitcoind -testnet
- segnet
2016年,为了支持SegNet的开发测试,一个特定目的的测试网络启动。(目前已不再是必须的,因为segwit已经被testnet3引入)
- Regtest
本地区块链
$ bitcoind -regtest
挖矿和共识
挖矿是确保比特币去中心化安全性的机制。比特币是一种经济激励机制。
矿工负责验证新的交易并记录在全球帐薄上。挖出一个新区块的平均时间是10分钟。而记录在区块链上的交易则被认为是确认过的。
比特币的确认时间目前比较长,一个小时之上。
矿工有两种奖励:交易费和区块奖励。为了获得奖励,矿工需要解决一个数学难题。比特币采用PoW方案来解决这个难题(工作量证明-Proof-of-Work)。答案被记录在新区块中并作为一个凭据。该凭据可以证明矿工花费了一定的算力来解决这个问题。
这个过程称为挖矿,因为奖励(比特币发生成)旨在模拟收益递减,就像开采贵金属一样。比特币总量固定而且区块生成的比特币每四年或210000个区块减半。2009年一个区块奖励是50个比特币,2012年11月为25个比特币,2016年7月则为12.5个。到2140年,不会再有新的比特币生成。
目前,交易费只占矿工收入的0.5%。而随着奖励指数级下降,区块上的交易日渐增多,比特币矿业收入的更大比例将来自交易费用。
从发行上来看,比特币是具有通缩特性的。