《区块链技术与应用》北大肖臻老师——课程笔记【9-10】


提示:以下内容只是个人在学习过程中记录的笔记,图片均是肖老师课程的截图,可供参考。如有错误或不足之处,请大家指正。

一、BTC-比特币脚本

输入输出脚本

在这里插入图片描述
输入脚本包含两个操作,分别把两个很长的数压入栈里。

比特币使用的脚本语言非常简单,唯一能访问的内存空间就是一个堆栈,和其他编程语言不同的是没有变量等,所以比特币脚本也叫做基于栈的语言。

输出脚本有两行,分别对应上面的两个输出,每个输出有单独的一段脚本。
在这里插入图片描述
交易的宏观信息:
Txid:交易ID
Hash:交易哈希值
Version:比特币协议版本号
Size:交易大小
Locktime:设定交易的生效时间,0是立即生效,非0是过一段时间后生效
Vin:输入
Vout:输出
Blockhash:交易所在区块哈希值
Confirmations:交易有多少确认信息
Time:交易产生时间
Blocktime:区块产生时间

Time和blcoktime都是表示从很早的一个时间点到现在过了多少秒

在这里插入图片描述
输入结构是个数组,一个交易可以有多个输入。每个输入都要说明币是来自之前哪个交易的输出。

Txid和vout是给出币的来源。Txid是之前交易的哈希值,vout表示是这个交易里的第几个输出。
scriptSig:输入脚本。输入脚本最简单的形式就是给出scriptSig即可,证明有权利花这个币。
在这里插入图片描述
交易的输出是数组结构。
Value指输出的金额,也就是转账的金额(单位:BTC)
n:序号,表示当前交易第几个输出
scriptPubkey:输出脚本,输出脚本最简单的形式是给出pubKey。
Asm:输出脚本内容,里面包含一系列操作
Hex:哈希值
reqSigs:需要多少签名才能兑现
Type:输出类型,publichash是公钥哈希
Addresses:输出地址
在这里插入图片描述
输入输出脚本的执行过程(以上图为例):
在区块链中,A转给B交易,后面B转给C,B给C的交易中币的来源是A转给B的,所以B的输入脚本vout是指向A转给B的输出脚本的vout。

验证交易的合法性是要把B转给C的输入脚本和A转给B的输出脚本拼接在一起执行,输入脚本在前,输出脚本在后,早期是两个脚本从头到尾一起执行,后面出于安全性考虑改为两个脚本分别执行。首先执行输入脚本,没有出错再执行输出脚本,如果能顺利执行,最后栈顶的结果为非0值,为true则验证通过,这个交易就是合法的。如果执行过程中出现任何错误,交易就是非法的,如果一个交易有多个输入,那么每个输入脚本都要和对应的输出脚本匹配之后进行验证,全都验证通过这个交易才是合法的。

输入输出脚本的形式:

1、P2PK(pay to public key)——最简单的形式
输出脚本里直接给出收款人的公钥PUSHDATA(PubKey),CHECKSIG检查签名,在输入脚本里直接给出签名即可。这个签名是由私钥对这个输入脚本所在的整个交易进行的签名。
在这里插入图片描述

脚本执行:
在这里插入图片描述
第一行来自输入脚本,后两行来自输出脚本。实际代码出于安全考虑,这两个脚本实际上是分别执行。
第一条语句是把输入脚本里提供的签名压入栈,
第二条语句是把输出脚本里提供的公钥压入栈。
第三条是把栈顶的这两个元素弹出来,用公钥检查签名是否正确,如果正确返回true,说明验证通过,否则执行出错,交易就是非法的。
在这里插入图片描述
Input Scripts:把签名压入栈。
Output Scripts:这个交易是上面那个交易的币的来源,输出有两行,第一行是把公钥压入栈,第二行是CHECKSIG检查签名。

