以太坊客户端Geth(windows)

Posted This_is_Leon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了以太坊客户端Geth(windows)相关的知识,希望对你有一定的参考价值。

以太坊客户端Geth(windows)

0.小贴士(solc、linux常用命令)

1.linux系统安装node,并且进行环境变量的配置

安装完成后进行软连接

sudo ln -s /home/leon/node/node-v12.18.1-linux-x64/bin/npm /usr/local/bin/npm
sudo ln -s /usr/local/node/node-v4.4.7-linux-x64/bin/node /usr/local/bin/node

2.安装solc-select

  1. 首先安装pip3

    sudo apt-get install python3-pip
    
  2. solc-select 安装

    pip3 install solc-select
    
  3. 配置solc-select环境变量,solc-select默认安装在/home/leon/.local/bin下,使用sudo vi /etc/profile打开配置文件。在最底下添加

    export PATH=$PATH:/home/leon/.local/bin
    
  4. 若想安装某一版本的solc:

    solc-select install 0.4.26
    
  5. 若想使用某一版本的solc:

    solc-select use 0.4.26
    
  6. 若想查看当前solc的版本:

    solc --version
    

3.使用solc对文件进行编译

solc --abi Coin.sol

4.控制光标的显示隐藏

//隐藏光标
echo -e "\\033[?25l"
//显示光标
echo -e "\\033[?25h"

5.将一个文件夹下的全部文件复制到另一个文件

cp -r 当前文件夹名 另一个文件的路径

1.下载geth客户端

  • 从geth官网下载客户端并进行安装。
  • 配置环境变量
  • 打开命令行输入geth version
C:\\Users\\liaozheng\\geth\\project\\mychain>geth version
Geth
Version: 1.10.3-stable
Git Commit: 991384a7f6719e1125ca0be7fb27d0c4d1c5d2d3
Git Commit Date: 20210505
Architecture: amd64
Go Version: go1.16.3
Operating System: windows
GOPATH=D:\\A1\\GO\\goproject
GOROOT=D:\\A1\\GO\\go

2.搭建自己的私链

  • 首先写一段创世区块的json代码

    
      "config": 
        "chainId": 15
      ,
      "difficulty": "2000",
      "gasLimit": "2100000",
      "alloc": 
        "0xaC02660e24Cb4B891bD3Fe305A56C1783f4237d6": "balance": "30000000000000000"
      
    
    
  • 在用户路径的geth文件夹下创建project/mychain的文件夹,把genesis.json的文件放进去

  • 输入geth --datadir geth/project/mychain init geth/project/mychain/genesis.json 创建自己的私链

  • 注意:一定要在mychain文件夹下运行geth --datadir . --networkid 15 启动这条私链

3.与私链进行交互

问题:Geth客户端启动私链一直显示looking for peer……解决办法

解决方法:启动命令加上--nodiscover,禁止寻找节点

1.运行以下代码便会显示控制台

geth --datadir . --networkid 15 console --nodiscover

2.下面的命令,可以将控制台和挖矿出块的一些反馈分开显示,

geth --datadir . --networkid 15 console --nodiscover 2>output.log

然后在mychain文件夹下找到output.log文件:

运行type output.log命令获取区块信息。(若是linux系统,可使用tail -f output.log动态检测日志的更新)

在powershell窗口下运行以下命令可以实时获得日志内容:

Get-Content D:\\www\\webapp1\\Logs\\t20190116.log -wait
  • Get-Content 获取指定文件的内容
  • -wait:等待文件输出,每秒检查一次,ctrl+c退出

3.添加–rpc则可以与metaMask钱包进行连接:

geth --datadir . --networkid 15 --rpc console --nodiscover 2>output.log

常用命令:

personal.newAccount():创建账户

personal.unlockAccount():解锁账户

eth.accounts:列出系统中的账户

eth.getBalance():查看账户余额,返回值的单位是Wei

eth.getBalance("0xaC02660e24Cb4B891bD3Fe305A56C1783f4237d6")

eth.blockNumber:列出当前区块高度

eth.getTransaction():获取交易信息

eth.getBlock():获取区块信息

miner.start():开始挖矿

miner.stop():停止挖坑

web3.fromWei():Wei换算成以太币

web3.fromWei(eth.getBalance("0xaC02660e24Cb4B891bD3Fe305A56C1783f4237d6"),"ether")

web3.toWei():以太币换算成Wei

txpool.status:交易池中的状态

测试

