Java基于Geth1.8实现区块链数据上链(节点同步、合约部署,以及踩坑记录—主节点控制台卡死、节点同步出错的解决方案)

前言:本文将从一个区块链入门小白的视角,来一步步的讲解如何实现区块链数据上链,链上数据查询,geth多节点同步。以及讲解在上链过程中,我踩过的坑及其解决方案。如果有不对的地方,还请大佬指教!🙇‍🙇‍🙇‍
声明:本文为作者Huathy原创文章,未经许可,禁止转载。否则依法追究责任!

环境搭建

GoLang环境安装

  1. 版本安装 :https://studygolang.com/dl
    基于go1.22.0.windows-amd64.msi (60MB)稳定版本
  2. gopath配置
    Windows版本安装自动配置,或类似JavaHome配置

Geth环境安装

下载geth1.8.20版本:geth-windows-amd64-1.8.20-24d727b6.exe
配置环境变量:
在这里插入图片描述

geth初始化

  1. 编写创世区块配置文件genesis.json
    {
    	"config": {
    	  "chainId": 1,
    	  "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": "0xffffffff",
    	"difficulty": "0x00002",
    	"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    	"coinbase": "0x0000000000000000000000000000000000000000",
    	"alloc": { },
    	"number": "0x0",
    	"gasUsed": "0x0",
    	"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
    }
    
  2. 执行初始化命令
    geth init --datadir eth_node1 C:\env\Geth\genesis.json  
    geth init --datadir eth_node2 C:\env\Geth\genesis.json  
    
    在这里插入图片描述

启动节点

geth  --datadir "eth_node1" --port 30303 --ipcdisable --networkid 23 --rpc  --rpcaddr "localhost" --rpcport "8546" --rpccorsdomain "*" --rpcapi "db,eth,net,web3" --cache 2048 --miner.threads 4 console 2 
geth  --datadir "eth_node2" --port 30304 --ipcdisable --networkid 23 --rpc  --rpcaddr "localhost" --rpcport "8547" --rpccorsdomain "*" --rpcapi "db,eth,net,web3" console 2 
# 日志重定向
geth  --datadir "eth_node1" --port 30303 --ipcdisable --networkid 23 --rpc  --rpcaddr "localhost" --rpcport "8546" --rpccorsdomain "*" --rpcapi "db,eth,net,web3" --cache 2048 --miner.threads 4 console 2>eth_node1.log
geth  --datadir "eth_node2" --port 30304 --ipcdisable --networkid 23 --rpc  --rpcaddr "localhost" --rpcport "8547" --rpccorsdomain "*" --rpcapi "db,eth,net,web3" console 2>eth_node2.log

Geth节点同步

  1. 在node1上获取enode地址
    admin.nodeInfo.enode
    
  2. node2将node1地址添加为peer
    # 将node1的enode地址添加到node2中
    admin.addPeer("enode://46de00161f2bf8995b736dfa98a94187fe72c3b4324a96741348a0708ca90be35d728941aeeedcc6349365744bec2b64bc72ec2e2e0d2858d5cbae94ae227118@127.0.0.1:30303")
    # 使用admin.peers查看
    admin.peers
    

在这里插入图片描述

  1. node1调用miner.start()开始掘金,node2开始同步
    # 新建账户
    personal.newAccount("huathy")
    # 查看账户
    eth.accounts
    # 指定掘金账户
    miner.setEtherbase("0xd8554b507a868d5d30ff3d2e14b92615c243831e")
    # 开始掘金
    miner.start()
    # 停止掘金
    miner.stop()
    # 查看同步状态
    eth.syncing 
    # 查看区块数量是否同步
    eth.blockNumber
    

在这里插入图片描述在这里插入图片描述在这里插入图片描述特别注意:同步区块时,不要关闭控制台!注意使用正常的exit命令退出!否则下次启动同步,将导致程序退出,同步失败!

主节点控制台卡死、无法退出问题

先在节点2执行exit命令,正常退出节点2。然后直接关闭主节点控制台。但再次打开时,节点2添加peers会导致主节点异常退出。执行eth.blockNumber会发现主节点的区块数量为0。这时,我们找到主节点的文件夹,删除geth目录下的chaindata文件夹。同时将节点2的该文件夹拷贝到geth目录下。再次启动节点1、2开启同步,可见区块数量一致,同步正常。
在这里插入图片描述

部署智能合约

编写合约代码MyContract.sol

使用remix平台,编写智能合约代码https://remix.ethereum.org/
注意选择编译环境,以及复制生成的abi以及bytecode到文件MyContract.abi和MyContract.bin。

pragma solidity ^0.8.0;

contract MyContract {
    mapping(string => string) public data;

    function storeData(string memory id, string memory value) public {
        data[id] = value;
    }

    function retrieveData(string memory id) public view returns (string memory) {
        return data[id];
    }
}

在这里插入图片描述
在这里插入图片描述

将智能合约转为Java代码

  1. 创建SpringBoot项目,并引入依赖
<dependency>
	<groupId>org.web3j</groupId>
	<artifactId>geth</artifactId>
	<version>${geth.version}</version>
	<exclusions>
		<exclusion>
			<artifactId>core</artifactId>
			<groupId>org.web3j</groupId>
		</exclusion>
	</exclusions>
</dependency>
<dependency>
	<groupId>org.web3j</groupId>
	<artifactId>parity</artifactId>
	<version>${geth.version}</version>
	<exclusions>
		<exclusion>
			<artifactId>core</artifactId>
			<groupId>org.web3j</groupId>
		</exclusion>
	</exclusions>
</dependency>
<dependency>
	<groupId>org.web3j</groupId>
	<artifactId>codegen</artifactId>
	<version>5.0.0</version>
</dependency>
  1. 编写转换代码
import org.web3j.codegen.SolidityFunctionWrapperGenerator;
import java.util.Arrays;
import java.util.stream.Stream;

public class Sol2Java {
    public static void main(String[] args) {
        Sol2Java.generateClass(
                "D:\\Huathy\\Desktop\\taobao\\warehouse\\src\\main\\resources\\sol\\MyContract.abi",
                "D:\\Huathy\\Desktop\\taobao\\warehouse\\src\\main\\resources\\sol\\MyContract.bin",
                "D:\\Huathy\\Desktop\\taobao\\warehouse\\src\\main\\resources\\sol");
    }
    /**
     *
     * 生成合约的java代码
     * 其中 -p 为生成java代码的包路径此参数和 -o 参数配合使用,以便将java文件放入正确的路径当中
     * @param abiFile abi的文件路径
     * @param binFile bin的文件路径
     * @param generateFile 生成的java文件路径
     */
    public static void generateClass(String abiFile,String binFile,String generateFile){
        String[] args = Arrays.asList(
                "-a",abiFile,
                "-b",binFile,
                "-p","",
                "-o",generateFile
        ).toArray(new String[0]);
        Stream.of(args).forEach(System.out::println);
        SolidityFunctionWrapperGenerator.main(args);
    }
}

智能合约Java代理类使用

  1. 获取私钥。注意在获取的私钥前的0x
    在这里插入图片描述2. 部署合约
package com.yeqifu;

import com.yeqifu.bus.geth.MyContract;
import org.junit.Test;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.gas.DefaultGasProvider;

public class TestMyContract {
    static String nodeUrl = "http://localhost:8546"; // 连接以太坊节点,替换为实际节点URL
    static String contractAddress = "0xd8554b507a868d5d30ff3d2e14b92615c243831e";
    static String privateKey = "0xff9b62e39ec890263e586eab6e5a216c637ba1360381c9eb870ef11884a0b0a6"; // 部署者的私钥

    /**
     * 部署合约
     *
     * @throws Exception
     */
    @Test
    public void deplyContract() throws Exception {
        // RPC调用url(此处为ropsten)
        Web3j web3j = Web3j.build(new HttpService(nodeUrl));
        Credentials credentials = Credentials.create(privateKey);

        MyContract contract = MyContract.deploy(web3j, credentials, new DefaultGasProvider()).sendAsync().get();
        System.out.println("DataStore contract deployed at address: " + contract.getContractAddress());
    }
}

如果在部署过程中出现gas不足或者gas超出限制等问题,可能是由于eth余额不足,可以先进行调用矿工进行掘金。如果排查余额充足,则可能是geth版本问题,Version: 1.8.20-stable版本亲测可用。另外新版的语法于旧版本有所不同。

  • 8
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
以下是使用geth创建基于联盟链的私有区块链,拥有自己的节点和genesis区块,以及创建10个合约账户的步骤: **1. 安装geth** 首先需要安装geth,可以从官网下载二进制文件或者通过包管理器进行安装。 **2. 创建genesis区块** 在创建私有区块链之前,需要先创建genesis区块,可以使用puppeth工具来完成。puppeth是一个命令行工具,可以帮助我们创建和管理私有区块链。 使用以下命令来启动puppeth: ``` puppeth ``` 根据提示进行以下设置: - 输入一个名字来创建一个新的网络 - 选择一个网络类型,选择2(Configure new genesis) - 选择网络协议,选择1(Ethash - proof-of-work) - 选择预分配的币数,输入0 - 输入一个新的地址作为挖矿奖励的收件人地址 - 输入一个新的账户地址,用于签署genesis区块 - 选择一个密码,用于加密私钥 - 选择一个目标平台,选择1(Ethereum) - 选择一个链ID,输入一个数字作为你的私有链ID - 选择是否要使用Clique共识算法,选择2(No) 完成以上设置后,puppeth会自动创建genesis.json文件,该文件包含了我们需要在geth中使用的genesis区块数据。 **3. 初始化节点** 接下来需要初始化节点,使用以下命令: ``` geth --datadir /path/to/chain init /path/to/genesis.json ``` 其中,/path/to/chain是你想要存储区块链数据的目录,/path/to/genesis.json是上一步中生成的genesis.json文件的路径。 **4. 创建账户** 使用以下命令来创建账户: ``` geth --datadir /path/to/chain account new ``` 这将会提示你输入一个密码,该密码将会用于加密账户的私钥。创建完毕后,你将会得到一个账户地址。 重复以上步骤,创建10个账户。 **5. 启动节点** 使用以下命令来启动节点: ``` geth --datadir /path/to/chain --networkid [network_id] --nodiscover console ``` 其中,/path/to/chain是你的区块链数据目录,[network_id]是你在puppeth中设置的私有链ID。 启动后,会进入geth控制台,可以在控制台中进行各种操作,例如挖矿、转账等。 **6. 解锁账户** 在控制台中,使用以下命令来解锁账户: ``` personal.unlockAccount(address, password, duration) ``` 其中,address是你的账户地址,password是你在创建账户时设置的密码,duration是解锁时间,单位为秒。 解锁账户后,可以使用以下命令来查询账户余额: ``` eth.getBalance(address) ``` 以上就是使用geth创建基于联盟链的私有区块链,拥有自己的节点和genesis区块,以及创建10个合约账户的步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Huathy-雨落江南,浮生若梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值