以太坊私链搭建与配置
个人记录,很多操作参考了这篇文章与其他的,主要是为了给自己一条特别适合自己工作环境的私链。
关于环境
用的geth,安装啥的我觉得不用多说了,资料太多
init
创世区块
在非go目录下,新建一个,比如我在~/PersonWork/bychain
,目录下来一个gensis.json,创世区块!
1 | { |
注意!
config参数请加上byzantiumBlock、constantinopleBlock、petersburgBlock,因为其实以太坊本身就要经历这四个阶段,如果不加的话,在0.5.5版本的solc之后,就会出问题,因为EIP 145:EVM 中的按位移动(bitwise shifting)指令,是constantinopleBlock版本的 ,这个SHR吧,从0.5.5版本开始,就被用来跟在CALLDATALOAD后面,(通过右移)用来取不同位数,所以,你要是在搭建私链的时候,很可能被坑,你的执行到SHR指令戛然而止Orz,从外部表现来看就是:“gas required exceeds allowance or always failing transaction”,当然这个Error大部分时候和这个问题没关系。

初始化命令
1 | geth --datadir data0 init genesis.json |
命令的主体是 geth init
,表示初始化区块链,命令可以带有选项和参数,其中 --datadir
选项后面跟一个目录名,这里为 data0,表示指定数据存放目录为 data0,genesis.json 是 init
命令的参数。初始化完成data0里面就会有初始化数据
运行节点
1 | # 节点1 |
上面命令的主体是 geth console
,表示启动节点并进入交互式控制台。
各选项含义如下:
- –identity:指定节点 ID;
- –rpc:表示开启 HTTP-RPC 服务;
- –rpcport:指定 HTTP-RPC 服务监听端口号(默认为 8545);
- –rpccorsdomain:允许rpc跨的域 (browser enforced)
- –datadir:指定区块链数据的存储位置;
- –port:指定和其他节点连接所用的端口号(默认为 30303);
- –nodiscover:关闭节点发现机制,防止加入有同样初始配置的陌生节点。
一个节点可以有多个账户,默认0账户收钱(就上面定义的),每次生成一个account,这个节点下面就会在文件夹keystone下生成一个文件,钥匙文件
钥匙文件
每个账户都由一对钥匙定义,一个私钥和一个公钥。 账户以地址为索引,地址由公钥衍生而来,取公钥的最后 20个字节。每对私钥 /地址都编码在一个钥匙文件里。钥匙文件是JSON文本文件,可以用任何文本编辑器打开和浏览。钥匙文件的关键部分,账户私钥,通常用你创建帐户时设置的密码进行加密。钥匙文件可以在以太坊节点数据目录的keystore子目录下找到。
source: https://blog.csdn.net/wzygis/article/details/73480112
一旦进入console了,这是一个交互式的 JavaScript 执行环境,在这里面可以执行 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(交易hash):获取交易;
- eth.getBlock():获取区块;
- miner.start():开始挖矿;
- miner.stop():停止挖矿;
- web3.fromWei():Wei 换算成以太币;
- web3.toWei():以太币换算成 Wei;
- txpool.status:交易池中的状态;
- admin.addPeer():连接到其他节点;
这些命令支持 Tab
键自动补全
节点网络
启动前添加
1 | # 进入节点目录下的geth文件夹 |
启动时添加
1 | # 节点连接:启动节点时添加 |
启动后添加
1 | # 节点1:获取节点1信息 |
如果出现admin.addPeer()返回true但是实际节点没有添加成功的例子,也即新增节点不生效,像这样:
1 | > admin.addPeer("enode://c4586276391b3c88ec23889d1bc825d0c7d69bd5765d4545686f835608068b8dc48799d2686a04ea0f9e17aed099bf9b56935679fa6493e9b17151624a320714@172.16.0.17:30303") |
查看节点全信息,查找原因
1 | > admin.nodeInfo |
智能合约
发布
对于这样一个demo:
1 | pragma solidity >=0.4.22 <0.6.0; |
geth智能合约发布需要bytecode和abi
1 | # In geth console |
Demo
可使用remix改善发布这个步骤,虽然改版了,但是差不多;注意gas可能会超过范围哦,修改下
智能合约的访问
当获取合约实例之后(比如 testInstance),在geth console中可以通过三种方法调用合约方法(比如testFunc)
- testInstance.testFunc.sendTransaction();
- testInstance.testFunc();
- testInstance.testFunc.call();
本文将讲解这三种调用方法的区别
- testInstance.testFunc.sendTransaction(); 会创建一个交易,调用之后会返回一个交易hash值,它会广播到网络,等待矿工打包, 它会消耗gas。
- testInstance.testFunc.call(); 它完全是一个本地调用,不会向区块链网络广播任何东西,它的返回值完全取决于 testFunc 方法的代码,不会消耗gas
- testInstance.testFunc(); 它会比较特殊,由于有constant标识的方法不会修改状态变量,所以它不会被编译器执行。所以,如果testFunc() 有constant标识,它并不会被编译器执行,web3.js会执行call()的本地操作。相反如果没有constant标识,会执行sendTransaction()操作。
1 | // 得到address的智能合约实例 |
看下这个交易:
1 | eth.getTransaction("0xe9b9747a0e1cda6e4f46644e39e54cc2b7a78983311bddc654299d692217df72") |
这里我想到了个问题,要是我没有abi怎么办,查了下资料,这个问题比较棘手。。。
监听事件
1 | // 获取事件对象 |
API
更多:https://web3js.readthedocs.io
节点
admin.addPeer()
连接节点,两个节点要要指定相同的 chainID
admin.nodeInfo.enode
知道节点信息
admin.peers
可以查看连接到的其他节点信息,
net.peerCount
可以查看已连接到的节点数量。
eth.syncing
节点同步;当CurrentBlock大于等于HighestBlock时会返回false,也就是同步完成之后,再执行eth.syncing()函数会返回false。
如果同步没完成,则显示以下字段:
- startingBlock:开始同步的起始区块编号;
- currentBlock:当前正在导入的区块编号;
- highestBlock:通过所链接的节点获得的当前最高的区块高度;
- pulledStates:当前已经拉取的状态条目数;
- knownStates:当前已知的待拉取的总状态条目数;
账户
personal.newAccount()
创建账户,输入两遍密码即可;可以创建好多个,按照创建顺序,0,1,2,…账户,用eth.accounts
可以枚举有多少,以及地址是啥
eth.accounts()
枚举该节点的所有账户,[“0x嘻嘻嘻嘻嘻嘻嘻”,“0x发发发发发”]
eth.coinbase
挖到一个区块会奖励5个以太币,挖矿所得的奖励会进入矿工的账户,这个账户叫做coinbase,默认情况下coinbase是本地账户中的第一个账户:
eth.getBalance(eth.accounts[0])
查看账户余额,可以单位换算以下,见下
web3.fromWei(eth.getBalance(eth.accounts[1]),‘ether’)
以Wei为单位查看余额
web3.eth.personal.unlockAccount(address, password, unlockDuraction [, callback])
解锁账户,转账挖矿都需要解锁账户,如果解锁账户碰到这个问题"error-account-unlock-with-http-access-is-forbidden",在启动geth console的时候可以加上参数"–allow-insecure-unlock";
unlockDuration的时间应该是秒
miner.setEtherbase()
将其他账户设置成coinbase
,比如miner.setEtherbase(eth.accounts[1])
挖矿
miner.start(1)
其中 start 的参数表示挖矿使用的线程数。第一次启动挖矿会先生成挖矿所需的 DAG 文件,这个过程有点慢,等进度达到 100% 后,就会开始挖矿,此时屏幕会被挖矿信息刷屏。
miner.stop()
不解释
miner.start(1);admin.sleepBlocks(1);miner.stop();
一次只挖一个块
区块
eth.blockNumber
区块数量
eth.getBlock( i )
查看区块i的信息
eth.getBlock(“pengding/[number]”).gasLimit
Gas Limit就是一次交易中Gas的可用上限,在你提交交易之前,需要为交易设定一个Gas用量的上限。这个值一般写在gensis.json文件里,如果想提高gas,带上--targetgaslimit xxxxx
交易
eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[1],value:amount})
发送交易,这是一个简单的转账交易,后面有合约创建和合约交互
txpool.status
展示交易池
eth.getBlock(“pending”, true).transactions
查看当前待确认交易
eth.getBlockTransactionCount(“pending”);
查看当前待确认交易个数
eth.getTransaction(“0x交易hash”)
查看交易信息
eth.estimatesGas({data: bytecode})
评估bytecode的gas消耗
单位换算
web3.toWei(5,‘ether’)
参考: