新手小白搭建以太坊私有链,实现挖矿,转账交易,合约部署,节点连接,节点间调用合约

安装环境

1.首先安装VMware和Ubuntu
安装教程连接

链接:https://pan.baidu.com/s/1D6-M3lTQbnTDGqJ-T2lHXw 
提取码:585t 
复制这段内容后打开百度网盘手机App,操作更方便哦

安装包连接

链接:https://pan.baidu.com/s/1cNKvQjymAwtPzKefuBCjkQ 
提取码:9jf9 
复制这段内容后打开百度网盘手机App,操作更方便哦

2.安装以太坊客户端
这里给出两种方式
1)PPA 直接安装
安装必要的工具包:

apt install software-properties-common

添加以太坊源

add-apt-repository -y ppa:ethereum/ethereum
apt update

安装git
安装git工具,git是一个非常优秀的免费、开源的版本管理控制工具, 我们可以使用git工具方便地下载官方(Golang、Hyperledger Fabric等等)在Github网站上发布的相关源代码或其它内容。

安装git工具使用如下命令:

sudo apt update
sudo apt install git

安装cURL
使用如下命令安装cURL:

sudo apt install curl

安装Docker
查看系统中是否已经安装Docker:
使用如下命令安装Docker的最新版本

sudo apt update
sudo apt install docker.io

查看Docker版本信息

docker --version

安装Docker-compose
确定系统中是否已安装docker-compose工具

$ docker-compose --version

如系统提示未安装,则使用如下命令安装docker-compose工具:

sudo apt install docker-compose

安装成功后,查看Docker-Compose版本信息

$ docker-compose --version

安装 go-ethereum

apt install ethereum

用geth version查一下成功了么,成功了就是这样谁的
在这里插入图片描述
2).源码安装
因为 go-ethereum 使用 Go 语言编写,编译源码前需要配置好 Go 环境。
安装go
使用wget工具下载安装包

wget https://dl.google.com/go/go1.11.linux-amd64.tar.gz

解压tar包到/usr/local

sudo tar zxvf go1.11.linux-amd64.tar.gz -C /usr/local

创建Go目录

mkdir $HOME/go

用vim打开~./bashrc,配置环境变量

vim ~/.bashrc

增加下面的环境变量,保存退出

export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin

输入如下保存退出
在这里插入图片描述

:wq

使环境变量立即生效

source ~/.bashrc

检测go是否安装好

go version

在这里插入图片描述
安装make

sudo apt install make

安装g++

sudo apt install g++

安装libltdl-dev 库

sudo apt-get install libltdl-dev

3.下载和编译 Geth
安装 C 编译器:

apt install -y build-essential

下载最新源码

git clone https://github.com/ethereum/go-ethereum

编译安装:

cd go-ethereum
make geth

用geth version查看是否成功
在这里插入图片描述
4.安装 Solidity 编译器

add-apt-repository ppa:ethereum/ethereum
apt update
apt install solc

再推荐两个浏览器IDE,挺好用的

http://remix.ethereum.org/
http://remix.hubwiz.com/

私有链搭建

一、配置初始状态
要运行以太坊私有链,需要定义自己的创世区块,创世区块信息写在一个 JSON 格式的配置文件中。首先将下面的内容保存到一个 JSON 文件中,例如 genesis.json。

