区块链和分布式账本技术是全球十大战略技术趋势之一,也是金融界,科技界过去一年高度关注的热点。自从2015年,人们发现了区块链巨大的潜在价值后,区块链技术已经飞速发展了两年多,全球众多大型金融机构都投入了人力财力进行区块链研究,R3.chinaLedger,工信部区块链联盟快速发展起来。从行业巨头参与的积极性和政府的重视程度来看,我国并不想在区块链领域落后。
智能合约:对智能合约的探索是出于对比特币区块链低效的脚本系统的不满,该脚本使用的是非图灵完备的堆栈语言,只能实现有限的功能。
一些智能合约研究者一直追求在区块链上运行强大的机器语言,让每个用户都能见证其运行的过程和结果,实现“程序即规则(code is law)”的智能环境。以图灵完备的以太坊EVM,超级账本ChainCode到Chain平台的ChainCore,研究者的目标是在有效的存储空间中设计一个完备合约语言和高效的底层虚拟机,甚至将传统开发语言(C/c++/java)移植到区块链上。
区块链究竟是什么?狭义地说,区块链就是比特币的底层技术;不过经过7年的发展,区块链不再依附于比特币,而是独立地发展成为一种革命性的技术,比特币而是区块链最大,最成功的应用。
技术层面看,区块链是一个基于共识机制,去中心化的公开数据库。共识机制是指在分布式系统中保证数据的一致性的的算法;去中心化是指参与区块链的所有节点都是权力对等,所有人可以瓶等自由地参与区块链网络,公开数据库意味着所有人可以看到国王的区块和交易,保证无法造假和改写。总结得出区块链由许多对等的节点组成,通过共识算法保证区块数据和交易数据的一致性,从而形成一个统一的分布式账本。
价值层面看,区块链是一个价值互联网,用于传递价值,目前的互联网仅用来传递消息,但是还不能可靠地传递价值,而比特币区块链却可以在全球范围内自由地传递比特币,并且能够保证步备双花,不被冒用。区块是记录价值,传递消息和价值本身转移的一个可信账本。
区块链的四大主要特点:
Distributed(分布式的):分布式是全球化的,系统上的节点运行在任何地方都一样,除了网络连接速度有区别,其他没有任何区别,区块链没有中心节点,数据分布式地存储在各个节点上,即使绝大部分节点毁灭了,只要还有1个节点存在,就可以重新建立并还原区块链数据。
Autonomous(自治的):区块链是一种去中心化的,自治的交易体系,这种自治性表现在两个方面1)所有节点都是对等的,每个节点都可以自由加入和离开,并且这一行为对整个区块链系统的运行没有任何影响,所有的节点都是按照相同的规则来达成共识,且无需其他节点的参与 2)区块链系统本身一旦运行起来,就可自行产生区块并且同步数据,无需人工参与
Contractual(按照合约执行)区块链是按照合约执行,第一体现在各个节点的运行规则(指的是交易,区块链或协议)上,按照既定的规则执行,一旦出现违背规则的行为,就会被其他节点锁抛弃,第二体现在智能合约上,智能合约是一种可程序化的合同条款,规则或规定,包含在每个交易中,交易验证时必须先运行智能合约,只有通过了验证的交易才能被接受
Trackable(可追溯的):区块链的数据是公开透明的,不能被篡改,而且相关交易之间有一定的关联性,因而很容易被追溯,比如比特币区块链,每一枚比特币都有其特地的来源,通过输入可以追溯到上一个交易,或者通过输出追溯到下一个交易
比特币地址是一个由数字和字母组成的字符串,可以与任何想给你比特币的人分享,由公钥(一个同样由数字和字母组成的字符串)生成的比特币地址以数字“1”开头,下面是一个比特币地址的例子:
比特币地址是由公钥经过单向的Hash函数生成,用户通常所见到的比特币地址是经过“Base58Check”编码的,这种编码使用了58个字符,(一种Base58数字系统)的校验码,提高了可读性,避免了歧义,并有效地防止了在地址转录和输入中产生错误。Base58Check编码也被用于比特币的其他地方,例如私钥,加密的密钥和脚本Hash中,用来提高可读性和录入的正确性。
下面以一个具体的例子来说明一个区块链上的交易构成。假设有一个带有一个交易及一个输出的交易A,其中的输入列表和输出列表如下所示:
Input:
Previous tx:f5d8ee39a430901c91a5917b9f2dc19d6d1a0e9cea205b009ca73dd04470b9a6(以前交易的HASH值)
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的输入。
输入和输出:
输入是对其他输出的引用,一个交易中通常拥有多个输入,所有被引用的值相加,得出的总和值在该交易A的输出中用到。Previous tx是以前交易的HASH值,Index是被引用交易的特定输出号,ScriptSig是一个脚本的前一半(脚本在后文讨论)
脚本包含两个部分,一个签名和一个公钥,公钥属于交易输出的收款人并且表明交易创建者允许收款人获得的输出金额;另一部分是ECDSA签名是通过对交易的HASH值进行ECDSA签名得到的,签名和公钥一起证明源地址的真正所有者创建了该支付交易
输出中包含发送比特币的指令,金额(VALUE)是以聪(Satoshi,1BTC=100000000聪)为单位的数值,ScriptPubKey是脚本的另一半,可以有多个输出,共享了输入金额
区块和区块链:
数据项 | 描述 | 长度 |
Magic no(魔法数) | 总是0xD9B4BEF9 | 4字节 |
BloskSize(区块大小) | 到区块结束的字节长度 | 4字节 |
Blockheader(区块头) | 包含6个数据项 | 80字节 |
Transaction counter(交易数量) | 正整数VI=VarInt | 1~9字节 |
Transaction(交易) | 交易列表(非空) |
每个区块都包含一个被称为“魔法数”的常数0xD9B4BEF9,区块的大小区块头,区块所包含的交易数量及部分或所有的j近期新交易。在每个区块中对整个区块链起决定作用的是区块头
区块头的info:
数据项 | 目的 | 更新时间 | 大小(字节) |
Version(版本) | 区域版本号 | 更新软件后,制定了一个新的版本号 | 4字节 |
hashPrevBlock(前一区块的HASH) | 前一区块的256位HASH值 | 新的区块进来时 | 32 |
hashMerkleRoot Merkle(根节点HASH值) | 基于一个区块中所有交易的256位HASH值 | 接受一个交易时 | 32 |
Time(时间戳) | 从1970-01-00 00:00开始到现在,以秒为单位的时间戳 | 每几秒就更新 | 4 |
bits(当前目标HASH值) | 压缩格式的当前目标HASH值 | 当挖矿难度调整时 | 4 |
Nonce(随机数) | 从0开始的32位随机数 | 产生Hash时(每次产生hash随机数时都要增长) | 4 |
这里的hashprevblock就是区块连成区块链的关键字段,每个区块都必须要指向前一个区块,否则无法通过验证。这个区块链会一直追溯到源头,指向创世区块,显然,创世区块的prevblock的值位0或空,在区块头中,最关键的一个数据项是一个随机数Nonce,这串数字是一个答案这个答案对每个区块来说都是唯一的特地具体如下:
这个答案很难获得 | 有效答案有多个,不过只需要找到一个就行 | 其他节点对有效答案的验证很容易
因为答案很难找的,没有固定算法可以获得,只能用穷举法不断尝试,做法就是“挖矿”。
实例1:安全创建合约
比如在一个网站上注册了一个账号,希望网站建立我的信用,但是新用户没有以前的名誉来支撑我的信用,一个解决方案就是向网站付些钱购买信用,但是假如关闭了这个账号希望能退回钱,但是不足以相信网站,可能会花掉或者倒闭,对于该问题,可以用合约来解决,具体步骤如下:
1)用户和网站相互发送各自新生成的公钥
2)用户创建TX1(支付交易),该交易比如支出10个BTC到网站地址,用户创建TX1但是不广播
3)用户把tx1交易的hash值发送给网站
4)网站使用tx1的hash值创建交易tx2(合约),tx2取tx1的钱并且支付到用户地址。注意tx2需要双方签名,所以该交易并不完整,nlock_time设置成未来时间(比如6个月后),输入序列号位0
5)最终,这个不完整的交易(仅仅网站签名,用户未签名)被回送给用户,用户检查合约是否如预期一样执行,即6个月后10BTC最终会回到他的地址,序列号为0代表双方同意则合约可以被修订,现在该交易的输入脚本还不完整,因为用户还未签名,所以要等用户对合约进行签名
6)用户先广播tx1,再广播tx2
在此期间,用户和网站都不能单独得到10BTC,6个月后,合约完成,即使网站消失,用户也能得到自己的押金
如果用户想要提早关闭账号,网站创建新版的TX2,nlock_time为0,并且输入的序列号为UNIT_MAX重新签名,将该交易发回用户,用户签名后广播该交易,就能提早结束合约并且释放押金
如果时间到了,用户还想保留他的账号,合约会使用新的lock_time,序列号比以前的序列号大1双方重新签名,广播tx1和tx2,当然,无论发生什么,双方都必须同意,才能改变合约
如果用户被证明是恶意用户,那么网站就不会同意提前结束合约或者要求增加押金数量以及延长合约时间
实例2:担保和争端调解
一个卖家或买家和他不认识或者不信任的某人进行交易,一般情况下交易正常进行,买家不向任何第三方参与,但是出现问题的时候,想要一个第三方,专业的调解服务来决定谁拿到钱
换句话,某人想用一些币的时候,这些币要在第三方同意的情况下,才能被花掉
实现步骤如下:
1)和商家一起引入一个调解员(如ClearCoin)
2)得到商家的公钥K1,得到调解员的公钥K2,创建自己的公钥K3
3)把K2发给商家,商家生成一个随机数挑战调解员,调解员用K2的私钥签名,用来证明K2确实属于调解员
4)创建一个交易tx1,使用如下脚本并且广播
23CHECKMULTISIGVERIFY
现在这些币被锁定,将要解锁的话,需要如下几种情况:
客户和商家双方都同意,无须调解员
客户和调解员同意,调解员认同客户
商家和调解员同意,调解员认同商家
输入签名时,客户需要创建包含2个签名位的脚本,自己签一个,再把未完成的交易发给商家或调解员,请求第二个签名
密码学基础:
HASH函数是密码学的一个重要分支,它是一种将任意长度的输入变换为固定长度的输出且不可逆的单向密码体制,Hash函数在数字签名h和消息完整性检测等方面有着广泛的应用
技术原理:
hash函数又称为哈希函数,散列函数,杂凑函数,是一种单向密码体制,即从明文到密文的不可逆映射,只有加密过程,没有解密过程。
hash函数可以将满足要求的任意长度的输入进行转换,从而得到固定长度的输出,这个固定长度的输出称为原文的散列值或消息摘要
hash函数的数学表达式为:h=H(m)其中,H是hash函数,m是长度明文,h是固定长度hash值。
理想的hash函数对于不同的输入可以获得不同的Hash值,如果是两个不同的消息,存H(x)=H(x'),则称x和x'是hash函数的一个碰撞
由于hash函数单向的特征及长度固定的特征使得它可以生成消息或数据块的消息摘要(也称为散列值,哈希值),因此在数据完整性和数字签名领域有者广泛的应用
典型的hash函数有两类:消息摘要算法(MD5)和安全散列算法(SHA)
HASH函数有如下特点:
易压缩:对于任意大小的输入x,hash值H(x)的长度很小,在实际应用中,函数H产生的hash值长度固定
易计算:对于任意给定的消息,计算其hash值比较容易
单向性:求hash值的原文计算上b不可行,即求hash的逆很困难
抗碰撞性:理想的hash函数是无碰撞的,但在实际算法的设计中很难做到这点,有两种抗碰撞性:一种是弱抗碰撞性,即对于给定的消息,要发现另一个消息,满足H(x)=H(y)在计算上是不可行的,另一种是强抗碰撞性,对于任意一对不同的消息(x,y),使得H(x)=H(y)在计算上也是不可行的
高灵敏性:这是从比特位角度出发,指的是1比特位的输入会造成1/2的比特位发生变化
SHA-1算法:
1993年美国国家标准技术研究所NIST公布了安全散列算法SHA-0标准,1995年4月公布的修改版本称之为SHA-1。SHA-1在设计方面很大程度模仿MD5设计,但他对任意长度的消息均是生成160位的信息摘要,(MD5仅仅生成128位的摘要),因此抗穷举搜索能力更强,他有5个参与运算的32位寄存器字,消息分组和填充方式与MD5相同,主循环也同样是4轮,但每轮进行20次操作,包含非线性运算,移位和加法运算等,但非线性函数,加法常数和x循环左移操作的设计与MD5还是有一些区别。
SHA-1的输入是最大长度小于2的64次方的消息,输入信息以512位的分组为单位进行处理,输出是160位的消息摘要,SHA-1具有实现速度高,容易实现,应用范围广等优点,其算法描述如下:
1)对输入的信息进行填充:进行填充后,消息的长度模512应与448同余,填充的方式第一位是1,余下各位都为0,再将消息被填充前的长度以big-endian的方式附加在上一步留下的最后64位中。该步骤为必须,即使消息的长度已经是所希望的长度,填充的长度范围是1到512
2)初始化缓冲区:可以用160位来存放Hash函数的初始变量,中间摘要以及最终摘要,但首先必须进行初始化,对每个32位的初始变量赋值,j即:
H0=0x67452301
H1=0xefcdab89
H2=0x98badcfe
H3=0x10325476
H4=0xc3d2e1f0
3)进入消息处理主循环,处理消息块:一次处理512位的消息块,总共进行4轮处理,每轮进行20次操作,如图,这4轮操作处理具有类似的结构,但每轮所使用的辅助函数和常数都各不相同,每轮的输入均为当前处理的消息分组和缓冲区的当前值A,B,C,D,E,输出仍放在缓冲区以替代旧的A,B,C,D,E的值,第四轮的输出再与第一轮的输入CVq相加,以产生CV q+1,其中加法是缓冲区5个字中的每个字与CVq中相应的字模232相加
4)输出:所有的消息分组都被处理完之后,最后一个分组的输出即为得到的消息摘要值