Skip to content

Commit

Permalink
change getting data from root db
Browse files Browse the repository at this point in the history
  • Loading branch information
halibobo1205 committed Nov 23, 2023
1 parent f629a8c commit 19952bf
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 37 deletions.
25 changes: 22 additions & 3 deletions chainbase/src/main/java/org/tron/core/service/MortgageService.java
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,25 @@ public long queryReward(byte[] address) {
return reward + accountCapsule.getAllowance();
}

private long computeReward(long cycle, AccountCapsule accountCapsule) {
long reward = 0;
for (Vote vote : accountCapsule.getVotesList()) {
byte[] srAddress = vote.getVoteAddress().toByteArray();
long totalReward = delegationStore.getReward(cycle, srAddress);
long totalVote = delegationStore.getWitnessVote(cycle, srAddress);
if (totalVote == DelegationStore.REMARK || totalVote == 0) {
continue;
}
long userVote = vote.getVoteCount();
double voteRate = (double) userVote / totalVote;
reward += voteRate * totalReward;
logger.debug("ComputeReward {}, {}, {}, {}, {}, {}, {}.", cycle,
Hex.toHexString(accountCapsule.getAddress().toByteArray()), Hex.toHexString(srAddress),
userVote, totalVote, totalReward, reward);
}
return reward;
}

