主页 > imtoken钱包下载国际版 > 区块链学习(一)——Mac上以太坊私链搭建

区块链学习(一)——Mac上以太坊私链搭建

imtoken钱包下载国际版 2023-05-04 06:28:56

go-ethereum 客户端安装

go-ethereum 客户端,通常称为 Geth,是一个命令行界面,可执行在 Go 中实现的完整以太坊节点。 Geth 得益于 Go 语言的多平台特性,支持在多个平台(如 Windows、Linux、Mac)上使用。 Geth是以太坊协议的具体实现。 通过Geth,您可以实现以太坊的各种功能,如创建、编辑和删除账户,启用挖矿,转账以太币,部署和执行智能合约等。 因此,我们选择geth工具进行开发。 由于我是mac,所以优先使用mac进行开发。 mac中的geth安装如下:

brew tap ethereum/ethereum
brew install ethereum

检查是否安装成功

geth --help

如果输出一些帮助提示命令,则安装成功。

打造私链

以太坊支持自定义创世块。 要运行一条私有链,我们需要定义我们自己的创世块。 创世块信息以json格式写在配置文件中。 先将以下内容保存到一个json文件中,比如genesis.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"
}

初始化:写入创世块

准备好创世块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文件,并根据其内容将创世块写入区块链。 如果在日志信息中看到Successfully written genesis state字样,说明初始化成功。

初始化成功后的目录如下:

搭建私有以太坊节点_以太坊的私有链_以太坊搭建私有链

这里写图片描述

其中,区块数据存放在geth/chaindata,账户数据存放在keystore。

启动私有链节点

初始化完成后,你就会拥有自己的私有链,然后就可以启动自己的私有链节点,进行一些操作了。 在终端中输入以下命令启动节点:

geth --datadir data0 --networkid 1108 console

上面命令的主体是geth console,意思是启动节点,进入交互式控制台。 --datadir 选项指定使用 data0 作为数据目录。 --networkid 选项后跟一个数字,这里是1108,表示指定私有链的network id为1108。 连接到其他节点时将使用网络 ID。 以太坊公网的network id为1,为了不和公链网络冲突,运行私链节点时必须指定自己的network id(以上命令可能会运行失败,我直接重启mac,然后进入privateChain目录,简单粗暴)。

运行上述命令后,区块链节点启动,进入Javascript控制台:

这里写图片描述

这是一个交互式 Javascript 执行环境,可以在其中执行 Javascript 代码,其中 > 是命令提示符。 在这个环境中,还内置了一些操作以太坊的Javascript对象,可以直接使用这些对象。 这些对象主要包括:

eth:包含一些操作区块链相关的方法

net:包含以下方法查看p2p网络状态

admin:包含一些管理节点相关的方法

miner:包含一些启动和停止挖矿的方法

personal:主要包括一些管理账户的方法

txpool:包含一些查看交易内存池的方法

web3:包含以上对象,还包含一些单位换算的方法

使用 Javascript 控制台

进入以太坊Javascript控制台后,可以使用内置对象进行一些操作。 这些内置对象提供了很多功能,比如查看区块和交易、创建账户、挖矿、发送交易、部署智能合约等。接下来介绍几个常用的功能。 以下操作中,前面带>的表示在Javascript Console中执行的命令。

创建账户

我们之前只是建了一条私链搭建私有以太坊节点,没有自己的账号。 可以在js控制台输入eth.accounts验证:

> eth.accounts
[]

此时没有账号,再使用个人对象创建账号:

> personal.newAccount()
> Passphrase:
> Repeat passphrase:
"0x4a3b0216e1644c1bbabda527a6da7fc5d178b58f"

Passphrase其实就是密码的意思。 输入密码两次后,创建一个帐户。 再次执行命令:

> personal.newAccount()
> Passphrase:
> Repeat passphrase:
"0x46b24d04105551498587e3c6ce2c3341d5988938"

这时候再看账目,竟然有两个。

> eth.accounts

