close

探索以太经典的奥秘-如何在以太经典上建立智能合约

微信截图_20181112181352

本文来源于Medium,作者:Yaz Khoury

文章翻译:ETC亚太社区  转载请注明出处

原文链接:https://medium.com/ethereum-classic/adventures-in-classical-ether-38d576a9bdff

【此篇内附代码,文章较长,请耐心阅读】

我初遇以太坊是在它刚刚上线几周后,从那时起我便对区块链上智能合约的概念产生了浓厚的兴趣。我觉得构建智能合约的过程是十分有趣的,利用去中心化的应用程序会使我们的生活更加便利。

自从The DAO事件过后,我开始关注以太经典并在分叉后选择支持它,我一直坚信着区块链的“不可变更”原则是更具价值的。因此我成为了以太经典社区的一员。

为了更好地理解智能合约是如何在以太经典平台上运作的,我将尝试建立一个智能合约。在这里,我选择着手建立一个简单的商标注册智能合约。它的目的在于帮助用户检索已注册的商标,并查看谁注册了该商标,同时还可以在商标未被注册的情况下注册新的商标。

我想我说的应该很明白了,让我们开始吧!

小贴士:本指南假设您对区块链和EVM上的智能合约有一些基本了解。如果想要了解更多基础知识,请持续关注公众号后续文章。

关于本地设置,我选择使用Truffle套件。它可以支持在终端模拟器上进行智能合约的本地测试、部署及调试。除此之外,我们还需要一个客户端来连接网络。为简单起见,我们将使用ganache-cli 

首先,我们必须安装ganache并运行它:

$ npm install -g ganache-cli

$ ganache-cli

当你运行时ganache-cli,它将在本地运行以太坊客户端,这有助于更快地构建以太坊应用程序。

ganache-cli在一个终端窗口中持续运行。请记录它在终端窗口中连接的端口和主机:

Listening on 127.0.0.1:8545
net_version
eth_accounts

很好,现在我们已经有了一个在本地运行的以太坊客户端!接下来,让我们构建我们的项目环境。我们首先创建一个目录并初始化truffle:

$ npm install -g truffle
$ mkdir trademark-contract && cd trademark-contract
$ truffle init

现在我们已经在项目中成功建立了一个truffle启动项。接下来我们需要通过验证确保truffle项目可以配合正在运行的ganache客户端。你可以使用自己喜欢的IDE或文本编辑器进行编码,我将在这里使用vim。

$ vim truffle.js

使用以下代码替换文件中的所有内容:

module.exports = {
   networks: {
       development: {
           host: “localhost”,
           port: 8545,
           network_id: “*”,
       }
    }
};

这段代码中指定的端口和主机正是之前在运行ganache-cli时所记录的。

我们将通过运行以下代码来测试它是否正常工作:

$ truffle console
truffle(development)>

如果有效,你会在终端上看到truffle(development)>。输入  .exit以退出truffle开发控制台。

现在我们的环境已经构建完成,让我们开始构建我们的智能合约!

对于这个项目,我们将在Solidity中编写智能合约,这是智能合约的通用语言。

小贴士:对于部署到ETC,我们只能使用Solidity 0.4.2以下版本进行编译 。当你安装Truffle时,它会安装最新的Solidity版本,我们将无法将其部署到ETC。为简单起见,我将演示如何在Truffle中编写和测试我们的智能合约,然后修改Solidity的版本并将其部署到ETC区块链上。

对于我们的智能合约种类,我们希望建立一个简单的商标注册合约。该智能合约的作用为检索查看商标是否已注册,注册登记未重复的商标信息,并能查看已注册商标的相关信息。

此智能合约的代码可在此GitHub存储库中找到。https://github.com/YazzyYaz/trademark-contract/blob/master/contracts/TrademarkRegistration.sol

我们首先写出Solidity智能合约版本:

pragma solidity ^0.4.19;

注意:在这里,我们通过添加^指定一个0.4.19或更高的Solidity版本,以便Truffle用其更高版本进行编译。当稍后在以太经典上编译智能合约代码时,我们需要删除^的内容。

然后我们为智能合约添加框架代码:

contract TradeMarkRegistration {}

太好了,到目前为止我们有一份空的智能合约。现在让我们考虑一下想要在其中构建的内容。我们需要建立一个关于商标的结构struct,其中包括名称描述phrase、作者authorName、时间timestamp和证明proof

我们可以将它们编译成:

struct TradeMark {
   string phrase;
   string authorName;
   uint256 timestamp;
   bytes32 proof;
}