/**
* Compute reward from begin cycle to end cycle, which endCycle must greater than beginCycle.
* While computing reward after new reward algorithm taking effective cycle number,
Expand Down Expand Up @@ -244,12 +263,12 @@ private void sortWitness(List<ByteString> list) {

private long getOldReward(long beginCycle, long oldEndCycle, AccountCapsule accountCapsule) {
if (beginCycle + 1 == oldEndCycle) {
return rewardCalService.computeReward(beginCycle, accountCapsule.getInstance());
return computeReward(beginCycle, accountCapsule);
}
long cacheData = rewardCalService.getReward(accountCapsule.createDbKey(), beginCycle);
long cacheData = rewardCalService.getRewardCache(accountCapsule.createDbKey(), beginCycle);
long reward = 0;
for (long cycle = beginCycle; cycle < oldEndCycle; cycle++) {
reward += rewardCalService.computeReward(cycle, accountCapsule.getInstance());
reward += computeReward(cycle, accountCapsule);
}
if (cacheData != -1 && cacheData != reward) {
logger.error("Old reward algorithm reward not equal, address {}, beginCycle {}, "
Expand Down
122 changes: 89 additions & 33 deletions chainbase/src/main/java/org/tron/core/service/RewardCalService.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
package org.tron.core.service;

import static org.tron.core.store.DelegationStore.REMARK;

import com.google.common.primitives.Bytes;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.protobuf.InvalidProtocolBufferException;
import io.prometheus.client.Histogram;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.LongStream;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.util.encoders.Hex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.tron.common.prometheus.MetricKeys;
import org.tron.common.prometheus.Metrics;
import org.tron.common.utils.ByteArray;
import org.tron.core.Constant;
import org.tron.core.db.common.iterator.DBIterator;
import org.tron.core.db2.common.DB;
import org.tron.core.store.AccountStore;
import org.tron.core.store.CheckTmpStore;
import org.tron.core.store.DelegationStore;
import org.tron.core.store.DynamicPropertiesStore;
import org.tron.core.store.RewardCacheStore;
Expand All @@ -28,18 +35,16 @@
@Component
@Slf4j(topic = "rewardCalService")
public class RewardCalService {
@Autowired
private DynamicPropertiesStore propertiesStore;
@Autowired
private DelegationStore delegationStore;

@Autowired
private AccountStore accountStore;
private final DB<byte[], byte[]> propertiesStore;
private final DB<byte[], byte[]> delegationStore;
private final DB<byte[], byte[]> accountStore;

@Autowired
private RewardCacheStore rewardCacheStore;

private DBIterator accountIterator;
@Autowired
private CheckTmpStore checkTmpStore;

private byte[] isDoneKey;
private static final byte[] IS_DONE_VALUE = new byte[]{0x01};
Expand All @@ -54,16 +59,24 @@ public class RewardCalService {
private final ExecutorService es = Executors.newSingleThreadExecutor(
new ThreadFactoryBuilder().setNameFormat("rewardCalService").build());


@Autowired
public RewardCalService(@Autowired DynamicPropertiesStore propertiesStore,
@Autowired DelegationStore delegationStore, @Autowired AccountStore accountStore) {
this.propertiesStore = propertiesStore.getDb();
this.delegationStore = delegationStore.getDb();
this.accountStore = accountStore.getDb();
}

@PostConstruct
private void init() throws IOException {
newRewardCalStartCycle = propertiesStore.getNewRewardAlgorithmEffectiveCycle();
this.newRewardCalStartCycle = this.getNewRewardAlgorithmEffectiveCycle();
if (newRewardCalStartCycle != Long.MAX_VALUE) {
isDoneKey = ByteArray.fromLong(newRewardCalStartCycle);
if (rewardCacheStore.has(isDoneKey)) {
logger.info("RewardCalService is already done");
return;
}
accountIterator = (DBIterator) accountStore.getDb().iterator();
calReward();
}
}
Expand All @@ -79,13 +92,12 @@ public void calReward() throws IOException {
}

public void calRewardForTest() throws IOException {
newRewardCalStartCycle = propertiesStore.getNewRewardAlgorithmEffectiveCycle();
this.newRewardCalStartCycle = this.getNewRewardAlgorithmEffectiveCycle();
isDoneKey = ByteArray.fromLong(newRewardCalStartCycle);
if (rewardCacheStore.has(isDoneKey)) {
logger.info("RewardCalService is already done");
return;
}
accountIterator = (DBIterator) accountStore.getDb().iterator();
initLastAccount();
startRewardCal();
}
Expand All @@ -107,7 +119,7 @@ private void startRewardCal() {
return;
}
logger.info("RewardCalService start from lastAccount: {}", ByteArray.toHexString(lastAccount));
((DBIterator) delegationStore.getDb().iterator()).prefixQueryAfterThat(
((DBIterator) delegationStore.iterator()).prefixQueryAfterThat(
new byte[]{Constant.ADD_PRE_FIX_BYTE_MAINNET}, lastAccount).forEachRemaining(e -> {
try {
doRewardCal(e.getKey(), ByteArray.toLong(e.getValue()));
Expand All @@ -123,10 +135,13 @@ private void doRewardCal(byte[] address, long beginCycle) throws InterruptedExce
if (beginCycle >= newRewardCalStartCycle) {
return;
}
long endCycle = delegationStore.getEndCycle(address);
long endCycle = this.getEndCycle(address);
if (endCycle >= newRewardCalStartCycle) {
return;
}
if (beginCycle >= endCycle) {
return;
}
//skip the last cycle reward
boolean skipLastCycle = beginCycle + 1 == endCycle;
if (skipLastCycle) {
Expand All @@ -136,42 +151,39 @@ private void doRewardCal(byte[] address, long beginCycle) throws InterruptedExce
return;
}

Protocol.Account account = getAccount(address);
if (account == null || account.getVotesList().isEmpty()) {
List<Protocol.Vote> votesList = this.getVotesList(address);
if (votesList.isEmpty()) {
return;
}
Histogram.Timer requestTimer = Metrics.histogramStartTimer(
MetricKeys.Histogram.DO_REWARD_CAL_DELAY,
(newRewardCalStartCycle - beginCycle) / 100 + "");
long reward = LongStream.range(beginCycle, newRewardCalStartCycle)
.map(i -> computeReward(i, account))
.map(i -> computeReward(i, votesList))
.sum();
this.putReward(address, beginCycle, endCycle, reward, skipLastCycle);
this.putReward(address, beginCycle, endCycle, reward, votesList, skipLastCycle);
Metrics.histogramObserve(requestTimer);
}

private Protocol.Account getAccount(byte[] address) {
private List<Protocol.Vote> getVotesList(byte[] address) {
try {
accountIterator.seek(address);
if (accountIterator.hasNext()) {
byte[] account = accountIterator.next().getValue();
return Protocol.Account.parseFrom(account);
}
byte[] account = this.accountStore.get(address);
return Protocol.Account.parseFrom(account).getVotesList();
} catch (InvalidProtocolBufferException e) {
logger.error("getAccount error: {}", e.getMessage());
}
return null;
return new ArrayList<>();
}

long computeReward(long cycle, Protocol.Account account) {
private long computeReward(long cycle, List<Protocol.Vote> votesList) {
long reward = 0;
for (Protocol.Vote vote : account.getVotesList()) {
for (Protocol.Vote vote : votesList) {
byte[] srAddress = vote.getVoteAddress().toByteArray();
long totalReward = delegationStore.getReward(cycle, srAddress);
long totalReward = this.getReward(cycle, srAddress);
if (totalReward <= 0) {
continue;
}
long totalVote = delegationStore.getWitnessVote(cycle, srAddress);
long totalVote = this.getWitnessVote(cycle, srAddress);
if (totalVote <= 0) {
continue;
}
Expand All @@ -182,24 +194,68 @@ long computeReward(long cycle, Protocol.Account account) {
return reward;
}

public long getReward(byte[] address, long cycle) {
public long getRewardCache(byte[] address, long cycle) {
return rewardCacheStore.getReward(buildKey(address, cycle));
}

private void putReward(byte[] address, long start, long end, long reward, boolean skipLastCycle) {
long startCycle = delegationStore.getBeginCycle(address);
long endCycle = delegationStore.getEndCycle(address);
private void putReward(byte[] address, long start, long end, long reward,
List<Protocol.Vote> votesList, boolean skipLastCycle) {
long startCycle = this.getBeginCycle(address);
long endCycle = this.getEndCycle(address);
//skip the last cycle reward
if (skipLastCycle) {
startCycle += 1;
}
List<Protocol.Vote> newVotesList = this.getVotesList(address);
// check if the delegation is still valid
if (startCycle == start && endCycle == end) {
if (startCycle == start && endCycle == end && votesList.equals(newVotesList)) {
rewardCacheStore.putReward(buildKey(address, start), reward);
}
}

private byte[] buildKey(byte[] address, long beginCycle) {
return Bytes.concat(address, ByteArray.fromLong(beginCycle));
}

private long getBeginCycle(byte[] address) {
byte[] value = this.delegationStore.get(address);
return value == null ? 0 : ByteArray.toLong(value);
}

private long getEndCycle(byte[] address) {
byte[] value = this.delegationStore.get(generateKey("end", address, null));
return value == null ? REMARK : ByteArray.toLong(value);
}

private long getReward(long cycle, byte[] address) {
byte[] value = this.delegationStore.get(generateKey(cycle, address, "reward"));
return value == null ? 0 : ByteArray.toLong(value);
}

private long getWitnessVote(long cycle, byte[] address) {
byte[] value = this.delegationStore.get(generateKey(cycle, address, "vote"));
return value == null ? REMARK : ByteArray.toLong(value);
}

private byte[] generateKey(long cycle, byte[] address, String suffix) {
return generateKey(cycle + "", address, suffix);
}

private byte[] generateKey(String prefix, byte[] address, String suffix) {
StringBuilder sb = new StringBuilder();
if (prefix != null) {
sb.append(prefix).append("-");
}
sb.append(Hex.toHexString(address));
if (suffix != null) {
sb.append("-").append(suffix);
}
return sb.toString().getBytes();
}

private long getNewRewardAlgorithmEffectiveCycle() {
byte[] value = this.propertiesStore.get("NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE".getBytes());
return value == null ? Long.MAX_VALUE : ByteArray.toLong(value);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ private static void setUp() {
@Test
public void query() throws IOException {
rewardCalService.calRewardForTest();
Assert.assertEquals(3189, rewardCalService.getReward(OWNER_ADDRESS, 3));
Assert.assertEquals(3189, rewardCalService.getRewardCache(OWNER_ADDRESS, 3));
rewardCalService.calRewardForTest();
}

Expand Down

0 comments on commit 19952bf

Please sign in to comment.