APP下载

基于脚本解释器的区块链交易合约原理与实践

2020-09-26郭倩王中豪王晟典林映春

网络空间安全 2020年9期
关键词:比特币智能合约运行机制

郭倩 王中豪 王晟典 林映春

摘   要:基于脚本解释器的区块链交易合约架构是目前最简洁且高效的智能合约设计之一,它具有去中心化、总量固定、可自由兑换、匿名性等特点,也有利于密码技术在区块链中的灵活应用与实现。文章在整体介绍比特币脚本系统交易结构的基础上,阐述了面向未花费交易(UTXO)的输入交易、输出交易的结构,并详细地给出了比特币脚本指令系统及其执行过程和验证机制,从而实现了区块链交易合约中基于脚本解释器的公钥支付方案。

关键词:智能合约;比特币;运行机制

中图分类号: TP312          文献标识码:A

Abstract: The blockchain transaction contract architecture based on the script interpreter is one of the most concise and efficient smart contract designs at present. It has the characteristics of decentralization, fixed total amount, free exchange, and anonymity. It is also conducive to the flexible application and implementation of cryptography in the blockchain. Based on the overall introduction of the transaction structure of the Bitcoin script system, this paper explains the structure of input transactions and output transactions for unspent transactions (UTXO). In addition, this paper details the Bitcoin script instruction system and its execution process and verification mechanism, so as to implement the public key payment scheme based on the script interpreter in the blockchain transaction contract.

Key words: smart contracts; bitcoin; operating mechanism

1 引言

智能合約(Smart Contracts)在广义上讲是指任何符合多方之间约定的计算机协议,现多指运行在区块链上的一个程序或者脚本,具有自动执行、不可篡改、可回溯等特性。Nick Szabo在1994年提出“智能合约”的概念[1],并将其定义为一个使用计算机处理执行合约条款的交易协议。其目的在于以最小化恶意或意外的异常情况,以及最大限度减少对第三方中介需求的前提下,简化合约的执行和减少合约的执行成本来完成一些常见合约条件。但由于当时缺乏一个可信的第三方平台,加上合约在社会生活中的重要性,智能合约未能真正成为主流合约指定方式。

2008年,学者Satoshi Nakamoto发表了题为《Bitcoin: A Peer-to-Peer Electronic Cash System》的研究报告[2],并在此基础上设计并实现了比特币这种新型数字货币。比特币在对等网络的基础上使用了大量密码学技术[3],并使用工作量证明作为一致性共识算法解决了数字货币面临的“双花”问题。其核心区块链提供了一个以链式数据结构和全网共识为主要特征的分布式数据存储平台[4],由此又获得了去信任和不可篡改等重要特征,从而改变了传统网络交易的固定模式,受到了全社会各界人士的广泛关注。

更为重要的是,比特币系统采用了一种基于脚本解释器的区块链交易合约架构。该脚本解释器采用了一种含有一百多条指令的新计算机指令系统,并采用“栈结构”构造了脚本指令的运行环境。尽管不支持循环和递归机制,但是其脚本易于编写和阅读,并支持密码协议设计,因此它是目前最简洁且高效的智能合约设计之一。它具有去中心化、总量固定、可自由兑换、匿名性等特点,也有利于密码技术在区块链中的灵活应用与实现。

虽然基于脚本解释器的区块链交易构架是非图灵完备的,但它的交易表示结构、指令系统为区块链智能合约的出现奠定了基础[5],并已具有智能合约的雏形,因此理解比特币中的交易系统对于理解并发展智能合约具有重要的借鉴价值。本文在整体介绍比特币脚本系统交易结构的基础上,阐述了面向未花费交易(UTXO)的输入交易、输出交易的结构,并详细地给出了比特币脚本指令系统及其执行过程和验证机制,从而实现了区块链交易合约中基于脚本解释器的公钥支付方案。

2 比特币的交易结构

比特币中交易(Transaction)结构适用于存储每一笔交易的数据结构[6],交易在比特币系统中以tx进行简写。由于比特币是一种数字货币系统,它的交易也只用来记录交易中的货币交换,因此它的交易结构比较简单。具体而言,它的交易内容主要包含交易输入方(购买者)资金的来源和交易输出方(销售者)资金的去处与金额分配。注意,交易输入的总货币量与输出的总货币量是相等的。此外,比特币系统为每个交易添加简单的控制字段。

表1展示了比特币中交易格式的一般结构,并对交易结构中的每个字段的类型和长度(B表示字节)和功能加以描述。一个交易通常包含四方面的信息。

(1)版本号(Version No):交易结构内部编号,用以明确一笔交易参照的规则;

(2)交易输入(tx_in):本次交易中资金的来源,可以含多项,其中,第一个字段为输入项个数,其后跟随输入项列表;

