ethers - 区块链变更链上状态与在确认(对账)说明

文章目录

  • 前言
    • [ethers - 区块链变更链上状态与在确认(对账)说明](#ethers - 区块链变更链上状态与在确认(对账)说明)
      • [1. 为什么对账环节采用go比java要好。](#1. 为什么对账环节采用go比java要好。)
      • [2. 测试合约准备](#2. 测试合约准备)
      • [3. 变更链上状态与在确认(对账)测试](#3. 变更链上状态与在确认(对账)测试)

前言

  如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。

  而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!!


ethers - 区块链变更链上状态与在确认(对账)说明

链上所有交互都存在区块重组的风险,不能交易一上链就直接判定业务变更成功。

最稳妥的标准做法是:等到该笔交易所在区块,往前追溯满 20 个区块确认,确认交易已落在最终固化链上,同时交易回执 status=1,双重条件都满足,才能判定这笔链上交易真正生效、业务变更最终成功。

我这边先用 ethers 写脚本做演示和 Demo 说明;但在真实生产环境里,链上最终确认与对账环节,行业普遍首选 Go 开发,当然用 Java 也能实现,只是并不做优先推荐。

如果自身业务交易频率很低、体量不大,完全可以基于 tx_hash 做链上核验和对账确认,这种场景下直接用 Java 来实现也是完全可行的。

1. 为什么对账环节采用go比java要好。

1、 内存占用极低,常驻运行更稳;

Go 编译原生二进制,空闲内存只需几十 MB;Java 依赖 JVM,基线内存动辄几百 MB,长期 7×24 小时跑对账服务,Java 更容易堆内存波动、GC 卡顿。

2、 部署运维极简,无环境依赖;

Go 编译单二进制文件,丢服务器直接启动,无需装运行环境、不用调 JVM 参数、不用关心 GC 配置;Java 必须依赖 JDK,还要调堆内存、GC 策略,发布重启流程更繁琐。

3、 I/O 模型适配链上轮询场景;

对账是典型RPC 网络 I/O 密集型 ,Go 原生轻量协程、异步 I/O 开销极小;Java 线程开销大、异步回调层级深,做区块轮询、日志拉取、断点补块,Go 写法更简洁高效。

4、 Web3 原生生态垄断;

以太坊 Geth 节点、公链客户端、链上监听 / 对账 / 清算中间件,底层全是 Go ;链上 SDK、节点交互、区块日志解析,Go 生态坑更少、适配更原生,Java Web3j 生态相对冷门、遇到问题排查资料少。

5、 启动快、故障恢复快;

对账服务需要重启补块、版本迭代、宕机自愈;Go 秒级启动,立刻接续断点区块同步;Java 启动慢、冷启动耗时久,故障恢复窗口期更长,容易漏数据、积压对账任务。

6、 服务轻量化,不冗余 ;

链上对账只是独立小守护服务,Go 轻量化刚刚好;Java 适合大型复杂业务系统,用来做单一对账属于重型框架干轻活,资源浪费、架构冗余。

2. 测试合约准备

js 复制代码
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;




import "hardhat/console.sol";


contract Counter {
    uint counter;

    event CounterInc(uint counter);

    function count() public {
        counter++;
        // console.log("Now, counter is: ", counter);
        emit CounterInc(counter);
    }

    function getCount() public view returns (uint) {
        return counter;
    }
}

部署脚本:

js 复制代码
// Hardhat 和 ethers.js 的「桥梁」,负责注册插件,让两者能协同工作;
import "@nomicfoundation/hardhat-ethers";
import { ethers } from "hardhat";


// HelloWorld 合约
async function contract(){
  console.log("开始部署 Counter 合约...");
  // 获取合约工厂
  const Counter = await ethers.getContractFactory("Counter");
  // 部署合约
  const counter = await Counter.deploy();
//   const helloWorld = await HelloWorld.deploy({
//     gasPrice: ethers.parseUnits("1000", "gwei"), // 1 Gwei = 10^9 wei
//   });
  await counter.waitForDeployment();
  // v6新版获取地址方式
  const contractAddress = await counter.getAddress();
  return contractAddress;
}

async function deploy() {

  const contractAddress = await contract();
  console.log(`Counter 部署完成!`);
  console.log(`合约地址: ${contractAddress}`);
}

// 启动 本地网络  npx hardhat node
deploy()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error("部署失败:", error);
    process.exit(1);
  });

注意的是hardhat,本地区块链网络需要添加如下,因为本地网络不会像公链那样平均大概15s左右自动增加。

bash 复制代码
 hardhat: {
      chainId: 31337, // Hardhat本地链官方默认链ID,无额外自定义
      mining: {
        auto: true,
        interval: [3000, 5000] // 3~5秒出一个块 模拟生产
      }
    },
    localhost: {
      url: "http://127.0.0.1:8545",
      chainId: 31337,
      blockGasLimit: 16777216, // 提高硬hat节点区块gas上限
      gas: 16777216 // 全局默认gas limit

    }
  }

部署合约:

3. 变更链上状态与在确认(对账)测试

效果:

区块链网络:

源码:

js 复制代码
import { ethers } from "ethers";




const abi = [
  "function count() public",
  "function getCount() public view returns (uint256)"
]


const contractAddress = "0x5FbDB2315678afecb367f032d93F642f64180aa3";

async function main() {

  const URL = `http://127.0.0.1:8545`;
  const provider = new ethers.JsonRpcProvider(URL);
  const signer = await provider.getSigner();
  // 连接到本地的 Hardhat 节点 ,并创建合约实例
  // 这里必须使用 signer 来创建合约实例,因为我们需要发送交易来调用 count 方法,这需要签名权限
  const counter = new ethers.Contract(contractAddress, abi, signer);
  // 获取当前 count 的值 ,并打印出来  
  const before = await counter.getCount();
  console.log("count 初始值:", before.toString());
  // 调用合约的 count 方法,并等待交易上链完成
  const tx = await counter.count();
  // 等待交易上链完成
  console.log("交易已发送,等待确认...");
  await tx.wait();
  console.log("交易上链完成:", tx.hash);
   
}


main().catch(console.error);

对账测试:

然后通过几个变量来判断,是否有效,

1、该交易所在区块是在当前区块前20 block的;

2、 removed: false, 事件没有被区块重组移除,是有效事件;

3、 blockNumber: 184,有区块号,代表 交易已上链,没有区块号,代表还在pending中;

4、 transactionHash存在且不为空。

然后通过 transactionHash进行对账,观察如下:

如果相同,说明对账成功。

源码:

js 复制代码
import { ethers } from "ethers";


const abi = [
  "event CounterInc(uint256 counter)"
];


const contractAddress = "0x5FbDB2315678afecb367f032d93F642f64180aa3";


async function main() {


  const URL = `http://127.0.0.1:8545`;
  const provider = new ethers.JsonRpcProvider(URL);
  // 连接到本地的 Hardhat 节点 ,并创建合约实例
  const counter = new ethers.Contract(contractAddress, abi, provider);
 
  // 获取当前区块高度
  const currentBlock = await provider.getBlockNumber();
  const block = currentBlock - 20;
  console.log("当前区块高度:", currentBlock);
  const fromBlock = currentBlock >= 20 ? currentBlock - 40 : 0;
  console.log("查询区块范围:", fromBlock, "到", block);
  // 查询过去 20 个区块内的 CounterInc 事件(查前 20 块安全防重组)
  const events = await counter.queryFilter(
    "CounterInc",
    fromBlock,
    block
  );
  console.log("找到事件数:", events.length);
  if (events.length > 0) {
    const lastEvent = events[events.length - 1];
    // 打印最后一个事件的 counter 参数值
    console.log(lastEvent);
    console.log("事件返回 count =", lastEvent.args.counter.toString());
  }
}

main().catch(console.error);
相关推荐
Jinkxs2 小时前
Java 跨域14-Java 与区块链(Hyperledger)集成
java·开发语言·区块链
cmes_love2 小时前
期货Level 2五档Tick历史数据详解
区块链
Man on the moon3 小时前
Solidity 零基础入门:从语法到实战,快速掌握智能合约开发
web3·区块链·智能合约
电报号dapp1193 小时前
DApp经济模型设计:2026年反泡沫完全指南
区块链·智能合约·哈希算法
CTA终结者5 小时前
期货开仓前保证金够吗:get_account 可用与占用字段对照
python·区块链
开源量化GO5 小时前
夜盘白盘衔接几分钟误下单:天勤交易时段与行情过滤
python·区块链
CTA量化套保10 小时前
一个账户跑多个期货策略:仓位与报单隔离思路
python·区块链
zhuhai_xigedian13 小时前
区块链技术加持:源网荷储系统的能源数据安全与溯源
大数据·区块链·能源
Jay-r15 小时前
智能合约开发中13种最常见漏洞及修复(精华版)
安全·web安全·区块链·智能合约·solidity