比特币交易的脚本是如何执行的

96
暴走的K哥哥
0.2 2018.01.24 11:08* 字数 779

学习UTXO中,一笔UTXO包含了一个解锁脚本(pkScript),花费这一笔UTXO时,需要通过该脚本验证,才能够花费这笔UTXO。

如何拥有一个UTXO的使用权

比特币的交易创建的输出并非一个简单的公钥地址,而是一个脚本。如果B给A转账0.5个btc的交易中,其实输出pkScript脚本类似:

OP_DUP OP_HASH160 abcd1234...9876 OP_EQUALVERIFY OP_CHECKSIG

其中abcd1234...9876为A的公钥哈希,其他为指令。当谁能提供一个签名和公钥,让这个脚本运行通过,谁就能花费这笔交易的0.5个btc。
当A需要花费这笔btc时,就需要验证这个脚本,所以当A提供公钥和签名时,实际A已经创建了另一笔交易。
所有人都可以验证A创建的这个新交易是否有效,如果有效,该交易就会被矿工打包进新的区块。

一笔交易单实际数据

In:
Previous tx: f5d8ee39a430901c91a5917b9f2dc19d6d1a0e9cea205b009ca73dd0
4470b9a6
Index: 0
scriptSig: 304502206e21798a42fae0e854281abd38bacd1aeed3ee3738d9e1446
618c4571d1090db022100e2ac980643b0b82c0e88ffdfec6b64e3e6ba35e7ba5fd
d7d5d6cc8d25c6b241501

Out:
Value: 5000000000
scriptPubKey: OP_DUP OP_HASH160 404371705fa9bd789a2fcd52d2c580b65d35
549d OP_EQUALVERIFY OP_CHECKSIG

这是一笔交易单数据,包含了收入来源和支出。当进行一笔交易时,需要在交易中描述这笔交易的来源(in),输出(out)交易金额,以及通过脚本的形式写上接收者的公钥(scriptPubKey)。然后验证你的输出(in)的合法性:通过输入的pre tx和index找到指向的UTXO脚本,使用自己的私钥签名(scriptSig)完成脚本验证,最后广播到网络完成转账。

收入来源In:

  • Previous tx 为收入来源交易单的散列值,连接到上一个交易单。
  • index 指明是收入来源交易单中具体哪个索引的out,从0开始。
  • scriptSig 包含了签名和公钥,用于验证Previous tx和index所指向的UTXO的锁定脚本。

接收对象Out:

  • value 发送的币值,单位为Satoshi,1BTC = 1亿Satoshi
  • scriptPubKey 接收方的锁定脚本,后续使用这笔UTXO需要提供公钥和签名通过该脚本的验证。

交易脚本是如何执行的

现在有签名、公钥,需要执行上一个交易输出的脚本获得该UTXO使用权:

sig: 30450221...ee0e01

pubkey: 042e930f...cabb

script: OP_DUP OP_HASH160 46af3fb4…6829 OP_EQUALVERIFY OP_CHECKSIG

比特币脚本被设计成以栈来运行的虚拟机指令,首先先把签名(sig)和公钥(pubkey)入栈:


然后执行指向的TxOut的脚本:
OP_DUP OP_HASH160 46af3fb4…6829 OP_EQUALVERIFY OP_CHECKSIG
首先执行OP_DUP,这条指令是把栈顶元素复制一份:

紧接着执行OP_HASH160,表示对栈顶进行SHA256/RipeMD160,实际就是计算公钥hash:


然后下一条是直接把数据46af3fb4…6829入栈:

然后执行OP_EQUALVERIFY,比较栈顶两个元素是否相等,如果不相等,整个脚本就执行失败,如果成功:


最后执行OP_CHECKSIG栈顶两个元素进行签名校验,如果相等,出栈返回成功。

区块链学习
Web note ad 1