Forth
FORTH 语言由 Charles H.Moore 在 1970 年设计。 让我们来看一下这门语言的一些代码:
25 10 * 50 + CR .
300 ok
让我们用来模拟一下stack(栈)的状态:
[]
[25]
[10 25]
[* 10 25] -> [250]
[50 250]
[+ 50 250] -> [300]
[CR 300]
[]
可以发现只需要从左到右按顺序把指令压入栈就可以了。 CR
表示将栈顶的内容输出到新的一行, .
表示语句结束,返回 ok
。
再看一个复杂一点的例子:
: FLOOR5 ( n -- n' ) DUP 6 < IF DROP 5 ELSE 1 - THEN ;
这段代码定义了一个名为FLOOR5
的函数, 不太确定( n -- n' )
的意义,可能是表示输入n,输出n’. 函数的内容可以翻译成:
假设输入n=1
[1]
[DUP 1] -> [1 1]
[6 1 1]
[< 6 1 1] -> [true 1] # 注意栈里更深的数值放符号左边,所以是 `1 < 6`
[THEN - 1 ELSE 5 DROP IF true 1] -> [5 DROP 1] -> [5] # 直接执行接下来的语句,忽略ELSE
[5]
假设输入n=8
[8]
[DUP 8] -> [8 8]
[6 8 8]
[< 6 8 8] -> [false 8]
[THEN - 1 ELSE 5 DROP IF false 8] -> [- 1 8] -> [7] # 直接执行ELSE里的语句
[7]
所以,FORTH 是一门非常简单的语言。那么,我们为什么要了解一门48年前的语言呢?因为时下最火热的比特币所使用的脚本就和FORTH非常类似。
Bitcoin Script
bitcoin最核心的一点:如何花掉属于你的钱。我们知道比特币是存储再某个特定的地址里的,那么当试图花掉地址里的钱时,就必须提供某种凭证,证明你对该地址的所有权。
简单地说就是?与?的关系,实际上,一个地址即是一把锁。我们知道ECDSA签名算法的使用方法是:
<privKey> + <data> -> <sig>
<privKey> -> <pubKey>
<sig> + <pubKey> -> true or false
<sig>(签名)可以验证出 <pubKey> 是否属于我(<privKey>的拥有者),那么,可不可用<pubKey>来做比特币的地址呢? 可以,但比特币没有必要保存很长的完整的<pubKey>,
只需要它的哈希(摘要)即可, address即是编码过后的 <pubKeyHash>, 这也提高了地址的安全性。
让我们来看一下比特币中最常见的交易 P2PH(pay-to-pubkey-hash)的验证脚本。
<sig> <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
其中<pubKeyHash>是由地址解码得到的,<pubKey>和<sig>是由spender提供的。让我们来运行一下这段脚本:
[OP_DUP <pubKey> <sig>] -> [<pubKey> <pubKey> <sig>]
[OP_HASH160 <pubKey> <pubKey> <sig>] -> [<pubHashA> <pubKey> <sig>]
[OP_EQUALVERIFY <pubKeyHash> <pubHashA> <pubKey> <sig>] -> [<pubKey> <sig>] # 假设哈希相等
[OP_CHECKSIG <pubKey> <sig>] -> [true] # 假设签名通过
那么如何在比特币网络中运行一些有趣的脚本呢,下一篇我们会讲到如何构建交易。