然后,我们需要为验证商标是否存在的证明构建映射。同时我们还需要为它在商标结构中构建一个映射。此外我们需要添加两个功能,一个用于检查商标是否在我们的映射中注册,另一个用于为我们的语句生成证明。对于验证功能,我们将简单地使用sha256哈希生成器。

mapping (bytes32 => bool) private trademarkLookup;
mapping (bytes32 => TradeMark) public trademarkRegistry;

function checkTradeMark(string phrase) constant returns (bool) {
   bytes32 proof = phraseProof(phrase);
   return trademarkLookup[proof];

}

function phraseProof(string phrase) constant returns (bytes32) {
   return sha256(phrase);
}

这里的功能很简单。首先用checkTradeMark生成一个商标语段证明并传输,然后查看它是否存储在trademarkLookup映射中并返回一个布尔值。通过phraseProof 使用sha256散列函数。

另外,请注意在函数中返还附近的constant。这意味着该函数不应该改变区块链或合约的状态(并且根本不使用gas),而只是执行静态的简单任务,如生成哈希值或执行简单查找。

现在,让我们建立商标注册功能:

function registerTradeMark(string document, string author)
returns (bool) {
 if (checkTradeMark(document) == false) {
    bytes32 proofHash = phraseProof(document);
    TradeMark memory trademark = TradeMark({
      phrase: document,
      authorName: author,
      timestamp: now,
      proof: proofHash
    });
    trademarkLookup[proofHash] = true;
    trademarkRegistry[proofHash] = trademark;
    return true;
 }
 return false;
}

该函数只能简单的获取注册商标的数据,并向我们构建的结构中返回数据。

我们已经完成了智能合约。现在,让我们编译并部署它。

在终端中,我们从索引内部运行:

$ truffle compile
Compiling TradeMarkRegistration.sol…
Compiling Migrations.sol…
Writing artifacts to ./build/contracts

如果你在编译时看到一堆警告弹出,可以暂时忽略它们。

现在,让我们转移智能合约:

$ truffle migrate
Using network ‘development’.
Running migration: 1_initial_migration.js
 Deploying Migrations…
 … 0x67927682a4f832b72fbce053fc90f55249f41c4ae50af65ef537e134ca4fc43c
 Migrations: 0xc85fa4542d77675b4e05253456cbd3d579f5e4de
 Deploying TrademarkRegistration…
 … 0x26ac51700167a9ed91ced3f21f54c6ec4d5250cce8e9f647229903a9f15aea52
 TrademarkRegistration: 0x2552fd4d9736ab3e147deb7e87b82758c87a3aa6
Saving successful migration to network…
 … 0x1430e29094b1281ee0468b6132fa2b14e88c017239831aa10cd56e3233444e6b
Saving artifacts…
Running migration: 2_deploy_contracts.js
 Replacing TrademarkRegistration…
 … 0x671942c306680d3d788852f8797a5521c8558057e19d9a948d0d9c1b711e1ddd
 TrademarkRegistration: 0x50c74ff65ccd8a12c8e4757a3268671ec67918cf
Saving successful migration to network…
 … 0xaecd9a087edf24b70c1a1963e00ffded813b4244bae5383203422e9f1e46fd45
Saving artifacts…

很好,我们已经将智能合约部署到我们本地的客户端。现在,让我们与它进行交互,看看它是否按预期工作。

$ truffle console
truffle(development)>

我们将通过创建引用其地址的var来调用我们的智能合约:

truffle(development)> var trademark = TrademarkRegistration.at(TrademarkRegistration.address)
undefined
truffle(development)> trademark.address
‘0x50c74ff65ccd8a12c8e4757a3268671ec67918cf’

很好,我们获取了智能合约的地址。现在,我们将调用这些函数并测试一个商标用语。

我在这个例子中的商标是:“ETC Take My Energy”,编撰者是“ETC Commuity”。

我们先调用checkTradeMark函数:

truffle(development)> trademark.checkTradeMark(“ETC Take My Energy”)
false

它返回的结果为False,毕竟我们还没注册过这个商标。让我们继续接下来的步骤:

truffle(development)> trademark.registerTradeMark(“ETC Take My Energy”, “ETC Community”)
{ tx: ‘0x58ced570617bea3b210a7a914f749777e1f95c4c212551ca54a2cb0617f88895’,
 receipt:
  { transactionHash: ‘0x58ced570617bea3b210a7a914f749777e1f95c4c212551ca54a2cb0617f88895’,
    transactionIndex: 0,
    blockHash: ‘0x26cadc9a227dd7edea0b1ed72dfdcfa3b99e9c409cbc4c14d5a3fd451084b972’,
    blockNumber: 6,
    gasUsed: 129690,
    cumulativeGasUsed: 129690,
    contractAddress: null,
    logs: [],
    status: ‘0x1’,
    logsBloom: ‘0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000’ },
 logs: [] }

