[北大肖臻-区块链技术与应用笔记]第八节课——BTC 脚本

这篇具有很好参考价值的文章主要介绍了[北大肖臻-区块链技术与应用笔记]第八节课——BTC 脚本。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

[北大肖臻-区块链技术与应用笔记]第八节课——BTC 脚本


比特币系统中使用的脚本语言很简单, 唯一能访问的内存空间就是一个栈,这点和通用脚本语言的区别很大。

一、实际交易举例

btc 脚本语言,# 区块链学习

btc 脚本语言,# 区块链学习

这个交易有一个输入和两个输出,其中一个输出已经被花出去了,另一个没有被花出去。

输入脚本

输入脚本包含两个操作,分别将两个很长的数压入栈中。

输出脚本

输出脚本有两行,分别对应上面的两个输出,即每个输出有自己单独的一段脚本

交易结构

"result":{
	"txid":"921a.dd24",//交易id
	"hash":"921a.dd24",//交易的哈希值
	"version":1,//使用的比特币协议版本号
	"size":226,//交易的大小
	"locktime":0,//交易的生效时间,0代表立即生效,非0代表经过几个区块后才允许上链
	"vin":[...],//交易的输入
	"vout":[...],//交易的输出
	"b1 ockhash":"0000000000000000002c510d..5c0b",//交易所在区块的哈希值
	"confirmations":23,//目前已经有几个确认,包括自己及其后面有多少区块上链
	"time":1530846727,//交易产生的时间戳
	"b1 ocktime":1530846727//该交易所在的区块的产生时间
}
交易的输入

交易的输入是一个列表,可以有多个输入,如果一个交易有多个输入,那么每个输入都要指明来源,并给出签名。

"vin":[{
	"txid":"c0cb...c57b",//该输入的来源交易的哈希值
	"vout":0,//该输入对应“来源交易”的哪一个输出。是一个索引值
	"scriptsig":{//输入脚本,这里是最简单的形式,只有签名    
		"asm":"3045...0018",
		"hex":"4830...0018"
	}	
}],
交易的输出

交易的输出也可以有多个,形成列表

"vout":[{
	"va1ue":0.22684000,//金额,即转过去多少BTC
	"n":0,//序号,表示这个输出在这个交易中的索引
	"scriptPubKey":{//输出脚本
		"asm":"DUP HASH160 628e...d/43 EQUALVERTFY CHECKSTG",
		"hex":"76a9.88ac",
		"regsigs":1,//这个输出需要多少个签名才能兑现,有的输出需要多重签名
		"type":"pubkeyhash",//输出的类型,此处pubkeyhash是公钥的哈希
		"addresses":["19z8LJkNXLrTv2QK5jgTncJCGUEEfpQvSr"]//输出的地址
    }
},{
	"va1ue":0.53756644,
	"n":1,
	"scriptPubKey":{
		"asm":"DUP HASH160 da7d...2cd2 EQUALVERIFY CHECKSIG",
		"hex":"76a9.88ac",
		"regsigs":1,
		"type":"pubkeyhash",
		"addresses":["1LVGTpdyeVLCLCDK2m9f7Pbh7zwhs7NYhX"]
    }
}]

二、脚本举例说明

btc 脚本语言,# 区块链学习

在早期的比特币系统中,B->C这个交易的输入脚本和A->B这个交易的输出脚本拼在一起执行。

后来,出于安全因素的考虑,这两个脚本改为分别执行,首先执行输入脚本,如果没有出错,那么再执行输出脚本,如果能顺利执行,并且最后得到非零值(true),那么这个交易就是合法的。

如果一个交易有多个输入,每个输入脚本都要去找到前面特定区块中所对应的输出脚本,匹配之后来进行验证。全部验证通过后,这个交易才是合法的。

三、输入输出脚本的形式

P2PK(Pay to Public Key)

input script:
	PUSHDATA(Sig)
