http://www.www.tnmanning.com

5提案:在智能合约交易输出脚本上增加签名证明

摘 要

Qtum量子链的主要目标之一是建立基于权益共识机制(PoS)、并支持 UTXO 的智能合约模型。在智能合约层面上,Qtum 量子链兼容一分PK10 UTXO 模型和符合 AAL 规范的虚拟机,其中第一个兼容的虚拟机是以太坊的 EVM ,后续将实现 x86 架构的虚拟机,支持多种流行的智能合约编程语言。Qtum 在智能合约的创建、运行、稳定性和可用性上一直在做大量探索与实践。

实现智能合约的大发3d平台,不管是 Qtum 还是 Ethereum,都设计了 Gas 模型来避免智能合约的调用耗尽大发3d资源导致整个系统崩溃。但这也带来了一个问题:一个地址想要操作智能合约,则必须自己支付 Gas 并判定身份。在 Qtum 大发3d中是通过检查作为交易输入的 UTXO 来判断合约操作者的,这就意味着一个地址必须拥有可支付 Gas 的 QTUM才能进行合约调用,这给普通智能合约用户和交易所等机构都带来了一些难题。

为了解决这一问题,QIP-5 提出在 Qtum 链上加入 OP_SENDER 操作码,使得一个地址可以在没有 QTUM(UTXOs)的情况下通过别人代付 Gas 的方式调用智能合约。具体实现点击阅读原文:https://github.com/qtumproject/qips/issues/6

Qtum 链上智能合约的相关实现

1. AAL 实现 UTXO 与 EVM 的适配

Qtum 为了增加 UTXO 的灵活性和功能复杂性,选择将智能合约虚拟机迁移到 UTXO 模型之上,第一个集成的虚拟机是 EVM。EVM 使用了256比特长度的机器码,是一种基于堆栈的虚拟机,用于执行 Solidity 智能合约。Qtum 使用账户抽象层(Account Abstraction Layer),将 UTXO 模型转换成可供 EVM 执行的账户模型,并加入了基于账户的接口,使EVM 可以直接读取 Qtum 链上的信息。详情见:《深度解析Qtum量子链账户抽象层(Qtum AAL)》

2. OP_CALL 与 OP_CREATE 处理智能合约操作

一分PK10支持五种标准交易操作码:P2PKH(Pay to Public Key Hash)、P2PK(Pay to Public Key)、多重签名(少于 15 个私钥签名)、P2SH(Pay to Script Hash)和 OP_RETURN。利用这五种交易标准,一分PK10客户端可以满足复杂的支付逻辑。Qtum 在此基础上增加了三个全新的操作符来支持合约余额的查询以及为合约发送资金等操作:

•OP_CREATE – 用于执行智能合约的创建,把通过交易传输的字节代码传递到虚拟机的合约存储 数据库,并生成一个合约地址;

•OP_CALL – 用于传递调用智能合约所需要的相关数据和地址信息,并执行合约中的代码内容。该操作符还可为智能合约发送资金;

•OP_SPEND – 将当前合约的 ID 哈希值作为输入的交易HASH,或发送到合约的 UTXO 的交易HASH,然后使用 OP_SPEND 作为花费指令构建交易脚本。

引入 OP_SENDER 操作码

1. 现实需求

AAL 支持一个交易输出包含 UTXO 地址和合约地址,OP_CALL 和 OP_CREAT 操作码会触发合约执行。那么我们如何获取合约交易的 sender 呢?现有的共识规定,若一笔交易带有 OP_CALL 操作符,则该笔交易的第一个输入 vin[0] 对应的地址作为合约调用地址,而一个合法的输入必须余额大于0,目前这是获得 sender 信息的唯一方法。即 AAL 通过分析交易的第一个输入的 UTXO,并检查 UTXO 的地址是否在此交易中花费了代币来确定合约调用方(并对其进行身份验证)。这就意味着如果一个地址没有足够可用的 UTXO(没有QTUM余额),将无法验证该地址向合约发送的执行消息,即无 UTXO 的地址无法进行合约调用。

