查看原文
其他

比特币史话·71 | 智能合约(6): 逆波兰式

刘教链 刘教链 2023-01-30

(扬·卢卡西维兹,波兰逻辑学家。图片来源于网络)
前情回顾:
比特币史话·66 | 智能合约(1): 脚本的由来
比特币史话·67 | 智能合约(2): 合约并不智能
比特币史话·68 | 智能合约(3): 同性恋之死
比特币史话·69 | 智能合约(4): 图灵完全吗?
比特币史话·70 | 智能合约(5): 停机问题

正文:

1929年,波兰逻辑学家扬·卢卡西维兹(Jan Łukasewicz)发明了一种新颖的数学表达式写法,后人称之为“逆波兰表达式”(Reverse Polish Notation),又称为“后缀表达式”。相应的,与之相反的写法就是“波兰式”,又称为“前缀表达式”。

通常人们习惯的数学表达式写法是所谓的“中缀表达式”,也就是把运算符写在运算量的中间,像这样:(1 + 2 + 3) * 4。等价的前缀表达式写法顾名思义就是把运算符写在前面:(* (+ 1 2 3) 4)。而等价的后缀表达式,也就是逆波兰表达式的写法则是这样的:1 2 3 + 4 *。

我们平时接触的数学和编程语言大多数用的都是最常见的中缀表达式,这种书写形式最符合人类的阅读习惯,但是对计算机最不友好,需要仔细地定义运算符的优先级,并合理的运用括号来表示所希望的计算顺序,才能让计算机正确领会人的意思。著名的函数式编程语言开山鼻祖LISP语言则使用前缀表达式来编写程序代码,好处是程序直接就是AST抽象语法树,免去了计算机语法解析之苦。而逆波兰表达式则是最不常见的一种写法,因为这种写法最违反人类的阅读习惯,只有少数的冷门编程语言比如Forth采用这种编码方式,这种写法对计算机是非常友好的,使用计算机最简单的栈(stack)就可以运算求值。但是逆波兰表达式的写法有一个最大的优点就是完全不需要括号,这样就避免了括号位置或嵌套顺序搞错造成不易察觉的错误(bug)。

中本聪选择了使用逆波兰表达式来编写比特币脚本。一方面,逆波兰表达式不容易出现编写错误,这本身就是系统的“安全性”或“健壮性”的重要体现;另一方面,不需要括号就避免了括号的配对问题,这一点对于比特币脚本的设计非常关键,后面我们会看到为什么没有括号对比特币脚本的设计是如此重要。

那么,上面示例的表达式用比特币脚本语言编写出来就是类似于这样的:

1 2 3 加法(OP_ADD) 4 乘法(OP_MUL)[注:已被禁用]

在举一个现实的例子。我们最常见的向比特币地址转账的交易,其中所用的比特币脚本是这个样子的:

收款人签名 收款人公钥 复制(OP_DUP) 哈希160(OP_HASH160) 收款人地址 验证相等(OP_EQUALVERIFY) 检查签名(OP_CHECKSIG)

以上,OP_开头的都是运算符,又叫操作符或操作码(operators),代表一种操作,其他的都是运算量(operands),是某一种被操作的数据。

在知道比特币脚本之前,我们对于比特币的理解和直观想象是一笔笔的比特币是以一个个不同面额的硬币(UTXO)的形式存放在比特币地址中的,好像被放在了一个带锁的保险箱中,只有持有这个比特币地址对应的所谓私钥,也就是这个保险箱的钥匙的主人,才能打开保险箱,动用存放在里面的比特币。

但是事实上,中本聪通过比特币脚本的设计,把保险箱的锁和钥匙升级成了智能锁和智能钥匙。这个配对的智能钥匙和智能锁就是把比特币脚本一掰两半得到的,就像中国古代的虎符,君王、将军各执一半,需用时拼在一起,即可调兵遣将。以上面向比特币地址转账的交易为例,掰成两半是这样的:

智能钥匙由收款人持有,只有必要时才需要出示:
收款人签名 收款人公钥

智能锁则由付款人公开在区块链账本上,锁住该枚比特币硬币:
复制(OP_DUP) 哈希160(OP_HASH160) 收款人地址 相等验证(OP_EQUALVERIFY) 检查签名(OP_CHECKSIG)

智能钥匙在比特币中叫做解锁脚本(scriptSig)。智能锁则叫做锁定脚本(scriptPubKey)或见证脚本(witness script)。钥匙和锁拼在一起,就还原出了可以运行的脚本,可由任何人加以运算和验证。至此,诸君可以看到,采用逆波兰表达式消除了括号,使得在掰开脚本的时候避免了括号配对的麻烦和可能出现的错误。

我们前面的表述“存放在比特币地址中”其实仍然是把比特币“地址”和银行“账户”进行了类比和等同,而事实上,正像之前早已讲过的,比特币系统中压根儿就没有所谓的“账户”,也不存在所谓比特币放在哪儿的问题。比特币区块链上真实存在的,只是一个个的比特币硬币(UTXO未花交易输出),每一枚都有着不同的面值,并被一把“智能锁”也就是“锁定脚本”锁住。任何人只要能够出示可以开启这把“智能锁”的“智能钥匙”,就可以动用这个硬币。

所以说,有没有不在任何一个比特币地址中的比特币?答案显然是肯定的。比如一个硬币的锁定脚本是“哈希256(OP_HASH256) <哈希值> 相等吗(OP_EQUAL)”,那么只需要能够提供给定哈希值的正确的原像(preimage)就可以花费这个币,这个硬币没有“存放在”任何一个地址中。

有了这个精巧的设计,我们所需要的“担保交易”(escrow)就非常容易实现了。

【未完待续】(公众号:刘教链)

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存