欢迎光临
我们一直在努力

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

文章目录

  • 前言
    • ethers – 区块链变更链上状态与在确认(对账)说明
      • 1. 为什么对账环节采用go比java要好。
      • 2. 测试合约准备
      • 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. 测试合约准备

// 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;
}
}

部署脚本:

// 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左右自动增加。

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. 变更链上状态与在确认(对账)测试

效果: 在这里插入图片描述 区块链网络: 在这里插入图片描述 源码:

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进行对账,观察如下: 在这里插入图片描述 在这里插入图片描述 如果相同,说明对账成功。

源码:

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);

赞(0)
未经允许不得转载:171主机测评 » ethers - 区块链变更链上状态与在确认(对账)说明
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址