Skip to content

Commit df53cd9

Browse files
committed
feat(vm,consensus): harden resource calculations(TIP-833)
1 parent 614c989 commit df53cd9

9 files changed

Lines changed: 1077 additions & 31 deletions

File tree

actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public static void load(StoreFactory storeFactory) {
4646
VMConfig.initAllowTvmBlob(ds.getAllowTvmBlob());
4747
VMConfig.initAllowTvmSelfdestructRestriction(ds.getAllowTvmSelfdestructRestriction());
4848
VMConfig.initAllowTvmOsaka(ds.getAllowTvmOsaka());
49+
VMConfig.initAllowHardenResourceCalculation(ds.getAllowHardenResourceCalculation());
4950
}
5051
}
5152
}

actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import com.google.common.collect.HashBasedTable;
1010
import com.google.protobuf.ByteString;
11+
import java.math.BigInteger;
1112
import java.util.HashMap;
1213
import java.util.HashSet;
1314
import java.util.Optional;
@@ -17,6 +18,7 @@
1718
import org.bouncycastle.util.Strings;
1819
import org.bouncycastle.util.encoders.Hex;
1920
import org.tron.common.crypto.Hash;
21+
import org.tron.common.math.StrictMathWrapper;
2022
import org.tron.common.parameter.CommonParameter;
2123
import org.tron.common.runtime.vm.DataWord;
2224
import org.tron.common.utils.ByteArray;
@@ -223,7 +225,7 @@ public Pair<Long, Long> getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCap
223225
long totalEnergyLimit = getDynamicPropertiesStore().getTotalEnergyCurrentLimit();
224226
long totalEnergyWeight = getTotalEnergyWeight();
225227

226-
long balance = (long) ((double) newEnergyUsage * totalEnergyWeight / totalEnergyLimit * TRX_PRECISION);
228+
long balance = usageToBalance(newEnergyUsage, totalEnergyWeight, totalEnergyLimit);
227229

228230
return Pair.of(balance, restoreSlots * BLOCK_PRODUCED_INTERVAL / 1_000);
229231
}
@@ -246,11 +248,22 @@ public Pair<Long, Long> getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsul
246248
long totalNetLimit = getDynamicPropertiesStore().getTotalNetLimit();
247249
long totalNetWeight = getTotalNetWeight();
248250

249-
long balance = (long) ((double) newNetUsage * totalNetWeight / totalNetLimit * TRX_PRECISION);
251+
long balance = usageToBalance(newNetUsage, totalNetWeight, totalNetLimit);
250252

251253
return Pair.of(balance, restoreSlots * BLOCK_PRODUCED_INTERVAL / 1_000);
252254
}
253255

