注:没有全部复原,抽取了主体知识,加入了一些自己的理解,强烈建议去学习肖臻老师的课程,这绝对算得上是国内区块链讲解的顶级教程,纯学术和技术
BTC使用的脚本语言是非常简单的,唯一能访问的内存空间就是一个堆栈 ,不像C,C++那样有全局变量和局部变量还有动态分配的内存空间
所以叫基于栈的语言
stack base language
看一下交易的宏观信息,
size:交易的大小
locktime:用来表示交易的生效时间,0表示立即生效,10表示10个区块之后才能写进区块里面
time:交易产生的时间
输出最简单的形式就是给出一个Public Key
reqSigs:需要的签名数量
有一个交叉,后面的交易的输入要放在前面,前面的交易的输出要放在后面
早期的BTC脚本中这两个脚本是拼接在一起的,从头到尾执行一遍
出于安全因素的考虑,现在这两个脚本分开执行,首先执行输入脚本,如果没有出错,再执行输出脚本,
最后栈顶的结果为非0值,也就是true,那么验证通过 ,这个交易就是合法的,如果执行过程中出现任何错误,这个交易就是非法的
如果一个交易有多个输入脚本,那么所有的输入脚本都要与对应的输出脚本匹配之后来进行验证,全都验证通过这个交易才是合法的
输入输出的形式:
1.最简单的形式: P2PK,Pay to Pubic Key
输出脚本里直接给出收款人的公钥
CHECKSIG是检查签名的操作
输入脚本直接给出签名就可以,私钥对输入脚本所在的整个交易的签名
注:拼接起来,第一行是输入脚本,后两行是输出脚本,实际执行中是分开执行的,PPT是为了方便,拼接在一起显示
流程:
2.最常用的形式:P2PKH:Pay to Public Key Hash
与第一种的区别是输出脚本里没有直接给出收款人的公钥
给出的是公钥的哈希
公钥是在输入脚本里给出的
输入脚本既要给出签名也要给出公钥
输出脚本里的DUP,HASH160都是为了验证签名的正确性
流程:
3.最复杂的形式:P2SH: Pay to Script Hash
输出脚本给出的是一个接收者提供的脚本的哈希,这个脚本叫redeemScriptHash,赎回脚本
输入脚本要给出赎回脚本的具体内容,同时要给出能让这个赎回脚本正确运行的签名
第一阶段步骤:
第二阶段步骤:
在传输前需要将数据结构转换成方便网络传输的 字节流 形式,这个过程称为 序列化
从字节流“恢复”数据成数据结构的形式,这个过程称为 反序列化
输出脚本中需要N个,输入脚本只需要提供M个合法签名就可以验证通过,N>=M,N>1/2M
输入脚本有一个BUG,执行的时候会从堆栈中多弹出一个元素,所以第一个为多余的元素
M个签名的顺序要在N个公钥中签名的顺序一致才可以
FALSE就是多余的元素
将输入脚本的两个签名压入栈中
将阈值M=2压入栈
将三个公钥压入栈
将N=3压入栈
执行CHECKMULTISIG,看看是不是符合多重签名
本质是将复杂度从输出脚本转移到输入脚本
步骤:
至此,第一阶段的验证就结束了,下面是第二阶段的验证
只有RETURN操作,后面的都不执行,无论输入的什么内容,到输出脚本就RETURN,不再执行任何操作
这个脚本是证明销毁BTC的一种方法
为什么要销毁BTC?
两种应用场景:
发布消息不需要记账权,发布区块需要记账权,任何用户都可以使用这种方法销毁少量的BTC
这种操作对全节点是比较友好的,因为不需要写入UTXO中,手续费全部都用来写入脚本,输出为0
coinbase脚本里面也可以写东西【前面讲的】
OP_CHECKSIG,PPT里都省略了OP
BTC的脚本不支持循环,也就不会陷入死循环
不像以太坊是图灵完备的,但是其密码学的功能很强大,比如CHECKMULTISIG一句话就可以支持多重签名验证,所以比特币的脚本看上去很简单,但是针对比特币的应用场景做了很好的优化
因为不需要写入UTXO中,交易费用全部都用来写入脚本,输出为0
coinbase脚本里面也可以写东西【前面讲的】
OP_CHECKSIG,PPT里都省略了OP
比特币的script不支持循环,也就不会陷入死循环
不像以太坊是图灵完备的,但是其密码学的功能很强大,比如CHECKMULTISIG一句话就可以支持多重签名验证,所以BTC的脚本看上去很简单,但是针对BTC的应用场景做了很好的优化