mt logoMyToken
Vốn hóa thị trường:
0%
FGI:
0%
Tiền điện tử:--
Trao đổi --
ETH Gas:--
EN
USD
APP
Ap Store QR Code

Scan Download

深度解析量子链账户抽象层(Qtum AAL):为Dapp提供了新的基础平台

sưu tầm
đăng lại

Qtum账户抽象层(AAL)实现简析

Qtum设计上以比特币UTXO为基础账户模型,并实现了支持EVM规范的智能合约,这是通过账户抽象层(Account Abstract Layer, AAL)来完成的。AAL对UTXO账户和EVM合约账户之间进行了适配,这样通过AAL可以使用UTXO交易输出实现在链上创建智能合约,发送交易到合约账户用于触发合约的执行,完成执行后AAL最终对执行结果进行处理并适配至UTXO。由于采用了AAL,合约开发者不需关心对合约操作相关的UTXO转换细节,即可使用EVM的特性进行开发而且兼容现有以太坊的智能合约。本文通过对从UTXO交易到智能合约执行的实现代码进行解读,初略分析了AAL的工作过程。

1.UTXO交易新增的脚本操作码

Qtum 针对UTXO交易脚本新增了三个操作码OP_CREATE,OP_CALL和OP_SPEND,目的是用于为UTXO和EVM账户模型之间的转换提供操作支持。这些操作码定义在opcodetype枚举类型中:

enum opcodetype{            ……        OP_CREATE = 0xc1,          OP_CALL = 0xc2,            OP_SPEND= 0xc3,        ……        }

这个三个操作码分别有以下作用

为了在区块生成过程中,识别并处理由这几个操作码控制的交易,在用于UTXO模型交易的类CTransaction中增加了HasCreateOrCall()和HasOpSpend()函数,用于新区块中对mempool中的交易处理,并在脚本操作码解析的EvalScript()函数中增加了相应的处理。

2.UTXO交易到EVM模型交易的转换

产生新的区块时,除了对UTXO交易进行常规的参数合法性、共识规则、DDOS攻击检查等之外,还需要使用操作码检查函数HasCreateOrCall()判断交易输出是否包含OP_CREATE或OP_CALL,分别对应着EVM需要执行合约创建或合约调用。这部分有以下的处理过程:

2.1 进行EVM模型的账号参数提取

合约在EVM的执行用到了data、gasPrice、gasLimit、VM version这几个参数,这些参数是通过RPC调用sendtocontract 发送的,sendtocontract会生成一个UTXO交易,并在交易输出中使用了OP_CALL操作码,之后交易会广播到区块链网络上。AAL中从UTXO到EVM的适配是通过QtumTxConverter类实现的,在这一步中该类的成员函数extractionQtumTransactions()和parseEthTXParams()完成对所有此类UTXO交易输出的参数提取。代码片段如下:

dev::Address receiveAddress;    valtype vecAddr;

if (opcode == OP_CALL)    {        vecAddr = stack.back();        stack.pop_back();        receiveAddress = dev::Address(vecAddr);    }              valtype code(stack.back());    stack.pop_back();    uint64_t gasPrice = CScriptNum::vch_to_uint64(stack.back());    stack.pop_back();    uint64_t gasLimit = CScriptNum::vch_to_uint64(stack.back());    stack.pop_back();    VersionVM version(CScriptNum::vch_to_uint64(stack.back()));    stack.pop_back();

return EthTransactionParams{version, dev::u256(gasLimit), dev::u256(gasPrice), code,                 receiveAddress }

以上代码首先判断如果opcode 为OP_CALL,则说明地址为vecAddr的合约已经创建,因此直接转换成EVM格式的地址receiveAddress,否则为OP_CREATE,对应合约的创建,没有该字段,所以不做提取。接下来依次完成了data、gasPrice、gasLimit、VM version的提取,这些都是EVM执行bytecode时必不可少的参数。

2.2 进行EVM账户模型的交易转换

交易转换是通过QtumTxConverter类的函数 createEthTX()完成,使用前面一步提取的参数和UTXO的交易输出vout创建了QtumTransaction类型的交易。由于QtumTransaction派生自EVM中的dev::eth::Transaction类,因此和EVM执行相关的操作QtumTransaction类都支持。

QtumTransaction txEth;

if ( etp.receiveAddress == dev::Address() ) {    txEth = QtumTransaction(txBit.vout[nOut].nValue, etp.gasPrice, (etp.gasLimit *     etp.gasPrice),     etp.code, dev::u256(0)); }

else{    txEth = QtumTransaction(txBit.vout[nOut].nValue, etp.gasPrice, (etp.gasLimit *    etp.gasPrice),     etp.receiveAddress, etp.code, dev::u256(0)); } dev::Address sender(GetSenderAddress(txBit, view)); txEth.forceSender(sender); txEth.setHashWith(uintToh256(txBit.GetHash())); txEth.setNVout(nOut);

首先代码etp.receiveAddress == dev::Address()判断该合约是EVM状态中没有而需要新创建的还是EVM状态已经包含的合约,差别只在于合约地址。然后,QtumTransaction()构造函数完成了部分的交易参数构造,接下来的语句提取交易的发送者(sender),之后设置交易HASH。一个UTXO交易支持多个输入和输出,Qtum的AAL设计考虑到了这种情况,因此AAL支持一个交易输出包含UTXO账号和合约账号,通过最后设置的nOut指示该交易的nOut输出是发送到智能合约的,所以该输出将触发合约执行。这样就按照EVM的账号模型完成了交易的转换。

