区块链开发指南带书签.pdf
http://www.100md.com
2020年1月5日
![]() |
| 第1页 |
![]() |
| 第6页 |
![]() |
| 第12页 |
![]() |
| 第29页 |
![]() |
| 第45页 |
![]() |
| 第382页 |
参见附件(14607KB,524页)。
区块链开发指南,这是一本关于区块链相关的书籍,现在区块链非常的火爆,关于区块链的开发岗位也增多了,这本可以帮助你了解到区块链开发的基本情况。

区块链开发指南内容简介
本书以比特币、以太坊、Fabric三种区块链的技术原理和实际操作为主要目标,全书具体内容如下。
第1章介绍比特币区块链,包括交易和交易链、区块和区块链、挖矿、矿池、脚本系统、合约应用案例等内容,向读者们介绍区块链基础知识。
第2章讲述区块链进阶技术,包括外带数据原理、Counterparty原理、挖矿算法解析、侧链技术,以及*新的IBLT、隔离见证、闪电网络等。
第3章的主要内容是区块链中使用的密码学基础,包括Hash函数、椭圆曲线密码体系、ECDSA签名、Schnorr数字签名和Bloom f ilter算法等,向开发者介绍密码学相关算法。
第4章是比特币区块链的编译、代码剖析、建立私链及API开发等实操内容。
第5章介绍以太坊的技术原理,包括以太坊简介、账户管理、交易原理、智能合约等,还涉及搭建私有链,智能合约开发、部署和调用等实操过程。
第6章介绍了IBM开源的区块链底层技术平台Fabric的原理和实操,对Fabric系统架构、节点、验证总账、交易背书的基本流程进行了详尽独到的分析,对Fabric的私有链建立和配置、链上代码的开发过程进行了详细的描述,为开发者使用Fabric提供技术指导。
区块链开发指南作者信息
申屠青春
金链盟常务副秘书长,银链科技CEO,深圳金融标准委员会会员,深圳大学博士,高级工程师,深圳市高层次人才,深圳市政府采购评审专家。曾获2008年深圳科技创新奖、2009年广东省科技进步三等奖,获得发明专利授权4项,获2012年深圳发明奖。2012年创立银链科技,2013年开始研究区块链,2016年转向金融行业,并发起成立金链盟。
宋波
曾在某外企支付公司任职中国区软件开发部经理,负责ATM、EMV IC银行卡、Kiosk等产品,现在币信负责移动IM的开发工作,先后参与了钱包、算法交易、区块链、交易引擎、矿池及APP等产品的开发。
张鹏
博士,硕士生导师,现为信息工程学院讲师,中国密码学会会员。研究方向为密码学与信息安全。近年来主持或参与本领域的国家、省、市多项科技计划项目,申请国家发明专利十余项,在本领域核心学术刊物上发表文章20多篇,其中多篇被SCI、EI检索。
汪晓明
朝夕网络CEO,10年互联网技术产品经验,在跨境电商、大数据、区块链等领域有丰富的经验。作为区块链技术早期探索者,一直积极推动区块链技术在国内的传播和应用落地,已推出面向金融机构的区块链数字资产和供应链产品。同时发起了有行业影响力的区块链视频节目《明说》,持续影响着更多人参与到区块链技术的研究和推广中。
季宙栋
万达网络科技集团先进技术研究中心副总经理,万达区块链负责人,(工信部)中国区块链技术与产业发展论坛副秘书长,超级账本中国技术工作组委员。专注于互联网金融业务的创新及金融科技实践,参与了工信部区块链白皮书及相关标准编制工作,ISO/IEC TC307中国代表团成员,牵头工信部区块链开源社区工作。
左川民
先后在多家知名企业担任技术专家和高级架构师。2015年开始从事区块链技术的研究工作,曾负责积分区块链项目区块链架构设计,专注于区块链技术框架Fabric的技术研究,目前为深圳科协、金链盟等机构的Fabric技术框架培训讲师,同时作为中国首批区块链系统功能测试评审专家参与区块链系统的评审。
区块链开发指南目录预览
第1章 区块链基础
第2章 区块链进阶
第3章 密码学基础
第4章 比特币区块链开发
第5章 以太坊智能合约开发
第6章 Fabric原理和实操
区块链开发指南精彩内容
比特币于2009年诞生,在很长一段时间内,人们只知比特币,不知区块链。从2015年开始,区块链像狂风一样席卷全球,倍受金融界和科技界的关注;2015年年底,区块链技术逐渐得到国内金融界和科技界的了解和认同。
区块链行业的蓬勃发展源于区块链有可能给各行业带来巨大的变革。麦肯锡在2016年年初发布报告,指出区块链技术将在未来五年内颠覆众多行业,特别是银行业和保险业;埃森哲预测到2025年,区块链技术每年可帮助全球8大投资银行节省80亿美元至120亿美元的基础设施成本。
全球金融巨头如IBM、高盛、摩根大通、花旗银行、中国平安、瑞银、德勤、毕马威等纷纷布局区块链;区块链初创公司在全球范围内如雨后春笋般崛起,发展速度惊人。从2012年以来,全球区块链创业领域共发生207起融资/并购事件,融资额高达14亿美元。
截至2017年3月,区块链在金融业的落地应用包括跨境支付、清算结算、互助保险、电子票据、商业银行抵押品、贸易金融、数字资产登记、银行间贸易、银行间对账与审计、监管与简化流程、积分、征信、外汇交易市场、证券清算和交割等。
区块链技术还能解决供应链管理、物联网、医疗、军事、政务等领域的很多问题。例如,Warmart试图用区块链保障我国市场的猪肉供应链安全;医疗领域中,生成基于区块链的、不可更改的电子病历、检验报告等用于存证,方便解决医疗纠纷;军事防卫和信息安全化中,区块链技术可实现信息防御平台的现代化;政务中,区块链可以简化文件归档与政府公共档案管理,并且可用来发放政府社保、养老金等社会福利及居民身份存证等。
区块链开发指南截图