cd geth/project/mychain
geth --datadir . --networkid 15 console --nodiscover 2>output.log
personal.unlockAccount(eth.accounts[0])
eth.sendTransaction(from: eth.accounts[0],to:'0xaC02660e24Cb4B891bD3Fe305A56C1783f4237d6',value: web3.toWei(10, 'ether'))

4.搭建一条开发者私链

进入开发者账户以后,账户之间进行转账的过程就不需要解锁账户了。方便了很多。

geth --datadir . --dev --nodiscover console 2>output.log

新的启动命令:

geth --datadir . --dev --rpc --nodiscover --rpccorsdomain "*" console 2>output.log

5.私链提供了一个API和一组远程调用RPC命令

本质上,JSON-RPC API 就是一个接口,允许我们编写的程序使用以太坊客户端作为网关,访问以太坊网络和链上数据。

curl -X POST -H "Content-Type: application/json" --data '"jsonrpc":"2.0","method":"web_clientVersion","params":[],"id":1' http://localhost:8545

4.solidity

1.小贴士

  • view关键字表示只读不写。
  • constructor表示,在deploy时需要输入初始值。
  • 当使用string类型的时候,会有警告,因为string类型可以设置无限长度,会一直消耗gas。所以常常改用bytes32,用16进制数进行表示。
  • 如下是一个Car.sol的合约对象
pragma solidity >0.4.22;

contract Car
  string brand;
  uint public price;
  constructor(string initBrand, uint initPrice) public 
    brand = initBrand;
    price = initPrice;
  
  function setBrand(string newBrand) public 
    brand = newBrand;
  
  function getBrand() public view returns(string) 
    return brand;
  
  function setPrice(uint newPrice) public
    price = newPrice;
  


  • assert:表示断言,即要求一定为真。
  • require:表示要求,可以为真,也可以为假
function _transfer(address _from, address _to, uint _value) internal 
	// Prevent transfer to 0x0 address. Use burn() instead
    require(_to != 0x0);
    // Check if the sender has enough
    require(balanceOf[_from] >= _value);
    // Check for overflows
    require(balanceOf[_to] + _value >= balanceOf[_to]);
    // Save this for an assertion in the future
    uint previousBalances = balanceOf[_from] + balanceOf[_to];
    // Subtract from the sender
    balanceOf[_from] -= _value;
    // Add the same to the recipient
    balanceOf[_to] += _value;
    emit Transfer(_from, _to, _value);
    // Asserts are used to use static analysis to find bugs in your code. They should never
    fail
    assert(balanceOf[_from] + balanceOf[_to] == previousBalances);

2.简单投票系统Ballot

  • 设置被选举人如下,被选举人的名字格式为bytes32,而remix不会将不够长度的输入参数补全,因此需要将候选人名字设置为64个16进制数
    • [“0x2022542500000000000000000000000000000000000000000000000000000000”,“0x2022543500000000000000000000000000000000000000000000000000000000”]
pragma solidity >=0.7.0 <0.8.0;

/** 
 * @title Ballot
 * @dev Implements voting process along with vote delegation
 */
