diff --git a/actuator/src/main/java/org/tron/core/actuator/ExchangeTransactionActuator.java b/actuator/src/main/java/org/tron/core/actuator/ExchangeTransactionActuator.java
index 612f673832e..6f50d61c235 100755
--- a/actuator/src/main/java/org/tron/core/actuator/ExchangeTransactionActuator.java
+++ b/actuator/src/main/java/org/tron/core/actuator/ExchangeTransactionActuator.java
@@ -66,7 +66,8 @@ public boolean execute(Object object) throws ContractExeException {
long tokenQuant = exchangeTransactionContract.getQuant();
byte[] anotherTokenID;
- long anotherTokenQuant = exchangeCapsule.transaction(tokenID, tokenQuant);
+ long anotherTokenQuant = exchangeCapsule.transaction(tokenID, tokenQuant,
+ dynamicStore.allowStrictMath());
if (Arrays.equals(tokenID, firstTokenID)) {
anotherTokenID = secondTokenID;
@@ -205,7 +206,8 @@ public boolean validate() throws ContractValidateException {
}
}
- long anotherTokenQuant = exchangeCapsule.transaction(tokenID, tokenQuant);
+ long anotherTokenQuant = exchangeCapsule.transaction(tokenID, tokenQuant,
+ dynamicStore.allowStrictMath());
if (anotherTokenQuant < tokenExpected) {
throw new ContractValidateException("token required must greater than expected");
}
diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java
index 8f3501442f0..fb4d6f76228 100644
--- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java
+++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java
@@ -779,6 +779,21 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore,
}
break;
}
+ case ALLOW_STRICT_MATH: {
+ if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7_7)) {
+ throw new ContractValidateException(
+ "Bad chain parameter id [ALLOW_STRICT_MATH]");
+ }
+ if (dynamicPropertiesStore.allowStrictMath()) {
+ throw new ContractValidateException(
+ "[ALLOW_STRICT_MATH] has been valid, no need to propose again");
+ }
+ if (value != 1) {
+ throw new ContractValidateException(
+ "This value[ALLOW_STRICT_MATH] is only allowed to be 1");
+ }
+ break;
+ }
default:
break;
}
@@ -857,7 +872,8 @@ public enum ProposalType { // current value, value range
MAX_DELEGATE_LOCK_PERIOD(78), // (86400, 10512000]
ALLOW_OLD_REWARD_OPT(79), // 0, 1
ALLOW_ENERGY_ADJUSTMENT(81), // 0, 1
- MAX_CREATE_ACCOUNT_TX_SIZE(82); // [500, 10000]
+ MAX_CREATE_ACCOUNT_TX_SIZE(82), // [500, 10000]
+ ALLOW_STRICT_MATH(87); // 0, 1
private long code;
diff --git a/actuator/src/main/java/org/tron/core/vm/OperationActions.java b/actuator/src/main/java/org/tron/core/vm/OperationActions.java
index 5ed6ead075f..e8e5eb86b98 100644
--- a/actuator/src/main/java/org/tron/core/vm/OperationActions.java
+++ b/actuator/src/main/java/org/tron/core/vm/OperationActions.java
@@ -989,6 +989,9 @@ public static void exeCall(Program program, DataWord adjustedCallEnergy,
PrecompiledContracts.PrecompiledContract contract =
PrecompiledContracts.getContractForAddress(codeAddress);
if (contract != null) {
+ if (program.isConstantCall()) {
+ contract = PrecompiledContracts.getOptimizedContractForConstant(contract);
+ }
program.callToPrecompiledAddress(msg, contract);
} else {
program.callToAddress(msg);
diff --git a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java
index be7b9423f5c..79d08af1aad 100644
--- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java
+++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java
@@ -16,6 +16,8 @@
import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION;
import com.google.protobuf.ByteString;
+
+import java.lang.reflect.Constructor;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.ArrayList;
@@ -194,6 +196,14 @@ public class PrecompiledContracts {
private static final DataWord blake2FAddr = new DataWord(
"0000000000000000000000000000000000000000000000000000000000020009");
+ public static PrecompiledContract getOptimizedContractForConstant(PrecompiledContract contract) {
+ try {
+ Constructor> constructor = contract.getClass().getDeclaredConstructor();
+ return (PrecompiledContracts.PrecompiledContract) constructor.newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
public static PrecompiledContract getContractForAddress(DataWord address) {
diff --git a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java
index 63c3ff791d6..79a536f4cbf 100644
--- a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java
+++ b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java
@@ -40,6 +40,7 @@ public static void load(StoreFactory storeFactory) {
VMConfig.initDynamicEnergyMaxFactor(ds.getDynamicEnergyMaxFactor());
VMConfig.initAllowTvmShangHai(ds.getAllowTvmShangHai());
VMConfig.initAllowEnergyAdjustment(ds.getAllowEnergyAdjustment());
+ VMConfig.initAllowStrictMath(ds.getAllowStrictMath());
}
}
}
diff --git a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java b/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java
index 3eb1f8fd4b8..90a2c6335f6 100644
--- a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java
+++ b/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java
@@ -51,6 +51,8 @@ public class VMConfig {
private static boolean ALLOW_ENERGY_ADJUSTMENT = false;
+ private static boolean ALLOW_STRICT_MATH = false;
+
private VMConfig() {
}
@@ -142,6 +144,10 @@ public static void initAllowEnergyAdjustment(long allow) {
ALLOW_ENERGY_ADJUSTMENT = allow == 1;
}
+ public static void initAllowStrictMath(long allow) {
+ ALLOW_STRICT_MATH = allow == 1;
+ }
+
public static boolean getEnergyLimitHardFork() {
return CommonParameter.ENERGY_LIMIT_HARD_FORK;
}
@@ -221,4 +227,8 @@ public static boolean allowTvmShanghai() {
public static boolean allowEnergyAdjustment() {
return ALLOW_ENERGY_ADJUSTMENT;
}
+
+ public static boolean allowStrictMath() {
+ return ALLOW_STRICT_MATH;
+ }
}
diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java
index 0b0ef5bc9ba..4273778a7d6 100644
--- a/actuator/src/main/java/org/tron/core/vm/program/Program.java
+++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java
@@ -2230,7 +2230,8 @@ public long updateContextContractFactor() {
contractState.getDynamicPropertiesStore().getCurrentCycleNumber(),
VMConfig.getDynamicEnergyThreshold(),
VMConfig.getDynamicEnergyIncreaseFactor(),
- VMConfig.getDynamicEnergyMaxFactor())) {
+ VMConfig.getDynamicEnergyMaxFactor(),
+ VMConfig.allowStrictMath())) {
contractState.updateContractState(getContextAddress(), contractStateCapsule
);
}
diff --git a/chainbase/src/main/java/org/tron/common/math/Maths.java b/chainbase/src/main/java/org/tron/common/math/Maths.java
new file mode 100644
index 00000000000..a1ff6ed89a1
--- /dev/null
+++ b/chainbase/src/main/java/org/tron/common/math/Maths.java
@@ -0,0 +1,20 @@
+package org.tron.common.math;
+
+/**
+ * This class is deprecated and should not be used in new code,
+ * for cross-platform consistency, please use {@link StrictMathWrapper} instead,
+ * especially for floating-point calculations.
+ */
+@Deprecated
+public class Maths {
+
+ /**
+ * Returns the value of the first argument raised to the power of the second argument.
+ * @param a the base.
+ * @param b the exponent.
+ * @return the value {@code a}{@code b}.
+ */
+ public static double pow(double a, double b, boolean useStrictMath) {
+ return useStrictMath ? StrictMathWrapper.pow(a, b) : MathWrapper.pow(a, b);
+ }
+}
diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java
index 8633534280b..8ebb86ea332 100644
--- a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java
+++ b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java
@@ -5,6 +5,7 @@
import com.google.protobuf.InvalidProtocolBufferException;
import lombok.extern.slf4j.Slf4j;
+import org.tron.common.math.Maths;
import org.tron.core.store.DynamicPropertiesStore;
import org.tron.protos.contract.SmartContractOuterClass;
import org.tron.protos.contract.SmartContractOuterClass.ContractState;
@@ -77,12 +78,13 @@ public boolean catchUpToCycle(DynamicPropertiesStore dps) {
dps.getCurrentCycleNumber(),
dps.getDynamicEnergyThreshold(),
dps.getDynamicEnergyIncreaseFactor(),
- dps.getDynamicEnergyMaxFactor()
+ dps.getDynamicEnergyMaxFactor(),
+ dps.allowStrictMath()
);
}
public boolean catchUpToCycle(
- long newCycle, long threshold, long increaseFactor, long maxFactor
+ long newCycle, long threshold, long increaseFactor, long maxFactor, boolean useStrictMath
) {
long lastCycle = getUpdateCycle();
@@ -119,9 +121,9 @@ public boolean catchUpToCycle(
}
// Calc the decrease percent (decrease factor [75% ~ 100%])
- double decreasePercent = Math.pow(
+ double decreasePercent = Maths.pow(
1 - (double) increaseFactor / DYNAMIC_ENERGY_DECREASE_DIVISION / precisionFactor,
- cycleCount
+ cycleCount, useStrictMath
);
// Decrease to this cycle
diff --git a/chainbase/src/main/java/org/tron/core/capsule/ExchangeCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ExchangeCapsule.java
index 1cf91301b43..0dec7d60820 100644
--- a/chainbase/src/main/java/org/tron/core/capsule/ExchangeCapsule.java
+++ b/chainbase/src/main/java/org/tron/core/capsule/ExchangeCapsule.java
@@ -112,9 +112,9 @@ public byte[] createDbKey() {
return calculateDbKey(getID());
}
- public long transaction(byte[] sellTokenID, long sellTokenQuant) {
+ public long transaction(byte[] sellTokenID, long sellTokenQuant, boolean useStrictMath) {
long supply = 1_000_000_000_000_000_000L;
- ExchangeProcessor processor = new ExchangeProcessor(supply);
+ ExchangeProcessor processor = new ExchangeProcessor(supply, useStrictMath);
long buyTokenQuant = 0;
long firstTokenBalance = this.exchange.getFirstTokenBalance();
diff --git a/chainbase/src/main/java/org/tron/core/capsule/ExchangeProcessor.java b/chainbase/src/main/java/org/tron/core/capsule/ExchangeProcessor.java
index e1b536b3e7a..91f5c101b58 100644
--- a/chainbase/src/main/java/org/tron/core/capsule/ExchangeProcessor.java
+++ b/chainbase/src/main/java/org/tron/core/capsule/ExchangeProcessor.java
@@ -1,14 +1,17 @@
package org.tron.core.capsule;
import lombok.extern.slf4j.Slf4j;
+import org.tron.common.math.Maths;
@Slf4j(topic = "capsule")
public class ExchangeProcessor {
private long supply;
+ private final boolean useStrictMath;
- public ExchangeProcessor(long supply) {
+ public ExchangeProcessor(long supply, boolean useStrictMath) {
this.supply = supply;
+ this.useStrictMath = useStrictMath;
}
private long exchangeToSupply(long balance, long quant) {
@@ -16,7 +19,8 @@ private long exchangeToSupply(long balance, long quant) {
long newBalance = balance + quant;
logger.debug("balance + quant: " + newBalance);
- double issuedSupply = -supply * (1.0 - Math.pow(1.0 + (double) quant / newBalance, 0.0005));
+ double issuedSupply = -supply * (1.0
+ - Maths.pow(1.0 + (double) quant / newBalance, 0.0005, this.useStrictMath));
logger.debug("issuedSupply: " + issuedSupply);
long out = (long) issuedSupply;
supply += out;
@@ -27,8 +31,8 @@ private long exchangeToSupply(long balance, long quant) {
private long exchangeFromSupply(long balance, long supplyQuant) {
supply -= supplyQuant;
- double exchangeBalance =
- balance * (Math.pow(1.0 + (double) supplyQuant / supply, 2000.0) - 1.0);
+ double exchangeBalance = balance
+ * (Maths.pow(1.0 + (double) supplyQuant / supply, 2000.0, this.useStrictMath) - 1.0);
logger.debug("exchangeBalance: " + exchangeBalance);
return (long) exchangeBalance;
diff --git a/chainbase/src/main/java/org/tron/core/db/StorageMarket.java b/chainbase/src/main/java/org/tron/core/db/StorageMarket.java
deleted file mode 100644
index 10a3b656565..00000000000
--- a/chainbase/src/main/java/org/tron/core/db/StorageMarket.java
+++ /dev/null
@@ -1,234 +0,0 @@
-package org.tron.core.db;
-
-import lombok.extern.slf4j.Slf4j;
-import org.tron.core.capsule.AccountCapsule;
-import org.tron.core.store.AccountStore;
-import org.tron.core.store.DynamicPropertiesStore;
-
-@Slf4j(topic = "DB")
-public class StorageMarket {
- private static final String LOG_MSG = "NewTotalPool: {}, newTotalReserved: {}.";
- private static final long MS_PER_YEAR = 365 * 24 * 3600 * 1000L;
- private AccountStore accountStore;
- private DynamicPropertiesStore dynamicPropertiesStore;
- private long supply = 1_000_000_000_000_000L;
-
-
- public StorageMarket(AccountStore accountStore, DynamicPropertiesStore dynamicPropertiesStore) {
- this.accountStore = accountStore;
- this.dynamicPropertiesStore = dynamicPropertiesStore;
- }
-
- private long exchangeToSupply(boolean isTRX, long quant) {
- logger.info("IsTRX: {}.", isTRX);
- long balance = isTRX ? dynamicPropertiesStore.getTotalStoragePool() :
- dynamicPropertiesStore.getTotalStorageReserved();
- logger.info("Balance: {}.", balance);
- long newBalance = balance + quant;
- logger.info("Balance + quant: {}.", balance + quant);
-
-// if (isTRX) {
-// dbManager.getDynamicPropertiesStore().saveTotalStoragePool(newBalance);
-// } else {
-// dbManager.getDynamicPropertiesStore().saveTotalStorageReserved(newBalance);
-// }
-
- double issuedSupply = -supply * (1.0 - Math.pow(1.0 + (double) quant / newBalance, 0.0005));
- logger.info("IssuedSupply: {}.", issuedSupply);
- long out = (long) issuedSupply;
- supply += out;
-
- return out;
- }
-
- private long exchangeToSupply2(boolean isTRX, long quant) {
- logger.info("IsTRX: {}.", isTRX);
- long balance = isTRX ? dynamicPropertiesStore.getTotalStoragePool() :
- dynamicPropertiesStore.getTotalStorageReserved();
- logger.info("Balance: {}.", balance);
- long newBalance = balance - quant;
- logger.info("Balance - quant: {}.", balance - quant);
-
-// if (isTRX) {
-// dbManager.getDynamicPropertiesStore().saveTotalStoragePool(newBalance);
-// } else {
-// dbManager.getDynamicPropertiesStore().saveTotalStorageReserved(newBalance);
-// }
-
- double issuedSupply = -supply * (1.0 - Math.pow(1.0 + (double) quant / newBalance, 0.0005));
- logger.info("IssuedSupply: {}.", issuedSupply);
- long out = (long) issuedSupply;
- supply += out;
-
- return out;
- }
-
- private long exchange_from_supply(boolean isTRX, long supplyQuant) {
- long balance = isTRX ? dynamicPropertiesStore.getTotalStoragePool() :
- dynamicPropertiesStore.getTotalStorageReserved();
- supply -= supplyQuant;
-
- double exchangeBalance =
- balance * (Math.pow(1.0 + (double) supplyQuant / supply, 2000.0) - 1.0);
- logger.info("ExchangeBalance: {}.", exchangeBalance);
- long out = (long) exchangeBalance;
-
- if (isTRX) {
- out = Math.round(exchangeBalance / 100000) * 100000;
- logger.info("Out: {}.", out);
- }
-
- return out;
- }
-
- public long exchange(long from, boolean isTRX) {
- long relay = exchangeToSupply(isTRX, from);
- return exchange_from_supply(!isTRX, relay);
- }
-
- public long calculateTax(long duration, long limit) {
- // todo: Support for change by the committee
- double ratePerYear = dynamicPropertiesStore.getStorageExchangeTaxRate() / 100.0;
- double millisecondPerYear = MS_PER_YEAR;
- double feeRate = duration / millisecondPerYear * ratePerYear;
- long storageTax = (long) (limit * feeRate);
- logger.info("StorageTax: {}.", storageTax);
- return storageTax;
- }
-
-
- public long tryPayTax(long duration, long limit) {
- long storageTax = calculateTax(duration, limit);
- long tax = exchange(storageTax, false);
- logger.info("Tax: {}.", tax);
-
- long newTotalTax = dynamicPropertiesStore.getTotalStorageTax() + tax;
- long newTotalPool = dynamicPropertiesStore.getTotalStoragePool() - tax;
- long newTotalReserved = dynamicPropertiesStore.getTotalStorageReserved()
- + storageTax;
- logger.info("Reserved: {}.", dynamicPropertiesStore.getTotalStorageReserved());
- boolean eq = dynamicPropertiesStore.getTotalStorageReserved()
- == 128L * 1024 * 1024 * 1024;
- logger.info("Reserved == 128GB: {}.", eq);
- logger.info("NewTotalTax: {}, newTotalPool: {}, newTotalReserved: {}.",
- newTotalTax, newTotalPool, newTotalReserved);
-
- return storageTax;
- }
-
- public long payTax(long duration, long limit) {
- long storageTax = calculateTax(duration, limit);
- long tax = exchange(storageTax, false);
- logger.info("Tax: {}.", tax);
-
- long newTotalTax = dynamicPropertiesStore.getTotalStorageTax() + tax;
- long newTotalPool = dynamicPropertiesStore.getTotalStoragePool() - tax;
- long newTotalReserved = dynamicPropertiesStore.getTotalStorageReserved()
- + storageTax;
- logger.info("Reserved: {}.", dynamicPropertiesStore.getTotalStorageReserved());
- boolean eq = dynamicPropertiesStore.getTotalStorageReserved()
- == 128L * 1024 * 1024 * 1024;
- logger.info("Reserved == 128GB: {}.", eq);
- logger.info("NewTotalTax: {}, newTotalPool: {}, newTotalReserved: {}.",
- newTotalTax, newTotalPool, newTotalReserved);
- dynamicPropertiesStore.saveTotalStorageTax(newTotalTax);
- dynamicPropertiesStore.saveTotalStoragePool(newTotalPool);
- dynamicPropertiesStore.saveTotalStorageReserved(newTotalReserved);
-
- return storageTax;
- }
-
- public long tryBuyStorageBytes(long storageBought) {
- long relay = exchangeToSupply2(false, storageBought);
- return exchange_from_supply(true, relay);
- }
-
- public long tryBuyStorage(long quant) {
- return exchange(quant, true);
- }
-
- public long trySellStorage(long bytes) {
- return exchange(bytes, false);
- }
-
- public AccountCapsule buyStorageBytes(AccountCapsule accountCapsule, long storageBought) {
- long now = dynamicPropertiesStore.getLatestBlockHeaderTimestamp();
- long currentStorageLimit = accountCapsule.getStorageLimit();
-
- long relay = exchangeToSupply2(false, storageBought);
- long quant = exchange_from_supply(true, relay);
-
- long newBalance = accountCapsule.getBalance() - quant;
- logger.info("New balance: {}.", newBalance);
-
- long newStorageLimit = currentStorageLimit + storageBought;
- logger.info("StorageBought: {}, newStorageLimit: {}.", storageBought, newStorageLimit);
-
- accountCapsule.setLatestExchangeStorageTime(now);
- accountCapsule.setStorageLimit(newStorageLimit);
- accountCapsule.setBalance(newBalance);
- accountStore.put(accountCapsule.createDbKey(), accountCapsule);
-
- long newTotalPool = dynamicPropertiesStore.getTotalStoragePool() + quant;
- long newTotalReserved = dynamicPropertiesStore.getTotalStorageReserved()
- - storageBought;
- logger.info(LOG_MSG, newTotalPool, newTotalReserved);
- dynamicPropertiesStore.saveTotalStoragePool(newTotalPool);
- dynamicPropertiesStore.saveTotalStorageReserved(newTotalReserved);
- return accountCapsule;
- }
-
-
- public void buyStorage(AccountCapsule accountCapsule, long quant) {
- long now = dynamicPropertiesStore.getLatestBlockHeaderTimestamp();
- long currentStorageLimit = accountCapsule.getStorageLimit();
-
- long newBalance = accountCapsule.getBalance() - quant;
- logger.info("New balance: {}.", newBalance);
-
- long storageBought = exchange(quant, true);
- long newStorageLimit = currentStorageLimit + storageBought;
- logger.info("StorageBought: {}, newStorageLimit: {}.", storageBought, newStorageLimit);
-
- accountCapsule.setLatestExchangeStorageTime(now);
- accountCapsule.setStorageLimit(newStorageLimit);
- accountCapsule.setBalance(newBalance);
- accountStore.put(accountCapsule.createDbKey(), accountCapsule);
-
- long newTotalPool = dynamicPropertiesStore.getTotalStoragePool() + quant;
- long newTotalReserved = dynamicPropertiesStore.getTotalStorageReserved()
- - storageBought;
- logger.info(LOG_MSG, newTotalPool, newTotalReserved);
- dynamicPropertiesStore.saveTotalStoragePool(newTotalPool);
- dynamicPropertiesStore.saveTotalStorageReserved(newTotalReserved);
-
- }
-
- public void sellStorage(AccountCapsule accountCapsule, long bytes) {
- long now = dynamicPropertiesStore.getLatestBlockHeaderTimestamp();
- long currentStorageLimit = accountCapsule.getStorageLimit();
-
- long quant = exchange(bytes, false);
- long newBalance = accountCapsule.getBalance() + quant;
-
- long newStorageLimit = currentStorageLimit - bytes;
- logger.info("Quant: {}, newStorageLimit: {}.", quant, newStorageLimit);
-
- accountCapsule.setLatestExchangeStorageTime(now);
- accountCapsule.setStorageLimit(newStorageLimit);
- accountCapsule.setBalance(newBalance);
- accountStore.put(accountCapsule.createDbKey(), accountCapsule);
-
- long newTotalPool = dynamicPropertiesStore.getTotalStoragePool() - quant;
- long newTotalReserved = dynamicPropertiesStore.getTotalStorageReserved()
- + bytes;
- logger.info(LOG_MSG, newTotalPool, newTotalReserved);
- dynamicPropertiesStore.saveTotalStoragePool(newTotalPool);
- dynamicPropertiesStore.saveTotalStorageReserved(newTotalReserved);
-
- }
-
- public long getAccountLeftStorageInByteFromBought(AccountCapsule accountCapsule) {
- return accountCapsule.getStorageLimit() - accountCapsule.getStorageUsage();
- }
-}
diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java
index 2b50ec76af2..4af338f09bb 100644
--- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java
+++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java
@@ -222,6 +222,7 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking
private static final byte[] ALLOW_ENERGY_ADJUSTMENT = "ALLOW_ENERGY_ADJUSTMENT".getBytes();
private static final byte[] MAX_CREATE_ACCOUNT_TX_SIZE = "MAX_CREATE_ACCOUNT_TX_SIZE".getBytes();
+ private static final byte[] ALLOW_STRICT_MATH = "ALLOW_STRICT_MATH".getBytes();
@Autowired
private DynamicPropertiesStore(@Value("properties") String dbName) {
@@ -2876,6 +2877,19 @@ public long getMaxCreateAccountTxSize() {
.map(ByteArray::toLong)
.orElse(CommonParameter.getInstance().getMaxCreateAccountTxSize());
}
+ public long getAllowStrictMath() {
+ return Optional.ofNullable(getUnchecked(ALLOW_STRICT_MATH))
+ .map(BytesCapsule::getData)
+ .map(ByteArray::toLong)
+ .orElse(CommonParameter.getInstance().getAllowStrictMath());
+ }
+ public void saveAllowStrictMath(long allowStrictMath) {
+ this.put(ALLOW_STRICT_MATH, new BytesCapsule(ByteArray.fromLong(allowStrictMath)));
+ }
+
+ public boolean allowStrictMath() {
+ return getAllowStrictMath() == 1L;
+ }
private static class DynamicResourceProperties {
diff --git a/common/src/main/java/org/tron/common/math/MathWrapper.java b/common/src/main/java/org/tron/common/math/MathWrapper.java
new file mode 100644
index 00000000000..519dafb9d42
--- /dev/null
+++ b/common/src/main/java/org/tron/common/math/MathWrapper.java
@@ -0,0 +1,14 @@
+package org.tron.common.math;
+
+/**
+ * This class is deprecated and should not be used in new code,
+ * for cross-platform consistency, please use {@link StrictMathWrapper} instead,
+ * especially for floating-point calculations.
+ */
+@Deprecated
+public class MathWrapper {
+
+ public static double pow(double a, double b) {
+ return Math.pow(a, b);
+ }
+}
diff --git a/common/src/main/java/org/tron/common/math/StrictMathWrapper.java b/common/src/main/java/org/tron/common/math/StrictMathWrapper.java
new file mode 100644
index 00000000000..6285f6567c0
--- /dev/null
+++ b/common/src/main/java/org/tron/common/math/StrictMathWrapper.java
@@ -0,0 +1,8 @@
+package org.tron.common.math;
+
+public class StrictMathWrapper {
+
+ public static double pow(double a, double b) {
+ return StrictMath.pow(a, b);
+ }
+}
diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java
index 62ed12d856c..1aa3befe8aa 100644
--- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java
+++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java
@@ -677,6 +677,10 @@ public class CommonParameter {
@Setter
public long maxCreateAccountTxSize = 1000L;
+ @Getter
+ @Setter
+ public long allowStrictMath;
+
private static double calcMaxTimeRatio() {
//return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1)));
return 5.0;
diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java
index da3b2b1becc..96ff41b91da 100644
--- a/common/src/main/java/org/tron/core/Constant.java
+++ b/common/src/main/java/org/tron/core/Constant.java
@@ -386,4 +386,5 @@ public class Constant {
public static final String COMMITTEE_ALLOW_OLD_REWARD_OPT = "committee.allowOldRewardOpt";
public static final String COMMITTEE_ALLOW_ENERGY_ADJUSTMENT = "committee.allowEnergyAdjustment";
+ public static final String COMMITTEE_ALLOW_STRICT_MATH = "committee.allowStrictMath";
}
diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java
index 027c225eb5d..247c5dd4fe2 100644
--- a/common/src/main/java/org/tron/core/config/Parameter.java
+++ b/common/src/main/java/org/tron/core/config/Parameter.java
@@ -24,7 +24,8 @@ public enum ForkBlockVersionEnum {
VERSION_4_7_1(27, 1596780000000L, 80),
VERSION_4_7_2(28, 1596780000000L, 80),
VERSION_4_7_4(29, 1596780000000L, 80),
- VERSION_4_7_5(30, 1596780000000L, 80);
+ VERSION_4_7_5(30, 1596780000000L, 80),
+ VERSION_4_7_7(31, 1596780000000L, 80);
// if add a version, modify BLOCK_VERSION simultaneously
@Getter
@@ -73,7 +74,7 @@ public class ChainConstant {
public static final int SINGLE_REPEAT = 1;
public static final int BLOCK_FILLED_SLOTS_NUMBER = 128;
public static final int MAX_FROZEN_NUMBER = 1;
- public static final int BLOCK_VERSION = 30;
+ public static final int BLOCK_VERSION = 31;
public static final long FROZEN_PERIOD = 86_400_000L;
public static final long DELEGATE_PERIOD = 3 * 86_400_000L;
public static final long TRX_PRECISION = 1000_000L;
diff --git a/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java b/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java
index 2acf1e12633..67739ac50d2 100644
--- a/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java
+++ b/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java
@@ -95,7 +95,6 @@ public void initChannel(NioDatagramChannel ch)
public void close() {
logger.info("Closing backup server...");
shutdown = true;
- ExecutorServiceManager.shutdownAndAwaitTermination(executor, name);
backupManager.stop();
if (channel != null) {
try {
@@ -104,6 +103,7 @@ public void close() {
logger.warn("Closing backup server failed.", e);
}
}
+ ExecutorServiceManager.shutdownAndAwaitTermination(executor, name);
logger.info("Backup server closed.");
}
}
diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java
index 769274e8f2a..0943723f2f4 100755
--- a/framework/src/main/java/org/tron/core/Wallet.java
+++ b/framework/src/main/java/org/tron/core/Wallet.java
@@ -1343,6 +1343,11 @@ public Protocol.ChainParameters getChainParameters() {
.setValue(dbManager.getDynamicPropertiesStore().getMaxCreateAccountTxSize())
.build());
+ builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder()
+ .setKey("getAllowStrictMath")
+ .setValue(dbManager.getDynamicPropertiesStore().getAllowStrictMath())
+ .build());
+
return builder.build();
}
diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java
index 00142733f74..8853971a5f8 100644
--- a/framework/src/main/java/org/tron/core/config/args/Args.java
+++ b/framework/src/main/java/org/tron/core/config/args/Args.java
@@ -234,6 +234,7 @@ public static void clearParam() {
PARAMETER.maxUnsolidifiedBlocks = 54;
PARAMETER.allowOldRewardOpt = 0;
PARAMETER.allowEnergyAdjustment = 0;
+ PARAMETER.allowStrictMath = 0;
}
/**
@@ -1217,6 +1218,10 @@ public static void setParam(final String[] args, final String confFileName) {
config.hasPath(Constant.COMMITTEE_ALLOW_ENERGY_ADJUSTMENT) ? config
.getInt(Constant.COMMITTEE_ALLOW_ENERGY_ADJUSTMENT) : 0;
+ PARAMETER.allowStrictMath =
+ config.hasPath(Constant.COMMITTEE_ALLOW_STRICT_MATH) ? config
+ .getInt(Constant.COMMITTEE_ALLOW_STRICT_MATH) : 0;
+
logConfig();
}
diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java
index d0c106a7e57..29eef1c3cb3 100644
--- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java
+++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java
@@ -367,6 +367,10 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule)
manager.getDynamicPropertiesStore().saveMaxCreateAccountTxSize(entry.getValue());
break;
}
+ case ALLOW_STRICT_MATH: {
+ manager.getDynamicPropertiesStore().saveAllowStrictMath(entry.getValue());
+ break;
+ }
default:
find = false;
break;
diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java
index 43e5838d1d5..908e248bdee 100644
--- a/framework/src/main/java/org/tron/core/db/Manager.java
+++ b/framework/src/main/java/org/tron/core/db/Manager.java
@@ -1321,23 +1321,17 @@ public void pushBlock(final BlockCapsule block)
return;
}
+ long oldSolidNum = getDynamicPropertiesStore().getLatestSolidifiedBlockNum();
try (ISession tmpSession = revokingStore.buildSession()) {
-
- long oldSolidNum =
- chainBaseManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum();
-
applyBlock(newBlock, txs);
tmpSession.commit();
- // if event subscribe is enabled, post block trigger to queue
- postBlockTrigger(newBlock);
- // if event subscribe is enabled, post solidity trigger to queue
- postSolidityTrigger(oldSolidNum,
- getDynamicPropertiesStore().getLatestSolidifiedBlockNum());
} catch (Throwable throwable) {
logger.error(throwable.getMessage(), throwable);
khaosDb.removeBlk(block.getBlockId());
throw throwable;
}
+ long newSolidNum = getDynamicPropertiesStore().getLatestSolidifiedBlockNum();
+ blockTrigger(newBlock, oldSolidNum, newSolidNum);
}
logger.info(SAVE_BLOCK, newBlock);
}
@@ -1367,6 +1361,19 @@ public void pushBlock(final BlockCapsule block)
}
}
+ void blockTrigger(final BlockCapsule block, long oldSolid, long newSolid) {
+ try {
+ // if event subscribe is enabled, post block trigger to queue
+ postBlockTrigger(block);
+ // if event subscribe is enabled, post solidity trigger to queue
+ postSolidityTrigger(oldSolid, newSolid);
+ } catch (Exception e) {
+ logger.error("Block trigger failed. head: {}, oldSolid: {}, newSolid: {}",
+ block.getNum(), oldSolid, newSolid, e);
+ System.exit(1);
+ }
+ }
+
public void updateDynamicProperties(BlockCapsule block) {
chainBaseManager.getDynamicPropertiesStore()
@@ -2216,7 +2223,7 @@ private void postLogsFilter(final BlockCapsule blockCapsule, boolean solidified,
}
}
- private void postBlockTrigger(final BlockCapsule blockCapsule) {
+ void postBlockTrigger(final BlockCapsule blockCapsule) {
// post block and logs for jsonrpc
if (CommonParameter.getInstance().isJsonRpcHttpFullNodeEnable()) {
postBlockFilter(blockCapsule, false);
diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java
index 85ad2dd18dd..3cc50c77890 100755
--- a/framework/src/main/java/org/tron/core/services/RpcApiService.java
+++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java
@@ -98,6 +98,7 @@
import org.tron.core.exception.ZksnarkException;
import org.tron.core.metrics.MetricsApiService;
import org.tron.core.services.filter.LiteFnQueryGrpcInterceptor;
+import org.tron.core.services.ratelimiter.PrometheusInterceptor;
import org.tron.core.services.ratelimiter.RateLimiterInterceptor;
import org.tron.core.services.ratelimiter.RpcApiAccessInterceptor;
import org.tron.core.utils.TransactionUtil;
@@ -189,6 +190,8 @@ public class RpcApiService extends RpcService {
private RpcApiAccessInterceptor apiAccessInterceptor;
@Autowired
private MetricsApiService metricsApiService;
+ @Autowired
+ private PrometheusInterceptor prometheusInterceptor;
@Getter
private DatabaseApi databaseApi = new DatabaseApi();
private WalletApi walletApi = new WalletApi();
@@ -252,6 +255,11 @@ public void start() {
// add lite fullnode query interceptor
serverBuilder.intercept(liteFnQueryGrpcInterceptor);
+ // add prometheus interceptor
+ if (parameter.isMetricsPrometheusEnable()) {
+ serverBuilder.intercept(prometheusInterceptor);
+ }
+
if (parameter.isRpcReflectionServiceEnable()) {
serverBuilder.addService(ProtoReflectionService.newInstance());
}
diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java
index 4d801f20e5c..cf945f664d1 100755
--- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java
+++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java
@@ -41,6 +41,7 @@
import org.tron.core.config.args.Args;
import org.tron.core.services.RpcApiService;
import org.tron.core.services.filter.LiteFnQueryGrpcInterceptor;
+import org.tron.core.services.ratelimiter.PrometheusInterceptor;
import org.tron.core.services.ratelimiter.RateLimiterInterceptor;
import org.tron.core.services.ratelimiter.RpcApiAccessInterceptor;
import org.tron.protos.Protocol.Account;
@@ -79,6 +80,9 @@ public class RpcApiServiceOnPBFT extends RpcService {
@Autowired
private RpcApiAccessInterceptor apiAccessInterceptor;
+ @Autowired
+ private PrometheusInterceptor prometheusInterceptor;
+
private final String executorName = "rpc-pbft-executor";
@Override
@@ -124,6 +128,11 @@ public void start() {
// add lite fullnode query interceptor
serverBuilder.intercept(liteFnQueryGrpcInterceptor);
+ // add prometheus interceptor
+ if (args.isMetricsPrometheusEnable()) {
+ serverBuilder.intercept(prometheusInterceptor);
+ }
+
if (args.isRpcReflectionServiceEnable()) {
serverBuilder.addService(ProtoReflectionService.newInstance());
}
diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java
index 6bdfc824163..4bd3fbe4fef 100755
--- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java
+++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java
@@ -42,6 +42,7 @@
import org.tron.core.config.args.Args;
import org.tron.core.services.RpcApiService;
import org.tron.core.services.filter.LiteFnQueryGrpcInterceptor;
+import org.tron.core.services.ratelimiter.PrometheusInterceptor;
import org.tron.core.services.ratelimiter.RateLimiterInterceptor;
import org.tron.core.services.ratelimiter.RpcApiAccessInterceptor;
import org.tron.protos.Protocol.Account;
@@ -81,6 +82,9 @@ public class RpcApiServiceOnSolidity extends RpcService {
@Autowired
private RpcApiAccessInterceptor apiAccessInterceptor;
+ @Autowired
+ private PrometheusInterceptor prometheusInterceptor;
+
private final String executorName = "rpc-solidity-executor";
@Override
@@ -125,6 +129,11 @@ public void start() {
// add lite fullnode query interceptor
serverBuilder.intercept(liteFnQueryGrpcInterceptor);
+ // add prometheus interceptor
+ if (parameter.isMetricsPrometheusEnable()) {
+ serverBuilder.intercept(prometheusInterceptor);
+ }
+
if (parameter.isRpcReflectionServiceEnable()) {
serverBuilder.addService(ProtoReflectionService.newInstance());
}
diff --git a/framework/src/main/java/org/tron/core/services/ratelimiter/PrometheusInterceptor.java b/framework/src/main/java/org/tron/core/services/ratelimiter/PrometheusInterceptor.java
new file mode 100644
index 00000000000..97458ffb1c4
--- /dev/null
+++ b/framework/src/main/java/org/tron/core/services/ratelimiter/PrometheusInterceptor.java
@@ -0,0 +1,46 @@
+
+package org.tron.core.services.ratelimiter;
+
+import io.grpc.ForwardingServerCall;
+import io.grpc.Metadata;
+import io.grpc.ServerCall;
+import io.grpc.ServerCallHandler;
+import io.grpc.ServerInterceptor;
+import io.grpc.Status;
+import io.prometheus.client.Histogram;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import org.tron.common.prometheus.MetricKeys;
+import org.tron.common.prometheus.Metrics;
+
+/**
+ * A {@link ServerInterceptor} which sends latency stats about incoming grpc calls to Prometheus.
+ */
+@Slf4j(topic = "metrics")
+@Component
+public class PrometheusInterceptor implements ServerInterceptor {
+
+ @Override
+ public ServerCall.Listener interceptCall(
+ ServerCall call, Metadata requestMetadata, ServerCallHandler next) {
+ return next.startCall(new MonitoringServerCall<>(call), requestMetadata);
+ }
+
+ static class MonitoringServerCall extends ForwardingServerCall
+ .SimpleForwardingServerCall {
+
+ private final Histogram.Timer requestTimer;
+
+ MonitoringServerCall(ServerCall delegate) {
+ super(delegate);
+ this.requestTimer = Metrics.histogramStartTimer(
+ MetricKeys.Histogram.GRPC_SERVICE_LATENCY, getMethodDescriptor().getFullMethodName());
+ }
+
+ @Override
+ public void close(Status status, Metadata responseHeaders) {
+ Metrics.histogramObserve(requestTimer);
+ super.close(status, responseHeaders);
+ }
+ }
+}
diff --git a/framework/src/main/java/org/tron/core/services/ratelimiter/RpcApiAccessInterceptor.java b/framework/src/main/java/org/tron/core/services/ratelimiter/RpcApiAccessInterceptor.java
index 8b5812129a2..c3471c2829c 100644
--- a/framework/src/main/java/org/tron/core/services/ratelimiter/RpcApiAccessInterceptor.java
+++ b/framework/src/main/java/org/tron/core/services/ratelimiter/RpcApiAccessInterceptor.java
@@ -6,13 +6,10 @@
import io.grpc.ServerCallHandler;
import io.grpc.ServerInterceptor;
import io.grpc.Status;
-import io.prometheus.client.Histogram;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.tron.common.parameter.CommonParameter;
-import org.tron.common.prometheus.MetricKeys;
-import org.tron.common.prometheus.Metrics;
@Slf4j
@Component
@@ -32,11 +29,7 @@ public Listener interceptCall(ServerCall call,
return new ServerCall.Listener() {};
} else {
- Histogram.Timer requestTimer = Metrics.histogramStartTimer(
- MetricKeys.Histogram.GRPC_SERVICE_LATENCY, endpoint);
- Listener res = next.startCall(call, headers);
- Metrics.histogramObserve(requestTimer);
- return res;
+ return next.startCall(call, headers);
}
} catch (Exception e) {
logger.error("check rpc api access Error: {}", e.getMessage());
diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java
index 250bc087be3..4790ee62bad 100644
--- a/framework/src/main/java/org/tron/program/Version.java
+++ b/framework/src/main/java/org/tron/program/Version.java
@@ -4,7 +4,7 @@ public class Version {
public static final String VERSION_NAME = "GreatVoyage-v4.7.5-64-g4103dfeb63";
public static final String VERSION_CODE = "18372";
- private static final String VERSION = "4.7.6";
+ private static final String VERSION = "4.7.7";
public static String getVersion() {
return VERSION;
diff --git a/framework/src/test/java/org/tron/common/backup/BackupServerTest.java b/framework/src/test/java/org/tron/common/backup/BackupServerTest.java
index 34b17ec186f..9bff6eed677 100644
--- a/framework/src/test/java/org/tron/common/backup/BackupServerTest.java
+++ b/framework/src/test/java/org/tron/common/backup/BackupServerTest.java
@@ -7,6 +7,7 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import org.junit.rules.Timeout;
import org.tron.common.backup.socket.BackupServer;
import org.tron.common.parameter.CommonParameter;
import org.tron.core.Constant;
@@ -17,6 +18,9 @@ public class BackupServerTest {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+ @Rule
+ public Timeout globalTimeout = Timeout.seconds(60);
private BackupServer backupServer;
@Before
@@ -40,5 +44,7 @@ public void tearDown() {
@Test
public void test() throws InterruptedException {
backupServer.initServer();
+ // wait for the server to start
+ Thread.sleep(1000);
}
}
diff --git a/framework/src/test/java/org/tron/core/StorageMarketTest.java b/framework/src/test/java/org/tron/core/StorageMarketTest.java
deleted file mode 100644
index 8b6e90e1c67..00000000000
--- a/framework/src/test/java/org/tron/core/StorageMarketTest.java
+++ /dev/null
@@ -1,256 +0,0 @@
-package org.tron.core;
-
-import static org.tron.core.config.Parameter.ChainConstant.TRANSFER_FEE;
-
-import com.google.protobuf.Any;
-import com.google.protobuf.ByteString;
-import lombok.extern.slf4j.Slf4j;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.tron.common.BaseTest;
-import org.tron.common.utils.ByteArray;
-import org.tron.core.capsule.AccountCapsule;
-import org.tron.core.config.args.Args;
-import org.tron.core.db.StorageMarket;
-import org.tron.protos.Protocol.AccountType;
-import org.tron.protos.contract.StorageContract.BuyStorageContract;
-
-@Slf4j
-public class StorageMarketTest extends BaseTest {
-
- private static final String OWNER_ADDRESS;
- private static final long initBalance = 10_000_000_000_000_000L;
- private static StorageMarket storageMarket;
-
- static {
- Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF);
- OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc";
- }
-
- /**
- * create temp Capsule test need.
- */
- @Before
- public void createAccountCapsule() {
- storageMarket = new StorageMarket(dbManager.getAccountStore(),
- dbManager.getDynamicPropertiesStore());
-
- AccountCapsule ownerCapsule =
- new AccountCapsule(
- ByteString.copyFromUtf8("owner"),
- ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)),
- AccountType.Normal,
- initBalance);
- dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule);
-
- dbManager.getDynamicPropertiesStore().saveTotalStorageReserved(
- 128L * 1024 * 1024 * 1024);
- dbManager.getDynamicPropertiesStore().saveTotalStoragePool(100_000_000_000000L);
- dbManager.getDynamicPropertiesStore().saveTotalStorageTax(0);
-
- dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(0);
- }
-
- private Any getContract(String ownerAddress, long quant) {
- return Any.pack(
- BuyStorageContract.newBuilder()
- .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(ownerAddress)))
- .setQuant(quant)
- .build());
- }
-
- @Test
- public void testBuyStorage() {
- long currentPool = dbManager.getDynamicPropertiesStore().getTotalStoragePool();
- long currentReserved = dbManager.getDynamicPropertiesStore().getTotalStorageReserved();
- Assert.assertEquals(currentPool, 100_000_000_000000L);
- Assert.assertEquals(currentReserved, 128L * 1024 * 1024 * 1024);
-
- AccountCapsule owner =
- dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS));
-
- long quant = 2_000_000_000_000L; // 2 million trx
- storageMarket.buyStorage(owner, quant);
-
- Assert.assertEquals(owner.getBalance(), initBalance - quant
- - TRANSFER_FEE);
- Assert.assertEquals(2694881440L, owner.getStorageLimit());
- Assert.assertEquals(currentReserved - 2694881440L,
- dbManager.getDynamicPropertiesStore().getTotalStorageReserved());
- Assert.assertEquals(currentPool + quant,
- dbManager.getDynamicPropertiesStore().getTotalStoragePool());
-
- }
-
- @Test
- public void testBuyStorage2() {
- long currentPool = dbManager.getDynamicPropertiesStore().getTotalStoragePool();
- long currentReserved = dbManager.getDynamicPropertiesStore().getTotalStorageReserved();
- Assert.assertEquals(currentPool, 100_000_000_000000L);
- Assert.assertEquals(currentReserved, 128L * 1024 * 1024 * 1024);
-
- AccountCapsule owner =
- dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS));
-
- long quant = 1_000_000_000_000L; // 1 million trx
-
- storageMarket.buyStorage(owner, quant);
-
- Assert.assertEquals(owner.getBalance(), initBalance - quant
- - TRANSFER_FEE);
- Assert.assertEquals(1360781717L, owner.getStorageLimit());
- Assert.assertEquals(currentReserved - 1360781717L,
- dbManager.getDynamicPropertiesStore().getTotalStorageReserved());
- Assert.assertEquals(currentPool + quant,
- dbManager.getDynamicPropertiesStore().getTotalStoragePool());
-
- storageMarket.buyStorage(owner, quant);
-
- Assert.assertEquals(owner.getBalance(), initBalance - 2 * quant
- - TRANSFER_FEE);
- Assert.assertEquals(2694881439L, owner.getStorageLimit());
- Assert.assertEquals(currentReserved - 2694881439L,
- dbManager.getDynamicPropertiesStore().getTotalStorageReserved());
- Assert.assertEquals(currentPool + 2 * quant,
- dbManager.getDynamicPropertiesStore().getTotalStoragePool());
-
- }
-
-
- @Test
- public void testBuyStorageBytes() {
- long currentPool = dbManager.getDynamicPropertiesStore().getTotalStoragePool();
- long currentReserved = dbManager.getDynamicPropertiesStore().getTotalStorageReserved();
- Assert.assertEquals(currentPool, 100_000_000_000000L);
- Assert.assertEquals(currentReserved, 128L * 1024 * 1024 * 1024);
-
- AccountCapsule owner =
- dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS));
-
- long bytes = 2694881440L; // 2 million trx
- storageMarket.buyStorageBytes(owner, bytes);
-
- Assert.assertEquals(owner.getBalance(), initBalance - 2_000_000_000_000L
- - TRANSFER_FEE);
- Assert.assertEquals(bytes, owner.getStorageLimit());
- Assert.assertEquals(currentReserved - bytes,
- dbManager.getDynamicPropertiesStore().getTotalStorageReserved());
- Assert.assertEquals(currentPool + 2_000_000_000_000L,
- dbManager.getDynamicPropertiesStore().getTotalStoragePool());
-
- }
-
- @Test
- public void testBuyStorageBytes2() {
- long currentPool = dbManager.getDynamicPropertiesStore().getTotalStoragePool();
- long currentReserved = dbManager.getDynamicPropertiesStore().getTotalStorageReserved();
- Assert.assertEquals(currentPool, 100_000_000_000000L);
- Assert.assertEquals(currentReserved, 128L * 1024 * 1024 * 1024);
-
- AccountCapsule owner =
- dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS));
-
- long bytes1 = 1360781717L;
-
- storageMarket.buyStorageBytes(owner, bytes1);
-
- Assert.assertEquals(owner.getBalance(), initBalance - 1_000_000_000_000L
- - TRANSFER_FEE);
- Assert.assertEquals(bytes1, owner.getStorageLimit());
- Assert.assertEquals(currentReserved - bytes1,
- dbManager.getDynamicPropertiesStore().getTotalStorageReserved());
- Assert.assertEquals(currentPool + 1_000_000_000_000L,
- dbManager.getDynamicPropertiesStore().getTotalStoragePool());
-
- long bytes2 = 1334099723L;
- storageMarket.buyStorageBytes(owner, bytes2);
- Assert.assertEquals(owner.getBalance(), initBalance - 2 * 1_000_000_000_000L
- - TRANSFER_FEE);
- Assert.assertEquals(bytes1 + bytes2, owner.getStorageLimit());
- Assert.assertEquals(currentReserved - (bytes1 + bytes2),
- dbManager.getDynamicPropertiesStore().getTotalStorageReserved());
- Assert.assertEquals(currentPool + 2 * 1_000_000_000_000L,
- dbManager.getDynamicPropertiesStore().getTotalStoragePool());
-
- }
-
- @Test
- public void testSellStorage() {
- long currentPool = dbManager.getDynamicPropertiesStore().getTotalStoragePool();
- long currentReserved = dbManager.getDynamicPropertiesStore().getTotalStorageReserved();
- Assert.assertEquals(currentPool, 100_000_000_000000L);
- Assert.assertEquals(currentReserved, 128L * 1024 * 1024 * 1024);
-
- AccountCapsule owner =
- dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS));
-
- long quant = 2_000_000_000_000L; // 2 million trx
- storageMarket.buyStorage(owner, quant);
-
- Assert.assertEquals(owner.getBalance(), initBalance - quant
- - TRANSFER_FEE);
- Assert.assertEquals(2694881440L, owner.getStorageLimit());
- Assert.assertEquals(currentReserved - 2694881440L,
- dbManager.getDynamicPropertiesStore().getTotalStorageReserved());
- Assert.assertEquals(currentPool + quant,
- dbManager.getDynamicPropertiesStore().getTotalStoragePool());
-
- long bytes = 2694881440L;
- storageMarket.sellStorage(owner, bytes);
-
- Assert.assertEquals(owner.getBalance(), initBalance);
- Assert.assertEquals(0, owner.getStorageLimit());
- Assert.assertEquals(currentReserved,
- dbManager.getDynamicPropertiesStore().getTotalStorageReserved());
- Assert.assertEquals(100_000_000_000_000L,
- dbManager.getDynamicPropertiesStore().getTotalStoragePool());
-
- }
-
- @Test
- public void testSellStorage2() {
- long currentPool = dbManager.getDynamicPropertiesStore().getTotalStoragePool();
- long currentReserved = dbManager.getDynamicPropertiesStore().getTotalStorageReserved();
- Assert.assertEquals(currentPool, 100_000_000_000000L);
- Assert.assertEquals(currentReserved, 128L * 1024 * 1024 * 1024);
-
- AccountCapsule owner =
- dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS));
-
- long quant = 2_000_000_000_000L; // 2 million trx
- storageMarket.buyStorage(owner, quant);
-
- Assert.assertEquals(owner.getBalance(), initBalance - quant
- - TRANSFER_FEE);
- Assert.assertEquals(2694881440L, owner.getStorageLimit());
- Assert.assertEquals(currentReserved - 2694881440L,
- dbManager.getDynamicPropertiesStore().getTotalStorageReserved());
- Assert.assertEquals(currentPool + quant,
- dbManager.getDynamicPropertiesStore().getTotalStoragePool());
-
- long bytes1 = 2694881440L - 1360781717L; // 1 million trx
- long bytes2 = 1360781717L; // 1 million trx
-
- storageMarket.sellStorage(owner, bytes1);
-
- Assert.assertEquals(owner.getBalance(), initBalance - 1_000_000_000_000L);
- Assert.assertEquals(1360781717L, owner.getStorageLimit());
- Assert.assertEquals(currentReserved - 1360781717L,
- dbManager.getDynamicPropertiesStore().getTotalStorageReserved());
- Assert.assertEquals(currentPool + 1_000_000_000_000L,
- dbManager.getDynamicPropertiesStore().getTotalStoragePool());
-
- storageMarket.sellStorage(owner, bytes2);
-
- Assert.assertEquals(owner.getBalance(), initBalance);
- Assert.assertEquals(0, owner.getStorageLimit());
- Assert.assertEquals(currentReserved,
- dbManager.getDynamicPropertiesStore().getTotalStorageReserved());
- Assert.assertEquals(currentPool,
- dbManager.getDynamicPropertiesStore().getTotalStoragePool());
-
- }
-
-
-}
diff --git a/framework/src/test/java/org/tron/core/WalletTest.java b/framework/src/test/java/org/tron/core/WalletTest.java
index 357a2d2ca08..a3258cba322 100644
--- a/framework/src/test/java/org/tron/core/WalletTest.java
+++ b/framework/src/test/java/org/tron/core/WalletTest.java
@@ -48,6 +48,7 @@
import org.tron.api.GrpcAPI.ProposalList;
import org.tron.common.BaseTest;
import org.tron.common.crypto.ECKey;
+import org.tron.common.parameter.CommonParameter;
import org.tron.common.utils.ByteArray;
import org.tron.common.utils.Utils;
import org.tron.core.actuator.DelegateResourceActuator;
@@ -72,6 +73,8 @@
import org.tron.core.store.DynamicPropertiesStore;
import org.tron.core.utils.ProposalUtil.ProposalType;
import org.tron.core.utils.TransactionUtil;
+import org.tron.core.vm.config.ConfigLoader;
+import org.tron.core.vm.config.VMConfig;
import org.tron.core.vm.program.Program;
import org.tron.protos.Protocol;
import org.tron.protos.Protocol.Block;
@@ -1043,6 +1046,79 @@ public void testGetAssetIssueByName() {
chainBaseManager.getDynamicPropertiesStore().saveAllowSameTokenName(0);
}
+ @Test
+ @SneakyThrows
+ public void testTriggerConstant() {
+ boolean preDebug = CommonParameter.getInstance().debug;
+ CommonParameter.getInstance().debug = true;
+ ConfigLoader.disable = true;
+ VMConfig.initAllowTvmTransferTrc10(1);
+ VMConfig.initAllowTvmConstantinople(1);
+ VMConfig.initAllowTvmShangHai(1);
+
+ String contractAddress =
+ Wallet.getAddressPreFixString() + "1A622D84ed49f01045f5f1a5AfcEb9c57e9cC3cc";
+
+ AccountCapsule accountCap = new AccountCapsule(
+ ByteString.copyFrom(ByteArray.fromHexString(contractAddress)),
+ Protocol.AccountType.Normal);
+ dbManager.getAccountStore().put(accountCap.createDbKey(), accountCap);
+
+ SmartContractOuterClass.SmartContract smartContract =
+ SmartContractOuterClass.SmartContract.newBuilder().build();
+ ContractCapsule contractCap = new ContractCapsule(smartContract);
+ dbManager.getContractStore().put(ByteArray.fromHexString(contractAddress), contractCap);
+
+ String codeString = "608060405234801561000f575f80fd5b50d3801561001b575f80fd5b50d280156100"
+ + "27575f80fd5b506004361061004c575f3560e01c80638da5cb5b14610050578063f8a8fd6d1461006e57"
+ + "5b5f80fd5b61005861008c565b6040516100659190610269565b60405180910390f35b6100766100af565b"
+ + "6040516100839190610269565b60405180910390f35b5f8054906101000a900473ffffffffffffffffffff"
+ + "ffffffffffffffffffff1681565b5f60017fbe0166938e2ea2f3f3e0746fdaf46e25c4d8de37ce56d70400"
+ + "cf284c80d47bbe601b7f10afab946e2be82aa3e4280cf24e2cab294911c3beb06ca9dd7ead06081265d07f"
+ + "1e1855bcdc3ed57c6f3c3874cde035782427d1236e2d819bd16c75676ecc003a6040515f81526020016040"
+ + "52604051610133949392919061038f565b6020604051602081039080840390855afa158015610153573d5f"
+ + "803e3d5ffd5b505050602060405103515f806101000a81548173ffffffffffffffffffffffffffffffffff"
+ + "ffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550734c95a52686a9b3"
+ + "ff9cf787b94b8549a988334c5773ffffffffffffffffffffffffffffffffffffffff165f8054906101000a"
+ + "900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffff"
+ + "ffff1614610205575f80fd5b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff"
+ + "16905090565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6102538261"
+ + "022a565b9050919050565b61026381610249565b82525050565b5f60208201905061027c5f83018461025a"
+ + "565b92915050565b5f819050919050565b5f819050919050565b5f815f1b9050919050565b5f6102b96102"
+ + "b46102af84610282565b610294565b61028b565b9050919050565b6102c98161029f565b82525050565b5f"
+ + "819050919050565b5f60ff82169050919050565b5f819050919050565b5f6103076103026102fd846102cf"
+ + "565b6102e4565b6102d8565b9050919050565b610317816102ed565b82525050565b5f819050919050565b"
+ + "5f61034061033b6103368461031d565b610294565b61028b565b9050919050565b61035081610326565b82"
+ + "525050565b5f819050919050565b5f61037961037461036f84610356565b610294565b61028b565b905091"
+ + "9050565b6103898161035f565b82525050565b5f6080820190506103a25f8301876102c0565b6103af6020"
+ + "83018661030e565b6103bc6040830185610347565b6103c96060830184610380565b9594505050505056fe"
+ + "a26474726f6e58221220e967690f9c06386434cbe4d8dd6dce394130f190d17621cbd4ae4cabdef4ad7964"
+ + "736f6c63430008140033";
+ CodeCapsule codeCap = new CodeCapsule(ByteArray.fromHexString(codeString));
+ dbManager.getCodeStore().put(ByteArray.fromHexString(contractAddress), codeCap);
+
+ SmartContractOuterClass.TriggerSmartContract contract =
+ SmartContractOuterClass.TriggerSmartContract.newBuilder()
+ .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(contractAddress)))
+ .setContractAddress(ByteString.copyFrom(ByteArray.fromHexString(contractAddress)))
+ .setData(ByteString.copyFrom(ByteArray.fromHexString("f8a8fd6d")))
+ .build();
+ TransactionCapsule trxCap = wallet.createTransactionCapsule(contract,
+ ContractType.TriggerSmartContract);
+
+ GrpcAPI.TransactionExtention.Builder trxExtBuilder = GrpcAPI.TransactionExtention.newBuilder();
+ GrpcAPI.Return.Builder retBuilder = GrpcAPI.Return.newBuilder();
+
+ Transaction tx = wallet.triggerConstantContract(contract, trxCap, trxExtBuilder, retBuilder);
+ Assert.assertEquals(Transaction.Result.code.SUCESS, tx.getRet(0).getRet());
+
+ VMConfig.initAllowTvmTransferTrc10(0);
+ VMConfig.initAllowTvmConstantinople(0);
+ VMConfig.initAllowTvmShangHai(0);
+ ConfigLoader.disable = false;
+ CommonParameter.getInstance().debug = preDebug;
+ }
+
@Test
@SneakyThrows
public void testEstimateEnergy() {
diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java
index 02107427cad..bf60b1cd910 100644
--- a/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java
+++ b/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java
@@ -1502,6 +1502,7 @@ public void SameTokenNameOpenTokenBalanceNotEnough() {
@Test
public void SameTokenNameCloseTokenRequiredNotEnough() {
dbManager.getDynamicPropertiesStore().saveAllowSameTokenName(0);
+ final boolean useStrictMath = dbManager.getDynamicPropertiesStore().allowStrictMath();
InitExchangeBeforeSameTokenNameActive();
long exchangeId = 2;
String tokenId = "abc";
@@ -1520,7 +1521,7 @@ public void SameTokenNameCloseTokenRequiredNotEnough() {
try {
ExchangeCapsule exchangeCapsule = dbManager.getExchangeStore()
.get(ByteArray.fromLong(exchangeId));
- expected = exchangeCapsule.transaction(tokenId.getBytes(), quant);
+ expected = exchangeCapsule.transaction(tokenId.getBytes(), quant, useStrictMath);
} catch (ItemNotFoundException e) {
fail();
}
@@ -1555,6 +1556,7 @@ public void SameTokenNameCloseTokenRequiredNotEnough() {
@Test
public void SameTokenNameOpenTokenRequiredNotEnough() {
dbManager.getDynamicPropertiesStore().saveAllowSameTokenName(1);
+ final boolean useStrictMath = dbManager.getDynamicPropertiesStore().allowStrictMath();
InitExchangeSameTokenNameActive();
long exchangeId = 2;
String tokenId = "123";
@@ -1575,7 +1577,7 @@ public void SameTokenNameOpenTokenRequiredNotEnough() {
try {
ExchangeCapsule exchangeCapsuleV2 = dbManager.getExchangeV2Store()
.get(ByteArray.fromLong(exchangeId));
- expected = exchangeCapsuleV2.transaction(tokenId.getBytes(), quant);
+ expected = exchangeCapsuleV2.transaction(tokenId.getBytes(), quant, useStrictMath);
} catch (ItemNotFoundException e) {
fail();
}
diff --git a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java
index db122f90c4f..52f8cdacc00 100644
--- a/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java
+++ b/framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java
@@ -25,6 +25,7 @@
import org.tron.core.store.DynamicPropertiesStore;
import org.tron.core.utils.ProposalUtil;
import org.tron.core.utils.ProposalUtil.ProposalType;
+import org.tron.protos.Protocol;
@Slf4j(topic = "actuator")
public class ProposalUtilTest extends BaseTest {
@@ -385,6 +386,51 @@ public void validateCheck() {
e.getMessage());
}
+ try {
+ ProposalUtil.validator(dynamicPropertiesStore, forkUtils,
+ ProposalType.ALLOW_STRICT_MATH.getCode(), 2);
+ Assert.fail();
+ } catch (ContractValidateException e) {
+ Assert.assertEquals(
+ "Bad chain parameter id [ALLOW_STRICT_MATH]",
+ e.getMessage());
+ }
+ hardForkTime =
+ ((ForkBlockVersionEnum.VERSION_4_7_7.getHardForkTime() - 1) / maintenanceTimeInterval + 1)
+ * maintenanceTimeInterval;
+ forkUtils.getManager().getDynamicPropertiesStore()
+ .saveLatestBlockHeaderTimestamp(hardForkTime + 1);
+ forkUtils.getManager().getDynamicPropertiesStore()
+ .statsByVersion(ForkBlockVersionEnum.VERSION_4_7_7.getValue(), stats);
+ try {
+ ProposalUtil.validator(dynamicPropertiesStore, forkUtils,
+ ProposalType.ALLOW_STRICT_MATH.getCode(), 2);
+ Assert.fail();
+ } catch (ContractValidateException e) {
+ Assert.assertEquals(
+ "This value[ALLOW_STRICT_MATH] is only allowed to be 1",
+ e.getMessage());
+ }
+ try {
+ ProposalUtil.validator(dynamicPropertiesStore, forkUtils,
+ ProposalType.ALLOW_STRICT_MATH.getCode(), 1);
+ } catch (ContractValidateException e) {
+ Assert.fail(e.getMessage());
+ }
+ Protocol.Proposal proposal = Protocol.Proposal.newBuilder().putParameters(
+ ProposalType.ALLOW_STRICT_MATH.getCode(), 1).build();
+ ProposalCapsule proposalCapsule = new ProposalCapsule(proposal);
+ ProposalService.process(dbManager, proposalCapsule);
+ try {
+ ProposalUtil.validator(dynamicPropertiesStore, forkUtils,
+ ProposalType.ALLOW_STRICT_MATH.getCode(), 1);
+ Assert.fail();
+ } catch (ContractValidateException e) {
+ Assert.assertEquals(
+ "[ALLOW_STRICT_MATH] has been valid, no need to propose again",
+ e.getMessage());
+ }
+
testEnergyAdjustmentProposal();
forkUtils.getManager().getDynamicPropertiesStore()
diff --git a/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java
index 90f74074a9b..0465cd2e867 100644
--- a/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java
+++ b/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java
@@ -1,7 +1,12 @@
package org.tron.core.capsule;
+import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
+import org.mockito.Mockito;
+import org.tron.core.config.args.Args;
+import org.tron.core.store.DynamicPropertiesStore;
+import org.tron.core.vm.config.VMConfig;
import org.tron.protos.contract.SmartContractOuterClass;
public class ContractStateCapsuleTest {
@@ -15,12 +20,12 @@ public void testCatchUpCycle() {
.setUpdateCycle(1000L)
.build());
- Assert.assertFalse(capsule.catchUpToCycle(1000L, 2_000_000L, 2000L, 10_00L));
+ Assert.assertFalse(capsule.catchUpToCycle(1000L, 2_000_000L, 2000L, 10_00L, false));
Assert.assertEquals(1000L, capsule.getUpdateCycle());
Assert.assertEquals(1_000_000L, capsule.getEnergyUsage());
Assert.assertEquals(5000L, capsule.getEnergyFactor());
- Assert.assertTrue(capsule.catchUpToCycle(1010L, 900_000L, 1000L, 10_000L));
+ Assert.assertTrue(capsule.catchUpToCycle(1010L, 900_000L, 1000L, 10_000L, false));
Assert.assertEquals(1010L, capsule.getUpdateCycle());
Assert.assertEquals(0L, capsule.getEnergyUsage());
Assert.assertEquals(3137L, capsule.getEnergyFactor());
@@ -32,7 +37,7 @@ public void testCatchUpCycle() {
.setUpdateCycle(1000L)
.build());
- Assert.assertTrue(capsule.catchUpToCycle(1001L, 2_000_000L, 2000L, 10_000L));
+ Assert.assertTrue(capsule.catchUpToCycle(1001L, 2_000_000L, 2000L, 10_000L, false));
Assert.assertEquals(1001L, capsule.getUpdateCycle());
Assert.assertEquals(0L, capsule.getEnergyUsage());
Assert.assertEquals(4250L, capsule.getEnergyFactor());
@@ -44,7 +49,7 @@ public void testCatchUpCycle() {
.setUpdateCycle(1000L)
.build());
- Assert.assertTrue(capsule.catchUpToCycle(1001L, 1_000_000L, 2000L, 10_000L));
+ Assert.assertTrue(capsule.catchUpToCycle(1001L, 1_000_000L, 2000L, 10_000L, false));
Assert.assertEquals(1001L, capsule.getUpdateCycle());
Assert.assertEquals(0L, capsule.getEnergyUsage());
Assert.assertEquals(4250L, capsule.getEnergyFactor());
@@ -56,7 +61,7 @@ public void testCatchUpCycle() {
.setUpdateCycle(1000L)
.build());
- Assert.assertTrue(capsule.catchUpToCycle(1001L, 900_000L, 2000L, 10_000L));
+ Assert.assertTrue(capsule.catchUpToCycle(1001L, 900_000L, 2000L, 10_000L, false));
Assert.assertEquals(1001L, capsule.getUpdateCycle());
Assert.assertEquals(0L, capsule.getEnergyUsage());
Assert.assertEquals(8000L, capsule.getEnergyFactor());
@@ -68,7 +73,7 @@ public void testCatchUpCycle() {
.setUpdateCycle(1000L)
.build());
- Assert.assertTrue(capsule.catchUpToCycle(1001L, 900_000L, 5000L, 10_000L));
+ Assert.assertTrue(capsule.catchUpToCycle(1001L, 900_000L, 5000L, 10_000L, false));
Assert.assertEquals(1001L, capsule.getUpdateCycle());
Assert.assertEquals(0L, capsule.getEnergyUsage());
Assert.assertEquals(10_000L, capsule.getEnergyFactor());
@@ -80,7 +85,7 @@ public void testCatchUpCycle() {
.setUpdateCycle(1000L)
.build());
- Assert.assertTrue(capsule.catchUpToCycle(1002L, 900_000L, 5000L, 10_000L));
+ Assert.assertTrue(capsule.catchUpToCycle(1002L, 900_000L, 5000L, 10_000L, false));
Assert.assertEquals(1002L, capsule.getUpdateCycle());
Assert.assertEquals(0L, capsule.getEnergyUsage());
Assert.assertEquals(7500L, capsule.getEnergyFactor());
@@ -92,7 +97,7 @@ public void testCatchUpCycle() {
.setUpdateCycle(1000L)
.build());
- Assert.assertTrue(capsule.catchUpToCycle(1003L, 900_000L, 5000L, 10_000L));
+ Assert.assertTrue(capsule.catchUpToCycle(1003L, 900_000L, 5000L, 10_000L, false));
Assert.assertEquals(1003L, capsule.getUpdateCycle());
Assert.assertEquals(0L, capsule.getEnergyUsage());
Assert.assertEquals(5312L, capsule.getEnergyFactor());
@@ -104,7 +109,7 @@ public void testCatchUpCycle() {
.setUpdateCycle(1000L)
.build());
- Assert.assertTrue(capsule.catchUpToCycle(1004L, 900_000L, 5000L, 10_000L));
+ Assert.assertTrue(capsule.catchUpToCycle(1004L, 900_000L, 5000L, 10_000L, false));
Assert.assertEquals(1004L, capsule.getUpdateCycle());
Assert.assertEquals(0L, capsule.getEnergyUsage());
Assert.assertEquals(3398L, capsule.getEnergyFactor());
@@ -116,7 +121,7 @@ public void testCatchUpCycle() {
.setUpdateCycle(1000L)
.build());
- Assert.assertTrue(capsule.catchUpToCycle(1005L, 900_000L, 5000L, 10_000L));
+ Assert.assertTrue(capsule.catchUpToCycle(1005L, 900_000L, 5000L, 10_000L, true));
Assert.assertEquals(1005L, capsule.getUpdateCycle());
Assert.assertEquals(0L, capsule.getEnergyUsage());
Assert.assertEquals(1723L, capsule.getEnergyFactor());
@@ -128,7 +133,7 @@ public void testCatchUpCycle() {
.setUpdateCycle(1000L)
.build());
- Assert.assertTrue(capsule.catchUpToCycle(1005L, 900_000L, 5000L, 10_000L));
+ Assert.assertTrue(capsule.catchUpToCycle(1005L, 900_000L, 5000L, 10_000L, true));
Assert.assertEquals(1005L, capsule.getUpdateCycle());
Assert.assertEquals(0L, capsule.getEnergyUsage());
Assert.assertEquals(1723L, capsule.getEnergyFactor());
@@ -140,7 +145,7 @@ public void testCatchUpCycle() {
.setUpdateCycle(1000L)
.build());
- Assert.assertTrue(capsule.catchUpToCycle(1006L, 900_000L, 5000L, 10_000L));
+ Assert.assertTrue(capsule.catchUpToCycle(1006L, 900_000L, 5000L, 10_000L, true));
Assert.assertEquals(1006L, capsule.getUpdateCycle());
Assert.assertEquals(0L, capsule.getEnergyUsage());
Assert.assertEquals(258L, capsule.getEnergyFactor());
@@ -151,12 +156,25 @@ public void testCatchUpCycle() {
.setEnergyFactor(5000L)
.setUpdateCycle(1000L)
.build());
-
- Assert.assertTrue(capsule.catchUpToCycle(1007L, 900_000L, 5000L, 10_000L));
+ Args.getInstance().setAllowStrictMath(1);
+ VMConfig.initAllowStrictMath(Args.getInstance().getAllowStrictMath());
+ DynamicPropertiesStore dps = Mockito.mock(DynamicPropertiesStore.class);
+ Mockito.when(dps.getCurrentCycleNumber()).thenReturn(1007L);
+ Mockito.when(dps.getDynamicEnergyThreshold()).thenReturn(900_000L);
+ Mockito.when(dps.getDynamicEnergyIncreaseFactor()).thenReturn(5000L);
+ Mockito.when(dps.getDynamicEnergyMaxFactor()).thenReturn(10_000L);
+ Mockito.when(dps.allowStrictMath()).thenReturn(VMConfig.allowStrictMath());
+ Assert.assertTrue(capsule.catchUpToCycle(dps));
Assert.assertEquals(1007L, capsule.getUpdateCycle());
Assert.assertEquals(0L, capsule.getEnergyUsage());
Assert.assertEquals(0L, capsule.getEnergyFactor());
}
+ @After
+ public void reset() {
+ Args.clearParam();
+
+ }
+
}
diff --git a/framework/src/test/java/org/tron/core/capsule/ExchangeCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/ExchangeCapsuleTest.java
index 791767a952f..5fcd259d738 100644
--- a/framework/src/test/java/org/tron/core/capsule/ExchangeCapsuleTest.java
+++ b/framework/src/test/java/org/tron/core/capsule/ExchangeCapsuleTest.java
@@ -52,8 +52,8 @@ public void testExchange() {
long sellQuant = 1_000_000L;
byte[] sellID = "abc".getBytes();
-
- long result = exchangeCapsule.transaction(sellID, sellQuant);
+ boolean useStrictMath = chainBaseManager.getDynamicPropertiesStore().allowStrictMath();
+ long result = exchangeCapsule.transaction(sellID, sellQuant, useStrictMath);
Assert.assertEquals(990_099L, result);
sellBalance += sellQuant;
Assert.assertEquals(sellBalance, exchangeCapsule.getFirstTokenBalance());
@@ -61,7 +61,7 @@ public void testExchange() {
Assert.assertEquals(buyBalance, exchangeCapsule.getSecondTokenBalance());
sellQuant = 9_000_000L;
- long result2 = exchangeCapsule.transaction(sellID, sellQuant);
+ long result2 = exchangeCapsule.transaction(sellID, sellQuant, useStrictMath);
Assert.assertEquals(9090909L, result + result2);
sellBalance += sellQuant;
Assert.assertEquals(sellBalance, exchangeCapsule.getFirstTokenBalance());
diff --git a/framework/src/test/java/org/tron/core/capsule/utils/ExchangeProcessorTest.java b/framework/src/test/java/org/tron/core/capsule/utils/ExchangeProcessorTest.java
index 3437eb0ea42..717c62b01a8 100644
--- a/framework/src/test/java/org/tron/core/capsule/utils/ExchangeProcessorTest.java
+++ b/framework/src/test/java/org/tron/core/capsule/utils/ExchangeProcessorTest.java
@@ -24,7 +24,7 @@ public class ExchangeProcessorTest extends BaseTest {
@BeforeClass
public static void init() {
long supply = 1_000_000_000_000_000_000L;
- processor = new ExchangeProcessor(supply);
+ processor = new ExchangeProcessor(supply, false);
}
@Test
@@ -135,5 +135,15 @@ public void testWithdraw() {
}
+ @Test
+ public void testStrictMath() {
+ long supply = 1_000_000_000_000_000_000L;
+ ExchangeProcessor processor = new ExchangeProcessor(supply, false);
+ long anotherTokenQuant = processor.exchange(4732214, 2202692725330L, 29218);
+ processor = new ExchangeProcessor(supply, true);
+ long result = processor.exchange(4732214, 2202692725330L, 29218);
+ Assert.assertNotEquals(anotherTokenQuant, result);
+ }
+
}
diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java
index 10cc766d8ed..ddf741fb6fa 100755
--- a/framework/src/test/java/org/tron/core/db/ManagerTest.java
+++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java
@@ -1,6 +1,9 @@
package org.tron.core.db;
import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.spy;
import static org.tron.common.utils.Commons.adjustAssetBalanceV2;
import static org.tron.common.utils.Commons.adjustBalance;
import static org.tron.common.utils.Commons.adjustTotalShieldedPoolValue;
@@ -27,6 +30,7 @@
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.contrib.java.lang.system.ExpectedSystemExit;
import org.junit.rules.TemporaryFolder;
import org.tron.common.application.TronApplicationContext;
import org.tron.common.crypto.ECKey;
@@ -107,6 +111,8 @@ public class ManagerTest extends BlockGenerate {
private static BlockCapsule blockCapsule2;
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
+ @Rule
+ public final ExpectedSystemExit exit = ExpectedSystemExit.none();
private static AtomicInteger port = new AtomicInteger(0);
private static String accountAddress =
Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc";
@@ -1151,4 +1157,12 @@ public void testTooBigTransaction() {
TooBigTransactionException.class, () -> dbManager.validateCommon(trx));
}
+
+ @Test
+ public void blockTrigger() {
+ exit.expectSystemExitWithStatus(1);
+ Manager manager = spy(new Manager());
+ doThrow(new RuntimeException("postBlockTrigger mock")).when(manager).postBlockTrigger(any());
+ manager.blockTrigger(new BlockCapsule(Block.newBuilder().build()), 1, 1);
+ }
}
diff --git a/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java b/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java
index ebb9e0bb223..83930403312 100644
--- a/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java
+++ b/framework/src/test/java/org/tron/core/services/RpcApiServicesTest.java
@@ -138,6 +138,8 @@ public static void init() throws IOException {
getInstance().setRpcPort(PublicMethod.chooseRandomPort());
getInstance().setRpcOnSolidityPort(PublicMethod.chooseRandomPort());
getInstance().setRpcOnPBFTPort(PublicMethod.chooseRandomPort());
+ getInstance().setMetricsPrometheusPort(PublicMethod.chooseRandomPort());
+ getInstance().setMetricsPrometheusEnable(true);
String fullNode = String.format("%s:%d", getInstance().getNodeLanIp(),
getInstance().getRpcPort());
String solidityNode = String.format("%s:%d", getInstance().getNodeLanIp(),