跳转到正文
buybitcoinsmart

术语表 /开发者参考

公钥脚本

又称 scriptPubKey、锁定脚本、Pubkey script。

公钥脚本是什么?
公钥脚本是附在每个交易输出上的一小段比特币脚本(Bitcoin Script),规定了该输出中的比特币再次转移之前必须满足的条件。

比特币并不存放在地址中,而是存放在输出里,每个输出由一个公钥脚本保护。Bitcoin Core 把这个字段称为 scriptPubKey,对于普通的现代输出,它的长度为22或34字节。当您把地址交给别人时,等于交给对方一份配方,对方的钱包据此写出公钥脚本。

运作方式

序列化交易中的每个输出依次包含三部分:以聪为单位的8字节金额、长度前缀和公钥脚本本身。输出中没有任何内容指明收款人。脚本就是收款人,而地址只是其中那几个字节带校验和的编码。

如今链上几乎所有输出都属于五种模板。传统的 pay-to-public-key-hash 锁定脚本长25字节,在20字节的哈希两侧共有四个操作码。pay-to-script-hash 锁定脚本长23字节,以 OP_EQUAL 结尾。相比之下,原生 SegWit 刻意做得很简单:一个版本字节加一次数据推送,单个公钥为22字节,脚本哈希为34字节,输出中完全没有逻辑。Taproot 同样为34字节,由一个版本字节和32字节的公钥组成。

中继策略只认这份简短的清单,拒绝转发其他任何格式,因此您无法自创输出格式并指望钱包向其付款。在这一点上,共识规则比中继策略宽松,但实际效果是这五种模板就是全部可选项。

这个名称是历史遗留。在最早的交易中,脚本确实包含公钥:创世区块的 coinbase 输出为67字节,包含一个65字节的未压缩公钥,后接 OP_CHECKSIG,您可以在 Bitcoin Core 自身的源代码中读到。向哈希而非公钥付款在2011年成为通行做法,如今大多数公钥脚本完全不含公钥,只含对公钥的承诺。

在哪里会遇到它

让任何节点解码一笔原始交易,每个输出都带有一个 scriptPubKey 对象,包含四个字段:便于阅读的汇编形式、原始十六进制、类型字符串,以及该类型对应的地址。区块浏览器显示的是同样的内容,通常改称锁定脚本或输出脚本。

钱包的仅观察设置也在这里。导入地址,就是告诉您的软件要在链上扫描哪些公钥脚本,因此在专业工具中,描述符(一种可生成某个密钥能产生的全部脚本的定义)已取代了逐个地址导入。

实用的识读技巧很简单。如果脚本以0开头且含20字节,花费它的人只需一个签名和一个便宜的输入。如果含32字节,背后就有一份您看不到的合约。如果以1开头且含32字节,则是 Taproot,它可能是单个密钥,也可能是一整棵条件树,外表却完全相同。

公钥脚本 vs 签名脚本

公钥脚本提出问题,签名脚本尝试作答,两者由不同的人在不同的时间写成。向您付款的人根据您提供的地址写出公钥脚本,并支付这些字节的费用。您日后花费时再写签名脚本,并自行支付这些字节的费用。因此,向 Taproot 地址付款,发送方的成本略高于向传统地址付款,而您日后转移这笔比特币时能节省得多得多。这两种脚本也是分别运行的,而不是合并成一个程序,这一改动在2010年作出,原因是最初的合并执行方式被发现可被利用。

请勿混淆

常见问题

比特币地址和公钥脚本是同一回事吗?

不是。地址是一种编码,发送方钱包会把它还原为公钥脚本。有些脚本(例如单纯的 OP_RETURN 输出)根本没有地址,因此区块浏览器有时会显示一个有脚本却没有收款人的输出。

公钥脚本里并没有公钥,为什么还叫这个名字?

这个名称源自2009年,当时输出确实包含原始公钥,后接 OP_CHECKSIG。向密钥哈希付款的做法在2011年取代了这种模式,但 scriptPubKey 这个字段名仍保留在代码和文档中。

相关术语

开发者参考中的更多术语

阅读本页英文版