(3)交易输出(tx_out):本次交易后资金的去处,可以含多项,其结构与交易输入相同;

(4)补助信息(Aux):保证交易的补助信息,包括:交易验证、时间锁等。

在四种信息中,输入交易和输出交易是两个列表结构,可以包含一或多个交易项。对输入交易而言,它包含多个输入交易组成的列表,每个交易含有一个交易地址,用于指向以前的交易输出,所有以前交易的货币量总和构成了本次交易的输入货币总量。对于输出交易而言,它也包含输出交易组成的列表,每个交易包含使用该货币的打开方式并给出了新的货币分配量,同样地,所有输出交易的货币量总和应与输出货币量相同。

图1展示了交易之间的相互关系。图中包括了4个交易,交易1输出货币量为100单位的货币,交易2则输出50个单位货币。交易3含有两个交易输入,分别指向前述交易1和交易2,这意味着交易3输入货币量为150个单位。交易3则有2个输出,并将150货币单位中的70单位给输出1和80单位给输出2。交易4则以交易3中的交易输出2的80货币单位为输入,交易输出则分别将30和50货币单位分配给两个交易输出。由此可知,利用交易输入和输出列表可有效而灵活的实现各种货币分配策略。

注意,比特币系统中交易并不直接包含购买者和销售者的信息,而是采用密码学中基于公钥密码的身份认证方式进行货币所有权的宣称与验证。所采用的具体原理和方法将在后续第5节加以介绍。

此外,比特币交易中也包含一些补助信息。例如,版本号用于向系统告知交易结构的版本,系统可对不同版本采取针对性地处理。时间锁(Lock Time)定义了交易放入区块中的时刻(由Unix时间指定),也可表示延迟交易被批准的时间(可看作是一种块高度表示)。具体而言,时间锁中的时间是该交易被加到区块的最早时间,在大多数的情况下它的值都是0,表示需要立即被加入区块中。如果锁定时间大于0而小于5亿(5*108),它的值就表示区块高度;如果大于5亿就表示一个Unix时间戳。

2.1 交易输入的结构

比特币中交易输入列表中每个交易输入的结构由五个字段构成,分别是哈希索引、输出索引、以及签名脚本的长度、脚本本体和序号。表2给出了每一个字段的详细类型与长度以及描述。

哈希索引包含了购买者在上次交易的256-比特的交易标识(txID),利用该标识能够迅速定位到货币资金的来源交易。由于该标识是之前交易经过两次嵌套SHA-256哈希运算后的输出,因此被叫作Hash索引。

输出索引进一步给出了前述交易标识所指交易中的第几个输出,这里要求该输出是未被锁定(花费)的,其中,输出索引是从0开始编号的。

输入结构中最后部分是签名脚本,该脚本是用来证明本次交易中的购买者是前述交易输出货币资金的拥有者。由于脚本长度可变,因此首先由长度字段告知脚本长度,然后紧跟着签名脚本序列本身,最后是签名脚本序号,它对于不同交易具有不同的意义,因此是交易结构所特指的。通常,当序号为0xFFFFFFFF时,该字段被忽略;否则,该字段被用于设置交易输出的锁定时间。

2.2 输出交易的结构

比特币中交易输出列表中每个交易输出的结构由三个字段构成,分别是分配的货币量、公钥脚本的长度和脚本本体。表3给出了每一个字段的详细类型与长度以及描述。

输出项中第一项是货币量,它以satoshis为单位进行表示,其中,1BTC=108 satoshis,即1satoshis为1个比特币的1亿分之一。输出交易中其它两个字段分别用于存储公钥脚本长度和公钥脚本本身,其中,公钥脚本是指用交易输出方(销售者)所拥有公钥生成的检验下次交易输入中签名的验证脚本。

图2显示了一个比特币交易中的输入和输出部分,并省略了两部分中脚本的长度等信息。可以看出比特币交易结构具有简洁和精炼的特点。

除了上述介绍的比特币交易结构,比特币系统还存在其它交易结构用于实现其它一些功能。例如,创币交易(也被称为coinbase交易)是一种可以由矿工创建的独特类型的比特币交易,矿工使用它来收取他们工作的区块奖励。

3 比特币脚本与指令系统

存储在交易中的公钥脚本(scriptPubkey)和签名脚本(scriptSig)字段中的挑戰和响应脚本使用专门为比特币开发的脚本语言进行编码。该语言简称为脚本(Script),是一种基于栈的语言,即它使用栈结构实现脚本输入参数的存储和运算。

比特币脚本被构建在一种特有的指令系统之上。在计算机系统中,指令系统通常是计算机硬件的语言系统,也叫机器语言,指机器所具有的全部指令的集合,它是软件和硬件的主要界面,反映了计算机所拥有的基本功能。因此,拥有指令系统的比特币脚本也趋于成为一种独立的计算机系统[7]。

