From 5c2e68a9bc1f8e73c2ab2a71bf6dd0b5d5845f74 Mon Sep 17 00:00:00 2001 From: federico Date: Fri, 31 Oct 2025 17:19:10 +0800 Subject: [PATCH 1/5] query the voters of witness --- tools/toolkit/README.md | 12 ++ .../main/java/org/tron/plugins/DbQuery.java | 133 ++++++++++++++++++ .../java/org/tron/plugins/utils/Constant.java | 5 + tools/toolkit/src/main/resources/query.conf | 9 ++ 4 files changed, 159 insertions(+) diff --git a/tools/toolkit/README.md b/tools/toolkit/README.md index 082fb589..51f6f8a9 100644 --- a/tools/toolkit/README.md +++ b/tools/toolkit/README.md @@ -210,11 +210,23 @@ reward = [ "TLyqzVGLV1srkB7dToTAEqgDSfPtXRJZYH", "TJvaAeFb8Lykt9RQcVyyTFN2iDvGMuyD4M" ] + +voters = { + allWitnesses = false + witnessList = [ + "TQopP5GM68QoqLzpz8YReDfSoCMkvwcZYd", + "TDpt9adA6QidL1B1sy3D8NC717C6L5JxFo", + ] + threshold = 10000 +} ``` - `vote.allWitnesses`: configure whether to query the vote information of all witnesses. - `vote.witnessList`: configure to query the vote information from specified witness list. The option is valid only when `vote.allWitnesses = false`. - `reward`: configure the address list you need to query the reward. +- `voters.allWitnesses`: configure whether to query the voter information of all witnesses. +- `voters.witnessList`: configure to query the voter information from specified witness list. +- `voters.threshold`: configure the threshold for voter information display. Execute query command. ```shell script diff --git a/tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java b/tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java index 16dc2ff3..d9273be6 100644 --- a/tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java +++ b/tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java @@ -14,6 +14,9 @@ import static org.tron.plugins.utils.Constant.MAINTENANCE_TIME_INTERVAL; import static org.tron.plugins.utils.Constant.NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE; import static org.tron.plugins.utils.Constant.REWARDS_KEY; +import static org.tron.plugins.utils.Constant.VOTERS_ALL_WITNESSES; +import static org.tron.plugins.utils.Constant.VOTERS_WITNESS_LIST; +import static org.tron.plugins.utils.Constant.VOTERS_WITNESS_THRESHOLD; import static org.tron.plugins.utils.Constant.VOTES_ALL_WITNESSES; import static org.tron.plugins.utils.Constant.VOTES_STORE; import static org.tron.plugins.utils.Constant.VOTES_WITNESS_LIST; @@ -43,6 +46,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.bouncycastle.util.encoders.Hex; import org.rocksdb.RocksDBException; +import org.tron.common.utils.Base58; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Commons; import org.tron.common.utils.Pair; @@ -106,6 +110,9 @@ public class DbQuery implements Callable { List rewardAddressList = new ArrayList<>(); Map latestWitnessVi = new HashMap<>(); + boolean allWitnessVoters = false; + List votersWitnessList = new ArrayList<>(); + long threshold; private void initStore() throws IOException, RocksDBException { String srcDir = database + File.separator + "database"; witnessStore = DbTool.getDB(srcDir, WITNESS_STORE); @@ -149,6 +156,7 @@ public Integer call() throws Exception { initStore(); processVotes(queryConfig); processRewards(queryConfig); + processVoters(queryConfig); DbTool.close(); return 0; @@ -413,6 +421,131 @@ private Boolean existInWitnessList(VotesCapsule votesCapsule, List witne return exist.get(); } + private void processVoters(Config config) { + if (config.hasPath(VOTERS_ALL_WITNESSES)) { + allWitnessVoters = config.getBoolean(VOTERS_ALL_WITNESSES); + } + if (config.hasPath(VOTERS_WITNESS_LIST)) { + votersWitnessList = config.getStringList(VOTERS_WITNESS_LIST); + } + + if (!allWitnessVoters && votersWitnessList.isEmpty()) { + spec.commandLine().getOut() + .println("skip the voters query."); + logger.info("skip the voters query."); + return; + } + + if (config.hasPath(VOTERS_WITNESS_THRESHOLD)) { + threshold = config.getLong(VOTERS_WITNESS_THRESHOLD); + } + spec.commandLine().getOut() + .println("start voters query."); + logger.info("start the voters query."); + long start = System.currentTimeMillis(); + Map> votersMap = new HashMap<>(); + DBIterator iterator = accountStore.iterator(); + spec.commandLine().getOut().format("start to query account store: ").println(); + logger.info("begin to query account store: "); + AccountCapsule accountCapsule; + long accountCnt = 0; + for (iterator.seekToFirst(); iterator.valid(); iterator.next()) { + accountCapsule = new AccountCapsule(iterator.getValue()); + ByteString owner = accountCapsule.getAddress(); + accountCapsule.getVotesList().forEach(vote -> { + spec.commandLine().getOut().format("voterAddress: %s", + StringUtil.encode58Check(vote.getVoteAddress().toByteArray())) + .println(); + if (votersMap.get(vote.getVoteAddress()) == null) { + votersMap.put(vote.getVoteAddress(), new HashMap<>()); + } + votersMap.get(vote.getVoteAddress()).put(owner, vote.getVoteCount()); + }); + + accountCnt++; + if (accountCnt % 10000000 == 0) { + spec.commandLine().getOut().format("processed %d accounts", accountCnt) + .println(); + logger.info("processed {} accounts", accountCnt); + } + } + +// DBIterator dbIterator = votesStore.iterator(); +// VotesCapsule votesCapsule; +// long totalVotesCnt = votesStore.size(); +// spec.commandLine().getOut().format("total votes: %d", totalVotesCnt).println(); +// logger.info("total votes: {}", totalVotesCnt); +// long votesCnt = 0; +// for (dbIterator.seekToFirst(); dbIterator.valid(); dbIterator.next()) { +// votesCapsule = new VotesCapsule(dbIterator.getValue()); +// ByteString owner = votesCapsule.getAddress(); +// votesCapsule.getOldVotes().forEach(vote -> { +// ByteString voteAddress = vote.getVoteAddress(); +// long voteCount = vote.getVoteCount(); +// long previousCnt = votersMap.get(voteAddress).get(owner); +// if (voteCount > previousCnt) { +// throw new IllegalArgumentException(" old vote count is greater than previous vote count"); +// } +// votersMap.get(voteAddress).put(owner, previousCnt - voteCount); +// }); +// votesCapsule.getNewVotes().forEach(vote -> { +// ByteString voteAddress = vote.getVoteAddress(); +// long voteCount = vote.getVoteCount(); +// long previousCnt = votersMap.get(voteAddress).getOrDefault(owner, 0L); +// votersMap.get(voteAddress).put(owner, previousCnt + voteCount); +// }); +// +// votesCnt++; +// if (votesCnt % 100 == 0) { +// spec.commandLine().getOut().format("processed %d/%d votes", votesCnt, totalVotesCnt) +// .println(); +// logger.info("processed {}/{} votes", votesCnt, totalVotesCnt); +// } +// } + + long end = System.currentTimeMillis(); + spec.commandLine().getOut() + .format("account db query finished, total time: %d ms.", end - start).println(); + logger.info("account db query finished, total time: {} ms.", end - start); + + if (allWitnessVoters) { + votersMap.entrySet().stream() + .forEach(entry -> { + String witness = StringUtil.encode58Check(entry.getKey().toByteArray()); + spec.commandLine().getOut() + .format("List the voters of witness: %s with votes great than %d: %s.", witness, + threshold).println(); + printVoters(entry.getValue(), threshold); + }); + } + + votersWitnessList.forEach(witness -> { + spec.commandLine().getOut() + .format("List the voters of witness: %s with votes great than %d.", witness, + threshold).println(); + logger.info("List the voters of witness: {} with votes great than {}.", witness, threshold); + Map votesMap = votersMap.get(ByteString.copyFrom(Commons.decode58Check(witness))); + printVoters(votesMap, threshold); + }); + + spec.commandLine().getOut().println("\nEnd of voters query."); + logger.info("End of voters query."); + } + + private void printVoters(Map votersMap, long threshold) { + votersMap.entrySet().stream() + .filter(entry -> entry.getValue() > threshold) + .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) + .forEach(entry -> { + String witness = StringUtil.encode58Check(entry.getKey().toByteArray()); + long voteCount = entry.getValue(); + spec.commandLine().getOut() + .format("voterAddress: %s, vote count: %d", witness, voteCount).println(); + logger.info("voterAddress: {}, vote count: {}", witness, voteCount); + }); + } + + private void processRewards(Config config) { if (config.hasPath(REWARDS_KEY)) { rewardAddressList = config.getStringList(REWARDS_KEY); diff --git a/tools/toolkit/src/main/java/org/tron/plugins/utils/Constant.java b/tools/toolkit/src/main/java/org/tron/plugins/utils/Constant.java index 7fcc380c..2d8951f4 100644 --- a/tools/toolkit/src/main/java/org/tron/plugins/utils/Constant.java +++ b/tools/toolkit/src/main/java/org/tron/plugins/utils/Constant.java @@ -53,6 +53,11 @@ public class Constant { public static final String VOTES_WITNESS_LIST = "vote.witnessList"; public static final int BLOCK_PRODUCED_INTERVAL = 3000; + public static final String VOTERS_ALL_WITNESSES = "voters.allWitnesses"; + public static final String VOTERS_WITNESS_LIST = "voters.witnessList"; + public static final String VOTERS_WITNESS_THRESHOLD = "voters.threshold"; + + public static final String REWARDS_KEY = "reward"; public static final byte[] CHANGE_DELEGATION = "CHANGE_DELEGATION".getBytes(); public static final byte[] CURRENT_CYCLE_NUMBER = "CURRENT_CYCLE_NUMBER".getBytes(); diff --git a/tools/toolkit/src/main/resources/query.conf b/tools/toolkit/src/main/resources/query.conf index a1df2aee..0cbae915 100644 --- a/tools/toolkit/src/main/resources/query.conf +++ b/tools/toolkit/src/main/resources/query.conf @@ -18,3 +18,12 @@ reward = [ "TDaQAfV7gZSPzx5FZ23kenPwLjr3AGxnmH", "TXwrVcWA2BPRMs9gGz5DciT6iwdDKagbpB" ] + +voters = { + allWitnesses = false + witnessList = [ + "TMEQ4hu7DtLTHPn6qPsYktk1QGdTbAyTEK", + "THKJYuUmMKKARNf7s2VT51g5uPY6KEqnat" + ] + threshold = 10000000 +} From 1ac34af593bc28d69a0d4cddc669eec195e17d58 Mon Sep 17 00:00:00 2001 From: federico Date: Fri, 31 Oct 2025 21:51:51 +0800 Subject: [PATCH 2/5] remove the log --- tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java b/tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java index d9273be6..0113cde3 100644 --- a/tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java +++ b/tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java @@ -453,9 +453,6 @@ private void processVoters(Config config) { accountCapsule = new AccountCapsule(iterator.getValue()); ByteString owner = accountCapsule.getAddress(); accountCapsule.getVotesList().forEach(vote -> { - spec.commandLine().getOut().format("voterAddress: %s", - StringUtil.encode58Check(vote.getVoteAddress().toByteArray())) - .println(); if (votersMap.get(vote.getVoteAddress()) == null) { votersMap.put(vote.getVoteAddress(), new HashMap<>()); } From 28f121018cd18b9592cad79e50138af962cc4fd9 Mon Sep 17 00:00:00 2001 From: federico Date: Mon, 3 Nov 2025 14:15:14 +0800 Subject: [PATCH 3/5] query the active witnesses --- .../main/java/org/tron/plugins/DbQuery.java | 107 ++++++++++-------- .../java/org/tron/plugins/utils/Constant.java | 2 + tools/toolkit/src/main/resources/query.conf | 1 + 3 files changed, 61 insertions(+), 49 deletions(-) diff --git a/tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java b/tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java index 0113cde3..5b18d0ba 100644 --- a/tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java +++ b/tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java @@ -14,12 +14,14 @@ import static org.tron.plugins.utils.Constant.MAINTENANCE_TIME_INTERVAL; import static org.tron.plugins.utils.Constant.NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE; import static org.tron.plugins.utils.Constant.REWARDS_KEY; +import static org.tron.plugins.utils.Constant.VOTERS_ALL_ACTIVE_WITNESSES; import static org.tron.plugins.utils.Constant.VOTERS_ALL_WITNESSES; import static org.tron.plugins.utils.Constant.VOTERS_WITNESS_LIST; import static org.tron.plugins.utils.Constant.VOTERS_WITNESS_THRESHOLD; import static org.tron.plugins.utils.Constant.VOTES_ALL_WITNESSES; import static org.tron.plugins.utils.Constant.VOTES_STORE; import static org.tron.plugins.utils.Constant.VOTES_WITNESS_LIST; +import static org.tron.plugins.utils.Constant.WITNESS_SCHEDULE_STORE; import static org.tron.plugins.utils.Constant.WITNESS_STORE; import com.google.common.collect.Maps; @@ -32,6 +34,7 @@ import java.math.BigInteger; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; @@ -46,7 +49,6 @@ import org.apache.commons.collections4.CollectionUtils; import org.bouncycastle.util.encoders.Hex; import org.rocksdb.RocksDBException; -import org.tron.common.utils.Base58; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Commons; import org.tron.common.utils.Pair; @@ -58,6 +60,7 @@ import org.tron.core.capsule.WitnessCapsule; import org.tron.core.exception.BadItemException; import org.tron.core.store.DelegationStore; +import org.tron.plugins.utils.Constant; import org.tron.plugins.utils.FileUtils; import org.tron.plugins.utils.JsonFormat; import org.tron.plugins.utils.db.DBInterface; @@ -78,7 +81,7 @@ public class DbQuery implements Callable { @CommandLine.Spec - CommandLine.Model.CommandSpec spec; + static CommandLine.Model.CommandSpec spec; @CommandLine.Option(names = {"-d", "--database-directory"}, defaultValue = "output-directory", @@ -101,6 +104,7 @@ public class DbQuery implements Callable { private DBInterface blockStore; private DBInterface accountStore; private DBInterface delegationStore; + private DBInterface witnessScheduleStore; boolean allWitness = false; List witnessList = new ArrayList<>(); @@ -111,8 +115,10 @@ public class DbQuery implements Callable { Map latestWitnessVi = new HashMap<>(); boolean allWitnessVoters = false; + boolean allActiveWitnesses = false; List votersWitnessList = new ArrayList<>(); - long threshold; + long threshold = 0; + private void initStore() throws IOException, RocksDBException { String srcDir = database + File.separator + "database"; witnessStore = DbTool.getDB(srcDir, WITNESS_STORE); @@ -122,6 +128,7 @@ private void initStore() throws IOException, RocksDBException { blockStore = DbTool.getDB(srcDir, BLOCK_STORE); accountStore = DbTool.getDB(srcDir, ACCOUNT_STORE); delegationStore = DbTool.getDB(srcDir, DELEGATION_STORE); + witnessScheduleStore = DbTool.getDB(srcDir, WITNESS_SCHEDULE_STORE); } @@ -425,11 +432,14 @@ private void processVoters(Config config) { if (config.hasPath(VOTERS_ALL_WITNESSES)) { allWitnessVoters = config.getBoolean(VOTERS_ALL_WITNESSES); } + if (config.hasPath(VOTERS_ALL_ACTIVE_WITNESSES)) { + allActiveWitnesses = config.getBoolean(VOTERS_ALL_ACTIVE_WITNESSES); + } if (config.hasPath(VOTERS_WITNESS_LIST)) { votersWitnessList = config.getStringList(VOTERS_WITNESS_LIST); } - if (!allWitnessVoters && votersWitnessList.isEmpty()) { + if (!allWitnessVoters && !allActiveWitnesses && votersWitnessList.isEmpty()) { spec.commandLine().getOut() .println("skip the voters query."); logger.info("skip the voters query."); @@ -453,9 +463,7 @@ private void processVoters(Config config) { accountCapsule = new AccountCapsule(iterator.getValue()); ByteString owner = accountCapsule.getAddress(); accountCapsule.getVotesList().forEach(vote -> { - if (votersMap.get(vote.getVoteAddress()) == null) { - votersMap.put(vote.getVoteAddress(), new HashMap<>()); - } + votersMap.computeIfAbsent(vote.getVoteAddress(), k -> new HashMap<>()); votersMap.get(vote.getVoteAddress()).put(owner, vote.getVoteCount()); }); @@ -467,39 +475,6 @@ private void processVoters(Config config) { } } -// DBIterator dbIterator = votesStore.iterator(); -// VotesCapsule votesCapsule; -// long totalVotesCnt = votesStore.size(); -// spec.commandLine().getOut().format("total votes: %d", totalVotesCnt).println(); -// logger.info("total votes: {}", totalVotesCnt); -// long votesCnt = 0; -// for (dbIterator.seekToFirst(); dbIterator.valid(); dbIterator.next()) { -// votesCapsule = new VotesCapsule(dbIterator.getValue()); -// ByteString owner = votesCapsule.getAddress(); -// votesCapsule.getOldVotes().forEach(vote -> { -// ByteString voteAddress = vote.getVoteAddress(); -// long voteCount = vote.getVoteCount(); -// long previousCnt = votersMap.get(voteAddress).get(owner); -// if (voteCount > previousCnt) { -// throw new IllegalArgumentException(" old vote count is greater than previous vote count"); -// } -// votersMap.get(voteAddress).put(owner, previousCnt - voteCount); -// }); -// votesCapsule.getNewVotes().forEach(vote -> { -// ByteString voteAddress = vote.getVoteAddress(); -// long voteCount = vote.getVoteCount(); -// long previousCnt = votersMap.get(voteAddress).getOrDefault(owner, 0L); -// votersMap.get(voteAddress).put(owner, previousCnt + voteCount); -// }); -// -// votesCnt++; -// if (votesCnt % 100 == 0) { -// spec.commandLine().getOut().format("processed %d/%d votes", votesCnt, totalVotesCnt) -// .println(); -// logger.info("processed {}/{} votes", votesCnt, totalVotesCnt); -// } -// } - long end = System.currentTimeMillis(); spec.commandLine().getOut() .format("account db query finished, total time: %d ms.", end - start).println(); @@ -514,22 +489,42 @@ private void processVoters(Config config) { threshold).println(); printVoters(entry.getValue(), threshold); }); - } + } else if (allActiveWitnesses) { + byte[] witnesses = witnessScheduleStore.get(Constant.ACTIVE_WITNESSES); + List activeWitnesses = decodeActiveWitness(witnesses); + spec.commandLine().getOut().format("There are %d active witnesses in db", + activeWitnesses.size()).println(); + logger.info("There are {} active witnesses in db", activeWitnesses.size()); + activeWitnesses.forEach(witness -> { + String witnessBase58 = StringUtil.encode58Check(witness.toByteArray()); + spec.commandLine().getOut() + .format("List the voters of active witness: %s with votes great than %d.", + witnessBase58, threshold).println(); + logger.info("List the voters of active witness: {} with votes great than {}.", + witnessBase58, threshold); + printVoters(votersMap.get(witness), threshold); + }); - votersWitnessList.forEach(witness -> { - spec.commandLine().getOut() - .format("List the voters of witness: %s with votes great than %d.", witness, - threshold).println(); - logger.info("List the voters of witness: {} with votes great than {}.", witness, threshold); - Map votesMap = votersMap.get(ByteString.copyFrom(Commons.decode58Check(witness))); - printVoters(votesMap, threshold); - }); + } else { + votersWitnessList.forEach(witness -> { + spec.commandLine().getOut() + .format("List the voters of witness: %s with votes great than %d.", witness, + threshold).println(); + logger.info("List the voters of witness: {} with votes great than {}.", witness, threshold); + Map votesMap = votersMap.get( + ByteString.copyFrom(Commons.decode58Check(witness))); + printVoters(votesMap, threshold); + }); + } spec.commandLine().getOut().println("\nEnd of voters query."); logger.info("End of voters query."); } private void printVoters(Map votersMap, long threshold) { + if (votersMap == null || votersMap.isEmpty()) { + return; + } votersMap.entrySet().stream() .filter(entry -> entry.getValue() > threshold) .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) @@ -829,4 +824,18 @@ private long getOldReward(long begin, long end, List> votes) return reward; } + public static List decodeActiveWitness(byte[] witnesses) { + if (ByteArray.isEmpty(witnesses) + || witnesses.length % Constant.ADDRESS_BYTE_ARRAY_LENGTH != 0) { + throw new IllegalArgumentException("witnesses is invalid"); + } + + List witnessList = new ArrayList<>(); + for (int i = 0; i < witnesses.length; i += Constant.ADDRESS_BYTE_ARRAY_LENGTH) { + witnessList.add(ByteString.copyFrom( + Arrays.copyOfRange(witnesses, i, i + Constant.ADDRESS_BYTE_ARRAY_LENGTH))); + } + return witnessList; + } + } diff --git a/tools/toolkit/src/main/java/org/tron/plugins/utils/Constant.java b/tools/toolkit/src/main/java/org/tron/plugins/utils/Constant.java index 2d8951f4..ca9f4a36 100644 --- a/tools/toolkit/src/main/java/org/tron/plugins/utils/Constant.java +++ b/tools/toolkit/src/main/java/org/tron/plugins/utils/Constant.java @@ -54,6 +54,8 @@ public class Constant { public static final int BLOCK_PRODUCED_INTERVAL = 3000; public static final String VOTERS_ALL_WITNESSES = "voters.allWitnesses"; + public static final String VOTERS_ALL_ACTIVE_WITNESSES = "voters.allActiveWitnesses"; + public static final String VOTERS_WITNESS_LIST = "voters.witnessList"; public static final String VOTERS_WITNESS_THRESHOLD = "voters.threshold"; diff --git a/tools/toolkit/src/main/resources/query.conf b/tools/toolkit/src/main/resources/query.conf index 0cbae915..4fcdb4cd 100644 --- a/tools/toolkit/src/main/resources/query.conf +++ b/tools/toolkit/src/main/resources/query.conf @@ -21,6 +21,7 @@ reward = [ voters = { allWitnesses = false + allActiveWitnesses = true witnessList = [ "TMEQ4hu7DtLTHPn6qPsYktk1QGdTbAyTEK", "THKJYuUmMKKARNf7s2VT51g5uPY6KEqnat" From 1d738ae2914c664feea4aae44a6eea23002a9705 Mon Sep 17 00:00:00 2001 From: federico Date: Mon, 3 Nov 2025 16:10:22 +0800 Subject: [PATCH 4/5] add the query doc --- tools/toolkit/README.md | 5 ++++- .../src/main/java/org/tron/plugins/DbQuery.java | 10 +++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/tools/toolkit/README.md b/tools/toolkit/README.md index 51f6f8a9..ffce129b 100644 --- a/tools/toolkit/README.md +++ b/tools/toolkit/README.md @@ -213,6 +213,7 @@ reward = [ voters = { allWitnesses = false + allActiveWitnesses = true witnessList = [ "TQopP5GM68QoqLzpz8YReDfSoCMkvwcZYd", "TDpt9adA6QidL1B1sy3D8NC717C6L5JxFo", @@ -225,8 +226,10 @@ voters = { The option is valid only when `vote.allWitnesses = false`. - `reward`: configure the address list you need to query the reward. - `voters.allWitnesses`: configure whether to query the voter information of all witnesses. +- `voters.allActiveWitnesses`: configure whether to query the voter information of all active + witnesses. - `voters.witnessList`: configure to query the voter information from specified witness list. -- `voters.threshold`: configure the threshold for voter information display. +- `voters.threshold`: configure the votes count threshold to filter the voters. Execute query command. ```shell script diff --git a/tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java b/tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java index 5b18d0ba..f56cc50a 100644 --- a/tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java +++ b/tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java @@ -504,7 +504,6 @@ private void processVoters(Config config) { witnessBase58, threshold); printVoters(votersMap.get(witness), threshold); }); - } else { votersWitnessList.forEach(witness -> { spec.commandLine().getOut() @@ -517,8 +516,13 @@ private void processVoters(Config config) { }); } - spec.commandLine().getOut().println("\nEnd of voters query."); + spec.commandLine().getOut().println("End of voters query."); logger.info("End of voters query."); + try { + iterator.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } } private void printVoters(Map votersMap, long threshold) { @@ -526,7 +530,7 @@ private void printVoters(Map votersMap, long threshold) { return; } votersMap.entrySet().stream() - .filter(entry -> entry.getValue() > threshold) + .filter(entry -> entry.getValue() >= threshold) .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) .forEach(entry -> { String witness = StringUtil.encode58Check(entry.getKey().toByteArray()); From f92a08461c5753d28c5658397994501ebdf7bf95 Mon Sep 17 00:00:00 2001 From: federico Date: Tue, 4 Nov 2025 11:39:26 +0800 Subject: [PATCH 5/5] print witness votes count --- .../main/java/org/tron/plugins/DbQuery.java | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java b/tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java index f56cc50a..279176a1 100644 --- a/tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java +++ b/tools/toolkit/src/main/java/org/tron/plugins/DbQuery.java @@ -298,6 +298,12 @@ private void processVotes(Config queryConfig) throws BadItemException { spec.commandLine().getOut().println(cnt.get() + " " + output); logger.info(cnt.get() + " " + output); }); + + try { + iterator.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } } private String formatWitness(WitnessCapsule witnessCapsule, long previousCnt) { @@ -480,9 +486,38 @@ private void processVoters(Config config) { .format("account db query finished, total time: %d ms.", end - start).println(); logger.info("account db query finished, total time: {} ms.", end - start); + Map witnessesMap = new HashMap<>(); + Map oldWitnessCnt = new HashMap<>(); + DBIterator witnessIterator = witnessStore.iterator(); + WitnessCapsule witnessCapsule; + for (witnessIterator.seekToFirst(); witnessIterator.valid(); witnessIterator.next()) { + witnessCapsule = new WitnessCapsule(witnessIterator.getValue()); + witnessesMap.put(ByteString.copyFrom(witnessIterator.getKey()), witnessCapsule); + oldWitnessCnt.put(witnessCapsule.getAddress(), witnessCapsule.getVoteCount()); + } + Map countWitness = countVote(); + countWitness.forEach((address, voteCount) -> { + WitnessCapsule witness = witnessesMap.get(address); + if (witness == null) { + throw new IllegalStateException("witness not exist"); + } + witness.setVoteCount(witness.getVoteCount() + voteCount); + witnessesMap.put(address, witness); + }); + + AtomicInteger cnt = new AtomicInteger(); + cnt.set(-1); if (allWitnessVoters) { votersMap.entrySet().stream() .forEach(entry -> { + WitnessCapsule witnessTmp = witnessesMap.get(entry.getKey()); + if (witnessTmp == null) { + throw new IllegalStateException("witness not exist"); + } + cnt.getAndIncrement(); + String output = formatWitness(witnessTmp, oldWitnessCnt.get(entry.getKey())); + spec.commandLine().getOut().println(cnt.get() + " " + output); + String witness = StringUtil.encode58Check(entry.getKey().toByteArray()); spec.commandLine().getOut() .format("List the voters of witness: %s with votes great than %d: %s.", witness, @@ -496,6 +531,14 @@ private void processVoters(Config config) { activeWitnesses.size()).println(); logger.info("There are {} active witnesses in db", activeWitnesses.size()); activeWitnesses.forEach(witness -> { + WitnessCapsule witnessTmp = witnessesMap.get(witness); + if (witnessTmp == null) { + throw new IllegalStateException("witness not exist"); + } + cnt.getAndIncrement(); + String output = formatWitness(witnessTmp, oldWitnessCnt.get(witness)); + spec.commandLine().getOut().println(cnt.get() + " " + output); + String witnessBase58 = StringUtil.encode58Check(witness.toByteArray()); spec.commandLine().getOut() .format("List the voters of active witness: %s with votes great than %d.", @@ -506,12 +549,22 @@ private void processVoters(Config config) { }); } else { votersWitnessList.forEach(witness -> { + ByteString address = ByteString.copyFrom(Commons.decode58Check(witness)); + if (!witnessesMap.containsKey(address)) { + spec.commandLine().getErr().format("address: %s is not a witness", witness).println(); + logger.error("address: {} is not a witness", witness); + return; + } + + cnt.getAndIncrement(); + String output = formatWitness(witnessesMap.get(address), oldWitnessCnt.get(address)); + spec.commandLine().getOut().println(cnt.get() + " " + output); + spec.commandLine().getOut() .format("List the voters of witness: %s with votes great than %d.", witness, threshold).println(); logger.info("List the voters of witness: {} with votes great than {}.", witness, threshold); - Map votesMap = votersMap.get( - ByteString.copyFrom(Commons.decode58Check(witness))); + Map votesMap = votersMap.get(address); printVoters(votesMap, threshold); }); } @@ -520,6 +573,7 @@ private void processVoters(Config config) { logger.info("End of voters query."); try { iterator.close(); + witnessIterator.close(); } catch (IOException e) { throw new RuntimeException(e); }