区块链技术丛书
区块链开发指南
申屠青春 主编
ISBN:978-7-111-57120-9
本书纸版由机械工业出版社于2017年出版,电子版由华章分社(北京华
章图文信息有限公司,北京奥维博世图书发行有限公司)全球范围内制
作与发行。
版权所有,侵权必究
客服热线:+ 86-10-68995265
客服信箱:service@bbbvip.com
官方网址:www.hzmedia.com.cn
新浪微博 @华章数媒
微信公众号 华章电子书(微信号:hzebook)目录
推荐序一 区块链的价值实现
推荐序二 区块链,推动金融代际跃升的新力量
推荐序三 区块链技术的现实和未来
前言
第1章 区块链基础
1.1 交易和交易链
1.1.1 比特币地址
1.1.2 交易的本质
1.1.3 输入和输出
1.1.4 交易类型
1.1.5 找零地址
1.2 区块和区块链
1.2.1 区块结构
1.2.2 创世块
1.2.3 区块链原理
1.3 挖矿、矿池
1.3.1 挖矿原理与区块的产生
1.3.2 挖矿难度
1.3.3 矿池原理与商业模式1.4 脚本系统
1.4.1 脚本特点
1.4.2 脚本运行过程
1.4.3 脚本操作码解读
1.4.4 脚本执行过程
1.5 合约应用案例
1.5.1 合约应用原理
1.5.2 示例1:提供押金证明
1.5.3 示例2:担保和争端调解
1.5.4 示例3:保证合约
1.5.5 示例4:使用外部状态
1.5.6 示例5:跨链交易
1.5.7 示例6:支付证明合约
1.5.8 示例7:特定对象的快速调整(微)支付
1.5.9 示例8:多方去中心化彩票
参考资料
第2章 区块链进阶
2.1 外带数据
2.1.1 OP_RETURN外带数据
2.1.2 Multi-Signatures外带数据
2.2 Counterparty2.2.1 Counterparty附生链的实现机制详解
2.2.2 发送
2.2.3 订单
2.2.4 发行
2.2.5 广播
2.2.6 赌约
2.3 挖矿算法解析
2.3.1 PoW挖矿算法及分析
2.3.2 PoS股权证明算法及分析
2.3.3 DPoS股份授权证明算法及分析
2.4 Sidechains
2.4.1 侧链背景
2.4.2 技术原理
2.5 最新比特币技术
2.5.1 IBLT
2.5.2 隔离见证
2.5.3 闪电网络
2.5.4 RSMC
2.5.5 HTLC
参考资料
第3章 密码学基础3.1 Hash函数
3.1.1 技术原理
3.1.2 SHA-1算法
3.1.3 SHA-2算法
3.1.4 SHA-3算法
3.1.5 RIPEMD160算法
3.2 椭圆曲线密码
3.2.1 椭圆曲线方程
3.2.2 公钥和私钥的产生算法
3.3 ECDSA数字签名
3.4 Schnorr数字签名
3.4.1 技术思想
3.4.2 Schnorr与ECDSA的异同
3.5 Bloom filter
3.5.1 技术原理
3.5.2 应用案例
第4章 比特币区块链开发
4.1 Bitcoin的编译过程
4.1.1 Ubuntu下的编译
4.1.2 Mac下的编译
4.1.3 Windows下的编译4.2 代码剖析
4.2.1 主要模块
4.2.2 初始化和启动
4.2.3 P2P网络
4.2.4 交易和区块
4.2.5 脚本系统
4.2.6 挖矿
4.2.7 私钥
4.3 性能实战
4.3.1 建立私链
4.3.2 优化改进
4.4 API开发
4.4.1 命令行调用
4.4.2 RPC API调用接口
4.4.3 如何调用API进行开发
4.4.4 通过命令实现区块链的查询实例
第5章 以太坊智能合约开发
5.1 以太坊
5.1.1 以太坊的定义
5.1.2 下一代区块链
5.1.3 以太坊虚拟机5.1.4 以太坊的工作原理
5.2 以太坊账户管理
5.2.1 账户
5.2.2 钥匙文件
5.2.3 创建账号
5.3 更新、备份、恢复账号
5.3.1 更新账号
5.3.2 账号备份和恢复
5.4 公有链、联盟链、私有链及网络配置
5.4.1 以太坊网络
5.4.2 公有链、私有链和联盟链
5.4.3 如何连接
5.4.4 更快地下载区块链
5.4.5 静态节点、信任节点和启动节点
5.5 搭建测试网络和私有链
5.5.1 Modern测试网
5.5.2 设置本地私有测试网
5.6 账户、交易核心概念及投注合约解析
5.6.1 外有账户与合约账户
5.6.2 什么是交易
5.6.3 什么是消息5.6.4 什么是gas
5.6.5 估算交易成本
5.6.6 账户交互示例:投注合约
5.7 深入浅出智能合约
5.7.1 合约的定义
5.7.2 以太坊高级语言
5.7.3 写合约
5.7.4 编译合约
5.7.5 创建和部署合约
5.7.6 与合约互动
5.7.7 合约元数据
5.7.8 测试合约和交易
5.8 如何部署、调用智能合约
5.8.1 RPC
5.8.2 惯例
5.8.3 部署合约
5.8.4 和智能合约互动
5.8.5 Web3.js
5.8.6 控制台
5.8.7 查看合约与交易
5.9 智能合约案例实战参考资料
第6章 Fabric原理和实操
6.1 超级账本项目背景
6.2 Fabric简介
6.3 系统架构
6.3.1 交易
6.3.2 区块链数据结构
6.3.3 节点
6.4 交易背书的基本流程
6.4.1 客户端创建交易后发送到它所选择的背书节点
6.4.2 背书节点模拟交易,然后生成背书签名
6.4.3 提交客户端获取交易的背书,通过排序服务广播
6.4.4 排序服务向所有节点投递交易消息
6.5 背书策略
6.5.1 背书策略规范
6.5.2 交易评估与背书策略
6.5.3 背书策略示例
6.6 验证总账(1.0版本之后的功能)和原始总账检查点(精简)
6.6.1 验证总账
6.6.2 原始总账检查点
6.7 Fabric V1.0开发者快速入门6.7.1 前置条件和系统配置
6.7.2 下载源代码,创建Fabric网络
6.7.3 生成配置文件
6.7.4 使用Docker创建Fabric网络创建加入通道(账本)
6.7.5 示例合约执行过程解析
6.7.6 查看智能合约执行日志
6.7.7 手工创建和加入通道
6.7.8 使用命令行工具部署、调用、查询智能合约
6.7.9 开发环境故障排除
6.7.10 Fabric常用的Docker命令
6.8 智能合约开发
6.8.1 智能合约的定义
6.8.2 GO语言智能合约的开发和部署
6.8.3 Java智能合约的编写与部署
6.8.4 开发和提交代码
相关术语
附录A 国内区块链联盟介绍
附录B 《ChinaLedger面向中国资本市场应用的分布式总账白皮书》全
文推荐序一 区块链的价值实现
区块链和分布式账本技术是全球十大战略技术趋势之一,也是我国
金融界、科技界过去一年高度关注的热点之一。毫无疑问,2017年我国
金融界、科技界将会加大在区块链和分布式账本技术领域的投入,同时
市场上将会出现几个实际的应用。
深圳市金融科技协会(原深圳市金融信息服务协会)在研究推动区
块链和分布式账本技术及应用的过程中,遇到了一批积极探索、深入钻
研、大胆应用这门技术的志同道合者,并与微众银行、国信证券、博时
基金、富德保险、深证通、银链科技、招银网络、致远速联、中证信用
等25家金融机构和金融科技企业共同发起并成立了金融区块链合作联盟
(深圳)。在这个过程中,我也加深了对申屠青春、姚辉亚、宿旭升等
区块链积极推动者的认识,与他们建立了友谊,其中申屠青春就是本书
的作者之一。
申屠青春近几年专注于研究区块链技术和应用,技术能力得到了业
内的高度认可。他对区块链的热爱程度近乎痴迷,凡是区块链圈内的交
流,几乎都有他的身影。对于区块链技术和标准,他都热心地和业内人
士进行分享。他为金链盟的筹建和运作做了不少有益的工作,也是成立
金链盟的倡议者之一。自从2015年,人们发现了区块链巨大的潜在价值后,区块链技术已
经飞速发展了两年多。这两年之中,区块链成为主流金融圈所推崇和研
究的创新技术。全球众多大型金融机构都投入了人力财力进行区块链研
究,R3、HyperLedger等大大小小的组织也纷纷成立。我国的反应也很
迅速,金链盟、ChinaLedger、工信部区块链联盟快速发展起来。从行
业巨头参与的积极性和政府的重视程度来看,我国显然不想在区块链领
域落后。
2008年年底,中本聪在他的论文中提出一个点对点电子支付系统的
构想,并且于2009年实现了比特币的原型。这个系统可以使地球上的任
何人通过互联网以极致的效率进行货币交换和价值传递,无需任何第三
方机构。比特币没有发明任何新技术或算法,其中涉及的技术工作量证
明、时间戳、公钥体系等早已成熟。神奇的是,中本聪通过对这几项技
术的组合解决了无需可信第三方的数字资产所有权问题。从广义上讲,这些技术和思想的集合正是如今谈论的区块链。
从技术上看,区块链算是一个自由开放、没有固定形式的开源社
区。众所周知,Linux开源社区中,Linus具有绝对权威来定制发展路
线。有趣的是,区块链社区不存在这样一个角色,中本聪在2010年就在
互联网上消失了,至今也没能确认其真实身份。也就是说,没有任何官
方定义区块链该怎么实现,以及未来该怎么样发展。没有方向也许正好
说明“一切皆有可能”。去权威的社区呈现出一种百花齐放的状态,并且涌现出了大量的优
秀项目和先进理念。纵览区块链的发展历史,大多创新点可归纳为共识
机制、智能合约、隐私安全、可扩展性这几个方面,由于技术实现的灵
活性相当大,因此更多的争论和共鸣在于设计理念和哲学上。
共识机制
中本聪在提出以工作量证明(PoW)机制作为共识算法之后,部分
人认为耗能过大,于是就有了Sunny King设计的“环保”的股权证明
(PoS)机制,后续又发展到Bitshares改进的股份授权证明(DPoS),并衍生出了更多的类PoS机制。从公有链的角度来看,共识算法就是公
平和效率孰重孰轻的决策,技术实现不是难点,难点在于如何从社会
学、从人性出发去设计激励机制。各种共识算法的支持者都有其合理的
理由,不同共识的争论即使到现在也还一直存在。
另一个领域,金融机构的关注点在于效率、不可篡改及对应用的支
持,由于不需要链上的代币激励,因而改进的拜占庭容错(PBFT)、PAXOS、RAFT等传统分布式一致性算法就成为首选。
由此也就形成了两种区块链生态:公有链和联盟链。公有链可以任
意加入,联盟链是许可加入,联盟链的用户大多是机构或公司,需要区
块链契合自身的业务模式。从共识机制开始,区块链就走向了两条不同
的道路,最终双方是竞争还是融合,有待后续观察。智能合约
对智能合约的探索是出于对比特币区块链低效的脚本系统的不满,该脚本使用的是非图灵完备的堆栈语言,只能实现有限的功能。
一些智能合约研究者一直追求在区块链上运行强大的机器语言,让
每个用户都能见证其运行的过程和结果,实现“程序即规则”(Code is
Law)的智能环境。从图灵完备的以太坊EVM、超级账本ChainCode到
Chain平台的ChainCore,研究者的目标是在有限的存储空间中设计一个
完备合约语言和高效的底层虚拟机,甚至将传统开发语言(如CC++、Java)移植到区块链上。效率和安全性的改进依然任重道远,这也是区
块链领域最有技术含量的发展方向之一。
隐私安全
区块链中的个人隐私保护是强需求,特别是金融机构要使用的区块
链,保护客户隐私是基本的合规条件;但同时还不能产生绝对隐私,必
须要让监管者知道交易内容。
隐私安全的研究者大多需要深入掌握密码学知识,这不是一件轻松
简单的工作。ZCash使用了零知识证明算法来隐藏交易双方在区块链的
信息;比特币使用多输入多输出交易、隐身地址(Stealth address)和其
他更多古老的混币方案来保护用户隐私。联盟链将采用数字证书认证用
户,隔离一切非相关用户的数据访问。隐私安全是一把双刃剑,技术上满足隐私保护的需要,同时也增加了系统实现的复杂度;在降低透明性
的同时,也要让监管更方便。
可扩展性
用户交易数的增多不可避免地会带来区块链数据膨胀的问题,可扩
展性解决的是如何尽可能高效地存储不可篡改的区块链数据。业界讨论
的焦点放在如下两种方向的解决方案上:
1)从交易层把部分交易迁移到子区块链上运行,即侧链、闪电网
络;
2)从减少存储上着手解决,对原始数据进行裁剪分片,研究更安
全的瘦客户端,只存储非全量验证数据就可正常工作。
也许从交易层进行分解可以让问题一劳永逸,但这种方法的可靠实
现没有理论上那么简单。侧链技术现在正处于原型验证期,到真正实用
的程度还需要一段时间。
从上述维度来看,区块链开发是一种综合能力的体现,其开发模式
与互联网应用大有不同。传统互联网应用要求快速迭代,不断试错,区
块链应用反而在发布前需要细致测试,对未来规划要有清晰的认识,因
为一旦上线了就不是开发者能控制的:没有灰度发布、没有回滚下线、试错的成本极高。区块链是一台永不停止的信任机器,任何一次改变都需要通过共识,要明白共识的达成是极其困难的,所以在开发时一定要
十分谨慎。
区块链技术的发展还面临着很多的挑战,需要更多的人才加入到探
索者的队伍中。区块链开发更是需要复合型人才,分布式网络、分布式
计算、密码学、编译原理、经济学等方面的内容都需要涉及,国内缺乏
区块链综合技术的教程,这本书来的正当其时。本书各个主题的作者都
是相关领域的专家或创业者,他们是对区块链理解最深入的一批人,具
有较强的实战经验。书中各章节内容深入浅出,按时间顺序介绍区块链
的技术发展,并且加入了大量的代码示例,鼓励读者动手实践,以帮助
读者快速掌握区块链的开发技能,是一本值得一读的实战型好书!
希望大家在阅读本书后有所收获。
邹胜
2017年4月
邹胜,深圳证券交易所前副总经理、深圳证券通信公司前董事长,拥有24年证券金融行业经验,曾领导深交所IT和深证通打造了第五代核
心交易系统、中国证券期货业南方中心、金融云等业内领先的金融科技
基础设施。现任深圳市金融科技协会联席会长,并致力于分布式交易技
术在中国证券金融行业的应用推广。推荐序二 区块链,推动金融代际跃升的
新力量
金融为解决信息不对称而生,纵观3000年的发展历程,金融业态的
变迁始终围绕着信息如何对称而展开,并基于外界环境的影响在金融化
与科技化两个维度上演绎迭代。从金融化维度上看,发展主线围绕
着“有中心”与“无中心”展开,哪一种业态更能解决信息对称,在不同的
时空下,基于不同的金融工程技术而有不同的呈现,近400年的现代金
融史正是一条从“无中心”到“有中心”再到“多中心”进而又可能回到“无中
心”的演变轨迹。从科技化维度上看,信息技术的进步对金融业的影响
非常敏感,人类历史上每一次信息技术的大提升都会带来金融业态的一
次跳跃,尤其是近一百年来,电报、电话、海底电缆、计算机、互联
网……无不带来金融业态的深刻变革,变革的指向始终是从“信息不对
称”到“信息有限对称”并向着“信息对称”发展。
回顾我国改革开放后40年的金融发展,1997年无疑是至关重要的一
年,那一年我国的银行业成功推出了网上银行,以此为标志,中国开始
进入互联网金融时代。伴随着互联网这一千年一出的技术革命,金融业
态发生着历史性的变革。不论我们以“互联网金融”还是以“金融互联
网”来称谓这场变革,都不可否认金融业在解决信息对称的有效性,以及达成信息对称的效率性上,都得到了大幅提升,尤其是在以4G和智
能手机为载体的移动金融出现之后,更是如此。
当然在这场长达20年的互联网金融变革中,互联网技术的内在缺陷
也日益显现,网上信息的失真、可篡改、无法确权、加密强度低等特性
都制约着金融业务的进一步深入,信息量越大反而越限制了信息的有效
性,互联网金融开始触及自身发展的瓶颈。如何寻找新一代的替代技术
解决信息的“二次不对称”,是金融业下一步演变的关键。
幸运的是,互联网本身也在迭代,并在其中一个迭代方向上出现了
区块链技术。BlockChain,从诞生的第一天起就具有信息的真实、不可
篡改、可确权、强加密等特征,这在某种意义上正是互联网技术的“扬
弃”。而其在物理层和通信协议层与互联网的兼容,更使得区块链技术
的应用成本低、推广简便。
金融业要求信息应真实、安全、准确、权属清晰,因此我们有理由
相信,互联网金融下一步演绎的方向是“区块链金融”,在区块链的路径
上,继续探索哪一种“中心化形态”更有利于解决信息的对称性和效率
性,从而将金融业态推向一个新的高度。
如果我们有能力预测“区块链金融”的发展轨迹,那么我们是否会形
成如下这样一些观点。
·互联网账户的区块链化。互联网金融的效应之一是让每一个金融机构都能平等地接触到终端用户,不受地域、网点、规模所限,重构大
中小金融机构在金融领域重要性的自上而下排序的金字塔结构,带有典
型的金融领域内的“普惠”特征。然而,这种扁平的平等触达客户的金融
结构还需要另一个先决条件,那就是中小金融机构必须用技术手段自证
自己的信用,自证安全可靠。显然,这有赖于区块链技术的运用。因
此,在线开户、存款、支付、交易等业务整体向区块链平台迁移成为一
种必然。
·支付工具和支付体系的区块链化。以国内支付领域的现状来看,扫码支付替代磁条卡支付的趋势已经确立。然而,扫码支付的安全性始
终是各方担忧的焦点。一方面,在二维码的生成与二次传播上如何增强
加密强度;另一方面在二维码底层第三方支付的虚拟账户层面或银行的
二类账户层面如何增强加密强度,必然会成为区块链技术发挥作用的结
合点。此外,从商户收单的领域来看,商户体系只是从围绕银行展开收
单和清算转变为围绕第三方支付公司展开,仍是其他“中心”的从属,基
于区块链技术构建的以各商户互为中心的、以预付费卡为支付载体
的“自收单体系”也将成为支付领域变革的一个重要方向。
·征信的区块链化。互联网的持续推进引领着全球进入大数据时
代,而征信在大数据时代呈现出了完全不同的业务逻辑和规则,但就目
前来看,数据的权属问题将构成大数据征信模式最重大的挑战。而数据
是谁的、在哪里确权、如何调用、如何计价等问题都可以借助区块链技术加以解决,从这个意义上说,大数据征信的内核是区块链征信。
·资产证券化的区块链化。资产证券化技术成功解决了基础资产如
何变成可交易的金融工具及如何计价交易的难题,从而极大地提升了金
融资产的周转效率,因此被视为20世纪最重要的金融创新。然而,其基
于线下的风险控制流程已难以适应互联网时代对金融效率和信息全面性
的要求,因此,资产证券化的互联网模式已成为金融B2B领域的重要方
向。同样,资产证券化各参与方信息的准确、不可篡改、确权、安全加
密等也是ABS互联网化必须要面对的问题,也必然要辅助以区块链技术
加以解决。
·金融监管的区块链化。随着金融体系的日益庞大和复杂,如何监
管已经成为世界难题。2008年美国次贷危机诱发的全球金融危机,深刻
反映出全球监管的滞后与漏洞。然而,随后出台的一系列监管补救法
案,包括多德弗兰克法案、沃克尔法案、新巴塞尔协议等,无一例外仍
在延续旧有的“规则性监管”的理念和思路,在所谓的金融杠杆控制上做
出各种主观性的设置,全然没有看到在新技术运用上有突破性的理念和
方法。基于后互联网时代的一系列信息技术已经完全可以做到实时、同
步、自合理性设置、自预测性、自迭代的监管,即“数据性监管”,这也
必然会成为下一轮全球金融监管改革的方向。区块链,基于其独特的信
息处理属性,无疑会在“数据化监管”方面发挥重要的作用,有效构建监
管部门、金融机构、金融客户之间的合理数据纽带。恰如20世纪90年代末互联网进入应用开发阶段一样,区块链的产业
应用同样需要一批具备区块链开发能力的人员、团队、技术组织,如何
高效率地普及区块链技术、高效构建区块链技术生态至关重要。申屠青
春等人编著的《区块链开发指南》,是一部难得一见的区块链实用著
作,系统性地总结和提炼了区块链技术的核心属性,并从开发者的视角
予以展开,相信在区块链技术和开发生态构建方面一定会发挥重要作
用。也希望有更多区块链领域的技术专家和先行者贡献自身的知识和体
会,共同推进区块链这一独特的信息技术,使其更迅速地与金融场景相
结合,共同提升我国的金融效率与质量。
曹彤
国金ABS云创始人
厦门国际金融技术有限公司董事长
中国区块链研究联盟副主任推荐序三 区块链技术的现实和未来
一直以来,科学技术都是推动时代发展的原动力。20世纪90年代,随着互联网的出现,人类的信息传递方式发生了重大改变,引发了新闻
媒体行业的革命,促进了电子商务的流行;移动互联网的发展带来的影
响更为巨大,激发了社交的变革,带来了更为便捷、高效的包括金融服
务、出行服务等在内的各类新型社会服务方式,而且社会的协作模式和
运作效率从整体上也发生了深刻的变化,这些正悄然改变着社会。区块
链作为近年来新兴的IT技术,对任何由第三方机构来进行信用背书的社
会协作模式都可能会带来改变,并在金融服务、企业运作、社会生活甚
至社会治理等领域引发深远的变革。
区块链是一种去中心化、去信任化的分布式账本技术,由分布式数
据存储、点对点传输、共识机制、加密算法等多种技术集合而成。区块
链是起源于比特币的底层技术,自2009年被提出以后,近年来已成为各
大金融机构、IT公司、投资机构、咨询机构关注的热点,产业界纷纷加
大研发投入力度。互联网全面发展以后,已经近乎完美地解决了信息传
递的问题,但是还不能自由地实现价值点到点的传递,价值的传递仍然
需要中心化的可信第三方来完成,在一些应用场景中仍存在一定的局限
性。区块链的出现能够在没有信任基础的双方之间建立信任,完成价值
传递,因而被誉为创造信任的机器。由于其具有去中心、去信任及不可篡改的特点,区块链被认为可以应用在多种业务场景中,用来建立信
任,提升透明性、可靠性与安全性。目前,区块链的应用已经不只是在
数字货币和支付结算领域,在供应链金融、数字资产交易、共享经济、食品安全、慈善等多个领域均有探索,而且还将为云计算、移动互联
网、物联网等新一代信息技术的发展带来新的机遇。
当前,区块链一方面带有耀眼的光环,另一方面在现实应用中还存
在着很多问题亟待解决,比如:大量冗余存储、共享的数据带来了数据
安全和隐私保护等方面的挑战;在去中心化、匿名的区块链系统中,使
用私钥管理用户资产,私钥一旦丢失,对应的资产所有权也将丢失,而
如今应用对于私钥保护基本上是用软件来实现的,理论上都存在被攻破
的可能性;另外,链上敏感数据的保护与验证也存在一定的矛盾,我们
既希望重要的信息对于无关者不可见,又需要相关者在一些场景下验证
信息;除此之外,智能合约也存在着一些问题,如现有司法系统对智能
合约的理解和接受程度问题,部分定性合同条款难以用代码来表述的问
题,代码缺陷对智能合约执行影响的问题等。璞玉亦须雕琢,对于区块
链的这些问题还需要进一步探索,还有大量艰苦的工作要做。
对于区块链,业内目前有两种截然相反的态度。一种是过于乐观,看到区块链技术在比特币应用的成功之后,认为区块链技术可以很快地
为社会各方面带来翻天覆地的变化。另一种态度则过于悲观,认为区块
链存在的问题太多,除了比特币之外再无成功应用,且区块链可以做的工作传统信息技术完全可以解决,甚至更高效。有业内人士担心这又是
一个被过度炒作的概念,最终会不了了之。从区块链技术的发展历史来
看,来源于比特币的区块链技术,具有无限制加入、匿名机制、公开账
本、工作量证明共识算法等技术特点,这些特点比较适合支付结算相关
应用,但不具有普适性。后来为了适应不同的应用场景,在比特币平台
之后,又陆续出现了多种底层平台,包括致力于打造“世界计算机”的以
太坊平台、提供跨行业解决方案的HyperLedger项目下的Fabric平台、为
受监管的金融行业提供专业解决方案的R3 Corda平台等,这些平台相互
影响并不断发展。目前区块链技术除了影响力最大的比特币之外,大部
分应用还处于探索阶段,成功的应用不多,但是从当前各方面的探索
中,我们也看到了区块链这种去中心、去信任的价值传递网络的巨大潜
力。区块链技术目前尚处在发展的初期阶段,现在最重要的是以务实的
态度深入研究,特别是要吃透技术细节,结合实际场景,推动区块链相
关应用扎实落地。在这方面,IT工程师们能够发挥更加积极的作用。
虽然区块链技术仍在发展之中,仍有不少问题需要解决,但是随着
基础平台的不断完善,区块链应用将得到快速发展。根据Gartner分析报
告预测,预计经过3到5年的发展,区块链应用的落地会出现大规模的增
长;未来10年左右,整个区块链市场将趋于成熟,广泛应用在智能合约
驱动类业务、数字货币业务、机构间和机构内业务及公共记录等领域。
目前,已有众多从理论和业务层面探讨区块链的图书和文章,但是技术
类图书却非常稀缺。本书对于区块链的开发做了系统的介绍,是献给站在IT前沿开拓者的佳作。作为IT从业者,此时更需要把握当下,因为未
来已来。让我们怀揣梦想,一起努力,共同打造更加完善的区块链服
务,用科技创造美好未来!
周天虹
招商银行信息科技部总经理
2017年4月前言
比特币于2009年诞生,在很长一段时间内,人们只知比特币,不知
区块链。从2015年开始,区块链像狂风一样席卷全球,倍受金融界和科
技界的关注;2015年年底,区块链技术逐渐得到国内金融界和科技界的
了解和认同。
区块链行业的蓬勃发展源于区块链有可能给各行业带来巨大的变
革。麦肯锡在2016年年初发布报告,指出区块链技术将在未来五年内颠
覆众多行业,特别是银行业和保险业;埃森哲预测到2025年,区块链技
术每年可帮助全球8大投资银行节省80亿美元至120亿美元的基础设施成
本。
全球金融巨头如IBM、高盛、摩根大通、花旗银行、中国平安、瑞
银、德勤、毕马威等纷纷布局区块链;区块链初创公司在全球范围内如
雨后春笋般崛起,发展速度惊人。从2012年以来,全球区块链创业领域
共发生207起融资并购事件,融资额高达14亿美元。
截至2017年3月,区块链在金融业的落地应用包括跨境支付、清算
结算、互助保险、电子票据、商业银行抵押品、贸易金融、数字资产登
记、银行间贸易、银行间对账与审计、监管与简化流程、积分、征信、外汇交易市场、证券清算和交割等。区块链技术还能解决供应链管理、物联网、医疗、军事、政务等领
域的很多问题。例如,Warmart试图用区块链保障我国市场的猪肉供应
链安全;医疗领域中,生成基于区块链的、不可更改的电子病历、检验
报告等用于存证,方便解决医疗纠纷;军事防卫和信息安全化中,区块
链技术可实现信息防御平台的现代化;政务中,区块链可以简化文件归
档与政府公共档案管理,并且可用来发放政府社保、养老金等社会福利
及居民身份存证等。
由此可见,区块链将带来一场巨大的变革。正如德勤的报告中所预
言的一样:“区块链是一场改变信任的革命,将重塑金融行业。”而它作
为一项伟大的技术,不仅仅对于金融行业有革新性,对于其他行业,也
会有深远的影响。
而今实施“区块链+”战略所面临的最大难题是:极度缺乏从业人
员。很多金融机构和企事业单位对区块链还停留在概念阶段,其开发人
员不懂区块链;大部分对区块链技术感兴趣的人,或者想要从事区块链
行业的技术人员,未能系统地了解区块链的原理和发展,缺乏区块链开
发者应有的知识和技术储备。
为了让更多的开发人员转变成区块链开发者,让更多现有的区块链
开发人员系统地理解区块链技术,在区块链领导媒体巴比特的提议和牵
头下,成立了《区块链开发指南》编写小组,开始构思、编写本书。编写小组成员有:银链科技CEO申屠青春、深圳大学教授张鹏、币
信资深程序员宋波、朝夕网络CEO汪晓明、万达网络区块链研发中心总
经理季宙栋、华安保险系统架构师左川民、巴比特区块链资深工程师易
长军。
本书内容由申屠青春负责组织,共包含六个章节,具体分工如下:
申屠青春编写第1章和第2章的大部分内容,易长军对本部分内容亦有贡
献,币信的樊渊文贡献了1.4.2节、1.4.3节和1.4.4节,比特大陆的潘志彪
贡献了2.5.2节、2.5.3节和2.5.4节;张鹏编写第3章;宋波编写第4章;汪
晓明编写第5章;季宙栋编写第6章的实操部分,左川民编写第6章的原
理部分。此外,银链科技的林素兰参与第1章和第2章部分内容的编辑,万达网络的丛宏雷、张梦航参与第6章实操部分内容的编写。
本书以比特币、以太坊、Fabric三种区块链的技术原理和实际操作
为主要目标,全书具体内容如下。
第1章介绍比特币区块链,包括交易和交易链、区块和区块链、挖
矿、矿池、脚本系统、合约应用案例等内容,向读者们介绍区块链基础
知识。
第2章讲述区块链进阶技术,包括外带数据原理、Counterparty原
理、挖矿算法解析、侧链技术,以及最新的IBLT、隔离见证、闪电网
络等。第3章的主要内容是区块链中使用的密码学基础,包括Hash函数、椭圆曲线密码体系、ECDSA签名、Schnorr数字签名和Bloom filter算法
等,向开发者介绍密码学相关算法。
第4章是比特币区块链的编译、代码剖析、建立私链及API开发等实
操内容。
第5章介绍以太坊的技术原理,包括以太坊简介、账户管理、交易
原理、智能合约等,还涉及搭建私有链,智能合约开发、部署和调用等
实操过程。
第6章介绍了IBM开源的区块链底层技术平台Fabric的原理和实操,对Fabric系统架构、节点、验证总账、交易背书的基本流程进行了详尽
独到的分析,对Fabric的私有链建立和配置、链上代码的开发过程进行
了详细的描述,为开发者使用Fabric提供技术指导。
最后,感谢编写小组各成员的配合和支持,使本书最终得以完本。
感谢巴比特的李涛,时时督促此书的编写;感谢机械工业出版社华章公
司的编辑杨绣国为本书顺利出版付出的努力。编写小组期待本书能够在
区块链应用开发中给开发者以参考和启发。由于成书仓促,错误之处在
所难免,恳请广大读者朋友批评指正。
申屠青春2017年4月于深圳第1章 区块链基础
区块链究竟是什么?狭义地说,区块链就是比特币的底层技术;不
过,经过7年的发展,区块链已经不再“依附于”比特币,而是独立地发
展成为了一种革命性的技术,比特币则是区块链最大、最成功的应用。
从技术层面来看,区块链是一个基于共识机制、去中心化的公开数
据库。共识机制是指在分布式系统中保证数据一致性的算法;去中心化
是指参与区块链的所有节点都是权力对等的,没有高低之分,同时也指
所有人都可以平等自由地参与区块链网络,唯一的限制就是个人自己的
选择;公开数据库则意味着所有人都可以看到过往的区块和交易,这也
保证了无法造假和改写。基于以上特性,可以总结得出:区块链由许多
对等的节点组成,通过共识算法保证区块数据和交易数据的一致性,从
而形成一个统一的分布式账本。
从价值层面来看,区块链是一个价值互联网,用于传递价值。目前
的互联网仅用来传递消息,但是还不能可靠地传递价值;而比特币区块
链却可以在全球范围内自由地传递比特币,并且能够保证不被双花、不
被冒用。从这个角度来说,区块链是记录价值、传递消息和价值本身转
移的一个可信账本。
这里要提一下区块链在维基百科上的官方定义:一个区块链是一个基于比特币协议的不需要许可的分布式数据库,它维护了一个持续增长
的不可篡改的数据记录列表,即使对于该数据库节点的运营者们也是如
此。简而言之,区块链就是区块用某种方式组织起来的链条。在区块链
中,信用或记录被放在各个区块中,然后用密码签名的方式“链接”到下
一个区块。这些区块在系统的每一个节点上都有完整的副本,所有的信
息都带有时间戳,是可追溯的。事实上,在区块链创建之初,我们在大
多数情况下谈论的区块链都是比特币的底层实现方式。
基于区块链的系统和以往的其他系统存在很多不同之处,以区块链
技术为核心的系统包括如下四大最主要的特点。
·Distributed(分布式的)
·区块链是全球化的,系统上的节点是运行在太平洋某个小岛的笔
记本电脑上还是运行在中国某个小镇的服务器上,对系统本身来说都是
一样的,除了网络连接速度有区别之外,其他没有任何区别。区块链没
有中心节点,数据分布式地存储在各个节点上,即使绝大部分节点毁灭
了,只要还有1个节点存在,就可以重新建立并还原区块链数据。
·Autonomous(自治的)
·区块链是一种去中心化的、自治的交易体系,这种自治性表现在
两个方面:1)所有节点都是对等的,每个节点都可以自由加入和离
开,并且这一行为对整个区块链系统的运行没有任何影响。所有的节点都是按照相同的规则来达成共识,且无需其他节点的参与。2)区块链
系统本身一旦运行起来,就可自行产生区块并且同步数据,无需人工参
与。
·Contractual(按照合约执行的)
·区块链是按照合约执行的,第一体现在各个节点的运行规则(指
的是交易、区块链或协议)上,按照既定的规则执行,一旦出现违背规
则的行为,就会被其他节点所抛弃;第二体现在智能合约上,智能合约
是一种可程序化的合同条款、规则或规定,包含在每个交易中,交易验
证时必须先运行智能合约,只有通过了验证的交易才能被接受。
·Trackable(可追溯的)
·区块链的数据是公开透明的,不能被篡改,而且相关交易之间有
一定的关联性,因而很容易被追溯。比如比特币区块链,每一枚比特币
都有其特定的来源,通过输入可以追溯到上一个交易,或者通过输出追
溯到下一个交易。
·此外,区块链代码本身也是可追溯的,区块链系统是开源软件,其对于所有的人都是公开的,因此任何人都可以查看并修改这些代码,不过修改后的代码需要经过开源社区上其他程序员的审核。
本书主要讨论区块链技术,这不仅包括了比特币区块链技术,还包含了比特币区块链所没有的一些技术,本章接下来将对区块链的一些基
本知识做一个详细的介绍,包括交易和交易链、区块、挖矿、矿池、脚
本、智能合约等。1.1 交易和交易链
交易是签过名的数据结构,该数据结构会在区块链网络中广播,并
被收集到区块中。它会引用以前的交易,从该交易中发送特定数量的比
特币到一个或多个公钥中(即比特币地址),并且交易未被加密(比特
币体系中没有加密任何数据)。多个交易可组成一个区块(block),这些区块同样也会在区块链网络中传播,一个区块会引用上一个区块,简而言之,区块链就是由区块(block)用某种方式组织起来的链条
(chain)。区块链包括成千上万个区块,而一个区块内又包含一个或多
个交易,上下关联的交易组成了一个交易链,一个交易链内部可能又包
含了多个交易,下面的章节将会对这些知识点进行详细解释。1.1.1 比特币地址
比特币地址是一个由数字和字母组成的字符串,可以与任何想给你
比特币的人分享。由公钥(一个同样由数字和字母组成的字符串)生成
的比特币地址以数字“1”开头。下面是一个比特币地址的例子:
1J7mdg5rbQyUHENYdx39WVWK7fsLpEoXZy
在交易中,比特币地址通常是以收款方的形式出现。如果把比特币
交易比作一张支票,那么比特币地址就是收款人,也就是我们要写
入“收款人”一栏的内容。一张支票的收款人可能是某个银行账户,也可
能是某个公司、机构,甚至是现金支票。支票不需要指定一个特定的账
户,而是可以用一个普通的名字作为收款人,这使得它成为一种相当灵
活的支付工具。与此类似,比特币地址的使用也使比特币交易变得很灵
活。比特币地址可以代表一对公钥和私钥的所有者,也可以代表其他东
西。
比特币地址是由公钥经过单向的Hash函数生成的。用户通常所见到
的比特币地址是经过“Base58Check”编码的,这种编码使用了58个字符
(一种Base58数字系统)和校验码,提高了可读性、避免了歧义,并有
效地防止了在地址转录和输入中产生错误。Base58Check编码也被用于
比特币的其他地方,例如私钥、加密的密钥和脚本Hash中,用来提高可读性和录入的正确性。图1-1描述了如何从公钥生成比特币地址。1.1.2 交易的本质
交易实质上就是包含一组输入列表和输出列表的数据结构,也可称
之为转账记录,这其中就包括了交易金额、来源和收款人等信息,表1-
1就是一个比特币交易的数据格式。
表1-1 比特币交易数据格式图1-1 比特币地址生成流程
下面以一个具体的例子来说明一个区块链上的交易构成。假设有一
个带有一个交易及一个输出的交易A,其中的输入列表和输出列表如下
所示:
Input:
Previous tx: f5d8ee39a430901c91a5917b9f2dc19d6d1a0e9cea205b009ca73dd04470b9a6
Index: 0
scriptSig: 304502206e21798a42fae0e854281abd38bacd1aeed3ee3738d9e1446618c4571d10
90db022100e2ac980643b0b82c0e88ffdfec6b64e3e6ba35e7ba5fdd7d5d6cc8d25c6b241501
Output:
Value: 5000000000
scriptPubKey: OP_DUP OP_HASH160 404371705fa9bd789a2fcd52d2c580b65d35549d
OP_EQUALVERIFY OP_CHECKSIG
上文表示,交易A的输入0从交易
f5d8ee39a430901c91a5917b9f2dc19d6d1a0e9cea205b009ca73dd04470b9a6
的0号输出中导入了50个比特币,然后该输出发送50个比特币到一个比
特币地址的公钥Hash值
(404371705fa9bd789a2fcd52d2c580b65d35549d,该公钥Hash值是十六
进制表示,而非正常的base58表示)。
如果接收者想花掉这笔钱,那么他首先得创建自己的交易B,再引
用该交易A的0号输出作为交易B的输入。1.1.3 输入和输出
输入是对其他交易输出的引用,一个交易中通常列有多个输入。所
有被引用的输出值相加,得出的总和值会在该交易A的输出中用到。
Previous tx是以前交易的Hash值,Index是被引用交易的特定输出号,ScriptSig是一个脚本的前一半(脚本将在后文中详细讨论)。
脚本包含两个部分,一个签名和一个公钥,公钥属于交易输出的收
款人,并且表明交易创建者允许收款人获得的输出金额;另一个部分是
ECDSA签名,是通过对交易的Hash值进行ECDSA签名而得到的。签名
和公钥一起,证明原地址的真正所有者创建了该支付交易。
输出中包含了发送比特币的指令,金额(Value)是以聪
(Satoshi,1BTC=100000000聪)为单位的数值。ScriptPubKey是脚本的
另一半(这点将在后文中详细讨论),可以有多个输出,它们共享了输
入金额。一个交易中的每一个输出都只能被后来的交易当成输入引用一
次。如果你不想丢币,那就需要把所有输入值的总和值发送到一个输出
地址。如果输入是50BTC,但你仅想发送25BTC,那么比特币将创建2
个25BTC的输出:一个发往目标地址,另一个则回到你的地址(称之
为“找零”,详见1.1.5节)。在交易过程中,会产生一笔交易费,作为交
易费支付的任何比特币都不能被赎回,生成这个区块的矿工将获得这笔
交易费。为了验证某个交易的输入已经被授权,可以收集被引用的输出中的
所有金额。比特币体系使用了一个类似于Forth的脚本系统,其目的是验
证从某地址发出的比特币是否真正属于该地址的拥有人,输入的
scriptSig和被引用的输出scriptPubKey会按顺序运行。如果scriptPubKey
返回真,则输入被授权,证明是地址拥有人发出了比特币。通过脚本系
统,发送者可以创建非常复杂的发送条件,人们为了收到金额,首先必
须满足这些条件。举个例子,可以创建一个能被任何人赎回而无需授权
的输出,也可以创建一个需要10个不同签名的输入,或者无需公钥仅由
密码赎回的输出。1.1.4 交易类型
根据目标地址的不同,可以把交易分为如下几种类型。
(1)支付到公钥Hash
scriptPubKey: OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG
scriptSig:
一个比特币地址只是一个Hash值,因而发送者无法在scriptPubKey
中提供完整的公钥,当要赎回比特币时,接收者需要同时提供签名
scriptSig和公钥scriptPubKey,脚本系统会验证公钥的Hash值与
scriptPubKey中的Hash值是否匹配,同时还会检查公钥和签名是否匹
配。检查过程见4.2.5节。
(2)支付到脚本Hash
该类交易非常有意义,未来应该会在某些场合频繁使用。该类交易
的接受地址不是通常意义上的地址,而是一个多签地址,以3开头。比
如,三对公钥对可以生成一个多签地址。需要在生成过程中指定n of 3
中的n,n的范围是[1,3],若n=1,则仅需要一个私钥签名即可花费该地
址的币,若n=3,则需要三把私钥依次签名才可以。
地址以3开头,可以实现多方管理资产,极大地提高安全性,也可以轻松实现基于比特币原生的三方交易担保支付。一个m-of-n的模式如
下:
m {pubkey}...{pubkey} n OP_CHECKMULTISIG
其中,m和n需要满足:1≤n≤20,m≤n。
m和n可以是1 of 1、1 of 2、2 of 3等组合,通常选择n=3。
·1 of 3,最大程度私钥冗余。防丢私钥损失,3把私钥中任意一把即
可签名发币,即使丢失2把也可以保障不受损失。
·2 of 3,提高私钥冗余度的同时解决单点信任问题。3把私钥中的任
意2把私钥可签名发币,对于三方不完全信任的情形,即中介交易,非
常适用。
·3 of 3,最大程度解决资金信任问题,无私钥冗余。必须3把私钥全
部签名才能发币,适用于多方共同管理的重要资产,但是任何一方遗失
私钥均会造成严重损失。
多签地址的交易构造、签名、发送过程与普通交易类似。
(3)挖矿交易
挖矿(coinbase)交易用于凭空产生比特币。挖矿交易只有一个输入,该输入有一个“coinbase”参数,没有scriptSig,“coinbase”中的数据
可以是任意内容,它不会被使用。比特币把压缩的当前目标Hash值和任
意精确度的“extraNonce”都存储在这儿,区块头中的Nonce每次一溢出,它们就会增长。extraNonce有助于扩大工作量证明函数的范围,矿工很
容易修改Nonce(4字节)、时间戳和extraNonce(2~100字节)。
挖矿交易的输出金额在一段时间内是固定值,初始是50个比特币,每21万个区块后减半,目前已经经历了两次减半,因而是12.5个比特
币。输出地址可以是任何地址,一般是矿工或矿池的比特币地址。
Nonce溢出是指在对一个块进行散列时,Nonce从0开始,每计算一
次Hash都要增长一次,因而有可能会出现超过数值范围的情况,这时,extraNonce就要相应增长以存储Nonce。1.1.5 找零地址
在实际的区块链交易中,假设A拥有一个比特币地址,里面包含着
还没有花费过的10个比特币。B也有一个比特币地址,里面一分钱也没
有。当A想向B支付10个比特币时,A地址里的未花费输出变为零,而B
的则会变为10 BTC。如果A想支付的金额与所拥有的相同,自然不会存
在需要找零钱的问题。不过当手头的金额比要支付的大时,找零自然也
是天经地义的事情。
假设A的地址上有35个比特币(如图1-2所示),当A想向B支付8个
比特币时,如图1-2所示,只需要使用包含着20个比特币的那一笔未消
费支出,并设置好要支持的金额即可,剩下的12个比特币则会返回给
A,以便A在将来可以继续使用。
图1-2 找零示意图
这样就有了一个找零机制,实际上,比特币在交易时会把消费时所
用的地址(消费地址)的余额设置为零。当需要支付的金额小于可用余额时,在交易信息中必须告诉比特币网络零钱将要被发送至哪个地址,即“找零地址”。找零地址可能是也可能不是原先的发送地址。除此之
外,发送地址所留下的剩余款项将由网络作为交易费支付给矿工。在上
面的例子里,A可以选择将找回的零钱发送到一个新创建的找零地址
上,或者将原先发送的地址设置为找零地址,并将零钱返回。虽然将发
送地址作为找零地址对A而言是方便了管理,不过这也可能会造成A的
隐私性降低,在一定程度上还可能会影响到B的匿名性。
根据设计,每一笔比特币交易将在一个称为“区块链”的全球性的公
共总账上永久可见,这就意味着任何人随时都可以在上面进行跟踪查
询。通过将某个比特币地址与其使用者关联起来,好事者都可以据此绘
制关于这个人与他人之间的资金转移的关系图。但如果是将找回的零钱
发送至一个新创建的地址,那么就可以让这种追踪变得更加困难。
要理解这一点,可以参考图1-3。假设从地址A发送比特币到地址B
后,零钱返回地址为A,则区块链会揭示地址A向地址B支付了一笔钱。
同样的道理,如果有两个或两个以上地址参与其中,任何涉及这个接收
零钱的找零地址都会揭示A作为支付方的交易。假如某个控制着的任何
接收地址或付款地址的人其身份是众所周知的,那么其他有过交易往来
的各方的身份也有可能被推断出来。
现在想象一下,地址A发起付款到地址B,但此时将找零地址更改
为新生成的地址C,如图1-4所示。如果没有进一步的信息,那么其他人所能知道的,只是有一个交易拆分了地址A的余额至地址B和C。而地址
B或C的主人可能是也可能不是A。由于新地址C的加入,让整个交易的
真相变得更加扑朔离迷:哪一个地址代表着被支付方,哪一个地址代表
着找回的零钱呢?
图1-3 两种找零方案
图1-4 重新生成找零地址
当所有各方都将零钱发送至新创建的地址时,要想将个人身份与地
址相关联,就必须收集更多的信息,并耗费更多的资源。1.2 区块和区块链
比特币网络中,数据会以文件的形式被永久记录,我们称这些文件
为区块。一个区块是一些或所有最新比特币交易的记录集,且未被其他
先前的区块记录。可以将区块想象为一个城市记录者其记录本上单独的
一页纸(对房地产产权的变更记录),或者是股票交易所的总账本。在
绝大多数情况下,新区块会被加入到记录的最后(在比特币中的名称为
区块链),一旦写上,就再也不能改变或删除。每个区块记录了它被创
建之前发生的所有事件。1.2.1 区块结构
一个区块的结构如表1-2所示。
表1-2 区块结构示意图
每个区块都包括了一个被称为“魔法数”的常数0xD9B4BEF9、区块
的大小、区块头、区块所包含的交易数量及部分或所有的近期新交易。
在每个区块中,对整个区块链起决定作用的是区块头,如表1-3所示,接下来本章将会对每一个字段都做出比较详细的解释。
表1-3 区块头描述这里的hashPrevBlock就是区块之所以能够连成区块链的关键字段,该字段使得各个区块之间可以连接起来,形成一个巨大的“链条”。每个
区块都必须要指向前一个区块,否则无法通过验证。这个区块链条会一
直追溯到源头,也就是指向创世区块。很显然,创世区块的
hashPrevBlock的值为零或为空。在区块头中,最关键的一个数据项是一
个随机数Nonce,这串数字是一个答案,而这个答案对于每一个区块来
说都是唯一的,它的特点具体如下。
·这个答案很难获得。
·有效答案有多个,不过我们只需要找到一个答案就可以了。
·其他节点对有效答案的验证很容易。
正是因为问题很难解答,没有固定的算法可以求出答案,所以唯一
的做法就是不断尝试,找寻这个答案的做法就是“挖矿”,可以想象,会
有很多人同时都在“挖矿”,他们之间是相互竞争的关系。区块内包含许多交易,它们通过Merkle根节点间接被散列,以保证
矿工能及时追踪一个正在打包的区块内交易的变化情况。一旦生成
Merkle根节点,那么对包含一个交易的区块做散列所花的时间,与对包
含1万个交易的区块做散列所花的时间是一样的。
目标Hash值的压缩格式是一个特殊的浮点编码类型,首字节是指数
(仅使用了5个最低位),后3个字节是尾数,它能表示256位的数值。
一个区块头的SHA-256(一种单向函数的算法,可形成长度为256位的
串)值必定要小于或等于目标Hash值,该区块才能被网络所接受。目标
Hash值越低,产生一个新区块的难度就越大。
Merkle树是Hash的二叉树。在比特币中会两次使用SHA-256算法来
生成Merkle树,如果叶子个数为奇数,则要重复计算最后一个叶子的两
次SHA-256值,以达到偶数叶子节点的要求。
计算过程:首先按照区块中交易的两次SHA-256进行散列,然后按
照Hash值的大小进行排序,生成最底层。第二层的每个元素则是相连续
的两个Hash值的两次SHA-256的Hash值。之后,会重复这个过程,直到
某一层只有一个Hash值为止,这就是Merkle根。举例来说,想象有3个
交易,a、b、c,那么Merkle根的生成过程如下所示:
d1 = dhash(a)
d2 = dhash(b)
d3 = dhash(c)
d4 = dhash(c) 只有3个元素,是奇数,因而将最后一个元素重算一次
d5 = dhash(d1 concat d2)d6 = dhash(d3 concat d4)
d7 = dhash(d5 concat d6)
这里的d7就是以上三个交易的Merkle根。需要注意的是,Merkle树
的Hash值是小头位序(即高位在后,是数字在计算机中的一种表示形
式)。对于某些实现和计算来说,在散列计算前应该先按位反转,之后
在散列计算后再反转一次。1.2.2 创世块
创世块(Genesis Block)是指区块链的第一个区块,现在的比特币
客户端版本把创世区块号定为0,以前的版本把该区块号定为1。以下是
创世块的一种表示形式,它出现在以前的比特币代码的注释中,第一个
代码段定义了创建该块所需要的所有变量,第二个代码段是标准的区块
类格式,还包含了第一个代码段中缩短版本的数据。
GetHash= 0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
hashMerkleRoot = 0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
txNew.vin[0].scriptSig = 4866047994
0x736B6E616220726F662074756F6C69616220646E6F63657320666F206B6E697262206E6F20726F6C6C65636E61684320393030322F6E614A2F33302073656D695420656854
txNew.vout[0].nValue = 5000000000
txNew.vout[0].scriptPubKey =
0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704 OP_CHECKSIG
block.nVersion = 1
block.nTime = 1231006505
block.nBits = 0x1d00ffff
block.nNonce = 2083236893
CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=
4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1)
CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLocKt
ime=0)
CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030
332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73)
CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
vMerkleTree: 4a5e1e
coinbase参数(看上面的十六进制)中包含了“The Times
03Jan2009 Chancellor on brink of second bailout for banks.”这句话。
这句话翻译过来就是“2009年1月3日,首相第二次对处于崩溃边缘的银行进行紧急救助”,这句话正是泰晤士报当天的头版文章标题(如
图1-5所示)。这应该是一个该区块在2009年1月3日或之后创建的一个
证据,同时也是对银行系统采用部分准备金制度导致不稳定性的一个说
明。图1-5 2009年1月3日的泰晤士报创世块50BTC的收益被发送到如下地址:
1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa,我们称该交易为创世交
易。
创世块的收益花不掉,原因如下:比特币客户端把区块和交易分别
存储在两个数据库中,当客户端发现区块数据库为空时,就会用代码直
接生成一个创世块,但是没有把创世交易存储到客户端的交易数据库
中,比特币网络一旦收到要花掉创世交易输出的交易时,因为在交易数
据库中找不到创世交易,因而都会拒绝,也就是说花不掉这50个币了。
出现这种情况很可能是中本聪为了纪念创世交易,故意而为的。
创世块的数据结构如下所示。
·01000000:指版本号。
·0000000000000000000000000000000000000000000000000000000000000000:
为prev block。
·3BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A:
为Merkle根。
·29AB5F49:时间戳。
·FFFF001D:目标Hash值。·1DAC2B7C:随机数。
·01:交易个数。
·01000000:版本。
·01:输入个数。
·0000000000000000000000000000000000000000000000000000000000000000FFFFFFFF:
前一个输出。
·4D:脚本长度。
·04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73:
scriptsig脚本。
·FFFFFFFF:序列号。
·01:输出个数。
·00F2052A01000000:50 BTC的收益。
·43:指脚本scriptPubKey的长度。
·4104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC:
脚本scriptPubKey。·00000000:锁定时间。
JSON版本的创世块如下所示:
{
hash:000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f,ver:1, prev_block:0000000000000000000000000000000000000000000000000000000
000000000, mrkl_root:4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b,time:1231006505,bits:486604799,nonce:2083236893,n_tx:1,size:285,tx:[
{
hash:4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b,ver:1,vin_sz:1,vout_sz:1,lock_time:0,size:204,in:[
{
prev_out:{
hash:0000000000000000000000000000000000000000000000000000000000000000,n:4294967295
},coinbase:04ffff001d0104455468652054696d65732030332f4a616e2f3230303920
4368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73
}
],out:[
{
value:50.00000000,scriptPubKey:04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e
0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f OP_CHECKSIG
}
]
}
],mrkl_tree:[
4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
]
}1.2.3 区块链原理
区块链是所有比特币节点共享的交易数据库,这些节点基于比特币
协议参与到比特币网络中来。区块链包含每一个曾在比特币系统执行过
的交易,根据这个信息,人们可以找到任何时候任一个地址中的币数
量。
由于每个区块包含前一个区块的Hash值,这就使得从创世块到当前
块形成了一条块链,每个区块必定按时间顺序跟随在前一个区块之后,区块链结构如图1-6所示。因为不知道前一块区块的Hash值,因此没法
生成当前区块,所以要改变一个已经在块链中存在了一段时间的区块,从计算上来说是不可行的,如果它被改变,那么它之后的每个区块都必
须随之改变。这些特性使得双花比特币非常困难,区块链是比特币的最
大创新。图1-6 区块链示意图
如果一个区块是最长块链的最后一个区块,那么诚实的矿工只会在
这个区块的基础上生成后续块(创建新区块时通过引用该区块来实
现)。“长度”是指被计算成区块链的所有联合难度,而不是区块的数
量,尽管这个区别仅仅在防御几个潜在攻击时有用。如果一个区块链中
的所有区块和交易均有效,则该区块链有效,并且要以创世块开头。
对于区块链中的任何区块来说,只有一条通向创世块的路径。然
而,从创世块出发,却可能有分叉。当两个区块产生的时间仅相差几秒
时,可能会产生包含一个区块的分叉。当出现以上现象时,矿工节点会
根据收到区块的时间,在先收到的区块的基础上继续挖矿。哪个区块的
后续区块先出现,那么这个区块就会被包括进主链,因为这条块链更
长。
短区块链(或有效区块链)中的区块没有作用,当比特币客户端转
向另一个长区块链时,短区块链中所有有效的交易都将被重新加入到交
易队列池中,并被包括到另一个区块中。短区块链中的区块收益不会在
长链中出现,因而这些收益实际上是丢失了,这就是比特币网络设定
100个区块成熟时间的原因。
短区块链中的区块经常被称为“孤立”区块,事实上这些区块都有父
区块,并且可能还有子区块,只不过这些区块链未被包含进比特币主链,就好像被孤立了一样。1.3 挖矿、矿池
1.3.1 挖矿原理与区块的产生
比特币的挖矿和节点软件是基于对等网络、数字签名来发起和验证
交易的。节点向网络广播交易,这些广播出来的交易需要经过矿工的验
证,矿工们会用自己的工作证明结果来表达确认,确认后的交易会被打
包到数据块中,数据块会串起来形成连续的数据块链。中本聪本人设计
了第一版的比特币挖矿程序,这一程序随后被开发为广泛使用的第一代
挖矿软件bitcoind,这一代软件在2009年到2010年期间都比较流行。
每一个比特币的节点都会收集所有尚未确认的交易,并且会将其归
集到一个数据块中,这个数据块将和前面一个数据块集成在一起。矿工
节点会附加一个随机调整数,并计算前一个数据块的SHA-256 Hash运算
值。挖矿节点不断进行重复尝试,直到它找到的随机调整数使得产生的
Hash值低于某个特定的目标为止。由于Hash运算是不可逆的,因此寻找
到符合要求的随机调整数将会非常困难,因此需要一个可以预计总次数
的不断试错的过程。这时,工作量证明机制就发挥作用了。当一个节点
找到了符合要求的解,那么它就可以向全网广播自己的结果。其他节点
就可以接收这个新解出来的数据块,并检验其是否符合规则。只要其他
节点通过计算Hash值发现其确实满足要求(比特币要求的运算目标),那么该数据块就是有效的,其他的节点就会接受该数据块,并将其附加
在自己已有的链条之后。
当挖矿时,你会经常对区块头进行散列,你正在挖的区块也会时常
进行更新,一个区块头如上文所述的表1-3所示。
表1-3中的大部分数据项对所有用户都是一致的,不过,在时间戳
上可能会有些区别。如果当前区块的时间戳大于前11个区块的平均时间
戳,并且小于“网络调整时间(Network-Adjusted Time)”+2小时,则认
为该时间戳是有效的。其中的“网络调整时间”是指与你相连接的所有节
点的平均时间。当节点A连接到节点B时,A将从B处得到一个UTC的时
间戳,A先将其转换成本地UTC并保存起来,网络调整时间等于所有节
点的本地UTC时间+所有相连节点的偏移量平均值,然而,该网络时间
永远不会调整到超过本地系统时间70分钟以上。
Nonce随机数通常都不会相同,但是它以严格的线性方式在增长,从0开始,每次执行散列时都会增长,当Nonce溢出时(此事经常发
生),挖矿交易的extraNonce项就会增长,其将改变Merkle树的根节
点。
假定针对这些数据项,人们经常会独自产生同样序列号的Hash值,那么,最快的矿机通常会赢。然而,两人产生同样的Merkle根节点基本
上(或几乎)是不可能的,因为区块中的第一个交易是挖矿交易并且会“发送”到你独一无二的比特币地址上。而你的区块与其他人的区块是
有区别的,因此,产生的Hash值肯定也会(几乎可以肯定)不同,你计
算的每个Hash值和网络中的其他人一样,都有同样的获胜机会。
比特币使用SHA256(SHA256(区块头))计算Hash值,但要注意
字节序。例如,以下的Python代码用于计算某一区块的Hash值,使用的
是2011年6月区块号为125552的最小Hash值。该区块头建立在表1-3所示
的6个数据项之上,并且以十六进制的小端结尾方式连接在一起。
>>> import hashlib
>>> header_hex = (01000000 +
81cd02ab7e569e8bcd9317e2fe99f2de44d49ab2b8851ba4a308000000000000 +
e320b6c2fffc8d750423db8b1eb942ae710e951ed797f7affc8892b0f1fc122b +
c7f5d74d +
f2b9441a +
42a14695)
>>> header_bin = header_hex.decode('hex')
>>> hash = hashlib.sha256(hashlib.sha256(header_bin).digest).digest
>>> hash.encode('hex_codec')
'1dbd981fe6985776b644b173a4d0385ddc1aa2a829688d1e0000000000000000'
>>> hash[::-1].encode('hex_codec')
'00000000000000001e8d6829a8a21adc5d38d0a473b144b6765798e61f98bd1d'
注意 实际的Hash值是一串256位的数值,首部有许多零。当
以大头端十六进制常数方式打印或存储时,它的首部有许多零;如果它
以小头端打印或存储时,零就会变换到尾部。例如,如果表示成字节
串-最低(或者开头)的字节串地址显示最小位的数,那么这就是小头
端表示。blockexplorer的输出把Hash值显示为大头端表示的数值,因为
数字的表示通常是首部数字是最大的数字(从左向右读)。1.3.2 挖矿难度
挖矿难度是对挖矿困难程度的度量,即指计算符合给定目标的一个
Hash值的困难程度。比特币网络有一个全局的区块难度,有效的区域必
须有一个Hash值,该Hash值必须小于给定的目标Hash值。矿池也会有一
个自定义的共享难度,用来设定产生股份的最低难度限制。
难度每过2016块就会改变一次,计算公式为:
difficulty=difficulty_1_targetcurrent_target
其中,目标(target)是一个256位长的数值。
测量难度有许多不同的方法,通过这些方法得到的
difficulty_1_target有可能也会不同。传统情况下,它表示一个Hash值,前32位为0,后续部分为1(称之为矿池难度或pdiff),比特币协议把目
标Hash值表示成一个固定精度的自定义浮点类型,因而,比特币客户端
用该值来估计难度(称之为bdiff)。
难度经常被存储在区块中,每个块存储一个十六制的目标Hash值的
压缩表达式(称之为Bits),目标Hash值可以通过预先定义的公式计算
出来。例如:如果区块中压缩的目标Hash值为0x1b0404cb,那么十六进
制的目标Hash值就为如下形式:0x0404cb×28×(0x1b-3)
=0x00000000000404CB000000000000000000000000000000000000000000000000
因而目标Hash值为0x1b0404cb时,难度为:
0x00000000FFFF00000000000000000000000000000000000000000000000000000x00000000000404CB000000000000000000000000000000000000000000000000
=16307.420938523983(bdiff)
或者:
0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0x00000000000404CB000000000000000000000000000000000000000000000000
=16307.669773817162(pdiff)
其中:
0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
是挖矿机使用的最大目标Hash值。而
0x00000000FFFF0000000000000000000000000000000000000000000000000000
则是比特币网络使用的浮点编码类型,后面的位数被缩短了。
下面是一个快速计算比特币难度的方法,这里使用的算法是修改的
泰勒序列(读者可以参考wikipedia上的教程),并且依赖记录来转换难
度计算。
ncludeinclude
inline float fast_log(float val)
{
int const exp_ptr = reinterpret_cast(val);
int x = exp_ptr;
const int log_2 = ((x >> 23) 255) - 128;
x = ~(255 << 23);
x += 127 << 23;
exp_ptr = x;
val = ((-1.0f3) val + 2) val - 2.0f3;
return ((val + log_2) 0.69314718f);
}
float difficulty(unsigned int bits)
{
static double max_body = fast_log(0x00ffff), scaland = fast_log(256);
return exp(max_body - fast_log(bits 0x00ffffff) + scaland (0x1d - ((bits 0xff000000) >> 24)));
}
int main
{
std::cout << difficulty(0x1b0404cb) << std::endl;
return 0;
}
如果想要了解难度计算的数学原理,那么可以看看如下的Python代
码:
import decimal, math
l = math.log
e = math.e
print 0x00ffff 2(8(0x1d - 3)) float(0x0404cb 2(8(0x1b - 3)))
print l(0x00ffff 2(8(0x1d - 3)) float(0x0404cb 2(8(0x1b - 3))))
print l(0x00ffff 2(8(0x1d - 3))) - l(0x0404cb 2(8(0x1b - 3)))
print l(0x00ffff) + l(2(8(0x1d - 3))) - l(0x0404cb) - l(2(8(0x1b - 3)))
print l(0x00ffff) + (8(0x1d - 3))l(2) - l(0x0404cb) - (8(0x1b - 3))l(2)
print l(0x00ffff float(0x0404cb)) + (8(0x1d - 3))l(2) - (8(0x1b - 3))l(2)
print l(0x00ffff float(0x0404cb)) + (0x1d - 0x1b)l(28)
前难度可以通过http:blockexplorer.comqgetdifficulty 来获得,下一
个难度可以通过http:blockexplorer.comqestimate 来获得。难度的变化
情况可以查看http:bitcoin.sipa.be 。最大难度大约等于maximum_target1(因为0会导致无穷大),这是
一个非常大的数值,大约为2224 ;当maximum_target为最小值1时,则
最小难度值也为1。
难度可根据以前2016个区块的产生时间而定,每过2016块就会改变
一次。预计每隔10分钟产生一个区块,因而产生2016个区块要花费2周
时间。如果前2016个区块的产生时间多于两周,则难度会降低;否则难
度就会增加。
为了找到新区块,该区块的Hash值必须小于目标Hash值,实际上它
是一个在0到2256 -1之间的随机数,难度1的偏移量是:
0xffff×2208
难度D的偏移量是:
(0xffff×2208 )D
在难度D下,为了找到新区块,预期要计算的Hash数量是:
D×2256 (0xffff×2208 )
或者只是:
D×248 0xffff难度的设定,是为了以每10分钟一个区块的速度产生2016个区块,因而,在600秒内计算(D×248 0xffff)个Hash,这就意味着产生2016个
区块的网络Hash速率(算力)是:
D×248 0xffff600
可以进一步简化为:
D×232 600
以上公式有较好的精度。
在难度为1时,算力是7Mhashes秒,难度是5006860589,这就意味
着以前2016个区块被找到,其平均算力是:35.840PHashs。
5006860589×232 600≈35.840PHashs
发现一个区块的平均时间,可以用以下公式估计:
时间=难度×232 算力
其中,难度是当前的难度,算力是指矿机的计算能力,以hashess
为单位,时间是你找到两个区块的平均时间。举例来说,使用Python计
算,算力为1Ghashess的矿机,难度在20000时,产生一个新区块的时
间,计算式如下: python -c print 20000 232 109 60 60.0
23.85
其中表示指数,该语句运算的结果就是:找到一个新区块要花费
近1天的时间。1.3.3 矿池原理与商业模式
随着生成区块的难度逐步增加,挖矿变成了一个碰运气的事情,单
一节点要生成一个区块需要花费数年的时间(除非这个单一节点拥有大
量的计算力)。为了激励计算力较低的用户继续参与挖矿,矿池就出现
了。在一个矿池里,许多不同的人贡献出自己的计算力来生成一个区
块,然后再根据每个人的贡献比例来分发奖励。通过这种方式,要得到
那个50个比特币的奖励就不必等待数年的时间了,小矿工能定期得到属
于他们那部分的比特币奖励。一个share(贡献股份)为一个矿池给客
户端的一个合法的工作证明,同时这也是用来生成区块的工作证明,但
是没有这么复杂,只需要很少的时间就能达到一个share。
矿池是比特币(Bitcoin)等P2P密码学虚拟货币开采所必需的基础
设施,一般是对外开放的团队开采服务器。其存在的意义是提升比特币
开采的稳定性,使矿工薪酬趋于稳定,目前国内较为著名的比特币商业
矿池有F2Pool、BTCC Pool、BW Pool、BTC.com等。
关于矿池挖矿的方式,目前存在如下几种不同的方式。
·Slush方式:Slush矿池基于积分制,较老的shares将比新的shares拥
有更低的权重,以减少一轮中切换矿池的投机分子。
·Pay-Per-Share方式:该方式为立即为每一个share支付报酬。该支出来源于矿池现有的比特币资金,因此可以立即取现,而不用等待区块
生成完毕或确认之后。这样可以避免矿池运营者幕后操纵。这种方法减
少了矿工的风险,但将风险转移给了矿池的运营者。运营者可以收取手
续费来弥补这些风险可能造成的损失。
·Luke-Jr方式:该方式借用了其他方式的长处,如Slush方式一样,矿工需要提供工作证明来获得shares,如Puddinpop方式一样,当区块生
成时马上进行支付。但是不像之前的方式,一个区块的shares,会被再
次利用来生成下一个区块。为了区分参与矿工的交易传输费用,只有当
矿工的余额超过1BTC时才进行支付。如果没有达到1BTC,那么将在下
一个区块生成时进行累计。如果矿工在一周内没有提供一个share,那么
矿池会将剩下的余额进行支付,不管余额是多少。
·Triplemining方式:该方式是将一些中等大小矿池的计算力合并起
来,然后将获得奖励的1%按照各个矿池计算力的比例分发给矿池运营
者。
·P2Pool方式:P2Pool的挖矿节点工作在类似于比特币区块链的一种
shares链上。由于没有中心,所以也不会受到DoS攻击。和其他现有的
矿池技术都不一样,在该方式下,每个节点工作的区块,都包括支付给
前期shares的所有者及该节点自己的比特币。99%的奖励(50BTC+交易
费用)会平均分配给矿工,另外0.5%会奖励给生成区块的人。·Puddinpop方式:一种使用“元哈希”技术的方式,使用特定的
Puddinpop挖矿软件,现在已经没有矿池使用这种方式了。
目前使用较多的方式为Pay-Per-Share(PPS),矿工使用起来也比
较方便。
但从去中心化的角度来说,还是推荐P2Pool,在避免DoS攻击的同
时,也能防止个别矿池拥有超大的计算力而对比特币网络造成威胁。不
过P2Pool的使用方式较PPS更为复杂。1.4 脚本系统
比特币在交易中使用脚本系统,与FORTH(一种编译语言)一
样,脚本是简单的、基于堆栈的,并且是从左向右处理的,它特意设计
成非图灵完整的形式,没有LOOP语句。
一个脚本本质上是众多指令的列表,这些指令记录在每个交易中,若交易的接收者想花掉发送给他的比特币,那么这些指令就是描述接收
者是如何获得这些比特币的。一个典型的发送比特币到目标地址D的脚
本,要求接收者提供以下两个条件,才能花掉发给他的比特币:
1)一个公钥,当进行散列生成比特币地址时,生成的地址是嵌入
在脚本中的目标地址D。
2)一个签名,用于证明接收者保存了与上述公钥相对应的私钥。
脚本可以灵活地改变花掉比特币的条件,举个例子,脚本系统可能
会同时要求两个私钥或几个私钥,或者无需任何私钥等。
如果联合脚本中未导致失败并且堆栈顶元素为真(非零),则表明
交易有效。原先发送币的一方,控制脚本运行,以便比特币在下一个交
易中使用。想花掉币的另一方必须把以前记录的运行为真的脚本,放到
输入区。堆栈保存着字节向量,当用作数字时,字节向量被解释成小尾序的
变长整数,最重要的位用于决定整数的正负号。比如,0x81代表-1,0x80则是0的另外一种表示方式(称之为负0)。正0用一个NULL长度向
量表示。字节向量可以解析为布尔值,这里False表示为0,True表示为
非0。1.4.1 脚本特点
表1-4至表1-12是脚本的所有关键字列表(命令函数),一些更复
杂的操作码已被禁用,不再考虑,因为钱包客户在这些操作码的程序实
现上可能有Bug,如果某个交易使用了这些操作码,那么其将会使比特
币块链产生分叉。我们提到脚本的时候,通常省略了这些把数字压入堆
栈的关键字。
表1-4 脚本常见关键字字段
表1-5所示的是脚本的流程控制。
表1-5 脚本的流程控制表1-6 脚本的堆栈处理表1-7展示的是字符串操作码,若有在交易中出现了已禁用的操作
码,则必须终止和失败返回。
表1-7 字符串操作码表1-8展示的是位操作码,若有在交易中出现了已禁用的操作码,则必须终止和失败返回。
表1-8 位操作码
注意 算术逻辑的输入仅限于有符号32位长整数,但输出有可
能会溢出。如果任何命令的输入值其长度超过4字节,那么脚本必须中
止和失败返回。如果在交易中出现了标记为已禁用的操作码,也必须终
止和失败返回。
表1-9 算术逻辑操作码(若在交易中出现已禁用的操作码,则必须终
止和失败返回)表1-10 脚本的加密码表1-11 脚本中的伪关键字(这些关键字仅供内部使用,辅助进行交易
匹配)
表1-12 保留关键字1.4.2 脚本运行过程
在这里,我们先讨论单输入单输出的比特币交易,因为这样描述起
来更为方便,而且不会影响对脚本的理解,以下面的一个交易Hash值为
例:
9c50cee8d50e273100987bb12ec46208cb04a1d5b68c9bea84fd4a04854b5eb1
这是一个单输入单输出交易,下面来看下我们要关注的数据。
Hash:
9c50cee8d50e273100987bb12ec46208cb04a1d5b68c9bea84fd4a04854b5eb1
对于输入交易,需要关注如下值。
前导输入的Hash:
437b95ae15f87c7a8ab4f51db5d3c877b972ef92f26fbc6d3c4663d1bc750149
输入脚本scriptSig:
3045022100efe12e2584bbd346bccfe67fd50a54191e4f45f945e3853658284358d9c062ad02200121e00b6297c0874650d00b786971f5b4601e32b3f81afa9f9f8108e93c752201038b29d4fbbd12619d45c84c83cb4330337ab1b1a3737250f29cec679d7551148a
对于输出交易,需要关注如下值。转账金额:0.05010000 btc
输出脚本scriptPubKey:
OP_DUP OP_HASH160 be10f0a78f5ac63e8746f7f2e62a5663eed05788 OP_EQUALVERIFY OP_CHECKSIG
假设Alice是转账发送者,Bob是接受者。那么输入交易表明了Alice
要动用的比特币的来源,交易输出表明了Alice要转账的数额和转账对象
——Bob。那么,有读者可能会问,数据中的输入脚本和输出脚本是不
是就是题和解?答对了一半!
在Bitcoin Wiki中提到:原先发送币的一方,控制脚本运行,以便比
特币在下一个交易中使用。想花掉币的另一方必须把以前记录的运行为
真的脚本,放到输入区。
换句话说,在一个交易中,输出脚本是数学题,输入脚本是题解,但不是这道数学题的题解。我开始看Wiki的时候,在这里遇到了一些障
碍,没法理解输入脚本和输出脚本的联系。但是在考虑到交易间的关系
之后,就明白了。
假设有这么一系列交易,如图1-7所示。图1-7 三对交易示范图
那么,这一系列交易具有如下特征。
·三个交易都是单输入单输出交易。
·每个输入交易输出交易中,都包含对应的脚本。
·交易a为Alice转账给Bob;交易b为Bob转账给Carol;交易c为Carol
转账给Dave。
·当前交易的输入都引用前一个交易的输出,如交易b的输入就是引
用交易a的输出。
按照之前的说法,交易a中的输出脚本就是Alice为Bob出的数学
题。那么,Bob想要引用交易a输出交易的比特币,就要解开这道数学
题。题解是在交易b的输入脚本里给出的!Bob解开了这道题,获得了奖
金,然后在交易b中为Carol出一道数学题,等待Carol来解……所以说,在图1-8中相同颜色的输出和输入才是一对题和解。
图1-8 输入输出一一对应图1.4.3 脚本操作码解读
要理解比特币脚本,先要了解堆栈,这是一个后进先出(Last In
First Out)的容器,脚本系统对数据的操作都是通过它完成的。比特币
脚本系统中有两个堆栈:主堆栈和副堆栈,一般来说主要使用主堆栈。
下面就来列举几个简单的例子,看下指令是如何对堆栈进行操作的。
常数入栈:指把一段常数压入到堆栈中,这个常数成为栈顶元素,如图1-9所示。
OP_DUP:复制栈顶元素,如图1-10所示。
图1-9 常数入栈图1-10 复制栈顶元素
OP_EQUALVERIFY:用于检查栈顶两个元素是否相等,如图1-11
所示。1.4.4 脚本执行过程
Alice在转账给Bob的时候,输出交易中给出了Bob的钱包地址(等
价于公钥Hash),当Bob想要转账给Carol的时候,他要证明自己拥有与
这个钱包地址对应的私钥,所以在输入交易中给出了自己的公钥及使用
私钥对交易的签名。下面来看个实例。
交易a:
9c50cee8d50e273100987bb12ec46208cb04a1d5b68c9bea84fd4a04854b5eb1
交易b:
62fadb313b74854a818de4b4c0dc2e2049282b28ec88091a9497321203fb016e
交易b中有一个输入交易引用了交易a的输出交易,它们的脚本是一
对题与解。
题:交易a的输出脚本,若干个脚本指令和转账接收方的公钥
Hash。
OP_DUPOP_HASH160be10f0a78f5ac63e8746f7f2e62a5663eed05788OP_EQUALVERIFY OP_CHECKSIG
解:交易b的输入脚本,这么一长串只是两个元素,签名和公钥(sigpubkey)。
3046022100ba1427639c9f67f2ca1088d0140318a98cb1e84f604dc90ae00ed7a5f9c61cab02210094233d018f2f014a5864c9e0795f13735780cafd51b950f503534a6af246aca301 03a63ab88e75116b313c6de384496328df2656156b8ac48c75505cd20a4890f5ab
下面来看下这两段脚本是如何执行完成解题过程的。
首先执行的是输入脚本。因为脚本是从左向右执行的,那么先入栈
的是签名,随后是公钥。接着,执行的是输出脚本。从左向右执行,第
一个指令是OP_DUP——复制栈顶元素(如图1-12所示)。
OP_HASH160用于计算栈顶元素Hash,得到pubkeyhash,如图1-13
所示。
然后将输出脚本中的公钥Hash入栈,为了与前面计算中所得到的
Hash区别开来,这里称它为pubkeyhash',如图1-14所示。
图1-11 检查栈顶元素是否相等图1-12 复制栈顶元素
图1-13 栈顶元素Hash160图1-14 公钥Hash入栈
OP_EQUALVERIFY则会检查栈顶前两个元素是否相等,如果相等
则继续执行,否则中断执行,返回失败,如图1-15所示。
OP_CHECKSIG使用栈顶前两个元素执行签名校验操作,如果相
等,则返回成功,否则返回失败,如图1-16所示。
图1-15 检查Hash值是否相等图1-16 返回结果
这样一串指令执行下来,就可以验证这道数学题是否做对了,也就
是说,验明了想要花费钱包地址中比特币的人是否拥有对应的私钥。上
面的执行过程是可以在脚本模拟器中进行的,并且能够看到每一步执行
的状态。1.5 合约应用案例
1.4节的脚本系统,详细说明了脚本的运行原理,本节将描述在实
际应用场景中如何使用脚本系统构建合约应用。1.5.1 合约应用原理
每个比特币交易都有一个或多个输入和输出,每个输入或输出都有
一个小的纯函数与之相关联,称为脚本,脚本可包含简化形式交易的签
名。
每个交易都有一个锁定时间,使得该交易处于特定状态并且可被新
交易替换,直至锁定时间来临。预定时间可以是块索引或时间戳(这两
个因素使用同一个内存项,小于5亿是块索引,大于5亿是时间戳)。当
一个交易的锁定时间到了,则称之为终结。
每个交易的输入都有一个序列号,对于正常发送币的交易,该序列
号为UNIT_MAX,锁定时间为0。如果锁定时间还未达到,但所有的序
列号为UNIT_MAX,则该交易也被认为是终结。序列号用来发布交易
的新版本,无须验证其他输入的签名。例如:在一个交易中,每个输入
都来自于不同的一方,每个输入的序列号都是0,这些序列号可以独立
增加。
签名验证是很灵活的,因为交易的签名方式可以通过SIGHASH符
号来控制,该符号附加在签名后面。通过这种方式能够构建特殊的合
约,交易的每个输入方只对交易的一部分进行签名,因而每个输入方都
能够单方面改变该交易的一部分内容,而无需其他输入方的参与。SIGHASH符号分为两部分,一种模式和一个ANYONECANPAY指示
器。签名模式包含如下几种模式。
·SIGHASH_ALL:这是默认模式。它指示一个交易除输入脚本之
外,所有部分都被签名。对输入脚本进行签名显然是不可能的,那样将
无法构建一个交易,所以脚本总是不被签名。尽管如此,需要注意的
是,输入的其他属性如输出、序列号等都会被签名。直观地说,它的意
思是“如果每个人都把他们的钱放进去,并且输出的正是我想要的,那
么我也同意把我的钱放进去。”
·SIGHASH_NONE:输出没有被签名,可以是任何内容。使用这种
模式意味着“如果每个人都把他们的钱放进去,我也同意把我的钱放进
去,但我不关心输出的是什么。”这种模式使得其他输入方可以通过改
变输入序列号来更新交易。
·SIGHASH_SINGLE:与SIGHASH_NONE一样,输入被签名,但
序列号没有被签名。因而其他人可以创建交易的新版本,然而,唯一的
输出也要被签名。该模式说明“如果输出的正是我想要的,那么我同意
把钱放进去,但我不关心其他人的输入。”
ANYONECANPAY指示器可以与以上三种模式联合使用,当设置
了ANYONECANPAY时,仅仅是该输入被签名,其他输入可以是任意
内容。脚本可以包括CHECKMULTISIG操作码,该操作码提供了n-of-m的
签名验证,即:你可以提供多个公钥m,定义必须出现的有效签名个数
n,签名个数n可以小于公钥数量m。如果我们设置以下脚本,则一个输
出需要两个签名:
22CHECKMULTISIGVERIFY
有如下两种通用的方式可用来安全地创建合约。
·在P2P网络之外传递部分完成或无效的交易。
·使用两个交易:创建一个交易(合约交易),先签名但不会马上
广播,在达成合约并且被锁定在内存中之后,广播另一个交易(支付交
易),最后再广播合约。
采用以上的方式即可保证人们能够知道他们达成的合约内容。这些
特性可以让我们在区块链的基础上创建有趣的、创新的金融手段。1.5.2 示例1:提供押金证明
想象一下,你在一个网站(论坛或WIKI)上注册了一个账号,现
在你希望在网站运营者处建立你的信用,但是你没有以前的名誉来支撑
你的信用。一个解决方案就是向网站付点钱购买信用,但是如果你关闭
了账号,可能会想要回这部分钱。你对该网站的信任程度不足以让你将
钱存到该网站,因为你担心网站会花掉你的钱。另一个风险是,某一天
该网站有可能会消失。
建立信用度的目的是你做出某种奉献,让网站知道你不是一个垃圾
机器人。但是你不想让网站花掉你的钱。如果网站运营者消失了,你最
终想把钱要回来,而无需他们的任何许可。
对于该问题,可以通过合约来解决,具体步骤如下。
1)用户和网站相互发送各自新生成的公钥。
2)用户创建交易TX1(支付交易),该交易支出10个BTC到网站
地址,用户创建了TX1但不广播。
3)用户把TX1交易的Hash值发送给网站。
4)网站使用TX1的Hash值创建交易TX2(合约),TX2花掉TX1的
钱并且支付到用户地址。注意,TX2需要双方签名,因而该交易并不完整,nLocKt
ime被设置成未来时间(比如六个月之后),输入的序列号
为0。
5)最终,这个不完整的交易TX2(一半已签名)被回送给用户,用户检查合约是否如预期的一样在执行,即六个月后10BTC最终会回到
他的地址(除非情况有变)。序列号为0,表示如果双方同意,则合约
可以被修订。现在,该交易的输入脚本还不完整,因为用户未签名,所
以要等用户对合约进行签名并且把签名放到合适的位置上。
6)用户先广播TX1,再广播TX2。
在这个阶段,用户和网站都不能单独得到10BTC。六个月之后,合
约完成,即使网站消失了,用户也能得到币。
如果用户想要提早关闭账号,又该怎么处理呢?网站创建新版的
TX2,nLocKt
ime设为0,并且输入的序列号设为UINT_MAX,重新签
名,把该交易发回用户,用户签名后广播该交易,就能提早结束合约并
且释放10BTC。
如果六个月快到了,而用户还想保留他的账号,又该怎么办呢?类
似的事情发生后,合约会使用新的nLocKt
ime,序列号比以前的序列号
大1,双方重新签名,广播232次。当然,无论发生什么,双方都必须同
意,才能真正改变合约。显然,如果该用户被证明是存在恶意行为的(例如:垃圾邮件发送
者),那么网站不会同意提早结束合约。如果用户有太多的滥用行为,则网站可以要求增加存款数量,或者要求延长合约时间。1.5.3 示例2:担保和争端调解
一个买家想和他不认识或不信任的某人进行交易,一般情况下若交
易能够正常进行时,买家不想任何第三方参与。但是当交易出现问题
时,他想有一个第三方——也许是一个专业的争端调解服务来决定谁能
拿到钱。
注意 这个概念同时适用于买家和卖家。例如,调解员可向商
家要求邮资证明,以判断是否发货。
换句话说,某人想锁定某些币时,这些币要在第三方同意的情况
下,才能被花掉。
该示例的实现步骤具体如下。
1)和商家一起引入一个调解员(如:ClearCoin)。
2)得到商家的公钥K1,得到调解员的公钥K2,创建自己的公钥
K3。
3)把K2发给商家,商家生成一个随机数挑战调解员,调解员用K2
的私钥签名,用来证明K2确实属于调解员。
4)创建一个交易TX1,使用如下输出脚本并且广播该交易。23CHECKMULTISIGVERIFY
现在这些币被锁定了,如果要解锁这些币,需要使用以下几种方
式。
·客户和商家同意(无论是成功的交易,还是在没有调解的情况下
商家同意回退给客户)。
·客户和调解者同意(失败的交易,调解者认同客户,客户得到退
款)。
·调解者和商家同意(商品已经发送,尽管有争议,商家还是得到
币)。
输入签名时,内容被设为相关联的输出。这样,为了从这个交易中
得到币,客户要创建包含两个签名位的脚本,自己签一个,再把未完成
的交易发给商家或调解员,请求第二个签名。1.5.4 示例3:保证合约
保证合约是建造公众商品时的集资办法,公众商品是指一旦建成,任何人都可以免费享受到好处的商品。标准的例子是灯塔,所有人都认
同应该建造一个,但是对于航海者个人来说灯塔太贵了,而且灯塔不只
是他一个人用得着,同时也会方便其他的航海者。
一个解决方案就是向所有人集资,只有当筹集的资金超过所需的建
造成本时,每个人才真正付钱;如果集资款不足,则谁都不用付钱。
在保证合约集资方面,包括频繁的、小额的、经常自动进行的集
资,例如互联网电台的资金和网页翻译等,比特币要优于传统的支付方
式。假设有一个浏览器的插件可供你发送一点币,它能检测当前页面的
语言并且广播一个集资请求,用于把该页面翻译成你的语言。如果使用
该插件的许多用户同时查看该页面(例如:该页面从高流量的网站链接
过来),那么足够的集资请求就能广播出去,到达一定的金额时,可自
动付钱给一个高质量的翻译公司,当翻译完成后该页面将自动在你的浏
览器中加载。
我们能以比特币的方式建立以下模型,具体步骤如下。
1)主办方创建新的捐赠地址,宣布如果筹集资金超过1000BTC,则将建造该商品,任何人都可以捐赠。2)捐赠者创建一个新交易,把一定数量的钱打到集资地址上,但
是他们并不广播该交易。该交易与常规的交易相似,但有三个不同点:
首先,不能做任何改变,如果你没有正确的输出金额1000BTC,那么你
必须先创建一个;第二,输入脚本要以
SIGHASH_ALL|SIGHASH_ANYONECANPAY的模式签名;最后,输出
值是1000BTC,注意,这不是一个有效的交易,因为输出值比输入值大
得多。
3)把交易上传到主办方的服务器上,他们把交易保存到磁盘上,随时更新捐赠的币数量。
4)一旦服务器获得了足够的币,它将把所有捐赠者上传的独立交
易合并成一个新的交易,该交易只有一个输出,仅仅是把钱付到捐赠地
址,该输出与每个捐赠者的交易的输出部分相同,而输入部分则是所有
捐赠者输入的集合。
5)广播完整的交易,发送捐赠的币到捐赠地址中。
这样的场景依靠了协议的几个方面,首先使用了SIGHASH符号,SIGHASH_ALL是默认模式,意味着要签名所有交易的内容,除了输入
脚本。SIGHASH_ANYONECANPAY是附加的指示器,意味着签名仅覆
盖自己的输入部分,而不会覆盖其他人的输入,这样一来,其他人的输
入可以留空。使用这些符号,我们能创建这样一个签名,即使在添加进其他输入之后,该签名依旧是有效的。但如果输出内容或其他的交易部
分被改变了,那么该签名就会无效了。第二,输入值小于输出值的交易
是无效的(原因很明显),这也就意味着捐赠者把发送币的交易发送给
主办方是安全的,因为主办方不可能得到这些捐赠币,除非再加上其他
的输入值等于或超过输出值。
不使用SIGHASH_ANYONECANPAY指示器也可以创建保证合约。
不需捐赠者创建交易的集资方式有两个步骤,一旦达到集资的总金额,主办方就会创建包含所有捐赠者输入的交易,然后依次在捐赠者中传
递,每个捐赠者都对该交易进行签名。但是,先使用
SIGHASH_ANYONECANPAY指示器,然后合并交易,这样可能会更方
便一些。
保证合约可以保证下一个块的资金网络安全,通过这种方式,即使
一个块中的交易数量比较少,挖矿也能挣钱(因为保证合约的交易一般
占用空间较大,因而需要付出更多的网络转账费)。
Tabarrok在他的论文“The private provision of public goods via
dominant assurance contracts”中详尽地描述了保证合约的概念,在一个
通用的保证合约中,如果合约失败了(在预定时间内集资不足),主办
方会给捐赠者支付网络转账费,这种类型的合约旨在鼓励捐赠者积极参
与。1.5.5 示例4:使用外部状态
脚本被设计成纯函数,它们不能访问外部服务器,也不能导入任何
会改变的外部状态,因为攻击者会利用该特性突破区块链。而且,脚本
语言的功能被严格限制了。幸运的是,我们可以以其他的方式创建交
易,从而与外部世界相联系。
考虑一个例子,老人想让他的孙子继承遗产,继承时间是在他死
后,或者在孙子年满18岁时,无论先满足哪个条件,他的孙子都可以得
到遗产。
为了解决这个问题,老人首先向他自己发送孙子要继承的资产数
量,以便有一个正确的继承数量的唯一输出;接着,他创建了一个带有
锁定时间的交易,该交易的意思是:在孙子18岁生日时,把币支付到孙
子的地址中,老人对该交易签名,不进行广播,直接把该交易给了孙
子。当过了孙子的18岁生日之后,孙子广播了这个交易并且得到他的
币。孙子可以在这个时间之前广播该交易,但他不会提前得到币,有些
节点会在内存池中把这种交易丢弃掉,因为锁定时间在遥远的将来。
死亡条件则很难判断,因为比特币节点不会检测主观条件,我们必
须依靠预言,预言是指具有密钥对的服务器,当用户自定义的表达式被
证明是真的,它就能按照要求对交易进行签名。以下是例子,老人创建了一个交易花掉了他的币,把输出设为:
OP_DROP2CHECKMULTISIG
这是一个预言脚本,具有与众不同的形式——它把数据推到堆栈
中,然后立即删除。公钥发布在预言服务器的网站上,为公众所知,Hash值设为用户自定义表达式的Hash值,该表达式以预言服务器能够理
解的方式进行编写,以确认老人已经死亡。举个例子,可能是以下字符
串的Hash值:
if(has_died('johnsmith',born_on=19500102))return(10.0,1JxgRXEHBi86zYzHN2U4KMyRCg4LvwNUrp);
以上语言是假设的,由预言服务器定义该语言,其可能是任何一种
语言。返回值是一个输出:币数量和孙子的地址。
再一次,老人创建了一个交易,没有广播而是直接给了孙子,他另
外还提供了一个表达式和预言服务器的名字,Hash值被写入交易,预言
服务器则能解锁表达式。算法的具体实现如下。
1)预言服务器接受评估请求,请求包括了用户提供的用户自定义
表达式、输出脚本和部分完成的交易,交易中除了scriptSig签名之外,其他部分都已经完成,签名仅包括了孙子的签名,还不足以解锁输出。
2)预言服务器检查表达式,得到其Hash值,并且与交易中的Hash值对照,如果两者不一致,则返回错误。
3)预言服务器评估表达式,如果表达式的结果不是交易输出的目
标地址,则返回错误。
4)预言服务器签名交易,返回签名给用户。
注意 对一个比特币交易进行签名时,输入脚本被设为相关联
的输出脚本。原因是当OP_CHECKSIG操作起作用时,包含该操作码的
脚本被放到输入中,脚本并不包含签名本身。预言服务器并不知道完整
的输出,也没有必要知道,因为它知道输出脚本、自己的公钥和表达式
的Hash值,这就足以使它检查输出脚本并且完成交易。
5)用户接受新签名,插入到交易的scriptSig项中,广播交易。
当且仅当预言服务器认为老人死了,孙子才能广播两个交易(合约
和申报),并且得到币。
预言服务器可以评估任何事情,然而区块链中的输出脚本的形式总
是一样的,可考虑以下的可能性。
·给定一个日期,假定mtgox比特币的美元价格在12.5~13.5之间:
today==20110925exchange_rate(mtgoxUSD)>=12.5exchange_rate(mtgox-USD)<=13.5·打赌我会做一些我从来不会做的事情(比如,获得奥林匹克金
牌):
google_results_count(site:www.google.comhostednews'MikeHearn'Olympicgoldmedal)>0
以上函数通过Google来搜索MikeHearn这个人获得奥林匹克金牌
(Olympicgoldmedal)的块数
·欧洲电视台的歌唱比赛,选择两个优胜者之一进行打赌:
if(eurovision_winner=='Azerbaijan')
return 1Lj9udBVDwptFffGSJSC2sohCfudQgSTPD;
else
return 1JxgRXEHBi86zYzHN2U4KMyRCg4LvwNUrp;
这些条件可使预言服务器的签名变得任意复杂,但是区块链仅需要
包含一个Hash值即可。
1.信任最小化:挑战
有许多方法可以降低对预言服务器的信任程度。
回到我们的第一个例子,预言服务器还没有看到孙子想解锁的交
易,因为该交易从没被广播过。这样,它不会支持孙子赎回币,因为它
不知道该交易是否存在。我们能做到,并且也应该做到,以自动方式定
期挑战预言服务器,确保它总是按照我们想象的方式进行输出。挑战无须花费任何币,因为要签名的交易是无效的(例如:与一个并不存在的
交易进行关联),预言服务器没法知道签名请求是随意的还是真实的,如何以一个尚未成真的条件来挑战预言服务器,是一个开放的研究课
题。
2.信任最小化:多个独立预言服务器
如果需要,CHECKMULTISIG中的签名个数n可以增加至能够达到
n-of-m的预言服务器模式(即m个预言服务器中需要有n个预言服务器签
名才能使交易有效)。当然,检查预言服务器是独立的而非串通的,这
一点也是很重要的。
3.信任最小化:可信的硬件
使用合适的硬件,即可进行信任计算。比如,以INTELTXT或AMD
等硬件来建立一个封闭的运行环境,然后用TPM芯片向第三方证实其可
信度。第三方可判定硬件是否处于所需状态。如果硬件失败,则需要有
人介入CPU程序的执行过程,甚至在极端的情况下,内存总线没有数据
流过(如果程序足够小,则完全可以使用缓存来运行程序)。
4.信任最小化:亚马逊AWS预言服务器
最终,也许是目前最现实的方法就是使用亚马逊的网页服务,截至
2013年11月,最合适的预言服务器的解决方案是“this recipe for creating atrusted computing environment using AWS”,该方案基于“this project for
doing selective SSL logging and decryption”。基本思想是:预言服务器使
用亚马逊作为其信任根,并且能用亚马逊API证明其是值得信任的,该
预言服务器记录在线银行接口的加密SSL会话,如果以后产生交易争
端,那么会话记录将被解密,争端就可以得到解决。1.5.6 示例5:跨链交易
比特币技术可以用来创建多个独立的货币,与比特币实现理念相同
的山寨币,可以在有限信任的条件下与比特币进行自由交易。域名币
(Namecoin)就是一个例子,它与比特币的运作规则有些不同,它可以
在域名空间中租用域名。
举个例子,想象一个财团发行了欧元币(EURCoins),即一种以
财团的银行存款1:1支持的加密货币。这样的货币与比特币存在不同的
交易集:更中心化,但没有外汇风险。人们可能希望在比特币与欧元币
之间来回交易,为了实现这个想法,可以使用TierNolan提出的协议。实
现步骤具体如下。
1)A产生一些随机数据X(秘密)。
2)A产生TX1交易(支付)包含了带跨链交易脚本的输出。它允许
币以A和B共同签名的方式释放,也可以以私密X和B签名的方式释放,该交易未广播,块链的释放脚本包含了私密的Hash值,并非真正的私密
X本身。
3)A产生TX2(合约),花掉TX1并且输出到A的地址,该交易有
个未来的锁定时间,输入的序列号为0,因而可以被替换。A签名TX2并
且发送给B,B给TX2签名后发送回A。4)A广播TX1和TX2,B可以看到币但是不能花掉它们,因为并没
有输出到B的地址,该交易还没有终结。
5)B在山寨币块链上执行相同的操作,B的锁定时间应该大于A的
锁定时间,双方的交易都待定但未完全。
6)因为A知道私密X,A能马上申报他的币,然而,A在申报币的
过程中,向B释放了私密X,所以B可以以私密X和签名B来完成山寨币
块链的交易。
自动化交易完全是以点对点的方式进行的,其能确保货币的流动
性,该协议使得这种交易更为灵活。跨链交易的脚本如下所示:
IF
2 2 CHECKMULTISIGVERIFY
ELSE
CHECKSIGVERIFY SHA256 EQUALVERIFY
ENDIF
合约输入的脚本如下所示:
1
或者:
0由合约输入脚本中的1或0来决定应该使用哪种方式。如果为1,则
跨链交易的脚本执行第一段代码:
2 2 CHECKMULTISIGVERIFY
如果是0,则跨链交易的脚本执行第二段代码:
CHECKSIGVERIFY SHA256 EQUALVERIFY
参考“Atomic cross-chain trading”(见参考资料[9])能够得到更详细
的说明。
注意 欧元币是一个很自然的想法,还有其他方法也能够实现
点对货币的交易(把比特币换成菲亚特汽车,反之亦然),看“Ripple
currency exchange”(见参考资料[10])可以得到更多的信息。
Sergio Demian-Lerner提出了P2PTradeX协议,一种块链交易的解决
方案,该方案需要把一个块链中的确认规则有效地编码进另一个块链的
确认规则中。1.5.7 示例6:支付证明合约
在示例4中,我们看到了如何基于任意程序的输出来实现条件支
付,这些程序非常有用,能够实现任何常规程序所能实现的功能,比如
获取网页。缺点是需要一个第三方(预言服务器),尽管我们可以用技
术来降低预言服务器的信任度,但谁都不能降低到0。
对于受限的程序、纯函数,新加密技术已经出现,这些技术能从将
信任度降低到0,无需第三方参加。这些程序不能进行任何IO操作,但
是在许多情况下,这种限制被证明并不重要,或者可以以其他的方式绕
过,比如给程序一个签过名并且打过时间戳的文档作为输入,无需程序
自己从网上下载。
若想进一步详细了解,可以阅读一下该协议的解释“Zero Knowledge
Contingent Payment”(见参考资料[11])。1.5.8 示例7:特定对象的快速调整(微)支付
与传统支付系统相比,比特币交易的费用非常便宜,但是还是需要
一些费用以便矿工来挖矿,以及融合到区块链上。有些情况下,你可能
想要快速和便宜地调整发送到某个特定地址的货币金额,而不会导致产
生广播交易的费用。
举个例子,有一个你尚不信任的互联网接入点,就像你从来没有去
过的咖啡屋中的一个Wi-Fi热点一样。每使用10K字节的流量你得向咖啡
屋支付0.001BTC,而无须注册咖啡屋账号。零信任解决方案意味着可以
全自动完成整个过程,因而你在月初预先转了一笔钱到你的手机钱包
中,然后你的手机会自动与AP协商并且按需给AP支付费用,咖啡屋也
希望任何人都能来付钱给它,而无须担心被诈骗。
为了达到这个目标,可以使用下面的协议。该协议依赖nLocKt
ime
与原设计不同的行为,从2013年开始,时间锁定的交易被认为是非标准
协议,不能进入内存池,这样就不能在锁定时间过期之前广播出去。当
nLocKt
ime的行为恢复回中本聪的初始设计时,就需要修改以下讨论的
协议了。
可定义客户端为发送币的那一方,服务端为接收币的另一方,以下
协议的实施过程是从客户的角度来进行的,具体步骤如下。1)创建公钥K1,向服务端请求公钥K2。
2)创建、签名,但不广播交易T1,支付10BTC到输出,需要服务
端和你自己的公钥,使用OP_CHECKMULTISIG是一个好办法。
3)创建退款交易T2,与T1的输出相关联,发送所有币回到你的地
址。该交易有一个锁定时间,例如几小时后,不签名并且把该交易发送
给服务端,常规来说,输出脚本是“2 K1 K22 CHECKMULTISIG”。
4)服务端用K2签名T2,返回给客户,注意,服务端目前还未看到
T1,仅仅看到了T1的Hash值(该Hash值在未签名的T2中)。
5)客户验证服务端的签名是否正确,如果不正确则中止。
6)客户签名T1并且把签名返回给服务端,服务端广播T1(如果他
们双方有联系的话,每一方都可以广播T1),币被锁定。
7)客户创建一个新交易T3,与T1相联系,类似于退款交易,有K1
和K2两个输出,把所有币分配给第一个输出K1,它做了与退款交易相
同的事情,但是没有锁定时间,客户签名T3,发送给服务端。
8)服务端验证输出到它的地址的币数量是正确的,验证客户提供
的签名是正确的。
9)当客户想付钱给服务端时就调整T3,向服务端的输出增加足够的币,同时减少他自己的币数量,然后重新签名T3,发送给服务端。客
户无须发送整个交易,只需要发送签名和增加的币数量即可。服务端调
整T3内容与新的币数量相吻合,验证客户的签名并且继续。
整个过程会持续到会话结束,或者到1天的时间快到时,此时,AP
会签名和广播最终版本的交易,向它自己分配最终的币数量。退款交易
需要处理服务端消息中断和未分配币的情况,如果发生了这些事件,一
旦锁定时间过期,客服就可以广播退款交易,拿回所有的钱。
这个协议已经用bitcoinj实现了。
当nLocKt
ime的交易能够进入内存池、交易替换重新启用时,本协
议必须被修改。在这种情况下,无需退款交易。T3有一个序列号,每次
都比前一次大1,T3的锁定时间与之前的时间相一致。每次的支付都使
得序列号增加1,以确保会优先发生最后版本。如果没有正常关闭通道
协议,则意味着向服务端支付币不会成功,直到锁定时间过期,客户拿
回所有币为止。为了避免这种情况,双方共同签名T3交易,序列号为
0xFFFFFFFF,导致立即确认,而不用考虑nLocKt
ime的值。
锁定时间和序列号可以避免一种攻击,在这种攻击中:AP提供连
通性,客户使用TX2的第一版本双花,使币回到他自己的地址中,阻止
咖啡屋申报账单。如果客户尝试这么做,该交易不会马上被包括进去,AP在一段时间内可以观察到该交易被广播,然后广播它看到的最后一个版本,就能推翻客户的双花企图。
后一种协议依赖交易替换,具有更大的灵活性,因为在通道的生命
周期中,只要客户能收到服务端的签名,协议就能使客户为自己分配的
币的数量越来越少。但是在许多用例中,这个功能是不必要的。交易替
换同样允许配置更复杂的超过两方的通道,如何在这种使用场景下详尽
地描述协议,就留给读者作为练习吧。1.5.9 示例8:多方去中心化彩票
使用示例6的一些技术和一些高级的脚本,使得构建无人值守的多
方彩票系统成为可能。准确协议在“Secure multiparty computations on
Bitcoin”(见参考资料[12])中已经有详细描述。参考资料
[1] http:www.8btc.combitcoin_block_chain
[2] http:www.360doc.comcontent1412281018005502_436322050.shtml
[3] http:www.8btc.combitcoin-change-addresses-explanation
[4] http:8btc.comarticle-1786-1.html
[5] http:www.8btc.combitcoin-transactions
[6] http:8btc.comarticle-1775-1.html
[7] http:8btc.comarticle-1767-1.html
[8] http:www.8btc.comunderstand-bitcoin-script
[9] https:en.bitcoin.itwikiAtomic_cross-chain_trading
[10] https:en.bitcoin.itwikiRipple_currency_exchange
[11] https:en.bitcoin.itwikiZero_Knowledge_Contingent_Payment
[12] http:eprint.iacr.org2013784第2章 区块链进阶
2.1 外带数据
区块链的外带数据是指那些保存在区块链上但不进行货币交易的信
息,比如需要永久保存的信息,前面提到过存在于区块链上的每一笔交
易都有一个输入和输出,区块链的外带数据也是采用类似的方式来存储
的。
如果有在比特币上永久存储数据的需求,那么你目前有两种选择,即:“OP_RETURN”和“Multi-Signatures”。OP_RETURN是指在每个交易
的公钥脚本中嵌入OP_RETURN操作码,之后放置外带数据;Multi-
Signatures则是指在建立多签地址时,使用空白签名区域来放置数据。
此类外带数据的方法旨在让编程者更简单地将数据编码到交易中,同时
又不会影响到比特币区块链的功能,目前非常流行,在Omni、Open
Assets、Blockstack和Factom等的区块链上都有应用。2.1.1 OP_RETURN外带数据
2013年,比特币协议中引进了一项新功能,即:创建一种名为
OP_RETURN的交易,可以嵌入40字节小段数据(目前已经是80字节
长)。最初,这个功能旨在把情境信息加入比特币交易里,比如配送信
息等。后来,发展出了更具创造性的用法,即创造最小量的交易
(0.00000001 BTC加上交易费),并且可嵌入任何你想放进去的信息。
比如交易号:
495926f46e3aae80088919f363b3b6ff52116e28637b63eb2a681b1fb990d2e4
所对应的交易输出为OP_RETURN类型,那么它的输出脚本则为:
OP_RETURN 4343020549a5710049a57190
利用这个功能的第一个有趣的应用就是存在性证明(Proof Of
Existence),它可以为任何文件创建一个Hash,并且可以放入区块链
中,这点不同于其他所有文件的身份认证ID。之后,通过比较区块链里
的Hash和你手头文件的Hash,就可以用那个交易的时间戳和存储在其中
的Hash,来证明那个时点上某个文件是确实存在的。只要二者匹配,就
有了证明。值得注意的是,只能在该交易中输出很小金额的比特币,如
0.00005,因为输出到OP_RETURN中的比特币是无法被再次使用的。2.1.2 Multi-Signatures外带数据
多签名地址是另外一种外带数据的方法。例如,对于1-of-2型的多
签名地址,我们在建立该地址时,提供的第一个公钥是发送者的,因而
输出金额可以赎回;而第二个公钥是空白的,因而该空间可以用来存储
外带数据。对数据的要求则是:前缀是数据的长度,后面是用0来充值
的无数据区域。
该交易的输出脚本为:
1 <0> 2 OP_CHECKMULTISIGN
这里的<0>区域可用于存储外带数据,该输出金额一样可以被花
费。如果要存储更多数据,则可采用1-of-3或1-of-5型的多签地址。2.2 Counterparty
合约币Counterparty是以合约币协议运行的全套金融工具,合约币
协议建立在比特币块链的基础之上,把比特币块链当成可信的时间戳服
务和可信的信息发布证明。
目前合约币已经实现了众多的技术创新点,比如燃烧证明、合约、去中心化XCP与BTC交易所、赌约或期货、资产或股份发行、分红等。
Counterparty是建立在比特币协议上的传输层,用于建立和使用去中心
化的财务工具协议。简单来说,可以将XCP理解为很多“小的BTC”即
XCP=“小的BTC”,但是这些“小的BTC”(XCP)不仅仅具有货币的交易
功能,还具有资产发行(例如发行股票)、股息分配及下注的功能。
每个合约币信息都包括以下特性。
·有一个源地址。
·有一个目的地址。
·有一定数量的比特币,从源代码发送到目的地址(如果存在目的
地址的话)。
·以比特币计的费用,支付给挖到这个交易的矿工。·最多40字节的外带数据,这些数据通过上述的两个外带数据方法
嵌入到比特币交易中。
为了方便区分,每个合约币交易的数据区域都以UTF-8格式的
CNTRPRTY打头,这个字符串已经足够长,因而很难将合约币的交易
与在OP_RETURN区域带有伪随机数的比特币交易搞混。在测试情况下
(例如:在任何块链中使用TESTCOIN合约币网络),这个字符串
是“XX”。
识别字节串“CNTRPRTY”之后的四个字节说明了目的地址的存在
性、比特币交易费用的多少,以及交易的比特币数量(根据合约消息类
型的不同而不同)。其他的数据则根据消息类型具有不同的格式,具体
请参考源代码。
另外,每个合约币交易都必须有一个明确且唯一的源地址,在含有
合约币交易的比特币交易中,所有输入都必须一致。在比特币交易中资
金唯一的源地址,就是合约币交易的源地址。
合约币交易的源地址和目的地址,就是比特币地址,任何比特币地
址都可以收到任何合约币的资产(如果该地址有资产的话,也可以向外
发送资产)。
此外,需要说明的是,所有信息都会按照顺序进行解析,一次一
个,并且会忽略区块边界。2.2.1 Counterparty附生链的实现机制详解
附生链支持构建两种类型的交易:BTC发送和以BTC发送合约币的
资产分红,这两种交易不包含数据区,对于后者,能使用多个“目的”输
出。除BTC和XCP以外的所有资产均具有如下属性:Asset name、Asset
ID、Description、Divisiblity、Callability、Call date(if callable)即赎回
日期(如果是可赎回的)、Call price(if callable)即赎回价格(如果是
可赎回的)等。
资产名称是大写的ASCII字符串,当编码成十进制整数时,其值大
于263 ,小于或等于2568 。所有资产名称,除了“BTC”和“XCP”以外,必须至少有4字节长,而且不能以字符“A”开头。这样处理后,某些13字
节的资产名称是有效的,但是14字节的就不行。
资产可以是可分割的或不可分割的,可分割资产可以分成8个十进
制的位置。资产可以有描述,也可以随时改变。
资产可以是“可赎回的”,可赎回资产在赎回期之后,可以被现在的
发行者,以赎回价格(以XCP为单位)强制“赎回”,赎回价格可以设置
成该资产首次发行的价格。
可赎回资产可以在赎回日期之后赎回,该赎回日期是在块链中的一
个区块中第一次定义的时间。赎回价格指定为6个十制数的精度,是XCP与该资产的最小单位的
比率。
附生链的交易类型包括:发送(Send)、订单(Order)、BTC支
付(BTCPay)、发行(Issue)、广播(Broadcast)、赌约(Bet)、分
红(Dividend)、燃烧(Burn)、取消(Cancel)、回调(Callback)
等。下面就来一一介绍下。2.2.2 发送
发送(Send)是指从源地址发送任何合约币资产到目的地址,如果
在解析(以交易顺序)该消息时,发送者还没有足够的资产数量,则该
发送消息只能部分满足。Counterparty支持发送比特币,这里不使用任
何数据输出。2.2.3 订单
订单(Order)是指给定某种资产的特定数量,要得到另外资产的
特定数量。“买单”和“卖单”之间没有本质差别。在订单解析时,被给的
资产通常会马上被签订合约。也就是说,如果有人想用1个XCP换2个
BTC,一旦他发布了这个订单,那么他的XCP账号马上会减去1个
XCP。
当订单在块链中可见时,协议会将它与另一个以前见过的开放订单
撮合在一起。两个被撮合成功的订单称为“订单对”,如果订单对中的任
何一个订单包含比特币,那么这个订单对会被指定为“待处理”状态,直
到必要的BTCPay交易发布;如果订单对中的订单没有包含比特币,那
么这个贸易将立即完成,并且以协议自身指定的地址形成新的收支平
衡。
所有订单都是定价单,询价指定了一个人想要付出和得到的比率,订单会匹配定价以下的最高价格,订单对就是按照这个价格撮合的。也
就是说,如果有个开放订单以0.11XCP每份资产卖出,第二个卖单以
0.12XCP每份资产卖出,第三个卖单以0.145XCP每份资产卖出,然后
有一个新订单要以0.14XCP每份资产的价格买入,那么它将会先匹配第
二个买单,XCP和BTC将会以0.12XCPASST的价格成交。所有订单允许部分执行,也就是说,订单并非要么完全成交,要么
不成交。在前一个例子中,如果购买比特币的一方想买的数量多于第一
个卖单的数量,那么买单剩余未成交的数量会由后面的现存卖单来满
足。在所有可能的订单对撮合完之后,当前的买单被列为开放订单(如
果还有数量未被满足的话),如果存在多个价格相同的开放买单,则订
单将按照时间顺序撮合。
用户发布开放订单之后,开放订单会在一定数量的区块后过期,当
订单过期时,所有担保的资金都会返回到订单发布的那一方。
等待比特币支付的订单对将在10个区块后过期,其中的订单将会重
新发布。一般情况下,不会存在虚假交易,因为每一方提供的资产都存
储在担保处。然而,担保比特币是不可能的,因而那些想购买比特币的
人会要求只匹配有向比特币矿工支付交易费用的交易。另一方面,当创
建订单售出比特币时,用户可以支付他愿意支付的任意费用;如果是部
分订单,则仅支付部分费用。
此外,可用支付比特币的方式来关闭那些等待BTCPay消息的订单
对。在BTCPay消息的数据区块中,存储着两个Hash串连接而成的字节
串,这两个Hash串是由订单对中的两个订单Hash生成的。2.2.4 发行
资产可以以发行消息类型的方式进行发行(Issue):用户指定名称
和数量,协议计入相应的地址。资产名称必须是唯一的,或者以前被相
同地址发行过的。如果要重新发行一个资产,也就是说,对已经发行的
资产进行增发,那么发行的资产名称、可分割性和发布地址必须匹配。
对某个已经存在的资产进行增发,这个权利可以转移给别的地址。资产
可以被不可逆地锁定,防止进行增发,以保证资产拥有者免受通胀风
险。2.2.5 广播
广播(Broadcast)用于发布文本或数字信息,并且附带一个时间戳
作为系列广播的一部分,这系列广播被称为“反馈”。一个反馈和一个地
址相关联:从给定地址过来的任何广播,都是该地址反馈的一部分。一
个反馈的时间戳必须是单向增加的。赌注以数字形式在反馈中下注,这
个数值可以是货币的价格,或者可以是对未来事件可能的离散输出的一
部分描述。例如,有人可能以文本形式这么描述:“US QE on 2014-01-
01:dec=1,const=2,inc=3”,并且宣布结果是“US QE on 2014-01-
01:decrease!”和数值1,更为复杂的赌约可以以非块链的方式进行发布。
发布内容为文本字符串“LOCK”(大小写不敏感)的单个广播可以
锁定反馈,阻止它成为以后的广播源地址,同时也阻止它成为任意新赌
约的主题(如果反馈被锁定,但还有开放的或未解决的赌约与之相关,那么,那些赌约或赌约对会无损害地过期)。广播-1的数值会被赌约结
算所忽略。反馈以它的发布地址来识别。2.2.6 赌约
赌约(Bets)是指打赌一个特定反馈会等于(或者不等于)某个特
定时间的一个目标值,例如,打赌2020年1月1日12点整比特币的价格是
否为10000美元。参与赌博的人用他们的赌金进行担保,当到达指定时
间,该赌约就会按照反馈结果进行结算,赢者获得赌金。
等于不等于赌约不能用杠杆。然而,为了让两个赌注能被撮合,它们的杠杆水平、时间期限和目标值都必须相同,否则,它们会以订单
的形式撮合,除非赌约的赔率与订单价格是反相关的(赔率=保证金庄
家保证金),如果有可能,每个赌约都会以尽可能高的赔率撮合到开放
赌约。
目标值必须非负,赌约对(合约)不受-1的广播值所影响。赌约的
最后期限不能晚于它们指定反馈的最后一个广播的时间戳。赌约的过期
与订单相同,例如:过了特定的区块数量后就会过期。如果赌约对在
2016个区块后,发现一个区块的时间戳在赌约的最后期限之后过期,那
么,赌约费用将会是初始保证费用的一定比例,这部分并非赌约收入。
因为区块时间的存在,以及交易在块链中被订单化这种非确定性方
式的存在,所有合约必须非增量解决,但是涉及的资金必须马上放入担
保契约,而且必须有结算日期。否则,有人看到价格下跌了,就会把要被扣除的资金隐藏起来。2.3 挖矿算法解析
2.3.1 PoW挖矿算法及分析
PoW(Proof of Work),即工作证明。也就是说,你获得多少货
币,取决于你挖矿贡献的有效工作,比如,你的电脑性能越好,分给你
的矿就会越多,即根据你的工作证明来执行货币的分配。大部分的虚拟
货币,比如比特币、莱特币等,都是基于PoW模式的虚拟货币(算力越
高、挖矿时间越长,你获得的货币就会越多)。
第1章已经说过挖矿算法其实就是通过一个Hash函数找到一个满足
当前难度的Nonce(包含在区块头里面)的值,Hash函数输入数据的长
度是任意的,将产生一个固定且绝不雷同的值,可将其视为输出的数字
指纹。对于特定输入,Hash的结果每次都不一样,任何实现相同Hash函
数的人都可以计算和验证。加密Hash函数的主要特征就是不同的输入几
乎不可能出现相同的数字指纹。因此,相对于随机的选择输入,有意地
选择输入去找一个特定的Hash值,这几乎是不可能的,否则就破解了所
使用的Hash算法,如SHA-256等。
矿工用一些交易来构建候选区块,他会计算这个区块头Hash的值,看其是否小于当前目标值,如果这个值小于目标值,矿工就会修改这个
Nonce的值,然后再试一次。通常来说一个矿工会做成千上万次Hash运算,从而得到一个合适的Nonce的值,使得区块头Hash满足当前难度。
这也是PoW(工作量证明)算法的由来。
PoW要求出示一定的证明表明工作量,证明可以是直接记录也可以
通过概率表示,其中对于由小概率事件累计而成的工作,出示结果等同
于证明了工作量(因为不太可能直接得到小概率结果)。在比特币和其
他类比特币的系统中,PoW系统是以合乎要求的Hash作为工作结果的。
由于矿工需要一定量的计算才能取得合法的计算结果,因此得到合法的
计算结果就可以证明完成了一定量的计算。2.3.2 PoS股权证明算法及分析
PoS(Proof of Stake),即股权证明。它又是什么意思呢?简单来
说,它是根据你持有货币的量和时间,给你发利息的一个制度。在股权
证明模式下,有一个名词叫币龄,每个币每天产生1币龄,例如你持有
100个币,总共持有了30天,那么,此时你的币龄就为3000,这个时
候,如果你发现了一个PoS区块,你的币龄就会被清空为0。你每被清空
365币龄,你将会从区块中获得0.05个币的利息(可以理解为年利率
5%),那么在这个案例中,利息=3000×5%365=0.41个币。
以现有的比特币运行发展情况来看,比特币每年的挖矿产量都在不
断减半,我们可以预计,随着比特币产量的不断降低,矿工人数也会越
来越少,这样就会导致整个比特币网络的稳定性出现问题。PoS的解决
方案是鼓励大家都去打开钱包客户端程序,因为只有这样才可以发现
PoS区块,才会获得利息,这也增加了网络的健壮性。
其次还有一个担忧,就是当矿工人数降低时,比特币很可能会被一
些高算力的人或团队进行51%攻击,如果采用PoS体系,你即便拥有了
全网51%的算力,也未必能够进行51%攻击,因为这还要求攻击者持有
全球51%的货币量,而这是很难达到的。
现在,我们知道比特币是一个永远不会膨胀的体系了,因为它的货币总量看起来貌似是固定的,但实际上比特币是一个货币紧缩的体系,因为总存在钱包永久丢失的可能,PoS采用类似年利率的方式在一定程
度上是可以缓解这个问题的。
不过,到目前为止,PoS算法还没有被比特币采用的迹象。2.3.3 DPoS股份授权证明算法及分析
股份授权证明机制(DPoS)是一种新的保障加密货币网络安全的
算法,由比特股bitshares提出。它在尝试解决比特币采用的传统工作量
证明机制(PoW)及点点币和NXT所采用的股份证明机制(PoS)的问
题的同时,还能通过实施科技式的民主,来抵消中心化所带来的负面影
响。
以比特股为例来说,DPoS机制是让每一个持有BTS(比特股发行的
一种加密货币)的人对为整个系统资源当代表的人进行投票,而获得票
数最多的101个代表将进行交易打包计算。对此,可以理解为有101个矿
池,这101个矿池彼此的权利是完全对等的。那些握着BTS选票的人可
以随时通过投票更换这些代表(矿池),但如果他们提供的算力不稳
定,计算机宕机或试图利用手中的权力作恶,那将会立刻被愤怒的选民
们踢出整个系统,而后备代表可以随时顶上去。从某种角度来看,DPoS有点像美国的议会制度,只不过不是四年一次选举,而是时刻都
在选举中。2.4 Sidechains
Sidechains(侧链)实质上不是指特定的某个区块链,而是指那些
遵守侧链协议的所有区块链,这个词是针对比特币主链来说的。侧链协
议是指可以让比特币安全地从比特币主链转移到其他区块链,同时又可
以让其他区块链上的货币安全返回到比特币主链的一种协议。
所以从某种程度上来说,现在市面上的所有区块链,例如以太坊、莱特币、狗狗币等区块链都可以成为侧链应用。侧链的实现具有重大意
义,它意味着比特币可以在不同的区块链上流通,其应用范围和应用前
景会更加广泛。一旦侧链的应用流行起来,有创意有想法的人就会研发
出各种不同的侧链协议来和比特币进行对接,很显然这种方式会进一步
巩固比特币在区块链中的地位。2.4.1 侧链背景
侧链的提出主要是基于以下几个原因。
(1)应对其他区块链的应用威胁
现在市面上出现了几种非常流行的区块链,例如以太坊区块链、比
特股区块链等,这些不断产生的新的区块链势必会对比特币区块链产生
很大的威胁。以太坊区块链更是提出了智能合约这个有望颠覆整个区块
链的应用,而到目前为止,基于比特币的应用开发项目还不多,已有的
项目难度也很大。
(2)比特币核心开发组不欢迎附生链
比特币现有的应用中已经存在合约币和彩色币等附生链应用,但是
基于一些原因比特币核心开发组并不是很欢迎这些应用。他们的考虑是
这些应用会在一定程度上降低比特币区块链的安全性。
(3)Blockstream商业化的考虑
有了以太坊众筹的前车之鉴,比特币核心开发组也希望能以某种商
业化的方式来实现更高的回报,所以基于比特币的侧链应用也激发了一
群人开始尝试商业化这些应用。基于以上三个原因,提出侧链协议,把比特币从主链上安全地转移
到了其他货币区块链,这样既增加了区块链的多样性又可以应对二代币
的竞争,同时这些应用本身确实具有比较大的商业前景,一旦实现商业
化,这一块也将成为一块很大的蛋糕。2.4.2 技术原理
楔入式侧链技术(pegged sidechain),它将实现比特币和其他数字
资产在多个区块链间的转移,这就意味着用户们在使用他们已有资产的
情况下,就可以访问新的加密货币系统。目前,侧链技术主要由
Blockstream公司负责开发。
这里先列出“侧链”所需具备的属性,具体如下。
·在侧链间移动的资产应当能够被当前持有者移回,但除此之外的
任何人都不行(包括前持有者)。
·资产的移动应当是无交易对手风险的;也就是说,不诚实的一方
无法阻止转移的发生。
·资产转移应当是元操作(原子操作)的,即要么完全完成,要么
根本不发生。不存在会导致资产损失或允许欺诈产生的失败模式。
·侧链应当设有防火墙:一个会使某条链发生资产铸造(或偷盗)
的缺陷(Bug),不应导致其他任何链出现资产的铸造或偷盗。
·区块链重组时应当处理干净,即使是在资产转移的期间也要如
此;任何破坏应当只发生在它所处的侧链上。总的来说,理想情况下,侧链应当完全独立,其他链上所需的全部数据应由用户提供。侧链的验证者应当只有在侧链本身的显式共识规则有要求时,才去跟踪其他链。
·不应要求用户去跟踪他们未主动使用的侧链。
早期“转移”钱币的解决方案是用一个可公开识别的方式来销毁比特
币的,新的区块链能够检测到,以允许铸造新币[Bac13b]。这解决了
上面提到的部分问题,但由于这种方法只允许单向转移,因此还不足以
满足我们的目的。我们提出的方案是由资产转移的交易本身提供所有者
证明,从而实现资产转移,以避免让节点有跟踪发送方链的需求。从上
层实现的角度来说,当资产从一个区块链向另一个链移动时,我们在第
一个区块链上创建交易锁定资产,然后在第二个区块链上创建一笔交
易,该交易的输入中包含一个锁定已正确完成的密码学证明。这些输入
可用某种资产类型来标记,比如创生出资产的区块链的创世哈希
(genesis hash)。
第一个区块链称之为父链,第二个则简称为侧链。在某些模型中,两条链可对称地来处理,因此这一术语是相对而言的。如果打算将资产
从(初始)父链转移到一条侧链,期间可能会再转移到别的侧链,最终
还能转回至父链,并保全初始资产。一般情况下,我们把父链看成是比
特币系统,侧链则是其他区块链中的某一个 ......
区块链开发指南
申屠青春 主编
ISBN:978-7-111-57120-9
本书纸版由机械工业出版社于2017年出版,电子版由华章分社(北京华
章图文信息有限公司,北京奥维博世图书发行有限公司)全球范围内制
作与发行。
版权所有,侵权必究
客服热线:+ 86-10-68995265
客服信箱:service@bbbvip.com
官方网址:www.hzmedia.com.cn
新浪微博 @华章数媒
微信公众号 华章电子书(微信号:hzebook)目录
推荐序一 区块链的价值实现
推荐序二 区块链,推动金融代际跃升的新力量
推荐序三 区块链技术的现实和未来
前言
第1章 区块链基础
1.1 交易和交易链
1.1.1 比特币地址
1.1.2 交易的本质
1.1.3 输入和输出
1.1.4 交易类型
1.1.5 找零地址
1.2 区块和区块链
1.2.1 区块结构
1.2.2 创世块
1.2.3 区块链原理
1.3 挖矿、矿池
1.3.1 挖矿原理与区块的产生
1.3.2 挖矿难度
1.3.3 矿池原理与商业模式1.4 脚本系统
1.4.1 脚本特点
1.4.2 脚本运行过程
1.4.3 脚本操作码解读
1.4.4 脚本执行过程
1.5 合约应用案例
1.5.1 合约应用原理
1.5.2 示例1:提供押金证明
1.5.3 示例2:担保和争端调解
1.5.4 示例3:保证合约
1.5.5 示例4:使用外部状态
1.5.6 示例5:跨链交易
1.5.7 示例6:支付证明合约
1.5.8 示例7:特定对象的快速调整(微)支付
1.5.9 示例8:多方去中心化彩票
参考资料
第2章 区块链进阶
2.1 外带数据
2.1.1 OP_RETURN外带数据
2.1.2 Multi-Signatures外带数据
2.2 Counterparty2.2.1 Counterparty附生链的实现机制详解
2.2.2 发送
2.2.3 订单
2.2.4 发行
2.2.5 广播
2.2.6 赌约
2.3 挖矿算法解析
2.3.1 PoW挖矿算法及分析
2.3.2 PoS股权证明算法及分析
2.3.3 DPoS股份授权证明算法及分析
2.4 Sidechains
2.4.1 侧链背景
2.4.2 技术原理
2.5 最新比特币技术
2.5.1 IBLT
2.5.2 隔离见证
2.5.3 闪电网络
2.5.4 RSMC
2.5.5 HTLC
参考资料
第3章 密码学基础3.1 Hash函数
3.1.1 技术原理
3.1.2 SHA-1算法
3.1.3 SHA-2算法
3.1.4 SHA-3算法
3.1.5 RIPEMD160算法
3.2 椭圆曲线密码
3.2.1 椭圆曲线方程
3.2.2 公钥和私钥的产生算法
3.3 ECDSA数字签名
3.4 Schnorr数字签名
3.4.1 技术思想
3.4.2 Schnorr与ECDSA的异同
3.5 Bloom filter
3.5.1 技术原理
3.5.2 应用案例
第4章 比特币区块链开发
4.1 Bitcoin的编译过程
4.1.1 Ubuntu下的编译
4.1.2 Mac下的编译
4.1.3 Windows下的编译4.2 代码剖析
4.2.1 主要模块
4.2.2 初始化和启动
4.2.3 P2P网络
4.2.4 交易和区块
4.2.5 脚本系统
4.2.6 挖矿
4.2.7 私钥
4.3 性能实战
4.3.1 建立私链
4.3.2 优化改进
4.4 API开发
4.4.1 命令行调用
4.4.2 RPC API调用接口
4.4.3 如何调用API进行开发
4.4.4 通过命令实现区块链的查询实例
第5章 以太坊智能合约开发
5.1 以太坊
5.1.1 以太坊的定义
5.1.2 下一代区块链
5.1.3 以太坊虚拟机5.1.4 以太坊的工作原理
5.2 以太坊账户管理
5.2.1 账户
5.2.2 钥匙文件
5.2.3 创建账号
5.3 更新、备份、恢复账号
5.3.1 更新账号
5.3.2 账号备份和恢复
5.4 公有链、联盟链、私有链及网络配置
5.4.1 以太坊网络
5.4.2 公有链、私有链和联盟链
5.4.3 如何连接
5.4.4 更快地下载区块链
5.4.5 静态节点、信任节点和启动节点
5.5 搭建测试网络和私有链
5.5.1 Modern测试网
5.5.2 设置本地私有测试网
5.6 账户、交易核心概念及投注合约解析
5.6.1 外有账户与合约账户
5.6.2 什么是交易
5.6.3 什么是消息5.6.4 什么是gas
5.6.5 估算交易成本
5.6.6 账户交互示例:投注合约
5.7 深入浅出智能合约
5.7.1 合约的定义
5.7.2 以太坊高级语言
5.7.3 写合约
5.7.4 编译合约
5.7.5 创建和部署合约
5.7.6 与合约互动
5.7.7 合约元数据
5.7.8 测试合约和交易
5.8 如何部署、调用智能合约
5.8.1 RPC
5.8.2 惯例
5.8.3 部署合约
5.8.4 和智能合约互动
5.8.5 Web3.js
5.8.6 控制台
5.8.7 查看合约与交易
5.9 智能合约案例实战参考资料
第6章 Fabric原理和实操
6.1 超级账本项目背景
6.2 Fabric简介
6.3 系统架构
6.3.1 交易
6.3.2 区块链数据结构
6.3.3 节点
6.4 交易背书的基本流程
6.4.1 客户端创建交易后发送到它所选择的背书节点
6.4.2 背书节点模拟交易,然后生成背书签名
6.4.3 提交客户端获取交易的背书,通过排序服务广播
6.4.4 排序服务向所有节点投递交易消息
6.5 背书策略
6.5.1 背书策略规范
6.5.2 交易评估与背书策略
6.5.3 背书策略示例
6.6 验证总账(1.0版本之后的功能)和原始总账检查点(精简)
6.6.1 验证总账
6.6.2 原始总账检查点
6.7 Fabric V1.0开发者快速入门6.7.1 前置条件和系统配置
6.7.2 下载源代码,创建Fabric网络
6.7.3 生成配置文件
6.7.4 使用Docker创建Fabric网络创建加入通道(账本)
6.7.5 示例合约执行过程解析
6.7.6 查看智能合约执行日志
6.7.7 手工创建和加入通道
6.7.8 使用命令行工具部署、调用、查询智能合约
6.7.9 开发环境故障排除
6.7.10 Fabric常用的Docker命令
6.8 智能合约开发
6.8.1 智能合约的定义
6.8.2 GO语言智能合约的开发和部署
6.8.3 Java智能合约的编写与部署
6.8.4 开发和提交代码
相关术语
附录A 国内区块链联盟介绍
附录B 《ChinaLedger面向中国资本市场应用的分布式总账白皮书》全
文推荐序一 区块链的价值实现
区块链和分布式账本技术是全球十大战略技术趋势之一,也是我国
金融界、科技界过去一年高度关注的热点之一。毫无疑问,2017年我国
金融界、科技界将会加大在区块链和分布式账本技术领域的投入,同时
市场上将会出现几个实际的应用。
深圳市金融科技协会(原深圳市金融信息服务协会)在研究推动区
块链和分布式账本技术及应用的过程中,遇到了一批积极探索、深入钻
研、大胆应用这门技术的志同道合者,并与微众银行、国信证券、博时
基金、富德保险、深证通、银链科技、招银网络、致远速联、中证信用
等25家金融机构和金融科技企业共同发起并成立了金融区块链合作联盟
(深圳)。在这个过程中,我也加深了对申屠青春、姚辉亚、宿旭升等
区块链积极推动者的认识,与他们建立了友谊,其中申屠青春就是本书
的作者之一。
申屠青春近几年专注于研究区块链技术和应用,技术能力得到了业
内的高度认可。他对区块链的热爱程度近乎痴迷,凡是区块链圈内的交
流,几乎都有他的身影。对于区块链技术和标准,他都热心地和业内人
士进行分享。他为金链盟的筹建和运作做了不少有益的工作,也是成立
金链盟的倡议者之一。自从2015年,人们发现了区块链巨大的潜在价值后,区块链技术已
经飞速发展了两年多。这两年之中,区块链成为主流金融圈所推崇和研
究的创新技术。全球众多大型金融机构都投入了人力财力进行区块链研
究,R3、HyperLedger等大大小小的组织也纷纷成立。我国的反应也很
迅速,金链盟、ChinaLedger、工信部区块链联盟快速发展起来。从行
业巨头参与的积极性和政府的重视程度来看,我国显然不想在区块链领
域落后。
2008年年底,中本聪在他的论文中提出一个点对点电子支付系统的
构想,并且于2009年实现了比特币的原型。这个系统可以使地球上的任
何人通过互联网以极致的效率进行货币交换和价值传递,无需任何第三
方机构。比特币没有发明任何新技术或算法,其中涉及的技术工作量证
明、时间戳、公钥体系等早已成熟。神奇的是,中本聪通过对这几项技
术的组合解决了无需可信第三方的数字资产所有权问题。从广义上讲,这些技术和思想的集合正是如今谈论的区块链。
从技术上看,区块链算是一个自由开放、没有固定形式的开源社
区。众所周知,Linux开源社区中,Linus具有绝对权威来定制发展路
线。有趣的是,区块链社区不存在这样一个角色,中本聪在2010年就在
互联网上消失了,至今也没能确认其真实身份。也就是说,没有任何官
方定义区块链该怎么实现,以及未来该怎么样发展。没有方向也许正好
说明“一切皆有可能”。去权威的社区呈现出一种百花齐放的状态,并且涌现出了大量的优
秀项目和先进理念。纵览区块链的发展历史,大多创新点可归纳为共识
机制、智能合约、隐私安全、可扩展性这几个方面,由于技术实现的灵
活性相当大,因此更多的争论和共鸣在于设计理念和哲学上。
共识机制
中本聪在提出以工作量证明(PoW)机制作为共识算法之后,部分
人认为耗能过大,于是就有了Sunny King设计的“环保”的股权证明
(PoS)机制,后续又发展到Bitshares改进的股份授权证明(DPoS),并衍生出了更多的类PoS机制。从公有链的角度来看,共识算法就是公
平和效率孰重孰轻的决策,技术实现不是难点,难点在于如何从社会
学、从人性出发去设计激励机制。各种共识算法的支持者都有其合理的
理由,不同共识的争论即使到现在也还一直存在。
另一个领域,金融机构的关注点在于效率、不可篡改及对应用的支
持,由于不需要链上的代币激励,因而改进的拜占庭容错(PBFT)、PAXOS、RAFT等传统分布式一致性算法就成为首选。
由此也就形成了两种区块链生态:公有链和联盟链。公有链可以任
意加入,联盟链是许可加入,联盟链的用户大多是机构或公司,需要区
块链契合自身的业务模式。从共识机制开始,区块链就走向了两条不同
的道路,最终双方是竞争还是融合,有待后续观察。智能合约
对智能合约的探索是出于对比特币区块链低效的脚本系统的不满,该脚本使用的是非图灵完备的堆栈语言,只能实现有限的功能。
一些智能合约研究者一直追求在区块链上运行强大的机器语言,让
每个用户都能见证其运行的过程和结果,实现“程序即规则”(Code is
Law)的智能环境。从图灵完备的以太坊EVM、超级账本ChainCode到
Chain平台的ChainCore,研究者的目标是在有限的存储空间中设计一个
完备合约语言和高效的底层虚拟机,甚至将传统开发语言(如CC++、Java)移植到区块链上。效率和安全性的改进依然任重道远,这也是区
块链领域最有技术含量的发展方向之一。
隐私安全
区块链中的个人隐私保护是强需求,特别是金融机构要使用的区块
链,保护客户隐私是基本的合规条件;但同时还不能产生绝对隐私,必
须要让监管者知道交易内容。
隐私安全的研究者大多需要深入掌握密码学知识,这不是一件轻松
简单的工作。ZCash使用了零知识证明算法来隐藏交易双方在区块链的
信息;比特币使用多输入多输出交易、隐身地址(Stealth address)和其
他更多古老的混币方案来保护用户隐私。联盟链将采用数字证书认证用
户,隔离一切非相关用户的数据访问。隐私安全是一把双刃剑,技术上满足隐私保护的需要,同时也增加了系统实现的复杂度;在降低透明性
的同时,也要让监管更方便。
可扩展性
用户交易数的增多不可避免地会带来区块链数据膨胀的问题,可扩
展性解决的是如何尽可能高效地存储不可篡改的区块链数据。业界讨论
的焦点放在如下两种方向的解决方案上:
1)从交易层把部分交易迁移到子区块链上运行,即侧链、闪电网
络;
2)从减少存储上着手解决,对原始数据进行裁剪分片,研究更安
全的瘦客户端,只存储非全量验证数据就可正常工作。
也许从交易层进行分解可以让问题一劳永逸,但这种方法的可靠实
现没有理论上那么简单。侧链技术现在正处于原型验证期,到真正实用
的程度还需要一段时间。
从上述维度来看,区块链开发是一种综合能力的体现,其开发模式
与互联网应用大有不同。传统互联网应用要求快速迭代,不断试错,区
块链应用反而在发布前需要细致测试,对未来规划要有清晰的认识,因
为一旦上线了就不是开发者能控制的:没有灰度发布、没有回滚下线、试错的成本极高。区块链是一台永不停止的信任机器,任何一次改变都需要通过共识,要明白共识的达成是极其困难的,所以在开发时一定要
十分谨慎。
区块链技术的发展还面临着很多的挑战,需要更多的人才加入到探
索者的队伍中。区块链开发更是需要复合型人才,分布式网络、分布式
计算、密码学、编译原理、经济学等方面的内容都需要涉及,国内缺乏
区块链综合技术的教程,这本书来的正当其时。本书各个主题的作者都
是相关领域的专家或创业者,他们是对区块链理解最深入的一批人,具
有较强的实战经验。书中各章节内容深入浅出,按时间顺序介绍区块链
的技术发展,并且加入了大量的代码示例,鼓励读者动手实践,以帮助
读者快速掌握区块链的开发技能,是一本值得一读的实战型好书!
希望大家在阅读本书后有所收获。
邹胜
2017年4月
邹胜,深圳证券交易所前副总经理、深圳证券通信公司前董事长,拥有24年证券金融行业经验,曾领导深交所IT和深证通打造了第五代核
心交易系统、中国证券期货业南方中心、金融云等业内领先的金融科技
基础设施。现任深圳市金融科技协会联席会长,并致力于分布式交易技
术在中国证券金融行业的应用推广。推荐序二 区块链,推动金融代际跃升的
新力量
金融为解决信息不对称而生,纵观3000年的发展历程,金融业态的
变迁始终围绕着信息如何对称而展开,并基于外界环境的影响在金融化
与科技化两个维度上演绎迭代。从金融化维度上看,发展主线围绕
着“有中心”与“无中心”展开,哪一种业态更能解决信息对称,在不同的
时空下,基于不同的金融工程技术而有不同的呈现,近400年的现代金
融史正是一条从“无中心”到“有中心”再到“多中心”进而又可能回到“无中
心”的演变轨迹。从科技化维度上看,信息技术的进步对金融业的影响
非常敏感,人类历史上每一次信息技术的大提升都会带来金融业态的一
次跳跃,尤其是近一百年来,电报、电话、海底电缆、计算机、互联
网……无不带来金融业态的深刻变革,变革的指向始终是从“信息不对
称”到“信息有限对称”并向着“信息对称”发展。
回顾我国改革开放后40年的金融发展,1997年无疑是至关重要的一
年,那一年我国的银行业成功推出了网上银行,以此为标志,中国开始
进入互联网金融时代。伴随着互联网这一千年一出的技术革命,金融业
态发生着历史性的变革。不论我们以“互联网金融”还是以“金融互联
网”来称谓这场变革,都不可否认金融业在解决信息对称的有效性,以及达成信息对称的效率性上,都得到了大幅提升,尤其是在以4G和智
能手机为载体的移动金融出现之后,更是如此。
当然在这场长达20年的互联网金融变革中,互联网技术的内在缺陷
也日益显现,网上信息的失真、可篡改、无法确权、加密强度低等特性
都制约着金融业务的进一步深入,信息量越大反而越限制了信息的有效
性,互联网金融开始触及自身发展的瓶颈。如何寻找新一代的替代技术
解决信息的“二次不对称”,是金融业下一步演变的关键。
幸运的是,互联网本身也在迭代,并在其中一个迭代方向上出现了
区块链技术。BlockChain,从诞生的第一天起就具有信息的真实、不可
篡改、可确权、强加密等特征,这在某种意义上正是互联网技术的“扬
弃”。而其在物理层和通信协议层与互联网的兼容,更使得区块链技术
的应用成本低、推广简便。
金融业要求信息应真实、安全、准确、权属清晰,因此我们有理由
相信,互联网金融下一步演绎的方向是“区块链金融”,在区块链的路径
上,继续探索哪一种“中心化形态”更有利于解决信息的对称性和效率
性,从而将金融业态推向一个新的高度。
如果我们有能力预测“区块链金融”的发展轨迹,那么我们是否会形
成如下这样一些观点。
·互联网账户的区块链化。互联网金融的效应之一是让每一个金融机构都能平等地接触到终端用户,不受地域、网点、规模所限,重构大
中小金融机构在金融领域重要性的自上而下排序的金字塔结构,带有典
型的金融领域内的“普惠”特征。然而,这种扁平的平等触达客户的金融
结构还需要另一个先决条件,那就是中小金融机构必须用技术手段自证
自己的信用,自证安全可靠。显然,这有赖于区块链技术的运用。因
此,在线开户、存款、支付、交易等业务整体向区块链平台迁移成为一
种必然。
·支付工具和支付体系的区块链化。以国内支付领域的现状来看,扫码支付替代磁条卡支付的趋势已经确立。然而,扫码支付的安全性始
终是各方担忧的焦点。一方面,在二维码的生成与二次传播上如何增强
加密强度;另一方面在二维码底层第三方支付的虚拟账户层面或银行的
二类账户层面如何增强加密强度,必然会成为区块链技术发挥作用的结
合点。此外,从商户收单的领域来看,商户体系只是从围绕银行展开收
单和清算转变为围绕第三方支付公司展开,仍是其他“中心”的从属,基
于区块链技术构建的以各商户互为中心的、以预付费卡为支付载体
的“自收单体系”也将成为支付领域变革的一个重要方向。
·征信的区块链化。互联网的持续推进引领着全球进入大数据时
代,而征信在大数据时代呈现出了完全不同的业务逻辑和规则,但就目
前来看,数据的权属问题将构成大数据征信模式最重大的挑战。而数据
是谁的、在哪里确权、如何调用、如何计价等问题都可以借助区块链技术加以解决,从这个意义上说,大数据征信的内核是区块链征信。
·资产证券化的区块链化。资产证券化技术成功解决了基础资产如
何变成可交易的金融工具及如何计价交易的难题,从而极大地提升了金
融资产的周转效率,因此被视为20世纪最重要的金融创新。然而,其基
于线下的风险控制流程已难以适应互联网时代对金融效率和信息全面性
的要求,因此,资产证券化的互联网模式已成为金融B2B领域的重要方
向。同样,资产证券化各参与方信息的准确、不可篡改、确权、安全加
密等也是ABS互联网化必须要面对的问题,也必然要辅助以区块链技术
加以解决。
·金融监管的区块链化。随着金融体系的日益庞大和复杂,如何监
管已经成为世界难题。2008年美国次贷危机诱发的全球金融危机,深刻
反映出全球监管的滞后与漏洞。然而,随后出台的一系列监管补救法
案,包括多德弗兰克法案、沃克尔法案、新巴塞尔协议等,无一例外仍
在延续旧有的“规则性监管”的理念和思路,在所谓的金融杠杆控制上做
出各种主观性的设置,全然没有看到在新技术运用上有突破性的理念和
方法。基于后互联网时代的一系列信息技术已经完全可以做到实时、同
步、自合理性设置、自预测性、自迭代的监管,即“数据性监管”,这也
必然会成为下一轮全球金融监管改革的方向。区块链,基于其独特的信
息处理属性,无疑会在“数据化监管”方面发挥重要的作用,有效构建监
管部门、金融机构、金融客户之间的合理数据纽带。恰如20世纪90年代末互联网进入应用开发阶段一样,区块链的产业
应用同样需要一批具备区块链开发能力的人员、团队、技术组织,如何
高效率地普及区块链技术、高效构建区块链技术生态至关重要。申屠青
春等人编著的《区块链开发指南》,是一部难得一见的区块链实用著
作,系统性地总结和提炼了区块链技术的核心属性,并从开发者的视角
予以展开,相信在区块链技术和开发生态构建方面一定会发挥重要作
用。也希望有更多区块链领域的技术专家和先行者贡献自身的知识和体
会,共同推进区块链这一独特的信息技术,使其更迅速地与金融场景相
结合,共同提升我国的金融效率与质量。
曹彤
国金ABS云创始人
厦门国际金融技术有限公司董事长
中国区块链研究联盟副主任推荐序三 区块链技术的现实和未来
一直以来,科学技术都是推动时代发展的原动力。20世纪90年代,随着互联网的出现,人类的信息传递方式发生了重大改变,引发了新闻
媒体行业的革命,促进了电子商务的流行;移动互联网的发展带来的影
响更为巨大,激发了社交的变革,带来了更为便捷、高效的包括金融服
务、出行服务等在内的各类新型社会服务方式,而且社会的协作模式和
运作效率从整体上也发生了深刻的变化,这些正悄然改变着社会。区块
链作为近年来新兴的IT技术,对任何由第三方机构来进行信用背书的社
会协作模式都可能会带来改变,并在金融服务、企业运作、社会生活甚
至社会治理等领域引发深远的变革。
区块链是一种去中心化、去信任化的分布式账本技术,由分布式数
据存储、点对点传输、共识机制、加密算法等多种技术集合而成。区块
链是起源于比特币的底层技术,自2009年被提出以后,近年来已成为各
大金融机构、IT公司、投资机构、咨询机构关注的热点,产业界纷纷加
大研发投入力度。互联网全面发展以后,已经近乎完美地解决了信息传
递的问题,但是还不能自由地实现价值点到点的传递,价值的传递仍然
需要中心化的可信第三方来完成,在一些应用场景中仍存在一定的局限
性。区块链的出现能够在没有信任基础的双方之间建立信任,完成价值
传递,因而被誉为创造信任的机器。由于其具有去中心、去信任及不可篡改的特点,区块链被认为可以应用在多种业务场景中,用来建立信
任,提升透明性、可靠性与安全性。目前,区块链的应用已经不只是在
数字货币和支付结算领域,在供应链金融、数字资产交易、共享经济、食品安全、慈善等多个领域均有探索,而且还将为云计算、移动互联
网、物联网等新一代信息技术的发展带来新的机遇。
当前,区块链一方面带有耀眼的光环,另一方面在现实应用中还存
在着很多问题亟待解决,比如:大量冗余存储、共享的数据带来了数据
安全和隐私保护等方面的挑战;在去中心化、匿名的区块链系统中,使
用私钥管理用户资产,私钥一旦丢失,对应的资产所有权也将丢失,而
如今应用对于私钥保护基本上是用软件来实现的,理论上都存在被攻破
的可能性;另外,链上敏感数据的保护与验证也存在一定的矛盾,我们
既希望重要的信息对于无关者不可见,又需要相关者在一些场景下验证
信息;除此之外,智能合约也存在着一些问题,如现有司法系统对智能
合约的理解和接受程度问题,部分定性合同条款难以用代码来表述的问
题,代码缺陷对智能合约执行影响的问题等。璞玉亦须雕琢,对于区块
链的这些问题还需要进一步探索,还有大量艰苦的工作要做。
对于区块链,业内目前有两种截然相反的态度。一种是过于乐观,看到区块链技术在比特币应用的成功之后,认为区块链技术可以很快地
为社会各方面带来翻天覆地的变化。另一种态度则过于悲观,认为区块
链存在的问题太多,除了比特币之外再无成功应用,且区块链可以做的工作传统信息技术完全可以解决,甚至更高效。有业内人士担心这又是
一个被过度炒作的概念,最终会不了了之。从区块链技术的发展历史来
看,来源于比特币的区块链技术,具有无限制加入、匿名机制、公开账
本、工作量证明共识算法等技术特点,这些特点比较适合支付结算相关
应用,但不具有普适性。后来为了适应不同的应用场景,在比特币平台
之后,又陆续出现了多种底层平台,包括致力于打造“世界计算机”的以
太坊平台、提供跨行业解决方案的HyperLedger项目下的Fabric平台、为
受监管的金融行业提供专业解决方案的R3 Corda平台等,这些平台相互
影响并不断发展。目前区块链技术除了影响力最大的比特币之外,大部
分应用还处于探索阶段,成功的应用不多,但是从当前各方面的探索
中,我们也看到了区块链这种去中心、去信任的价值传递网络的巨大潜
力。区块链技术目前尚处在发展的初期阶段,现在最重要的是以务实的
态度深入研究,特别是要吃透技术细节,结合实际场景,推动区块链相
关应用扎实落地。在这方面,IT工程师们能够发挥更加积极的作用。
虽然区块链技术仍在发展之中,仍有不少问题需要解决,但是随着
基础平台的不断完善,区块链应用将得到快速发展。根据Gartner分析报
告预测,预计经过3到5年的发展,区块链应用的落地会出现大规模的增
长;未来10年左右,整个区块链市场将趋于成熟,广泛应用在智能合约
驱动类业务、数字货币业务、机构间和机构内业务及公共记录等领域。
目前,已有众多从理论和业务层面探讨区块链的图书和文章,但是技术
类图书却非常稀缺。本书对于区块链的开发做了系统的介绍,是献给站在IT前沿开拓者的佳作。作为IT从业者,此时更需要把握当下,因为未
来已来。让我们怀揣梦想,一起努力,共同打造更加完善的区块链服
务,用科技创造美好未来!
周天虹
招商银行信息科技部总经理
2017年4月前言
比特币于2009年诞生,在很长一段时间内,人们只知比特币,不知
区块链。从2015年开始,区块链像狂风一样席卷全球,倍受金融界和科
技界的关注;2015年年底,区块链技术逐渐得到国内金融界和科技界的
了解和认同。
区块链行业的蓬勃发展源于区块链有可能给各行业带来巨大的变
革。麦肯锡在2016年年初发布报告,指出区块链技术将在未来五年内颠
覆众多行业,特别是银行业和保险业;埃森哲预测到2025年,区块链技
术每年可帮助全球8大投资银行节省80亿美元至120亿美元的基础设施成
本。
全球金融巨头如IBM、高盛、摩根大通、花旗银行、中国平安、瑞
银、德勤、毕马威等纷纷布局区块链;区块链初创公司在全球范围内如
雨后春笋般崛起,发展速度惊人。从2012年以来,全球区块链创业领域
共发生207起融资并购事件,融资额高达14亿美元。
截至2017年3月,区块链在金融业的落地应用包括跨境支付、清算
结算、互助保险、电子票据、商业银行抵押品、贸易金融、数字资产登
记、银行间贸易、银行间对账与审计、监管与简化流程、积分、征信、外汇交易市场、证券清算和交割等。区块链技术还能解决供应链管理、物联网、医疗、军事、政务等领
域的很多问题。例如,Warmart试图用区块链保障我国市场的猪肉供应
链安全;医疗领域中,生成基于区块链的、不可更改的电子病历、检验
报告等用于存证,方便解决医疗纠纷;军事防卫和信息安全化中,区块
链技术可实现信息防御平台的现代化;政务中,区块链可以简化文件归
档与政府公共档案管理,并且可用来发放政府社保、养老金等社会福利
及居民身份存证等。
由此可见,区块链将带来一场巨大的变革。正如德勤的报告中所预
言的一样:“区块链是一场改变信任的革命,将重塑金融行业。”而它作
为一项伟大的技术,不仅仅对于金融行业有革新性,对于其他行业,也
会有深远的影响。
而今实施“区块链+”战略所面临的最大难题是:极度缺乏从业人
员。很多金融机构和企事业单位对区块链还停留在概念阶段,其开发人
员不懂区块链;大部分对区块链技术感兴趣的人,或者想要从事区块链
行业的技术人员,未能系统地了解区块链的原理和发展,缺乏区块链开
发者应有的知识和技术储备。
为了让更多的开发人员转变成区块链开发者,让更多现有的区块链
开发人员系统地理解区块链技术,在区块链领导媒体巴比特的提议和牵
头下,成立了《区块链开发指南》编写小组,开始构思、编写本书。编写小组成员有:银链科技CEO申屠青春、深圳大学教授张鹏、币
信资深程序员宋波、朝夕网络CEO汪晓明、万达网络区块链研发中心总
经理季宙栋、华安保险系统架构师左川民、巴比特区块链资深工程师易
长军。
本书内容由申屠青春负责组织,共包含六个章节,具体分工如下:
申屠青春编写第1章和第2章的大部分内容,易长军对本部分内容亦有贡
献,币信的樊渊文贡献了1.4.2节、1.4.3节和1.4.4节,比特大陆的潘志彪
贡献了2.5.2节、2.5.3节和2.5.4节;张鹏编写第3章;宋波编写第4章;汪
晓明编写第5章;季宙栋编写第6章的实操部分,左川民编写第6章的原
理部分。此外,银链科技的林素兰参与第1章和第2章部分内容的编辑,万达网络的丛宏雷、张梦航参与第6章实操部分内容的编写。
本书以比特币、以太坊、Fabric三种区块链的技术原理和实际操作
为主要目标,全书具体内容如下。
第1章介绍比特币区块链,包括交易和交易链、区块和区块链、挖
矿、矿池、脚本系统、合约应用案例等内容,向读者们介绍区块链基础
知识。
第2章讲述区块链进阶技术,包括外带数据原理、Counterparty原
理、挖矿算法解析、侧链技术,以及最新的IBLT、隔离见证、闪电网
络等。第3章的主要内容是区块链中使用的密码学基础,包括Hash函数、椭圆曲线密码体系、ECDSA签名、Schnorr数字签名和Bloom filter算法
等,向开发者介绍密码学相关算法。
第4章是比特币区块链的编译、代码剖析、建立私链及API开发等实
操内容。
第5章介绍以太坊的技术原理,包括以太坊简介、账户管理、交易
原理、智能合约等,还涉及搭建私有链,智能合约开发、部署和调用等
实操过程。
第6章介绍了IBM开源的区块链底层技术平台Fabric的原理和实操,对Fabric系统架构、节点、验证总账、交易背书的基本流程进行了详尽
独到的分析,对Fabric的私有链建立和配置、链上代码的开发过程进行
了详细的描述,为开发者使用Fabric提供技术指导。
最后,感谢编写小组各成员的配合和支持,使本书最终得以完本。
感谢巴比特的李涛,时时督促此书的编写;感谢机械工业出版社华章公
司的编辑杨绣国为本书顺利出版付出的努力。编写小组期待本书能够在
区块链应用开发中给开发者以参考和启发。由于成书仓促,错误之处在
所难免,恳请广大读者朋友批评指正。
申屠青春2017年4月于深圳第1章 区块链基础
区块链究竟是什么?狭义地说,区块链就是比特币的底层技术;不
过,经过7年的发展,区块链已经不再“依附于”比特币,而是独立地发
展成为了一种革命性的技术,比特币则是区块链最大、最成功的应用。
从技术层面来看,区块链是一个基于共识机制、去中心化的公开数
据库。共识机制是指在分布式系统中保证数据一致性的算法;去中心化
是指参与区块链的所有节点都是权力对等的,没有高低之分,同时也指
所有人都可以平等自由地参与区块链网络,唯一的限制就是个人自己的
选择;公开数据库则意味着所有人都可以看到过往的区块和交易,这也
保证了无法造假和改写。基于以上特性,可以总结得出:区块链由许多
对等的节点组成,通过共识算法保证区块数据和交易数据的一致性,从
而形成一个统一的分布式账本。
从价值层面来看,区块链是一个价值互联网,用于传递价值。目前
的互联网仅用来传递消息,但是还不能可靠地传递价值;而比特币区块
链却可以在全球范围内自由地传递比特币,并且能够保证不被双花、不
被冒用。从这个角度来说,区块链是记录价值、传递消息和价值本身转
移的一个可信账本。
这里要提一下区块链在维基百科上的官方定义:一个区块链是一个基于比特币协议的不需要许可的分布式数据库,它维护了一个持续增长
的不可篡改的数据记录列表,即使对于该数据库节点的运营者们也是如
此。简而言之,区块链就是区块用某种方式组织起来的链条。在区块链
中,信用或记录被放在各个区块中,然后用密码签名的方式“链接”到下
一个区块。这些区块在系统的每一个节点上都有完整的副本,所有的信
息都带有时间戳,是可追溯的。事实上,在区块链创建之初,我们在大
多数情况下谈论的区块链都是比特币的底层实现方式。
基于区块链的系统和以往的其他系统存在很多不同之处,以区块链
技术为核心的系统包括如下四大最主要的特点。
·Distributed(分布式的)
·区块链是全球化的,系统上的节点是运行在太平洋某个小岛的笔
记本电脑上还是运行在中国某个小镇的服务器上,对系统本身来说都是
一样的,除了网络连接速度有区别之外,其他没有任何区别。区块链没
有中心节点,数据分布式地存储在各个节点上,即使绝大部分节点毁灭
了,只要还有1个节点存在,就可以重新建立并还原区块链数据。
·Autonomous(自治的)
·区块链是一种去中心化的、自治的交易体系,这种自治性表现在
两个方面:1)所有节点都是对等的,每个节点都可以自由加入和离
开,并且这一行为对整个区块链系统的运行没有任何影响。所有的节点都是按照相同的规则来达成共识,且无需其他节点的参与。2)区块链
系统本身一旦运行起来,就可自行产生区块并且同步数据,无需人工参
与。
·Contractual(按照合约执行的)
·区块链是按照合约执行的,第一体现在各个节点的运行规则(指
的是交易、区块链或协议)上,按照既定的规则执行,一旦出现违背规
则的行为,就会被其他节点所抛弃;第二体现在智能合约上,智能合约
是一种可程序化的合同条款、规则或规定,包含在每个交易中,交易验
证时必须先运行智能合约,只有通过了验证的交易才能被接受。
·Trackable(可追溯的)
·区块链的数据是公开透明的,不能被篡改,而且相关交易之间有
一定的关联性,因而很容易被追溯。比如比特币区块链,每一枚比特币
都有其特定的来源,通过输入可以追溯到上一个交易,或者通过输出追
溯到下一个交易。
·此外,区块链代码本身也是可追溯的,区块链系统是开源软件,其对于所有的人都是公开的,因此任何人都可以查看并修改这些代码,不过修改后的代码需要经过开源社区上其他程序员的审核。
本书主要讨论区块链技术,这不仅包括了比特币区块链技术,还包含了比特币区块链所没有的一些技术,本章接下来将对区块链的一些基
本知识做一个详细的介绍,包括交易和交易链、区块、挖矿、矿池、脚
本、智能合约等。1.1 交易和交易链
交易是签过名的数据结构,该数据结构会在区块链网络中广播,并
被收集到区块中。它会引用以前的交易,从该交易中发送特定数量的比
特币到一个或多个公钥中(即比特币地址),并且交易未被加密(比特
币体系中没有加密任何数据)。多个交易可组成一个区块(block),这些区块同样也会在区块链网络中传播,一个区块会引用上一个区块,简而言之,区块链就是由区块(block)用某种方式组织起来的链条
(chain)。区块链包括成千上万个区块,而一个区块内又包含一个或多
个交易,上下关联的交易组成了一个交易链,一个交易链内部可能又包
含了多个交易,下面的章节将会对这些知识点进行详细解释。1.1.1 比特币地址
比特币地址是一个由数字和字母组成的字符串,可以与任何想给你
比特币的人分享。由公钥(一个同样由数字和字母组成的字符串)生成
的比特币地址以数字“1”开头。下面是一个比特币地址的例子:
1J7mdg5rbQyUHENYdx39WVWK7fsLpEoXZy
在交易中,比特币地址通常是以收款方的形式出现。如果把比特币
交易比作一张支票,那么比特币地址就是收款人,也就是我们要写
入“收款人”一栏的内容。一张支票的收款人可能是某个银行账户,也可
能是某个公司、机构,甚至是现金支票。支票不需要指定一个特定的账
户,而是可以用一个普通的名字作为收款人,这使得它成为一种相当灵
活的支付工具。与此类似,比特币地址的使用也使比特币交易变得很灵
活。比特币地址可以代表一对公钥和私钥的所有者,也可以代表其他东
西。
比特币地址是由公钥经过单向的Hash函数生成的。用户通常所见到
的比特币地址是经过“Base58Check”编码的,这种编码使用了58个字符
(一种Base58数字系统)和校验码,提高了可读性、避免了歧义,并有
效地防止了在地址转录和输入中产生错误。Base58Check编码也被用于
比特币的其他地方,例如私钥、加密的密钥和脚本Hash中,用来提高可读性和录入的正确性。图1-1描述了如何从公钥生成比特币地址。1.1.2 交易的本质
交易实质上就是包含一组输入列表和输出列表的数据结构,也可称
之为转账记录,这其中就包括了交易金额、来源和收款人等信息,表1-
1就是一个比特币交易的数据格式。
表1-1 比特币交易数据格式图1-1 比特币地址生成流程
下面以一个具体的例子来说明一个区块链上的交易构成。假设有一
个带有一个交易及一个输出的交易A,其中的输入列表和输出列表如下
所示:
Input:
Previous tx: f5d8ee39a430901c91a5917b9f2dc19d6d1a0e9cea205b009ca73dd04470b9a6
Index: 0
scriptSig: 304502206e21798a42fae0e854281abd38bacd1aeed3ee3738d9e1446618c4571d10
90db022100e2ac980643b0b82c0e88ffdfec6b64e3e6ba35e7ba5fdd7d5d6cc8d25c6b241501
Output:
Value: 5000000000
scriptPubKey: OP_DUP OP_HASH160 404371705fa9bd789a2fcd52d2c580b65d35549d
OP_EQUALVERIFY OP_CHECKSIG
上文表示,交易A的输入0从交易
f5d8ee39a430901c91a5917b9f2dc19d6d1a0e9cea205b009ca73dd04470b9a6
的0号输出中导入了50个比特币,然后该输出发送50个比特币到一个比
特币地址的公钥Hash值
(404371705fa9bd789a2fcd52d2c580b65d35549d,该公钥Hash值是十六
进制表示,而非正常的base58表示)。
如果接收者想花掉这笔钱,那么他首先得创建自己的交易B,再引
用该交易A的0号输出作为交易B的输入。1.1.3 输入和输出
输入是对其他交易输出的引用,一个交易中通常列有多个输入。所
有被引用的输出值相加,得出的总和值会在该交易A的输出中用到。
Previous tx是以前交易的Hash值,Index是被引用交易的特定输出号,ScriptSig是一个脚本的前一半(脚本将在后文中详细讨论)。
脚本包含两个部分,一个签名和一个公钥,公钥属于交易输出的收
款人,并且表明交易创建者允许收款人获得的输出金额;另一个部分是
ECDSA签名,是通过对交易的Hash值进行ECDSA签名而得到的。签名
和公钥一起,证明原地址的真正所有者创建了该支付交易。
输出中包含了发送比特币的指令,金额(Value)是以聪
(Satoshi,1BTC=100000000聪)为单位的数值。ScriptPubKey是脚本的
另一半(这点将在后文中详细讨论),可以有多个输出,它们共享了输
入金额。一个交易中的每一个输出都只能被后来的交易当成输入引用一
次。如果你不想丢币,那就需要把所有输入值的总和值发送到一个输出
地址。如果输入是50BTC,但你仅想发送25BTC,那么比特币将创建2
个25BTC的输出:一个发往目标地址,另一个则回到你的地址(称之
为“找零”,详见1.1.5节)。在交易过程中,会产生一笔交易费,作为交
易费支付的任何比特币都不能被赎回,生成这个区块的矿工将获得这笔
交易费。为了验证某个交易的输入已经被授权,可以收集被引用的输出中的
所有金额。比特币体系使用了一个类似于Forth的脚本系统,其目的是验
证从某地址发出的比特币是否真正属于该地址的拥有人,输入的
scriptSig和被引用的输出scriptPubKey会按顺序运行。如果scriptPubKey
返回真,则输入被授权,证明是地址拥有人发出了比特币。通过脚本系
统,发送者可以创建非常复杂的发送条件,人们为了收到金额,首先必
须满足这些条件。举个例子,可以创建一个能被任何人赎回而无需授权
的输出,也可以创建一个需要10个不同签名的输入,或者无需公钥仅由
密码赎回的输出。1.1.4 交易类型
根据目标地址的不同,可以把交易分为如下几种类型。
(1)支付到公钥Hash
scriptPubKey: OP_DUP OP_HASH160
scriptSig:
一个比特币地址只是一个Hash值,因而发送者无法在scriptPubKey
中提供完整的公钥,当要赎回比特币时,接收者需要同时提供签名
scriptSig和公钥scriptPubKey,脚本系统会验证公钥的Hash值与
scriptPubKey中的Hash值是否匹配,同时还会检查公钥和签名是否匹
配。检查过程见4.2.5节。
(2)支付到脚本Hash
该类交易非常有意义,未来应该会在某些场合频繁使用。该类交易
的接受地址不是通常意义上的地址,而是一个多签地址,以3开头。比
如,三对公钥对可以生成一个多签地址。需要在生成过程中指定n of 3
中的n,n的范围是[1,3],若n=1,则仅需要一个私钥签名即可花费该地
址的币,若n=3,则需要三把私钥依次签名才可以。
地址以3开头,可以实现多方管理资产,极大地提高安全性,也可以轻松实现基于比特币原生的三方交易担保支付。一个m-of-n的模式如
下:
m {pubkey}...{pubkey} n OP_CHECKMULTISIG
其中,m和n需要满足:1≤n≤20,m≤n。
m和n可以是1 of 1、1 of 2、2 of 3等组合,通常选择n=3。
·1 of 3,最大程度私钥冗余。防丢私钥损失,3把私钥中任意一把即
可签名发币,即使丢失2把也可以保障不受损失。
·2 of 3,提高私钥冗余度的同时解决单点信任问题。3把私钥中的任
意2把私钥可签名发币,对于三方不完全信任的情形,即中介交易,非
常适用。
·3 of 3,最大程度解决资金信任问题,无私钥冗余。必须3把私钥全
部签名才能发币,适用于多方共同管理的重要资产,但是任何一方遗失
私钥均会造成严重损失。
多签地址的交易构造、签名、发送过程与普通交易类似。
(3)挖矿交易
挖矿(coinbase)交易用于凭空产生比特币。挖矿交易只有一个输入,该输入有一个“coinbase”参数,没有scriptSig,“coinbase”中的数据
可以是任意内容,它不会被使用。比特币把压缩的当前目标Hash值和任
意精确度的“extraNonce”都存储在这儿,区块头中的Nonce每次一溢出,它们就会增长。extraNonce有助于扩大工作量证明函数的范围,矿工很
容易修改Nonce(4字节)、时间戳和extraNonce(2~100字节)。
挖矿交易的输出金额在一段时间内是固定值,初始是50个比特币,每21万个区块后减半,目前已经经历了两次减半,因而是12.5个比特
币。输出地址可以是任何地址,一般是矿工或矿池的比特币地址。
Nonce溢出是指在对一个块进行散列时,Nonce从0开始,每计算一
次Hash都要增长一次,因而有可能会出现超过数值范围的情况,这时,extraNonce就要相应增长以存储Nonce。1.1.5 找零地址
在实际的区块链交易中,假设A拥有一个比特币地址,里面包含着
还没有花费过的10个比特币。B也有一个比特币地址,里面一分钱也没
有。当A想向B支付10个比特币时,A地址里的未花费输出变为零,而B
的则会变为10 BTC。如果A想支付的金额与所拥有的相同,自然不会存
在需要找零钱的问题。不过当手头的金额比要支付的大时,找零自然也
是天经地义的事情。
假设A的地址上有35个比特币(如图1-2所示),当A想向B支付8个
比特币时,如图1-2所示,只需要使用包含着20个比特币的那一笔未消
费支出,并设置好要支持的金额即可,剩下的12个比特币则会返回给
A,以便A在将来可以继续使用。
图1-2 找零示意图
这样就有了一个找零机制,实际上,比特币在交易时会把消费时所
用的地址(消费地址)的余额设置为零。当需要支付的金额小于可用余额时,在交易信息中必须告诉比特币网络零钱将要被发送至哪个地址,即“找零地址”。找零地址可能是也可能不是原先的发送地址。除此之
外,发送地址所留下的剩余款项将由网络作为交易费支付给矿工。在上
面的例子里,A可以选择将找回的零钱发送到一个新创建的找零地址
上,或者将原先发送的地址设置为找零地址,并将零钱返回。虽然将发
送地址作为找零地址对A而言是方便了管理,不过这也可能会造成A的
隐私性降低,在一定程度上还可能会影响到B的匿名性。
根据设计,每一笔比特币交易将在一个称为“区块链”的全球性的公
共总账上永久可见,这就意味着任何人随时都可以在上面进行跟踪查
询。通过将某个比特币地址与其使用者关联起来,好事者都可以据此绘
制关于这个人与他人之间的资金转移的关系图。但如果是将找回的零钱
发送至一个新创建的地址,那么就可以让这种追踪变得更加困难。
要理解这一点,可以参考图1-3。假设从地址A发送比特币到地址B
后,零钱返回地址为A,则区块链会揭示地址A向地址B支付了一笔钱。
同样的道理,如果有两个或两个以上地址参与其中,任何涉及这个接收
零钱的找零地址都会揭示A作为支付方的交易。假如某个控制着的任何
接收地址或付款地址的人其身份是众所周知的,那么其他有过交易往来
的各方的身份也有可能被推断出来。
现在想象一下,地址A发起付款到地址B,但此时将找零地址更改
为新生成的地址C,如图1-4所示。如果没有进一步的信息,那么其他人所能知道的,只是有一个交易拆分了地址A的余额至地址B和C。而地址
B或C的主人可能是也可能不是A。由于新地址C的加入,让整个交易的
真相变得更加扑朔离迷:哪一个地址代表着被支付方,哪一个地址代表
着找回的零钱呢?
图1-3 两种找零方案
图1-4 重新生成找零地址
当所有各方都将零钱发送至新创建的地址时,要想将个人身份与地
址相关联,就必须收集更多的信息,并耗费更多的资源。1.2 区块和区块链
比特币网络中,数据会以文件的形式被永久记录,我们称这些文件
为区块。一个区块是一些或所有最新比特币交易的记录集,且未被其他
先前的区块记录。可以将区块想象为一个城市记录者其记录本上单独的
一页纸(对房地产产权的变更记录),或者是股票交易所的总账本。在
绝大多数情况下,新区块会被加入到记录的最后(在比特币中的名称为
区块链),一旦写上,就再也不能改变或删除。每个区块记录了它被创
建之前发生的所有事件。1.2.1 区块结构
一个区块的结构如表1-2所示。
表1-2 区块结构示意图
每个区块都包括了一个被称为“魔法数”的常数0xD9B4BEF9、区块
的大小、区块头、区块所包含的交易数量及部分或所有的近期新交易。
在每个区块中,对整个区块链起决定作用的是区块头,如表1-3所示,接下来本章将会对每一个字段都做出比较详细的解释。
表1-3 区块头描述这里的hashPrevBlock就是区块之所以能够连成区块链的关键字段,该字段使得各个区块之间可以连接起来,形成一个巨大的“链条”。每个
区块都必须要指向前一个区块,否则无法通过验证。这个区块链条会一
直追溯到源头,也就是指向创世区块。很显然,创世区块的
hashPrevBlock的值为零或为空。在区块头中,最关键的一个数据项是一
个随机数Nonce,这串数字是一个答案,而这个答案对于每一个区块来
说都是唯一的,它的特点具体如下。
·这个答案很难获得。
·有效答案有多个,不过我们只需要找到一个答案就可以了。
·其他节点对有效答案的验证很容易。
正是因为问题很难解答,没有固定的算法可以求出答案,所以唯一
的做法就是不断尝试,找寻这个答案的做法就是“挖矿”,可以想象,会
有很多人同时都在“挖矿”,他们之间是相互竞争的关系。区块内包含许多交易,它们通过Merkle根节点间接被散列,以保证
矿工能及时追踪一个正在打包的区块内交易的变化情况。一旦生成
Merkle根节点,那么对包含一个交易的区块做散列所花的时间,与对包
含1万个交易的区块做散列所花的时间是一样的。
目标Hash值的压缩格式是一个特殊的浮点编码类型,首字节是指数
(仅使用了5个最低位),后3个字节是尾数,它能表示256位的数值。
一个区块头的SHA-256(一种单向函数的算法,可形成长度为256位的
串)值必定要小于或等于目标Hash值,该区块才能被网络所接受。目标
Hash值越低,产生一个新区块的难度就越大。
Merkle树是Hash的二叉树。在比特币中会两次使用SHA-256算法来
生成Merkle树,如果叶子个数为奇数,则要重复计算最后一个叶子的两
次SHA-256值,以达到偶数叶子节点的要求。
计算过程:首先按照区块中交易的两次SHA-256进行散列,然后按
照Hash值的大小进行排序,生成最底层。第二层的每个元素则是相连续
的两个Hash值的两次SHA-256的Hash值。之后,会重复这个过程,直到
某一层只有一个Hash值为止,这就是Merkle根。举例来说,想象有3个
交易,a、b、c,那么Merkle根的生成过程如下所示:
d1 = dhash(a)
d2 = dhash(b)
d3 = dhash(c)
d4 = dhash(c) 只有3个元素,是奇数,因而将最后一个元素重算一次
d5 = dhash(d1 concat d2)d6 = dhash(d3 concat d4)
d7 = dhash(d5 concat d6)
这里的d7就是以上三个交易的Merkle根。需要注意的是,Merkle树
的Hash值是小头位序(即高位在后,是数字在计算机中的一种表示形
式)。对于某些实现和计算来说,在散列计算前应该先按位反转,之后
在散列计算后再反转一次。1.2.2 创世块
创世块(Genesis Block)是指区块链的第一个区块,现在的比特币
客户端版本把创世区块号定为0,以前的版本把该区块号定为1。以下是
创世块的一种表示形式,它出现在以前的比特币代码的注释中,第一个
代码段定义了创建该块所需要的所有变量,第二个代码段是标准的区块
类格式,还包含了第一个代码段中缩短版本的数据。
GetHash= 0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
hashMerkleRoot = 0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
txNew.vin[0].scriptSig = 4866047994
0x736B6E616220726F662074756F6C69616220646E6F63657320666F206B6E697262206E6F20726F6C6C65636E61684320393030322F6E614A2F33302073656D695420656854
txNew.vout[0].nValue = 5000000000
txNew.vout[0].scriptPubKey =
0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704 OP_CHECKSIG
block.nVersion = 1
block.nTime = 1231006505
block.nBits = 0x1d00ffff
block.nNonce = 2083236893
CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=
4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1)
CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLocKt
ime=0)
CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030
332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73)
CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
vMerkleTree: 4a5e1e
coinbase参数(看上面的十六进制)中包含了“The Times
03Jan2009 Chancellor on brink of second bailout for banks.”这句话。
这句话翻译过来就是“2009年1月3日,首相第二次对处于崩溃边缘的银行进行紧急救助”,这句话正是泰晤士报当天的头版文章标题(如
图1-5所示)。这应该是一个该区块在2009年1月3日或之后创建的一个
证据,同时也是对银行系统采用部分准备金制度导致不稳定性的一个说
明。图1-5 2009年1月3日的泰晤士报创世块50BTC的收益被发送到如下地址:
1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa,我们称该交易为创世交
易。
创世块的收益花不掉,原因如下:比特币客户端把区块和交易分别
存储在两个数据库中,当客户端发现区块数据库为空时,就会用代码直
接生成一个创世块,但是没有把创世交易存储到客户端的交易数据库
中,比特币网络一旦收到要花掉创世交易输出的交易时,因为在交易数
据库中找不到创世交易,因而都会拒绝,也就是说花不掉这50个币了。
出现这种情况很可能是中本聪为了纪念创世交易,故意而为的。
创世块的数据结构如下所示。
·01000000:指版本号。
·0000000000000000000000000000000000000000000000000000000000000000:
为prev block。
·3BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A:
为Merkle根。
·29AB5F49:时间戳。
·FFFF001D:目标Hash值。·1DAC2B7C:随机数。
·01:交易个数。
·01000000:版本。
·01:输入个数。
·0000000000000000000000000000000000000000000000000000000000000000FFFFFFFF:
前一个输出。
·4D:脚本长度。
·04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73:
scriptsig脚本。
·FFFFFFFF:序列号。
·01:输出个数。
·00F2052A01000000:50 BTC的收益。
·43:指脚本scriptPubKey的长度。
·4104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC:
脚本scriptPubKey。·00000000:锁定时间。
JSON版本的创世块如下所示:
{
hash:000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f,ver:1, prev_block:0000000000000000000000000000000000000000000000000000000
000000000, mrkl_root:4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b,time:1231006505,bits:486604799,nonce:2083236893,n_tx:1,size:285,tx:[
{
hash:4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b,ver:1,vin_sz:1,vout_sz:1,lock_time:0,size:204,in:[
{
prev_out:{
hash:0000000000000000000000000000000000000000000000000000000000000000,n:4294967295
},coinbase:04ffff001d0104455468652054696d65732030332f4a616e2f3230303920
4368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73
}
],out:[
{
value:50.00000000,scriptPubKey:04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e
0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f OP_CHECKSIG
}
]
}
],mrkl_tree:[
4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
]
}1.2.3 区块链原理
区块链是所有比特币节点共享的交易数据库,这些节点基于比特币
协议参与到比特币网络中来。区块链包含每一个曾在比特币系统执行过
的交易,根据这个信息,人们可以找到任何时候任一个地址中的币数
量。
由于每个区块包含前一个区块的Hash值,这就使得从创世块到当前
块形成了一条块链,每个区块必定按时间顺序跟随在前一个区块之后,区块链结构如图1-6所示。因为不知道前一块区块的Hash值,因此没法
生成当前区块,所以要改变一个已经在块链中存在了一段时间的区块,从计算上来说是不可行的,如果它被改变,那么它之后的每个区块都必
须随之改变。这些特性使得双花比特币非常困难,区块链是比特币的最
大创新。图1-6 区块链示意图
如果一个区块是最长块链的最后一个区块,那么诚实的矿工只会在
这个区块的基础上生成后续块(创建新区块时通过引用该区块来实
现)。“长度”是指被计算成区块链的所有联合难度,而不是区块的数
量,尽管这个区别仅仅在防御几个潜在攻击时有用。如果一个区块链中
的所有区块和交易均有效,则该区块链有效,并且要以创世块开头。
对于区块链中的任何区块来说,只有一条通向创世块的路径。然
而,从创世块出发,却可能有分叉。当两个区块产生的时间仅相差几秒
时,可能会产生包含一个区块的分叉。当出现以上现象时,矿工节点会
根据收到区块的时间,在先收到的区块的基础上继续挖矿。哪个区块的
后续区块先出现,那么这个区块就会被包括进主链,因为这条块链更
长。
短区块链(或有效区块链)中的区块没有作用,当比特币客户端转
向另一个长区块链时,短区块链中所有有效的交易都将被重新加入到交
易队列池中,并被包括到另一个区块中。短区块链中的区块收益不会在
长链中出现,因而这些收益实际上是丢失了,这就是比特币网络设定
100个区块成熟时间的原因。
短区块链中的区块经常被称为“孤立”区块,事实上这些区块都有父
区块,并且可能还有子区块,只不过这些区块链未被包含进比特币主链,就好像被孤立了一样。1.3 挖矿、矿池
1.3.1 挖矿原理与区块的产生
比特币的挖矿和节点软件是基于对等网络、数字签名来发起和验证
交易的。节点向网络广播交易,这些广播出来的交易需要经过矿工的验
证,矿工们会用自己的工作证明结果来表达确认,确认后的交易会被打
包到数据块中,数据块会串起来形成连续的数据块链。中本聪本人设计
了第一版的比特币挖矿程序,这一程序随后被开发为广泛使用的第一代
挖矿软件bitcoind,这一代软件在2009年到2010年期间都比较流行。
每一个比特币的节点都会收集所有尚未确认的交易,并且会将其归
集到一个数据块中,这个数据块将和前面一个数据块集成在一起。矿工
节点会附加一个随机调整数,并计算前一个数据块的SHA-256 Hash运算
值。挖矿节点不断进行重复尝试,直到它找到的随机调整数使得产生的
Hash值低于某个特定的目标为止。由于Hash运算是不可逆的,因此寻找
到符合要求的随机调整数将会非常困难,因此需要一个可以预计总次数
的不断试错的过程。这时,工作量证明机制就发挥作用了。当一个节点
找到了符合要求的解,那么它就可以向全网广播自己的结果。其他节点
就可以接收这个新解出来的数据块,并检验其是否符合规则。只要其他
节点通过计算Hash值发现其确实满足要求(比特币要求的运算目标),那么该数据块就是有效的,其他的节点就会接受该数据块,并将其附加
在自己已有的链条之后。
当挖矿时,你会经常对区块头进行散列,你正在挖的区块也会时常
进行更新,一个区块头如上文所述的表1-3所示。
表1-3中的大部分数据项对所有用户都是一致的,不过,在时间戳
上可能会有些区别。如果当前区块的时间戳大于前11个区块的平均时间
戳,并且小于“网络调整时间(Network-Adjusted Time)”+2小时,则认
为该时间戳是有效的。其中的“网络调整时间”是指与你相连接的所有节
点的平均时间。当节点A连接到节点B时,A将从B处得到一个UTC的时
间戳,A先将其转换成本地UTC并保存起来,网络调整时间等于所有节
点的本地UTC时间+所有相连节点的偏移量平均值,然而,该网络时间
永远不会调整到超过本地系统时间70分钟以上。
Nonce随机数通常都不会相同,但是它以严格的线性方式在增长,从0开始,每次执行散列时都会增长,当Nonce溢出时(此事经常发
生),挖矿交易的extraNonce项就会增长,其将改变Merkle树的根节
点。
假定针对这些数据项,人们经常会独自产生同样序列号的Hash值,那么,最快的矿机通常会赢。然而,两人产生同样的Merkle根节点基本
上(或几乎)是不可能的,因为区块中的第一个交易是挖矿交易并且会“发送”到你独一无二的比特币地址上。而你的区块与其他人的区块是
有区别的,因此,产生的Hash值肯定也会(几乎可以肯定)不同,你计
算的每个Hash值和网络中的其他人一样,都有同样的获胜机会。
比特币使用SHA256(SHA256(区块头))计算Hash值,但要注意
字节序。例如,以下的Python代码用于计算某一区块的Hash值,使用的
是2011年6月区块号为125552的最小Hash值。该区块头建立在表1-3所示
的6个数据项之上,并且以十六进制的小端结尾方式连接在一起。
>>> import hashlib
>>> header_hex = (01000000 +
81cd02ab7e569e8bcd9317e2fe99f2de44d49ab2b8851ba4a308000000000000 +
e320b6c2fffc8d750423db8b1eb942ae710e951ed797f7affc8892b0f1fc122b +
c7f5d74d +
f2b9441a +
42a14695)
>>> header_bin = header_hex.decode('hex')
>>> hash = hashlib.sha256(hashlib.sha256(header_bin).digest).digest
>>> hash.encode('hex_codec')
'1dbd981fe6985776b644b173a4d0385ddc1aa2a829688d1e0000000000000000'
>>> hash[::-1].encode('hex_codec')
'00000000000000001e8d6829a8a21adc5d38d0a473b144b6765798e61f98bd1d'
注意 实际的Hash值是一串256位的数值,首部有许多零。当
以大头端十六进制常数方式打印或存储时,它的首部有许多零;如果它
以小头端打印或存储时,零就会变换到尾部。例如,如果表示成字节
串-最低(或者开头)的字节串地址显示最小位的数,那么这就是小头
端表示。blockexplorer的输出把Hash值显示为大头端表示的数值,因为
数字的表示通常是首部数字是最大的数字(从左向右读)。1.3.2 挖矿难度
挖矿难度是对挖矿困难程度的度量,即指计算符合给定目标的一个
Hash值的困难程度。比特币网络有一个全局的区块难度,有效的区域必
须有一个Hash值,该Hash值必须小于给定的目标Hash值。矿池也会有一
个自定义的共享难度,用来设定产生股份的最低难度限制。
难度每过2016块就会改变一次,计算公式为:
difficulty=difficulty_1_targetcurrent_target
其中,目标(target)是一个256位长的数值。
测量难度有许多不同的方法,通过这些方法得到的
difficulty_1_target有可能也会不同。传统情况下,它表示一个Hash值,前32位为0,后续部分为1(称之为矿池难度或pdiff),比特币协议把目
标Hash值表示成一个固定精度的自定义浮点类型,因而,比特币客户端
用该值来估计难度(称之为bdiff)。
难度经常被存储在区块中,每个块存储一个十六制的目标Hash值的
压缩表达式(称之为Bits),目标Hash值可以通过预先定义的公式计算
出来。例如:如果区块中压缩的目标Hash值为0x1b0404cb,那么十六进
制的目标Hash值就为如下形式:0x0404cb×28×(0x1b-3)
=0x00000000000404CB000000000000000000000000000000000000000000000000
因而目标Hash值为0x1b0404cb时,难度为:
0x00000000FFFF00000000000000000000000000000000000000000000000000000x00000000000404CB000000000000000000000000000000000000000000000000
=16307.420938523983(bdiff)
或者:
0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0x00000000000404CB000000000000000000000000000000000000000000000000
=16307.669773817162(pdiff)
其中:
0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
是挖矿机使用的最大目标Hash值。而
0x00000000FFFF0000000000000000000000000000000000000000000000000000
则是比特币网络使用的浮点编码类型,后面的位数被缩短了。
下面是一个快速计算比特币难度的方法,这里使用的算法是修改的
泰勒序列(读者可以参考wikipedia上的教程),并且依赖记录来转换难
度计算。
nclude
inline float fast_log(float val)
{
int const exp_ptr = reinterpret_cast
int x = exp_ptr;
const int log_2 = ((x >> 23) 255) - 128;
x = ~(255 << 23);
x += 127 << 23;
exp_ptr = x;
val = ((-1.0f3) val + 2) val - 2.0f3;
return ((val + log_2) 0.69314718f);
}
float difficulty(unsigned int bits)
{
static double max_body = fast_log(0x00ffff), scaland = fast_log(256);
return exp(max_body - fast_log(bits 0x00ffffff) + scaland (0x1d - ((bits 0xff000000) >> 24)));
}
int main
{
std::cout << difficulty(0x1b0404cb) << std::endl;
return 0;
}
如果想要了解难度计算的数学原理,那么可以看看如下的Python代
码:
import decimal, math
l = math.log
e = math.e
print 0x00ffff 2(8(0x1d - 3)) float(0x0404cb 2(8(0x1b - 3)))
print l(0x00ffff 2(8(0x1d - 3)) float(0x0404cb 2(8(0x1b - 3))))
print l(0x00ffff 2(8(0x1d - 3))) - l(0x0404cb 2(8(0x1b - 3)))
print l(0x00ffff) + l(2(8(0x1d - 3))) - l(0x0404cb) - l(2(8(0x1b - 3)))
print l(0x00ffff) + (8(0x1d - 3))l(2) - l(0x0404cb) - (8(0x1b - 3))l(2)
print l(0x00ffff float(0x0404cb)) + (8(0x1d - 3))l(2) - (8(0x1b - 3))l(2)
print l(0x00ffff float(0x0404cb)) + (0x1d - 0x1b)l(28)
前难度可以通过http:blockexplorer.comqgetdifficulty 来获得,下一
个难度可以通过http:blockexplorer.comqestimate 来获得。难度的变化
情况可以查看http:bitcoin.sipa.be 。最大难度大约等于maximum_target1(因为0会导致无穷大),这是
一个非常大的数值,大约为2224 ;当maximum_target为最小值1时,则
最小难度值也为1。
难度可根据以前2016个区块的产生时间而定,每过2016块就会改变
一次。预计每隔10分钟产生一个区块,因而产生2016个区块要花费2周
时间。如果前2016个区块的产生时间多于两周,则难度会降低;否则难
度就会增加。
为了找到新区块,该区块的Hash值必须小于目标Hash值,实际上它
是一个在0到2256 -1之间的随机数,难度1的偏移量是:
0xffff×2208
难度D的偏移量是:
(0xffff×2208 )D
在难度D下,为了找到新区块,预期要计算的Hash数量是:
D×2256 (0xffff×2208 )
或者只是:
D×248 0xffff难度的设定,是为了以每10分钟一个区块的速度产生2016个区块,因而,在600秒内计算(D×248 0xffff)个Hash,这就意味着产生2016个
区块的网络Hash速率(算力)是:
D×248 0xffff600
可以进一步简化为:
D×232 600
以上公式有较好的精度。
在难度为1时,算力是7Mhashes秒,难度是5006860589,这就意味
着以前2016个区块被找到,其平均算力是:35.840PHashs。
5006860589×232 600≈35.840PHashs
发现一个区块的平均时间,可以用以下公式估计:
时间=难度×232 算力
其中,难度是当前的难度,算力是指矿机的计算能力,以hashess
为单位,时间是你找到两个区块的平均时间。举例来说,使用Python计
算,算力为1Ghashess的矿机,难度在20000时,产生一个新区块的时
间,计算式如下: python -c print 20000 232 109 60 60.0
23.85
其中表示指数,该语句运算的结果就是:找到一个新区块要花费
近1天的时间。1.3.3 矿池原理与商业模式
随着生成区块的难度逐步增加,挖矿变成了一个碰运气的事情,单
一节点要生成一个区块需要花费数年的时间(除非这个单一节点拥有大
量的计算力)。为了激励计算力较低的用户继续参与挖矿,矿池就出现
了。在一个矿池里,许多不同的人贡献出自己的计算力来生成一个区
块,然后再根据每个人的贡献比例来分发奖励。通过这种方式,要得到
那个50个比特币的奖励就不必等待数年的时间了,小矿工能定期得到属
于他们那部分的比特币奖励。一个share(贡献股份)为一个矿池给客
户端的一个合法的工作证明,同时这也是用来生成区块的工作证明,但
是没有这么复杂,只需要很少的时间就能达到一个share。
矿池是比特币(Bitcoin)等P2P密码学虚拟货币开采所必需的基础
设施,一般是对外开放的团队开采服务器。其存在的意义是提升比特币
开采的稳定性,使矿工薪酬趋于稳定,目前国内较为著名的比特币商业
矿池有F2Pool、BTCC Pool、BW Pool、BTC.com等。
关于矿池挖矿的方式,目前存在如下几种不同的方式。
·Slush方式:Slush矿池基于积分制,较老的shares将比新的shares拥
有更低的权重,以减少一轮中切换矿池的投机分子。
·Pay-Per-Share方式:该方式为立即为每一个share支付报酬。该支出来源于矿池现有的比特币资金,因此可以立即取现,而不用等待区块
生成完毕或确认之后。这样可以避免矿池运营者幕后操纵。这种方法减
少了矿工的风险,但将风险转移给了矿池的运营者。运营者可以收取手
续费来弥补这些风险可能造成的损失。
·Luke-Jr方式:该方式借用了其他方式的长处,如Slush方式一样,矿工需要提供工作证明来获得shares,如Puddinpop方式一样,当区块生
成时马上进行支付。但是不像之前的方式,一个区块的shares,会被再
次利用来生成下一个区块。为了区分参与矿工的交易传输费用,只有当
矿工的余额超过1BTC时才进行支付。如果没有达到1BTC,那么将在下
一个区块生成时进行累计。如果矿工在一周内没有提供一个share,那么
矿池会将剩下的余额进行支付,不管余额是多少。
·Triplemining方式:该方式是将一些中等大小矿池的计算力合并起
来,然后将获得奖励的1%按照各个矿池计算力的比例分发给矿池运营
者。
·P2Pool方式:P2Pool的挖矿节点工作在类似于比特币区块链的一种
shares链上。由于没有中心,所以也不会受到DoS攻击。和其他现有的
矿池技术都不一样,在该方式下,每个节点工作的区块,都包括支付给
前期shares的所有者及该节点自己的比特币。99%的奖励(50BTC+交易
费用)会平均分配给矿工,另外0.5%会奖励给生成区块的人。·Puddinpop方式:一种使用“元哈希”技术的方式,使用特定的
Puddinpop挖矿软件,现在已经没有矿池使用这种方式了。
目前使用较多的方式为Pay-Per-Share(PPS),矿工使用起来也比
较方便。
但从去中心化的角度来说,还是推荐P2Pool,在避免DoS攻击的同
时,也能防止个别矿池拥有超大的计算力而对比特币网络造成威胁。不
过P2Pool的使用方式较PPS更为复杂。1.4 脚本系统
比特币在交易中使用脚本系统,与FORTH(一种编译语言)一
样,脚本是简单的、基于堆栈的,并且是从左向右处理的,它特意设计
成非图灵完整的形式,没有LOOP语句。
一个脚本本质上是众多指令的列表,这些指令记录在每个交易中,若交易的接收者想花掉发送给他的比特币,那么这些指令就是描述接收
者是如何获得这些比特币的。一个典型的发送比特币到目标地址D的脚
本,要求接收者提供以下两个条件,才能花掉发给他的比特币:
1)一个公钥,当进行散列生成比特币地址时,生成的地址是嵌入
在脚本中的目标地址D。
2)一个签名,用于证明接收者保存了与上述公钥相对应的私钥。
脚本可以灵活地改变花掉比特币的条件,举个例子,脚本系统可能
会同时要求两个私钥或几个私钥,或者无需任何私钥等。
如果联合脚本中未导致失败并且堆栈顶元素为真(非零),则表明
交易有效。原先发送币的一方,控制脚本运行,以便比特币在下一个交
易中使用。想花掉币的另一方必须把以前记录的运行为真的脚本,放到
输入区。堆栈保存着字节向量,当用作数字时,字节向量被解释成小尾序的
变长整数,最重要的位用于决定整数的正负号。比如,0x81代表-1,0x80则是0的另外一种表示方式(称之为负0)。正0用一个NULL长度向
量表示。字节向量可以解析为布尔值,这里False表示为0,True表示为
非0。1.4.1 脚本特点
表1-4至表1-12是脚本的所有关键字列表(命令函数),一些更复
杂的操作码已被禁用,不再考虑,因为钱包客户在这些操作码的程序实
现上可能有Bug,如果某个交易使用了这些操作码,那么其将会使比特
币块链产生分叉。我们提到脚本的时候,通常省略了这些把数字压入堆
栈的关键字。
表1-4 脚本常见关键字字段
表1-5所示的是脚本的流程控制。
表1-5 脚本的流程控制表1-6 脚本的堆栈处理表1-7展示的是字符串操作码,若有在交易中出现了已禁用的操作
码,则必须终止和失败返回。
表1-7 字符串操作码表1-8展示的是位操作码,若有在交易中出现了已禁用的操作码,则必须终止和失败返回。
表1-8 位操作码
注意 算术逻辑的输入仅限于有符号32位长整数,但输出有可
能会溢出。如果任何命令的输入值其长度超过4字节,那么脚本必须中
止和失败返回。如果在交易中出现了标记为已禁用的操作码,也必须终
止和失败返回。
表1-9 算术逻辑操作码(若在交易中出现已禁用的操作码,则必须终
止和失败返回)表1-10 脚本的加密码表1-11 脚本中的伪关键字(这些关键字仅供内部使用,辅助进行交易
匹配)
表1-12 保留关键字1.4.2 脚本运行过程
在这里,我们先讨论单输入单输出的比特币交易,因为这样描述起
来更为方便,而且不会影响对脚本的理解,以下面的一个交易Hash值为
例:
9c50cee8d50e273100987bb12ec46208cb04a1d5b68c9bea84fd4a04854b5eb1
这是一个单输入单输出交易,下面来看下我们要关注的数据。
Hash:
9c50cee8d50e273100987bb12ec46208cb04a1d5b68c9bea84fd4a04854b5eb1
对于输入交易,需要关注如下值。
前导输入的Hash:
437b95ae15f87c7a8ab4f51db5d3c877b972ef92f26fbc6d3c4663d1bc750149
输入脚本scriptSig:
3045022100efe12e2584bbd346bccfe67fd50a54191e4f45f945e3853658284358d9c062ad02200121e00b6297c0874650d00b786971f5b4601e32b3f81afa9f9f8108e93c752201038b29d4fbbd12619d45c84c83cb4330337ab1b1a3737250f29cec679d7551148a
对于输出交易,需要关注如下值。转账金额:0.05010000 btc
输出脚本scriptPubKey:
OP_DUP OP_HASH160 be10f0a78f5ac63e8746f7f2e62a5663eed05788 OP_EQUALVERIFY OP_CHECKSIG
假设Alice是转账发送者,Bob是接受者。那么输入交易表明了Alice
要动用的比特币的来源,交易输出表明了Alice要转账的数额和转账对象
——Bob。那么,有读者可能会问,数据中的输入脚本和输出脚本是不
是就是题和解?答对了一半!
在Bitcoin Wiki中提到:原先发送币的一方,控制脚本运行,以便比
特币在下一个交易中使用。想花掉币的另一方必须把以前记录的运行为
真的脚本,放到输入区。
换句话说,在一个交易中,输出脚本是数学题,输入脚本是题解,但不是这道数学题的题解。我开始看Wiki的时候,在这里遇到了一些障
碍,没法理解输入脚本和输出脚本的联系。但是在考虑到交易间的关系
之后,就明白了。
假设有这么一系列交易,如图1-7所示。图1-7 三对交易示范图
那么,这一系列交易具有如下特征。
·三个交易都是单输入单输出交易。
·每个输入交易输出交易中,都包含对应的脚本。
·交易a为Alice转账给Bob;交易b为Bob转账给Carol;交易c为Carol
转账给Dave。
·当前交易的输入都引用前一个交易的输出,如交易b的输入就是引
用交易a的输出。
按照之前的说法,交易a中的输出脚本就是Alice为Bob出的数学
题。那么,Bob想要引用交易a输出交易的比特币,就要解开这道数学
题。题解是在交易b的输入脚本里给出的!Bob解开了这道题,获得了奖
金,然后在交易b中为Carol出一道数学题,等待Carol来解……所以说,在图1-8中相同颜色的输出和输入才是一对题和解。
图1-8 输入输出一一对应图1.4.3 脚本操作码解读
要理解比特币脚本,先要了解堆栈,这是一个后进先出(Last In
First Out)的容器,脚本系统对数据的操作都是通过它完成的。比特币
脚本系统中有两个堆栈:主堆栈和副堆栈,一般来说主要使用主堆栈。
下面就来列举几个简单的例子,看下指令是如何对堆栈进行操作的。
常数入栈:指把一段常数压入到堆栈中,这个常数成为栈顶元素,如图1-9所示。
OP_DUP:复制栈顶元素,如图1-10所示。
图1-9 常数入栈图1-10 复制栈顶元素
OP_EQUALVERIFY:用于检查栈顶两个元素是否相等,如图1-11
所示。1.4.4 脚本执行过程
Alice在转账给Bob的时候,输出交易中给出了Bob的钱包地址(等
价于公钥Hash),当Bob想要转账给Carol的时候,他要证明自己拥有与
这个钱包地址对应的私钥,所以在输入交易中给出了自己的公钥及使用
私钥对交易的签名。下面来看个实例。
交易a:
9c50cee8d50e273100987bb12ec46208cb04a1d5b68c9bea84fd4a04854b5eb1
交易b:
62fadb313b74854a818de4b4c0dc2e2049282b28ec88091a9497321203fb016e
交易b中有一个输入交易引用了交易a的输出交易,它们的脚本是一
对题与解。
题:交易a的输出脚本,若干个脚本指令和转账接收方的公钥
Hash。
OP_DUPOP_HASH160be10f0a78f5ac63e8746f7f2e62a5663eed05788OP_EQUALVERIFY OP_CHECKSIG
解:交易b的输入脚本,这么一长串只是两个元素,签名和公钥(sigpubkey)。
3046022100ba1427639c9f67f2ca1088d0140318a98cb1e84f604dc90ae00ed7a5f9c61cab02210094233d018f2f014a5864c9e0795f13735780cafd51b950f503534a6af246aca301 03a63ab88e75116b313c6de384496328df2656156b8ac48c75505cd20a4890f5ab
下面来看下这两段脚本是如何执行完成解题过程的。
首先执行的是输入脚本。因为脚本是从左向右执行的,那么先入栈
的是签名,随后是公钥。接着,执行的是输出脚本。从左向右执行,第
一个指令是OP_DUP——复制栈顶元素(如图1-12所示)。
OP_HASH160用于计算栈顶元素Hash,得到pubkeyhash,如图1-13
所示。
然后将输出脚本中的公钥Hash入栈,为了与前面计算中所得到的
Hash区别开来,这里称它为pubkeyhash',如图1-14所示。
图1-11 检查栈顶元素是否相等图1-12 复制栈顶元素
图1-13 栈顶元素Hash160图1-14 公钥Hash入栈
OP_EQUALVERIFY则会检查栈顶前两个元素是否相等,如果相等
则继续执行,否则中断执行,返回失败,如图1-15所示。
OP_CHECKSIG使用栈顶前两个元素执行签名校验操作,如果相
等,则返回成功,否则返回失败,如图1-16所示。
图1-15 检查Hash值是否相等图1-16 返回结果
这样一串指令执行下来,就可以验证这道数学题是否做对了,也就
是说,验明了想要花费钱包地址中比特币的人是否拥有对应的私钥。上
面的执行过程是可以在脚本模拟器中进行的,并且能够看到每一步执行
的状态。1.5 合约应用案例
1.4节的脚本系统,详细说明了脚本的运行原理,本节将描述在实
际应用场景中如何使用脚本系统构建合约应用。1.5.1 合约应用原理
每个比特币交易都有一个或多个输入和输出,每个输入或输出都有
一个小的纯函数与之相关联,称为脚本,脚本可包含简化形式交易的签
名。
每个交易都有一个锁定时间,使得该交易处于特定状态并且可被新
交易替换,直至锁定时间来临。预定时间可以是块索引或时间戳(这两
个因素使用同一个内存项,小于5亿是块索引,大于5亿是时间戳)。当
一个交易的锁定时间到了,则称之为终结。
每个交易的输入都有一个序列号,对于正常发送币的交易,该序列
号为UNIT_MAX,锁定时间为0。如果锁定时间还未达到,但所有的序
列号为UNIT_MAX,则该交易也被认为是终结。序列号用来发布交易
的新版本,无须验证其他输入的签名。例如:在一个交易中,每个输入
都来自于不同的一方,每个输入的序列号都是0,这些序列号可以独立
增加。
签名验证是很灵活的,因为交易的签名方式可以通过SIGHASH符
号来控制,该符号附加在签名后面。通过这种方式能够构建特殊的合
约,交易的每个输入方只对交易的一部分进行签名,因而每个输入方都
能够单方面改变该交易的一部分内容,而无需其他输入方的参与。SIGHASH符号分为两部分,一种模式和一个ANYONECANPAY指示
器。签名模式包含如下几种模式。
·SIGHASH_ALL:这是默认模式。它指示一个交易除输入脚本之
外,所有部分都被签名。对输入脚本进行签名显然是不可能的,那样将
无法构建一个交易,所以脚本总是不被签名。尽管如此,需要注意的
是,输入的其他属性如输出、序列号等都会被签名。直观地说,它的意
思是“如果每个人都把他们的钱放进去,并且输出的正是我想要的,那
么我也同意把我的钱放进去。”
·SIGHASH_NONE:输出没有被签名,可以是任何内容。使用这种
模式意味着“如果每个人都把他们的钱放进去,我也同意把我的钱放进
去,但我不关心输出的是什么。”这种模式使得其他输入方可以通过改
变输入序列号来更新交易。
·SIGHASH_SINGLE:与SIGHASH_NONE一样,输入被签名,但
序列号没有被签名。因而其他人可以创建交易的新版本,然而,唯一的
输出也要被签名。该模式说明“如果输出的正是我想要的,那么我同意
把钱放进去,但我不关心其他人的输入。”
ANYONECANPAY指示器可以与以上三种模式联合使用,当设置
了ANYONECANPAY时,仅仅是该输入被签名,其他输入可以是任意
内容。脚本可以包括CHECKMULTISIG操作码,该操作码提供了n-of-m的
签名验证,即:你可以提供多个公钥m,定义必须出现的有效签名个数
n,签名个数n可以小于公钥数量m。如果我们设置以下脚本,则一个输
出需要两个签名:
2
有如下两种通用的方式可用来安全地创建合约。
·在P2P网络之外传递部分完成或无效的交易。
·使用两个交易:创建一个交易(合约交易),先签名但不会马上
广播,在达成合约并且被锁定在内存中之后,广播另一个交易(支付交
易),最后再广播合约。
采用以上的方式即可保证人们能够知道他们达成的合约内容。这些
特性可以让我们在区块链的基础上创建有趣的、创新的金融手段。1.5.2 示例1:提供押金证明
想象一下,你在一个网站(论坛或WIKI)上注册了一个账号,现
在你希望在网站运营者处建立你的信用,但是你没有以前的名誉来支撑
你的信用。一个解决方案就是向网站付点钱购买信用,但是如果你关闭
了账号,可能会想要回这部分钱。你对该网站的信任程度不足以让你将
钱存到该网站,因为你担心网站会花掉你的钱。另一个风险是,某一天
该网站有可能会消失。
建立信用度的目的是你做出某种奉献,让网站知道你不是一个垃圾
机器人。但是你不想让网站花掉你的钱。如果网站运营者消失了,你最
终想把钱要回来,而无需他们的任何许可。
对于该问题,可以通过合约来解决,具体步骤如下。
1)用户和网站相互发送各自新生成的公钥。
2)用户创建交易TX1(支付交易),该交易支出10个BTC到网站
地址,用户创建了TX1但不广播。
3)用户把TX1交易的Hash值发送给网站。
4)网站使用TX1的Hash值创建交易TX2(合约),TX2花掉TX1的
钱并且支付到用户地址。注意,TX2需要双方签名,因而该交易并不完整,nLocKt
ime被设置成未来时间(比如六个月之后),输入的序列号
为0。
5)最终,这个不完整的交易TX2(一半已签名)被回送给用户,用户检查合约是否如预期的一样在执行,即六个月后10BTC最终会回到
他的地址(除非情况有变)。序列号为0,表示如果双方同意,则合约
可以被修订。现在,该交易的输入脚本还不完整,因为用户未签名,所
以要等用户对合约进行签名并且把签名放到合适的位置上。
6)用户先广播TX1,再广播TX2。
在这个阶段,用户和网站都不能单独得到10BTC。六个月之后,合
约完成,即使网站消失了,用户也能得到币。
如果用户想要提早关闭账号,又该怎么处理呢?网站创建新版的
TX2,nLocKt
ime设为0,并且输入的序列号设为UINT_MAX,重新签
名,把该交易发回用户,用户签名后广播该交易,就能提早结束合约并
且释放10BTC。
如果六个月快到了,而用户还想保留他的账号,又该怎么办呢?类
似的事情发生后,合约会使用新的nLocKt
ime,序列号比以前的序列号
大1,双方重新签名,广播232次。当然,无论发生什么,双方都必须同
意,才能真正改变合约。显然,如果该用户被证明是存在恶意行为的(例如:垃圾邮件发送
者),那么网站不会同意提早结束合约。如果用户有太多的滥用行为,则网站可以要求增加存款数量,或者要求延长合约时间。1.5.3 示例2:担保和争端调解
一个买家想和他不认识或不信任的某人进行交易,一般情况下若交
易能够正常进行时,买家不想任何第三方参与。但是当交易出现问题
时,他想有一个第三方——也许是一个专业的争端调解服务来决定谁能
拿到钱。
注意 这个概念同时适用于买家和卖家。例如,调解员可向商
家要求邮资证明,以判断是否发货。
换句话说,某人想锁定某些币时,这些币要在第三方同意的情况
下,才能被花掉。
该示例的实现步骤具体如下。
1)和商家一起引入一个调解员(如:ClearCoin)。
2)得到商家的公钥K1,得到调解员的公钥K2,创建自己的公钥
K3。
3)把K2发给商家,商家生成一个随机数挑战调解员,调解员用K2
的私钥签名,用来证明K2确实属于调解员。
4)创建一个交易TX1,使用如下输出脚本并且广播该交易。2
现在这些币被锁定了,如果要解锁这些币,需要使用以下几种方
式。
·客户和商家同意(无论是成功的交易,还是在没有调解的情况下
商家同意回退给客户)。
·客户和调解者同意(失败的交易,调解者认同客户,客户得到退
款)。
·调解者和商家同意(商品已经发送,尽管有争议,商家还是得到
币)。
输入签名时,内容被设为相关联的输出。这样,为了从这个交易中
得到币,客户要创建包含两个签名位的脚本,自己签一个,再把未完成
的交易发给商家或调解员,请求第二个签名。1.5.4 示例3:保证合约
保证合约是建造公众商品时的集资办法,公众商品是指一旦建成,任何人都可以免费享受到好处的商品。标准的例子是灯塔,所有人都认
同应该建造一个,但是对于航海者个人来说灯塔太贵了,而且灯塔不只
是他一个人用得着,同时也会方便其他的航海者。
一个解决方案就是向所有人集资,只有当筹集的资金超过所需的建
造成本时,每个人才真正付钱;如果集资款不足,则谁都不用付钱。
在保证合约集资方面,包括频繁的、小额的、经常自动进行的集
资,例如互联网电台的资金和网页翻译等,比特币要优于传统的支付方
式。假设有一个浏览器的插件可供你发送一点币,它能检测当前页面的
语言并且广播一个集资请求,用于把该页面翻译成你的语言。如果使用
该插件的许多用户同时查看该页面(例如:该页面从高流量的网站链接
过来),那么足够的集资请求就能广播出去,到达一定的金额时,可自
动付钱给一个高质量的翻译公司,当翻译完成后该页面将自动在你的浏
览器中加载。
我们能以比特币的方式建立以下模型,具体步骤如下。
1)主办方创建新的捐赠地址,宣布如果筹集资金超过1000BTC,则将建造该商品,任何人都可以捐赠。2)捐赠者创建一个新交易,把一定数量的钱打到集资地址上,但
是他们并不广播该交易。该交易与常规的交易相似,但有三个不同点:
首先,不能做任何改变,如果你没有正确的输出金额1000BTC,那么你
必须先创建一个;第二,输入脚本要以
SIGHASH_ALL|SIGHASH_ANYONECANPAY的模式签名;最后,输出
值是1000BTC,注意,这不是一个有效的交易,因为输出值比输入值大
得多。
3)把交易上传到主办方的服务器上,他们把交易保存到磁盘上,随时更新捐赠的币数量。
4)一旦服务器获得了足够的币,它将把所有捐赠者上传的独立交
易合并成一个新的交易,该交易只有一个输出,仅仅是把钱付到捐赠地
址,该输出与每个捐赠者的交易的输出部分相同,而输入部分则是所有
捐赠者输入的集合。
5)广播完整的交易,发送捐赠的币到捐赠地址中。
这样的场景依靠了协议的几个方面,首先使用了SIGHASH符号,SIGHASH_ALL是默认模式,意味着要签名所有交易的内容,除了输入
脚本。SIGHASH_ANYONECANPAY是附加的指示器,意味着签名仅覆
盖自己的输入部分,而不会覆盖其他人的输入,这样一来,其他人的输
入可以留空。使用这些符号,我们能创建这样一个签名,即使在添加进其他输入之后,该签名依旧是有效的。但如果输出内容或其他的交易部
分被改变了,那么该签名就会无效了。第二,输入值小于输出值的交易
是无效的(原因很明显),这也就意味着捐赠者把发送币的交易发送给
主办方是安全的,因为主办方不可能得到这些捐赠币,除非再加上其他
的输入值等于或超过输出值。
不使用SIGHASH_ANYONECANPAY指示器也可以创建保证合约。
不需捐赠者创建交易的集资方式有两个步骤,一旦达到集资的总金额,主办方就会创建包含所有捐赠者输入的交易,然后依次在捐赠者中传
递,每个捐赠者都对该交易进行签名。但是,先使用
SIGHASH_ANYONECANPAY指示器,然后合并交易,这样可能会更方
便一些。
保证合约可以保证下一个块的资金网络安全,通过这种方式,即使
一个块中的交易数量比较少,挖矿也能挣钱(因为保证合约的交易一般
占用空间较大,因而需要付出更多的网络转账费)。
Tabarrok在他的论文“The private provision of public goods via
dominant assurance contracts”中详尽地描述了保证合约的概念,在一个
通用的保证合约中,如果合约失败了(在预定时间内集资不足),主办
方会给捐赠者支付网络转账费,这种类型的合约旨在鼓励捐赠者积极参
与。1.5.5 示例4:使用外部状态
脚本被设计成纯函数,它们不能访问外部服务器,也不能导入任何
会改变的外部状态,因为攻击者会利用该特性突破区块链。而且,脚本
语言的功能被严格限制了。幸运的是,我们可以以其他的方式创建交
易,从而与外部世界相联系。
考虑一个例子,老人想让他的孙子继承遗产,继承时间是在他死
后,或者在孙子年满18岁时,无论先满足哪个条件,他的孙子都可以得
到遗产。
为了解决这个问题,老人首先向他自己发送孙子要继承的资产数
量,以便有一个正确的继承数量的唯一输出;接着,他创建了一个带有
锁定时间的交易,该交易的意思是:在孙子18岁生日时,把币支付到孙
子的地址中,老人对该交易签名,不进行广播,直接把该交易给了孙
子。当过了孙子的18岁生日之后,孙子广播了这个交易并且得到他的
币。孙子可以在这个时间之前广播该交易,但他不会提前得到币,有些
节点会在内存池中把这种交易丢弃掉,因为锁定时间在遥远的将来。
死亡条件则很难判断,因为比特币节点不会检测主观条件,我们必
须依靠预言,预言是指具有密钥对的服务器,当用户自定义的表达式被
证明是真的,它就能按照要求对交易进行签名。以下是例子,老人创建了一个交易花掉了他的币,把输出设为:
这是一个预言脚本,具有与众不同的形式——它把数据推到堆栈
中,然后立即删除。公钥发布在预言服务器的网站上,为公众所知,Hash值设为用户自定义表达式的Hash值,该表达式以预言服务器能够理
解的方式进行编写,以确认老人已经死亡。举个例子,可能是以下字符
串的Hash值:
if(has_died('johnsmith',born_on=19500102))return(10.0,1JxgRXEHBi86zYzHN2U4KMyRCg4LvwNUrp);
以上语言是假设的,由预言服务器定义该语言,其可能是任何一种
语言。返回值是一个输出:币数量和孙子的地址。
再一次,老人创建了一个交易,没有广播而是直接给了孙子,他另
外还提供了一个表达式和预言服务器的名字,Hash值被写入交易,预言
服务器则能解锁表达式。算法的具体实现如下。
1)预言服务器接受评估请求,请求包括了用户提供的用户自定义
表达式、输出脚本和部分完成的交易,交易中除了scriptSig签名之外,其他部分都已经完成,签名仅包括了孙子的签名,还不足以解锁输出。
2)预言服务器检查表达式,得到其Hash值,并且与交易中的Hash值对照,如果两者不一致,则返回错误。
3)预言服务器评估表达式,如果表达式的结果不是交易输出的目
标地址,则返回错误。
4)预言服务器签名交易,返回签名给用户。
注意 对一个比特币交易进行签名时,输入脚本被设为相关联
的输出脚本。原因是当OP_CHECKSIG操作起作用时,包含该操作码的
脚本被放到输入中,脚本并不包含签名本身。预言服务器并不知道完整
的输出,也没有必要知道,因为它知道输出脚本、自己的公钥和表达式
的Hash值,这就足以使它检查输出脚本并且完成交易。
5)用户接受新签名,插入到交易的scriptSig项中,广播交易。
当且仅当预言服务器认为老人死了,孙子才能广播两个交易(合约
和申报),并且得到币。
预言服务器可以评估任何事情,然而区块链中的输出脚本的形式总
是一样的,可考虑以下的可能性。
·给定一个日期,假定mtgox比特币的美元价格在12.5~13.5之间:
today==20110925exchange_rate(mtgoxUSD)>=12.5exchange_rate(mtgox-USD)<=13.5·打赌我会做一些我从来不会做的事情(比如,获得奥林匹克金
牌):
google_results_count(site:www.google.comhostednews'MikeHearn'Olympicgoldmedal)>0
以上函数通过Google来搜索MikeHearn这个人获得奥林匹克金牌
(Olympicgoldmedal)的块数
·欧洲电视台的歌唱比赛,选择两个优胜者之一进行打赌:
if(eurovision_winner=='Azerbaijan')
return 1Lj9udBVDwptFffGSJSC2sohCfudQgSTPD;
else
return 1JxgRXEHBi86zYzHN2U4KMyRCg4LvwNUrp;
这些条件可使预言服务器的签名变得任意复杂,但是区块链仅需要
包含一个Hash值即可。
1.信任最小化:挑战
有许多方法可以降低对预言服务器的信任程度。
回到我们的第一个例子,预言服务器还没有看到孙子想解锁的交
易,因为该交易从没被广播过。这样,它不会支持孙子赎回币,因为它
不知道该交易是否存在。我们能做到,并且也应该做到,以自动方式定
期挑战预言服务器,确保它总是按照我们想象的方式进行输出。挑战无须花费任何币,因为要签名的交易是无效的(例如:与一个并不存在的
交易进行关联),预言服务器没法知道签名请求是随意的还是真实的,如何以一个尚未成真的条件来挑战预言服务器,是一个开放的研究课
题。
2.信任最小化:多个独立预言服务器
如果需要,CHECKMULTISIG中的签名个数n可以增加至能够达到
n-of-m的预言服务器模式(即m个预言服务器中需要有n个预言服务器签
名才能使交易有效)。当然,检查预言服务器是独立的而非串通的,这
一点也是很重要的。
3.信任最小化:可信的硬件
使用合适的硬件,即可进行信任计算。比如,以INTELTXT或AMD
等硬件来建立一个封闭的运行环境,然后用TPM芯片向第三方证实其可
信度。第三方可判定硬件是否处于所需状态。如果硬件失败,则需要有
人介入CPU程序的执行过程,甚至在极端的情况下,内存总线没有数据
流过(如果程序足够小,则完全可以使用缓存来运行程序)。
4.信任最小化:亚马逊AWS预言服务器
最终,也许是目前最现实的方法就是使用亚马逊的网页服务,截至
2013年11月,最合适的预言服务器的解决方案是“this recipe for creating atrusted computing environment using AWS”,该方案基于“this project for
doing selective SSL logging and decryption”。基本思想是:预言服务器使
用亚马逊作为其信任根,并且能用亚马逊API证明其是值得信任的,该
预言服务器记录在线银行接口的加密SSL会话,如果以后产生交易争
端,那么会话记录将被解密,争端就可以得到解决。1.5.6 示例5:跨链交易
比特币技术可以用来创建多个独立的货币,与比特币实现理念相同
的山寨币,可以在有限信任的条件下与比特币进行自由交易。域名币
(Namecoin)就是一个例子,它与比特币的运作规则有些不同,它可以
在域名空间中租用域名。
举个例子,想象一个财团发行了欧元币(EURCoins),即一种以
财团的银行存款1:1支持的加密货币。这样的货币与比特币存在不同的
交易集:更中心化,但没有外汇风险。人们可能希望在比特币与欧元币
之间来回交易,为了实现这个想法,可以使用TierNolan提出的协议。实
现步骤具体如下。
1)A产生一些随机数据X(秘密)。
2)A产生TX1交易(支付)包含了带跨链交易脚本的输出。它允许
币以A和B共同签名的方式释放,也可以以私密X和B签名的方式释放,该交易未广播,块链的释放脚本包含了私密的Hash值,并非真正的私密
X本身。
3)A产生TX2(合约),花掉TX1并且输出到A的地址,该交易有
个未来的锁定时间,输入的序列号为0,因而可以被替换。A签名TX2并
且发送给B,B给TX2签名后发送回A。4)A广播TX1和TX2,B可以看到币但是不能花掉它们,因为并没
有输出到B的地址,该交易还没有终结。
5)B在山寨币块链上执行相同的操作,B的锁定时间应该大于A的
锁定时间,双方的交易都待定但未完全。
6)因为A知道私密X,A能马上申报他的币,然而,A在申报币的
过程中,向B释放了私密X,所以B可以以私密X和签名B来完成山寨币
块链的交易。
自动化交易完全是以点对点的方式进行的,其能确保货币的流动
性,该协议使得这种交易更为灵活。跨链交易的脚本如下所示:
IF
2
ELSE
ENDIF
合约输入的脚本如下所示:
或者:
跨链交易的脚本执行第一段代码:
2
如果是0,则跨链交易的脚本执行第二段代码:
参考“Atomic cross-chain trading”(见参考资料[9])能够得到更详细
的说明。
注意 欧元币是一个很自然的想法,还有其他方法也能够实现
点对货币的交易(把比特币换成菲亚特汽车,反之亦然),看“Ripple
currency exchange”(见参考资料[10])可以得到更多的信息。
Sergio Demian-Lerner提出了P2PTradeX协议,一种块链交易的解决
方案,该方案需要把一个块链中的确认规则有效地编码进另一个块链的
确认规则中。1.5.7 示例6:支付证明合约
在示例4中,我们看到了如何基于任意程序的输出来实现条件支
付,这些程序非常有用,能够实现任何常规程序所能实现的功能,比如
获取网页。缺点是需要一个第三方(预言服务器),尽管我们可以用技
术来降低预言服务器的信任度,但谁都不能降低到0。
对于受限的程序、纯函数,新加密技术已经出现,这些技术能从将
信任度降低到0,无需第三方参加。这些程序不能进行任何IO操作,但
是在许多情况下,这种限制被证明并不重要,或者可以以其他的方式绕
过,比如给程序一个签过名并且打过时间戳的文档作为输入,无需程序
自己从网上下载。
若想进一步详细了解,可以阅读一下该协议的解释“Zero Knowledge
Contingent Payment”(见参考资料[11])。1.5.8 示例7:特定对象的快速调整(微)支付
与传统支付系统相比,比特币交易的费用非常便宜,但是还是需要
一些费用以便矿工来挖矿,以及融合到区块链上。有些情况下,你可能
想要快速和便宜地调整发送到某个特定地址的货币金额,而不会导致产
生广播交易的费用。
举个例子,有一个你尚不信任的互联网接入点,就像你从来没有去
过的咖啡屋中的一个Wi-Fi热点一样。每使用10K字节的流量你得向咖啡
屋支付0.001BTC,而无须注册咖啡屋账号。零信任解决方案意味着可以
全自动完成整个过程,因而你在月初预先转了一笔钱到你的手机钱包
中,然后你的手机会自动与AP协商并且按需给AP支付费用,咖啡屋也
希望任何人都能来付钱给它,而无须担心被诈骗。
为了达到这个目标,可以使用下面的协议。该协议依赖nLocKt
ime
与原设计不同的行为,从2013年开始,时间锁定的交易被认为是非标准
协议,不能进入内存池,这样就不能在锁定时间过期之前广播出去。当
nLocKt
ime的行为恢复回中本聪的初始设计时,就需要修改以下讨论的
协议了。
可定义客户端为发送币的那一方,服务端为接收币的另一方,以下
协议的实施过程是从客户的角度来进行的,具体步骤如下。1)创建公钥K1,向服务端请求公钥K2。
2)创建、签名,但不广播交易T1,支付10BTC到输出,需要服务
端和你自己的公钥,使用OP_CHECKMULTISIG是一个好办法。
3)创建退款交易T2,与T1的输出相关联,发送所有币回到你的地
址。该交易有一个锁定时间,例如几小时后,不签名并且把该交易发送
给服务端,常规来说,输出脚本是“2 K1 K22 CHECKMULTISIG”。
4)服务端用K2签名T2,返回给客户,注意,服务端目前还未看到
T1,仅仅看到了T1的Hash值(该Hash值在未签名的T2中)。
5)客户验证服务端的签名是否正确,如果不正确则中止。
6)客户签名T1并且把签名返回给服务端,服务端广播T1(如果他
们双方有联系的话,每一方都可以广播T1),币被锁定。
7)客户创建一个新交易T3,与T1相联系,类似于退款交易,有K1
和K2两个输出,把所有币分配给第一个输出K1,它做了与退款交易相
同的事情,但是没有锁定时间,客户签名T3,发送给服务端。
8)服务端验证输出到它的地址的币数量是正确的,验证客户提供
的签名是正确的。
9)当客户想付钱给服务端时就调整T3,向服务端的输出增加足够的币,同时减少他自己的币数量,然后重新签名T3,发送给服务端。客
户无须发送整个交易,只需要发送签名和增加的币数量即可。服务端调
整T3内容与新的币数量相吻合,验证客户的签名并且继续。
整个过程会持续到会话结束,或者到1天的时间快到时,此时,AP
会签名和广播最终版本的交易,向它自己分配最终的币数量。退款交易
需要处理服务端消息中断和未分配币的情况,如果发生了这些事件,一
旦锁定时间过期,客服就可以广播退款交易,拿回所有的钱。
这个协议已经用bitcoinj实现了。
当nLocKt
ime的交易能够进入内存池、交易替换重新启用时,本协
议必须被修改。在这种情况下,无需退款交易。T3有一个序列号,每次
都比前一次大1,T3的锁定时间与之前的时间相一致。每次的支付都使
得序列号增加1,以确保会优先发生最后版本。如果没有正常关闭通道
协议,则意味着向服务端支付币不会成功,直到锁定时间过期,客户拿
回所有币为止。为了避免这种情况,双方共同签名T3交易,序列号为
0xFFFFFFFF,导致立即确认,而不用考虑nLocKt
ime的值。
锁定时间和序列号可以避免一种攻击,在这种攻击中:AP提供连
通性,客户使用TX2的第一版本双花,使币回到他自己的地址中,阻止
咖啡屋申报账单。如果客户尝试这么做,该交易不会马上被包括进去,AP在一段时间内可以观察到该交易被广播,然后广播它看到的最后一个版本,就能推翻客户的双花企图。
后一种协议依赖交易替换,具有更大的灵活性,因为在通道的生命
周期中,只要客户能收到服务端的签名,协议就能使客户为自己分配的
币的数量越来越少。但是在许多用例中,这个功能是不必要的。交易替
换同样允许配置更复杂的超过两方的通道,如何在这种使用场景下详尽
地描述协议,就留给读者作为练习吧。1.5.9 示例8:多方去中心化彩票
使用示例6的一些技术和一些高级的脚本,使得构建无人值守的多
方彩票系统成为可能。准确协议在“Secure multiparty computations on
Bitcoin”(见参考资料[12])中已经有详细描述。参考资料
[1] http:www.8btc.combitcoin_block_chain
[2] http:www.360doc.comcontent1412281018005502_436322050.shtml
[3] http:www.8btc.combitcoin-change-addresses-explanation
[4] http:8btc.comarticle-1786-1.html
[5] http:www.8btc.combitcoin-transactions
[6] http:8btc.comarticle-1775-1.html
[7] http:8btc.comarticle-1767-1.html
[8] http:www.8btc.comunderstand-bitcoin-script
[9] https:en.bitcoin.itwikiAtomic_cross-chain_trading
[10] https:en.bitcoin.itwikiRipple_currency_exchange
[11] https:en.bitcoin.itwikiZero_Knowledge_Contingent_Payment
[12] http:eprint.iacr.org2013784第2章 区块链进阶
2.1 外带数据
区块链的外带数据是指那些保存在区块链上但不进行货币交易的信
息,比如需要永久保存的信息,前面提到过存在于区块链上的每一笔交
易都有一个输入和输出,区块链的外带数据也是采用类似的方式来存储
的。
如果有在比特币上永久存储数据的需求,那么你目前有两种选择,即:“OP_RETURN”和“Multi-Signatures”。OP_RETURN是指在每个交易
的公钥脚本中嵌入OP_RETURN操作码,之后放置外带数据;Multi-
Signatures则是指在建立多签地址时,使用空白签名区域来放置数据。
此类外带数据的方法旨在让编程者更简单地将数据编码到交易中,同时
又不会影响到比特币区块链的功能,目前非常流行,在Omni、Open
Assets、Blockstack和Factom等的区块链上都有应用。2.1.1 OP_RETURN外带数据
2013年,比特币协议中引进了一项新功能,即:创建一种名为
OP_RETURN的交易,可以嵌入40字节小段数据(目前已经是80字节
长)。最初,这个功能旨在把情境信息加入比特币交易里,比如配送信
息等。后来,发展出了更具创造性的用法,即创造最小量的交易
(0.00000001 BTC加上交易费),并且可嵌入任何你想放进去的信息。
比如交易号:
495926f46e3aae80088919f363b3b6ff52116e28637b63eb2a681b1fb990d2e4
所对应的交易输出为OP_RETURN类型,那么它的输出脚本则为:
OP_RETURN 4343020549a5710049a57190
利用这个功能的第一个有趣的应用就是存在性证明(Proof Of
Existence),它可以为任何文件创建一个Hash,并且可以放入区块链
中,这点不同于其他所有文件的身份认证ID。之后,通过比较区块链里
的Hash和你手头文件的Hash,就可以用那个交易的时间戳和存储在其中
的Hash,来证明那个时点上某个文件是确实存在的。只要二者匹配,就
有了证明。值得注意的是,只能在该交易中输出很小金额的比特币,如
0.00005,因为输出到OP_RETURN中的比特币是无法被再次使用的。2.1.2 Multi-Signatures外带数据
多签名地址是另外一种外带数据的方法。例如,对于1-of-2型的多
签名地址,我们在建立该地址时,提供的第一个公钥是发送者的,因而
输出金额可以赎回;而第二个公钥是空白的,因而该空间可以用来存储
外带数据。对数据的要求则是:前缀是数据的长度,后面是用0来充值
的无数据区域。
该交易的输出脚本为:
1
这里的<0>区域可用于存储外带数据,该输出金额一样可以被花
费。如果要存储更多数据,则可采用1-of-3或1-of-5型的多签地址。2.2 Counterparty
合约币Counterparty是以合约币协议运行的全套金融工具,合约币
协议建立在比特币块链的基础之上,把比特币块链当成可信的时间戳服
务和可信的信息发布证明。
目前合约币已经实现了众多的技术创新点,比如燃烧证明、合约、去中心化XCP与BTC交易所、赌约或期货、资产或股份发行、分红等。
Counterparty是建立在比特币协议上的传输层,用于建立和使用去中心
化的财务工具协议。简单来说,可以将XCP理解为很多“小的BTC”即
XCP=“小的BTC”,但是这些“小的BTC”(XCP)不仅仅具有货币的交易
功能,还具有资产发行(例如发行股票)、股息分配及下注的功能。
每个合约币信息都包括以下特性。
·有一个源地址。
·有一个目的地址。
·有一定数量的比特币,从源代码发送到目的地址(如果存在目的
地址的话)。
·以比特币计的费用,支付给挖到这个交易的矿工。·最多40字节的外带数据,这些数据通过上述的两个外带数据方法
嵌入到比特币交易中。
为了方便区分,每个合约币交易的数据区域都以UTF-8格式的
CNTRPRTY打头,这个字符串已经足够长,因而很难将合约币的交易
与在OP_RETURN区域带有伪随机数的比特币交易搞混。在测试情况下
(例如:在任何块链中使用TESTCOIN合约币网络),这个字符串
是“XX”。
识别字节串“CNTRPRTY”之后的四个字节说明了目的地址的存在
性、比特币交易费用的多少,以及交易的比特币数量(根据合约消息类
型的不同而不同)。其他的数据则根据消息类型具有不同的格式,具体
请参考源代码。
另外,每个合约币交易都必须有一个明确且唯一的源地址,在含有
合约币交易的比特币交易中,所有输入都必须一致。在比特币交易中资
金唯一的源地址,就是合约币交易的源地址。
合约币交易的源地址和目的地址,就是比特币地址,任何比特币地
址都可以收到任何合约币的资产(如果该地址有资产的话,也可以向外
发送资产)。
此外,需要说明的是,所有信息都会按照顺序进行解析,一次一
个,并且会忽略区块边界。2.2.1 Counterparty附生链的实现机制详解
附生链支持构建两种类型的交易:BTC发送和以BTC发送合约币的
资产分红,这两种交易不包含数据区,对于后者,能使用多个“目的”输
出。除BTC和XCP以外的所有资产均具有如下属性:Asset name、Asset
ID、Description、Divisiblity、Callability、Call date(if callable)即赎回
日期(如果是可赎回的)、Call price(if callable)即赎回价格(如果是
可赎回的)等。
资产名称是大写的ASCII字符串,当编码成十进制整数时,其值大
于263 ,小于或等于2568 。所有资产名称,除了“BTC”和“XCP”以外,必须至少有4字节长,而且不能以字符“A”开头。这样处理后,某些13字
节的资产名称是有效的,但是14字节的就不行。
资产可以是可分割的或不可分割的,可分割资产可以分成8个十进
制的位置。资产可以有描述,也可以随时改变。
资产可以是“可赎回的”,可赎回资产在赎回期之后,可以被现在的
发行者,以赎回价格(以XCP为单位)强制“赎回”,赎回价格可以设置
成该资产首次发行的价格。
可赎回资产可以在赎回日期之后赎回,该赎回日期是在块链中的一
个区块中第一次定义的时间。赎回价格指定为6个十制数的精度,是XCP与该资产的最小单位的
比率。
附生链的交易类型包括:发送(Send)、订单(Order)、BTC支
付(BTCPay)、发行(Issue)、广播(Broadcast)、赌约(Bet)、分
红(Dividend)、燃烧(Burn)、取消(Cancel)、回调(Callback)
等。下面就来一一介绍下。2.2.2 发送
发送(Send)是指从源地址发送任何合约币资产到目的地址,如果
在解析(以交易顺序)该消息时,发送者还没有足够的资产数量,则该
发送消息只能部分满足。Counterparty支持发送比特币,这里不使用任
何数据输出。2.2.3 订单
订单(Order)是指给定某种资产的特定数量,要得到另外资产的
特定数量。“买单”和“卖单”之间没有本质差别。在订单解析时,被给的
资产通常会马上被签订合约。也就是说,如果有人想用1个XCP换2个
BTC,一旦他发布了这个订单,那么他的XCP账号马上会减去1个
XCP。
当订单在块链中可见时,协议会将它与另一个以前见过的开放订单
撮合在一起。两个被撮合成功的订单称为“订单对”,如果订单对中的任
何一个订单包含比特币,那么这个订单对会被指定为“待处理”状态,直
到必要的BTCPay交易发布;如果订单对中的订单没有包含比特币,那
么这个贸易将立即完成,并且以协议自身指定的地址形成新的收支平
衡。
所有订单都是定价单,询价指定了一个人想要付出和得到的比率,订单会匹配定价以下的最高价格,订单对就是按照这个价格撮合的。也
就是说,如果有个开放订单以0.11XCP每份资产卖出,第二个卖单以
0.12XCP每份资产卖出,第三个卖单以0.145XCP每份资产卖出,然后
有一个新订单要以0.14XCP每份资产的价格买入,那么它将会先匹配第
二个买单,XCP和BTC将会以0.12XCPASST的价格成交。所有订单允许部分执行,也就是说,订单并非要么完全成交,要么
不成交。在前一个例子中,如果购买比特币的一方想买的数量多于第一
个卖单的数量,那么买单剩余未成交的数量会由后面的现存卖单来满
足。在所有可能的订单对撮合完之后,当前的买单被列为开放订单(如
果还有数量未被满足的话),如果存在多个价格相同的开放买单,则订
单将按照时间顺序撮合。
用户发布开放订单之后,开放订单会在一定数量的区块后过期,当
订单过期时,所有担保的资金都会返回到订单发布的那一方。
等待比特币支付的订单对将在10个区块后过期,其中的订单将会重
新发布。一般情况下,不会存在虚假交易,因为每一方提供的资产都存
储在担保处。然而,担保比特币是不可能的,因而那些想购买比特币的
人会要求只匹配有向比特币矿工支付交易费用的交易。另一方面,当创
建订单售出比特币时,用户可以支付他愿意支付的任意费用;如果是部
分订单,则仅支付部分费用。
此外,可用支付比特币的方式来关闭那些等待BTCPay消息的订单
对。在BTCPay消息的数据区块中,存储着两个Hash串连接而成的字节
串,这两个Hash串是由订单对中的两个订单Hash生成的。2.2.4 发行
资产可以以发行消息类型的方式进行发行(Issue):用户指定名称
和数量,协议计入相应的地址。资产名称必须是唯一的,或者以前被相
同地址发行过的。如果要重新发行一个资产,也就是说,对已经发行的
资产进行增发,那么发行的资产名称、可分割性和发布地址必须匹配。
对某个已经存在的资产进行增发,这个权利可以转移给别的地址。资产
可以被不可逆地锁定,防止进行增发,以保证资产拥有者免受通胀风
险。2.2.5 广播
广播(Broadcast)用于发布文本或数字信息,并且附带一个时间戳
作为系列广播的一部分,这系列广播被称为“反馈”。一个反馈和一个地
址相关联:从给定地址过来的任何广播,都是该地址反馈的一部分。一
个反馈的时间戳必须是单向增加的。赌注以数字形式在反馈中下注,这
个数值可以是货币的价格,或者可以是对未来事件可能的离散输出的一
部分描述。例如,有人可能以文本形式这么描述:“US QE on 2014-01-
01:dec=1,const=2,inc=3”,并且宣布结果是“US QE on 2014-01-
01:decrease!”和数值1,更为复杂的赌约可以以非块链的方式进行发布。
发布内容为文本字符串“LOCK”(大小写不敏感)的单个广播可以
锁定反馈,阻止它成为以后的广播源地址,同时也阻止它成为任意新赌
约的主题(如果反馈被锁定,但还有开放的或未解决的赌约与之相关,那么,那些赌约或赌约对会无损害地过期)。广播-1的数值会被赌约结
算所忽略。反馈以它的发布地址来识别。2.2.6 赌约
赌约(Bets)是指打赌一个特定反馈会等于(或者不等于)某个特
定时间的一个目标值,例如,打赌2020年1月1日12点整比特币的价格是
否为10000美元。参与赌博的人用他们的赌金进行担保,当到达指定时
间,该赌约就会按照反馈结果进行结算,赢者获得赌金。
等于不等于赌约不能用杠杆。然而,为了让两个赌注能被撮合,它们的杠杆水平、时间期限和目标值都必须相同,否则,它们会以订单
的形式撮合,除非赌约的赔率与订单价格是反相关的(赔率=保证金庄
家保证金),如果有可能,每个赌约都会以尽可能高的赔率撮合到开放
赌约。
目标值必须非负,赌约对(合约)不受-1的广播值所影响。赌约的
最后期限不能晚于它们指定反馈的最后一个广播的时间戳。赌约的过期
与订单相同,例如:过了特定的区块数量后就会过期。如果赌约对在
2016个区块后,发现一个区块的时间戳在赌约的最后期限之后过期,那
么,赌约费用将会是初始保证费用的一定比例,这部分并非赌约收入。
因为区块时间的存在,以及交易在块链中被订单化这种非确定性方
式的存在,所有合约必须非增量解决,但是涉及的资金必须马上放入担
保契约,而且必须有结算日期。否则,有人看到价格下跌了,就会把要被扣除的资金隐藏起来。2.3 挖矿算法解析
2.3.1 PoW挖矿算法及分析
PoW(Proof of Work),即工作证明。也就是说,你获得多少货
币,取决于你挖矿贡献的有效工作,比如,你的电脑性能越好,分给你
的矿就会越多,即根据你的工作证明来执行货币的分配。大部分的虚拟
货币,比如比特币、莱特币等,都是基于PoW模式的虚拟货币(算力越
高、挖矿时间越长,你获得的货币就会越多)。
第1章已经说过挖矿算法其实就是通过一个Hash函数找到一个满足
当前难度的Nonce(包含在区块头里面)的值,Hash函数输入数据的长
度是任意的,将产生一个固定且绝不雷同的值,可将其视为输出的数字
指纹。对于特定输入,Hash的结果每次都不一样,任何实现相同Hash函
数的人都可以计算和验证。加密Hash函数的主要特征就是不同的输入几
乎不可能出现相同的数字指纹。因此,相对于随机的选择输入,有意地
选择输入去找一个特定的Hash值,这几乎是不可能的,否则就破解了所
使用的Hash算法,如SHA-256等。
矿工用一些交易来构建候选区块,他会计算这个区块头Hash的值,看其是否小于当前目标值,如果这个值小于目标值,矿工就会修改这个
Nonce的值,然后再试一次。通常来说一个矿工会做成千上万次Hash运算,从而得到一个合适的Nonce的值,使得区块头Hash满足当前难度。
这也是PoW(工作量证明)算法的由来。
PoW要求出示一定的证明表明工作量,证明可以是直接记录也可以
通过概率表示,其中对于由小概率事件累计而成的工作,出示结果等同
于证明了工作量(因为不太可能直接得到小概率结果)。在比特币和其
他类比特币的系统中,PoW系统是以合乎要求的Hash作为工作结果的。
由于矿工需要一定量的计算才能取得合法的计算结果,因此得到合法的
计算结果就可以证明完成了一定量的计算。2.3.2 PoS股权证明算法及分析
PoS(Proof of Stake),即股权证明。它又是什么意思呢?简单来
说,它是根据你持有货币的量和时间,给你发利息的一个制度。在股权
证明模式下,有一个名词叫币龄,每个币每天产生1币龄,例如你持有
100个币,总共持有了30天,那么,此时你的币龄就为3000,这个时
候,如果你发现了一个PoS区块,你的币龄就会被清空为0。你每被清空
365币龄,你将会从区块中获得0.05个币的利息(可以理解为年利率
5%),那么在这个案例中,利息=3000×5%365=0.41个币。
以现有的比特币运行发展情况来看,比特币每年的挖矿产量都在不
断减半,我们可以预计,随着比特币产量的不断降低,矿工人数也会越
来越少,这样就会导致整个比特币网络的稳定性出现问题。PoS的解决
方案是鼓励大家都去打开钱包客户端程序,因为只有这样才可以发现
PoS区块,才会获得利息,这也增加了网络的健壮性。
其次还有一个担忧,就是当矿工人数降低时,比特币很可能会被一
些高算力的人或团队进行51%攻击,如果采用PoS体系,你即便拥有了
全网51%的算力,也未必能够进行51%攻击,因为这还要求攻击者持有
全球51%的货币量,而这是很难达到的。
现在,我们知道比特币是一个永远不会膨胀的体系了,因为它的货币总量看起来貌似是固定的,但实际上比特币是一个货币紧缩的体系,因为总存在钱包永久丢失的可能,PoS采用类似年利率的方式在一定程
度上是可以缓解这个问题的。
不过,到目前为止,PoS算法还没有被比特币采用的迹象。2.3.3 DPoS股份授权证明算法及分析
股份授权证明机制(DPoS)是一种新的保障加密货币网络安全的
算法,由比特股bitshares提出。它在尝试解决比特币采用的传统工作量
证明机制(PoW)及点点币和NXT所采用的股份证明机制(PoS)的问
题的同时,还能通过实施科技式的民主,来抵消中心化所带来的负面影
响。
以比特股为例来说,DPoS机制是让每一个持有BTS(比特股发行的
一种加密货币)的人对为整个系统资源当代表的人进行投票,而获得票
数最多的101个代表将进行交易打包计算。对此,可以理解为有101个矿
池,这101个矿池彼此的权利是完全对等的。那些握着BTS选票的人可
以随时通过投票更换这些代表(矿池),但如果他们提供的算力不稳
定,计算机宕机或试图利用手中的权力作恶,那将会立刻被愤怒的选民
们踢出整个系统,而后备代表可以随时顶上去。从某种角度来看,DPoS有点像美国的议会制度,只不过不是四年一次选举,而是时刻都
在选举中。2.4 Sidechains
Sidechains(侧链)实质上不是指特定的某个区块链,而是指那些
遵守侧链协议的所有区块链,这个词是针对比特币主链来说的。侧链协
议是指可以让比特币安全地从比特币主链转移到其他区块链,同时又可
以让其他区块链上的货币安全返回到比特币主链的一种协议。
所以从某种程度上来说,现在市面上的所有区块链,例如以太坊、莱特币、狗狗币等区块链都可以成为侧链应用。侧链的实现具有重大意
义,它意味着比特币可以在不同的区块链上流通,其应用范围和应用前
景会更加广泛。一旦侧链的应用流行起来,有创意有想法的人就会研发
出各种不同的侧链协议来和比特币进行对接,很显然这种方式会进一步
巩固比特币在区块链中的地位。2.4.1 侧链背景
侧链的提出主要是基于以下几个原因。
(1)应对其他区块链的应用威胁
现在市面上出现了几种非常流行的区块链,例如以太坊区块链、比
特股区块链等,这些不断产生的新的区块链势必会对比特币区块链产生
很大的威胁。以太坊区块链更是提出了智能合约这个有望颠覆整个区块
链的应用,而到目前为止,基于比特币的应用开发项目还不多,已有的
项目难度也很大。
(2)比特币核心开发组不欢迎附生链
比特币现有的应用中已经存在合约币和彩色币等附生链应用,但是
基于一些原因比特币核心开发组并不是很欢迎这些应用。他们的考虑是
这些应用会在一定程度上降低比特币区块链的安全性。
(3)Blockstream商业化的考虑
有了以太坊众筹的前车之鉴,比特币核心开发组也希望能以某种商
业化的方式来实现更高的回报,所以基于比特币的侧链应用也激发了一
群人开始尝试商业化这些应用。基于以上三个原因,提出侧链协议,把比特币从主链上安全地转移
到了其他货币区块链,这样既增加了区块链的多样性又可以应对二代币
的竞争,同时这些应用本身确实具有比较大的商业前景,一旦实现商业
化,这一块也将成为一块很大的蛋糕。2.4.2 技术原理
楔入式侧链技术(pegged sidechain),它将实现比特币和其他数字
资产在多个区块链间的转移,这就意味着用户们在使用他们已有资产的
情况下,就可以访问新的加密货币系统。目前,侧链技术主要由
Blockstream公司负责开发。
这里先列出“侧链”所需具备的属性,具体如下。
·在侧链间移动的资产应当能够被当前持有者移回,但除此之外的
任何人都不行(包括前持有者)。
·资产的移动应当是无交易对手风险的;也就是说,不诚实的一方
无法阻止转移的发生。
·资产转移应当是元操作(原子操作)的,即要么完全完成,要么
根本不发生。不存在会导致资产损失或允许欺诈产生的失败模式。
·侧链应当设有防火墙:一个会使某条链发生资产铸造(或偷盗)
的缺陷(Bug),不应导致其他任何链出现资产的铸造或偷盗。
·区块链重组时应当处理干净,即使是在资产转移的期间也要如
此;任何破坏应当只发生在它所处的侧链上。总的来说,理想情况下,侧链应当完全独立,其他链上所需的全部数据应由用户提供。侧链的验证者应当只有在侧链本身的显式共识规则有要求时,才去跟踪其他链。
·不应要求用户去跟踪他们未主动使用的侧链。
早期“转移”钱币的解决方案是用一个可公开识别的方式来销毁比特
币的,新的区块链能够检测到,以允许铸造新币[Bac13b]。这解决了
上面提到的部分问题,但由于这种方法只允许单向转移,因此还不足以
满足我们的目的。我们提出的方案是由资产转移的交易本身提供所有者
证明,从而实现资产转移,以避免让节点有跟踪发送方链的需求。从上
层实现的角度来说,当资产从一个区块链向另一个链移动时,我们在第
一个区块链上创建交易锁定资产,然后在第二个区块链上创建一笔交
易,该交易的输入中包含一个锁定已正确完成的密码学证明。这些输入
可用某种资产类型来标记,比如创生出资产的区块链的创世哈希
(genesis hash)。
第一个区块链称之为父链,第二个则简称为侧链。在某些模型中,两条链可对称地来处理,因此这一术语是相对而言的。如果打算将资产
从(初始)父链转移到一条侧链,期间可能会再转移到别的侧链,最终
还能转回至父链,并保全初始资产。一般情况下,我们把父链看成是比
特币系统,侧链则是其他区块链中的某一个 ......
您现在查看是摘要介绍页, 详见PDF附件(14607KB,524页)。