contract Ballot 
   	//投票人的结构体
    struct Voter 
        uint weight; // 其投票所占用的权值,其他投票者可以将投票权利给其他投票人,因此会改变一个投票人的权值
        bool voted;  // 检查是否已经投票,若为true则已经投票
        address delegate; // 委托投票人的地址
        uint vote;   // 是对哪一个被选举人投票
    
	
	//被选举人的结构体
    struct Proposal 
        // If you can limit the length to a certain number of bytes, 
        // always use one of bytes1 to bytes32 because they are much cheaper
        bytes32 name;   // 被选举人的名字(32字节)
        uint voteCount; // 被选举人获得的票数
    

    address public chairperson;		//主持人的地址

    mapping(address => Voter) public voters;		//从地址到投票人的映射,一个地址相当于一个投票人

    Proposal[] public proposals;	//所有被选举人的数组

    /** 
     * @dev Create a new ballot to choose one of 'proposalNames'.
     * @param proposalNames names of proposals
     */
    constructor(bytes32[] memory proposalNames) 
        chairperson = msg.sender;		//将第一个部署合约的人设置为主持人
        voters[chairperson].weight = 1;		//其权重为1
		
		//将所有待选的被选举人存储到被选举人数组中
        for (uint i = 0; i < proposalNames.length; i++) 
            // 'Proposal(...)' creates a temporary
            // Proposal object and 'proposals.push(...)'
            // appends it to the end of 'proposals'.
            proposals.push(Proposal(
                name: proposalNames[i],
                voteCount: 0
            ));
        
    
    
    /** 
     * @dev Give 'voter' the right to vote on this ballot. May only be called by 'chairperson'.
     * @param voter address of voter
     */
     //主持人分发选票
    function giveRightToVote(address voter) public 
        require(
            msg.sender == chairperson,		//第一,分发选票的人必须是主持人
            "Only chairperson can give right to vote."
        );
        require(
            !voters[voter].voted,		//第二,分发的对象不能是已经投票了的
            "The voter already voted."
        );
        require(voters[voter].weight == 0);		//将分发对象的权值设置为1
        voters[voter].weight = 1;
    

    /**
     * @dev Delegate your vote to the voter 'to'.
     * @param to address to which vote is delegated
     */
     //将选票委托给他人投票
    function delegate(address to) public 
        Voter storage sender = voters[msg.sender];		
        require(!sender.voted, "You already voted.");		//检查是否已经投票
        require(to != msg.sender, "Self-delegation is disallowed.");		//检查是否是投给自己(不允许为自己投票)

        while (voters[to].delegate != address(0)) 		//检查委托对象是不是也委托给了其他人
            to = voters[to].delegate;		//开始层层委托,会委托给委托链的最后一个投票人

            // We found a loop in the delegation, not allowed.
            require(to != msg.sender, "Found loop in delegation.");		//不允许把委托链形成一个环	
        
        sender.voted = true;		//设置委托人已经投票
        sender.delegate = to;		//其委托对象是to
        Voter storage delegate_ = voters[to];	
        if (delegate_.voted) 		//如果被委托人此时已经投票了
            // If the delegate already voted,
            // directly add to the number of votes
            proposals[delegate_.vote].voteCount += sender.weight;	//将被委托人的投票对象加上委托人的权值
         else 		//若被委托人还没有投票
            // If the delegate did not vote yet,
            // add to her weight.
            delegate_.weight += sender.weight;		//修改被委托人的权值=被委托人的权值+委托人权值
        
    

    /**
     * @dev Give your vote (including votes delegated to you) to proposal 'proposals[proposal].name'.
     * @param proposal index of proposal in the proposals array
     */
    function vote(uint proposal) public 
        Voter storage sender = voters[msg.sender];
        require(sender.weight != 0, "Has no right to vote");		//检查是否有权投票
        require(!sender.voted, "Already voted.");		//检查是否已经投票
        sender.voted = true;
        sender.vote = proposal;

        // If 'proposal' is out of the range of the array,
        // this will throw automatically and revert all
        // changes.
        proposals[proposal].voteCount += sender.weight;		//为投票对象增加投票人的对应票数
    

    /** 
     * @dev Computes the winning proposal taking all previous votes into account.
     * @return winningProposal_ index of winning proposal in the proposals array
     */
    function winningProposal() public view
            returns (uint winningProposal_)
    
        uint winningVoteCount = 0;		//在所有的被选举人中找到一个得票最多的返回其编号
        for (uint p = 0; p < proposals.length; p++) 
            if (proposals[p].voteCount > winningVoteCount) 
                winningVoteCount = proposals[p].voteCount;
                winningProposal_ = p;
            
        
    

    /** 
     * @dev Calls winningProposal() function to get the index of the winner contained in the proposals array and then
     * @return winnerName_ the name of the winner
     */
    function winnerName() public view
            returns (bytes32 winnerName_)
    
        winnerName_ = proposals[winningProposal()].name;	//在所有的被选举人中找到一个得票最多的返回其名字



/home/leon/node/node-v12.18.1-linux-x64/bin

5.web3js

1.首先安装web3.js

npm install web3@0.20.1

2.在安装的node_modules同级文件夹下打开node

3.书写代码:

var Web3 =require('web3')
var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'))

4.另外打开一个终端启动私链,再输入web3.isConnected(),返回结果为true,说明建立了连接。

5.输入web3.version,可以得到版本信息

