Web3j 获取区块 ID - 使用时间戳高效查找
要根据时间戳获得块id,可以使用以下代码:
public static BigInteger getBlockIdByTimestamp(Web3j web3j, long timestamp) throws Exception {
BigInteger latestBlockNumber = web3j.ethBlockNumber().send().getBlockNumber();
BigInteger earliestBlockNumber = BigInteger.ZERO;
while (latestBlockNumber.compareTo(earliestBlockNumber) >= 0) {
BigInteger midBlockNumber = latestBlockNumber.add(earliestBlockNumber).divide(BigInteger.valueOf(2));
EthBlock midBlock = web3j.ethGetBlockByNumber(DefaultBlockParameter.valueOf(midBlockNumber), true).send();
if (midBlock.getBlock() != null && midBlock.getBlock().getTimestamp().longValue() >= timestamp) {
// 优化:根据时间差计算减多少
long timeDifference = midBlock.getBlock().getTimestamp().longValue() - timestamp;
latestBlockNumber = midBlockNumber.subtract(BigInteger.valueOf(timeDifference / 3000 + 1)); // 每个块ID大约3秒,所以除以3000并加1
} else {
earliestBlockNumber = midBlockNumber.add(BigInteger.ONE);
}
}
// 检查最早的块是否在时间范围内
EthBlock earliestBlock = web3j.ethGetBlockByNumber(DefaultBlockParameter.valueOf(earliestBlockNumber), true).send();
if (earliestBlock.getBlock() != null && earliestBlock.getBlock().getTimestamp().longValue() >= timestamp) {
return earliestBlock.getBlock().getNumber();
}
return null;
}
这个方法使用二分查找来找到最接近给定时间戳的块。首先,它获取当前最新的块号和初始块号(0)。然后,它在这个范围内进行二分查找,直到找到最接近时间戳的块。最后,它检查找到的块是否在时间范围内,并返回块号。
为了满足每隔三秒产生一个块id的条件,可以在循环中加入等待时间的逻辑。代码如下:
public static BigInteger getBlockIdByTimestamp(Web3j web3j, long timestamp) throws Exception {
BigInteger latestBlockNumber = web3j.ethBlockNumber().send().getBlockNumber();
BigInteger earliestBlockNumber = BigInteger.ZERO;
while (latestBlockNumber.compareTo(earliestBlockNumber) >= 0) {
BigInteger midBlockNumber = latestBlockNumber.add(earliestBlockNumber).divide(BigInteger.valueOf(2));
EthBlock midBlock = web3j.ethGetBlockByNumber(DefaultBlockParameter.valueOf(midBlockNumber), true).send();
if (midBlock.getBlock() != null && midBlock.getBlock().getTimestamp().longValue() >= timestamp) {
// 优化:根据时间差计算减多少
long timeDifference = midBlock.getBlock().getTimestamp().longValue() - timestamp;
latestBlockNumber = midBlockNumber.subtract(BigInteger.valueOf(timeDifference / 3000 + 1)); // 每个块ID大约3秒,所以除以3000并加1
} else {
earliestBlockNumber = midBlockNumber.add(BigInteger.ONE);
}
// 等待 3 秒
Thread.sleep(3000);
}
// 检查最早的块是否在时间范围内
EthBlock earliestBlock = web3j.ethGetBlockByNumber(DefaultBlockParameter.valueOf(earliestBlockNumber), true).send();
if (earliestBlock.getBlock() != null && earliestBlock.getBlock().getTimestamp().longValue() >= timestamp) {
return earliestBlock.getBlock().getNumber();
}
return null;
}
这个方法每次循环结束后会等待3秒钟,以满足每隔三秒产生一个块id的条件。
原文地址: https://www.cveoy.top/t/topic/fVbK 著作权归作者所有。请勿转载和采集!