不同计算机的指令系统包含的指令种类和数目也不同。一般均包含算术运算型、逻辑运算型、数据传送型、判定和控制型、移位操作型、位(位串)操作型、输入和输出型等指令[8,9]。比特币中脚本系统的指令采用后缀表达式,即将运算符写在操作数之后,因此指令格式可表示为:

操作数1 操作数2 ……操作数n 操作指令

操作指令由“OP_”开头后面接英文操作名构成,例如:OP_ADD、OP_AND。操作指令将被编码为一个字节,例如,字节0x93用于表示加法运算符OP_ADD,该字节值称为运算符的操作码。在操作指令之前的是操作数列表,根据指令不同它可包含零个或多个操作数,例如:OP_NOP是无操作数的空指令、 OP_ADD是双操作数加法指令等。操作数寻址方式只支持立即寻址方式。

在比特币脚本系统中常用的指令包括:

(1)堆栈处理指令:

OP_DUP(数据复制操作)、OP_DROP(删除栈顶元素)、OP_SWAP(栈顶的两个元素进行交换)等;

(2)流程控制指令:

OP_RETURN(标记交易无效)、

OP_VERIFY(如果栈顶元素为false,标识交易无效。如果为true,则交易有效)等;

(3)加密签名指令:

OP_HASH256(进行hash散列计算)、

OP_CHECKSIGVERIFY(进行签名验证)等;

(4)逻辑操作指令:

OP_EQUAL(判断是否相等)、

OP_EQUALVERIFY(判断是否相等后进行脚本流程控制判断,如果栈顶元素为false就标识交易无效)等。

(5)算术操作指令:

OP_ADD(加)、OP_SUB(减)、

OP_MAX(取最大值)、OP_MIN(取最小值)等。

比特币指令系统内容已较为丰富,可以支持大多数业务的编程需要,也为智能合约的实现创造了基础。

4 比特币脚本执行过程

比特币脚本的执行系统是一种简单的、基于栈结构的、从左到右处理的脚本执行系统[10,11]。下面将从脚本构造和脚本执行过程两个方面加以介绍。

比特币脚本是由若干指令组成的指令序列。例如,判定等式2+3=5的脚本可表示为:

<2> <3> OP_ADD <5> OP_EQUAL

其中,<>中的值为操作数,并且脚本采用了逆波兰式(Reverse Polish notation,RPN)的表达形式。

该脚本将在栈(Stack)结构中被脚本解释器执行,其中,栈是一种具有“先入后出”性质的数据结构表示。脚本解释器要执行一个包含n个参数的脚本指令,首先将参数推送到堆栈上,然后根据读取的操作码,解释器通过直接从堆栈读取这n个值来执行计算,并将返回值存储在堆栈上。因此,这种栈运行方式不需要变量来存储参数或返回值。

表4中,本文给出了前述脚本的运行过程。首先,脚本解释器将操作数<2>和<3>压入到栈中;其次,脚本解释器在接收到OP_ADD指令后将两个栈顶操作数相加,得到结果<5>被置于栈顶;然后,操作数<5>压入到栈中;最后,脚本解释器在接收到OP_EQUAL指令后将两个栈顶元素进行比较,并将结果“真”值置于栈顶,运算结束。因此,5步运算后脚本解释器即可输出最终结果。

与通用语言相比,脚本运行方式具有功能有限的缺点,例如,它不支持循环。但它也有实现方便、便于编程、灵活性强等优点,而且不存在脚本执行不停机等异常现象,因此易于被比特币等轻量级区块链系统所采用。总之,比特币脚本特点可归纳为三点:脚本内存访问采用栈结构、脚本不含有循环、脚本执行总能终止。

5 密码脚本执行与验证

脚本系统在比特币区块链中的直接应用就是密码功能的实现。由于区块链中大量使用了密码技术,而且密码技术在不同的合约中使用方法多样,因而需要一种灵活的方法来支持密码技术在不同合约的使用。由于用户能够在交易中通过灵活而短小的脚本指令对密码操作指令进行编程,因此脚本系统较好地解决了上述问题。

比特币区块链中密码技术的使用是多样的,例如,需要几个签名来解锁这些比特币、除有效签名外还需要提供密码来解锁特定货币。目前,比特币区块链常见的密码脚本有四种类型:

(1)类型1:公钥支付

pay-to-public-key (P2PK):

scriptPubKey: OPCHECKSIG

scriptSig:

(2)类型2:付款到公用密钥哈希

pay-to-public-key-hash (P2PKH):

scriptPubKey: OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG

scriptSig:

(3)类型3:按脚本哈希支付

pay-to-script-hash (P2SH):

scriptPubKey: OP_HASH160 OP_EQUAL

scriptSig: