打字猴:1.703865337e+09
1703865337
1703865338
1703865339
1703865340 区块链技术驱动金融:数字货币与智能合约技术 [:1703863920]
1703865341 区块链技术驱动金融:数字货币与智能合约技术 3.2 比特币的脚本
1703865342
1703865343 每个交易输出不仅确定了一个公钥,其实同时指定了一个脚本。那脚本是什么?为什么我们要用一个脚本?在这一节我们要学习比特币的工作控制语言,也叫脚本。之后,我们就会懂得为什么要用一个脚本,而不是简单地分配一个公钥。
1703865344
1703865345 最常见的比特币交易,就是通过某人的签名去取得他在前一笔交易中获得的资金。这种情况下,我们希望交易的输出包含这样的信息:“凭借地址X的所有者的签名,才可以获得这笔资金。”我们知道地址其实就是一个公钥的哈希值,所以仅仅说地址X并没有告诉我们公钥在哪里,也没有给我们一个检查签名的方法。所以,交易输出必须这样描述:“凭借哈希值为X的公钥,以及这个公钥所有者的签名,才可以获得这笔资金。”这实际上就是最常见的比特币脚本,如图3.4所示。
1703865346
1703865347
1703865348
1703865349
1703865350 图3.4 P2PH脚本范例
1703865351
1703865352 注:一个常见的比特币输出脚本范例。
1703865353
1703865354 那么谁执行这个脚本?这一系列指令是如何完成的呢?秘密在于,交易的输入包括了脚本(而不是签名)。为了确认一笔交易正确地获取了上一笔交易所输出的资金,我们把交易的输入脚本和上一笔交易的输出脚本串联起来,这个串联脚本必须被成功地执行后才可以获取资金。这两个脚本,一个是输出脚本(scriptPubKey),另一个是输入脚本(scriptSig)。输出脚本只是指定了一个公钥(或是公钥哈希值的地址),输入脚本指定了一个对应公钥的签名。图3.5就是两个脚本结合的案例。
1703865355
1703865356 比特币脚本语言
1703865357
1703865358 这个脚本语言是为比特币开发的。在比特币里只叫作“脚本”。它和另一种Forth语言有很多相似的地方,Forth是一种简单的堆栈式编程语言(stack-based programming language),但你并不需要先学习Forth语言才会使用比特币的脚本语言。比特币的脚本语言设计原则就是简明扼要,并内生地支持加密操作。比如,脚本里面有目的性的指令用来计算哈希值和检验签名。
1703865359
1703865360 这种脚本语言是堆栈式的,意味着每个指令只被执行一次,是线性的,无法循环执行。所以指令的数目给了我们一个执行时间与内存使用的上限。这个语言不是图灵完备的,意味着不能随意运行强大函数功能。[1]但这是有意设计的,因为矿工需要去执行这些网络上任意交易提交者所递交的脚本,设计者并不希望让他们提交可能无限循环的脚本。
1703865361
1703865362
1703865363
1703865364
1703865365 图3.5 结合输入脚本和输出脚本范例
1703865366
1703865367 注:为了确认当前交易是否正确地获取了前一笔交易输出的资金,我们把两个脚本链接起来,把上一笔交易的输出脚本(图中虚线下方)添加到当前交易的输入脚本(虚线上方)之后,形成一个新的脚本。请注意里面有一个“?”,用作标识——我们后面会来确认它是否与当前交易提供的公钥的哈希值一致。
1703865368
1703865369 执行比特币脚本只能产生两个结果:要么被成功执行,这种情况下,交易有效;要么脚本执行出现错误,这种情况下,整个交易无效,拒绝记入区块链。
1703865370
1703865371 这个脚本语言十分简单。只有256个指令,每个只用一个字节。256个指令中,有15个目前不可用,有75个被保留还没有具体定义(以后或许可以被用来扩展),剩下的才是可用的。
1703865372
1703865373 许多在其他语言里常见的基本指令这里面都有。例如,基本的算数、逻辑语句(如If-then)、抛出错误、过早返回等。而且,还有密码指令,比如哈希函数语句、签名验证语句,还有一个重要的特殊指令是“CHECKMULTISIG”——可以查证多个签名。表3.1列举了一些比特币工作控制语言里的常用语句。
1703865374
1703865375 CHECKMULTISIG指令要求指定n个公钥和一个参数t(作为一个临界值)。这个指令正确执行的条件是:在n个公钥中,至少可以选出t个现时有效的签名。我们在本章3.3节会示范这个指令的用法,但现在我们需要认识到这个原生指令是非常强大的,它以一种极其精练的方式协助我们查验交易中的多方签名。
1703865376
1703865377 不过,目前比特币多方签名功能实现过程中有一个缺陷,CHECKMULTISIG指令在执行的时候会返回一个没用的值,而且系统还必须要安排一个堆栈中的变量去储存它,然后再忽略掉。由于修复这个缺陷成本很高,两害相权取其轻,这个缺陷就一直没被修复,我们在第3章3.6节会再做讨论。但目前,这个程序缺陷也算是比特币的一个特性。
1703865378
1703865379 表3.1 一些比特币脚本工作语言中的指令及其功能
1703865380
1703865381
1703865382
1703865383
1703865384 执行一个脚本
1703865385
1703865386 在堆栈语言里执行一个脚本,我们只需要一个堆栈来垒积数据,不需要分配任何内存与变量。因此,堆栈语言中计算相当容易。总共有两类指令:数据指令和工作码指令。数据指令的作用是把数据推到堆栈的最上面;工作码指令则通常是用堆栈顶部的数据作为输入值,用来计算一个函数。
[ 上一页 ]  [ :1.703865337e+09 ]  [ 下一页 ]