6.安装ganache-cli

  1. 配置环境,运行npm list web3可以查看web3的版本信息,运行npm list solc可以查看solc的版本信息

    npm install ganache-cli web3@0.20.1 solc@0.4.26
    
  2. 运行node_modules/.bin/ganache-cli可以启用一个虚拟的区块链,ganache会默认创建10个账户,每个账户有100以太币。也会有10个账户的地址信息,和每个账户的私钥。

  3. 编写一个简单的投票智能合约Voting.sol,记住代码要从Remix里复制粘贴过来。

    pragma solidity >0.4.22;
    
    contract Voting 
    
        bytes32[] public candidateList;
        mapping (bytes32 => uint8) public votesReceived;
        
        constructor(bytes32[] candidateNames) public 
            candidateList = candidateNames;
        
    
        function voteForCandidate(bytes32 candidate) public 
            require(validCandidate(candidate));
            votesReceived[candidate] += 1;
        
    
        function totalVotesFor(bytes32 candidate) view public returns (uint8) 
            require(validCandidate(candidate));
            return votesReceived[candidate];
        
    
        function validCandidate(bytes32 candidate) view public returns (bool) 
            for(uint8 i = 0; i < candidateList.length; i++) 
                if(candidateList[i] == candidate)
                    return true;
            
            return false;
        
    
    
  4. 打开node命令窗口,输入web3命令

    var Web3 = require('web3')
    var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
    
    

    调用web3.isConnected(),若为true则说明连接上了。

    调用web3.eth.accounts,则可以得到全部的十个账户地址。

    继续输入命令:

    var solc = require('solc')
    var sourceCode = fs.readFileSync('Voting.sol').toString()
    

    输入sourceCode,即可输出转变成String的Voting.sol文件。

    有了源代码之后,就可以去编译文件了。

    var compiledCode = solc.compile(sourceCode)
    

    输入compiledCode,即可查看得到全部编译文件。接下来声明abi合约接口和字节码变量

     var abi = JSON.parse(compiledCode.contracts[':Voting'].interface);
    var byteCode = compiledCode.contracts[':Voting'].bytecode;
    

    定义抽象的合约对象并且使用地址[0]部署合约,同时设置gas费用:

    var VotingContract = web3.eth.contract(abi)
    var deployTxObj = data: byteCode, from: web3.eth.accounts[0], gas: 3000000
    

    new一个合约实例,ganache-cli窗口也会显示有交易产生:

    var contractInstance = VotingContract.new(['Alice', 'Leon', 'Yetta'], deployTxObj);
    

    输入contractInstance.address可以得到合约地址。

    使用控制台可以进行交互:

    比如给Alice投票,查看Alice的票数

    contractInstance.voteForCandidate('Alice', from:web3.eth.accounts[0]);
    contractInstance.totalVotesFor("Alice").toString();
    

    BigNumber s: 1, e: 0, c: [ 1 ] ,这个数值的含义。s表示正负,1为正;e表示10的多少次方,c表示数字。这个表示的意思就是正1。

  5. 编写index.html和index.js文件

    • 直接从官网下载0.20.6版本的web3Js,再利用script导入web3js的链接
    • 即可打开网页进行投票了

7.linux子系统拿到主机硬盘文件

  1. 首先cd…退出到主目录

  2. cd mnt 进入这个文件

  3. 这时cd c 就进入c盘,cd d就进入d盘

  4. 啊啊

    ["0x7df78276198c61a2e6f2d2678b5ced1eb8b9548507652d4b09808abb1fa52c64","0xcf57aede2d508be2204ab79410486ca15d3d3aa0e651aa03d4cc84f6dc488439","0xc3784ea94d1f62fb2c160feae8d2bc0c3df41d1f6171fdb3abd95c90466a9563"]
    
  5. 切换目录

    cd ../../mnt/d/广工/findlab/以太坊/以太坊/源码/simple_voting_dapp
    
  6. node文档快速编辑

    var Web3 = require('web3')
    var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"))
    var solc = require('solc')
    var sourceCode = fs.readFileSync('Voting.sol').toString()
    var compiledCode = solc.compile(sourceCode)
     var abi = JSON.parse(compiledCode.contracts[':Voting'].interface);
    var byteCode = compiledCode.contracts[':Voting'].bytecode
    var VotingContract = web3.eth.contract(abi)
    var deployTxObj = data: byteCode, from: web3.eth.accounts[0], gas: 3000000
    var contractInstance = VotingContract.new(['Alice', 'Leon', 'Yetta'], deployTxObj)
    
    //查看地址
    contractInstance.address
    //修改index.js的contract地址
    //运行服务器监听
    node server.js
    //输入前端网址
    

以上是关于以太坊客户端Geth(windows)的主要内容,如果未能解决你的问题,请参考以下文章

以太坊geth主网全节点部署

以太坊钱包搭建与使用

以太坊私有链环境搭建

以太坊私有链环境搭建

怎么在windows下启动以太坊java客户端ethereumj

如何搭建以太坊私有链