3.合约执行及执行结果的UTXO转换

合约的执行会改变状态(由QtumState类的实例化对象globalState统一管理),对于合约的状态,Qtum沿用了EVM定义,所以能兼容所有的符合EVM规范的智能合约。但是账户金额的转移(transfer),Qtum做了UTXO的转换,这意味着智能合约和普通的UTXO模型账号之间能完成交互,这是AAL实现UTXO支持智能合约的重要的一环。下面简要介绍一下合约执行和状态结果的转换过程。

3.1 合约执行环境构建及合约执行

合约的执行是对合约处理中很关键的一步,直接对合约的状态产生影响。通过ByteCodeExec类实现了EVM对合约bytecode的执行,主要函数是performByteCode()。这一步的主要流程是使用上面提取的交易参数,来进行虚拟机执行环境的构建,之后完成合约的执行,其代码如下:

for(QtumTransaction& tx : txs){    dev::eth::EnvInfo envInfo(BuildEVMEnvironment());    std::unique_ptr   se(dev::eth::ChainParams(dev::eth::genesisInfo(dev::eth::Network::HomesteadTest)).    createSealEngine());

if(!tx.isCreation() && !globalState->addressInUse(tx.receiveAddress())){        dev::eth::ExecutionResult execRes;        execRes.excepted = dev::eth::TransactionException::Unknown;        result.push_back(ResultExecute{execRes, dev::eth::TransactionReceipt(dev::h256(),        dev::u256(), dev::eth::LogEntries()), CTransaction()});

continue;    }    result.push_back(globalState->execute(envInfo, *se.get(), tx, type, OnOpFunc())); }

首先是构建合约执行环境,由BuildEVMEnvironment()完成。可以看到这个执行环境是针对每个独立交易进行的,这样就最大限度的把不同交易的合约执行过程隔离开,避免合约执行过程中的交叉影响。然后构建一个新的sealEngine类,该类是EVM执行引擎,由createSealEngine()函数具体完成。中间对出现的可能状态异常进行检查,之后globalState->execute()完成合约的执行,这里使用到了构建的执行环境envInfo和EVM执行引擎se。

3.2 合约执行结果的UTXO转换

合约执行完成后的结果保存在vector result,vector向量理记录了每个合约执行产生的EVM账户间transfer关系,AAL通过把这些transfer转换成UTXO交易,完成了从EVM账户模型到UTXO模型交易的转换。这一处理是通过processingResults()函数实现的,以下是代码片段。

ByteCodeExecResult resultBCE;

for(size_t i = 0; i < result.size(); i++){

if(result[i].execRes.excepted != dev::eth::TransactionException::None){

if(txs[i].value() > 0){            CMutableTransaction tx;            tx.vin.push_back(CTxIn(h256Touint(txs[i].getHashWith()), txs[i].getNVout(), CScript() <<            OP_SPEND));            CScript script(CScript() << OP_DUP << OP_HASH160 << txs[i].sender().asBytes() <<            OP_EQUALVERIFY << OP_CHECKSIG);            tx.vout.push_back(CTxOut(CAmount(txs[i].value()), script));            resultBCE.valueTransfers.push_back(CTransaction(tx));        }    } else {        resultBCE.usedFee += CAmount(result[i].execRes.gasUsed);        CAmount ref((txs[i].gas() - result[i].execRes.gasUsed) * txs[i].gasPrice());

if(ref > 0){            CScript script(CScript() << OP_DUP << OP_HASH160 << txs[i].sender().asBytes() <<            OP_EQUALVERIFY << OP_CHECKSIG);            resultBCE.refundOutputs.push_back(CTxOut(ref, script));            resultBCE.refundSender += ref;        }    }    if(result[i].tx != CTransaction()){        resultBCE.valueTransfers.push_back(result[i].tx);    }}

首先定义了ByteCodeExecResult类型的resultBCE变量,用于保存转换的结果。使用操作码OP_SPEND,用于实现交易的花费,这是因为比特币的UTXO通过私钥签名在交易输入解锁后来实现余额花费的,而EVM执行涉及不同账户之间的transfer,所以需要通过OP_SPEND实现这些transfer到UTXO模型交易的转换。如果execRes.excepted不为None,即合约执行异常,则将余额返还给合约调用者。否则,如果没有异常,则将扣除消耗的gas之后的剩余gas返还给合约的调用者。对于合约执行中出现的transfer其UTXO交易保存在result[i].tx中。因此,经过这一步处理合约执行产生的不同UTXO账户之间的交易就保存在valueTransfers向量中了,最终这些交易会包含进新的区块中。至此AAL模块就完成了从EVM交易到UTXO的转换。

4.总结

AAL通过新增的UTXO脚本操作码,协助完成合约的创建、执行和花费。在合约创建和执行前,需要进行UTXO交易到EVM模型交易的转换,之后使用构建的EVM执行环境和引擎,完成合约的执行。AAL最终对合约的执行结果进行处理并从EVM适配至UTXO,这样就实现了基于UTXO的智能合约。 AAL使得Qtum兼容符合EVM规范的智能合约,为Dapp提供一个新的基础平台,同时UTXO的优点使得诸如并行处理、隐私性等优点能得以保留。

Tuyên bố từ chối trách nhiệm: Bản quyền của bài viết này thuộc về tác giả gốc và không đại diện cho MyToken(www.mytokencap.com)Ý kiến ​​và vị trí; vui lòng liên hệ với chúng tôi nếu bạn có thắc mắc về nội dung
Đọc liên quan