3 比特币的交易机制

  • 这章剖析比特币运行机制。
  • 前两章泛泛讨论比特币
    • 这章近距离了解比特币用的数据结构、实际脚本以及语言,
    • 这种较为精准的介绍会为本书后面的章节建立场景。
  • 本章帮助我们真正懂得比特币实质

  • 如2章
    • 比特币的共识机制设定了一个只允许往里写入的账簿
    • 一旦数据被写入,它将永远储存在那
  • 去中心化(或分布式)协议确保账簿中存储数据的共识
    • 矿工会执行协议并确认交易,
    • 这些机制确保每一笔交易都真实发生,且账簿中的每个比特币都没有被使用过。
  • 账簿形成一种货币系统。
  • 同时假设,可用货币奖励矿工,使矿工积极完成记账操作
  • 本章:
    • 如何建立货币系统、如何奖励矿工,从而保证整个流程有序运行。

3.1比特币的交易

  • 比特币交易的过程其实就是不停地创造区块,
  • 先看一个简单模式的账簿,
    • 这个账簿里,
    • 每一笔交易依次被添加到账簿里。

  • 如何用这个账簿来创造一种货币?
  • (许多人误认作比特币使用的方式):
    • 建立一个以账户为核心的系统,
    • 可以创新币且放入某人账号,然后就可以转给其他人。
    • 一笔交易这样:“把爱丽丝账户17转给鲍勃”,
      • 然后由爱丽丝签名。
    • 图3.1,爱丽丝在第一笔交易里收25
    • 转17给鲍勃,她账户还有8

在这里插入图片描述

  • 不便之处,
    • 如果想确认一笔交易是否真实就必须跟踪每一个账户的余额
    • 当爱想要转给戴15
      • 她是否真的有15?
    • 为搞清楚,须回过头去看和爱丽丝有关的所有交易,
      • 加总来确认当时的余额
    • 更有效的办法,如另外增加一个数据字段,
      • 更新每次交易后的账户余额,
      • 但这增加了记账的工作量。

  • 比特币没有用这种记账方式,
  • 用了第1章1.5节里提到的“财奴币”相类似的方法来记录交易。

  • 这种方式就像财奴币里的付币,
    • 每个交易中都有一个输入值和输出值。
  • 输入值是将被消费掉的币(这些币是前一个交易创造出来的),
  • 输出是在本次交易中创造出来的币。
  • 铸造新币时,只创造新币,不消旧币(就像财奴币里的造币,只有输出,没有输入)。
  • 每笔交易都有一个独一无二ID。
  • 每笔交易可多输出,
    • 输出索引从0,
    • 称第一个输出为“输出0”

  • 图3.2。
  • 1是铸造新币的交易,因此没输入,也没签名;
    • 输出是向爱丽丝转移25个币。
  • 爱丽丝想把些币转给鲍勃,她就创造了一条新交易,
    • 图3.2中的交易2。
    • 她必须明确指出币的来源(引用之前某笔交易)
    • 爱丽丝指出本次交易的币来自交易1中的输出0(交易1唯一输出)
    • 即向爱丽丝转25个币
    • 爱丽丝还要明确收款人也就是输出的地址,
      • 两输出,
        • 转17给鲍勃,
        • 转8给爱丽丝自己。
    • 整个交易由爱丽丝签名这样,
      • 大家就知道这笔交易爱丽丝确实授权了

在这里插入图片描述

  • 地址转换。
  • 为什么爱丽丝要把币转给自己?
  • 比特币就像财奴币中描述的币一样,交易中输出的币,要么在另
    个交易中被完全消费,要么就一个都不消费,不存在只消费部分
  • 爱丽丝只需付给鲍勃17,但爱丽丝在上一交易中实际获得25,
    • 为把这些币全部消费掉,她必须再转给自己8
    • 8可转到另一地址(不同于交易1中获得25个币的地址)
    • 但前提是该地址为爱丽丝所有,这就叫地址转换

  • 有效验证。
  • 当一个新的交易被加入总账,它的有效性是否易验证?
  • 核査一下爱丽丝引用的交易输出,确认她确实有25没花
  • 因为用了哈希指针,所以核查很快。
  • 为确认这25没被花,只需从爱丽丝所引用的交易开始,
    • 一直核査到账本上最新记录的交易为止
    • 不需从账本建立之初的交易开始核査
    • 这种方法也不需增加额外数据结构(将看到,加入新数据结构将进一步提速)

  • 资金合并。
  • 和财奴币一样,比特币交易可能有许多输入与输出,资金分隔与合并也很容易。
  • 假如鲍勃在两笔不同的交易中分别收到17和2,
    • 现在他想把这两笔钱合并起来花掉,这很容易,他只需发起一个交易,交易里有两个输入和一个输出,输出的地址是他自己的地
      址,这样,鲍勃就把两个交易合二为一了

  • 共同支付。
  • 如果卡罗尔和鲍勃想共同支付戴维,
    • 可发起一个交易,
    • 交易里两输入和一输出
    • 两输入引用的“上一笔交易”的输出地址不同,
      • 因此,这笔交易需两个签名:
        • 卡罗尔的和鲍勃的。

  • 交易语法。
  • 比特币交易涉及的概念就是上面这些。
  • 再看看比特币交易在底层是如何实现
  • 实际上,比特币在网络上传输的数据结构都是一串字符,图3.3显示了一个真实的程序,经过编译就变成供机器执行的二进制代码

在这里插入图片描述

  • 图3.3,
  • 一个比特币交易分三
    • 元数据、
    • 一系列的输入
    • 和一系列的输出

