Ethereum 简明教程
Ethereum - Introduction
比特币的巨大成功引起了一些人的兴趣,让他们创建自己的货币。鉴于比特币提供的数字货币的优势,人们希望在自己的应用程序中使用 Blockchain 的概念。人们希望摆脱物理 contract,转向智能数字 contract,其中拒绝、透明度、安全性等几个问题会自动得到解决。这一努力的结果是创建了 Ethereum,一个用于创建支持智能合约的分布式 Blockchain 应用程序的流行平台。
在本教程中,您将学习如何在 Ethereum 平台上创建分布式应用程序 (DAPP)。更具体地说,您将学习如何编写 contract、在本地 Blockchain 上对其进行测试,并最终将其部署到外部 Blockchain 上进行深度测试和商业用途。您将使用 Solidity ,一种面向对象的语言,用于 contract 开发。您还将使用 Remix ,一个用于开发和测试 contract 的开源 IDE。若要将经过测试的 contract 部署到外部 Blockchain 上,您将使用 Ganache 。若要与 contract 交互,您需要一个客户端应用程序。我们将使用 MyEtherWallet 为每个这样的客户端创建一个钱包。contract 创建者将发布 contract。任何其他客户端都将使用 contract 提供的界面查看联系值,并向创建者汇款以执行 contract 的一部分。
因此,让我们首先编写 contract。
Ethereum - Smart Contracts
有若干工具可用于开发和测试 contract。最简单的工具之一位于官方的 Ethereum 网站上。该工具称为 Remix ,我们将使用此工具进行 contract 开发。
Ethereum - Solidity for Contract Writing
Solidity 是一种面向对象语言,专门用于撰写合约。这是一种高级语言,继承了 C++、Python 和 JavaScript 的特性。Solidity 编译器会将你的源代码编译成字节码,以在以太坊虚拟机 (EVM) 上运行。
要快速了解 Solidity 语法,请查看 IDE 中的示例代码。
pragma solidity >=0.4.22 <0.6.0;
contract Ballot {
第一行是对编译器的指令。第二行开始定义合约。在合约中,你可以声明变量,例如:
address chairperson;
你还可以定义诸如 Proposal 的结构,并创建这些结构项的数组。在代码窗口中 بررسی这一点。
然后,你可以定义一个在实例化合约时调用的构造函数。
constructor(uint8 _numProposals) public {
在构造函数之后,你会定义多个方法,这些方法就是合约方法。在示例合约中, giveRightToVote 就是一种具有以下语法的此类方法:
function giveRightToVote(address toVoter) public {
public 关键字使该方法可以被具有合约访问权限的任何客户端公开调用。
同样地,示例合约定义了另外三个名为 delegate, vote 和 winningProposal 的方法。针对这些方法,自己 بررسی Solidity 语法,以加深理解。这些是你撰写自己合约的先决条件。说明 Solidity 的完整语法超出了本教程的范围。
Ethereum - Developing MyContract
我们将其命名为合同 MyContract ,如下所示 −
contract MyContract {
我们将声明两个变量,如下所示 −
uint amount;
uint value;
变量 amount 将保存合同执行者发送给合同创建者的累计金额。 value 字段将保存合同价值。随着执行者的执行合同, value 领域将被修改以反映平衡的合同价值。
在合同构造函数中,我们设置了这两个变量的值。
constructor (uint initialAmount, uint initialValue) public {
amount = 0;
value = 1000;
}
最初,合同收取的金额为零,因此我们将 amount 字段设置为 0。我们将合同 value 设置为某个任意数字,在本例中为 1000。合同创建者决定此值。
若要检查任何时间点的收款,我们提供一个名为 getAmount 的公共合同方法,定义如下 −
function getAmount() public view returns(uint) {
return amount;
}
若要获得任何给定时间点的平衡合同价值,我们定义 getBalance 方法,如下所示 −
function getBalance() public view returns(uint) {
return value;
}
最后,我们编写一种合同方法 (Send) 。它允许客户向合同创建者发送一些钱 −
function send(uint newDeposit) public {
value = value - newDeposit;
amount = amount + newDeposit;
}
执行 send 方法将会修改合同的 value 和 amount 字段。
完整的合同代码如下 −
contract MyContract {
uint amount;
uint value;
constructor (uint initialAmount, uint initialValue) public {
amount = 0;
value = 1000;
}
function getBalance() public view returns(uint) {
return value;
}
function getAmount() public view returns(uint) {
return amount;
}
function send(uint newDeposit) public {
value = value - newDeposit;
amount = amount + newDeposit;
}
}
Ethereum - Compiling the Contract
一旦写好完整的合约代码,在该 IDE 中编译它就是小菜一碟。只需单击 IDE 中的 Autocompile 复选框,如下面的屏幕截图所示−
或者,您可以通过单击标题为 “Start to compile” 的按钮来编译合约。
如果有任何拼写错误,请在代码窗口中更正它。确保代码完全编译且没有错误。现在,您已准备就绪部署合约。
Ethereum - Deploying the Contract
在本章中,我们将学习如何在 Ethereum 上部署 contract。点击 Run 菜单选项以部署 contract。将出现以下屏幕。
contract 名称显示在突出显示的列表框中。在其下方,您会注意到 Deploy 按钮,单击以部署 contract。该 contract 将部署在 Remix 内置 Blockchain 上。您可以在屏幕底部看到已部署的 contract。您可以在下方屏幕截图的突出显示部分中看到这一点。
请注意,在此突出显示区域中存在三个方法名称。接下来,您将通过执行 contract 方法与 contract 进行交互。
Ethereum - Interacting with the Contract
单击已部署的合同后,您将看到合同提供的各种公共方法。这在下面的屏幕截图中显示。
第一个方法 send 在前面包含一个编辑框。在这里,您将输入合同方法所需的各个参数。其他两个方法不接受任何参数。
Sending Money
现在,在合同窗口中看到 send 函数的前面输入一些金额,例如 100。单击 send 按钮。这将执行合同 send 方法,减少合同 value 字段的值,并增加 amount 字段的值。
Ethereum - Limitations of Remix
到目前为止,您使用的 Remix IDE 足以用于您的合约的开发和初始测试。对于实际合约,您需要针对各种参数测试您的功能。Remix 无法创建真实的(非测试)用户账户,以在其之间转账。您无法控制 Remix 创建的区块链配置。您甚至无法监视交易执行。
Remix 错过了多项高级操作。因此,我们需要将合约部署到一个提供所有这些功能的更复杂的区块链上。您将在我们随后的章节中学习到其中一个名为 Ganache 的区块链。
Ethereum - Ganache for Blockchain
Ganache 用于设置个人以太坊区块链以测试您的 Solidity 合约。与 Remix 相比,它提供了更多功能。当您使用 Ganache 时,您将了解这些功能。在开始使用 Ganache 之前,您必须先在本地计算机上下载并安装区块链。
Downloading Ganache
您可以从以下 URL 下载 Ganache −
Ganache 可用于多个平台。我们在 Mac 上开发并测试了本教程。因此,下面的截图将展示 Mac 安装。当您打开上面给出的安装 URL 时,它会自动检测机器的操作系统并引导您进行合适的二进制文件安装。下面的截图显示了 Mac 安装。
当您点击下载按钮时,它将开始下载适合 Mac 安装的 DMG 文件。
Ethereum - Ganache Server Settings
单击屏幕右上角的设置图标,如下面屏幕截图所示−
服务器设置屏幕将显示如下−
在此处,您将能够设置 Ganache 服务器的服务器地址和端口号。暂时将其保留为其默认值。网络 ID 是 Ganache 服务器的内部区块链标识符;将其保留为其默认值。 Automine 按钮处于 ON 状态,表示将立即处理交易。如果您将其关闭,它将要求您输入秒数,然后会进行挖矿。
Ethereum - A Quick Walkthrough
接下来,我们简单了解一下 Ganache 桌面端有哪些功能。在桌面上方,我们有多个菜单选项,其中一些与我们直接相关。菜单栏在以下屏幕截图中突出显示了 −
单击 TRANSACTIONS 菜单,它会显示到目前为止执行的所有事务。你很快就会执行事务。现在,返回上方的屏幕,不时检查事务。典型的事务屏幕如下图所示 −
同样,当你单击 BLOCKS 菜单时,你将看到各种已开采的区块。请考虑以下屏幕截图,了解“区块”菜单的外观 −
单击 LOGS 菜单。它将为你打开系统日志。在这里,你可以检查你在以太坊区块链上执行的各种操作。
现在,你已经了解了如何使用 Ganache 设置私有以太坊区块链,你现在将创建几个将使用此区块链的客户端。
Ethereum - MyEtherWallet
对于客户端应用程序,您将使用 MyEtherWallet 。
从以下 URL 下载 MyEtherWallet 软件 −
如果需要,解压缩已下载的文件并打开 index.html 。您将看到以下用于创建新钱包的界面。
Ethereum - Creating Wallet
在本章中,我们将学习如何创建以太坊钱包。要创建一个新钱包,请输入你选择的密码,然后单击“ Create New Wallet ”按钮。当你这样做时,将创建一个钱包。数字钱包本质上是生成一对公钥/私钥,你需要将它们存储在安全的地方。钱包创建后的结果如下图所示 −
单击 “Download Keystore File (UTC / JSON)” 按钮以保存生成的密钥。现在,单击 “I understand. Continue” 按钮。你的私钥将出现在屏幕上,如下图所示 −
单击 “Print Paper Wallet” 按钮以保留钱包私钥的物理记录。以后解锁钱包时需要使用它。你将看到以下屏幕。不要丢弃此输出。
要解锁钱包,请单击 “Save Your Address” 按钮。你将看到以下屏幕。
钱包可以使用上一个屏幕中突出显示的私钥选项来解锁。从上一个屏幕截图中剪切并粘贴私钥,然后单击“解锁”按钮。你的钱包将被解锁,你将看到一条消息出现在屏幕底部。由于钱包目前不包含任何内容,所以解锁钱包对我们来说并不是很有用。
Attaching Wallet to Ganache Blockchain
您现在已经创建了一个钱包;此钱包是到 Blockchain 的客户端界面。我们将把钱包连接到您在前面的课程中已启动的 Ganache Blockchain。若要执行此操作,请单击 Network 下拉框,如下面的屏幕截图所示 −
转到列表底部。您将看到 “Add Custom Network / Node” 的选项。选择此项。
现在,将出现一个屏幕,要求输入 Ganache 服务器地址和它正在侦听的端口。
输入您的 Ganache 服务器详细信息 – http://127.0.0.1 和端口: 8545 。这些将是您在 Ganache 服务器设置中设置的值。为此节点指定您选择的 name 。单击 “Save & Use Custom Node” 按钮。您将在屏幕底部看到连接的消息。此时,您的钱包已成功连接到 Ganache Blockchain。
您现在已准备好在此连接的 Blockchain 上部署 contract。
Ethereum - Deploying Contract
要部署合约,请选择 Contracts 菜单选项,如下面的屏幕截图所示 −
您需要在此屏幕上输入合约的字节码。请记住,当您编译智能合约代码时,它将生成 EVM 上运行的字节码。现在您需要从 Remix IDE 获取此字节码。
转到 Remix IDE 界面,您先前键入的合约应在代码窗口中。如果没有,请在代码窗口中重新键入合约。点击字节码按钮,如下面屏幕截图所示 −
编译的源代码的字节码与一些其他信息一并复制到剪贴板中。将复制的代码粘贴到您喜欢的文本编辑器中。以下是文本编辑器的截图 −
object 标记的值包含所需的字节码。小心复制此字节码,确保不复制带引号的内容。字节码非常长,因此请确保一直复制到最后一个字节。现在,将此字节码粘贴到 Deploy Contract 界面中,如下所示 −
Gas Limit 字段将自动设置。
在 Gas 限制字段下方,你会找到用于访问钱包的选择。
现在,使用将要部署此合约的 Ganache 帐户的 Private Key 访问钱包。若要获取此私钥,请返回 Ganache 窗口。点击如下图中所示的第一个帐户的 keys 图标。
你会看到用户帐户 # 1 的私钥,如下图所示。
复制此私钥,并将其粘贴到“粘贴你的私钥”部分,如下图所示。
你将在屏幕底部看到 “Unlock” 按钮。解锁后,屏幕底部会显示“成功”消息。此时,你的钱包已连接到 Ganache 区块链的帐户 # 1。
现在,你可以为合约签名并部署它了。点击 “Sign Transaction” 按钮,如下图所示。
对交易签名会生成并显示 Raw 和 Signed 交易。点击 “Deploy Contract” 按钮在 Ganache 区块链上部署合约。记住,合约由 Ganache 区块链的帐户 # 1 用户部署。因此,帐户 # 1 用户成为合约创建者。在部署合约之前,系统会要求你确认交易,因为如果你要在公共的真实以太坊区块链上部署此合约,它可能会耗费一些真金白银。不必担心,对于正在你的本地机器上运行的当前私有区块链,无需支付真金白银。点击 Make transaction 按钮,如下图所示。
检查 Ganache 控制台;你会看到帐户 # 1 中的 ETH 余额已减少,如下图所示。
现在,点击 TRANSACTIONS 菜单,如下图所示。
你会看到交易详情。
在此屏幕上,你会找到合约的发布地址。地址在上图中做了标记。你将公开分发此地址,以让其他人知道你的合约可在指定的地址上,他们可以连接到该地址,并执行合约方法(例如向你 - 合约创建者 - 发送钱)。复制此合约地址以供参考,因为在下一步中你将需要它。
Ethereum - Interacting with Deployed Contract
现在,您已准备好与已部署的合约交互。回到 MyEtherWallet 桌面,然后单击“与合约交互”标签,如下图所示 −
将您先前复制的合约地址粘贴到 “Contract Address” 字段中。您还需要将 “ABI / JSON Interface” 合约粘贴到上述屏幕上。
要获取 ABI ,请转到 Remix 窗口,然后单击 ABI 按钮,如下图所示。
ABI/JSON 接口将被复制到剪贴板。将其粘贴到您喜欢的编辑器中以检查生成接口,如下所示 −
ABI / JSON Interface
[
{
"constant": false,
"inputs": [
{
"name": "newDeposit",
"type": "uint256"
}
],
"name": "send",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"name": "initialAmount",
"type": "uint256"
},
{
"name": "initialValue",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"constant": true,
"inputs": [],
"name": "getAmount",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getBalance",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
}
]
将此 JSON 粘贴到 MyEtherWallet 接口后,您会注意到 JSON 接口下方的 ACCESS 按钮现在处于激活状态,如下图所示 −
单击 Access 按钮以访问该合约。
单击 Access 按钮后,合约地址和功能选择下拉列表将出现在屏幕上,如 Remix 编辑器中所示。这在下面的截图中显示。
您可以检查合约的各种功能,就像在 Remix 部署中的情况一样。请注意,该联系方式现已部署在外部 Ganache 区块链上。检查 getAmount 函数;您将获得数量值为零,并且 getBalance 将显示余额为 1000。
现在尝试汇款。它会为您显示一个 textedit 控件,用于输入金额。编写合约时,会使用一些“gas”,并且在将其写入块链之前,系统将要求您确认该交易。该交易将在短时间内执行,具体取决于您在 Ganache 服务器上设置的挖矿时间。此后,您可以重新检查该合约的 value 和 amount 字段,以验证这些字段确实已修改。
您现在可以检查 Ganache 桌面以查看到目前为止您执行过的交易。一个示例输出如下所示 −
到目前为止,您既是合约创建者,又是合约执行者。这没有多大意义,因为您希望其他人使用您的合约。为此,我们会为我们的 Ganache 区块链创建一个新的客户端,并从新创建的帐户 2 向帐户 1 的合约创建者汇款。
Ethereum - Creating Contract Users
在本章中,我们将学习在以太坊上创建合约用户。要为我们的已发布合约创建用户,我们将创建一个 MyEtherWallet 客户端,它附加到你之前步骤中一直在使用的同一个 Ganache 区块链。转到 MyEtherWallet 屏幕并创建一个新钱包。
单击 contracts 菜单,并选择 “Interact with Contract” 选项,就像前面一样。请注意,这个新用户将仅与已发布的合约进行交互,而不会部署自己的合约。请指定你在前面使用过的合约地址和 ABI。
现在,单击 Access 按钮并调用 *send *方法。当被询问时,输入一些值,例如发送 100 ETH。提交交易。提交后,将出现以下屏幕。
要将这个新客户端附加到我们的 Ganache 区块链,请转到 Ganache 控制台。单击账户 #2 的密钥图标,如下图所示 −
你将获得账户 #2 的私钥。
复制收到的密钥并在新创建的钱包中使用它,如下所示 −
单击 Unlock 按钮以附加钱包。
当钱包成功解锁后,写下所需的发送交易。
通过单击 “Generate Transaction” 按钮生成事务。
Make 交易并等待一段时间,以便其在区块链中生效。现在,执行 “getAmount” ,则现在应显示 200 的金额。
执行 “getBalance” 。 value 字段现在应为 800。
检查交易日志,查看不同的用户执行的各种交易。