output script:
	PUSHDATA(PubKey)
	CHECKSIG

输入脚本中直接给出签名(收款人用自己的私钥对输入脚本所在的整个交易的签名

输出脚本中直接给出收款人的公钥,最后的CHECKSIG是检查签名。

脚本执行

为方便显示,将输入输出脚本拼接显示如下:

btc 脚本语言,# 区块链学习

1️⃣ 第一条语句,将输入脚本中的签名压入栈

2️⃣ 第二条语句,将输出脚本中的公钥压入栈

3️⃣ 第三条语句,弹出栈顶的两个元素,用公钥PubKey检查一下签名Sig是否正确。如果正确,返回True,说明验证通过

P2PKH(Pay to Public Key Hash)

input script:
	PUSHDATA(Sig)
	PUSHDATA(PubKey)
output script:
	DUP
	HASH160
	PUSHDATA(PubKeyHash)
	EQUALVERIEY
	CHECKSIG

P2PKH的输出脚本中没有给出收款人的公钥,给出的是公钥的哈希值。

在输入脚本中给出了这个人的公钥(也就是既要给出公钥又要给出签名)

P2PKH是最常用的一种形式。

脚本执行

为方便显示,将输入输出脚本拼接显示如下:

btc 脚本语言,# 区块链学习

1️⃣ 第一条语句,将输入脚本中的签名压入栈

2️⃣ 第二条语句,将输入脚本中的公钥压入栈

3️⃣ 第三条语句,将栈顶元素复制一遍(所以又压入了一次公钥)

4️⃣ 第四条语句,将栈顶元素取出来取哈希,再将得到的哈希值压入栈(也就是将栈顶的公钥变成了其哈希值)

5️⃣ 第五条语句,将输出脚本中提供的公钥的哈希值压入栈

6️⃣ 第六条语句,弹出栈顶的两个元素(都是公钥的哈希值),比较它们是否相等——防止有人用自己的公钥冒充币的来源的交易的收款人的公钥

7️⃣ 第七条语句,弹出栈顶的两个元素(公钥和签名),用公钥PubKey检查一下签名Sig是否正确。如果正确,返回True,说明验证通过

P2SH(Pay to Script Hash)

这是最复杂的一种形式,这种形式下输出脚本给出的不是收款人的公钥的哈希,而是收款人提供的赎回脚本(Redeem Script)的哈希。将来要花这个输出脚本的BTC的时候,相应交易的输入脚本要给出赎回脚本的具体内容,同时还要给出让赎回脚本能正确运行所需要的签名。

input script:
	...
	PUSHDATA (Sig)//签名
	...
	PUSHDATA(serialized redeemScript)//序列化赎回脚本
output script:
	HASH160
	PUSHDATA(redeemScriptHash)//赎回脚本的哈希
	EQUAL

input script要给出一些签名(数目不定)及一段序列化的redeemScript。验证分如下两步:

1️⃣ 验证序列化的redeemScript是否与output script中的赎回脚本哈希值匹配?

2️⃣ 反序列化并执行redeemScript,验证input script中给出的签名是否正确?

redeemScriptr的形式

1️⃣ P2PK形式

2️⃣ P2PKH形式

3️⃣ 多重签名形式

用P2SH实现P2PK的功能

redeemScript:
	PUSHDATA(PubKey)
	CHECKSIG
input script:
	PUSHDATA(Sig)
	PUSHDATA(serialized redeemScript)
output script:
	HASH160
	PUSHDATA (redeemscriptHash)
	EQUAL
第一阶段的验证

验证序列化的redeemScript是否与output script中的赎回脚本哈希值匹配

btc 脚本语言,# 区块链学习

1️⃣ 第一步,将输入脚本中的交易签名压入栈

2️⃣ 第二步,将输入脚本中给出的赎回脚本压入栈

3️⃣ 第三步,弹出栈顶元素取哈希再压栈,也就得到了赎回脚本的哈希(Redeem Script Hash)

4️⃣ 第四步,将输出脚本中给出的赎回脚本的哈希值压入栈

5️⃣ 第五步,比较栈顶两个元素是否相等,相当于用之前的输出脚本给出的赎回脚本哈希,验证了输入脚本提供的赎回脚本是否是正确的

第二阶段的验证

反序列化并执行redeemScript,验证input script中给出的签名是否正确

btc 脚本语言,# 区块链学习

1️⃣ 第一步,将脚本中写死的公钥压入栈

2️⃣ 第二步,验证输入脚本中给出的交易签名的正确性。验证通过就会返回True

四、多重签名

P2SH常见的应用场景就是对多重签名的支持

比特币系统中一个交易输出可能要求使用它的交易输入提供多个签名,才能把BTC取出来。比如某个公司可能要求5个合伙人中的任意三个提供签名,才能把公司的钱转走。这样设计不但为私钥的泄露提供了一定安全性保护,也为私钥的丢失提供了一定的容错性

最早的多重签名

最早的多重签名,目前已经不推荐使用

inputScript:
	X//在输入脚本里往栈中添加一个没用的元素,抵消掉BTC其中的一个bug。
	PUSHDATA(Sig 1)
	PUSHDATA(Sig 2)
	PUSHDATA(Sig M)
outputScript:
	M
	PUSHDATA(pubkey_1)
	PUSHDATA(pubkey_2)
	...
	PUSHDATA(pubkey N)
	N
	CHECKMULTISIG

给出的M个签名的相对顺序,要和对应的输出脚本中N个公钥中对应公钥的相对顺序一致

脚本执行

btc 脚本语言,# 区块链学习

1️⃣ 第一步,将输入脚本中的多余元素(前述的叉)压栈

2️⃣ 第二步,将输入脚本里的M个签名依次压入栈中(这里M=2)

输入脚本执行完。

3️⃣ 第三步,将输出脚本中给定的阈值M压栈

4️⃣ 第四步,将输出脚本中给定的N个公钥压栈

5️⃣ 第五步,将输出脚本中给定的公钥数N压栈

6️⃣ 第六步,执行CEHCKMULTISIG,以检查堆栈中是否按顺序包含了N个签名中的M个

这是最早的多重签名,并没有用到P2SH,就是用比特币脚本中原生的CEHCKMULTISIG实现的.。

这样在实际使用时有些不方便的地方,例如电商网站开通了比特币支付渠道,但要求要有5个合伙人中3个人的签名才能把BTC转走。但这样做之后,用户在BTC支付的时候,生成的转账交易里也给出5个合伙人的公钥,同时还要给出N和M的值。

而这些公钥,以及N和M的值就要电商网站公布给用户,而且不同的电商网站规则也不一样,这就让用户生成转账交易变得不方便。因为这些复杂性都暴露给用户了

用P2SH实现多重签名

相比前面的实现,这样的本质是将复杂性从输出脚本转移到了赎回脚本中,输出脚本只需要给出赎回脚本的哈希值就行了。N个公钥以及N、M的值都在赎回脚本中给出来,而赎回脚本由输入脚本提供,这样也就和支付给它的用户们隔离开了。

btc 脚本语言,# 区块链学习

从用户的角度来看,采用这种P2SH的支付方式,和P2PKH支付方式没有多大区别,只不过输出脚本中的是赎回脚本的哈希值而不是公钥的哈希值

输入脚本就是电商网站要把这笔BTC转出去时候用的,这种方式下输入脚本要包含M个签名,以及赎回脚本的序列化版本。

如果电商将来改变了采用的多重签名规则,就只需要改变一下赎回脚本的内容和输入脚本中的内容,然后把新的赎回脚本的哈希值公布出去就可以了。对用户而言也只是付款时候输出脚本中要包含的哈希值发生了变化。

执行情况
第一阶段验证

btc 脚本语言,# 区块链学习

1️⃣ 第一步,将占位元素压栈

2️⃣ 第二步,将输入脚本中的M个签名压栈

3️⃣ 第三步,将输入脚本中保存的序列化的赎回脚本压栈

输入脚本执行结束

4️⃣ 第四步,弹出栈顶元素取哈希再压栈,即将栈顶的赎回脚本取哈希

5️⃣ 第五步,将输出脚本中给出的赎回脚本哈希值(RSH)压栈

6️⃣ 第六步,判断栈顶两个元素是否相等,即判断一下计算出的赎回脚本哈希和给定的赎回脚本哈希是否相等

输出脚本执行结束,第一阶段验证结束

第二阶段验证

1️⃣ 第一步,将签名数M压栈

2️⃣ 第二步,将N个公钥压栈

3️⃣ 第三步,将给定的公钥数N压栈

4️⃣ 第四步,使用CEHCKMULTISIG操作检查多重签名的正确性

五、Proof of Burn:销毁BTC

这是一种特殊的输出脚本,执行到RETURN语句就会出错,然后验证就会终止,后面的语句完全没有机会执行。

为什么要销毁比特币?一般有两种应用场景:

1️⃣ 一些小的加密货币(AltCoin:Alternative Coin),要求销毁一定数量的比特币可以得到一定数量的这种币。这时Proof of Burn就可以证明自己销毁了这些比特币。

2️⃣ 往区块链里写入一些内容。因为区块链是不可篡改的账本,有人就利用这个特性向其中写入一些需要永久保存的内容。比如第一节课学的digital commitment,即需要证明自己在某一时间知道某些内容。例如某些知识产权保护,可以将知识产权取哈希之后,将哈希值放在这种输出脚本的RETURN语句的后面。反正哈希值很小,而且哈希值没有泄露原来的内容,将来出现纠纷时,再将原来的内容公布出去,大家在区块链上找到这个交易的输出脚本里的哈希值,就可以证明自己在某个时间点已经掌握了这些知识了。

对于上面说的第2种应用场景,回想在前面学习到铸币交易时,铸币交易的CoinBase域也可以随便写什么内容,为什么不在那里写呢?这种方法很难,必须要获得记账权,而且是在CoinBase域设定好内容的情况下,去获得记账权。根本来说,是因为发布交易不需要有记账权,但发布区块需要取得记账权。

任何用户都可以用Proof of Burn的方法,销毁极少量的比特币,换取向比特币系统的区块链中写入一些内容的机会。

没有销毁比特币,仅仅支付了交易费,也可以向区块链中写入内容:

btc 脚本语言,# 区块链学习

BTC系统中使用的脚本语言很简单,它也不是图灵完备的语言,甚至不支持循环,这样设计也有其用意,不支持循环也就不会有死循环。后面学的以太坊的脚本语言就是图灵完备的,这样就靠其它机制来防止进入死循环等。

BTC的脚本语言针对BTC应用场景做了很好的优化,如检查多重签名时的CHECKMULTISIG操作一条就能实现,这是其强大之处。

参考资料

1、【区块链学习笔记】8:比特币中使用的脚本语言#1

2、【区块链学习笔记】9:比特币中使用的脚本语言#2文章来源地址https://www.toymoban.com/news/detail-811979.html

到了这里,关于[北大肖臻-区块链技术与应用笔记]第八节课——BTC 脚本的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

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

    提示:以下内容只是个人在学习过程中记录的笔记,图片均是肖老师课程的截图,可供参考。如有错误或不足之处,请大家指正。 1. 转账交易时如果接收者不在线(没有连接到比特币网络上)怎么办? 转账交易不需要接收者在线,这个交易只是在区块链上记录一下,把发送

    2024年01月22日
    浏览(48)
  • 北大肖臻老师《区块链技术与应用》系列课程学习笔记[27]以太坊-反思

    目录 一、智能合约的反思         1.Is smart contract really smart?         2. Irrevocability is a double edged sword.         3. Nothing is irrevocable. 二、语言设计上的反思         1.Is solidity the right programming language?         2.编写智能合约的语言应该有什么样的表达力? 三

    2024年01月20日
    浏览(57)
  • 北大肖臻老师《区块链技术与应用》系列课程学习笔记[20]以太坊-权益证明

    目录 一、为什么要转入权益证明         1.比特币系统的相关数据          2.以太坊的统计数据         3.比特币和以太坊当成一个国家 二、思考         1.矿工为什么要挖矿?         2.为什么要给矿工这些收益,这些出块奖励呢?         3.矿工具体

    2023年04月25日
    浏览(42)
  • 北大肖臻老师《区块链技术与应用》系列课程学习笔记[25]以太坊-智能合约-5

    智能合约-1 智能合约-2 智能合约-3 智能合约-4 网上竞拍第二版:由投标者自己取回出价 (1)存在的问题         重入攻击,如果有黑客写了一个如下方程序会怎么样?         这个hack_bid跟前面的那个黑客合约hack_bid合约是一样的,通过调用拍卖bid函数参与竞拍,ha

    2024年03月11日
    浏览(65)
  • 北大肖臻老师《区块链技术与应用》系列课程学习笔记[22]以太坊-智能合约-2

    智能合约-1 目录 一、智能合约的创建和运行         1.智能合约的创建         2.汽油费         3.错误处理         4.嵌套调用 二、思考         1.GasLimit和GasUsed         2.以太坊中的GasLimit跟比特币的区别 1.智能合约的创建         智能合约 由一个外

    2024年02月19日
    浏览(50)
  • 北大肖臻老师《区块链技术与应用》系列课程学习笔记[23]以太坊-智能合约-3

    智能合约-1 智能合约-2 1.假设某个全节点要打包一些交易到一个区块里,这些交易里有一些是对智能合约的调用,那么这个全节点应该先执行完智能合约再挖矿,还是先挖矿获得记账权再执行这些智能合约?         在区块链中,如果有一笔转账交易发布上去,需要所有的全

    2023年04月23日
    浏览(45)
  • 北大肖臻老师《区块链技术与应用》系列课程学习笔记[21]以太坊-智能合约-1

    目录 一、什么是智能合约 二、智能合约的代码结构         1.Solidity语言         2.bid函数         3.fallback()函数  二、外部账户如何调用智能合约 三、一个合约如何调用另一个合约中的函数         1.直接调用         2.使用address类型的call()函数      

    2024年02月05日
    浏览(44)
  • 北大肖臻老师《区块链技术与应用》系列课程学习笔记[17]以太坊-GHOST协议

    目录 一、以太坊的出块时间及可能带来的问题         1.以太坊的出块时间         2.以太坊与比特币系统的平均出块时间对比         3.带来的问题 二、GHOST协议         1.GHOST协议的核心思想         2.GHOST协议的缺陷         3.改进后的GHOST协议    

    2024年02月09日
    浏览(51)
  • 北大肖臻老师《区块链技术与应用》系列课程学习笔记[15]以太坊-交易树和收据树

     目录 一、以太坊中的三种树 二、状态树、交易树和收据树的区别 三、交易树和收据树的用途         1.交易树和收据树的用途         2.如何实现复杂的查询操作         3.以太坊中Bloom Filter的用途 四、以太坊的运行过程        在以太坊中,存在三种基于树的

    2024年02月05日
    浏览(54)
  • 北大肖臻老师<<区块链技术>>笔记1

    课程的大纲 密码学基础 比特币的数据结构 共识协议和系统实现 挖矿算法和难度调整 比特币的脚本 软分叉和硬分叉 匿名和隐私保护 以太坊是后面的 首先是密码学基础的学习: crypto-currency(虚拟货币) 是不加密的,区块链上所有的教以都是公开的。其中有转账金额和地址。

    2024年02月02日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包