{
    
    
  "config": {
    
    
    "chainId": 15665883188,
    "homesteadBlock": 0,
    "eip150Block": 0,
    "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "eip155Block": 0,
    "eip158Block": 0,
    "byzantiumBlock": 0,
    "constantinopleBlock": 0,
    "petersburgBlock": 0,
    "istanbulBlock": 0,
    "ethash": {
    
    }
  },
  "nonce": "0x0",
  "timestamp": "0x5ddf8f3e",
  "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "gasLimit": "0x47b760",
  "difficulty": "0x400",
  "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "coinbase": "0x0000000000000000000000000000000000000000",
  "alloc": {
    
     },
  "number": "0x0",
  "gasUsed": "0x0",
  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
 
chainID:指定了独立的区块链网络 ID。网络 ID 在连接到其他节点的时候会用到,以太坊公网的网络 ID 是 1,为了不与公有链网络冲突,运行私有链节点的时候要指定自己的网络 ID。不同 ID 网络的节点无法相互连接。
alloc: 用来预置账号以及账号的以太币数量,因为私有链挖矿比较容易,所以我们不需要预置有币的账号,需要的时候自己创建即可以,默认为空即可。
coinbase: 矿工的账号,随便填即可。
difficulty: 设置当前区块的难度,如果难度过大,cpu挖矿就很难,这里设置较小难度。
extraData: 附加信息。这里要注意一下,新版本该值需要为16进制数据,以0x 开头。
gasLimit: 该值设置对GAS的消耗总量限制,用来限制区块能包含的交易信息总和,因为我们要做的是私有链,所以此处填最大。
nonce: nonce就是一个64位随机数(0x后一位为4个二进制位,故有16位),用于挖矿,注意他和mixhash的设置需要满足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章节所描述的条件。
mixhash:与nonce配合用于挖矿,由上一个区块的一部分生成的hash。注意他和nonce的设置需要满足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章节所描述的条件。
parentHash: 上一个区块的hash值,因为是创世块,所以这个值是0。
timestamp: 设置创世块的时间戳。

这里有一点需要注意,就是chainId,这个建议写的少见一点,如果和别人重复的话,在后期的节点同步过程会连接到别人的节点,同步会很慢。
2.初始化创世区块
在这里首先建立一个文件夹privatechain,然后把创世区块的.json文件放在此文件夹里边,然后在文件夹里运行此

geth --datadir data0 init genesis.json

他会生成一个data0文件夹,里边含有两个文件夹,输出如下代表成功了
在这里插入图片描述

在这里插入图片描述
其中 geth/chaindata 中存放的是区块数据,keystore 中存放的是账户数据。
接下来便是启动私有链节点

geth --identity "SCAU" --rpc --rpcport "8545" --datadir data0 --port "30303" --rpcapi "db,eth,net,web3" --allow-insecure-unlock --networkid 65534 --nodiscover console

上面命令的主体是 geth console,表示启动节点并进入交互式控制台。
各选项含义如下:

–identity:指定节点,用于标示目前网络的名字;
–rpc:表示开启 HTTP-RPC 服务;
–rpcport:指定 HTTP-RPC 服务监听端口号(默认为 8545);
–datadir:指定区块链数据的存储位置;
–port:指定和其他节点连接所用的端口号(默认为 30303);
–rpcapi: 设置允许连接的rpc的客户端,一般为db,eth,net,web3;
–networkid: 设置当前区块链的网络ID,用于区分不同的网络,是一个数字;
–nodiscover:关闭节点发现机制,防止加入有同样初始配置的陌生节点;
–maxpeers : 如果你不希望其他人连接到你的测试链,可以使用maxpeers 0。反之,如果你确切知道希望多少人连接到你的节点,你也可以通过调整数字来实现;
–rpccorsdomain : 这个可以指示什么URL能连接到你的节点来执行RPC定制端任务。务必谨慎,输入一个特定的URL而不是wildcard ( * ),后者会使所有的URL都能连接到你的RPC实例;
–console:启动命令行模式,可以在Geth中执行命令。

运行上面的命令后,就启动了区块链节点并进入了该节点的控制台:

如下便是成功了
在这里插入图片描述
之后,在data0中输入

geth attach ipc:geth.ipc

这回打开一个控制台
在这里插入图片描述
控制台操作
1.创建账户

personal.newAccount("0000");

注意:创建账户中的”0000“也是这个账户的密码

在这里插入图片描述
查看用户

personal.listAccounts

在这里插入图片描述
获取账号

personal.listAccounts[1]

这相当于一个数组,1代表第二个账户
在这里插入图片描述
查看账户余额

eth.getBalance("账号");或者
eth.getBalance(personal.listAccounts[0])

在这里插入图片描述
注意:没挖矿的情况下为0
解锁账号

personal.unlockAccount(personal.listAccounts[0]);

在这里需要输入密码,就是建立账户时给的
成功返回true

在这里插入图片描述
挖矿

miner.start(1)这个是全力挖矿
miner.start()一般用这个就行

如图出现小锤子,说明开始挖了
在这里插入图片描述
停止挖矿

miner.stop()

还有其他一些常用操作,不一一示例,后边用得着再说

eth.accounts:枚举系统中的账户;
eth.getBalance():查看账户余额,返回值的单位是 Wei(Wei 是以太坊中最小货币面额单位,类似比特币中的聪,1 ether = 10^18 Wei);
eth.blockNumber:列出区块总数;
eth.getTransaction():获取交易;
eth.getBlock():获取区块;
web3.fromWei():Wei 换算成以太币;
web3.toWei():以太币换算成 Wei;
txpool.status:交易池中的状态;
admin.addPeer():连接到其他节点;

账户之间转账

再创建一个账户,查看一下他的余额还是0
在这里插入图片描述
出于人道主义,我们得实现一下财富平等,所以,打钱吧
1.在打钱之前先解锁一下出钱的账户

personal.unlockAccount(personal.listAccounts[0]);

上边演示过了如何解锁,不在赘述
2.金额转换

amount = web3.toWei(5,'ether')
转多少,写多少,比较抠的话也可以写小数,0.00000001也可以的

在这里插入图片描述

3.打钱

eth.sendTransaction({
    
    from:personal.listAccounts[0],to:personal.listAccounts[1],value:amount})

from和to后边也可以直接写账户地址,就是创建账户后给的那一串,记得把双引号带着
注意:如果你的账户没有挖矿,那么交易不会发生,所以记得启动一下挖矿
好了,钱打完了,看一下贫富差距
在这里插入图片描述
好吧,差距比我和马云都大。。。。

一些小工具
查看交易状态

txpool.status

在这里插入图片描述
如果刚才转账了没挖矿,那么pending就为1
查看交易

eth.getBlock("pending",true);

会获得交易的信息
在这里插入图片描述
查看交易

eth.getTransaction("交易的一串数据");

产看当前区块数

eth.blockNumber

通过区块号查看区块:

eth.getBlock(4)

实现合约部署

1.首先建立一个.sol文件,在里边写代码
比如如下

pragma solidity ^0.8.3

contract test {
    
    
    string public  data = "hello world!";
    function testArray() public returns (string memory){
    
    
      return data;
   }
}

几点说明,这是用solidity写的,有一个solidity的教程可以看一下这个

https://zhuanlan.zhihu.com/p/353507891

pragma solidity ^0.8.3这是版本号
在这里返回值跟c和Java不一样,需要加returns,如果返回值是string,还要加memory
将这个.sol文件和.json文件放一起就可以
然后再这两个文件夹的位置运行如下两个代码

solcjs --bin mystring.sol

这个会生成一个.bin文件在这里插入图片描述
要注意:如果你的代码里有错误,在这里会显示出来,警告可以忽略,但error不幸
在运行如下语句

solcjs --abi  mystring.sol

生成一个.abi文件
在这里插入图片描述

之后进入data0文件夹,打开控制台

geth attach ipc:geth.ipc

建立code变量和abi变量

code="0x..."

省略的是.bin里边的,直接把.bin里边的数据全部copy过来就可以
需要注意的是,要用双引号包裹,在前边加上0x

abi=...

省略的是.abi文件里的内容,直接复制粘贴就好
解锁账户

personal.unlockAccount(personal.listAccounts[0]);

查看所需gas,就是查一下部署这个合约需要到少手续费

web3.eth.estimateGas({
    
    data:code})

挖矿

miner.start()

发送部署合约

myContract = eth.contract(abi)
contract = myContract.new({
    
    from:eth.accounts[0],data:code,gas:1000000})

获取合约地址

eth.getCode(contract.address)

调用合约

contract.testArray.call()

testArray是方法名,call是内置函数,把自己的方法名改上去就行
遇到msg.sender需要指明请求地址

contract.update.call("0xb18d9b39bb2d624a7bd6db3bd9a119071ac9625e",1111,{
    
    from:eth.accounts[0]})

节点连接

创建文件夹,复制.json过来,创建文件夹data1,初始化

geth --datadir data0 init genesis.json

然后

geth --identity "SCAU" --rpc --rpcport "8545" --datadir data1 --port "30303" --rpcapi "db,eth,net,web3" --allow-insecure-unlock --networkid 65534 --nodiscover console

注意改一下rpcport和port
在data0中输入

geth attach ipc:geth.ipc

查看节点标识

admin.nodeInfo.enode

节点连接

admin.addPeer("enode://4923254425942156a684eebd06f2371f2601b8d4a55e80d9800930715a54da5f3fea189ea99a2d0e573c7efb68b7e35ed14d02657fe674d58abd0f83e4c24dc6@127.0.0.1:3002?discport=0")

里边的要改成你自己节点的标识,也就是admin.nodeInfo.enode的结果

查看连接

admin.peers

查看已连接的节点数量

 net.peerCount

看节点1和节点2数据是否完全同步
关掉节点1的挖矿,在节点2查一下节点1的余额,能查到说明连接成功
节点1向节点2转账

eth.sendTransaction({
    
    from: eth.coinbase, to: "0x7992d63ef38d07aeca3ca0958fb751b60038fc41", value: 66666666})

节点间合约方法/函数调用,使用合约地址调用合约

节点2调用节点1部署的合约
定义abi

abi=。。。

.abi里边的内容

定义合约部署地址
用下边这句在节点1查一下

contract.address

在节点2

address=...

在节点2运行下边

myContract = eth.contract(abi)
contract = myContract.at(address)

调合约函数就可以了

contact.ca.call()

如果是有msg.sender的用下边

contract.update.sendTransaction("0x7992d63ef38d07aeca3ca0958fb751b60038fc41",6, {
    
    from: eth.accounts[0]})
contract.update.call("0x7992d63ef38d07aeca3ca0958fb751b60038fc41",6,{
    
    from:eth.accounts[0]})

Guess you like

Origin blog.csdn.net/mlynb/article/details/117410575