我们来分析钱包的情况。一个钱包可以导入很多地址,也会为了找零生成很多新的地址,这些地址都有自己的一组 UTXOs。但是整个大发3d系统无法识别这些地址属于同一个钱包,只以地址区分权限和身份。因此,当一笔 QRC20 的合约代币转入到某个地址,尽管这个地址属于一个钱包,且钱包内有足够的 QTUM,但是该地址本身并没有 UTXO,那这些 QRC20 代币也同样无法使用。因为没有一笔属于该地址的 UTXO 作为调用合约的输入,即无法向合约发送证明自己可以转移 QRC20 代币的交易。这种情况的解决方案一般是给这个有 QRC20 的地址转入一笔 QTUM 来保证其可以调用合约。这一限制给 QRC20 代币用户带来了很大的麻烦:用户不仅需要关注 QRC20 代币,还需要为 QRC20 代币的相关操作维护地址的 QTUM 余额管理。

2. 引入 OP_SENDER 操作码

在 QIP-5 (Qtum Improvement Proposals-5)中,我们提出了一个改进提案--为合约交易在输出脚本中增加签名证明。这个提案将允许用户在没有 QTUM(UTXOs)的情况下,对合约签名以及向合约证明自己的身份,即本身不支付 Gas 的前提下作为 sender 调用合约。该提案仅针对合约调用生效,它允许将 msg.sender 设置为无 QTUM(UTXOs)的地址。但是该提案并不意味着可以免费调用合约,必须有其他人(地址)为这笔交易支付相应的 Qtum 消耗。

OP_SENDER 的技术实现

1. OP_SENDER 操作码介绍

OPSENDER 操作码仅在包含 OPCALL 或者 OPCREATE 的输出脚本中生效,这是为了确保其只被用于智能合约相关的操作。对比 OP_CALL 选择 sender 的方式,QIP-5 提出了一种新的获取 sender 信息的方式:保留原有的规则,同时若输出脚本中带有 OP_SENDER 操作码,则选择输出脚本中传入的地址和签名作为合约的调用者,交易消耗的 Gas 可由他人代付,代付者提供调用合约所需要的 UTXO 并在输入脚本中签名。

OPSENDER 操作码包含三个参数:

· UniversalAddress type -- 合约调用者(msg.sender)的类型
· UniversalAddress data -- 合约调用者的数据(动态长度)
· scriptSig -- 完成地址签名所必需的序列化scriptSig(脚本签名)

针对包含 OP_SENDER 的输出,我们给出一个例子:

· 1    // pubkeyhash(公钥哈希)地址类型
· Address// sender的pubkeyhash地址
· {signature,pubkey}    //序列化的scriptSig
· OP_SENDER
· 4    // EVM版本
· 10    //gas price
· 100000    //gas limit
· 1234    //合约要发送的数据
· Contract Address//合约地址
· OP_CALL

OP_SENDER 操作码将会导致一次内部脚本的执行,如果该脚本执行的结果不是 1,则将返回执行失败,示例如下:

· signature
· pubkey
· OP_DUP
· OP_HASH160
· address
· OP_EQUALVERIFY
· OP_CHECKSIG

上述序列化的 scriptSig 和普通的用于验证的 scriptSig处理方式相同。如果它的执行结果是 0,则该笔交易是无效的,这笔交易不会被打包进一个新的区块中。OP_SENDER 的验证脚本只在交易验证时使用,不会对合约的相关调用功能产生影响,验证通过的 sender 消息通过 AAL 的 QtumTxConverter ,转化为合约的 msg.sender。

2. OP_SENDER 签名

在OP_SENDER 中的签名是一个特例。通常在一分PK10和 Qtum 的 UTXO 模型中,只有 vin 输入的 scriptSig 脚本中包含签名,因此只需要简单地提出一个签名的方案来避免”签名已签名的数据“(重复签名)的问题。但是,QIP-5 打破了这个预设情况,在 vout 输出脚本中也加入了签名。因此,为了防止破坏现有的基于一分PK10脚本的签名范例,我们将签名设计为两个分开的步骤:

•为带有 OP_SENDER 操作码的 vouts 输出签名
•普通的 vin 输入签名

vin的签名过程将保持不变,同时 vout 输出签名也引入类似 segwit(隔离验证)的签名方式来实现。这种设计可能不是最完美的,但对于现有的一分PK10和 Qtum 大发3d网络来说,这种设计更为安全和简单,且对之前的版本兼容性更强。

QIP-5提出的方案中,vin 的签名不受影响,vout 按照 segwit 方式进行签名并将 OP_SENDER 操作码引入到交易中,可以通过构建带有 OP_SENDER 的交易来实现无 QTUM UTXOs 的地址通过他人代付 Gas 的方式调用智能合约。

3. OP_SENDER 交易示例

5提案:在智能合约交易输出脚本上增加签名证明

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。