以太坊的私有链_搭建私有以太坊节点_以太坊搭建私有链

["0x4a3b0216e1644c1bbabda527a6da7fc5d178b58f", "0x46b24d04105551498587e3c6ce2c3341d5988938"]

账号默认保存在数据目录下的keystore文件夹中。 查看目录结构,发现data0/keystore中多了两个文件。 这两个文件对应刚刚创建的两个账户。 这是一个json格式的文本文件,可以打开查看。 存储在其中的私钥是用密码加密的。 信息。

这里写图片描述

json文件中的信息格式如下:

{
  "address": "4a3b0216e1644c1bbabda527a6da7fc5d178b58f",
  "crypto": {
    "cipher": "aes-128-ctr",
    "ciphertext": "238d6d48126b762c8f13e84622b1bbb7713f7244c2f24555c99b76396fae8355",
    "cipherparams": {
      "iv": "d0f5a3d3e6c1eeec77bf631bc938725d"
    },
    "kdf": "scrypt",
    "kdfparams": {
      "dklen": 32,
      "n": 262144,
      "p": 1,
      "r": 8,
      "salt": "70dc72c4eb63bea50f7637d9ff85bb53f6ca8ace17f4245feae9c0bc9abaad82"
    },
    "mac": "bd7fc0c937c39f1cbbf1ca654c33b53d7f9c644c6dacfeefe1641d2f3decea04"
  },
  "id": "57803d82-0cd4-4a78-9c29-9f9252fdcf60",
  "version": 3
}

查看账户余额

eth 对象提供了查看账户余额的方法:

> eth.getBalance(eth.accounts[0])
0
> eth.getBalance(eth.accounts[1])
0

目前两个账户的以太币余额为0,要使账户有余额,可以从其他账户转账,或者通过挖矿获得以太币奖励。

开始和停止挖矿

通过 miner.start() 开始挖矿:

以太坊的私有链_搭建私有以太坊节点_以太坊搭建私有链

> miner.start(10)

start参数表示用于挖矿的线程数。 第一次开始挖矿,首先会生成挖矿所需的DAG文件。 这个过程有点慢。 进度达到100%后开始挖矿,屏幕上会刷新挖矿信息。

如果进度达到100%后想停止挖矿,可以在js控制台中输入

miner.stop():

注意:输入的字符会被挖矿刷新画面信息冲掉,没关系,输入完整的miner.stop()回车即可停止挖矿。

挖出一个区块将奖励5 ETH,挖矿获得的奖励将进入矿工账户。 这个账户叫做 coinbase。 默认情况下,coinbase 是本地账户中的第一个账户:

> eth.coinbase
"0x4a3b0216e1644c1bbabda527a6da7fc5d178b58f"

当前coinbase为0号账户,如果想将挖矿收益转移到其他账户,可以通过miner.setEtherbase()将其他账户设置为coinbase:

> miner.setEtherbase(eth.accounts[1])
true
> eth.coinbase
"0x46b24d04105551498587e3c6ce2c3341d5988938"

挖出区块后,账户 0 中应该有余额:

> eth.getBalance(eth.accounts[0])
2.31e+21

getBalance()返回值的单位是wei,是ether的最小单位,1 ether = 10的wei的18次方。 要查看您有多少以太币,您可以使用 web3.fromWei() 将返回值转换为以太币:

> web3.fromWei(eth.getBalance(eth.accounts[0]),'ether')
2310

发送交易

截至目前,账户1的余额仍为0:

> eth.getBalance(eth.accounts[1])
0

您可以通过发送交易将 10 个以太币从账户 0 转移到账户 1:

> amount = web3.toWei(10,'ether')
"10000000000000000000"
> eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[1],value:amount})
Error: authentication needed: password or unlock
    at web3.js:3143:20
    at web3.js:6347:15
    at web3.js:5081:36
    at :1:1

这里报错。 原因是帐户每隔一段时间就会被锁定。 要发送交易,必须先解锁帐户。 由于我们要从账户 0 发送交易,因此必须解锁账户 0:

