diff --git a/.github/workflows/math-check.yml b/.github/workflows/math-check.yml new file mode 100644 index 00000000000..0f0255815d5 --- /dev/null +++ b/.github/workflows/math-check.yml @@ -0,0 +1,93 @@ +name: Check Math Usage + +on: + push: + branches: [ 'master', 'release_**' ] + pull_request: + branches: [ 'develop', 'release_**' ] + workflow_dispatch: + +jobs: + check-math: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Check for java.lang.Math usage + id: check-math + shell: bash + run: | + echo "Checking for java.lang.Math usage..." + + touch math_usage.txt + + while IFS= read -r file; do + filename=$(basename "$file") + if [[ "$filename" == "StrictMathWrapper.java" || "$filename" == "MathWrapper.java" ]]; then + continue + fi + + perl -0777 -ne ' + s/"([^"\\]|\\.)*"//g; + s/'\''([^'\''\\]|\\.)*'\''//g; + s!/\*([^*]|\*[^/])*\*/!!g; + s!//[^\n]*!!g; + $hasMath = 0; + $hasMath = 1 if /^[\s]*import[\s]+java\.lang\.Math\b/m; + $hasMath = 1 if /\bjava\s*\.\s*lang\s*\.\s*Math\s*\./; + $hasMath = 1 if /(?> math_usage.txt + done < <(find . -type f -name "*.java") + + sort -u math_usage.txt -o math_usage.txt + + if [ -s math_usage.txt ]; then + echo "❌ Error: Forbidden Math usage found in the following files:" + cat math_usage.txt + echo "math_found=true" >> $GITHUB_OUTPUT + echo "Please use org.tron.common.math.StrictMathWrapper instead of direct Math usage." + else + echo "✅ No forbidden Math usage found" + echo "math_found=false" >> $GITHUB_OUTPUT + fi + + - name: Upload findings + if: steps.check-math.outputs.math_found == 'true' + uses: actions/upload-artifact@v4 + with: + name: math-usage-report + path: math_usage.txt + + - name: Create comment + if: github.event_name == 'pull_request' && steps.check-math.outputs.math_found == 'true' + uses: actions/github-script@v6 + with: + script: | + const fs = require('fs'); + const findings = fs.readFileSync('math_usage.txt', 'utf8'); + const body = `### ❌ Math Usage Detection Results + + Found forbidden usage of \`java.lang.Math\` in the following files: + + \`\`\` + ${findings} + \`\`\` + + **Please review if this usage is intended.** + > [!CAUTION] + > Note: You should use \`org.tron.common.math.StrictMathWrapper\`. + > If you need to use \`java.lang.Math\`, please provide a justification. + `; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: body + }); + + - name: Fail if Math usage found + if: steps.check-math.outputs.math_found == 'true' + run: exit 1 diff --git a/actuator/src/main/java/org/tron/core/actuator/AbstractActuator.java b/actuator/src/main/java/org/tron/core/actuator/AbstractActuator.java index c88baf9b3ca..2f1bb450d1b 100644 --- a/actuator/src/main/java/org/tron/core/actuator/AbstractActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/AbstractActuator.java @@ -2,9 +2,14 @@ import com.google.protobuf.Any; import com.google.protobuf.GeneratedMessageV3; +import org.tron.common.math.Maths; +import org.tron.common.utils.Commons; import org.tron.common.utils.ForkController; import org.tron.core.ChainBaseManager; +import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.exception.BalanceInsufficientException; +import org.tron.core.store.AccountStore; import org.tron.protos.Protocol.Transaction.Contract; import org.tron.protos.Protocol.Transaction.Contract.ContractType; @@ -63,4 +68,61 @@ public AbstractActuator setForkUtils(ForkController forkController) { return this; } + public long addExact(long x, long y) { + return Maths.addExact(x, y, chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + } + + public long addExact(int x, int y) { + return Maths.addExact(x, y, chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + } + + public long floorDiv(long x, long y) { + return Maths.floorDiv(x, y, chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + } + + public long floorDiv(long x, int y) { + return this.floorDiv(x, (long) y); + } + + public long multiplyExact(long x, long y) { + return Maths.multiplyExact(x, y, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + } + + public long multiplyExact(long x, int y) { + return this.multiplyExact(x, (long) y); + } + + public int multiplyExact(int x, int y) { + return Maths.multiplyExact(x, y, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + } + + public long subtractExact(long x, long y) { + return Maths.subtractExact(x, y, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + } + + public int min(int a, int b) { + return Maths.min(a, b, chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + } + + public long min(long a, long b) { + return Maths.min(a, b, chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + } + + public void adjustBalance(AccountStore accountStore, byte[] accountAddress, long amount) + throws BalanceInsufficientException { + AccountCapsule account = accountStore.getUnchecked(accountAddress); + this.adjustBalance(accountStore, account, amount); + } + + /** + * judge balance. + */ + public void adjustBalance(AccountStore accountStore, AccountCapsule account, long amount) + throws BalanceInsufficientException { + Commons.adjustBalance(accountStore, account, amount, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + } } diff --git a/actuator/src/main/java/org/tron/core/actuator/AccountPermissionUpdateActuator.java b/actuator/src/main/java/org/tron/core/actuator/AccountPermissionUpdateActuator.java index fcc4d775d43..f2eafb20a5e 100644 --- a/actuator/src/main/java/org/tron/core/actuator/AccountPermissionUpdateActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/AccountPermissionUpdateActuator.java @@ -8,7 +8,6 @@ import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.tron.common.utils.Commons; import org.tron.common.utils.DecodeUtil; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionResultCapsule; @@ -52,11 +51,11 @@ public boolean execute(Object object) throws ContractExeException { accountPermissionUpdateContract.getActivesList()); accountStore.put(ownerAddress, account); - Commons.adjustBalance(accountStore, ownerAddress, -fee); + adjustBalance(accountStore, ownerAddress, -fee); if (chainBaseManager.getDynamicPropertiesStore().supportBlackHoleOptimization()) { chainBaseManager.getDynamicPropertiesStore().burnTrx(fee); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole(), fee); + adjustBalance(accountStore, accountStore.getBlackhole(), fee); } result.setStatus(fee, code.SUCESS); @@ -111,7 +110,7 @@ private boolean checkPermission(Permission permission) throws ContractValidateEx throw new ContractValidateException("key's weight should be greater than 0"); } try { - weightSum = Math.addExact(weightSum, key.getWeight()); + weightSum = addExact(weightSum, key.getWeight()); } catch (ArithmeticException e) { throw new ContractValidateException(e.getMessage()); } diff --git a/actuator/src/main/java/org/tron/core/actuator/AssetIssueActuator.java b/actuator/src/main/java/org/tron/core/actuator/AssetIssueActuator.java index 55218897c5d..331b45f106a 100644 --- a/actuator/src/main/java/org/tron/core/actuator/AssetIssueActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/AssetIssueActuator.java @@ -24,7 +24,6 @@ import java.util.List; import java.util.Objects; import lombok.extern.slf4j.Slf4j; -import org.tron.common.utils.Commons; import org.tron.common.utils.DecodeUtil; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; @@ -84,11 +83,11 @@ public boolean execute(Object result) throws ContractExeException { .put(assetIssueCapsuleV2.createDbV2Key(), assetIssueCapsuleV2); } - Commons.adjustBalance(accountStore, ownerAddress, -fee); + adjustBalance(accountStore, ownerAddress, -fee); if (dynamicStore.supportBlackHoleOptimization()) { dynamicStore.burnTrx(fee); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole(), fee);//send to blackhole + adjustBalance(accountStore, accountStore.getBlackhole(), fee);//send to blackhole } AccountCapsule accountCapsule = accountStore.get(ownerAddress); List frozenSupplyList = assetIssueContract.getFrozenSupplyList(); diff --git a/actuator/src/main/java/org/tron/core/actuator/CreateAccountActuator.java b/actuator/src/main/java/org/tron/core/actuator/CreateAccountActuator.java index 1c6aca4d7d7..352f394d6cb 100755 --- a/actuator/src/main/java/org/tron/core/actuator/CreateAccountActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/CreateAccountActuator.java @@ -6,7 +6,6 @@ import com.google.protobuf.InvalidProtocolBufferException; import java.util.Objects; import lombok.extern.slf4j.Slf4j; -import org.tron.common.utils.Commons; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; import org.tron.core.capsule.AccountCapsule; @@ -48,13 +47,12 @@ public boolean execute(Object result) accountStore .put(accountCreateContract.getAccountAddress().toByteArray(), accountCapsule); - Commons - .adjustBalance(accountStore, accountCreateContract.getOwnerAddress().toByteArray(), -fee); + adjustBalance(accountStore, accountCreateContract.getOwnerAddress().toByteArray(), -fee); // Add to blackhole address if (dynamicStore.supportBlackHoleOptimization()) { dynamicStore.burnTrx(fee); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole(), fee); + adjustBalance(accountStore, accountStore.getBlackhole(), fee); } ret.setStatus(fee, code.SUCESS); } catch (BalanceInsufficientException | InvalidProtocolBufferException e) { diff --git a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java index 161f22cfb17..90e91d8d3b2 100755 --- a/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/DelegateResourceActuator.java @@ -162,7 +162,8 @@ public boolean validate() throws ContractValidateException { } long netUsage = (long) (accountNetUsage * TRX_PRECISION * ((double) (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); - long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage); + long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage, + dynamicStore.allowStrictMath2()); if (ownerCapsule.getFrozenV2BalanceForBandwidth() - v2NetUsage < delegateBalance) { throw new ContractValidateException( "delegateBalance must be less than or equal to available FreezeBandwidthV2 balance"); @@ -175,7 +176,8 @@ public boolean validate() throws ContractValidateException { long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); - long v2EnergyUsage = getV2EnergyUsage(ownerCapsule, energyUsage); + long v2EnergyUsage = getV2EnergyUsage(ownerCapsule, energyUsage, + dynamicStore.allowStrictMath2()); if (ownerCapsule.getFrozenV2BalanceForEnergy() - v2EnergyUsage < delegateBalance) { throw new ContractValidateException( "delegateBalance must be less than or equal to available FreezeEnergyV2 balance"); diff --git a/actuator/src/main/java/org/tron/core/actuator/ExchangeCreateActuator.java b/actuator/src/main/java/org/tron/core/actuator/ExchangeCreateActuator.java index b7f5b90da45..27d3da509b4 100755 --- a/actuator/src/main/java/org/tron/core/actuator/ExchangeCreateActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/ExchangeCreateActuator.java @@ -9,7 +9,6 @@ import java.util.Arrays; import java.util.Objects; import lombok.extern.slf4j.Slf4j; -import org.tron.common.utils.Commons; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; import org.tron.core.capsule.AccountCapsule; @@ -121,7 +120,7 @@ public boolean execute(Object object) throws ContractExeException { if (dynamicStore.supportBlackHoleOptimization()) { dynamicStore.burnTrx(fee); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole(), fee); + adjustBalance(accountStore, accountStore.getBlackhole(), fee); } ret.setExchangeId(id); ret.setStatus(fee, code.SUCESS); diff --git a/actuator/src/main/java/org/tron/core/actuator/ExchangeInjectActuator.java b/actuator/src/main/java/org/tron/core/actuator/ExchangeInjectActuator.java index 7848f898ced..482f5bdf081 100755 --- a/actuator/src/main/java/org/tron/core/actuator/ExchangeInjectActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/ExchangeInjectActuator.java @@ -71,14 +71,14 @@ public boolean execute(Object object) throws ContractExeException { if (Arrays.equals(tokenID, firstTokenID)) { anotherTokenID = secondTokenID; - anotherTokenQuant = Math - .floorDiv(Math.multiplyExact(secondTokenBalance, tokenQuant), firstTokenBalance); + anotherTokenQuant = floorDiv(multiplyExact( + secondTokenBalance, tokenQuant), firstTokenBalance); exchangeCapsule.setBalance(firstTokenBalance + tokenQuant, secondTokenBalance + anotherTokenQuant); } else { anotherTokenID = firstTokenID; - anotherTokenQuant = Math - .floorDiv(Math.multiplyExact(firstTokenBalance, tokenQuant), secondTokenBalance); + anotherTokenQuant = floorDiv(multiplyExact( + firstTokenBalance, tokenQuant), secondTokenBalance); exchangeCapsule.setBalance(firstTokenBalance + anotherTokenQuant, secondTokenBalance + tokenQuant); } diff --git a/actuator/src/main/java/org/tron/core/actuator/ExchangeWithdrawActuator.java b/actuator/src/main/java/org/tron/core/actuator/ExchangeWithdrawActuator.java index 8929305d68c..fb8fe9384d3 100755 --- a/actuator/src/main/java/org/tron/core/actuator/ExchangeWithdrawActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/ExchangeWithdrawActuator.java @@ -76,16 +76,12 @@ public boolean execute(Object object) throws ContractExeException { BigInteger bigTokenQuant = new BigInteger(String.valueOf(tokenQuant)); if (Arrays.equals(tokenID, firstTokenID)) { anotherTokenID = secondTokenID; -// anotherTokenQuant = Math -// .floorDiv(Math.multiplyExact(secondTokenBalance, tokenQuant), firstTokenBalance); anotherTokenQuant = bigSecondTokenBalance.multiply(bigTokenQuant) .divide(bigFirstTokenBalance).longValueExact(); exchangeCapsule.setBalance(firstTokenBalance - tokenQuant, secondTokenBalance - anotherTokenQuant); } else { anotherTokenID = firstTokenID; -// anotherTokenQuant = Math -// .floorDiv(Math.multiplyExact(firstTokenBalance, tokenQuant), secondTokenBalance); anotherTokenQuant = bigFirstTokenBalance.multiply(bigTokenQuant) .divide(bigSecondTokenBalance).longValueExact(); exchangeCapsule.setBalance(firstTokenBalance - anotherTokenQuant, @@ -210,8 +206,6 @@ public boolean validate() throws ContractValidateException { BigDecimal bigSecondTokenBalance = new BigDecimal(String.valueOf(secondTokenBalance)); BigDecimal bigTokenQuant = new BigDecimal(String.valueOf(tokenQuant)); if (Arrays.equals(tokenID, firstTokenID)) { -// anotherTokenQuant = Math -// .floorDiv(Math.multiplyExact(secondTokenBalance, tokenQuant), firstTokenBalance); anotherTokenQuant = bigSecondTokenBalance.multiply(bigTokenQuant) .divideToIntegralValue(bigFirstTokenBalance).longValueExact(); if (firstTokenBalance < tokenQuant || secondTokenBalance < anotherTokenQuant) { @@ -230,8 +224,6 @@ public boolean validate() throws ContractValidateException { } } else { -// anotherTokenQuant = Math -// .floorDiv(Math.multiplyExact(firstTokenBalance, tokenQuant), secondTokenBalance); anotherTokenQuant = bigFirstTokenBalance.multiply(bigTokenQuant) .divideToIntegralValue(bigSecondTokenBalance).longValueExact(); if (secondTokenBalance < tokenQuant || firstTokenBalance < anotherTokenQuant) { diff --git a/actuator/src/main/java/org/tron/core/actuator/MarketCancelOrderActuator.java b/actuator/src/main/java/org/tron/core/actuator/MarketCancelOrderActuator.java index f859e580253..31b5e87e12d 100644 --- a/actuator/src/main/java/org/tron/core/actuator/MarketCancelOrderActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/MarketCancelOrderActuator.java @@ -23,7 +23,6 @@ import com.google.protobuf.InvalidProtocolBufferException; import java.util.Objects; import lombok.extern.slf4j.Slf4j; -import org.tron.common.utils.Commons; import org.tron.common.utils.DecodeUtil; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.MarketOrderCapsule; @@ -100,7 +99,7 @@ public boolean execute(Object object) throws ContractExeException { if (dynamicStore.supportBlackHoleOptimization()) { dynamicStore.burnTrx(fee); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole(), fee); + adjustBalance(accountStore, accountStore.getBlackhole(), fee); } // 1. return balance and token MarketUtils diff --git a/actuator/src/main/java/org/tron/core/actuator/MarketSellAssetActuator.java b/actuator/src/main/java/org/tron/core/actuator/MarketSellAssetActuator.java index 15e5a98f86a..43f21b716d8 100644 --- a/actuator/src/main/java/org/tron/core/actuator/MarketSellAssetActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/MarketSellAssetActuator.java @@ -129,7 +129,7 @@ public boolean execute(Object object) throws ContractExeException { if (dynamicStore.supportBlackHoleOptimization()) { dynamicStore.burnTrx(fee); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole(), fee); + adjustBalance(accountStore, accountStore.getBlackhole(), fee); } // 1. transfer of balance transferBalanceOrToken(accountCapsule); @@ -244,7 +244,7 @@ public boolean validate() throws ContractValidateException { long fee = calcFee(); if (Arrays.equals(sellTokenID, "_".getBytes())) { - if (ownerAccount.getBalance() < Math.addExact(sellTokenQuantity, fee)) { + if (ownerAccount.getBalance() < addExact(sellTokenQuantity, fee)) { throw new ContractValidateException("No enough balance !"); } } else { @@ -400,8 +400,10 @@ private void matchSingleOrder(MarketOrderCapsule takerOrderCapsule, // => takerBuyTokenQuantityCurrent_A = takerSellTokenQuantityRemain_TRX * // makerSellTokenQuantity_A/makerBuyTokenQuantity_TRX + boolean useStrictMath2 = dynamicStore.allowStrictMath2(); long takerBuyTokenQuantityRemain = MarketUtils - .multiplyAndDivide(takerSellRemainQuantity, makerSellQuantity, makerBuyQuantity); + .multiplyAndDivide(takerSellRemainQuantity, makerSellQuantity, makerBuyQuantity, + useStrictMath2); if (takerBuyTokenQuantityRemain == 0) { // quantity too small, return sellToken to user @@ -424,7 +426,8 @@ private void matchSingleOrder(MarketOrderCapsule takerOrderCapsule, // makerBuyTokenQuantity_TRX / makerSellTokenQuantity_A makerBuyTokenQuantityReceive = MarketUtils - .multiplyAndDivide(makerSellRemainQuantity, makerBuyQuantity, makerSellQuantity); + .multiplyAndDivide(makerSellRemainQuantity, makerBuyQuantity, makerSellQuantity, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); takerBuyTokenQuantityReceive = makerOrderCapsule.getSellTokenQuantityRemain(); long takerSellTokenLeft = @@ -447,7 +450,7 @@ private void matchSingleOrder(MarketOrderCapsule takerOrderCapsule, takerOrderCapsule.setSellTokenQuantityRemain(0); MarketUtils.updateOrderState(takerOrderCapsule, State.INACTIVE, marketAccountStore); - makerOrderCapsule.setSellTokenQuantityRemain(Math.subtractExact( + makerOrderCapsule.setSellTokenQuantityRemain(subtractExact( makerOrderCapsule.getSellTokenQuantityRemain(), takerBuyTokenQuantityRemain)); } else { // taker > maker @@ -458,7 +461,8 @@ private void matchSingleOrder(MarketOrderCapsule takerOrderCapsule, // makerSellTokenQuantityRemain_A/makerBuyTokenQuantityCurrent_TRX = // makerSellTokenQuantity_A/makerBuyTokenQuantity_TRX makerBuyTokenQuantityReceive = MarketUtils - .multiplyAndDivide(makerSellRemainQuantity, makerBuyQuantity, makerSellQuantity); + .multiplyAndDivide(makerSellRemainQuantity, makerBuyQuantity, makerSellQuantity, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); MarketUtils.updateOrderState(makerOrderCapsule, State.INACTIVE, marketAccountStore); if (makerBuyTokenQuantityReceive == 0) { @@ -475,7 +479,7 @@ private void matchSingleOrder(MarketOrderCapsule takerOrderCapsule, return; } else { makerOrderCapsule.setSellTokenQuantityRemain(0); - takerOrderCapsule.setSellTokenQuantityRemain(Math.subtractExact( + takerOrderCapsule.setSellTokenQuantityRemain(subtractExact( takerOrderCapsule.getSellTokenQuantityRemain(), makerBuyTokenQuantityReceive)); } } @@ -524,7 +528,8 @@ private MarketOrderCapsule createAndSaveOrder(AccountCapsule accountCapsule, private void transferBalanceOrToken(AccountCapsule accountCapsule) { if (Arrays.equals(sellTokenID, "_".getBytes())) { - accountCapsule.setBalance(Math.subtractExact(accountCapsule.getBalance(), sellTokenQuantity)); + accountCapsule.setBalance(subtractExact( + accountCapsule.getBalance(), sellTokenQuantity)); } else { accountCapsule .reduceAssetAmountV2(sellTokenID, sellTokenQuantity, dynamicStore, assetIssueStore); @@ -537,7 +542,7 @@ private void addTrxOrToken(MarketOrderCapsule orderCapsule, long num, byte[] buyTokenId = orderCapsule.getBuyTokenId(); if (Arrays.equals(buyTokenId, "_".getBytes())) { - accountCapsule.setBalance(Math.addExact(accountCapsule.getBalance(), num)); + accountCapsule.setBalance(addExact(accountCapsule.getBalance(), num)); } else { accountCapsule .addAssetAmountV2(buyTokenId, num, dynamicStore, assetIssueStore); @@ -550,7 +555,7 @@ private void addTrxOrToken(MarketOrderCapsule orderCapsule, long num) { byte[] buyTokenId = orderCapsule.getBuyTokenId(); if (Arrays.equals(buyTokenId, "_".getBytes())) { - accountCapsule.setBalance(Math.addExact(accountCapsule.getBalance(), num)); + accountCapsule.setBalance(addExact(accountCapsule.getBalance(), num)); } else { accountCapsule .addAssetAmountV2(buyTokenId, num, dynamicStore, assetIssueStore); diff --git a/actuator/src/main/java/org/tron/core/actuator/ParticipateAssetIssueActuator.java b/actuator/src/main/java/org/tron/core/actuator/ParticipateAssetIssueActuator.java index 77e345b2a92..7fdf15acd18 100755 --- a/actuator/src/main/java/org/tron/core/actuator/ParticipateAssetIssueActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/ParticipateAssetIssueActuator.java @@ -64,8 +64,8 @@ public boolean execute(Object object) throws ContractExeException { //subtract from owner address byte[] ownerAddress = participateAssetIssueContract.getOwnerAddress().toByteArray(); AccountCapsule ownerAccount = accountStore.get(ownerAddress); - long balance = Math.subtractExact(ownerAccount.getBalance(), cost); - balance = Math.subtractExact(balance, fee); + long balance = subtractExact(ownerAccount.getBalance(), cost); + balance = subtractExact(balance, fee); ownerAccount.setBalance(balance); byte[] key = participateAssetIssueContract.getAssetName().toByteArray(); @@ -74,14 +74,14 @@ public boolean execute(Object object) throws ContractExeException { assetIssueCapsule = Commons .getAssetIssueStoreFinal(dynamicStore, assetIssueStore, assetIssueV2Store).get(key); - long exchangeAmount = Math.multiplyExact(cost, assetIssueCapsule.getNum()); - exchangeAmount = Math.floorDiv(exchangeAmount, assetIssueCapsule.getTrxNum()); + long exchangeAmount = multiplyExact(cost, assetIssueCapsule.getNum()); + exchangeAmount = floorDiv(exchangeAmount, assetIssueCapsule.getTrxNum()); ownerAccount.addAssetAmountV2(key, exchangeAmount, dynamicStore, assetIssueStore); //add to to_address byte[] toAddress = participateAssetIssueContract.getToAddress().toByteArray(); AccountCapsule toAccount = accountStore.get(toAddress); - toAccount.setBalance(Math.addExact(toAccount.getBalance(), cost)); + toAccount.setBalance(addExact(toAccount.getBalance(), cost)); if (!toAccount.reduceAssetAmountV2(key, exchangeAmount, dynamicStore, assetIssueStore)) { throw new ContractExeException("reduceAssetAmount failed !"); } @@ -156,7 +156,7 @@ public boolean validate() throws ContractValidateException { try { //Whether the balance is enough long fee = calcFee(); - if (ownerAccount.getBalance() < Math.addExact(amount, fee)) { + if (ownerAccount.getBalance() < addExact(amount, fee)) { throw new ContractValidateException("No enough balance !"); } @@ -181,8 +181,8 @@ public boolean validate() throws ContractValidateException { int trxNum = assetIssueCapsule.getTrxNum(); int num = assetIssueCapsule.getNum(); - long exchangeAmount = Math.multiplyExact(amount, num); - exchangeAmount = Math.floorDiv(exchangeAmount, trxNum); + long exchangeAmount = multiplyExact(amount, num); + exchangeAmount = floorDiv(exchangeAmount, trxNum); if (exchangeAmount <= 0) { throw new ContractValidateException("Can not process the exchange!"); } diff --git a/actuator/src/main/java/org/tron/core/actuator/ShieldedTransferActuator.java b/actuator/src/main/java/org/tron/core/actuator/ShieldedTransferActuator.java index 284650f1ffb..2773dc07d26 100644 --- a/actuator/src/main/java/org/tron/core/actuator/ShieldedTransferActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/ShieldedTransferActuator.java @@ -96,9 +96,9 @@ public boolean execute(Object result) //adjust and verify total shielded pool value try { - Commons.adjustTotalShieldedPoolValue( - Math.addExact(Math.subtractExact(shieldedTransferContract.getToAmount(), - shieldedTransferContract.getFromAmount()), fee), dynamicStore); + Commons.adjustTotalShieldedPoolValue(addExact(subtractExact( + shieldedTransferContract.getToAmount(), + shieldedTransferContract.getFromAmount()), fee), dynamicStore); } catch (ArithmeticException | BalanceInsufficientException e) { logger.debug(e.getMessage(), e); ret.setStatus(0, code.FAILED); @@ -327,9 +327,11 @@ private void checkProof(List spendDescriptions, long totalShieldedPoolValue = dynamicStore .getTotalShieldedPoolValue(); try { - valueBalance = Math.addExact(Math.subtractExact(shieldedTransferContract.getToAmount(), + valueBalance = addExact(subtractExact( + shieldedTransferContract.getToAmount(), shieldedTransferContract.getFromAmount()), fee); - totalShieldedPoolValue = Math.subtractExact(totalShieldedPoolValue, valueBalance); + totalShieldedPoolValue = subtractExact( + totalShieldedPoolValue, valueBalance); } catch (ArithmeticException e) { logger.debug(e.getMessage(), e); throw new ZkProofValidateException(e.getMessage(), true); @@ -452,7 +454,7 @@ private void validateTransparent(ShieldedTransferContract shieldedTransferContra AccountCapsule toAccount = accountStore.get(toAddress); if (toAccount != null) { try { - Math.addExact(getZenBalance(toAccount), toAmount); + addExact(getZenBalance(toAccount), toAmount); } catch (ArithmeticException e) { logger.debug(e.getMessage(), e); throw new ContractValidateException(e.getMessage()); diff --git a/actuator/src/main/java/org/tron/core/actuator/TransferActuator.java b/actuator/src/main/java/org/tron/core/actuator/TransferActuator.java index 5e3d605aed7..a0deabf8f00 100755 --- a/actuator/src/main/java/org/tron/core/actuator/TransferActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/TransferActuator.java @@ -7,7 +7,6 @@ import java.util.Arrays; import java.util.Objects; import lombok.extern.slf4j.Slf4j; -import org.tron.common.utils.Commons; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; import org.tron.core.capsule.AccountCapsule; @@ -58,13 +57,13 @@ public boolean execute(Object object) throws ContractExeException { fee = fee + dynamicStore.getCreateNewAccountFeeInSystemContract(); } - Commons.adjustBalance(accountStore, ownerAddress, -(Math.addExact(fee, amount))); + adjustBalance(accountStore, ownerAddress, -(addExact(fee, amount))); if (dynamicStore.supportBlackHoleOptimization()) { dynamicStore.burnTrx(fee); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole(), fee); + adjustBalance(accountStore, accountStore.getBlackhole(), fee); } - Commons.adjustBalance(accountStore, toAddress, amount); + adjustBalance(accountStore, toAddress, amount); ret.setStatus(fee, code.SUCESS); } catch (BalanceInsufficientException | ArithmeticException | InvalidProtocolBufferException e) { logger.debug(e.getMessage(), e); @@ -156,7 +155,7 @@ public boolean validate() throws ContractValidateException { } } - if (balance < Math.addExact(amount, fee)) { + if (balance < addExact(amount, fee)) { logger.warn("Balance is not sufficient. Account: {}, balance: {}, amount: {}, fee: {}.", StringUtil.encode58Check(ownerAddress), balance, amount, fee); throw new ContractValidateException( @@ -164,7 +163,7 @@ public boolean validate() throws ContractValidateException { } if (toAccount != null) { - Math.addExact(toAccount.getBalance(), amount); + addExact(toAccount.getBalance(), amount); } } catch (ArithmeticException e) { logger.debug(e.getMessage(), e); diff --git a/actuator/src/main/java/org/tron/core/actuator/TransferAssetActuator.java b/actuator/src/main/java/org/tron/core/actuator/TransferAssetActuator.java index de2b2faec86..d93263055eb 100644 --- a/actuator/src/main/java/org/tron/core/actuator/TransferAssetActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/TransferAssetActuator.java @@ -83,11 +83,11 @@ public boolean execute(Object result) throws ContractExeException { .addAssetAmountV2(assetName.toByteArray(), amount, dynamicStore, assetIssueStore); accountStore.put(toAddress, toAccountCapsule); - Commons.adjustBalance(accountStore, ownerAccountCapsule, -fee); + adjustBalance(accountStore, ownerAccountCapsule, -fee); if (dynamicStore.supportBlackHoleOptimization()) { dynamicStore.burnTrx(fee); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole(), fee); + adjustBalance(accountStore, accountStore.getBlackhole(), fee); } ret.setStatus(fee, code.SUCESS); } catch (BalanceInsufficientException e) { @@ -177,7 +177,7 @@ public boolean validate() throws ContractValidateException { assetBalance = toAccount.getAsset(dynamicStore, ByteArray.toStr(assetName)); if (assetBalance != null) { try { - assetBalance = Math.addExact(assetBalance, amount); //check if overflow + assetBalance = addExact(assetBalance, amount); //check if overflow } catch (Exception e) { logger.debug(e.getMessage(), e); throw new ContractValidateException(e.getMessage()); diff --git a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java index 79a09664180..2f2eed7fded 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnDelegateResourceActuator.java @@ -82,7 +82,7 @@ public boolean execute(Object result) throws ContractExeException { * ((double) (dynamicStore.getTotalNetLimit()) / dynamicStore.getTotalNetWeight())); transferUsage = (long) (receiverCapsule.getNetUsage() * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForBandwidth())); - transferUsage = Math.min(unDelegateMaxUsage, transferUsage); + transferUsage = min(unDelegateMaxUsage, transferUsage); receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForBandwidth(-unDelegateBalance); } @@ -105,7 +105,7 @@ public boolean execute(Object result) throws ContractExeException { * ((double) (dynamicStore.getTotalEnergyCurrentLimit()) / dynamicStore.getTotalEnergyWeight())); transferUsage = (long) (receiverCapsule.getEnergyUsage() * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForEnergy())); - transferUsage = Math.min(unDelegateMaxUsage, transferUsage); + transferUsage = min(unDelegateMaxUsage, transferUsage); receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForEnergy(-unDelegateBalance); } diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index 08d0f5a8da5..42ddc65c745 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -1,9 +1,11 @@ package org.tron.core.actuator; -import static java.lang.Math.max; -import static java.lang.Math.min; import static org.apache.commons.lang3.ArrayUtils.getLength; import static org.apache.commons.lang3.ArrayUtils.isNotEmpty; +import static org.tron.common.math.Maths.addExact; +import static org.tron.common.math.Maths.floorDiv; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.min; import static org.tron.protos.contract.Common.ResourceCode.ENERGY; import com.google.protobuf.ByteString; @@ -124,9 +126,9 @@ public void validate(Object object) throws ContractValidateException { trx = context.getTrxCap().getInstance(); // If tx`s fee limit is set, use it to calc max energy limit for constant call if (isConstantCall && trx.getRawData().getFeeLimit() > 0) { - maxEnergyLimit = Math.min(maxEnergyLimit, trx.getRawData().getFeeLimit() + maxEnergyLimit = min(maxEnergyLimit, trx.getRawData().getFeeLimit() / context.getStoreFactory().getChainBaseManager() - .getDynamicPropertiesStore().getEnergyFee()); + .getDynamicPropertiesStore().getEnergyFee(), VMConfig.allowStrictMath2()); } blockCap = context.getBlockCap(); if ((VMConfig.allowTvmFreeze() || VMConfig.allowTvmFreezeV2()) @@ -563,8 +565,10 @@ public long getAccountEnergyLimitWithFixRatio(AccountCapsule account, long feeLi receipt.setCallerEnergyLeft(leftFrozenEnergy); } - long energyFromBalance = max(account.getBalance() - callValue, 0) / sunPerEnergy; - long availableEnergy = Math.addExact(leftFrozenEnergy, energyFromBalance); + long energyFromBalance = max(account.getBalance() - callValue, 0, + VMConfig.allowStrictMath2()) / sunPerEnergy; + long availableEnergy = addExact(leftFrozenEnergy, energyFromBalance, + VMConfig.allowStrictMath2()); long energyFromFeeLimit = feeLimit / sunPerEnergy; if (VMConfig.allowTvmFreezeV2()) { @@ -580,12 +584,13 @@ public long getAccountEnergyLimitWithFixRatio(AccountCapsule account, long feeLi receipt.setCallerEnergyWindowSizeV2(account.getWindowSizeV2(ENERGY)); account.setEnergyUsage( energyProcessor.increase(account, ENERGY, - account.getEnergyUsage(), min(leftFrozenEnergy, energyFromFeeLimit), now, now)); + account.getEnergyUsage(), min(leftFrozenEnergy, energyFromFeeLimit, + VMConfig.allowStrictMath2()), now, now)); receipt.setCallerEnergyMergedUsage(account.getEnergyUsage()); receipt.setCallerEnergyMergedWindowSize(account.getWindowSize(ENERGY)); rootRepository.updateAccount(account.createDbKey(), account); } - return min(availableEnergy, energyFromFeeLimit); + return min(availableEnergy, energyFromFeeLimit, VMConfig.allowStrictMath2()); } @@ -598,9 +603,10 @@ private long getAccountEnergyLimitWithFloatRatio(AccountCapsule account, long fe } // can change the calc way long leftEnergyFromFreeze = rootRepository.getAccountLeftEnergyFromFreeze(account); - callValue = max(callValue, 0); - long energyFromBalance = Math - .floorDiv(max(account.getBalance() - callValue, 0), sunPerEnergy); + boolean isStrict2 = VMConfig.allowStrictMath2(); + callValue = max(callValue, 0, isStrict2); + long energyFromBalance = floorDiv(max( + account.getBalance() - callValue, 0, isStrict2), sunPerEnergy, isStrict2); long energyFromFeeLimit; long totalBalanceForEnergyFreeze = account.getAllFrozenBalanceForEnergy(); @@ -619,13 +625,14 @@ private long getAccountEnergyLimitWithFloatRatio(AccountCapsule account, long fe .multiply(BigInteger.valueOf(feeLimit)) .divide(BigInteger.valueOf(totalBalanceForEnergyFreeze)).longValueExact(); } else { - energyFromFeeLimit = Math - .addExact(leftEnergyFromFreeze, - (feeLimit - leftBalanceForEnergyFreeze) / sunPerEnergy); + energyFromFeeLimit = addExact( + leftEnergyFromFreeze, (feeLimit - leftBalanceForEnergyFreeze) / sunPerEnergy, + VMConfig.allowStrictMath2()); } } - return min(Math.addExact(leftEnergyFromFreeze, energyFromBalance), energyFromFeeLimit); + return min(addExact(leftEnergyFromFreeze, energyFromBalance, + VMConfig.allowStrictMath2()), energyFromFeeLimit, VMConfig.allowStrictMath2()); } public long getTotalEnergyLimit(AccountCapsule creator, AccountCapsule caller, @@ -700,7 +707,8 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu long creatorEnergyLimit = 0; ContractCapsule contractCapsule = rootRepository .getContract(contract.getContractAddress().toByteArray()); - long consumeUserResourcePercent = contractCapsule.getConsumeUserResourcePercent(); + long consumeUserResourcePercent = contractCapsule.getConsumeUserResourcePercent( + VMConfig.allowStrictMath2()); long originEnergyLimit = contractCapsule.getOriginEnergyLimit(); if (originEnergyLimit < 0) { @@ -715,7 +723,8 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu } } if (consumeUserResourcePercent <= 0) { - creatorEnergyLimit = min(originEnergyLeft, originEnergyLimit); + creatorEnergyLimit = min(originEnergyLeft, originEnergyLimit, + VMConfig.allowStrictMath2()); } else { if (consumeUserResourcePercent < VMConstant.ONE_HUNDRED) { // creatorEnergyLimit = @@ -726,8 +735,8 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu BigInteger.valueOf(callerEnergyLimit) .multiply(BigInteger.valueOf(VMConstant.ONE_HUNDRED - consumeUserResourcePercent)) .divide(BigInteger.valueOf(consumeUserResourcePercent)).longValueExact(), - min(originEnergyLeft, originEnergyLimit) - ); + min(originEnergyLeft, originEnergyLimit, VMConfig.allowStrictMath2()), + VMConfig.allowStrictMath2()); } } if (VMConfig.allowTvmFreezeV2()) { @@ -748,7 +757,8 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu receipt.setOriginEnergyMergedWindowSize(creator.getWindowSize(ENERGY)); rootRepository.updateAccount(creator.createDbKey(), creator); } - return Math.addExact(callerEnergyLimit, creatorEnergyLimit); + return addExact(callerEnergyLimit, creatorEnergyLimit, + VMConfig.allowStrictMath2()); } private long getTotalEnergyLimitWithFloatRatio(AccountCapsule creator, AccountCapsule caller, @@ -764,13 +774,17 @@ private long getTotalEnergyLimitWithFloatRatio(AccountCapsule creator, AccountCa ContractCapsule contractCapsule = rootRepository .getContract(contract.getContractAddress().toByteArray()); - long consumeUserResourcePercent = contractCapsule.getConsumeUserResourcePercent(); + long consumeUserResourcePercent = contractCapsule.getConsumeUserResourcePercent( + VMConfig.allowStrictMath2()); if (creatorEnergyLimit * consumeUserResourcePercent > (VMConstant.ONE_HUNDRED - consumeUserResourcePercent) * callerEnergyLimit) { - return Math.floorDiv(callerEnergyLimit * VMConstant.ONE_HUNDRED, consumeUserResourcePercent); + return floorDiv( + callerEnergyLimit * VMConstant.ONE_HUNDRED, consumeUserResourcePercent, + VMConfig.allowStrictMath2()); } else { - return Math.addExact(callerEnergyLimit, creatorEnergyLimit); + return addExact(callerEnergyLimit, creatorEnergyLimit, + VMConfig.allowStrictMath2()); } } diff --git a/actuator/src/main/java/org/tron/core/actuator/WitnessCreateActuator.java b/actuator/src/main/java/org/tron/core/actuator/WitnessCreateActuator.java index ee223a32ffa..fc908a1713f 100755 --- a/actuator/src/main/java/org/tron/core/actuator/WitnessCreateActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/WitnessCreateActuator.java @@ -6,7 +6,6 @@ import com.google.protobuf.InvalidProtocolBufferException; import java.util.Objects; import lombok.extern.slf4j.Slf4j; -import org.tron.common.utils.Commons; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; import org.tron.core.capsule.AccountCapsule; @@ -140,12 +139,11 @@ private void createWitness(final WitnessCreateContract witnessCreateContract) } accountStore.put(accountCapsule.createDbKey(), accountCapsule); long cost = dynamicStore.getAccountUpgradeCost(); - Commons - .adjustBalance(accountStore, witnessCreateContract.getOwnerAddress().toByteArray(), -cost); + adjustBalance(accountStore, witnessCreateContract.getOwnerAddress().toByteArray(), -cost); if (dynamicStore.supportBlackHoleOptimization()) { dynamicStore.burnTrx(cost); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole(), +cost); + adjustBalance(accountStore, accountStore.getBlackhole(), +cost); } dynamicStore.addTotalCreateWitnessCost(cost); } diff --git a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java index 7044564b1e1..a34afa9d32e 100644 --- a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java @@ -16,6 +16,7 @@ package org.tron.core.utils; import static org.tron.common.crypto.Hash.sha3omit12; +import static org.tron.common.math.Maths.max; import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_COST_BASE_SIZE; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; @@ -270,7 +271,7 @@ public static long estimateConsumeBandWidthSize(DynamicPropertiesStore dps, long DelegateResourceContract.Builder builder2 = DelegateResourceContract.newBuilder() .setBalance(TRX_PRECISION); long builder2Size = builder2.build().getSerializedSize(); - long addSize = Math.max(builderSize - builder2Size, 0L); + long addSize = max(builderSize - builder2Size, 0L, dps.allowStrictMath2()); return DELEGATE_COST_BASE_SIZE + addSize; } diff --git a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java index 5c78fb89ffb..74dbaa741c3 100644 --- a/actuator/src/main/java/org/tron/core/vm/EnergyCost.java +++ b/actuator/src/main/java/org/tron/core/vm/EnergyCost.java @@ -1,5 +1,7 @@ package org.tron.core.vm; +import static org.tron.common.math.Maths.max; + import java.math.BigInteger; import org.tron.common.runtime.vm.DataWord; import org.tron.core.vm.config.VMConfig; @@ -248,7 +250,7 @@ public static long getMCopyCost(Program program) { int dstOffset = stack.peek().intValue(); int srcOffset = stack.get(stack.size() - 2).intValue(); - DataWord maxOffset = new DataWord(Math.max(dstOffset, srcOffset)); + DataWord maxOffset = new DataWord(max(dstOffset, srcOffset, VMConfig.allowStrictMath2())); return VERY_LOW_TIER + calcMemEnergy(oldMemSize, memNeeded(maxOffset, stack.get(stack.size() - 3)), stack.get(stack.size() - 3).longValueSafe(), Op.MCOPY); 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 79d08af1aad..53e2cba90d4 100644 --- a/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java +++ b/actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java @@ -1,6 +1,8 @@ package org.tron.core.vm; import static java.util.Arrays.copyOfRange; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.min; import static org.tron.common.runtime.vm.DataWord.WORD_SIZE; import static org.tron.common.utils.BIUtil.addSafely; import static org.tron.common.utils.BIUtil.isLessThan; @@ -624,14 +626,17 @@ public long getEnergyForData(byte[] data) { int expLen = parseLen(data, 1); int modLen = parseLen(data, 2); - byte[] expHighBytes = parseBytes(data, addSafely(ARGS_OFFSET, baseLen), Math.min(expLen, 32)); + boolean allowStrictMath2 = VMConfig.allowStrictMath2(); - long multComplexity = getMultComplexity(Math.max(baseLen, modLen)); + byte[] expHighBytes = parseBytes(data, addSafely(ARGS_OFFSET, baseLen), min(expLen, 32, + allowStrictMath2)); + + long multComplexity = getMultComplexity(max(baseLen, modLen, allowStrictMath2)); long adjExpLen = getAdjustedExponentLength(expHighBytes, expLen); // use big numbers to stay safe in case of overflow BigInteger energy = BigInteger.valueOf(multComplexity) - .multiply(BigInteger.valueOf(Math.max(adjExpLen, 1))) + .multiply(BigInteger.valueOf(max(adjExpLen, 1, allowStrictMath2))) .divide(GQUAD_DIVISOR); return isLessThan(energy, BigInteger.valueOf(Long.MAX_VALUE)) ? energy.longValueExact() diff --git a/actuator/src/main/java/org/tron/core/vm/VMUtils.java b/actuator/src/main/java/org/tron/core/vm/VMUtils.java index 1df0e0e22f1..090c4c54898 100644 --- a/actuator/src/main/java/org/tron/core/vm/VMUtils.java +++ b/actuator/src/main/java/org/tron/core/vm/VMUtils.java @@ -2,6 +2,7 @@ import static java.lang.String.format; import static org.apache.commons.codec.binary.Base64.encodeBase64String; +import static org.tron.common.math.Maths.addExact; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -169,7 +170,7 @@ public static boolean validateForSmartContract(Repository deposit, byte[] ownerA "Validate InternalTransfer error, balance is not sufficient."); } - Math.addExact(toAccount.getBalance(), amount); + addExact(toAccount.getBalance(), amount, VMConfig.allowStrictMath2()); } catch (ArithmeticException e) { logger.debug(e.getMessage(), e); throw new ContractValidateException(e.getMessage()); @@ -230,7 +231,8 @@ public static boolean validateForSmartContract(Repository deposit, byte[] ownerA ByteArray.toStr(tokenIdWithoutLeadingZero)); if (assetBalance != null) { try { - assetBalance = Math.addExact(assetBalance, amount); //check if overflow + addExact(assetBalance, amount, + VMConfig.allowStrictMath2()); //check if overflow } catch (Exception e) { logger.debug(e.getMessage(), e); throw new ContractValidateException(e.getMessage()); 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 5c4acb31bae..508bedc34dc 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 @@ -42,6 +42,7 @@ public static void load(StoreFactory storeFactory) { VMConfig.initAllowEnergyAdjustment(ds.getAllowEnergyAdjustment()); VMConfig.initAllowStrictMath(ds.getAllowStrictMath()); VMConfig.initAllowTvmCancun(ds.getAllowTvmCancun()); + VMConfig.initAllowStrictMath2(ds.getConsensusLogicOptimization()); } } } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java index bb0d4e8297c..164f9711a20 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/DelegateResourceProcessor.java @@ -54,6 +54,7 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra throw new ContractValidateException("delegateBalance must be greater than or equal to 1 TRX"); } + boolean allowStrictMath2 = dynamicStore.allowStrictMath2(); switch (param.getResourceType()) { case BANDWIDTH: { BandwidthProcessor processor = new BandwidthProcessor(ChainBaseManager.getInstance()); @@ -62,7 +63,7 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra long netUsage = (long) (ownerCapsule.getNetUsage() * TRX_PRECISION * ((double) (repo.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); - long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage); + long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage, allowStrictMath2); if (ownerCapsule.getFrozenV2BalanceForBandwidth() - v2NetUsage < delegateBalance) { throw new ContractValidateException( @@ -78,7 +79,7 @@ public void validate(DelegateResourceParam param, Repository repo) throws Contra long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) (repo.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); - long v2EnergyUsage = getV2EnergyUsage(ownerCapsule, energyUsage); + long v2EnergyUsage = getV2EnergyUsage(ownerCapsule, energyUsage, allowStrictMath2); if (ownerCapsule.getFrozenV2BalanceForEnergy() - v2EnergyUsage < delegateBalance) { throw new ContractValidateException( diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java index d521e596e3e..fc95f23cc03 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnDelegateResourceProcessor.java @@ -1,5 +1,6 @@ package org.tron.core.vm.nativecontract; +import static org.tron.common.math.Maths.min; import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; @@ -21,6 +22,7 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.store.DelegatedResourceAccountIndexStore; import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.nativecontract.param.UnDelegateResourceParam; import org.tron.core.vm.repository.Repository; @@ -115,7 +117,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { * dynamicStore.getTotalNetLimit() / repo.getTotalNetWeight()); transferUsage = (long) (receiverCapsule.getNetUsage() * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForBandwidth())); - transferUsage = Math.min(unDelegateMaxUsage, transferUsage); + transferUsage = min(unDelegateMaxUsage, transferUsage, VMConfig.allowStrictMath2()); receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForBandwidth(-unDelegateBalance); } @@ -139,7 +141,7 @@ public void execute(UnDelegateResourceParam param, Repository repo) { * dynamicStore.getTotalEnergyCurrentLimit() / repo.getTotalEnergyWeight()); transferUsage = (long) (receiverCapsule.getEnergyUsage() * ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForEnergy())); - transferUsage = Math.min(unDelegateMaxUsage, transferUsage); + transferUsage = min(unDelegateMaxUsage, transferUsage, VMConfig.allowStrictMath2()); receiverCapsule.addAcquiredDelegatedFrozenV2BalanceForEnergy(-unDelegateBalance); } diff --git a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceProcessor.java b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceProcessor.java index 211784d279b..2167635a28f 100644 --- a/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceProcessor.java +++ b/actuator/src/main/java/org/tron/core/vm/nativecontract/UnfreezeBalanceProcessor.java @@ -136,10 +136,12 @@ public long execute(UnfreezeBalanceParam param, Repository repo) { if (receiverCapsule != null) { switch (param.getResourceType()) { case BANDWIDTH: - receiverCapsule.safeAddAcquiredDelegatedFrozenBalanceForBandwidth(-unfreezeBalance); + receiverCapsule.safeAddAcquiredDelegatedFrozenBalanceForBandwidth(-unfreezeBalance, + VMConfig.allowStrictMath2()); break; case ENERGY: - receiverCapsule.safeAddAcquiredDelegatedFrozenBalanceForEnergy(-unfreezeBalance); + receiverCapsule.safeAddAcquiredDelegatedFrozenBalanceForEnergy(-unfreezeBalance, + VMConfig.allowStrictMath2()); break; default: //this should never happen diff --git a/actuator/src/main/java/org/tron/core/vm/program/Memory.java b/actuator/src/main/java/org/tron/core/vm/program/Memory.java index 8f263ca7344..70e4005a54a 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Memory.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Memory.java @@ -1,14 +1,16 @@ package org.tron.core.vm.program; -import static java.lang.Math.ceil; -import static java.lang.Math.min; import static java.lang.String.format; +import static org.tron.common.math.Maths.addExact; +import static org.tron.common.math.Maths.ceil; +import static org.tron.common.math.Maths.min; import static org.tron.common.utils.ByteUtil.EMPTY_BYTE_ARRAY; import static org.tron.common.utils.ByteUtil.oneByteToHexString; import java.util.LinkedList; import java.util.List; import org.tron.common.runtime.vm.DataWord; +import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.program.listener.ProgramListener; import org.tron.core.vm.program.listener.ProgramListenerAware; @@ -103,17 +105,17 @@ public void extend(int address, int size) { if (size <= 0) { return; } - - final int newSize = Math.addExact(address, size); + boolean allowStrictMath2 = VMConfig.allowStrictMath2(); + final int newSize = addExact(address, size, allowStrictMath2); int toAllocate = newSize - internalSize(); if (toAllocate > 0) { - addChunks((int) ceil((double) toAllocate / CHUNK_SIZE)); + addChunks((int) ceil((double) toAllocate / CHUNK_SIZE, allowStrictMath2)); } toAllocate = newSize - softSize; if (toAllocate > 0) { - toAllocate = (int) ceil((double) toAllocate / WORD_SIZE) * WORD_SIZE; - softSize = Math.addExact(softSize, toAllocate); + toAllocate = (int) ceil((double) toAllocate / WORD_SIZE, allowStrictMath2) * WORD_SIZE; + softSize = addExact(softSize, toAllocate, allowStrictMath2); if (programListener != null) { programListener.onMemoryExtend(toAllocate); @@ -192,7 +194,7 @@ public void copy(int destPos, int srcPos, int size) { private int captureMax(int chunkIndex, int chunkOffset, int size, byte[] src, int srcPos) { byte[] chunk = chunks.get(chunkIndex); - int toCapture = min(size, chunk.length - chunkOffset); + int toCapture = min(size, chunk.length - chunkOffset, VMConfig.allowStrictMath2()); System.arraycopy(src, srcPos, chunk, chunkOffset, toCapture); return toCapture; @@ -201,7 +203,7 @@ private int captureMax(int chunkIndex, int chunkOffset, int size, byte[] src, in private int grabMax(int chunkIndex, int chunkOffset, int size, byte[] dest, int destPos) { byte[] chunk = chunks.get(chunkIndex); - int toGrab = min(size, chunk.length - chunkOffset); + int toGrab = min(size, chunk.length - chunkOffset, VMConfig.allowStrictMath2()); System.arraycopy(chunk, chunkOffset, dest, destPos, toGrab); 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 9dda3ed6b7f..28e501feb78 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 @@ -1,12 +1,15 @@ package org.tron.core.vm.program; -import static java.lang.StrictMath.min; import static java.lang.String.format; import static org.apache.commons.lang3.ArrayUtils.EMPTY_BYTE_ARRAY; import static org.apache.commons.lang3.ArrayUtils.getLength; import static org.apache.commons.lang3.ArrayUtils.isEmpty; import static org.apache.commons.lang3.ArrayUtils.isNotEmpty; import static org.apache.commons.lang3.ArrayUtils.nullToEmpty; +import static org.tron.common.math.Maths.addExact; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.min; +import static org.tron.common.math.Maths.multiplyExact; import static org.tron.common.utils.ByteUtil.stripLeadingZeroes; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; @@ -159,11 +162,13 @@ public Program(byte[] ops, byte[] codeAddress, ProgramInvoke programInvoke, this.nonce = internalTransaction.getNonce(); } + @SuppressWarnings("unused") static String formatBinData(byte[] binData, int startPC) { StringBuilder ret = new StringBuilder(); for (int i = 0; i < binData.length; i += 16) { ret.append(Utils.align("" + Integer.toHexString(startPC + (i)) + ":", ' ', 8, false)); - ret.append(Hex.toHexString(binData, i, min(16, binData.length - i))).append('\n'); + ret.append(Hex.toHexString(binData, i, min(16, binData.length - i, + VMConfig.allowStrictMath2()))).append('\n'); } return ret.toString(); } @@ -633,7 +638,7 @@ private void withdrawRewardAndCancelVote(byte[] owner, Repository repo) { long balance = ownerCapsule.getBalance(); long allowance = ownerCapsule.getAllowance(); ownerCapsule.setInstance(ownerCapsule.getInstance().toBuilder() - .setBalance(Math.addExact(balance, allowance)) + .setBalance(addExact(balance, allowance, VMConfig.allowStrictMath2())) .setAllowance(0) .setLatestWithdrawTime(getTimestamp().longValue() * 1000) .build()); @@ -1231,7 +1236,8 @@ public DataWord getContractAddress() { public DataWord getBlockHash(int index) { if (index < this.getNumber().longValue() - && index >= Math.max(256, this.getNumber().longValue()) - 256) { + && index >= max(256, this.getNumber().longValue(), + VMConfig.allowStrictMath2()) - 256) { BlockCapsule blockCapsule = contractState.getBlockByNum(index); @@ -2155,11 +2161,13 @@ public boolean voteWitness(int witnessArrayOffset, int witnessArrayLength, try { VoteWitnessParam param = new VoteWitnessParam(); param.setVoterAddress(owner); - - byte[] witnessArrayData = memoryChunk(Math.addExact(witnessArrayOffset, DataWord.WORD_SIZE), - Math.multiplyExact(witnessArrayLength, DataWord.WORD_SIZE)); - byte[] amountArrayData = memoryChunk(Math.addExact(amountArrayOffset, DataWord.WORD_SIZE), - Math.multiplyExact(amountArrayLength, DataWord.WORD_SIZE)); + boolean allowStrictMath2 = VMConfig.allowStrictMath2(); + byte[] witnessArrayData = memoryChunk( + addExact(witnessArrayOffset, DataWord.WORD_SIZE, allowStrictMath2), + multiplyExact(witnessArrayLength, DataWord.WORD_SIZE, allowStrictMath2)); + byte[] amountArrayData = memoryChunk( + addExact(amountArrayOffset, DataWord.WORD_SIZE, allowStrictMath2), + multiplyExact(amountArrayLength, DataWord.WORD_SIZE, allowStrictMath2)); for (int i = 0; i < witnessArrayLength; i++) { DataWord witness = new DataWord(Arrays.copyOfRange(witnessArrayData, @@ -2235,7 +2243,8 @@ public long updateContextContractFactor() { VMConfig.getDynamicEnergyThreshold(), VMConfig.getDynamicEnergyIncreaseFactor(), VMConfig.getDynamicEnergyMaxFactor(), - VMConfig.allowStrictMath())) { + VMConfig.allowStrictMath(), + VMConfig.allowStrictMath2())) { contractState.updateContractState(getContextAddress(), contractStateCapsule ); } diff --git a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java index 7fcfbe8ef78..321efb729b9 100644 --- a/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java +++ b/actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java @@ -1,6 +1,8 @@ package org.tron.core.vm.repository; -import static java.lang.Long.max; +import static org.tron.common.math.Maths.addExact; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.round; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; @@ -187,7 +189,7 @@ public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) { long newEnergyUsage = recover(energyUsage, latestConsumeTime, now, windowSize); - return max(energyLimit - newEnergyUsage, 0); // us + return max(energyLimit - newEnergyUsage, 0, VMConfig.allowStrictMath2()); // us } @Override @@ -709,7 +711,7 @@ public long addBalance(byte[] address, long value) { StringUtil.createReadableString(accountCapsule.createDbKey()) + " insufficient balance"); } - accountCapsule.setBalance(Math.addExact(balance, value)); + accountCapsule.setBalance(addExact(balance, value, VMConfig.allowStrictMath2())); Key key = Key.create(address); accountCache.put(key, Value.create(accountCapsule, accountCache.get(key).getType().addType(Type.DIRTY))); @@ -875,7 +877,7 @@ private long increase(long lastUsage, long usage, long lastTime, long now, long if (lastTime + windowSize > now) { long delta = now - lastTime; double decay = (windowSize - delta) / (double) windowSize; - averageLastUsage = Math.round(averageLastUsage * decay); + averageLastUsage = round(averageLastUsage * decay, VMConfig.allowStrictMath2()); } else { averageLastUsage = 0; } diff --git a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java index 7bc760f9edf..753313afe43 100644 --- a/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java +++ b/actuator/src/main/java/org/tron/core/vm/utils/FreezeV2Util.java @@ -1,5 +1,8 @@ package org.tron.core.vm.utils; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.min; + import java.util.List; import java.util.stream.Collectors; @@ -132,7 +135,8 @@ public static long queryAvailableUnfreezeV2Size(byte[] address, Repository repos long now = repository.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp(); int unfreezingV2Count = accountCapsule.getUnfreezingV2Count(now); - return Long.max(UnfreezeBalanceV2Actuator.getUNFREEZE_MAX_TIMES() - unfreezingV2Count, 0L); + return max(UnfreezeBalanceV2Actuator.getUNFREEZE_MAX_TIMES() - unfreezingV2Count, 0L, + VMConfig.allowStrictMath2()); } public static long queryDelegatableResource(byte[] address, long type, Repository repository) { @@ -140,6 +144,7 @@ public static long queryDelegatableResource(byte[] address, long type, Repositor return 0L; } + boolean allowStrictMath2 = VMConfig.allowStrictMath2(); AccountCapsule accountCapsule = repository.getAccount(address); if (accountCapsule == null) { return 0L; @@ -161,8 +166,8 @@ public static long queryDelegatableResource(byte[] address, long type, Repositor return frozenV2Resource; } - long v2NetUsage = getV2NetUsage(accountCapsule, usage); - return Math.max(0L, frozenV2Resource - v2NetUsage); + long v2NetUsage = getV2NetUsage(accountCapsule, usage, allowStrictMath2); + return max(0L, frozenV2Resource - v2NetUsage, allowStrictMath2); } if (type == 1) { @@ -181,8 +186,8 @@ public static long queryDelegatableResource(byte[] address, long type, Repositor return frozenV2Resource; } - long v2EnergyUsage = getV2EnergyUsage(accountCapsule, usage); - return Math.max(0L, frozenV2Resource - v2EnergyUsage); + long v2EnergyUsage = getV2EnergyUsage(accountCapsule, usage, allowStrictMath2); + return max(0L, frozenV2Resource - v2EnergyUsage, allowStrictMath2); } return 0L; @@ -218,7 +223,7 @@ public static Triple checkUndelegateResource(byte[] address, l return Triple.of(0L, 0L, 0L); } - amount = Math.min(amount, resourceLimit); + amount = min(amount, resourceLimit, VMConfig.allowStrictMath2()); if (resourceLimit <= usagePair.getLeft()) { return Triple.of(0L, amount, usagePair.getRight()); } @@ -238,20 +243,22 @@ private static List getTotalWithdrawList(List{@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/common/utils/Commons.java b/chainbase/src/main/java/org/tron/common/utils/Commons.java index 55542d494b4..6bcff7ec6e9 100644 --- a/chainbase/src/main/java/org/tron/common/utils/Commons.java +++ b/chainbase/src/main/java/org/tron/common/utils/Commons.java @@ -1,5 +1,8 @@ package org.tron.common.utils; +import static org.tron.common.math.Maths.addExact; +import static org.tron.common.math.Maths.subtractExact; + import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.tron.common.parameter.CommonParameter; @@ -55,16 +58,18 @@ public static byte[] decodeFromBase58Check(String addressBase58) { return address; } - public static void adjustBalance(AccountStore accountStore, byte[] accountAddress, long amount) + public static void adjustBalance(AccountStore accountStore, byte[] accountAddress, long amount, + boolean useStrict) throws BalanceInsufficientException { AccountCapsule account = accountStore.getUnchecked(accountAddress); - adjustBalance(accountStore, account, amount); + adjustBalance(accountStore, account, amount, useStrict); } /** * judge balance. */ - public static void adjustBalance(AccountStore accountStore, AccountCapsule account, long amount) + public static void adjustBalance(AccountStore accountStore, AccountCapsule account, long amount, + boolean useStrict) throws BalanceInsufficientException { long balance = account.getBalance(); @@ -77,7 +82,7 @@ public static void adjustBalance(AccountStore accountStore, AccountCapsule accou String.format("%s insufficient balance, balance: %d, amount: %d", StringUtil.createReadableString(account.createDbKey()), balance, -amount)); } - account.setBalance(Math.addExact(balance, amount)); + account.setBalance(addExact(balance, amount, useStrict)); accountStore.put(account.getAddress().toByteArray(), account); } @@ -137,8 +142,9 @@ public static void adjustAssetBalanceV2(AccountCapsule account, String AssetID, public static void adjustTotalShieldedPoolValue(long valueBalance, DynamicPropertiesStore dynamicPropertiesStore) throws BalanceInsufficientException { - long totalShieldedPoolValue = Math - .subtractExact(dynamicPropertiesStore.getTotalShieldedPoolValue(), valueBalance); + long totalShieldedPoolValue = subtractExact( + dynamicPropertiesStore.getTotalShieldedPoolValue(), valueBalance, + dynamicPropertiesStore.allowStrictMath2()); if (totalShieldedPoolValue < 0) { throw new BalanceInsufficientException(String.format( "total shielded pool value can not below 0, actual: %d", totalShieldedPoolValue)); diff --git a/chainbase/src/main/java/org/tron/common/utils/ForkController.java b/chainbase/src/main/java/org/tron/common/utils/ForkController.java index 7cbac28e781..0a782b31e5b 100644 --- a/chainbase/src/main/java/org/tron/common/utils/ForkController.java +++ b/chainbase/src/main/java/org/tron/common/utils/ForkController.java @@ -1,5 +1,6 @@ package org.tron.common.utils; +import static org.tron.common.math.Maths.ceil; import static org.tron.common.utils.StringUtil.encode58Check; import com.google.common.collect.Maps; @@ -98,8 +99,8 @@ private boolean passNew(int version) { ++count; } } - return count >= Math - .ceil((double) versionEnum.getHardForkRate() * stats.length / 100); + return count >= ceil((double) versionEnum.getHardForkRate() * stats.length / 100, + manager.getDynamicPropertiesStore().allowStrictMath2()); } diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index b60fed63cda..26ee5bab34b 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -15,9 +15,23 @@ package org.tron.core.capsule; +import static org.tron.common.math.Maths.addExact; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.subtractExact; +import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; +import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_MS; +import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; +import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER; + import com.google.common.collect.Maps; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; +import java.util.List; +import java.util.Map; +import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.tron.common.utils.ByteArray; @@ -27,8 +41,8 @@ import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.Account.AccountResource; import org.tron.protos.Protocol.Account.Builder; -import org.tron.protos.Protocol.Account.Frozen; import org.tron.protos.Protocol.Account.FreezeV2; +import org.tron.protos.Protocol.Account.Frozen; import org.tron.protos.Protocol.Account.UnFreezeV2; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Key; @@ -38,19 +52,6 @@ import org.tron.protos.contract.AccountContract.AccountCreateContract; import org.tron.protos.contract.AccountContract.AccountUpdateContract; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import static java.lang.Math.ceil; -import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; -import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_MS; -import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_PRECISION; -import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; -import static org.tron.protos.contract.Common.ResourceCode.ENERGY; -import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER; -import static org.tron.protos.contract.Common.ResourceCode; - @Slf4j(topic = "capsule") public class AccountCapsule implements ProtoCapsule, Comparable { @@ -401,15 +402,18 @@ public void addAcquiredDelegatedFrozenV2BalanceForBandwidth(long balance) { this.account.getAcquiredDelegatedFrozenV2BalanceForBandwidth() + balance).build(); } - public void safeAddAcquiredDelegatedFrozenBalanceForBandwidth(long balance) { + public void safeAddAcquiredDelegatedFrozenBalanceForBandwidth(long balance, boolean useStrict) { this.account = this.account.toBuilder().setAcquiredDelegatedFrozenBalanceForBandwidth( - Math.max(0, this.account.getAcquiredDelegatedFrozenBalanceForBandwidth() + balance)) + max(0, this.account.getAcquiredDelegatedFrozenBalanceForBandwidth() + balance, + useStrict)) .build(); } - public void safeAddAcquiredDelegatedFrozenV2BalanceForBandwidth(long balance) { + @SuppressWarnings("unused") + public void safeAddAcquiredDelegatedFrozenV2BalanceForBandwidth(long balance, boolean useStrict) { this.account = this.account.toBuilder().setAcquiredDelegatedFrozenV2BalanceForBandwidth( - Math.max(0, this.account.getAcquiredDelegatedFrozenV2BalanceForBandwidth() + balance)) + max(0, this.account.getAcquiredDelegatedFrozenV2BalanceForBandwidth() + balance, + useStrict)) .build(); } @@ -496,10 +500,11 @@ public void addAcquiredDelegatedFrozenV2BalanceForEnergy(long balance) { this.account = this.account.toBuilder().setAccountResource(newAccountResource).build(); } - public void safeAddAcquiredDelegatedFrozenBalanceForEnergy(long balance) { + public void safeAddAcquiredDelegatedFrozenBalanceForEnergy(long balance, boolean useStrict) { AccountResource newAccountResource = getAccountResource().toBuilder() .setAcquiredDelegatedFrozenBalanceForEnergy( - Math.max(0, getAccountResource().getAcquiredDelegatedFrozenBalanceForEnergy() + balance)) + max(0, getAccountResource().getAcquiredDelegatedFrozenBalanceForEnergy() + balance, + useStrict)) .build(); this.account = this.account.toBuilder() @@ -507,10 +512,11 @@ public void safeAddAcquiredDelegatedFrozenBalanceForEnergy(long balance) { .build(); } - public void safeAddAcquiredDelegatedFrozenV2BalanceForEnergy(long balance) { + @SuppressWarnings("unused") + public void safeAddAcquiredDelegatedFrozenV2BalanceForEnergy(long balance, boolean useStrict) { AccountResource newAccountResource = getAccountResource().toBuilder() - .setAcquiredDelegatedFrozenV2BalanceForEnergy(Math.max(0, getAccountResource() - .getAcquiredDelegatedFrozenV2BalanceForEnergy() + balance)).build(); + .setAcquiredDelegatedFrozenV2BalanceForEnergy(max(0, getAccountResource() + .getAcquiredDelegatedFrozenV2BalanceForEnergy() + balance, useStrict)).build(); this.account = this.account.toBuilder().setAccountResource(newAccountResource).build(); } @@ -711,14 +717,15 @@ public boolean assetBalanceEnoughV2(byte[] key, long amount, return amount > 0 && null != currentAmount && amount <= currentAmount; } - public boolean addAssetAmount(byte[] key, long amount) { + public boolean addAssetAmount(byte[] key, long amount, boolean useStrict) { Map assetMap = this.account.getAssetMap(); String nameKey = ByteArray.toStr(key); Long currentAmount = assetMap.get(nameKey); if (currentAmount == null) { currentAmount = 0L; } - this.account = this.account.toBuilder().putAsset(nameKey, Math.addExact(currentAmount, amount)) + this.account = this.account.toBuilder().putAsset(nameKey, + addExact(currentAmount, amount, useStrict)) .build(); return true; } @@ -726,6 +733,7 @@ public boolean addAssetAmount(byte[] key, long amount) { public boolean addAssetAmountV2(byte[] key, long amount, DynamicPropertiesStore dynamicPropertiesStore, AssetIssueStore assetIssueStore) { importAsset(key); + boolean useStrict2 = dynamicPropertiesStore.allowStrictMath2(); //key is token name if (dynamicPropertiesStore.getAllowSameTokenName() == 0) { Map assetMap = this.account.getAssetMap(); @@ -737,8 +745,8 @@ public boolean addAssetAmountV2(byte[] key, long amount, currentAmount = 0L; } this.account = this.account.toBuilder() - .putAsset(nameKey, Math.addExact(currentAmount, amount)) - .putAssetV2(tokenID, Math.addExact(currentAmount, amount)) + .putAsset(nameKey, addExact(currentAmount, amount, useStrict2)) + .putAssetV2(tokenID, addExact(currentAmount, amount, useStrict2)) .build(); } //key is token id @@ -750,19 +758,19 @@ public boolean addAssetAmountV2(byte[] key, long amount, currentAmount = 0L; } this.account = this.account.toBuilder() - .putAssetV2(tokenIDStr, Math.addExact(currentAmount, amount)) + .putAssetV2(tokenIDStr, addExact(currentAmount, amount, useStrict2)) .build(); } return true; } - public boolean reduceAssetAmount(byte[] key, long amount) { + public boolean reduceAssetAmount(byte[] key, long amount, boolean useStrict2) { Map assetMap = this.account.getAssetMap(); String nameKey = ByteArray.toStr(key); Long currentAmount = assetMap.get(nameKey); if (amount > 0 && null != currentAmount && amount <= currentAmount) { this.account = this.account.toBuilder() - .putAsset(nameKey, Math.subtractExact(currentAmount, amount)).build(); + .putAsset(nameKey, subtractExact(currentAmount, amount, useStrict2)).build(); return true; } @@ -773,6 +781,7 @@ public boolean reduceAssetAmountV2(byte[] key, long amount, DynamicPropertiesStore dynamicPropertiesStore, AssetIssueStore assetIssueStore) { importAsset(key); //key is token name + boolean useStrict2 = dynamicPropertiesStore.allowStrictMath2(); if (dynamicPropertiesStore.getAllowSameTokenName() == 0) { Map assetMap = this.account.getAssetMap(); AssetIssueCapsule assetIssueCapsule = assetIssueStore.get(key); @@ -781,8 +790,8 @@ public boolean reduceAssetAmountV2(byte[] key, long amount, Long currentAmount = assetMap.get(nameKey); if (amount > 0 && null != currentAmount && amount <= currentAmount) { this.account = this.account.toBuilder() - .putAsset(nameKey, Math.subtractExact(currentAmount, amount)) - .putAssetV2(tokenID, Math.subtractExact(currentAmount, amount)) + .putAsset(nameKey, subtractExact(currentAmount, amount, useStrict2)) + .putAssetV2(tokenID, subtractExact(currentAmount, amount, useStrict2)) .build(); return true; } @@ -794,7 +803,7 @@ public boolean reduceAssetAmountV2(byte[] key, long amount, Long currentAmount = assetMapV2.get(tokenID); if (amount > 0 && null != currentAmount && amount <= currentAmount) { this.account = this.account.toBuilder() - .putAssetV2(tokenID, Math.subtractExact(currentAmount, amount)) + .putAssetV2(tokenID, subtractExact(currentAmount, amount, useStrict2)) .build(); return true; } diff --git a/chainbase/src/main/java/org/tron/core/capsule/ContractCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ContractCapsule.java index cb6292ed290..be73a338b90 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ContractCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractCapsule.java @@ -15,8 +15,8 @@ package org.tron.core.capsule; -import static java.lang.Math.max; -import static java.lang.Math.min; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.min; import com.google.protobuf.Any; import com.google.protobuf.ByteString; @@ -109,9 +109,9 @@ public byte[] getOriginAddress() { return this.smartContract.getOriginAddress().toByteArray(); } - public long getConsumeUserResourcePercent() { + public long getConsumeUserResourcePercent(boolean useStrictMath2) { long percent = this.smartContract.getConsumeUserResourcePercent(); - return max(0, min(percent, Constant.ONE_HUNDRED)); + return max(0, min(percent, Constant.ONE_HUNDRED, useStrictMath2), useStrictMath2); } public long getOriginEnergyLimit() { 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 8ebb86ea332..8deeebaa758 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ContractStateCapsule.java @@ -1,11 +1,13 @@ package org.tron.core.capsule; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.min; +import static org.tron.common.math.Maths.pow; import static org.tron.core.Constant.DYNAMIC_ENERGY_DECREASE_DIVISION; import static org.tron.core.Constant.DYNAMIC_ENERGY_FACTOR_DECIMAL; 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; @@ -79,12 +81,14 @@ public boolean catchUpToCycle(DynamicPropertiesStore dps) { dps.getDynamicEnergyThreshold(), dps.getDynamicEnergyIncreaseFactor(), dps.getDynamicEnergyMaxFactor(), - dps.allowStrictMath() + dps.allowStrictMath(), + dps.allowStrictMath2() ); } public boolean catchUpToCycle( - long newCycle, long threshold, long increaseFactor, long maxFactor, boolean useStrictMath + long newCycle, long threshold, long increaseFactor, long maxFactor, + boolean useStrictMath, boolean useStrictMath2 ) { long lastCycle = getUpdateCycle(); @@ -108,9 +112,10 @@ public boolean catchUpToCycle( double increasePercent = 1 + (double) increaseFactor / precisionFactor; this.contractState = ContractState.newBuilder() .setUpdateCycle(lastCycle) - .setEnergyFactor(Math.min( + .setEnergyFactor(min( maxFactor, - (long) ((getEnergyFactor() + precisionFactor) * increasePercent) - precisionFactor)) + (long) ((getEnergyFactor() + precisionFactor) * increasePercent) - precisionFactor, + useStrictMath2)) .build(); } @@ -121,7 +126,7 @@ public boolean catchUpToCycle( } // Calc the decrease percent (decrease factor [75% ~ 100%]) - double decreasePercent = Maths.pow( + double decreasePercent = pow( 1 - (double) increaseFactor / DYNAMIC_ENERGY_DECREASE_DIVISION / precisionFactor, cycleCount, useStrictMath ); @@ -132,9 +137,10 @@ public boolean catchUpToCycle( // That means we merge this special case to normal cases) this.contractState = ContractState.newBuilder() .setUpdateCycle(newCycle) - .setEnergyFactor(Math.max( + .setEnergyFactor(max( 0, - (long) ((getEnergyFactor() + precisionFactor) * decreasePercent) - precisionFactor)) + (long) ((getEnergyFactor() + precisionFactor) * decreasePercent) - precisionFactor, + useStrictMath2)) .build(); return true; diff --git a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java index 7d003b6b0e4..29d80cebe3f 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java @@ -1,5 +1,8 @@ package org.tron.core.capsule; +import static org.tron.common.math.Maths.min; +import static org.tron.common.math.Maths.multiplyExact; + import java.util.Objects; import lombok.Getter; import lombok.Setter; @@ -215,12 +218,13 @@ public void payEnergyBill(DynamicPropertiesStore dynamicPropertiesStore, receipt.getEnergyUsageTotal(), receipt.getResult(), energyProcessor, now); return; } + boolean useStrict2 = dynamicPropertiesStore.allowStrictMath2(); if ((!Objects.isNull(origin)) && caller.getAddress().equals(origin.getAddress())) { payEnergyBill(dynamicPropertiesStore, accountStore, forkController, caller, receipt.getEnergyUsageTotal(), receipt.getResult(), energyProcessor, now); } else { - long originUsage = Math.multiplyExact(receipt.getEnergyUsageTotal(), percent) / 100; + long originUsage = multiplyExact(receipt.getEnergyUsageTotal(), percent, useStrict2) / 100; originUsage = getOriginUsage(dynamicPropertiesStore, origin, originEnergyLimit, energyProcessor, originUsage); @@ -236,17 +240,18 @@ public void payEnergyBill(DynamicPropertiesStore dynamicPropertiesStore, private long getOriginUsage(DynamicPropertiesStore dynamicPropertiesStore, AccountCapsule origin, long originEnergyLimit, EnergyProcessor energyProcessor, long originUsage) { - + boolean useStrict2 = dynamicPropertiesStore.allowStrictMath2(); if (dynamicPropertiesStore.getAllowTvmFreeze() == 1 || dynamicPropertiesStore.supportUnfreezeDelay()) { - return Math.min(originUsage, Math.min(originEnergyLeft, originEnergyLimit)); + return min(originUsage, min(originEnergyLeft, originEnergyLimit, useStrict2), useStrict2); } if (checkForEnergyLimit(dynamicPropertiesStore)) { - return Math.min(originUsage, - Math.min(energyProcessor.getAccountLeftEnergyFromFreeze(origin), originEnergyLimit)); + return min(originUsage, + min(energyProcessor.getAccountLeftEnergyFromFreeze(origin), originEnergyLimit, + useStrict2), useStrict2); } - return Math.min(originUsage, energyProcessor.getAccountLeftEnergyFromFreeze(origin)); + return min(originUsage, energyProcessor.getAccountLeftEnergyFromFreeze(origin), useStrict2); } private void payEnergyBill( @@ -301,7 +306,7 @@ private void payEnergyBill( } else { //send to blackHole Commons.adjustBalance(accountStore, accountStore.getBlackhole(), - energyFee); + energyFee, dynamicPropertiesStore.allowStrictMath2()); } } diff --git a/chainbase/src/main/java/org/tron/core/capsule/utils/MarketUtils.java b/chainbase/src/main/java/org/tron/core/capsule/utils/MarketUtils.java index f345a96df81..fb86cb1f456 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/utils/MarketUtils.java +++ b/chainbase/src/main/java/org/tron/core/capsule/utils/MarketUtils.java @@ -15,6 +15,10 @@ package org.tron.core.capsule.utils; +import static org.tron.common.math.Maths.addExact; +import static org.tron.common.math.Maths.floorDiv; +import static org.tron.common.math.Maths.multiplyExact; + import com.google.protobuf.ByteString; import java.math.BigInteger; import java.util.Arrays; @@ -230,8 +234,8 @@ public static byte[] createPairKey(byte[] sellTokenId, byte[] buyTokenId) { public static int comparePrice(long price1SellQuantity, long price1BuyQuantity, long price2SellQuantity, long price2BuyQuantity) { try { - return Long.compare(Math.multiplyExact(price1BuyQuantity, price2SellQuantity), - Math.multiplyExact(price2BuyQuantity, price1SellQuantity)); + return Long.compare(multiplyExact(price1BuyQuantity, price2SellQuantity, true), + multiplyExact(price2BuyQuantity, price1SellQuantity, true)); } catch (ArithmeticException ex) { // do nothing here, because we will use BigInteger to compute again @@ -246,25 +250,6 @@ public static int comparePrice(long price1SellQuantity, long price1BuyQuantity, .compareTo(price2BuyQuantityBI.multiply(price1SellQuantityBI)); } - /** - * ex. - * for sellToken is A, buyToken is TRX. - * price_A_maker * sellQuantity_maker = Price_TRX * buyQuantity_maker - * ==> price_A_maker = Price_TRX * buyQuantity_maker/sellQuantity_maker - * - * price_A_maker_1 < price_A_maker_2 - * ==> buyQuantity_maker_1/sellQuantity_maker_1 < buyQuantity_maker_2/sellQuantity_maker_2 - * ==> buyQuantity_maker_1*sellQuantity_maker_2 < buyQuantity_maker_2 * sellQuantity_maker_1 - */ - public static int comparePrice(MarketPrice price1, MarketPrice price2) { - return comparePrice(price1.getSellTokenQuantity(), price1.getBuyTokenQuantity(), - price2.getSellTokenQuantity(), price2.getBuyTokenQuantity()); - } - - public static boolean isLowerPrice(MarketPrice price1, MarketPrice price2) { - return comparePrice(price1, price2) == -1; - } - /** * if takerPrice >= makerPrice, return True * note: here are two different token pairs @@ -297,10 +282,10 @@ public static void updateOrderState(MarketOrderCapsule orderCapsule, } } - public static long multiplyAndDivide(long a, long b, long c) { + public static long multiplyAndDivide(long a, long b, long c, boolean useStrictMath2) { try { - long tmp = Math.multiplyExact(a, b); - return Math.floorDiv(tmp, c); + long tmp = multiplyExact(a, b, useStrictMath2); + return floorDiv(tmp, c, useStrictMath2); } catch (ArithmeticException ex) { // do nothing here, because we will use BigInteger to compute again } @@ -320,8 +305,9 @@ public static void returnSellTokenRemain(MarketOrderCapsule orderCapsule, byte[] sellTokenId = orderCapsule.getSellTokenId(); long sellTokenQuantityRemain = orderCapsule.getSellTokenQuantityRemain(); if (Arrays.equals(sellTokenId, "_".getBytes())) { - accountCapsule.setBalance(Math.addExact( - accountCapsule.getBalance(), sellTokenQuantityRemain)); + accountCapsule.setBalance(addExact( + accountCapsule.getBalance(), sellTokenQuantityRemain, + dynamicStore.allowStrictMath2())); } else { accountCapsule .addAssetAmountV2(sellTokenId, sellTokenQuantityRemain, dynamicStore, assetIssueStore); diff --git a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java index 5cd0f796374..ef326977451 100644 --- a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java @@ -1,6 +1,7 @@ package org.tron.core.db; -import static java.lang.Long.max; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.min; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; @@ -78,11 +79,10 @@ public void updateAdaptiveTotalEnergyLimit() { / AdaptiveResourceLimitConstants.EXPAND_RATE_DENOMINATOR; // logger.info(totalEnergyAverageUsage + "<" + targetTotalEnergyLimit + "\n" + result); } - - result = Math.min( - Math.max(result, totalEnergyLimit), - totalEnergyLimit * dynamicPropertiesStore.getAdaptiveResourceLimitMultiplier() - ); + boolean useStrict2 = dynamicPropertiesStore.allowStrictMath2(); + result = min(max(result, totalEnergyLimit, useStrict2), + totalEnergyLimit * dynamicPropertiesStore.getAdaptiveResourceLimitMultiplier(), + useStrict2); dynamicPropertiesStore.saveTotalEnergyCurrentLimit(result); logger.debug("Adjust totalEnergyCurrentLimit, old: {}, new: {}.", @@ -178,7 +178,7 @@ public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) { long newEnergyUsage = recovery(accountCapsule, ENERGY, energyUsage, latestConsumeTime, now); - return max(energyLimit - newEnergyUsage, 0); // us + return max(energyLimit - newEnergyUsage, 0, dynamicPropertiesStore.allowStrictMath2()); // us } private long getHeadSlot() { diff --git a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java index c1875408850..9b446079337 100644 --- a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java @@ -1,5 +1,7 @@ package org.tron.core.db; +import static org.tron.common.math.Maths.min; +import static org.tron.common.math.Maths.round; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_PRECISION; @@ -51,7 +53,8 @@ protected long increase(long lastUsage, long usage, long lastTime, long now, lon if (lastTime + windowSize > now) { long delta = now - lastTime; double decay = (windowSize - delta) / (double) windowSize; - averageLastUsage = Math.round(averageLastUsage * decay); + averageLastUsage = round(averageLastUsage * decay, + dynamicPropertiesStore.allowStrictMath2()); } else { averageLastUsage = 0; } @@ -79,7 +82,8 @@ public long increase(AccountCapsule accountCapsule, ResourceCode resourceCode, if (lastTime + oldWindowSize > now) { long delta = now - lastTime; double decay = (oldWindowSize - delta) / (double) oldWindowSize; - averageLastUsage = Math.round(averageLastUsage * decay); + averageLastUsage = round(averageLastUsage * decay, + dynamicPropertiesStore.allowStrictMath2()); } else { averageLastUsage = 0; } @@ -111,7 +115,8 @@ public long increaseV2(AccountCapsule accountCapsule, ResourceCode resourceCode, if (lastTime + oldWindowSize > now) { long delta = now - lastTime; double decay = (oldWindowSize - delta) / (double) oldWindowSize; - averageLastUsage = Math.round(averageLastUsage * decay); + averageLastUsage = round(averageLastUsage * decay, + dynamicPropertiesStore.allowStrictMath2()); } else { averageLastUsage = 0; } @@ -127,7 +132,8 @@ public long increaseV2(AccountCapsule accountCapsule, ResourceCode resourceCode, long remainWindowSize = oldWindowSizeV2 - (now - lastTime) * WINDOW_SIZE_PRECISION; long newWindowSize = divideCeil( remainUsage * remainWindowSize + usage * this.windowSize * WINDOW_SIZE_PRECISION, newUsage); - newWindowSize = Math.min(newWindowSize, this.windowSize * WINDOW_SIZE_PRECISION); + newWindowSize = min(newWindowSize, this.windowSize * WINDOW_SIZE_PRECISION, + dynamicPropertiesStore.allowStrictMath2()); accountCapsule.setNewWindowSizeV2(resourceCode, newWindowSize); return newUsage; } @@ -189,7 +195,8 @@ public void unDelegateIncreaseV2(AccountCapsule owner, final AccountCapsule rece divideCeil( ownerUsage * remainOwnerWindowSizeV2 + transferUsage * remainReceiverWindowSizeV2, newOwnerUsage); - newOwnerWindowSize = Math.min(newOwnerWindowSize, this.windowSize * WINDOW_SIZE_PRECISION); + newOwnerWindowSize = min(newOwnerWindowSize, this.windowSize * WINDOW_SIZE_PRECISION, + dynamicPropertiesStore.allowStrictMath2()); owner.setNewWindowSizeV2(resourceCode, newOwnerWindowSize); owner.setUsage(resourceCode, newOwnerUsage); owner.setLatestTime(resourceCode, now); @@ -216,13 +223,15 @@ protected boolean consumeFeeForBandwidth(AccountCapsule accountCapsule, long fee try { long latestOperationTime = dynamicPropertiesStore.getLatestBlockHeaderTimestamp(); accountCapsule.setLatestOperationTime(latestOperationTime); - Commons.adjustBalance(accountStore, accountCapsule, -fee); + Commons.adjustBalance(accountStore, accountCapsule, -fee, + dynamicPropertiesStore.allowStrictMath2()); if (dynamicPropertiesStore.supportTransactionFeePool()) { dynamicPropertiesStore.addTransactionFeePool(fee); } else if (dynamicPropertiesStore.supportBlackHoleOptimization()) { dynamicPropertiesStore.burnTrx(fee); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole().createDbKey(), +fee); + Commons.adjustBalance(accountStore, accountStore.getBlackhole().createDbKey(), +fee, + dynamicPropertiesStore.allowStrictMath2()); } return true; @@ -235,11 +244,13 @@ protected boolean consumeFeeForNewAccount(AccountCapsule accountCapsule, long fe try { long latestOperationTime = dynamicPropertiesStore.getLatestBlockHeaderTimestamp(); accountCapsule.setLatestOperationTime(latestOperationTime); - Commons.adjustBalance(accountStore, accountCapsule, -fee); + Commons.adjustBalance(accountStore, accountCapsule, -fee, + dynamicPropertiesStore.allowStrictMath2()); if (dynamicPropertiesStore.supportBlackHoleOptimization()) { dynamicPropertiesStore.burnTrx(fee); } else { - Commons.adjustBalance(accountStore, accountStore.getBlackhole().createDbKey(), +fee); + Commons.adjustBalance(accountStore, accountStore.getBlackhole().createDbKey(), +fee, + dynamicPropertiesStore.allowStrictMath2()); } return true; diff --git a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java index e9c4feb7e18..114197a3407 100644 --- a/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java +++ b/chainbase/src/main/java/org/tron/core/db/TransactionTrace.java @@ -1,5 +1,7 @@ package org.tron.core.db; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.min; import static org.tron.common.runtime.InternalTransaction.TrxType.TRX_CONTRACT_CALL_TYPE; import static org.tron.common.runtime.InternalTransaction.TrxType.TRX_CONTRACT_CREATION_TYPE; import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_PRECISION; @@ -244,9 +246,11 @@ public void pay() throws BalanceInsufficientException { callerAccount = callContract.getOwnerAddress().toByteArray(); originAccount = contractCapsule.getOriginAddress(); - percent = Math - .max(Constant.ONE_HUNDRED - contractCapsule.getConsumeUserResourcePercent(), 0); - percent = Math.min(percent, Constant.ONE_HUNDRED); + boolean useStrictMath2 = dynamicPropertiesStore.allowStrictMath2(); + percent = max(Constant.ONE_HUNDRED - contractCapsule.getConsumeUserResourcePercent( + useStrictMath2), 0, useStrictMath2); + percent = min(percent, Constant.ONE_HUNDRED, + useStrictMath2); originEnergyLimit = contractCapsule.getOriginEnergyLimit(); break; default: @@ -299,7 +303,7 @@ private void resetAccountUsage(AccountCapsule accountCap, // If area merging happened during suicide, use the current window size long newSize = mergedSize == currentSize ? size : currentSize; // Calc new usage by fixed x-axes - long newUsage = Long.max(0, newArea / newSize); + long newUsage = max(0, newArea / newSize, dynamicPropertiesStore.allowStrictMath2()); // Reset account usage and window size accountCap.setEnergyUsage(newUsage); accountCap.setNewWindowSize(ENERGY, newUsage == 0 ? 0L : newSize); @@ -316,7 +320,7 @@ private void resetAccountUsageV2(AccountCapsule accountCap, long newSize = mergedSize == currentSize ? size : currentSize; long newSize2 = mergedSize == currentSize ? size2 : currentSize2; // Calc new usage by fixed x-axes - long newUsage = Long.max(0, newArea / newSize); + long newUsage = max(0, newArea / newSize, dynamicPropertiesStore.allowStrictMath2()); // Reset account usage and window size accountCap.setEnergyUsage(newUsage); accountCap.setNewWindowSizeV2(ENERGY, newUsage == 0 ? 0L : newSize2); diff --git a/chainbase/src/main/java/org/tron/core/service/MortgageService.java b/chainbase/src/main/java/org/tron/core/service/MortgageService.java index 29ea32208eb..233c142f053 100644 --- a/chainbase/src/main/java/org/tron/core/service/MortgageService.java +++ b/chainbase/src/main/java/org/tron/core/service/MortgageService.java @@ -1,5 +1,7 @@ package org.tron.core.service; +import static org.tron.common.math.Maths.min; + import java.math.BigInteger; import java.util.List; import java.util.stream.Collectors; @@ -205,7 +207,8 @@ private long computeReward(long beginCycle, long endCycle, AccountCapsule accoun .map(vote -> new Pair<>(vote.getVoteAddress().toByteArray(), vote.getVoteCount())) .collect(Collectors.toList()); if (beginCycle < newAlgorithmCycle) { - long oldEndCycle = Math.min(endCycle, newAlgorithmCycle); + long oldEndCycle = min(endCycle, newAlgorithmCycle, + dynamicPropertiesStore.allowStrictMath2()); reward = getOldReward(beginCycle, oldEndCycle, srAddresses); beginCycle = oldEndCycle; } diff --git a/chainbase/src/main/java/org/tron/core/store/AssetIssueStore.java b/chainbase/src/main/java/org/tron/core/store/AssetIssueStore.java index d38a5f0677e..4f69a6c3c66 100644 --- a/chainbase/src/main/java/org/tron/core/store/AssetIssueStore.java +++ b/chainbase/src/main/java/org/tron/core/store/AssetIssueStore.java @@ -43,13 +43,6 @@ private List getAssetIssuesPaginated(List return null; } -// return Streams.stream(iterator()) -// .map(Entry::getValue) -// .sorted(Comparator.comparing(a -> a.getName().toStringUtf8(), String::compareTo)) -// .skip(offset) -// .limit(Math.min(limit, ASSET_ISSUE_COUNT_LIMIT_MAX)) -// .collect(Collectors.toList()); - if (assetIssueList.size() <= offset) { return null; } 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 399c3a6b292..8d1fb19ea2b 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -1,5 +1,6 @@ package org.tron.core.store; +import static org.tron.common.math.Maths.max; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; @@ -2245,7 +2246,7 @@ public void addTotalNetWeight(long amount) { long totalNetWeight = getTotalNetWeight(); totalNetWeight += amount; if (allowNewReward()) { - totalNetWeight = Math.max(0, totalNetWeight); + totalNetWeight = max(0, totalNetWeight, allowStrictMath2()); } saveTotalNetWeight(totalNetWeight); } @@ -2258,7 +2259,7 @@ public void addTotalEnergyWeight(long amount) { long totalEnergyWeight = getTotalEnergyWeight(); totalEnergyWeight += amount; if (allowNewReward()) { - totalEnergyWeight = Math.max(0, totalEnergyWeight); + totalEnergyWeight = max(0, totalEnergyWeight, allowStrictMath2()); } saveTotalEnergyWeight(totalEnergyWeight); } @@ -2271,7 +2272,7 @@ public void addTotalTronPowerWeight(long amount) { long totalWeight = getTotalTronPowerWeight(); totalWeight += amount; if (allowNewReward()) { - totalWeight = Math.max(0, totalWeight); + totalWeight = max(0, totalWeight, allowStrictMath2()); } saveTotalTronPowerWeight(totalWeight); } @@ -2896,6 +2897,10 @@ public boolean allowStrictMath() { return getAllowStrictMath() == 1L; } + public boolean allowStrictMath2() { + return this.allowConsensusLogicOptimization(); + } + public void saveConsensusLogicOptimization(long value) { this.put(CONSENSUS_LOGIC_OPTIMIZATION, new BytesCapsule(ByteArray.fromLong(value))); diff --git a/common/src/main/java/org/tron/common/math/MathWrapper.java b/common/src/main/java/org/tron/common/math/MathWrapper.java index 519dafb9d42..758a0f18370 100644 --- a/common/src/main/java/org/tron/common/math/MathWrapper.java +++ b/common/src/main/java/org/tron/common/math/MathWrapper.java @@ -11,4 +11,68 @@ public class MathWrapper { public static double pow(double a, double b) { return Math.pow(a, b); } + + public static long addExact(long x, long y) { + return Math.addExact(x, y); + } + + public static int addExact(int x, int y) { + return Math.addExact(x, y); + } + + public static long floorDiv(long x, long y) { + return Math.floorDiv(x, y); + } + + public static int multiplyExact(int x, int y) { + return Math.multiplyExact(x, y); + } + + public static long multiplyExact(long x, long y) { + return Math.multiplyExact(x, y); + } + + public static long subtractExact(long x, long y) { + return Math.subtractExact(x, y); + } + + public static int min(int a, int b) { + return Math.min(a, b); + } + + public static long min(long a, long b) { + return Math.min(a, b); + } + + public static int max(int a, int b) { + return Math.max(a, b); + } + + public static long max(long a, long b) { + return Math.max(a, b); + } + + public static int round(float a) { + return Math.round(a); + } + + public static long round(double a) { + return Math.round(a); + } + + public static double ceil(double a) { + return Math.ceil(a); + } + + public static double signum(double a) { + return Math.signum(a); + } + + public static double random() { + return Math.random(); + } + + public static long abs(long a) { + return Math.abs(a); + } } diff --git a/common/src/main/java/org/tron/common/math/Maths.java b/common/src/main/java/org/tron/common/math/Maths.java new file mode 100644 index 00000000000..f0503cee2e4 --- /dev/null +++ b/common/src/main/java/org/tron/common/math/Maths.java @@ -0,0 +1,92 @@ +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); + } + + /** + * Adds two integers together, checking for overflow. + * @param x the first value. + * @param y the second value. + * @return the sum of {@code x} and {@code y}. + * @throws ArithmeticException if the result overflows an int. + */ + public static long addExact(long x, long y, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.addExact(x, y) : MathWrapper.addExact(x, y); + } + + public static int addExact(int x, int y, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.addExact(x, y) : MathWrapper.addExact(x, y); + } + + public static long floorDiv(long x, long y, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.floorDiv(x, y) : MathWrapper.floorDiv(x, y); + } + + public static int multiplyExact(int x, int y, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.multiplyExact(x, y) : MathWrapper.multiplyExact(x, y); + } + + public static long multiplyExact(long x, long y, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.multiplyExact(x, y) : MathWrapper.multiplyExact(x, y); + } + + public static long subtractExact(long x, long y, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.subtractExact(x, y) : MathWrapper.subtractExact(x, y); + } + + public static int min(int a, int b, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.min(a, b) : MathWrapper.min(a, b); + } + + public static long min(long a, long b, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.min(a, b) : MathWrapper.min(a, b); + } + + public static int max(int a, int b, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.max(a, b) : MathWrapper.max(a, b); + } + + public static long max(long a, long b, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.max(a, b) : MathWrapper.max(a, b); + } + + public static int round(float a, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.round(a) : MathWrapper.round(a); + } + + public static long round(double a, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.round(a) : MathWrapper.round(a); + } + + public static double ceil(double a, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.ceil(a) : MathWrapper.ceil(a); + } + + public static double signum(double a, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.signum(a) : MathWrapper.signum(a); + } + + public static double random(boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.random() : MathWrapper.random(); + } + + public static long abs(long a, boolean useStrictMath) { + return useStrictMath ? StrictMathWrapper.abs(a) : MathWrapper.abs(a); + } + +} diff --git a/common/src/main/java/org/tron/common/math/StrictMathWrapper.java b/common/src/main/java/org/tron/common/math/StrictMathWrapper.java index 6285f6567c0..6a4d9c4e1a6 100644 --- a/common/src/main/java/org/tron/common/math/StrictMathWrapper.java +++ b/common/src/main/java/org/tron/common/math/StrictMathWrapper.java @@ -5,4 +5,140 @@ public class StrictMathWrapper { public static double pow(double a, double b) { return StrictMath.pow(a, b); } + + /** + * *** methods are same as {@link java.lang.Math} methods, guaranteed by the call start *** + */ + + /** + * finally calls {@link java.lang.Math#addExact(long, long)} + */ + + public static long addExact(long x, long y) { + return StrictMath.addExact(x, y); + } + + /** + * finally calls {@link java.lang.Math#addExact(int, int)} + */ + + public static int addExact(int x, int y) { + return StrictMath.addExact(x, y); + } + + /** + * finally calls {@link java.lang.Math#subtractExact(long, long)} + */ + + public static long subtractExact(long x, long y) { + return StrictMath.subtractExact(x, y); + } + + /** + * finally calls {@link java.lang.Math#floorMod(long, long)} + */ + public static long multiplyExact(long x, long y) { + return StrictMath.multiplyExact(x, y); + } + + public static long multiplyExact(long x, int y) { + return multiplyExact(x, (long) y); + } + + public static int multiplyExact(int x, int y) { + return StrictMath.multiplyExact(x, y); + } + + /** + * finally calls {@link java.lang.Math#floorDiv(long, long)} + */ + public static long floorDiv(long x, long y) { + return StrictMath.floorDiv(x, y); + } + + public static long floorDiv(long x, int y) { + return floorDiv(x, (long) y); + } + + /** + * finally calls {@link java.lang.Math#min(int, int)} + */ + public static int min(int a, int b) { + return StrictMath.min(a, b); + } + + /** + * finally calls {@link java.lang.Math#min(long, long)} + */ + public static long min(long a, long b) { + return StrictMath.min(a, b); + } + + /** + * finally calls {@link java.lang.Math#max(int, int)} + */ + public static int max(int a, int b) { + return StrictMath.max(a, b); + } + + /** + * finally calls {@link java.lang.Math#max(long, long)} + */ + public static long max(long a, long b) { + return StrictMath.max(a, b); + } + + /** + * finally calls {@link java.lang.Math#round(float)} + */ + public static int round(float a) { + return StrictMath.round(a); + } + + /** + * finally calls {@link java.lang.Math#round(double)} + */ + public static long round(double a) { + return StrictMath.round(a); + } + + /** + * finally calls {@link java.lang.Math#signum(double)} + */ + public static double signum(double d) { + return StrictMath.signum(d); + } + + /** + * finally calls {@link java.lang.Math#signum(float)} + */ + public static long abs(long a) { + return StrictMath.abs(a); + } + + /** + * *** methods are same as {@link java.lang.Math} methods, guaranteed by the call end *** + */ + + /** + * *** methods are same as {@link java.lang.Math} methods by mathematical algorithms*** + * / + + + /** + * mathematical integer: ceil(i) = floor(i) = i + * @return the smallest (closest to negative infinity) double value that is greater + * than or equal to the argument and is equal to a mathematical integer. + */ + public static double ceil(double a) { + return StrictMath.ceil(a); + } + + /** + * *** methods are no matters *** + */ + public static double random() { + return StrictMath.random(); + } + } diff --git a/common/src/main/java/org/tron/common/runtime/vm/DataWord.java b/common/src/main/java/org/tron/common/runtime/vm/DataWord.java index 0eb0487a534..1601dcaad28 100644 --- a/common/src/main/java/org/tron/common/runtime/vm/DataWord.java +++ b/common/src/main/java/org/tron/common/runtime/vm/DataWord.java @@ -17,6 +17,9 @@ */ package org.tron.common.runtime.vm; +import static org.tron.common.math.Maths.min; +import static org.tron.common.math.Maths.signum; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import java.math.BigInteger; @@ -28,6 +31,7 @@ import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.FastByteComparisons; import org.tron.core.db.ByteArrayWrapper; +import org.tron.core.vm.config.VMConfig; /** * DataWord is the 32-byte array representation of a 256-bit number Calculations can be done on this @@ -165,7 +169,7 @@ public byte[] getClonedData() { byte[] ret = ByteUtil.EMPTY_BYTE_ARRAY; if (data != null) { ret = new byte[WORD_SIZE]; - int dataSize = Math.min(data.length, WORD_SIZE); + int dataSize = min(data.length, WORD_SIZE, VMConfig.allowStrictMath2()); System.arraycopy(data, 0, ret, 0, dataSize); } return ret; @@ -484,7 +488,7 @@ public int compareTo(DataWord o) { data, 0, data.length, o.getData(), 0, o.getData().length); // Convert result into -1, 0 or 1 as is the convention - return (int) Math.signum(result); + return (int) signum(result, VMConfig.allowStrictMath2()); } public void signExtend(byte k) { diff --git a/common/src/main/java/org/tron/common/utils/ByteUtil.java b/common/src/main/java/org/tron/common/utils/ByteUtil.java index 54d637d3f01..88d4cfdf90b 100644 --- a/common/src/main/java/org/tron/common/utils/ByteUtil.java +++ b/common/src/main/java/org/tron/common/utils/ByteUtil.java @@ -18,6 +18,8 @@ package org.tron.common.utils; +import static org.tron.common.math.Maths.min; + import com.google.common.base.Preconditions; import com.google.common.primitives.UnsignedBytes; import java.io.ByteArrayOutputStream; @@ -70,7 +72,7 @@ public static byte[] bigIntegerToBytes(BigInteger b, int numBytes) { byte[] bytes = new byte[numBytes]; byte[] biBytes = b.toByteArray(); int start = (biBytes.length == numBytes + 1) ? 1 : 0; - int length = Math.min(biBytes.length, numBytes); + int length = min(biBytes.length, numBytes, true); System.arraycopy(biBytes, start, bytes, numBytes - length, length); return bytes; } @@ -346,7 +348,7 @@ public static byte[] parseBytes(byte[] input, int offset, int len) { } byte[] bytes = new byte[len]; - System.arraycopy(input, offset, bytes, 0, Math.min(input.length - offset, len)); + System.arraycopy(input, offset, bytes, 0, min(input.length - offset, len, true)); return bytes; } diff --git a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java b/common/src/main/java/org/tron/core/vm/config/VMConfig.java similarity index 96% rename from actuator/src/main/java/org/tron/core/vm/config/VMConfig.java rename to common/src/main/java/org/tron/core/vm/config/VMConfig.java index 9f567344337..fa99daf20f4 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java +++ b/common/src/main/java/org/tron/core/vm/config/VMConfig.java @@ -55,6 +55,8 @@ public class VMConfig { private static boolean ALLOW_TVM_CANCUN = false; + private static Boolean ALLOW_STRICT_MATH_2 = false; + private VMConfig() { } @@ -154,6 +156,10 @@ public static void initAllowTvmCancun(long allow) { ALLOW_TVM_CANCUN = allow == 1; } + public static void initAllowStrictMath2(long allow) { + ALLOW_STRICT_MATH_2 = allow == 1; + } + public static boolean getEnergyLimitHardFork() { return CommonParameter.ENERGY_LIMIT_HARD_FORK; } @@ -241,4 +247,8 @@ public static boolean allowStrictMath() { public static boolean allowTvmCancun() { return ALLOW_TVM_CANCUN; } + + public static boolean allowStrictMath2() { + return ALLOW_STRICT_MATH_2; + } } diff --git a/framework/src/main/java/org/tron/common/logsfilter/ContractEventParser.java b/framework/src/main/java/org/tron/common/logsfilter/ContractEventParser.java index b2d8a0d8d3a..48181cb1255 100644 --- a/framework/src/main/java/org/tron/common/logsfilter/ContractEventParser.java +++ b/framework/src/main/java/org/tron/common/logsfilter/ContractEventParser.java @@ -1,5 +1,7 @@ package org.tron.common.logsfilter; +import static org.tron.common.math.Maths.min; + import java.math.BigInteger; import java.util.regex.Pattern; import lombok.extern.slf4j.Slf4j; @@ -76,7 +78,7 @@ protected static byte[] subBytes(byte[] src, int start, int length) { throw new OutputLengthException("data start:" + start + ", length:" + length); } byte[] dst = new byte[length]; - System.arraycopy(src, start, dst, 0, Math.min(length, src.length - start)); + System.arraycopy(src, start, dst, 0, min(length, src.length - start, true)); return dst; } diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index ce70d8b4cb7..86bff8fb665 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -18,6 +18,9 @@ package org.tron.core; +import static org.tron.common.math.Maths.addExact; +import static org.tron.common.math.Maths.ceil; +import static org.tron.common.math.Maths.max; import static org.tron.common.utils.Commons.getAssetIssueStoreFinal; import static org.tron.common.utils.Commons.getExchangeStoreFinal; import static org.tron.common.utils.WalletUtil.isConstant; @@ -880,10 +883,10 @@ public long calcCanDelegatedBandWidthMaxSize( long netUsage = (long) (accountNetUsage * TRX_PRECISION * ((double) (dynamicStore.getTotalNetWeight()) / dynamicStore.getTotalNetLimit())); - long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage); + long v2NetUsage = getV2NetUsage(ownerCapsule, netUsage, dynamicStore.allowStrictMath2()); long maxSize = ownerCapsule.getFrozenV2BalanceForBandwidth() - v2NetUsage; - return Math.max(0, maxSize); + return max(0, maxSize, dynamicStore.allowStrictMath2()); } public long calcCanDelegatedEnergyMaxSize(ByteString ownerAddress) { @@ -900,10 +903,11 @@ public long calcCanDelegatedEnergyMaxSize(ByteString ownerAddress) { long energyUsage = (long) (ownerCapsule.getEnergyUsage() * TRX_PRECISION * ((double) (dynamicStore.getTotalEnergyWeight()) / dynamicStore.getTotalEnergyCurrentLimit())); - long v2EnergyUsage = getV2EnergyUsage(ownerCapsule, energyUsage); + long v2EnergyUsage = getV2EnergyUsage(ownerCapsule, energyUsage, + dynamicStore.allowStrictMath2()); long maxSize = ownerCapsule.getFrozenV2BalanceForEnergy() - v2EnergyUsage; - return Math.max(0, maxSize); + return max(0, maxSize, dynamicStore.allowStrictMath2()); } public DelegatedResourceAccountIndex getDelegatedResourceAccountIndex(ByteString address) { @@ -2985,7 +2989,8 @@ public Transaction estimateEnergy(TriggerSmartContract triggerSmartContract, if (transaction.getRet(0).getRet().equals(code.SUCESS)) { txRetBuilder.setResult(true); txRetBuilder.setCode(response_code.SUCCESS); - estimateBuilder.setEnergyRequired((long) Math.ceil((double) high / dps.getEnergyFee())); + estimateBuilder.setEnergyRequired((long) ceil((double) high / dps.getEnergyFee(), + dps.allowStrictMath2())); } return transaction; @@ -3539,8 +3544,9 @@ public ShieldedTRC20Parameters createShieldedContractParameters( long totalToAmount = 0; if (scaledToAmount > 0) { try { - totalToAmount = receiveSize == 0 ? scaledToAmount - : (Math.addExact(scaledToAmount, shieldedReceives.get(0).getNote().getValue())); + totalToAmount = receiveSize == 0 ? scaledToAmount : (addExact( + scaledToAmount, shieldedReceives.get(0).getNote().getValue(), + dbManager.getDynamicPropertiesStore().allowStrictMath2())); } catch (ArithmeticException e) { throw new ZksnarkException("Unbalanced burn!"); } @@ -3671,8 +3677,9 @@ public ShieldedTRC20Parameters createShieldedContractParametersWithoutAsk( long totalToAmount = 0; if (scaledToAmount > 0) { try { - totalToAmount = receiveSize == 0 ? scaledToAmount - : Math.addExact(scaledToAmount, shieldedReceives.get(0).getNote().getValue()); + totalToAmount = receiveSize == 0 ? scaledToAmount : addExact( + scaledToAmount, shieldedReceives.get(0).getNote().getValue(), + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); } catch (ArithmeticException e) { throw new ZksnarkException("Unbalanced burn!"); } diff --git a/framework/src/main/java/org/tron/core/capsule/utils/RLP.java b/framework/src/main/java/org/tron/core/capsule/utils/RLP.java index 60a84cfd3d3..24b5c502a1c 100644 --- a/framework/src/main/java/org/tron/core/capsule/utils/RLP.java +++ b/framework/src/main/java/org/tron/core/capsule/utils/RLP.java @@ -3,6 +3,7 @@ import static java.util.Arrays.copyOfRange; import static org.bouncycastle.util.Arrays.concatenate; import static org.bouncycastle.util.BigIntegers.asUnsignedByteArray; +import static org.tron.common.math.Maths.pow; import static org.tron.common.utils.ByteUtil.byteArrayToInt; import static org.tron.common.utils.ByteUtil.intToBytesNoLeadZeroes; import static org.tron.common.utils.ByteUtil.isNullOrZeroArray; @@ -49,7 +50,7 @@ public class RLP { /** * Allow for content up to size of 2^64 bytes * */ - private static final double MAX_ITEM_LENGTH = Math.pow(256, 8); + private static final double MAX_ITEM_LENGTH = pow(256, 8, true); /** * Reason for threshold according to Vitalik Buterin: - 56 bytes maximizes the benefit of both * options - if we went with 60 then we would have only had 4 slots for long strings so RLP would 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 3a37490ee69..83ecbc1c1ab 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 @@ -1,7 +1,8 @@ package org.tron.core.config.args; -import static java.lang.Math.max; import static java.lang.System.exit; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.min; import static org.tron.core.Constant.ADD_PRE_FIX_BYTE_MAINNET; import static org.tron.core.Constant.DYNAMIC_ENERGY_INCREASE_FACTOR_RANGE; import static org.tron.core.Constant.DYNAMIC_ENERGY_MAX_FACTOR_RANGE; @@ -457,7 +458,7 @@ public static void setParam(final Config config) { if (config.hasPath(Constant.VM_MAX_ENERGY_LIMIT_FOR_CONSTANT)) { long configLimit = config.getLong(Constant.VM_MAX_ENERGY_LIMIT_FOR_CONSTANT); - PARAMETER.maxEnergyLimitForConstant = max(3_000_000L, configLimit); + PARAMETER.maxEnergyLimitForConstant = max(3_000_000L, configLimit, true); } if (config.hasPath(Constant.VM_LRU_CACHE_SIZE)) { @@ -1163,8 +1164,8 @@ public static void setParam(final Config config) { if (config.hasPath(Constant.ALLOW_DELEGATE_OPTIMIZATION)) { PARAMETER.allowDelegateOptimization = config.getLong(Constant.ALLOW_DELEGATE_OPTIMIZATION); - PARAMETER.allowDelegateOptimization = Math.min(PARAMETER.allowDelegateOptimization, 1); - PARAMETER.allowDelegateOptimization = Math.max(PARAMETER.allowDelegateOptimization, 0); + PARAMETER.allowDelegateOptimization = min(PARAMETER.allowDelegateOptimization, 1, true); + PARAMETER.allowDelegateOptimization = max(PARAMETER.allowDelegateOptimization, 0, true); } if (config.hasPath(Constant.COMMITTEE_UNFREEZE_DELAY_DAYS)) { @@ -1179,33 +1180,31 @@ public static void setParam(final Config config) { if (config.hasPath(Constant.ALLOW_DYNAMIC_ENERGY)) { PARAMETER.allowDynamicEnergy = config.getLong(Constant.ALLOW_DYNAMIC_ENERGY); - PARAMETER.allowDynamicEnergy = Math.min(PARAMETER.allowDynamicEnergy, 1); - PARAMETER.allowDynamicEnergy = Math.max(PARAMETER.allowDynamicEnergy, 0); + PARAMETER.allowDynamicEnergy = min(PARAMETER.allowDynamicEnergy, 1, true); + PARAMETER.allowDynamicEnergy = max(PARAMETER.allowDynamicEnergy, 0, true); } if (config.hasPath(Constant.DYNAMIC_ENERGY_THRESHOLD)) { PARAMETER.dynamicEnergyThreshold = config.getLong(Constant.DYNAMIC_ENERGY_THRESHOLD); PARAMETER.dynamicEnergyThreshold - = Math.min(PARAMETER.dynamicEnergyThreshold, 100_000_000_000_000_000L); - PARAMETER.dynamicEnergyThreshold = Math.max(PARAMETER.dynamicEnergyThreshold, 0); + = min(PARAMETER.dynamicEnergyThreshold, 100_000_000_000_000_000L, true); + PARAMETER.dynamicEnergyThreshold = max(PARAMETER.dynamicEnergyThreshold, 0, true); } if (config.hasPath(Constant.DYNAMIC_ENERGY_INCREASE_FACTOR)) { PARAMETER.dynamicEnergyIncreaseFactor = config.getLong(Constant.DYNAMIC_ENERGY_INCREASE_FACTOR); PARAMETER.dynamicEnergyIncreaseFactor = - Math.min(PARAMETER.dynamicEnergyIncreaseFactor, DYNAMIC_ENERGY_INCREASE_FACTOR_RANGE); - PARAMETER.dynamicEnergyIncreaseFactor = - Math.max(PARAMETER.dynamicEnergyIncreaseFactor, 0); + min(PARAMETER.dynamicEnergyIncreaseFactor, DYNAMIC_ENERGY_INCREASE_FACTOR_RANGE, true); + PARAMETER.dynamicEnergyIncreaseFactor = max(PARAMETER.dynamicEnergyIncreaseFactor, 0, true); } if (config.hasPath(Constant.DYNAMIC_ENERGY_MAX_FACTOR)) { PARAMETER.dynamicEnergyMaxFactor = config.getLong(Constant.DYNAMIC_ENERGY_MAX_FACTOR); PARAMETER.dynamicEnergyMaxFactor = - Math.min(PARAMETER.dynamicEnergyMaxFactor, DYNAMIC_ENERGY_MAX_FACTOR_RANGE); - PARAMETER.dynamicEnergyMaxFactor = - Math.max(PARAMETER.dynamicEnergyMaxFactor, 0); + min(PARAMETER.dynamicEnergyMaxFactor, DYNAMIC_ENERGY_MAX_FACTOR_RANGE, true); + PARAMETER.dynamicEnergyMaxFactor = max(PARAMETER.dynamicEnergyMaxFactor, 0, true); } PARAMETER.dynamicConfigEnable = config.hasPath(Constant.DYNAMIC_CONFIG_ENABLE) @@ -1624,7 +1623,7 @@ private static void initRocksDbSettings(Config config) { ? config.getInt(prefix + "levelNumber") : 7; int compactThreads = config.hasPath(prefix + "compactThreads") ? config.getInt(prefix + "compactThreads") - : max(Runtime.getRuntime().availableProcessors(), 1); + : max(Runtime.getRuntime().availableProcessors(), 1, true); int blocksize = config.hasPath(prefix + "blocksize") ? config.getInt(prefix + "blocksize") : 16; long maxBytesForLevelBase = config.hasPath(prefix + "maxBytesForLevelBase") 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 cfd12fffce2..43ea4460140 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -1,5 +1,8 @@ package org.tron.core.db; +import static org.tron.common.math.Maths.floorDiv; +import static org.tron.common.math.Maths.max; +import static org.tron.common.math.Maths.min; import static org.tron.common.utils.Commons.adjustBalance; import static org.tron.core.Constant.TRANSACTION_MAX_BYTE_SIZE; import static org.tron.core.exception.BadBlockException.TypeEnum.CALC_MERKLE_ROOT_FAILED; @@ -916,19 +919,20 @@ public void consumeMultiSignFee(TransactionCapsule trx, TransactionTrace trace) throws AccountResourceInsufficientException { if (trx.getInstance().getSignatureCount() > 1) { long fee = getDynamicPropertiesStore().getMultiSignFee(); - + boolean useStrictMath2 = getDynamicPropertiesStore().allowStrictMath2(); List contracts = trx.getInstance().getRawData().getContractList(); for (Contract contract : contracts) { byte[] address = TransactionCapsule.getOwner(contract); AccountCapsule accountCapsule = getAccountStore().get(address); try { if (accountCapsule != null) { - adjustBalance(getAccountStore(), accountCapsule, -fee); + adjustBalance(getAccountStore(), accountCapsule, -fee, useStrictMath2); if (getDynamicPropertiesStore().supportBlackHoleOptimization()) { getDynamicPropertiesStore().burnTrx(fee); } else { - adjustBalance(getAccountStore(), this.getAccountStore().getBlackhole(), +fee); + adjustBalance(getAccountStore(), this.getAccountStore().getBlackhole(), +fee, + useStrictMath2); } } } catch (BalanceInsufficientException e) { @@ -953,19 +957,20 @@ public void consumeMemoFee(TransactionCapsule trx, TransactionTrace trace) if (fee == 0) { return; } - + boolean useStrictMath2 = getDynamicPropertiesStore().allowStrictMath2(); List contracts = trx.getInstance().getRawData().getContractList(); for (Contract contract : contracts) { byte[] address = TransactionCapsule.getOwner(contract); AccountCapsule accountCapsule = getAccountStore().get(address); try { if (accountCapsule != null) { - adjustBalance(getAccountStore(), accountCapsule, -fee); + adjustBalance(getAccountStore(), accountCapsule, -fee, useStrictMath2); if (getDynamicPropertiesStore().supportBlackHoleOptimization()) { getDynamicPropertiesStore().burnTrx(fee); } else { - adjustBalance(getAccountStore(), this.getAccountStore().getBlackhole(), +fee); + adjustBalance(getAccountStore(), this.getAccountStore().getBlackhole(), +fee, + useStrictMath2); } } } catch (BalanceInsufficientException e) { @@ -1834,9 +1839,10 @@ private void payReward(BlockCapsule block) { mortgageService.payStandbyWitness(); if (chainBaseManager.getDynamicPropertiesStore().supportTransactionFeePool()) { - long transactionFeeReward = Math - .floorDiv(chainBaseManager.getDynamicPropertiesStore().getTransactionFeePool(), - Constant.TRANSACTION_FEE_POOL_PERIOD); + long transactionFeeReward = floorDiv( + chainBaseManager.getDynamicPropertiesStore().getTransactionFeePool(), + Constant.TRANSACTION_FEE_POOL_PERIOD, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); mortgageService.payTransactionFeeReward(witnessCapsule.getAddress().toByteArray(), transactionFeeReward); chainBaseManager.getDynamicPropertiesStore().saveTransactionFeePool( @@ -1850,9 +1856,10 @@ private void payReward(BlockCapsule block) { + chainBaseManager.getDynamicPropertiesStore().getWitnessPayPerBlock()); if (chainBaseManager.getDynamicPropertiesStore().supportTransactionFeePool()) { - long transactionFeeReward = Math - .floorDiv(chainBaseManager.getDynamicPropertiesStore().getTransactionFeePool(), - Constant.TRANSACTION_FEE_POOL_PERIOD); + long transactionFeeReward = floorDiv( + chainBaseManager.getDynamicPropertiesStore().getTransactionFeePool(), + Constant.TRANSACTION_FEE_POOL_PERIOD, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); account.setAllowance(account.getAllowance() + transactionFeeReward); chainBaseManager.getDynamicPropertiesStore().saveTransactionFeePool( chainBaseManager.getDynamicPropertiesStore().getTransactionFeePool() @@ -2433,8 +2440,10 @@ private void initLiteNode() { } transactionCount += trx.getTransactionIds().size(); long blockNum = trx.getNum(); - maxBlock = Math.max(maxBlock, blockNum); - minBlock = Math.min(minBlock, blockNum); + maxBlock = max(maxBlock, blockNum, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + minBlock = min(minBlock, blockNum, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); item.setBlockNum(blockNum); trx.getTransactionIds().forEach( tid -> chainBaseManager.getTransactionStore().put(Hex.decode(tid), item)); diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java index f575253c50c..55446593bd0 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java @@ -1,5 +1,7 @@ package org.tron.core.net.messagehandler; +import static org.tron.common.math.Maths.min; + import java.util.LinkedList; import java.util.List; import lombok.extern.slf4j.Slf4j; @@ -117,7 +119,7 @@ private BlockId getUnForkId(List blockIds) throws P2pException { private LinkedList getBlockIds(Long unForkNum, BlockId headID) throws P2pException { long headNum = headID.getNum(); - long len = Math.min(headNum, unForkNum + NetConstants.SYNC_FETCH_BATCH_NUM); + long len = min(headNum, unForkNum + NetConstants.SYNC_FETCH_BATCH_NUM, true); LinkedList ids = new LinkedList<>(); for (long i = unForkNum; i <= len; i++) { diff --git a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java index a63fd4bf0a9..b99b5b52bad 100644 --- a/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java +++ b/framework/src/main/java/org/tron/core/net/service/effective/ResilienceService.java @@ -1,5 +1,8 @@ package org.tron.core.net.service.effective; +import static org.tron.common.math.Maths.ceil; +import static org.tron.common.math.Maths.max; + import java.util.Comparator; import java.util.HashMap; import java.util.List; @@ -86,8 +89,8 @@ private void disconnectRandom() { long now = System.currentTimeMillis(); Map weights = new HashMap<>(); peers.forEach(peer -> { - int weight = (int) Math.ceil((double) (now - peer.getLastInteractiveTime()) / 500); - weights.put(peer, Math.max(weight, 1)); + int weight = (int) ceil((double) (now - peer.getLastInteractiveTime()) / 500, true); + weights.put(peer, max(weight, 1, true)); }); WeightedRandom weightedRandom = new WeightedRandom(weights); PeerConnection one = (PeerConnection) weightedRandom.next(); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java index cf04a1769aa..a6cc451b41c 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java @@ -1,5 +1,7 @@ package org.tron.core.services.jsonrpc.filters; +import static org.tron.common.math.Maths.min; + import com.google.protobuf.ByteString; import lombok.Getter; import org.apache.commons.lang3.StringUtils; @@ -55,7 +57,7 @@ public LogFilterWrapper(FilterRequest fr, long currentMaxBlockNum, Wallet wallet if (toBlockSrc == -1) { toBlockSrc = Long.MAX_VALUE; } - fromBlockSrc = Math.min(toBlockSrc, currentMaxBlockNum); + fromBlockSrc = min(toBlockSrc, currentMaxBlockNum, true); } else if (StringUtils.isNotEmpty(fr.getFromBlock()) && StringUtils.isEmpty(fr.getToBlock())) { diff --git a/framework/src/main/java/org/tron/program/DBConvert.java b/framework/src/main/java/org/tron/program/DBConvert.java index a13a2ffefb5..7b9d63544dc 100644 --- a/framework/src/main/java/org/tron/program/DBConvert.java +++ b/framework/src/main/java/org/tron/program/DBConvert.java @@ -1,6 +1,7 @@ package org.tron.program; import static org.fusesource.leveldbjni.JniDBFactory.factory; +import static org.tron.common.math.Maths.max; import java.io.File; import java.nio.file.Path; @@ -190,7 +191,7 @@ private Options newDefaultRocksDbOptions() { options.setTargetFileSizeBase(64 * 1024 * 1024); options.setTargetFileSizeMultiplier(1); options.setMaxBytesForLevelBase(512 * 1024 * 1024); - options.setMaxBackgroundCompactions(Math.max(1, Runtime.getRuntime().availableProcessors())); + options.setMaxBackgroundCompactions(max(1, Runtime.getRuntime().availableProcessors(), true)); options.setLevel0FileNumCompactionTrigger(4); options.setLevelCompactionDynamicLevelBytes(true); if ("market_pair_price_to_order".equalsIgnoreCase(this.dbName)) { diff --git a/framework/src/test/java/org/tron/common/BaseTest.java b/framework/src/test/java/org/tron/common/BaseTest.java index 959a746a141..9eddef83fba 100644 --- a/framework/src/test/java/org/tron/common/BaseTest.java +++ b/framework/src/test/java/org/tron/common/BaseTest.java @@ -16,6 +16,7 @@ import org.tron.common.application.Application; import org.tron.common.crypto.ECKey; import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.Commons; import org.tron.common.utils.Sha256Hash; import org.tron.consensus.base.Param; import org.tron.core.ChainBaseManager; @@ -23,6 +24,8 @@ import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.db.Manager; +import org.tron.core.exception.BalanceInsufficientException; +import org.tron.core.store.AccountStore; import org.tron.protos.Protocol; @Slf4j @@ -102,4 +105,10 @@ public Protocol.Block getSignedBlock(ByteString witness, long time, byte[] priva return block.toBuilder().setBlockHeader(blockHeader).build(); } + + public void adjustBalance(AccountStore accountStore, byte[] accountAddress, long amount) + throws BalanceInsufficientException { + Commons.adjustBalance(accountStore, accountAddress, amount, + chainBaseManager.getDynamicPropertiesStore().allowStrictMath2()); + } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java index 7debeb12772..9e58233c922 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java @@ -15,6 +15,8 @@ package org.tron.common.runtime.vm; +import static org.tron.common.math.Maths.max; + import com.google.protobuf.Any; import com.google.protobuf.ByteString; import org.junit.Assert; @@ -248,7 +250,8 @@ public void testMaxContractResultSize() { continue; } Result result = Result.newBuilder().setContractRet(cr).build(); - maxSize = Math.max(maxSize, result.getSerializedSize()); + maxSize = max(maxSize, result.getSerializedSize(), + dbManager.getDynamicPropertiesStore().allowStrictMath2()); } Assert.assertEquals(2, maxSize); } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java index 9558c701109..524a858d2b5 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/FreezeV2Test.java @@ -1,5 +1,6 @@ package org.tron.common.runtime.vm; +import static org.tron.common.math.Maths.min; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_MS; @@ -856,7 +857,8 @@ private TVMTestResult unDelegateResource( transferUsage = (long) (oldReceiver.getEnergyUsage() * ((double) (amount) / oldReceiver.getAllFrozenBalanceForEnergy())); } - transferUsage = Math.min(unDelegateMaxUsage, transferUsage); + transferUsage = min(unDelegateMaxUsage, transferUsage, + manager.getDynamicPropertiesStore().allowStrictMath2()); } DelegatedResourceStore delegatedResourceStore = manager.getDelegatedResourceStore(); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/MemoryTest.java b/framework/src/test/java/org/tron/common/runtime/vm/MemoryTest.java index b6e9cfe109c..dbbf6921567 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/MemoryTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/MemoryTest.java @@ -18,9 +18,9 @@ package org.tron.common.runtime.vm; -import static java.lang.Math.ceil; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertTrue; +import static org.tron.common.math.Maths.ceil; import java.util.Arrays; import lombok.extern.slf4j.Slf4j; @@ -43,7 +43,7 @@ private static void checkMemoryExtend(int dataSize) { } private static int calcSize(int dataSize, int chunkSize) { - return (int) ceil((double) dataSize / chunkSize) * chunkSize; + return (int) ceil((double) dataSize / chunkSize, true) * chunkSize; } @Test diff --git a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java index 833ed6b0ac3..27e7891e6d8 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsVerifyProofTest.java @@ -1,6 +1,8 @@ package org.tron.common.runtime.vm; import static org.junit.Assert.assertNotNull; +import static org.tron.common.math.Maths.random; +import static org.tron.common.math.Maths.round; import com.google.protobuf.ByteString; import java.math.BigInteger; @@ -4504,7 +4506,7 @@ private byte[] longTo32Bytes(long value) { } private long randomLong() { - return Math.round(Math.random() * Long.MAX_VALUE / 2); + return round(random(true) * Long.MAX_VALUE / 2, true); } } diff --git a/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java b/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java index 1d85e9a7eab..fc3b16f8f2e 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/VoteTest.java @@ -1,5 +1,6 @@ package org.tron.common.runtime.vm; +import static org.tron.common.math.Maths.max; import static org.tron.protos.Protocol.Transaction.Result.contractResult; import static org.tron.protos.Protocol.Transaction.Result.contractResult.REVERT; import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS; @@ -863,7 +864,8 @@ private void checkRewardAndWithdraw(byte[] contract, boolean isZero) throws Exce long rewardBySystem = mortgageService.queryReward(contract); long beginCycle = manager.getDelegationStore().getBeginCycle(contract); long currentCycle = manager.getDynamicPropertiesStore().getCurrentCycleNumber(); - long passedCycle = Math.max(0, currentCycle - beginCycle); + long passedCycle = max(0, currentCycle - beginCycle, + manager.getDynamicPropertiesStore().allowStrictMath2()); Assert.assertTrue(isZero ? rewardBySystem == 0 : rewardBySystem > 0); triggerContract(contract, SUCCESS, getConsumer(">=", rewardBySystem) diff --git a/framework/src/test/java/org/tron/common/utils/client/utils/AbiUtil.java b/framework/src/test/java/org/tron/common/utils/client/utils/AbiUtil.java index 976490b8c80..d518776adb2 100644 --- a/framework/src/test/java/org/tron/common/utils/client/utils/AbiUtil.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/AbiUtil.java @@ -1,5 +1,7 @@ package org.tron.common.utils.client.utils; +import static org.tron.common.math.Maths.abs; + import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.ArrayList; @@ -340,7 +342,7 @@ static class CoderNumber extends Coder { @Override byte[] encode(String value) { long n = Long.valueOf(value); - DataWord word = new DataWord(Math.abs(n)); + DataWord word = new DataWord(abs(n, true)); if (n < 0) { word.negate(); } diff --git a/framework/src/test/java/org/tron/common/utils/client/utils/DataWord.java b/framework/src/test/java/org/tron/common/utils/client/utils/DataWord.java index 6c36f4d636a..f676ef6c8e4 100644 --- a/framework/src/test/java/org/tron/common/utils/client/utils/DataWord.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/DataWord.java @@ -18,6 +18,8 @@ * along with the ethereumJ library. If not, see . */ +import static org.tron.common.math.Maths.signum; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import java.math.BigInteger; @@ -466,7 +468,7 @@ public int compareTo(DataWord o) { data, 0, data.length, o.getData(), 0, o.getData().length); // Convert result into -1, 0 or 1 as is the convention - return (int) Math.signum(result); + return (int) signum(result, true); } /** diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java index 807d0e1be02..179ba56e7ed 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeCreateActuatorTest.java @@ -125,8 +125,8 @@ public void sameTokenNameCloseSuccessExchangeCreate() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -216,7 +216,7 @@ public void sameTokenNameCloseSuccessExchangeCreate2() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.setBalance(200_000_000_000000L); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L, true); dbManager.getAccountStore().put(ownerAddress, accountCapsule); ExchangeCreateActuator actuator = new ExchangeCreateActuator(); @@ -710,8 +710,8 @@ public void sameTokenNameCloseNoEnoughBalance() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance, true); accountCapsule.setBalance(1000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -748,8 +748,8 @@ public void sameTokenNameOpenNoEnoughBalance() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance, true); accountCapsule.setBalance(1000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -785,8 +785,8 @@ public void sameTokenNameCloseSameTokens() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -822,8 +822,8 @@ public void sameTokenNameOpenSameTokens() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -859,8 +859,8 @@ public void sameTokenNameCloseLessToken() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), 1000); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), 1000); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), 1000, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), 1000, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -897,8 +897,8 @@ public void sameTokenNameOpenLessToken() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), 1000); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), 1000); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), 1000, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), 1000, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -934,8 +934,8 @@ public void sameTokenNameCloseMoreThanBalanceLimit() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -972,8 +972,8 @@ public void sameTokenNameOpenMoreThanBalanceLimit() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenBalance, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1010,7 +1010,7 @@ public void sameTokenNameCloseBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.setBalance(firstTokenBalance + 1000L); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L, false); dbManager.getAccountStore().put(ownerAddress, accountCapsule); ExchangeCreateActuator actuator = new ExchangeCreateActuator(); @@ -1047,7 +1047,7 @@ public void sameTokenNameOpenBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.setBalance(firstTokenBalance + 1000L); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L, false); dbManager.getAccountStore().put(ownerAddress, accountCapsule); ExchangeCreateActuator actuator = new ExchangeCreateActuator(); @@ -1082,8 +1082,8 @@ public void sameTokenNameCloseFirstTokenBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance - 1000L); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance - 1000L, false); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1120,8 +1120,8 @@ public void sameTokenNameOpenFirstTokenBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance - 1000L); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance - 1000L, false); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1158,7 +1158,7 @@ public void sameTokenNameCloseBalanceNotEnough2() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.setBalance(secondTokenBalance + 1000L); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), 200_000_000L); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), 200_000_000L, false); dbManager.getAccountStore().put(ownerAddress, accountCapsule); ExchangeCreateActuator actuator = new ExchangeCreateActuator(); @@ -1195,7 +1195,7 @@ public void sameTokenNameOpenBalanceNotEnough2() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.setBalance(secondTokenBalance + 1000L); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), 200_000_000L); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), 200_000_000L, false); dbManager.getAccountStore().put(ownerAddress, accountCapsule); ExchangeCreateActuator actuator = new ExchangeCreateActuator(); @@ -1230,8 +1230,8 @@ public void sameTokenNameCloseSecondTokenBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), 90_000_000L); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, false); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), 90_000_000L, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1268,8 +1268,8 @@ public void sameTokenNameOpenSecondTokenBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), 90_000_000L); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), 90_000_000L, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1305,7 +1305,7 @@ public void sameTokenNameCloseSecondTokenNotExist() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1342,7 +1342,7 @@ public void sameTokenNameOpenSecondTokenNotExist() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenBalance, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1388,7 +1388,7 @@ public void commonErrorCheck() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); accountCapsule.setBalance(200_000_000_000000L); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), 200_000_000L, true); dbManager.getAccountStore().put(ownerAddress, accountCapsule); actuatorTest.setContract(getContract( diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java index 6268c226c7e..7aef11ed793 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeInjectActuatorTest.java @@ -190,8 +190,8 @@ public void SameTokenNameCloseSuccessExchangeInject() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, false); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -451,7 +451,7 @@ public void SameTokenNameCloseSuccessExchangeInject2() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, false); accountCapsule.setBalance(firstTokenQuant); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -731,8 +731,8 @@ public void SameTokenNameCloseExchangeNotExist() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -819,8 +819,8 @@ public void SameTokenNameCloseAccountIsNotCreator() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -910,7 +910,7 @@ public void SameTokenNameCloseTokenIsNotInExchange() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, false); accountCapsule.setBalance(firstTokenQuant); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -995,8 +995,8 @@ public void SameTokenNameCloseTokenBalanceZero() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant, false); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, false); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1099,8 +1099,8 @@ public void SameTokenNameCloseTokenQuantLessThanZero() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), 1000L); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), 1000L, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1187,7 +1187,7 @@ public void SameTokenNameCloseCalculatedTokenQuantLessThanZero() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(firstTokenQuant); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1273,7 +1273,7 @@ public void SameTokenNameCloseTokenBalanceGreaterThanBalanceLimit() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(firstTokenQuant); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1358,7 +1358,7 @@ public void SameTokenNameCloseBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(firstTokenQuant - 1); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1445,8 +1445,8 @@ public void SameTokenNameCloseTokenBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant - 1); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant - 1, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1533,7 +1533,7 @@ public void SameTokenNameCloseBalanceNotEnough2() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(399_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1618,8 +1618,8 @@ public void SameTokenNameCloseAnotherTokenBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant - 1); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant - 1, false); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, false); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1785,8 +1785,8 @@ public void sameTokennullTransationResult() { TransactionResultCapsule ret = null; byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); 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 bf60b1cd910..d39706e0699 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java @@ -430,7 +430,7 @@ public void SameTokenNameCloseSuccessExchangeTransaction2() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); + accountCapsule.addAssetAmount(tokenId.getBytes(), 10000, true); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -588,7 +588,7 @@ public void SameTokenNameCloseInvalidAddress() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); + accountCapsule.addAssetAmount(tokenId.getBytes(), 10000, false); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -679,7 +679,7 @@ public void SameTokenNameCloseNoEnoughBalance() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); + accountCapsule.addAssetAmount(tokenId.getBytes(), 10000, false); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -729,7 +729,7 @@ public void SameTokenNameOpenNoEnoughBalance() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); + accountCapsule.addAssetAmount(tokenId.getBytes(), 10000, true); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -779,7 +779,7 @@ public void SameTokenNameCloseNoAccount() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); + accountCapsule.addAssetAmount(tokenId.getBytes(), 10000, true); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -870,7 +870,7 @@ public void SameTokenNameCloseExchangeNotExist() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); + accountCapsule.addAssetAmount(tokenId.getBytes(), 10000, true); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -959,7 +959,7 @@ public void SameTokenNameCloseTokenIsNotInExchange() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); + accountCapsule.addAssetAmount(tokenId.getBytes(), 10000, true); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -1049,7 +1049,7 @@ public void SameTokenNameCloseTokenBalanceZero() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); + accountCapsule.addAssetAmount(tokenId.getBytes(), 10000, true); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -1155,7 +1155,7 @@ public void SameTokenNameCloseTokenQuantLessThanZero() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); + accountCapsule.addAssetAmount(tokenId.getBytes(), 10000, true); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -1245,7 +1245,7 @@ public void SameTokenNameCloseTokenBalanceGreaterThanBalanceLimit() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), 10000); + accountCapsule.addAssetAmount(tokenId.getBytes(), 10000, true); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -1421,7 +1421,7 @@ public void SameTokenNameCloseTokenBalanceNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), quant - 1); + accountCapsule.addAssetAmount(tokenId.getBytes(), quant - 1, true); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); @@ -1511,7 +1511,7 @@ public void SameTokenNameCloseTokenRequiredNotEnough() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(tokenId.getBytes(), quant); + accountCapsule.addAssetAmount(tokenId.getBytes(), quant, true); Map assetMap = accountCapsule.getAssetMapForTest(); Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); Assert.assertEquals(null, assetMap.get(buyTokenId)); diff --git a/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java index 6844925288e..5c5536f873c 100644 --- a/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ExchangeWithdrawActuatorTest.java @@ -851,8 +851,8 @@ public void SameTokenNameCloseAccountIsNotCreator() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -943,7 +943,7 @@ public void SameTokenNameCloseTokenIsNotInExchange() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(firstTokenQuant); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1030,8 +1030,8 @@ public void SameTokenNameCloseTokenBalanceZero() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), firstTokenQuant, false); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, false); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1136,8 +1136,8 @@ public void SameTokenNameCloseTokenQuantLessThanZero() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), 1000L); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), 1000L, true); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, true); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); @@ -1227,8 +1227,8 @@ public void SameTokenNameCloseTnotherTokenQuantLessThanZero() { byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_FIRST); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); - accountCapsule.addAssetAmount(firstTokenId.getBytes(), 1000L); - accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant); + accountCapsule.addAssetAmount(firstTokenId.getBytes(), 1000L, false); + accountCapsule.addAssetAmount(secondTokenId.getBytes(), secondTokenQuant, false); accountCapsule.setBalance(10000_000000L); dbManager.getAccountStore().put(ownerAddress, accountCapsule); diff --git a/framework/src/test/java/org/tron/core/actuator/ParticipateAssetIssueActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ParticipateAssetIssueActuatorTest.java index 52e5f554374..88db0791b0a 100755 --- a/framework/src/test/java/org/tron/core/actuator/ParticipateAssetIssueActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ParticipateAssetIssueActuatorTest.java @@ -1230,7 +1230,7 @@ public void sameTokenNameCloseNotEnoughAssetTest() { AccountCapsule toAccount = chainBaseManager.getAccountStore().get(ByteArray.fromHexString(TO_ADDRESS)); toAccount.reduceAssetAmount(ByteString.copyFromUtf8(ASSET_NAME).toByteArray(), - TOTAL_SUPPLY - 10000); + TOTAL_SUPPLY - 10000, true); chainBaseManager.getAccountStore().put(toAccount.getAddress().toByteArray(), toAccount); ParticipateAssetIssueActuator actuator = new ParticipateAssetIssueActuator(); actuator.setChainBaseManager(chainBaseManager).setAny(getContract(1)); diff --git a/framework/src/test/java/org/tron/core/actuator/UpdateSettingContractActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UpdateSettingContractActuatorTest.java index 508cee731f0..1f9a9af825c 100644 --- a/framework/src/test/java/org/tron/core/actuator/UpdateSettingContractActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UpdateSettingContractActuatorTest.java @@ -108,8 +108,8 @@ public void successUpdateSettingContract() { Assert.assertEquals(ret.getInstance().getRet(), Protocol.Transaction.Result.code.SUCESS); Assert.assertEquals( dbManager.getContractStore().get(ByteArray.fromHexString(CONTRACT_ADDRESS)) - .getConsumeUserResourcePercent(), - TARGET_PERCENT); + .getConsumeUserResourcePercent( + dbManager.getDynamicPropertiesStore().allowStrictMath2()), TARGET_PERCENT); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { @@ -245,8 +245,8 @@ public void twiceUpdateSettingContract() { Assert.assertEquals(ret.getInstance().getRet(), Protocol.Transaction.Result.code.SUCESS); Assert.assertEquals( dbManager.getContractStore().get(ByteArray.fromHexString(CONTRACT_ADDRESS)) - .getConsumeUserResourcePercent(), - TARGET_PERCENT); + .getConsumeUserResourcePercent( + dbManager.getDynamicPropertiesStore().allowStrictMath2()), TARGET_PERCENT); // second secondActuator.validate(); @@ -255,8 +255,8 @@ public void twiceUpdateSettingContract() { Assert.assertEquals(ret.getInstance().getRet(), Protocol.Transaction.Result.code.SUCESS); Assert.assertEquals( dbManager.getContractStore().get(ByteArray.fromHexString(CONTRACT_ADDRESS)) - .getConsumeUserResourcePercent(), - 90L); + .getConsumeUserResourcePercent( + dbManager.getDynamicPropertiesStore().allowStrictMath2()), 90L); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); diff --git a/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java index 3346a1aead5..0eb69f8fd66 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.tron.common.math.Maths.max; import static org.tron.core.capsule.utils.TransactionUtil.isNumber; import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_COST_BASE_SIZE; import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; @@ -114,7 +115,7 @@ public static long estimateConsumeBandWidthSize(final AccountCapsule ownerCapsul TransactionCapsule fakeTransactionCapsule2 = new TransactionCapsule(builder2.build(), ContractType.DelegateResourceContract); long size2 = consumeBandWidthSize(fakeTransactionCapsule2, chainBaseManager); - long addSize = Math.max(size1 - size2, 0L); + long addSize = max(size1 - size2, 0L, true); return DELEGATE_COST_BASE_SIZE + addSize; } @@ -135,7 +136,7 @@ public static long estimateConsumeBandWidthSizeOld( TransactionCapsule fakeTransactionCapsule2 = new TransactionCapsule(builder2.build(), ContractType.DelegateResourceContract); long size2 = consumeBandWidthSize(fakeTransactionCapsule2, chainBaseManager); - long addSize = Math.max(size1 - size2, 0L); + long addSize = max(size1 - size2, 0L, true); return DELEGATE_COST_BASE_SIZE + addSize; } @@ -373,8 +374,8 @@ public void estimateConsumeBandWidthSizePositive() { DelegateResourceContract.newBuilder() .setBalance(TRX_PRECISION); - long expected = DELEGATE_COST_BASE_SIZE + Math.max( - builder.build().getSerializedSize() - builder2.build().getSerializedSize(), 0L); + long expected = DELEGATE_COST_BASE_SIZE + max( + builder.build().getSerializedSize() - builder2.build().getSerializedSize(), 0L, true); long actual = TransactionUtil.estimateConsumeBandWidthSize(dps, balance); Assert.assertEquals(expected, actual); } @@ -391,8 +392,8 @@ public void estimateConsumeBandWidthSizeBoundary() { DelegateResourceContract.newBuilder() .setBalance(TRX_PRECISION); - long expected = DELEGATE_COST_BASE_SIZE + Math.max( - builder.build().getSerializedSize() - builder2.build().getSerializedSize(), 0L); + long expected = DELEGATE_COST_BASE_SIZE + max( + builder.build().getSerializedSize() - builder2.build().getSerializedSize(), 0L, true); long actual = TransactionUtil.estimateConsumeBandWidthSize(dps, balance); Assert.assertEquals(expected, actual); } @@ -409,8 +410,8 @@ public void estimateConsumeBandWidthSizeEdge() { DelegateResourceContract.newBuilder() .setBalance(TRX_PRECISION); - long expected = DELEGATE_COST_BASE_SIZE + Math.max( - builder.build().getSerializedSize() - builder2.build().getSerializedSize(), 0L); + long expected = DELEGATE_COST_BASE_SIZE + max( + builder.build().getSerializedSize() - builder2.build().getSerializedSize(), 0L, true); long actual = TransactionUtil.estimateConsumeBandWidthSize(dps, balance); Assert.assertEquals(expected, actual); } @@ -427,8 +428,8 @@ public void estimateConsumeBandWidthSizeCorner() { DelegateResourceContract.newBuilder() .setBalance(TRX_PRECISION); - long expected = DELEGATE_COST_BASE_SIZE + Math.max( - builder.build().getSerializedSize() - builder2.build().getSerializedSize(), 0L); + long expected = DELEGATE_COST_BASE_SIZE + max( + builder.build().getSerializedSize() - builder2.build().getSerializedSize(), 0L, true); long actual = TransactionUtil.estimateConsumeBandWidthSize(dps, balance); Assert.assertEquals(expected, actual); } diff --git a/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java index de72b4be276..0ee0faa550a 100644 --- a/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/AccountCapsuleTest.java @@ -90,7 +90,7 @@ public void AssetAmountTest() { String nameAdd = "TokenX"; long amountAdd = 222L; boolean addBoolean = accountCapsuleTest - .addAssetAmount(nameAdd.getBytes(), amountAdd); + .addAssetAmount(nameAdd.getBytes(), amountAdd, true); Assert.assertTrue(addBoolean); @@ -102,7 +102,7 @@ public void AssetAmountTest() { long amountReduce = 22L; boolean reduceBoolean = accountCapsuleTest - .reduceAssetAmount(ByteArray.fromString("TokenX"), amountReduce); + .reduceAssetAmount(ByteArray.fromString("TokenX"), amountReduce, false); Assert.assertTrue(reduceBoolean); Map assetMapAfter = accountCapsuleTest.getAssetMapForTest(); 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 0465cd2e867..c90ad89abb3 100644 --- a/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/ContractStateCapsuleTest.java @@ -20,12 +20,12 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertFalse(capsule.catchUpToCycle(1000L, 2_000_000L, 2000L, 10_00L, false)); + Assert.assertFalse(capsule.catchUpToCycle(1000L, 2_000_000L, 2000L, 10_00L, false, 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, false)); + Assert.assertTrue(capsule.catchUpToCycle(1010L, 900_000L, 1000L, 10_000L, false, false)); Assert.assertEquals(1010L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(3137L, capsule.getEnergyFactor()); @@ -37,7 +37,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1001L, 2_000_000L, 2000L, 10_000L, false)); + Assert.assertTrue(capsule.catchUpToCycle(1001L, 2_000_000L, 2000L, 10_000L, false, false)); Assert.assertEquals(1001L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(4250L, capsule.getEnergyFactor()); @@ -49,7 +49,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1001L, 1_000_000L, 2000L, 10_000L, false)); + Assert.assertTrue(capsule.catchUpToCycle(1001L, 1_000_000L, 2000L, 10_000L, false, false)); Assert.assertEquals(1001L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(4250L, capsule.getEnergyFactor()); @@ -61,7 +61,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1001L, 900_000L, 2000L, 10_000L, false)); + Assert.assertTrue(capsule.catchUpToCycle(1001L, 900_000L, 2000L, 10_000L, false, false)); Assert.assertEquals(1001L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(8000L, capsule.getEnergyFactor()); @@ -73,7 +73,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1001L, 900_000L, 5000L, 10_000L, false)); + Assert.assertTrue(capsule.catchUpToCycle(1001L, 900_000L, 5000L, 10_000L, false, false)); Assert.assertEquals(1001L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(10_000L, capsule.getEnergyFactor()); @@ -85,7 +85,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1002L, 900_000L, 5000L, 10_000L, false)); + Assert.assertTrue(capsule.catchUpToCycle(1002L, 900_000L, 5000L, 10_000L, false, false)); Assert.assertEquals(1002L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(7500L, capsule.getEnergyFactor()); @@ -97,7 +97,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1003L, 900_000L, 5000L, 10_000L, false)); + Assert.assertTrue(capsule.catchUpToCycle(1003L, 900_000L, 5000L, 10_000L, false, false)); Assert.assertEquals(1003L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(5312L, capsule.getEnergyFactor()); @@ -109,7 +109,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1004L, 900_000L, 5000L, 10_000L, false)); + Assert.assertTrue(capsule.catchUpToCycle(1004L, 900_000L, 5000L, 10_000L, false, false)); Assert.assertEquals(1004L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(3398L, capsule.getEnergyFactor()); @@ -121,7 +121,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1005L, 900_000L, 5000L, 10_000L, true)); + Assert.assertTrue(capsule.catchUpToCycle(1005L, 900_000L, 5000L, 10_000L, true, true)); Assert.assertEquals(1005L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(1723L, capsule.getEnergyFactor()); @@ -133,7 +133,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1005L, 900_000L, 5000L, 10_000L, true)); + Assert.assertTrue(capsule.catchUpToCycle(1005L, 900_000L, 5000L, 10_000L, true, true)); Assert.assertEquals(1005L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(1723L, capsule.getEnergyFactor()); @@ -145,7 +145,7 @@ public void testCatchUpCycle() { .setUpdateCycle(1000L) .build()); - Assert.assertTrue(capsule.catchUpToCycle(1006L, 900_000L, 5000L, 10_000L, true)); + Assert.assertTrue(capsule.catchUpToCycle(1006L, 900_000L, 5000L, 10_000L, true, true)); Assert.assertEquals(1006L, capsule.getUpdateCycle()); Assert.assertEquals(0L, capsule.getEnergyUsage()); Assert.assertEquals(258L, capsule.getEnergyFactor()); diff --git a/framework/src/test/java/org/tron/core/capsule/utils/MerkleTreeTest.java b/framework/src/test/java/org/tron/core/capsule/utils/MerkleTreeTest.java index 910b1adba67..df84433726e 100644 --- a/framework/src/test/java/org/tron/core/capsule/utils/MerkleTreeTest.java +++ b/framework/src/test/java/org/tron/core/capsule/utils/MerkleTreeTest.java @@ -1,5 +1,7 @@ package org.tron.core.capsule.utils; +import static org.tron.common.math.Maths.pow; + import com.google.protobuf.ByteString; import java.nio.charset.StandardCharsets; import java.util.ArrayList; @@ -86,7 +88,7 @@ private static int getRank(int num) { num = num >> 1; rank++; } - if (temp == Math.pow(2, rank - 1)) { + if (temp == pow(2, rank - 1, true)) { rank -= 1; } return rank; 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 e9b79487204..683ac49e8ad 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -5,7 +5,6 @@ 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; import static org.tron.common.utils.Commons.getExchangeStoreFinal; import static org.tron.core.exception.BadBlockException.TypeEnum.CALC_MERKLE_ROOT_FAILED; @@ -36,6 +35,7 @@ import org.tron.common.crypto.ECKey; import org.tron.common.runtime.RuntimeImpl; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Commons; import org.tron.common.utils.JsonUtil; import org.tron.common.utils.LocalWitnesses; import org.tron.common.utils.PublicMethod; @@ -82,6 +82,7 @@ import org.tron.core.exception.ValidateScheduleException; import org.tron.core.exception.ValidateSignatureException; import org.tron.core.exception.ZksnarkException; +import org.tron.core.store.AccountStore; import org.tron.core.store.CodeStore; import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.store.ExchangeStore; @@ -1167,4 +1168,10 @@ public void blockTrigger() { doThrow(new RuntimeException("postBlockTrigger mock")).when(manager).postBlockTrigger(any()); manager.blockTrigger(new BlockCapsule(Block.newBuilder().build()), 1, 1); } + + public void adjustBalance(AccountStore accountStore, byte[] accountAddress, long amount) + throws BalanceInsufficientException { + Commons.adjustBalance(accountStore, accountAddress, amount, + chainManager.getDynamicPropertiesStore().allowStrictMath2()); + } } diff --git a/framework/src/test/java/org/tron/core/db/MarketPairPriceToOrderStoreTest.java b/framework/src/test/java/org/tron/core/db/MarketPairPriceToOrderStoreTest.java index 1f453cb9b41..d74229fb216 100755 --- a/framework/src/test/java/org/tron/core/db/MarketPairPriceToOrderStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/MarketPairPriceToOrderStoreTest.java @@ -1,5 +1,8 @@ package org.tron.core.db; +import static org.tron.common.math.Maths.random; +import static org.tron.common.math.Maths.round; + import java.util.List; import lombok.extern.slf4j.Slf4j; import org.junit.After; @@ -43,7 +46,7 @@ public void cleanDb() { } private static int randomInt(int minInt, int maxInt) { - return (int) Math.round(Math.random() * (maxInt - minInt) + minInt); + return (int) round(random(true) * (maxInt - minInt) + minInt, true); } @Test diff --git a/framework/src/test/java/org/tron/core/jsonrpc/ConcurrentHashMapTest.java b/framework/src/test/java/org/tron/core/jsonrpc/ConcurrentHashMapTest.java index ea0c0354bb0..1de106f68e8 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/ConcurrentHashMapTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/ConcurrentHashMapTest.java @@ -1,5 +1,8 @@ package org.tron.core.jsonrpc; +import static org.tron.common.math.Maths.random; +import static org.tron.common.math.Maths.round; + import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -17,7 +20,7 @@ public class ConcurrentHashMapTest { private static int randomInt(int minInt, int maxInt) { - return (int) Math.round(Math.random() * (maxInt - minInt) + minInt); + return (int) round(random(true) * (maxInt - minInt) + minInt, true); } /** diff --git a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java index 211e7228289..c1b0f8bb507 100644 --- a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java +++ b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java @@ -113,6 +113,7 @@ public void testUpdateConsensusLogicOptimization() { Assert.assertEquals(v, 0); Assert.assertTrue(!dbManager.getDynamicPropertiesStore().allowConsensusLogicOptimization()); Assert.assertFalse(dbManager.getDynamicPropertiesStore().allowWitnessSortOptimization()); + Assert.assertFalse(dbManager.getDynamicPropertiesStore().allowStrictMath2()); long value = 1; Proposal proposal = @@ -127,6 +128,7 @@ public void testUpdateConsensusLogicOptimization() { Assert.assertTrue(dbManager.getDynamicPropertiesStore().allowConsensusLogicOptimization()); Assert.assertTrue(dbManager.getDynamicPropertiesStore().allowWitnessSortOptimization()); + Assert.assertTrue(dbManager.getDynamicPropertiesStore().allowStrictMath2()); } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java b/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java index 67353eb24b1..915742d3f0d 100644 --- a/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/LibrustzcashTest.java @@ -4,6 +4,8 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; +import static org.tron.common.math.Maths.random; +import static org.tron.common.math.Maths.round; import static org.tron.common.zksnark.JLibrustzcash.librustzcashCheckDiversifier; import static org.tron.common.zksnark.JLibrustzcash.librustzcashComputeCm; import static org.tron.common.zksnark.JLibrustzcash.librustzcashIvkToPkd; @@ -87,7 +89,7 @@ public static void init() { } private static int randomInt(int minInt, int maxInt) { - return (int) Math.round(Math.random() * (maxInt - minInt) + minInt); + return (int) round(random(true) * (maxInt - minInt) + minInt, true); } public static void test(byte[] K, byte[] ovk, byte[] cv, byte[] cm, byte[] epk) diff --git a/framework/src/test/java/org/tron/core/zksnark/SaplingNoteTest.java b/framework/src/test/java/org/tron/core/zksnark/SaplingNoteTest.java index 60f6c8c0826..da4df70d9ac 100644 --- a/framework/src/test/java/org/tron/core/zksnark/SaplingNoteTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/SaplingNoteTest.java @@ -1,5 +1,8 @@ package org.tron.core.zksnark; +import static org.tron.common.math.Maths.random; +import static org.tron.common.math.Maths.round; + import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -30,7 +33,7 @@ public static void removeDb() { } private static int randomInt(int minInt, int maxInt) { - return (int) Math.round(Math.random() * (maxInt - minInt) + minInt); + return (int) round(random(true) * (maxInt - minInt) + minInt, true); } @Test diff --git a/plugins/src/main/java/org/tron/plugins/utils/ByteArray.java b/plugins/src/main/java/org/tron/plugins/utils/ByteArray.java index 3422c36ca9d..2922d110b7c 100644 --- a/plugins/src/main/java/org/tron/plugins/utils/ByteArray.java +++ b/plugins/src/main/java/org/tron/plugins/utils/ByteArray.java @@ -59,7 +59,7 @@ public static int compareUnsigned(byte[] a, byte[] b) { if (b == null) { return 1; } - int minLen = Math.min(a.length, b.length); + int minLen = StrictMath.min(a.length, b.length); for (int i = 0; i < minLen; ++i) { int aVal = a[i] & 0xFF; int bVal = b[i] & 0xFF; diff --git a/plugins/src/main/java/org/tron/plugins/utils/DBUtils.java b/plugins/src/main/java/org/tron/plugins/utils/DBUtils.java index 19547e2b5a5..f8559d5dba8 100644 --- a/plugins/src/main/java/org/tron/plugins/utils/DBUtils.java +++ b/plugins/src/main/java/org/tron/plugins/utils/DBUtils.java @@ -95,7 +95,8 @@ private static Options newDefaultRocksDbOptions(boolean forBulkLoad) { options.setTargetFileSizeBase(64 * 1024 * 1024); options.setTargetFileSizeMultiplier(1); options.setMaxBytesForLevelBase(512 * 1024 * 1024); - options.setMaxBackgroundCompactions(Math.max(1, Runtime.getRuntime().availableProcessors())); + options.setMaxBackgroundCompactions(StrictMath.max( + 1, Runtime.getRuntime().availableProcessors())); options.setLevel0FileNumCompactionTrigger(4); options.setLevelCompactionDynamicLevelBytes(true); final BlockBasedTableConfig tableCfg; diff --git a/plugins/src/main/java/org/tron/plugins/utils/MarketUtils.java b/plugins/src/main/java/org/tron/plugins/utils/MarketUtils.java index a36fc8ad57c..dbd578a59a3 100644 --- a/plugins/src/main/java/org/tron/plugins/utils/MarketUtils.java +++ b/plugins/src/main/java/org/tron/plugins/utils/MarketUtils.java @@ -130,8 +130,8 @@ public static int comparePriceKey(byte[] o1, byte[] o2) { public static int comparePrice(long price1SellQuantity, long price1BuyQuantity, long price2SellQuantity, long price2BuyQuantity) { try { - return Long.compare(Math.multiplyExact(price1BuyQuantity, price2SellQuantity), - Math.multiplyExact(price2BuyQuantity, price1SellQuantity)); + return Long.compare(StrictMath.multiplyExact(price1BuyQuantity, price2SellQuantity), + StrictMath.multiplyExact(price2BuyQuantity, price1SellQuantity)); } catch (ArithmeticException ex) { // do nothing here, because we will use BigInteger to compute again