256+
private long usageToBalance(long usage, long totalWeight, long totalLimit) {
257+
if (hardenResourceCalculation()) {
258+
return BigInteger.valueOf(usage)
259+
.multiply(BigInteger.valueOf(totalWeight))
260+
.multiply(BigInteger.valueOf(TRX_PRECISION))
261+
.divide(BigInteger.valueOf(totalLimit))
262+
.longValueExact();
263+
}
264+
return (long) ((double) usage * totalWeight / totalLimit * TRX_PRECISION);
265+
}
266+
254267
@Override
255268
public AssetIssueCapsule getAssetIssue(byte[] tokenId) {
256269
byte[] tokenIdWithoutLeadingZero = ByteUtil.stripLeadingZeroes(tokenId);
@@ -896,8 +909,19 @@ private long recover(long lastUsage, long lastTime, long now, long personalWindo
896909
}
897910

898911
private long increase(long lastUsage, long usage, long lastTime, long now, long windowSize) {
899-
long averageLastUsage = divideCeil(lastUsage * precision, windowSize);
900-
long averageUsage = divideCeil(usage * precision, windowSize);
912+
long averageLastUsage;
913+
long averageUsage;
914+
if (hardenResourceCalculation()) {
915+
BigInteger biPrecision = BigInteger.valueOf(precision);
916+
BigInteger biWindowSize = BigInteger.valueOf(windowSize);
917+
averageLastUsage = divideCeilExact(
918+
BigInteger.valueOf(lastUsage).multiply(biPrecision), biWindowSize);
919+
averageUsage = divideCeilExact(
920+
BigInteger.valueOf(usage).multiply(biPrecision), biWindowSize);
921+
} else {
922+
averageLastUsage = divideCeil(lastUsage * precision, windowSize);
923+
averageUsage = divideCeil(usage * precision, windowSize);
924+
}
901925

902926
if (lastTime != now) {
903927
assert now > lastTime;
@@ -917,21 +941,46 @@ private long divideCeil(long numerator, long denominator) {
917941
return (numerator / denominator) + ((numerator % denominator) > 0 ? 1 : 0);
918942
}
919943

944+
private long divideCeilExact(BigInteger numerator, BigInteger denominator) {
945+
BigInteger[] divRem = numerator.divideAndRemainder(denominator);
946+
long result = divRem[0].longValueExact();
947+
if (divRem[1].signum() > 0) {
948+
result = StrictMathWrapper.addExact(result, 1);
949+
}
950+
return result;
951+
}
952+
920953
private long getUsage(long usage, long windowSize) {
954+
if (hardenResourceCalculation()) {
955+
return BigInteger.valueOf(usage)
956+
.multiply(BigInteger.valueOf(windowSize))
957+
.divide(BigInteger.valueOf(precision))
958+
.longValueExact();
959+
}
921960
return usage * windowSize / precision;
922961
}
923962

963+
private boolean hardenResourceCalculation() {
964+
return VMConfig.allowHardenResourceCalculation();
965+
}
966+
924967
public long calculateGlobalEnergyLimit(AccountCapsule accountCapsule) {
925968
long frozeBalance = accountCapsule.getAllFrozenBalanceForEnergy();
926-
if (frozeBalance < 1_000_000L) {
969+
if (frozeBalance < precision) {
927970
return 0;
928971
}
929-
long energyWeight = frozeBalance / 1_000_000L;
972+
long energyWeight = frozeBalance / precision;
930973
long totalEnergyLimit = getDynamicPropertiesStore().getTotalEnergyCurrentLimit();
931974
long totalEnergyWeight = getDynamicPropertiesStore().getTotalEnergyWeight();
932975

933976
assert totalEnergyWeight > 0;
934977

978+
if (hardenResourceCalculation()) {
979+
return BigInteger.valueOf(energyWeight)
980+
.multiply(BigInteger.valueOf(totalEnergyLimit)
981+
.divide(BigInteger.valueOf(totalEnergyWeight)))
982+
.longValueExact();
983+
}
935984
return (long) (energyWeight * ((double) totalEnergyLimit / totalEnergyWeight));
936985
}
937986

chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,6 @@ public long calculateGlobalNetLimit(AccountCapsule accountCapsule) {
437437
if (frozeBalance < TRX_PRECISION) {
438438
return 0;
439439
}
440-
long netWeight = frozeBalance / TRX_PRECISION;
441440
long totalNetLimit = chainBaseManager.getDynamicPropertiesStore().getTotalNetLimit();
442441
long totalNetWeight = chainBaseManager.getDynamicPropertiesStore().getTotalNetWeight();
443442
if (dynamicPropertiesStore.allowNewReward() && totalNetWeight <= 0) {
@@ -446,16 +445,23 @@ public long calculateGlobalNetLimit(AccountCapsule accountCapsule) {
446445
if (totalNetWeight == 0) {
447446
return 0;
448447
}
448+
if (hardenCalculation()) {
449+
return calculateGlobalLimitV1(frozeBalance, totalNetLimit, totalNetWeight);
450+
}
451+
long netWeight = frozeBalance / TRX_PRECISION;
449452
return (long) (netWeight * ((double) totalNetLimit / totalNetWeight));
450453
}
451454

452455
public long calculateGlobalNetLimitV2(long frozeBalance) {
453-
double netWeight = (double) frozeBalance / TRX_PRECISION;
454456
long totalNetLimit = dynamicPropertiesStore.getTotalNetLimit();
455457
long totalNetWeight = dynamicPropertiesStore.getTotalNetWeight();
456458
if (totalNetWeight == 0) {
457459
return 0;
458460
}
461+
if (hardenCalculation()) {
462+
return calculateGlobalLimitV2(frozeBalance, totalNetLimit, totalNetWeight);
463+
}
464+
double netWeight = (double) frozeBalance / TRX_PRECISION;
459465
return (long) (netWeight * ((double) totalNetLimit / totalNetWeight));
460466
}
461467

chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL;
66
import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION;
77

8+
import java.math.BigInteger;
89
import lombok.extern.slf4j.Slf4j;
910
import org.tron.common.parameter.CommonParameter;
1011
import org.tron.core.capsule.AccountCapsule;
@@ -71,17 +72,20 @@ public void updateAdaptiveTotalEnergyLimit() {
7172

7273
long result;
7374
if (totalEnergyAverageUsage > targetTotalEnergyLimit) {
74-
result = totalEnergyCurrentLimit * AdaptiveResourceLimitConstants.CONTRACT_RATE_NUMERATOR
75-
/ AdaptiveResourceLimitConstants.CONTRACT_RATE_DENOMINATOR;
76-
// logger.info(totalEnergyAverageUsage + ">" + targetTotalEnergyLimit + "\n" + result);
75+
result = scaleByRate(totalEnergyCurrentLimit,
76+
AdaptiveResourceLimitConstants.CONTRACT_RATE_NUMERATOR,
77+
AdaptiveResourceLimitConstants.CONTRACT_RATE_DENOMINATOR);
7778
} else {
78-
result = totalEnergyCurrentLimit * AdaptiveResourceLimitConstants.EXPAND_RATE_NUMERATOR
79-
/ AdaptiveResourceLimitConstants.EXPAND_RATE_DENOMINATOR;
80-
// logger.info(totalEnergyAverageUsage + "<" + targetTotalEnergyLimit + "\n" + result);
79+
result = scaleByRate(totalEnergyCurrentLimit,
80+
AdaptiveResourceLimitConstants.EXPAND_RATE_NUMERATOR,
81+
AdaptiveResourceLimitConstants.EXPAND_RATE_DENOMINATOR);
8182
}
83+
long upperBound = hardenCalculation()
84+
? BigInteger.valueOf(totalEnergyLimit).multiply(BigInteger.valueOf(
85+
dynamicPropertiesStore.getAdaptiveResourceLimitMultiplier())).longValueExact()
86+
: totalEnergyLimit * dynamicPropertiesStore.getAdaptiveResourceLimitMultiplier();
8287
result = min(max(result, totalEnergyLimit, this.disableJavaLangMath()),
83-
totalEnergyLimit * dynamicPropertiesStore.getAdaptiveResourceLimitMultiplier(),
84-
this.disableJavaLangMath());
88+
upperBound, this.disableJavaLangMath());
8589

8690
dynamicPropertiesStore.saveTotalEnergyCurrentLimit(result);
8791
logger.debug("Adjust totalEnergyCurrentLimit, old: {}, new: {}.",
@@ -147,24 +151,30 @@ public long calculateGlobalEnergyLimit(AccountCapsule accountCapsule) {
147151
return 0;
148152
}
149153

150-
long energyWeight = frozeBalance / TRX_PRECISION;
151154
long totalEnergyLimit = dynamicPropertiesStore.getTotalEnergyCurrentLimit();
152155
long totalEnergyWeight = dynamicPropertiesStore.getTotalEnergyWeight();
153156
if (dynamicPropertiesStore.allowNewReward() && totalEnergyWeight <= 0) {
154157
return 0;
155158
} else {
156159
assert totalEnergyWeight > 0;
157160
}
161+
if (hardenCalculation()) {
162+
return calculateGlobalLimitV1(frozeBalance, totalEnergyLimit, totalEnergyWeight);
163+
}
164+
long energyWeight = frozeBalance / TRX_PRECISION;
158165
return (long) (energyWeight * ((double) totalEnergyLimit / totalEnergyWeight));
159166
}
160167

161168
public long calculateGlobalEnergyLimitV2(long frozeBalance) {
162-
double energyWeight = (double) frozeBalance / TRX_PRECISION;
163169
long totalEnergyLimit = dynamicPropertiesStore.getTotalEnergyCurrentLimit();
164170
long totalEnergyWeight = dynamicPropertiesStore.getTotalEnergyWeight();
165171
if (totalEnergyWeight == 0) {
166172
return 0;
167173
}
174+
if (hardenCalculation()) {
175+
return calculateGlobalLimitV2(frozeBalance, totalEnergyLimit, totalEnergyWeight);
176+
}
177+
double energyWeight = (double) frozeBalance / TRX_PRECISION;
168178
return (long) (energyWeight * ((double) totalEnergyLimit / totalEnergyWeight));
169179
}
170180

@@ -184,7 +194,15 @@ private long getHeadSlot() {
184194
return getHeadSlot(dynamicPropertiesStore);
185195
}
186196

187-
197+
private long scaleByRate(long value, long numerator, long denominator) {
198+
if (hardenCalculation()) {
199+
return BigInteger.valueOf(value)
200+
.multiply(BigInteger.valueOf(numerator))
201+
.divide(BigInteger.valueOf(denominator))
202+
.longValueExact();
203+
}
204+
return value * numerator / denominator;
205+
}
188206
}
189207

190208

0 commit comments

Comments
 (0)