-
Notifications
You must be signed in to change notification settings - Fork 1.6k
feat(*): optimize old rewards withdrawal #5742
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b09d19c
ac45bb9
9f683a9
98eb058
2d29a9d
9443ce1
4811675
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,7 +3,6 @@ | |
| import static org.tron.core.store.DelegationStore.DECIMAL_OF_VI_REWARD; | ||
| import static org.tron.core.store.DelegationStore.REMARK; | ||
|
|
||
| import com.google.common.annotations.VisibleForTesting; | ||
| import com.google.common.collect.Streams; | ||
| import com.google.common.primitives.Bytes; | ||
| import com.google.protobuf.ByteString; | ||
|
|
@@ -18,7 +17,6 @@ | |
| import java.util.stream.Collectors; | ||
| import java.util.stream.LongStream; | ||
| import javax.annotation.PreDestroy; | ||
| import lombok.Setter; | ||
| import lombok.extern.slf4j.Slf4j; | ||
| import org.bouncycastle.util.encoders.Hex; | ||
| import org.springframework.beans.factory.annotation.Autowired; | ||
|
|
@@ -27,9 +25,9 @@ | |
| import org.tron.common.es.ExecutorServiceManager; | ||
| import org.tron.common.parameter.CommonParameter; | ||
| import org.tron.common.utils.ByteArray; | ||
| import org.tron.common.utils.MerkleRoot; | ||
| import org.tron.common.utils.Pair; | ||
| import org.tron.common.utils.Sha256Hash; | ||
| import org.tron.core.capsule.utils.MerkleTree; | ||
| import org.tron.core.db.common.iterator.DBIterator; | ||
| import org.tron.core.db2.common.DB; | ||
| import org.tron.core.store.DelegationStore; | ||
|
|
@@ -55,10 +53,11 @@ public class RewardViCalService { | |
|
|
||
| private volatile long lastBlockNumber = -1; | ||
|
|
||
| @VisibleForTesting | ||
| @Setter | ||
| private Sha256Hash rewardViRoot = Sha256Hash.wrap( | ||
| ByteString.fromHex("9debcb9924055500aaae98cdee10501c5c39d4daa75800a996f4bdda73dbccd8")); | ||
| private static final String MAIN_NET_ROOT_HEX = | ||
| "9debcb9924055500aaae98cdee10501c5c39d4daa75800a996f4bdda73dbccd8"; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this root hex is already configured in conf. here it is declared again. Should it be possible for this value declared in one place instead of two different files?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is to ensure that the main-net node does not need to change the configuration file. |
||
|
|
||
| private final Sha256Hash rewardViRoot = CommonParameter.getInstance().getStorage().getDbRoot( | ||
| "reward-vi", Sha256Hash.wrap(ByteString.fromHex(MAIN_NET_ROOT_HEX))); | ||
|
|
||
| private final CountDownLatch lock = new CountDownLatch(1); | ||
|
|
||
|
|
@@ -99,25 +98,30 @@ private boolean isDone() { | |
| } | ||
|
|
||
| private void maybeRun() { | ||
| if (enableNewRewardAlgorithm()) { | ||
| if (this.newRewardCalStartCycle > 1) { | ||
| if (isDone()) { | ||
| this.clearUp(true); | ||
| logger.info("rewardViCalService is already done"); | ||
| } else { | ||
| if (lastBlockNumber == Long.MAX_VALUE // start rewardViCalService immediately | ||
| || this.getLatestBlockHeaderNumber() > lastBlockNumber) { | ||
| // checkpoint is flushed to db, so we can start rewardViCalService | ||
| startRewardCal(); | ||
| clearUp(true); | ||
| try { | ||
| if (enableNewRewardAlgorithm()) { | ||
| if (this.newRewardCalStartCycle > 1) { | ||
| if (isDone()) { | ||
| this.clearUp(true); | ||
| logger.info("rewardViCalService is already done"); | ||
| } else { | ||
| logger.info("startRewardCal will run after checkpoint is flushed to db"); | ||
| if (lastBlockNumber == Long.MAX_VALUE // start rewardViCalService immediately | ||
| || this.getLatestBlockHeaderNumber() > lastBlockNumber) { | ||
| // checkpoint is flushed to db, so we can start rewardViCalService | ||
| startRewardCal(); | ||
| clearUp(true); | ||
| } else { | ||
| logger.info("startRewardCal will run after checkpoint is flushed to db"); | ||
| } | ||
| } | ||
| } else { | ||
| clearUp(false); | ||
| logger.info("rewardViCalService is no need to run"); | ||
| } | ||
| } else { | ||
| clearUp(false); | ||
| logger.info("rewardViCalService is no need to run"); | ||
| } | ||
| } catch (Exception e) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In which case shall it throw an Exception?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Such as |
||
| logger.error(" Find fatal error, program will be exited soon.", e); | ||
| System.exit(1); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -137,7 +141,7 @@ private void destroy() { | |
|
|
||
| public long getNewRewardAlgorithmReward(long beginCycle, long endCycle, | ||
| List<Pair<byte[], Long>> votes) { | ||
| if (!rewardViStore.has(IS_DONE_KEY)) { | ||
| if (!isDone()) { | ||
| logger.warn("rewardViCalService is not done, wait for it"); | ||
| try { | ||
| lock.await(); | ||
|
|
@@ -174,10 +178,13 @@ private void calcMerkleRoot() { | |
| .map(this::getHash) | ||
| .collect(Collectors.toCollection(ArrayList::new)); | ||
|
|
||
| Sha256Hash rewardViRootLocal = MerkleTree.getInstance().createTree(ids).getRoot().getHash(); | ||
| Sha256Hash rewardViRootLocal = MerkleRoot.root(ids); | ||
| if (!Objects.equals(rewardViRoot, rewardViRootLocal)) { | ||
| logger.warn("merkle root mismatch, expect: {}, actual: {}", | ||
| rewardViRoot, rewardViRootLocal); | ||
| logger.warn("Merkle root mismatch, expect: {}, actual: {}." | ||
| + " If you are quite sure that there is no miscalculation (not on the main network)" | ||
| + ", please configure 'storage.merkleRoot.reward-vi = {}'" | ||
| + "(for a specific network such as Nile, etc.) in config.conf to fix the hints", | ||
| rewardViRoot, rewardViRootLocal, rewardViRootLocal); | ||
| } | ||
| logger.info("calcMerkleRoot: {}", rewardViRootLocal); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| package org.tron.common.utils; | ||
|
|
||
| import java.util.List; | ||
| import java.util.stream.Collectors; | ||
| import java.util.stream.IntStream; | ||
| import lombok.Getter; | ||
|
|
||
| public class MerkleRoot { | ||
|
|
||
| private MerkleRoot() { | ||
|
|
||
| } | ||
|
|
||
| public static Sha256Hash root(List<Sha256Hash> hashList) { | ||
| List<Leaf> leaves = createLeaves(hashList); | ||
| while (leaves.size() > 1) { | ||
| leaves = createParentLeaves(leaves); | ||
| } | ||
| return leaves.isEmpty() ? Sha256Hash.ZERO_HASH : leaves.get(0).hash; | ||
| } | ||
|
|
||
| private static List<Leaf> createParentLeaves(List<Leaf> leaves) { | ||
| int step = 2; | ||
| int len = leaves.size(); | ||
| return IntStream.iterate(0, i -> i + step) | ||
| .limit(len) | ||
| .filter(i -> i < len) | ||
| .mapToObj(i -> { | ||
| Leaf right = i + 1 < len ? leaves.get(i + 1) : null; | ||
| return createLeaf(leaves.get(i), right); | ||
| }).collect(Collectors.toList()); | ||
| } | ||
|
|
||
| private static List<Leaf> createLeaves(List<Sha256Hash> hashList) { | ||
| int step = 2; | ||
| int len = hashList.size(); | ||
| return IntStream.iterate(0, i -> i + step) | ||
| .limit(len) | ||
| .filter(i -> i < len) | ||
| .mapToObj(i -> { | ||
| Leaf right = i + 1 < len ? createLeaf(hashList.get(i + 1)) : null; | ||
| return createLeaf(createLeaf(hashList.get(i)), right); | ||
| }).collect(Collectors.toList()); | ||
| } | ||
|
|
||
| private static Leaf createLeaf(Leaf left, Leaf right) { | ||
| Leaf leaf = new Leaf(); | ||
| leaf.hash = right == null ? left.hash : computeHash(left.hash, right.hash); | ||
| return leaf; | ||
| } | ||
|
|
||
| private static Leaf createLeaf(Sha256Hash hash) { | ||
| Leaf leaf = new Leaf(); | ||
| leaf.hash = hash; | ||
| return leaf; | ||
| } | ||
|
|
||
| private static Sha256Hash computeHash(Sha256Hash leftHash, Sha256Hash rightHash) { | ||
| return Sha256Hash.of(true, | ||
| leftHash.getByteString().concat(rightHash.getByteString()).toByteArray()); | ||
| } | ||
|
|
||
| @Getter | ||
| private static class Leaf { | ||
|
|
||
| private Sha256Hash hash; | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a varible method
closeand a method with the same name in this class, maybe you should use different names to distinguish them.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No changes for now.