fde区块链(区块链教程(四):搭建私链、web3。js基础)
注:本教程为技术教程,不谈论且不涉及炒作任何数字货币
一、以太坊客户端
1。1、什么是以太坊客户端
- 以太坊客户端是一个软件应用程序,它实现以太坊规范并通过p2p网络与其他以太坊客户端进行通信。如果不同的以太坊客户端符合参考规范和标准化通信协议,则可以进行相互操作。
- 以太坊是一个开源项目,由“黄皮书”正式规范定义。除了各种以太坊改进提案之外,此正式规范还定义了以太坊客户端的标准行为。
- 因为以太坊有明确的正式规范,以太网客户端有了许多独立开发的软件实现,它们之间又可以彼此交互。
1。2、基于以太坊规范的网络
- 存在各种基于以太坊规范的网络,这些网络基本符合以太坊“黄皮书”中定义的形式规范,但它们之间可能相互也可能不相互操作。
- 这些基于以太坊的网络中有:以太坊,以太坊经典,Ella,Expanse,Ubiq,Musicoin等等。
- 虽然大多数在协议级别兼容,但这些网络通常具有特殊要求,以太坊客户端软件的维护人员、需要进行微小更改、以支持每个网络的功能或属性
1。3、太坊的多种客户端
- go-ethereum ( Go ) 官方推荐,比特币行情开发使用最多
- parity ( Rust ) 最轻便客户端,在历次以太坊网络攻击中表现卓越
- cpp-ethereum (C++)
- pyethapp (python)
- ethereumjs-lib ( javascript )
- EthereumJ / Harmony ( Java )
1。4、以太坊全节点
- 全节点是整个主链的一个副本,存储并维护链上的所有数据,并随时验证新区块的合法性。
- 区块链的健康和扩展弹性,取决于具有许多独立操作和地理上分散的全节点。每个全节点都可以帮助其他新节点获取区块数据,并提供所有交易和合约的独立验证。
- 运行全节点将耗费巨大的成本,包括硬件资源和带宽。
- 以太坊开发不需要在实时网络(主网)上运行的全节点。我们可以使用测试网络的节点来代替,也可以用本地私链,或者使用服务商提供的基于云的以太坊客户端;这些几乎都可以执行所有操作。
1。5、远程客户端和轻节点
- 远程客户端不存储区块链的本地副本或验证块和交易。这些客户端一般只提供钱包的功能,可以创建和广播交易。远程客户端可用于连接到现有网络,MetaMask 就是一个这样的客户端。
- 轻节点不保存链上的区块历史数据,只保存区块链当前的状态。轻节点可以对块和交易进行验证。
- 全节点的优缺点优点 为以太坊网络的灵活性和抗审查性提供有力支持权威地验证所有交易可以直接与公众区块链上的任何合约交互可以离线查询区块链状态(账户、合约等)可以直接把自己的合约部署到公共区块链中 缺点 需要巨大的硬件和带宽资源,而且会不断增长第一次下载往往需要几天才能完全同步必须及时维护、升级并保持在线状态以同步区块 公共测试网络节点的优缺点优点 一个testnet节点需要同步和存储更少的数据,大约10GB,具体取决于不同的网络一个testnet节点一般可以在几个小时内完成同步部署合约或进行交易只需要发送测试以太,可以从”水龙头“免费获得测试网络是公共区块链,有许多其他用户和合约运行(区别于私链) 缺点 测试网络上使用测试以太没有价值。因此无法测试交易对手的安全性,因为没有任何利害关系测试网络上的测试无法涵盖所有真实主网特性。例如:交易费用虽然是发送交易所必需的,但由于gas免费,因此 testnet上往往不会考虑。而且一般来说,测试网络不会像主网一样经常拥堵 本地私链的优缺点优点 磁盘上几乎没有数据,也不同步别的数据,是一个完全干净的环境无需获取测试以太,可以分配任意以太,也可以随时自己挖矿获得没有其他用户与合约,无外部干扰 缺点 没有其他用户意味与公链的行为不同,发送的交易并不存在空间或交易顺序的竞争除自己之外没有矿工意味着挖矿更容易预测,因此无法测试公链上发生的某些情况没有其他合约意味着必须部署要测试的所有内容,包括所有的依赖项和合约库
我们的教程主要基于本地私链的搭建,以后的交易等也主要基于我们的私链,因此以太坊客户端及私链的搭建在我们本次学习中至关重要。
jsON-RPC
- 以太坊客户端提供了API 和一组远程调用(RPC)命令,这些命令被编码为 JSON。这被称为 JSON-RPC API。本质上,JSON-RPCAPI 就是一个接口,允许我们编写的程序使用以太坊客户端作为网关,访问以太坊网络和链上数据。
- 通常,RPC 接口作为一个 HTTP 服务,端口设定为 8545。出于安全原因,默认情况下,它仅限于接受来自localhost 的连接。
- 要访问JSON-RPC API,我们可以使用编程语言编写的专用库,例如JavaScript的 web3。js。
- 或者也可以手动构建HTTP请求并发送/接收JSON编码的请求,如:
curl-XPOST-H";Content-type!application/json";--data';{";jsonrpc";!";2。0";,";method";!";web3_clientVersion";,";params";![],";id";!1}';http!//127。0。0。1!8545
二、用 Geth 搭建以太坊私链
2。1安装 go
大家首先输入go version查看自己是否配置成功go环境,若不成功参考下面博客:
go : GoLand安装及环境配置
若成功则如下图所示
2。2 安装 Geth(不建议最新版本,推荐1。9。25)
安装 Geth 有很多种方式,这里主要就 Linux 环境给出两种方法:系统包管理器(apt-get)安装和源码安装。更加推荐大家用源码安装,在整个过程中可以看到 Geth 各组件的构建步骤。
其他OS安装方法见本教程
方法一、apt-get
sudoapt-getinstallsoftware-properties-commonsudoadd-apt-repository-yppa!ethereum/ethereumsudoapt-getupdatesudoapt-getinstallethereum
方法二、源码安装
- 克隆 github 仓库我们的第一步是克隆 git 仓库,以获取源代码的副本。
gitclonehttps!//github。com/ethereum/go-ethereum。git
- 从源码构建 Geth要构建 Geth,切换到下载源代码的目录并使用 make 命令:
cdgo-ethereummakegeth
如果一切顺利,我们将看到 Go 编译器构建每个组件,直到它生成 geth 可执行文件:
build/env。shgorunbuild/ci。goinstall。/cmd/geth>;>;>;/usr/local/go/bin/goinstall-ldflags-Xmain。gitCommit=58a1e13e6dd7f52a1d5e67bee47d23fd6cfdee5c-v。/cmd/gethgithub。com/ethereum/go-ethereum/common/hexutilgithub。com/ethereum/go-ethereum/common/mathgithub。com/ethereum/go-ethereum/crypto/sha3github。com/ethereum/go-ethereum/rlpgithub。com/ethereum/go-ethereum/crypto/secp256k1github。com/ethereum/go-ethereum/common[。。。]github。com/ethereum/go-ethereum/cmd/utilsgithub。com/ethereum/go-ethereum/cmd/gethDonebuilding。Run";build/bin/geth";tolaunchgeth。
查看 geth version,确保在真正运行之前安装正常:
在这里插入图片描述
启动节点同步
安装好了 Geth,现在我们可以尝试运行一下它。执行下面的命令,geth 就会开始同步区块,并存储在当前目录下。
这里的 --syncmode fast 参数表示我们会以“快速”模式同步区块。在这种模式下,我们只会下载每个区块头和区块体,但不会执行验证所有的交易,直到所有区块同步完毕再去获取一个系统当前的状态。这样就节省了很多交易验证的时间。
geth–datadir。--syncmodefast
--datadir:后面的参数是区块数据及秘钥存放目录
通常,在同步以太坊区块链时,客户端会一开始就下载并验证每个块和每个交易,也就是说从创世区块开始。 毫无疑问,如果我们不加 --syncmode fast 参数,同步将花费很长时间并且具有很高的资源要求(它将需要更多的 RAM,如果你没有快速存储,则需要很长时间)。有些文章会把这个参数写成 --fast,这是以前快速同步模式的参数写法,现在已经被 –syncmode fast取代。如果我们想同步测试网络的区块,可以用下面的命令:
geth--testnet--datadir。--syncmodefast
--testnet 这个参数会告诉 geth 启动并连接到最新的测试网络,也就是 Ropsten。测试网络的区块和交易数量会明显少于主网,所以会更快一点。但即使是用快速模式同步测试网络,也会需要几个小时的时间
2。3 搭建自己的私有链
因为公共网络的区块数量太多,同步耗时太长,我们为了方便快速了解 Geth,可以试着用它来搭一个只属于自己的私链。首先,我们需要创建网络的“创世”(genesis)状态,这写在一个小小的 JSON 文件里(例如,我们将其命名为 genesis。json,保存到当前目录下):
{";config";!{";chainId";!15},";difficulty";!";2000";,";gasLimit";!";2100000";,";alloc";!{";7df9a875a174b3bc565e6424a0050ebc1b2d1d82";!{";balance";!";300000";},";f41c74c9ae680c1aa78f42e5647a62f353b7bdde";!{";balance";!";400000";}}}
genesis。json介绍
在这里插入图片描述
要创建一条以它作为创世块的区块链,我们可以使用下面的命令:
geth--datadir。initgenesis。json
初始化完成后目录下多了geth和keystore两个文件夹:
- geth:保存该链上的区块数据
- keystore:保存该链上的账户信息
可能遇到问题:
- Fatal! invalid genesis file! missing 0x prefix for hex data:这个错误信息意思很明白,就是你的json文件中,对于16进制数据,需要加上0x前缀
- Fatal! invalid genesis file! hex string has odd length! 从Geth 1。6版本开始,设置的十六进制数值,不能是奇数位, 比如不能是0x0,而应该是0x00。
- Fatal! failed to write genesis block! genesis has no chain configuration :这个错误信息,就是说,你的配置文件中,缺少config部分。
- Error! invalid sender! 这个错误虽然不会导致私有链初始化时出现失败的情况,但是会在以后的转账(web3。eth。sendTransaction),或者部署智能合约的时候产生。解决方法就是chainId 不能设置为0。 如果你完全按照Geth官方文档上给出的配置文件进行配置,就会产生这个错误。
在当前目录下运行 geth,就会启动这条私链,注意要将 networked 设置为与创世块配置里的chainId 一致。
//简单开启(base)haobo@haobo!~/home/mnt/bitcoin/test$geth--datadir。--networkid150--nodiscoverconsole//更一般的形式(base)haobo@haobo!~/home/mnt/bitcoin/test$geth--networkid150--datadir";。";--identity";kexin";--rpc--rpcport";8545";--rpcaddr";localhost";--port";30303";--nodiscover--allow-insecure-unlock--rpcapi";eth,net,web3,personal,admin,shh,txpool,debug,miner";console
参数含义:
在这里插入图片描述
我们可以看到节点正常启动:
在这里插入图片描述
启动完之后,就可以通过admin。nodeInfo。protocols。eth来获取到刚启动的节点的一些信息(如下),比较上文初始化的配置,相关内容是一致的。
在这里插入图片描述
恭喜!我们已经成功启动了一条自己的私链。
3、Geth 控制台命令
Geth Console 是一个交互式的 JavaScript 执行环境,其中 >; 是命令提示符,里面内置了一些用来操作以太坊的 JavaScript对象,我们可以直接调用这些对象来获取区块链上的相关信息。
这些对象主要包括:
- eth:主要包含对区块链进行访问和交互相关的方法;
- net:主要包含查看 p2p 网络状态的方法;
- admin:主要包含与管理节点相关的方法;
- miner:主要包含挖矿相关的一些方法;
- personal:包含账户管理的方法;
- txpool:包含查看交易内存池的方法;
- web3:包含以上所有对象,还包含一些通用方法。
常用命令有:
- personal。newAccount():创建账户;
- personal。unlockAccount():解锁账户;
- eth。accounts:枚举系统中的账户;
- eth。getBalance():查看账户余额,返回值的单位是 Wei(Wei 是以太坊中最小货币面额单位,类似比特币中的聪,1 ether = 10^18 Wei);
- eth。blockNumber:列出区块总数;
- eth。getTransaction():获取交易;
- eth。getBlock():获取区块;
- miner。start():开始挖矿;
- miner。stop():停止挖矿;
- web3。fromWei():Wei 换算成以太币;
- web3。toWei():以太币换算成 Wei;
- txpool。status:交易池中的状态;
- admin。addPeer():连接到其他节点
3。1 操作测试
3。1。1 创建账户
进入控制台后,可以通过使用命令来与私有链进行交互。创建一个新的账户:
>;personal。newAccount()Passphrase!Repeatpassphrase!";0xc8248c7ecbfd7c4104923275b99fafb308bbff92";
输入两遍密码后,生成账户地址。以同样的方式,可创建多个账户,查看账户:
>;eth。accounts
查看账户余额
>;eth。getBalance(eth。accounts[0])0
在这里插入图片描述
3。1。2 挖矿
启动挖矿:
>;miner。start(1)
其中 start 的参数表示挖矿使用的线程数。第一次启动挖矿会先生成挖矿所需的 DAG文件,这个过程有点慢,等进度达到 100% 后,就会开始挖矿,此时屏幕会被挖矿信息刷屏。
停止挖矿,在 控制台 中输入:
>;miner。stop()
挖到一个区块会奖励以太币,挖矿所得的奖励会进入矿工的账户,这个账户叫做 coinbase,默认情况下 coinbase 是本地账户中的第一个账户,可以通过 miner。setEtherbase() 将其他账户设置成 coinbase。
可以使用以下命令,当新区块挖出后,挖矿即可结束。
>;miner。start(1);admin。sleepBlocks(1);miner。stop();
3。1。3 交易
目前,账户 0 已经挖到了 3 个块的奖励,账户 1 的余额还是0:
>;eth。getBalance(eth。accounts[0])15000000000000000000>;eth。getBalance(eth。accounts[1])0
我们要从账户 0 向账户 1 转账,先解锁账户 0,才能发起交易:
>;personal。unlockAccount(eth。accounts[0])Unlockaccount0x3443ffb2a5ce3f4b80080791e0fde16a3fac2802Passphrase!true
发送交易,账户 0 ->; 账户 1:
>;amount=web3。toWei(5,';ether';)";5000000000000000000";>;eth。sendTransaction({from!eth。accounts[0],to!eth。accounts[1],value!amount})INFO[09-1207!38!12]Submittedtransactionfullhash=0x9f5e61f3d686f793e2df6378d1633d7a9d1df8ec8c597441e1355112d102a6cerecipient=0x02bee2a1582bbf58c42bbdfe7b8db4685d4d4c62";0x9f5e61f3d686f793e2df6378d1633d7a9d1df8ec8c597441e1355112d102a6ce";
此时如果没有挖矿,用 txpool。status 命令可以看到本地交易池中有一个待确认的交易,可以使用 eth。getBlock(";pending";, true)。transactions查看当前待确认交易。使用下面命令开始挖矿。
>;miner。start(1);admin。sleepBlocks(1);miner。stop();
新区块挖出后,挖矿结束,查看账户 1 的余额,已经收到了账户 0 的以太币:
>;web3。fromWei(eth。getBalance(eth。accounts[1]),';ether';)5
3。1。3 查看交易和区块
查看当前区块总数:
>;eth。blockNumber4
通过区块号查看区块:
>;eth。getBlock(4)
通过交易 Hash 查看交易(Hash 值包含在上面交易返回值中):
>;eth。getTransaction(";0x9f5e61f3d686f793e2df6378d1633d7a9d1df8ec8c597441e1355112d102a6ce";)
3。1。3 其他节点加入
此时,私有链已经通过该节点创建好了,如果其他节点想加入,需要通过以太坊客户端连接到该私有区块网络,并连接该网络的节点来同步区块信息。在其他主机上安装以太坊客户端Geth,通过Geth命令进入该私有区块链,注意要指定相同的网络号。
假设有两个节点:节点一和节点二,NetWorkID 都是 6666,通过下面的步骤就可以从节点一连接到节点二。
首先要知道节点二的 enode 信息,在节点二的 Geth Console 中执行下面的命令查看 enode 信息:
>;admin。nodeInfo。enode";enode!//d465bcbd5c34da7f4b8e00cbf9dd18e7e2c38fbd6642b7435f340c7d5168947ff2b822146e1dc1b07e02f7c15d5ca09249a92f1d0caa34587c9b2743172259ee@[!!]!30303";
然后在节点一的 Geth Console 中执行 admin。addPeer(),就可以连接到节点二:
>;admin。addPeer(";enode!//d465bcbd5c34da7f4b8e00cbf9dd18e7e2c38fbd6642b7435f340c7d5168947ff2b822146e1dc1b07e02f7c15d5ca09249a92f1d0caa34587c9b2743172259ee@[!!]!30303";)
addPeer() 的参数就是节点二的 enode 信息,注意要把 enode 中的 [!!] 替换成节点二的 IP 地址。连接成功后,节点二就会开始同步节点一的区块,同步完成后,任意一个节点开始挖矿,另一个节点会自动同步区块,向任意一个节点发送交易,另一个节点也会收到该笔交易。
通过 admin。peers可以查看连接到的其他节点信息,通过 net。peerCount可以查看已连接到的节点数量。
除了上面的方法,也可以在启动节点的时候指定--bootnodes选项连接到其他节点。
如果只是自己测试开发使用,建议使用dev环境,在需要在启动时增加–dev参数即可,在dev模式下会监听交易,一旦有交易发送就会打包然后挖矿确认,且默认的account[0]开发者账户初始有一大堆以太币。
3、智能合约操作
3。1、创建和编译智能合约
经过part2的学习大家已经基本上掌握了Solidity,接下来我们编写一个智能合约:
该合约包含一个方法 multiply(),将输入的两个数相乘后输出:
pragmasolidity^0。4。0;contractTestContract{functionmultiply(uinta,uintb)returns(uint){returna*b;}}
将上面的代码复制到Remix编辑器里,程序将自动完成编译。
在这里插入图片描述
点击 run 在Environment中设选择JavaScript VM, Value可设置为1,点击Deploy,则可创建该部署智能合约的交易。
因为我们要将该智能合约部署到私有链上,需要得到智能合约编译后的EVM二进制码和JSON ABI(Application Binary Interface)。将生成的交易保存到scenario。json文件,点击箭头所指按钮
在这里插入图片描述
其中38-65行为该智能合约的ABI(注意前面还有一个[符号),ABI指定了合约接口,包括可调用的合约方法、变量、事件等。
在这里插入图片描述
input`字段为合约EVM二进制码,可点击直接复制。
在Linux下可以直接使用安装好的编译器进行编。
评论