以太坊私有链搭建节点集群 到 简单helloworld智能合约编写 操作流程
Go-ethereum客户端通常被称为Geth,它是个命令行界面,执行在Go上实现的完整以太坊节点。Geth得益于Go语言的多平台特性,支持在多个平台上使用(比如Windows、Linux、Mac)。Geth是以太坊协议的具体落地实现,通过Geth,你可以实现以太坊的各种功能,如账户的新建编辑删除,开启挖矿,ether币的转移,智能合约的部署和执行等等。所以,我们选择 geth工具来进行开发。Mac 中安装geth如下:brew tap ethereum/ethereum brew install ethereum检查是否安装成功:geth --help如果输出一些帮助命令,则安装成功。
2.搭建私有链
以太坊支持自定义创世区块,要运行私有链,我们就需要定义自己的创世区块,创世区块信息写在一个json格式的配置文件中。json文件内容如下:{ "config": { "chainId": 10, "homesteadBlock": 0, "eip155Block": 0, "eip158Block": 0 }, "alloc" : {}, "coinbase" : "0x0000000000000000000000000000000000000000", "difficulty" : "0x20000", "extraData" : "", "gasLimit" : "0x2fefd8", "nonce" : "0x0000000000000042", "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000", "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", "timestamp" : "0x00" }
2.1初始化:写入创世区块
准备好创世区块json配置文件后,需要初始化区块链,将上面的创世区块信息写入到区块链中。首先要新建一个目录data0用来存放区块链数据(其实,这个目录data0就相当于一个根节点。当我们基于genesis.json生成根节点后,其他人就可以来连接此根节点,从而能进行交易)。data0目录结构如图所示: 接下来进入privatechain目录中,执行初始化命令:cd privatechain geth --datadir data0 init genesis.json上面的命令的主体是 geth init,表示初始化区块链,命令可以带有选项和参数,其中–datadir选项后面跟一个目录名,这里为 data0,表示指定数据存放目录为 data0, genesis.json是init命令的参数。运行上面的命令,会读取genesis.json文件,根据其中的内容,将创世区块写入到区块链中。如果看到log信息中含有Successfully wrote genesis state字样,说明初始化成功。初始化成功后的目录如下: 其中geth/chaindata中存放的是区块数据,keystore中存放的是账户数据。
2.2启动私有链节点
初始化完成后,就有了一条自己的私有链,之后就可以启动自己的私有链节点并做一些操作,在终端中输入以下命令即可启动节点:geth --datadir data0 --networkid 1008 console上面命令的主体是geth console,表示启动节点并进入交互式控制台,–datadir选项指定使用data0作为数据目录,–networkid选项后面跟一个数字,这里是1008,表示指定这个私有链的网络id为1008。网络id在连接到其他节点的时候会用到,以太坊公网的网络id是1,为了不与公有链网络冲突,运行私有链节点的时候要指定自己的网络id。运行上面的命令后,就启动了区块链节点并进入了Javascript Console: 这是一个交互式的Javascript执行环境,在这里面可以执行Javascript代码,其中>是命令提示符。在这个环境里也内置了一些用来操作以太坊的Javascript对象,可以直接使用这些对象。这些对象主要包括:eth:包含一些跟操作区块链相关的方法 net:包含以下查看p2p网络状态的方法 admin:包含一些与管理节点相关的方法 miner:包含启动&停止挖矿的一些方法 personal:主要包含一些管理账户的方法 txpool:包含一些查看交易内存池的方法 web3:包含了以上对象,还包含一些单位换算的方法
2.3 Javascript Console
进入以太坊Javascript Console后,就可以使用里面的内置对象做一些操作,这些内置对象提供的功能很丰富,比如查看区块和交易、创建账户、挖矿、发送交易、部署智能合约等。接下来介绍几个常用功能,下面的操作中,前面带>的表示在Javascript Console中执行的命令。
创建账户
前面只是搭建了私有链,并没有自己的账户,可以在js console中输入eth.accounts来验证:> eth.accounts []此时没有账户,接下来使用personal对象来创建一个账户:> personal.newAccount() > Passphrase: > Repeat passphrase: "0x67346d5619ae5747eb69629c8b1c8cbae71111c3"Passphrase其实就是密码的意思,输入两次密码后,就创建了一个账户。再次执行命令:> personal.newAccount() > Passphrase: > Repeat passphrase: "0xa48dba91281ee727c2424c85400f51f7a22716de"这时候再去看账户,就有两个了。> eth.accounts ["0x67346d5619ae5747eb69629c8b1c8cbae71111c3", "0xa48dba91281ee727c2424c85400f51f7a22716de"]账户默认会保存在数据目录的keystore文件夹中。查看目录结构,发现data0/keystore中多了两个文件,这两个文件就对应刚才创建的两个账户,这是json格式的文本文件,可以打开查看,里面存的是私钥经过密码加密后的信息。
查看账户余额
> eth.getBalance(eth.accounts[0]) 0 > eth.getBalance(eth.accounts[1]) 0
启动、停止挖矿
> miner.start(10)其中start的参数表示挖矿使用的线程数。第一次启动挖矿会先生成挖矿所需的DAG文件,这个过程有点慢,等进度达到100%后,就会开始挖矿,此时屏幕会被挖矿信息刷屏。如果想停止挖矿,并且进度已经达到100%之后,可以在js console中输入> miner.stop()挖到一个区块会奖励5个以太币,挖矿所得的奖励会进入矿工的账户,这个账户叫做coinbase,默认情况下coinbase是本地账户中的第一个账户:> eth.coinbase "0x67346d5619ae5747eb69629c8b1c8cbae71111c3"getBalance()返回值的单位是wei,wei是以太币的最小单位,1个以太币=10的18次方个wei。要查看有多少个以太币,可以用web3.fromWei()将返回值换算成以太币:> web3.fromWei(eth.getBalance(eth.accounts[0]),'ether')
发送一笔交易
> eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[1],value:amount})这里报错了,原因是账户每隔一段时间就会被锁住,要发送交易,必须先解锁账户,由于我们要从账户0发送交易,所以要解锁账户0:> personal.unlockAccount(eth.accounts[0])输入创建账户时设置的密码,就可以成功解锁账户。然后再发送交易。我们去查看账户1中的余额,发现还没转过去,此时交易已经提交到区块链,但还未被处理,这可以通过查看txpool来验证:> txpool.status { pending: 1, queued: 0 }其中有一条pending的交易,pending表示已提交但还未被处理的交易。要使交易被处理,必须要挖矿。这里我们启动挖矿,然后等待挖到一个区块之后就停止挖矿:> miner.start(1);admin.sleepBlocks(1);miner.stop();当miner.stop()返回true后,txpool中pending的交易数量应该为0了,说明交易已经被处理了,而账户1应该收到币了:> web3.fromWei(eth.getBalance(eth.accounts[1]),'ether') 10
查看交易
eth对象封装了查看交易和区块信息的方法。查看当前区块总数:> eth.blockNumber3.建立节点集群
在私有网络中建立多个节点组成的集群,并互相发现,产生交易。
如果是为了在本地网络运行多个以太坊节点的实例,必须确保一下几点:
1. 每个实例都有独立的数据目录(--datadir)
2. 每个实例运行都有独立的端口.(eth和rpc两者都是)(--port 和 --rpcprot)
3. 在集群的情况下, 实例之间都必须要知道彼此.
4. 唯一的ipc通信端点,或者禁用ipc.
在这里,我们选择在不同的电脑上分别建立节点组成集群,互相发现,产生交易。
在第一台电脑上启动节点
geth --datadir data0 --networkid 1008 console在第二台电脑上初始化并启动节点,注意网络ID要相同,确保节点都在一个私有网络中。
geth --datadir ./data/01 init ./genesis.json 初始化 注意和第一个节点使用相同的创始快json文件
geth --datadir data0 --networkid 1008 --bootnodes "enode://b86d51f0737672b80c9000caa706955b2a94286f8593774aab40c86cbb4fc871ce6853172871eef24bced4e6fa4576fb9d8fadfd0893b3f0873eddb9eb2072f2@192.168.6.150:30303" consolebootnodes后边的参数是第一台电脑上节点的enode url 可以在第一台电脑上通过>admin.nodeInfo.enode
来获取。
@192.168.6.150:30303 是第一台电脑的IP地址:192.168.150 以及ports:30303本节点的ports可以通过
admin.nodeInfo来获取。
至此两个节点应该就链接成功了。
3.1节点间发送以太币
> eth.sendTransaction({from: "0x5fba50fce50baf0b8a7314200ba46336958ac97e", to: "0x0a8c35653d8b229c16f0c9ce6f63cffb877cfdcf", value: web3.toWei(1, "ether")})
from中填当前节点的账号地址,to中填要发送给的节点的账号地址。
执行以上命令发送一个以太币。注意发送交易操作前要先解锁账号:
> personal.unlockAccount(eth.accounts[0], "passwoed")然后执行挖矿太能让交易生效。
> miner.start()
4.编写helloworld智能合约
让我们开始你的第一个严肃的合约。前沿是一个很大的开放领土,有时候你可能会感到孤独,所以我们的第一步就是创造一个自动伴侣,在你感到孤独时迎接你。我们会称他为“Greeter”。Greeter是一个智能数字化实体,它存在于区块链中,并能够根据其输入与任何与之交互的人进行对话。它可能不是一个说话者,但它是一个很好的倾听者。这是它的代码:
contract Mortal { /* Define variable owner of the type address */ address owner; /* This function is executed at initialization and sets the owner of the contract */ function Mortal() { owner = msg.sender; } /* Function to recover the funds on the contract */ function kill() { if (msg.sender == owner) selfdestruct(owner); } } contract Greeter is Mortal { /* Define variable greeting of the type string */ string greeting; /* This runs when the contract is executed */ function Greeter(string _greeting) public { greeting = _greeting; } /* Main function */ function greet() constant returns (string) { return greeting; } }你会注意到这个代码中有两个不同的合约:“Mortal”和“Greeter”。这是因为Solidity(我们使用的高级合同语言)具有继承性,这意味着一个合约可以继承另一个合约的特征。这对简化编码非常有用,因为合约的通用特征不需要每次重写,并且所有合约都可以用更小,更易读的块编写。所以通过只声明Greeter是Mortal的,你就继承了来自“Mortal”合约的所有特征,并使Greeter代码简单易读。
继承特征的“Mortal”仅仅意味着Greeter合同可以被其所有者杀死,以清理区块链并在不再需要合同时收回锁定在其中的资金。以太坊中的契约默认为不朽,并且没有所有者,这意味着一旦部署,作者就没有特殊的特权了。部署前请考虑这一点。
在部署合同前,需要准备两样东西:
1.编译后的代码。
2.应用程序二进制接口(ABI),它是一个定义如何与合约进行交互的JavaScript对象
我们可以通过使用Solidity编译器来获得这两者。(在线编译器remix的地址:点击打开链接)
4.1获得编译后的代码
将源代码(位于本页顶部)复制到Remix,它应该自动编译您的代码。 您可以放心地忽略右侧任何黄色警告框。
要访问已编译的代码,请确保右窗格中的下拉菜单已选中Greeter。 然后直接点击下拉菜单右边的details按钮。 在弹出窗口中,向下滚动并复制WEB3DEPLOY文本框中的所有代码。
在计算机上创建一个临时文本文件并粘贴该代码。 确保将第一行更改为如下所示:
var _greeting = "Hello World!"现在,可以将结果文本粘贴到geth窗口中,或者使用loadScript(“yourFilename.js”)导入文件。
然后执行挖矿。
等待一会终端中会看到类似这样的消息:
您可能必须先使用您在开始时选择的密码来“解锁”发送交易的帐户,因为您需要支付部署合同的GAS费用。
personal.unlockAccount(web3.eth.accounts [0],“yourPassword”)您可以使用以下命令来验证已部署的代码(将被编译):
eth.getCode(greeter.address)如果它返回“0x”以外的任何内容,那么恭喜! 你的小家伙活着! 如果再次创建合同(通过执行另一个eth.sendTransaction),它将发布到新地址。
4.2 执行Greeter
为了召唤你的机器人,只需在终端上输入以下命令:
greeter.greet();由于这个调用没引起在区块链上的任何变化,因此它会立即返回并且无需任何燃气费用。 你应该看到它返回你的问候语:
'Hello World!'
4.3 让其他人与您的代码交互
为了让其他人来执行你的合同,他们需要两个东西:1.合同所在地址
2. ABI(应用程序二进制接口),这是一种用户手册,描述合同功能的名称以及如何将它们调用到您的JavaScript控制台
想要获取地址,请运行以下命令:
greeter.address;得到类似下图的一个合约地址:
为了得到ABI,您需要直接从Remix复制ABI,类似于复制WEB3DEPLOY编译代码的方式。 在右侧窗格中,单击详细信息按钮并向下滚动到ABI文本框。 点击复制按钮复制整个ABI,然后将其粘贴到临时文本文档中。
然后,您可以实例化一个可用于在连接到网络的任何计算机上调用合同的JavaScript对象。 在以下行中,替换ABI(一个数组)和Address(一个字符串)以在JavaScript中创建合同对象:
var greeter = eth.contract(ABI).at(Address);这样别的节点就也可以通过
greeter.greet();调用你的机器人了。结果显示:
'Hello World!'
阅读更多
- 以太坊构建节点集群流程,多节点智能合约,常见错误及处理手段
- 搭建以太坊私有链和部署智能合约开发环境
- 以太坊私有链环境下智能合约部署流程
- HBase基本原理,集群搭建和简单操作
- (转)Redis集群搭建与简单使用(最少需要 6个节点)
- 区块链-智能合约简单脚本编写方法(solidity)
- 区块链-智能合约简单脚本编写方法(solidity)
- 如何搭建以太坊私有链并且创建智能合约
- 以太坊(3):以太坊私有链环境下的智能合约的编写、编译、创建与执行
- ETH 开发环境搭建及智能合约 helloworld
- WAS集群系列(17):WAS下修改某一个配置的操作流程(单节点+集群)
- Spark1.2集群环境搭建(Standalone+HA) 4G内存5个节点
- kubernetes简单集群搭建
- Redis集群搭建与简单使用
- 分布式缓存技术redis学习系列(四)——redis高级应用(集群搭建、集群分区原理、集群操作)
- centos7下安装编译并搭建hadoop2.6.0单节点伪分布式集群
- 5节点Hadoop分布式集群搭建-超详细文档
- centos6搭建redis集群搭建(单机多节点)
- 以太坊学习(四)--搭建智能合约测试环境、开发、编译、部署
- 消息订阅发布系统Apache Kafka分布式集群环境搭建和简单测试