2、P2PKH (Pay to Public Key Hash)
在这里插入图片描述
与第一种形式的区别:第一种输出脚本里没有直接给出收款人的公钥,给出的是公钥哈希,公钥是在输入脚本里给出,输入脚本既要给出签名,也要给出公钥,输出脚本里还有DUP ,HASH160,EQUALVERIFY操作,这些操作都是为了验证交易的正确性。这种形式是最常用的。

DUP:
在这里插入图片描述
HASH160 :
在这里插入图片描述

在这里插入图片描述
脚本执行结果:从上往下执行
第一条:把签名压入栈
第二条:把公钥压入栈
第三条:把栈顶元素复制一遍
第四条:把栈顶元素弹出来取哈希,然后把得到的哈希值再压入栈,栈顶变成了公钥哈希值
第五条:把输出脚本的公钥哈希压入栈
第六条:弹出栈顶两个元素,比较是否相等,防止冒名收款人
第七条:弹出栈顶两个元素,用公钥检查签名是否正确

3、P2SH(pay to script hash)——最复杂
输出脚本给出的不是公钥哈希,而是收款人提供的脚本哈希(redeemScriptHash)——赎回脚本,将来花这个币的时候输入脚本里要给出这个脚本哈希的赎回脚本的具体内容,同时还要给出能让这个赎回脚本正确运行的签名。
在这里插入图片描述
在这里插入图片描述

input script 两步验证都通过交易才合法。

在这里插入图片描述
在这里插入图片描述第一阶段验证过程
PUSHDATA(sig):把sig压入栈
PUSHDATA(seriRS):把赎回脚本压入栈
HASH160:得到赎回脚本哈希
PUSHDATA(RSH):把输出脚本给出的哈希压入栈
EQUAL:比较哈希是否相等
在这里插入图片描述
第二阶段验证过程
首先把输入脚本里提供的赎回脚本序列化进行反序列化,然后执行赎回脚本,把pubkey压入栈,用checksig验证正确性。

为什么要用P2SH这么复杂的方法?为什么要把部分功能嵌入到赎回脚本里?
P2SH这个功能在最初比特币版本里是没有的,后来通过软分叉的形式加上的,一个常见的应用场景是对多重签名的支持。比特币系统中一个输出可能要求多个签名才能把钱取出来,这样为私钥的泄露提供了一定的安全的保护,同时也为私钥丢失提供冗余。

多重签名:

在这里插入图片描述
这个功能通过CHECKMULTISIG实现,输出脚本给出N个公钥,给出一个预值M,输入脚本提供N个公钥中任意M个合法签名通过验证。
输入脚本的X:比特币中CHECKMULTISIG的实现有个bug,执行时会从堆栈上多弹出一个元素,现在没有办法修改(原因:去中心化,修改代价很大,要改要通过硬分叉 ),实际采用的解决方案是在输入脚本中往栈上多压入一个没用的元素X 。

注意:给出的M个的相对顺序,要和N个公钥的顺序一致才行。

在这里插入图片描述
在这里插入图片描述
CHECKMULTISIG的实现过程:
上图例子假设三个签名中给出两个即可,签名顺序和公钥顺序一致。FALSE就是多余的元素,把多余元素和两个签名依次压入栈,输入脚本就执行完毕。输出脚本中把M值压入栈,然后把三个公钥压入栈,然后把N值压入栈,最后执行CHECKMULTISIG,看签名中是否包含了两个,如果是验证通过。

这个过程没用到P2SH,就是用比特币脚本中原生的CHECKMULTISIG实现的。
实际应用不方便之处:如网上购物。

在这里插入图片描述
本质:复杂度从输出脚本转移到输入脚本,输出脚本变得简单,原来的复杂度被转移到赎回脚本中,输出脚本只需给出赎回脚本的哈希值即可,赎回脚本要给出N个公钥和N、M的值,赎回脚本是在输入脚本中提供的,即收款人提供的。
在这里插入图片描述
第一阶段
输入脚本:先把没用的元素False、两个签名,序列化的赎回脚本依次压入栈
输出脚本:取哈希,把输出脚本里提供的哈希值压入栈,判断两个哈希是否相等。
在这里插入图片描述
第二阶段
把赎回脚本展开执行,把M、三个公钥、N依次压入栈,检查多重签名正确性,三个有两个签名正确即可。

