主页 > 多语言仿imtoken钱包系统 > 以太坊智能合约漫游指南(一)
以太坊智能合约漫游指南(一)
我在智能合约领域工作了 4 年,主要研究比特币区块链。 我从事的一些项目包括 Proof of Existence、bitcore 和 Streamium。 上个月,我探索了在以太坊平台上的开发。
我决定为未来想要学习以太坊开发的程序员做一个简短的指南。 手册分为两部分:如何开始以太坊智能合约开发,以及智能合约安全简介。
如何开始学习以太坊智能合约
0. 基本概念
本指南假设您已经具备加密货币和区块链方面的一些基本技术背景。 如果您还没有,我建议您快速阅读 Andreas Antonopoulos 的《精通比特币》、Consensys 的《以太坊刚好够用的比特币》,或者至少看看 Scott Driscoll 的短片。 继续阅读需要了解公钥和私钥,为什么区块链需要矿工,如何实现去中心化共识,以及交易脚本和智能合约的概念。
在开始在以太坊上开发之前,您需要了解的另外两个重要的相关概念是以太坊虚拟机和气体。 以太坊的目的是成为一个智能合约平台。 它的起源可以追溯到 Vitalik Buterin 对比特币作为智能合约平台的局限性的评论。 以太坊虚拟机 (EVM) 是执行以太坊智能合约的地方。 它为编写合约提供了比比特币更具表现力和更完整的语言。 事实上,它是一种图灵完备的编程语言。 一个更好的比喻是,EVM 是一台执行智能合约的分布式世界计算机。 由于智能合约是由 EVM 执行的,因此必须有一种机制来限制每个合约占用的资源。 EVM 中运行的每一步操作实际上都是所有节点同时执行的。 这就是为什么需要存在汽油(气体)的原因。 以太坊合约代码交易可能会导致昂贵的操作,例如数据读写、密码原语、调动(发送信息到)其他合约等。 每个这样的操作都有一个 gas 计量价格,每笔交易消耗的 gas 单位需要用以太币支付,根据不断变化的 gas-ether 汇率计算。 相应的价格将从提交交易请求的以太坊账户中扣除。 同时,每笔交易可用的gas都会设置一个上限参数,以防止编程错误耗尽账户资金。 单击此处阅读有关汽油的更多信息。
1. 设置你的环境
好了,基础知识你已经知道了,我们赶紧把环境搭起来,开始写代码吧。 为了开始开发以太坊应用程序(或 dapp,分散应用程序的缩写,很多人喜欢这样称呼它)以太坊交易所app教程,您需要安装一个客户端来访问主网。 它将成为您进入这个分布式网络的窗口,提供一种观察区块链的方式,其中显示了所有 EVM(以太坊虚拟机)状态。 有许多子句兼容的客户端,最流行的是用 Go 语言实现的 geth。 但它并不是对开发人员最友好的客户端。 到目前为止,我发现的最佳选择是 testrpc 节点(是的,这个名字很糟糕)。 相信我,它会为你节省很多时间。 要安装它,请运行它:
$ sudo npm install -g ethereumjs-testrpc
$ testrpc
您应该在新终端中运行“testrpc”并在开发时保持运行。 每次运行 testrpc 时,它都会生成 10 个包含模拟测试资金的新地址供您使用。 这不是真钱,您可以安全地用这些钱进行任何实验而不会损失您的资金。 在以太坊中编写智能合约最流行的语言是 Solidity,因此我们将使用该语言。 我们还将使用 Truffle 开发框架,这将有助于创建智能合约、编译、部署和测试。 开始吧:
# First, let's install truffle
首先,让我们安装truffle
$ sudo npm install -g truffle# let's setup our project
$ mkdir solidity-experiments
$ cd solidity-experiments/
$ truffle init
Truffle 将生成演示项目所需的文件,包括 MetaCoin,一个代币合约的例子。 您应该能够通过运行 truffle 编译命令来编译示例合约。 然后,您需要使用'truffle migrate'命令通过我们正在运行的testrpc节点将合约部署到模拟网络上。
Compiling ConvertLib.sol...
Compiling MetaCoin.sol...
Compiling Migrations.sol...
Writing artifacts to ./build/contracts$ truffle migrate
Running migration: 1_initial_migration.js
Deploying Migrations...
Migrations: 0x78102b69114dbb846200a6a55c2fce8b16f61a5d
Saving successful migration to network...
Saving artifacts...
Running migration: 2_deploy_contracts.js
Deploying ConvertLib...
ConvertLib: 0xaa708272521f972b9ceced7e4b0dae92c77a49ad
Linking ConvertLib to MetaCoin
Deploying MetaCoin...
MetaCoin: 0xdd14d0691ca607d9a38f303501c5b0cf6c843fa1
Saving successful migration to network...
Saving artifacts...Note to Mac OS X users: Truffle is sometimes confused by .DS_Store files. If you get an error mentioning one of those files, just delete it.
我们刚刚将演示合约部署到测试节点。 哇! 简单吧? 是时候编写我们自己的合同了!
2. 编写你的第一个以太坊智能合约
在本教程中,我们将编写一个仅存在证明合约。 它是为了创建一种电子公正性,存储用于证明存在的文件的哈希值。 从“truffle create:contract”开始:
$ truffle create:contract ProofOfExistence1
从你的编译器打开 contract/ProofOfExistnece1.sol(我使用带 Solidity 语法高亮的 vim)
// Proof of Existence contract, version 1
contract ProofOfExistence1 {
// state
bytes32 public proof; // calculate and store the proof for a document
// *transactional function*
function notarize(string document) {
proof = calculateProof(document);
}// helper function to get a document's sha256
// *read-only function*
function calculateProof(string document) constant returns (bytes32) {
return sha256(document);
}
}
我们将从一段简单但有缺陷的代码开始,然后逐步接近更好的解决方案。 这是一个 Solidity 合约定义,有点像其他语言中的类。 合约中有状态和功能。 区分合同中可能出现的两种功能很重要。
我们的合同具有这些功能中的每一个以太坊交易所app教程,在评论中标记。 在下一段中,我们将看到我们使用的函数类型如何改变我们与智能合约交互的方式。 这个简单版本一次只存储一个证明,使用数据类型 bytes32 或 32bytes,其大小与 sha256 哈希相同。 交易功能“公证”允许我们将文件的哈希值存储在合约的状态变量“证明”中。 这个变量是一个公共变量,它是我们合约的用户验证一个文件是否公平的唯一途径。 我们稍后会自己做,但首先。 . .
让我们将 ProofOfExistence1 部署到网络上! 这一次,您需要通过编辑迁移文件 (migrations/2_deploy_contracts.js) 来告诉 Truffle 部署我们的新合约。 将内容替换为以下内容:
/*
* migrations/2_deploy_contracts.js:
*/
module.exports = function(deployer) {
deployer.deploy(ConvertLib);
deployer.autolink();
deployer.deploy(MetaCoin);
// add this line
deployer.deploy(ProofOfExistence1);
};
您也可以选择删除关于 ConvertLib 和 MetaCoin 的声明,我们将不再使用它们。 为了再次运行移动,您需要使用重新启动选项卡以确保它再次运行。
truffle migrate --reset
可以在此处找到有关 Truffle 移动工作原理的更多信息。
3. 与您的智能合约互动
现在我们已经部署了智能合约,让我们摆弄一下吧! 我们可以通过函数调用向它发送消息或读取其公共状态。 我们通过 Truffle 控制台执行此操作:
$ truffle console
// get the deployed version of our contract
truffle(default)> var poe = ProofOfExistence1.deployed()// and print its address
truffle(default)> console.log(poe.address)
0x3d3bce79cccc331e9e095e8985def13651a86004// let's register our first "document"
truffle(default)> poe.notarize('An amazing idea')
Promise { }// let's now get the proof for that document
truffle(default)> poe.calculateProof('An amazing idea').then(console.log)
Promise { }
0xa3287ff8d1abde95498962c4e1dd2f50a9f75bd8810bd591a64a387b93580ee7// To check if the contract's state was correctly changed:
truffle(default)> poe.proof().then(console.log)
0xa3287ff8d1abde95498962c4e1dd2f50a9f75bd8810bd591a64a387b93580ee7
// The hash matches the one we previously calculated
请注意,所有函数调用都会返回一个 Promise,当 Promise 被解析时,如果我们想检查它,我们可以通过 '.then(console.log)' 输出它。
我们做的第一件事是获取已部署合约的表达式并将其存储在名为“poe”的变量中。
然后我们将交易功能称为“公证”,它涉及状态更改。 当我们调用交易函数时,我们得到的是一个转换为交易 id 的 Promise,而不是函数返回的值。 请记住,为了改变 EVM 状态,我们需要消耗 gas 并向网络提交交易。 这就是为什么我们从更改状态的交易中获得交易 ID 作为 Promise 的结果。 在这里,我们对交易 ID 不感兴趣,所以我们可以放弃 Promise。 但是当我们真正编写应用程序时,我们会想要保存它以检查相应的事务并捕获错误。
接下来,我们调用只读(常量)函数“calculateProof”。 请记住使用“constant”关键字标记您的只读函数,否则 Truffle 将尝试创建一个事务来执行此函数。 这是我们告诉 Truffle 我们没有与区块链交互而只是阅读它的地方。 通过这个只读函数,我们将得到'An amazing idea'文件的sha256。
我们现在需要将其与智能合约的状态进行比较。 为了检查状态更改是否正确,我们需要读取公共状态变量“Proof”。 为了获取公共状态变量的值,我们调用一个具有相同名称的函数,该函数返回一个 Promise。 这一次,输出哈希是一致的,所以一切都按预期工作:)
正如您从上面的代码片段中看到的,我们的第一个版本的存在证明智能合约似乎有效! 做得好! 但它一次只能注册一个文件。 让我们做一个更好的版本。
翻译:洞爷