美文网首页区块链程序员
精通比特币第二版笔记

精通比特币第二版笔记

作者: 梁瀛渠 | 来源:发表于2018-03-10 21:47 被阅读179次

    [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的基本过程如下:

    1. SPV节点向向周边节点(peers)广播其感兴趣的交易(以bloom filter形式)
    2. 当一个peer节点发现一条交易包含在bloom filter中,该节点则返回该区块(区块头和一条merkle path)
    3. 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%。而随着奖励指数级下降,区块上的交易日渐增多,比特币矿业收入的更大比例将来自交易费用。

    从发行上来看,比特币是具有通缩特性的。

    相关文章

      本文标题:精通比特币第二版笔记

      本文链接:https://www.haomeiwen.com/subject/vfnbfftx.html