> personal.unlockAccount(eth.accounts[0])

以太坊搭建私有链_搭建私有以太坊节点_以太坊的私有链

Unlock account 0x4a3b0216e1644c1bbabda527a6da7fc5d178b58f Passphrase: true

输入创建账户时设置的密码即可成功解锁账户。 然后再次发送交易:

> amount = web3.toWei(10,'ether')
"10000000000000000000"
> eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[1],value:amount})
INFO [03-07|11:13:11] Submitted transaction                    fullhash=0x1b21bba16dd79b659c83594b0c41de42debb2738b447f6b24e133d51149ae2a6 recipient=0x46B24d04105551498587e3C6CE2c3341d5988938
"0x1b21bba16dd79b659c83594b0c41de42debb2738b447f6b24e133d51149ae2a6"

让我们检查帐户 1 中的余额:

> eth.getBalance(eth.accounts[1])
0

发现还没有转账。 此时交易已经提交到区块链,但是还没有处理。 这可以通过检查 txpool 来验证:

> txpool.status
{
  pending: 1,
  queued: 0
}

其中有一个pending transaction,意思是已经提交但是还没有处理的交易。

处理交易需要挖矿。 这里开始挖矿,等待挖出一个区块后停止挖矿:

> miner.start(1);admin.sleepBlocks(1);miner.stop();

当 miner.stop() 返回 true 时,txpool 中的待处理交易数应该为 0,表示交易已经处理完毕,账户 1 应该已经收到币:

> web3.fromWei(eth.getBalance(eth.accounts[1]),'ether')
10

查看交易和区块

eth 对象封装了查看交易和区块信息的方法。

查看当前区块总数:

> eth.blockNumber
463

按块号查看块:

> eth.getBlock(66)
{
  difficulty: 135266,
  extraData: "0xd783010802846765746886676f312e31308664617277696e",

以太坊搭建私有链_搭建私有以太坊节点_以太坊的私有链

gasLimit: 3350537, gasUsed: 0, hash: "0x265dfcc0649bf6240812256b2b9b4e3ae48d51fd8e43e25329ac111556eacdc8", logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", miner: "0x4a3b0216e1644c1bbabda527a6da7fc5d178b58f", mixHash: "0xaf755722f62cac9b483d3437dbc795f2d3a02e28ec03d39d8ecbb6012906263c", nonce: "0x3cd80f6ec5c2f3e9", number: 66, parentHash: "0x099776a52223b892d13266bb3aec3cc04c455dc797185f0b3300d39f9fc0a8ec", receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", size: 535, stateRoot: "0x0c9feec5a201c8c98618331aecbfd2d4d93da1c6064abd0c41ae649fc08d8d06", timestamp: 1520391527, totalDifficulty: 8919666, transactions: [], transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", uncles: []
}

按交易哈希查看交易:

> eth.getTransaction("0x1b21bba16dd79b659c83594b0c41de42debb2738b447f6b24e133d51149ae2a6")
{
  blockHash: "0x1cb368a27cc23c786ff5cdf7cd4351d48f4c8e8aea2e084a5e9d7c480449c79a",
  blockNumber: 463,
  from: "0x4a3b0216e1644c1bbabda527a6da7fc5d178b58f",
  gas: 90000,
  gasPrice: 18000000000,
  hash: "0x1b21bba16dd79b659c83594b0c41de42debb2738b447f6b24e133d51149ae2a6",
  input: "0x",
  nonce: 0,
  r: "0x31d22686e0d408a16497becf6d47fbfdffe6692d91727e5b7ed3d73ede9e66ea",
  s: "0x7ff7c14a20991e2dfdb813c2237b08a5611c8c8cb3c2dcb03a55ed282ce4d9c3",
  to: "0x46b24d04105551498587e3c6ce2c3341d5988938",
  transactionIndex: 0,
  v: "0x38",
  value: 10000000000000000000
}