元数据

  • 存放一些内部处理的信息:
    • 这笔交易的规模、
    • 输入数量
    • 输出数量
    • 此笔交易的哈希值,这个交易独一无二的ID。
      • 可用哈希指针指向这个ID。
    • “锁定时间”

  • 输入
  • 所有输入排成一个序列,输入格式都一样
  • 需明确说明之前一笔交易的某个输出,
    • 它包括之前那笔交易的哈希值,使其成为指向那个特定交易的哈希指针。
    • 同时包括之前交易输出的索引和一个签名:
      • 须有签名来证明我们有资格去支配这笔比特币

  • 输出
    • 所有输出排成一个序列。
    • 每个输出的内容分成两部分。
      • 所有输出的金额之和必须<=输入的金额之和。
      • 当输出的总金额小于输入总金额时,输出的总金额与输入的总金额的差额部分,就作为交易费支付给为这笔交易记账的矿工

  • 一长串字符看上去像接收地址
  • 每个输出都要和一个特定的公钥(地址)对应,
    • 所以这一长串字符里面确实有一部分看上去是公钥的哈希值,
    • 但里面还有一部分看上去像指令集合的东西,
      • 是一个比特币的脚本

3.2比特币的脚本

  • 每个交易输出确定公钥,同时指定一脚本
  • 这节学习比特币的工作控制语言,也叫脚本。
  • 懂得为什么要用一个脚本而不是简单分配一个公钥

  • 最常见的比特币交易,是通过某人的签名去取得他在前一笔交易
    中获得的资金。
    • 希望交易的输出包含这样的信息:
      • “凭借地址X的所有者的签名,才可获得这笔资金。”
    • 地址就是一个公钥的哈希值,所以仅仅说地址Ⅹ并没告诉我们公钥在哪,也没有给我们一个检査签名的方法。
      • 所以,交易输出须这样描述:“凭借哈希值为X的公钥,以及这个公钥所有者的签名,才可以获得这笔资金。”
      • 这实际上就是最常见的比特币脚本,如图3.4

在这里插入图片描述

  • 谁执行这脚本?
  • 这一系列指令如何完成?
  • 交易输入包括脚本(而不是签名)。
  • 为确认一笔交易正确地获取了上一笔交易所输出的,
    • 把交易的输入脚本和上一笔交易的输出脚本串联,
    • 这个串联脚本必须被成功地执行后才可以获取资金。
  • 输出脚本( scriptpubkey),
  • 输入脚本( scripts)。
  • 输出脚本只指定了一个公钥(或公钥哈希值的地址),
    • 输入脚本指定一个对应公钥的签名。
    • 图3.5就是两个脚本结合。

比特币脚本语言

  • 这个脚本语言为比特币开发。
  • 和Forh语言有相似,Forth是一种简单的堆栈式编程语言
  • 比特币的脚本语言设计原则就是简明扼要,并内生地支持加密操作。
  • 脚本里面有指令计算哈希值和检验签名

  • 这种语言是堆栈式的,每个指令只被执行一次,是线性的,无法循环
    • 指令数目给了一个执行时间与内存使用的上限
  • 语言不是图灵完备的,不能随意运行强大函数功能
    • 有意设计的,
    • 矿工需执行这些网络上任意交易提交者所递交的脚本,
    • 设计者不希望让他们提交可能无限循环的脚本。

在这里插入图片描述

  • 执行比特币脚本只能产生两结果:
    • 成功执行,交易有效;
    • 脚本执行出现错误,整个交易无效拒绝记入区块链。

  • 这个脚本语言十分简单。
  • 256个指令,每个一字节。
  • 256个指令中,15个目前不可用,75个被保留还没有具体定义(以后或
    许可以被用来扩展),剩下的才是可用的

  • 基本的算数、逻辑语句(如If-then)、抛出错误、过早返回
  • 密码指令,如哈希函数语句、签名验证语句,
    • 重要特殊指令是“ CHECKMIUILTTISIG”
      • 査证多个签名。
  • 表3.1一些比特币工作控制语言里的常用语句

在这里插入图片描述

  • CKMIUILTISIC要求指定n个公钥和一个参数t(作为一个临界值)。
  • 正确执行的条件是:
    • 在n个公钥中,至少可以选出t现时有效的签名。
    • 3.3节会示范这个指令的用法,现在需认识到这个原生指令是非常强大的,它以一种极其精练的方式协助我们查验交易中的多方签名

  • 不过,目前比特币多方签名功能实现过程中有个缺陷
  • CHECKMULTISIG执行时会返回一个没用值
    • 且系统还必须要安排一个堆機中的变量去储存它,然后再忽略掉
  • 修复这个缺陷成本高,一直没被修复,第3章3.6节会再讨论。
  • 但目前,这个程序缺陷也算是比特币的一个特性

执行一个脚本

  • 堆栈语言里执行一个脚本,我们只需一个堆栈来垒积数据,不需分配任何内存与变量
  • 两类
    • 数据指令和工作码指令。
  • 数据指令是把数据推到堆栈的最上面
  • 工作码指令
    • 用堆栈顶部的数据作为输入,计算一个函数

  • 图3.5怎么执行。
  • 图3.6展示每一条指令执行后的堆栈状态
  • 前两条指令属数据指令,
    • 脚本(包含在交易的输入项)中的签名
    • 用来验证签名的公钥
  • 后面几个指令是输出脚本(包含在上一交易的输出项中)里的指令

在这里插入图片描述

发布了558 篇原创文章 · 获赞 295 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/zhoutianzi12/article/details/105351622
今日推荐