目录

5.9 NatSpec

优质
小牛编辑
124浏览
2023-12-01

NatSpec

本节将进一步阐述您可以通过NatSpec协议构建的合约和交易来做什么。Solidity实现doxigen风格智能注释,然后可以用它来生成代码的各种外观元文档。一种这样的用例是生成用于事务确认的客户端可以提示用户的自定义消息

所以我们现在通过一个智能注释来扩展multiply7合约,此评注释指定一个自定义确认消息(通知)。

contract test {
   /// @notice Will multiply `a` by 7.
   function multiply(uint a) returns(uint d) {
       return a * 7;
   }
}

该注释具有在反引号之间的表达式,当向用户呈现交易确认消息时需要评估它。引用了调用方法参数的变量根据用户(或用户的dapp)发送的实际交易数据进行实例化。在geth中,支持确认通知的NatSpec已全面实施。NatSpec依赖于abi定义以及userDoc组件来生成正确的确认信息。因此,为了达成这一目的,合约需要按照上述方式注册其合约信息。

让我们看看一个完整的例子。作为一个非常认真的智能合同开发商,您首先创建合同并按照上述推荐步骤进行部署:

source = "contract test {
   /// @notice Will multiply `a` by 7.
   function multiply(uint a) returns(uint d) {
       return a * 7;
   }
}"
contract = eth.compile.solidity(source).test
MyContract = eth.contract(contract.info.abiDefinition)
contenthash = admin.saveInfo(contract.info, "~/dapps/shared/contracts/test/info.json")
MyContract.new({from: primary, data: contract.code}, function(error, contract){
  if(!error && contract.address) {
    admin.register(primary, contract.address, contenthash)
    // put it up on your favourite oldworld site:
    admin.registerUrl(contentHash, "http://dapphub.com/test/info.json")
  }
});

请注意,如果我们使用像群集这样的内容寻址存储系统,则第二步是不必要的,因为contenthash是(确定性地转换为)内容本身的唯一地址。 为了轻松地使用例子,只需简单地使用文件url方案(不完全是云,但会显示它如何工作)而不需要部署。

admin.registerUrl(contentHash, "file:///home/nirname/dapps/shared/contracts/test/info.json")

现在你已经作为开发者完成了,所以切换下角色,假装你是一个发送一个交易到multiply7合约的用户。

您需要使用该--natspec标志启动客户端,以启用智能确认和contractInfo提取。您还可以在控制台上使用admin.startNatSpec()admin.stopNatSpec()来设置它。

在控制台输入:

// obtain the abi definition for your contract
var info = admin.getContractInfo(address)
var abiDef = info.abiDefinition
// instantiate a contract for transactions
var Multiply7 = eth.contract(abiDef);
var myMultiply7 = Multiply7.at(address);

现在尝试发送一个真实的交易:

> myMultiply7.multiply.sendTransaction(6, {from: eth.accounts[0]})
NatSpec: Will multiply 6 by 7.
Confirm? [y/n] y
>

当这个交易被包含在一个块中,幸运的矿工的计算机上的某个地方,6将被乘以7,结果被忽略。任务完成。

如果交易没有接收,我们可以通过下面的命令看到:

eth.pendingTransactions

这将累积发送的所有事务,即使是被拒绝的事务,和未包括在当前的开采块(trans state)中的事务。后者可以通过以下方式表示:

eth.getBlock("pending", true).transactions()

如果您确定被拒绝的交易的位置,则可以使用修改的gas限额和天gas价格(两个可选参数)重新发送:

tx = eth.pendingTransactions[1]
eth.resend(tx, newGasPrice, newGasLimit)