使用P2SH做多重签名的实例(现在的多重签名多数是采用这种形式):
在这里插入图片描述
特殊的脚本格式
在这里插入图片描述
这种脚本格式的输出脚本开头是return格式,后面可以跟任意内容。

Return操作的作用:无条件返回错误
包含该操作的脚本永远不可能通过验证,执行到return语句会出错,执行会中止,后面跟的内容没有机会被执行。
这个脚本是证明销毁比特币的一种方法。

销毁比特币的原因:
两种应用场景,一是小的币种要求销毁一定数量的比特币才能得到币种,小币种叫AltCoin(Alternative coin)。
除了比特币以外的小的加密货币都可以叫做小币种。要求销毁一定数量的比特币可以得到一定数量的小币。证明付出一定代价才能得到小币种。
另一个应用场景是往区块链写入内容。往区块链添加需要永久保存的内容,要证明某些时间知道某些事情,如产权保护。
任何人都可以用这个方法在区块链内写入内容。发布交易不需要记账权,发布区块需要记账权。
在这里插入图片描述
为了简单其间,这些比特币脚本都省略了OP前缀,实际上要加上,如OP_CHECKSIG,OP_DUE

比特币系统中的脚本语言,没有专门的名字,就叫比特币脚本语言。不支持循环,这种设计的目的:不会有死循环,不会停机。比特币脚本在某些方面功能有限,在某些方面功能很强大。

在这里插入图片描述
这种形式交易的好处:矿工看到交易输出知道里面的输出永远不会兑现,所以就没有必要保存在UTXO中,对全节点比较友好。

二、BTC-分叉

分叉(fork)是指区块链上原来是一条链,分成了两条链。分叉可能由多种原因造成的,比如挖矿时两个节点同时挖到发布新的区块,就会产生临时性分叉,即state fork,由于对区块链有意见分歧而导致的分叉。

分叉攻击(forking attack):属于state fork,是故意造成对区块链有意见分歧而导致的分叉,是人为造成的,也叫做deliberate fork。

比特币协议发生改变也会导致分叉。
要修改比特币协议需要软件升级,在一个去中心化的系统里,升级软件的时候没有办法保证所有的节点都进行软件升级,有的节点因某些原因没有进行升级会导致分叉,这种分叉叫做protocol fork。

根据对协议内容修改不同,可以把protocol fork分为硬分叉(hard fork)和软分叉(soft fork)。

硬分叉:如果对比特币协议增加新的特性或扩展新功能等,没有进行升级软件的旧节点不认可这些新特性等,认为这些是非法的,属于对比特币协议内容产生意见分歧。
例:区块大小限制block size limit。协议规定区块大小是1M,有的认为size太小,提出要增加size limit。假设有人更新了这个限制协议,系统中拥有大多数算力的节点都更新了软件,节点升级了为新节点,没升级为旧节点,区块链就会在发布新区块时新旧节点没有达成共识,发生分叉。

硬分叉是永久性的,只要旧节点不升级软件,分叉是永远存在的。如ETH和ETC

一个去中心化系统,调整参数可能会导致分叉,而且取决于参数如何修改,有可能是硬分叉,有可能是软分叉。

软分叉:对比特币协议加限制,原来合法的区块在新的协议中会不合法,会导致软分叉。软分叉是临时性的。
软分叉实际出现情况:一是给某些目前协议中没有规定的域增加新含义,赋予新规则。如coinbase域。二是P2SH。

总结:
软分叉特点:只要系统中拥有半数以上算力的节点更新软件,系统就不会出现永久性分叉,可能有临时性分叉。
硬分叉特点:必须所有节点都更新软件,系统才不会出现永久性分叉。


Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