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(),