因为我们调用的registerTradeMark使用gas来注册商标,所以它会在我们的控制台上产生交易输出,就像在生产区块链上使用gas一样。

现在,让我们测试我们的商标是否已注册:

truffle(development)> trademark.checkTradeMark(“ETC Take My Energy”)
true

它现在显示为已注册。如果我们想要获取有关商标注册的数据怎么办?我们将使用getTradeMarkData功能:

truffle(development)> trademark.getTradeMarkData(“ETC Take My Energy”)
[  ‘ETC Take My Energy’,
   ‘ETC Community’,
   { [String: ‘1536767522’] s: 1, e: 9, c: [ 1536767522 ] },
 ‘0xf162b3f6c83d920f6ec6ee44bbede159c4c384c3efe1ad58ca209ad3441dbb26’ ]

这返还给我们的语句代表了的商标名、作者、时间戳和语句证明。好的,功能实现了!

现在,让我们为ETC重新编译这份智能合约。

还记得之前我提到ETC只可以运行低于Solidity 0.4.2以下版本的合约吗?我们将智能合约文件开头的代码更改为:

pragma solidity 0.4.19;

这说明我们只想用这个版本编译,而不是更高版本(通过省略^)

好的,现在我们需要转到这个Web IDE,以获得一个简单的Solidity编译工具。

https://ethereum.github.io/browser-solidity/#optimize=false&version=soljson-v0.4.25+commit.59dbf8f1.js

在这里的浏览器中,我们将在此处粘贴我们的代码:

在右侧,我们点击Settings并从Solidity version下拉列表中选择0.4.19+commit.c4cbbb05,如下所示:

这样设置后站点将知道我们将使用哪个编译器来编译智能合约。然后我们点击编译开始操作:

编译完成后,单击Details按钮。弹出窗口将显示我们需要的相关信息。我们需要两件事,即生成的字节码和ABI JSON代码。

对于字节码,我们需要复制粘贴“object”键内的内容。然后我们继续到MyCrypto进行部署。

注意:由于我们将部署到我们的ETC区块链,我将假设你已经拥有一个储存了ETC的ETC钱包并且已经使用过MyCrypto。

点击Contracts,再选择Deploy。将字节码复制粘贴到文本区域中,如下所示:

然后,点击Deploy Contract按钮进行部署。它会要求签名,你可以通过硬钱包或私钥进行签名。请注意,部署也会耗费gas费用,因此请确保钱包中有ETC,再进行部署。

部署完成后,你将看到如下所示的交易和合同地址:

请务必复制粘贴地址,因为你需要它来与智能合约进行交互。

至此为止,你已经成功在以太经典区块链上部署了这个智能合约!

让我们尝试在以太经典链上的智能合约进行商标注册。

返回MyCrypto-> Contracts。选择“Interact”选项。

在该分页中,你需要填写一些选项。首先是合同地址,这里的合约地址你可以直接粘贴之前部署智能合约存下的地址。

然后,你需要将我们之前提过的ABI JSON复制粘贴到文本区域。ABI JSON提供了一个简单的界面,可用于与智能合约进行交互。当我们编译合约时,它是在solidity-browser步骤中生成的。你可以在此处选择复制按钮进行复制:

继续将其粘贴到文本区域中,如下所示:

现在,当你单击时Access,它将生成一个界面供你与智能合约进行交互,如下所示:

如果我们从下拉列表中选择checkTradeMark,我们可以在phrase string中查看我们的商标。输入“ETC Take My Energy”并查看它返回的内容:

如果我们尚未在我们的ETC链上注册该商标,它就会返回false。

现在开始注册。从下拉列表中选择registerTradeMark,并填写为“ETC Take My Energy”,作者为“ETC Community”,如下所示:

现在,我们编写命令,提示我们签署交易。完成后(使用私钥或硬钱包),你将能够发送交易。交易完成后,你可以在gas跟踪器上看到它,并知道何时确认。一旦确认,我们可以返回MyCrypto并检查我们的商标是否已注册。

使用该功能checkTradeMark,我们看看它是否已注册:

它返回true!恭喜,你刚刚在ETC链上注册了你的第一个商标!

现在,让我们使用getTradeMarkData以下方法获取有关我们商标的数据:

好了,我们可以看到authorName,timestampproof

棒极了。我们可以通过在Web应用程序上构建友好界面来进一步扩展此智能合约。希望你喜欢这份指南。

更多资讯   敬请关注

Tags : featured