理解比特币交易脚本
阿牛哥 Lv4

比特币的交易基于UTXO,支持Pay to Public Key Hash(P2PKH-付款到公钥哈希)、Pay to Public Key(P2PK-付款到公钥)和Pay to Script Hash(P2SH-付款到脚本哈希)三种交易验证方式。

按照软件开发的一般原则,为了让交易支持多种验证方式,我们不会为每一种验证都设计一套硬编码(写死在代码里)的实现。而是会为了可扩展性,采用一套通用规则,让这些交易前的验证可以自定义,这正是为什么要在比特币中引入脚本的原因。

换句话说,在发生比特币交易时,脚本将被执行,完成具体的验证工作,验证成功才可以继续交易。

交易

在UTXO中,每笔交易被分为输入和输出两部分。交易的付款方是输入,收款方是输出。

UTXO的输入和输出

比特币网络在处理交易时,实际上只保证输入的合法性,也就是只验证付款人是否真的持有足够的币,如果余额不足,或者没有私钥,显然是不能转账的;而对于收款人,只要一个收款地址或者公钥就行了,不会做额外的验证,只有当他下次成为付款人付款给别人时才需要私钥解锁。

我们这里假设甲转给乙0.1BTC,乙又将这0.1BTC转给丙。

甲乙丙之间的转账关系

在乙转给丙的过程中,乙需要用私钥解开甲转给他0.1BTC。解锁的过程就是由脚本实现的。

输入脚本和输出脚本

每一笔交易脚本分为输入脚本和输出脚本两部分。

乙转给丙0.1BTC,解锁过程这样的,将交易2的输入脚本和交易1的输出脚本拼接,执行这段脚本,如果执行结果是TRUE,那么表示验证通过,解锁成功。

所以,每一笔交易都是要根据BTC的来源找到前一笔交易的,拼接前一笔的输出脚本和这一笔的输入脚本,完成验证。

为了降低复杂性,比特币的脚本在栈上执行。

P2PK

P2PK是比特币脚本中最简单的。如果甲转给乙0.1BTC采用了P2PK脚本,那么交易1的输出脚本是这样:

1
2
OP_PUSHDATA(publicKey)
OP_CHECKSIG

交易2的输入脚本是这样:

1
OP_PUSHDATA(sig)

执行过程是这样的,先拼接两段脚本,交易2的输入脚本在前,交易1的输出脚本在后,得到:

1
2
3
OP_PUSHDATA(sig)
OP_PUSHDATA(publicKey)
OP_CHECKSIG

执行拼接后的脚本:

P2PK脚本执行过程

函数OP_PUSHDATA将数据压入栈中,OP_CHECKSIG的作用是验证publickKey的签名是否是sig。如果验证通过,将在栈中压入非零值TRUE。

脚本的执行结果一旦为TRUE,那么转账成功。

P2PK以收款人的公钥作为参数入栈,意味着转帐前要获得收款人的公钥,显然不如使用钱包地址来得方便。P2PKH就可以解决这个问题。

P2PKH

我们日常发送BTC的交易就是走的P2PKH脚本,此时,甲转给乙不需要获得乙的公钥。

交易1输出脚本:

1
2
3
4
5
OP_DUP
OP_HASH160
OP_PUSHDATA(publicKeyHash)
OP_EQUALVERIFY
OP_CHECKSIG

交易2输入脚本:

1
2
OP_PUSHDATA(sig)
OP_PUSHDATA(publicKey)

拼接后:

1
2
3
4
5
6
7
OP_PUSHDATA(sig)
OP_PUSHDATA(publicKey)
OP_DUP
OP_HASH160
OP_PUSHDATA(publicKeyHash)
OP_EQUALVERIFY
OP_CHECKSIG

OP_DUP将栈顶的参数复制一份,OP_HASH160根据栈顶参数计算钱包地址。

P2PKH脚本执行过程

是不是很巧妙!

关于公钥和地址的关系,可以参考《SHA256在比特币中的应用(二)》

写在最后

理解比特币的交易脚本,对理解比特币底层的转账逻辑很有帮助。

前文还提到了P2SH,利用这个脚本功能可以实现多签(multisig),以后再介绍。(注:这里