Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(math): migrate all operations from Math to strictMath #64

Merged
merged 1 commit into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions .github/workflows/math-check.yml
Original file line number Diff line number Diff line change
@@ -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 /(?<![\w\.])(?<!Strict)Math\s*\./;
print "$ARGV\n" if $hasMath;
' "$file" >> 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
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.tron.core.actuator;

import static java.util.stream.Collectors.toList;
import static org.tron.common.math.StrictMathWrapper.addExact;

import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
Expand Down Expand Up @@ -111,7 +112,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());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.tron.core.actuator;

import static org.tron.common.math.StrictMathWrapper.floorDiv;
import static org.tron.common.math.StrictMathWrapper.multiplyExact;
import static org.tron.core.capsule.utils.TransactionUtil.isNumber;
import static org.tron.core.config.Parameter.ChainSymbol.TRX_SYMBOL_BYTES;

Expand All @@ -24,7 +26,6 @@
import org.tron.core.store.DynamicPropertiesStore;
import org.tron.core.store.ExchangeStore;
import org.tron.core.store.ExchangeV2Store;
import org.tron.core.utils.TransactionUtil;
import org.tron.protos.Protocol.Transaction.Contract.ContractType;
import org.tron.protos.Protocol.Transaction.Result.code;
import org.tron.protos.contract.ExchangeContract.ExchangeInjectContract;
Expand Down Expand Up @@ -71,14 +72,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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

package org.tron.core.actuator;

import static org.tron.common.math.StrictMathWrapper.addExact;
import static org.tron.common.math.StrictMathWrapper.subtractExact;
import static org.tron.core.actuator.ActuatorConstant.CONTRACT_NOT_EXIST;
import static org.tron.core.actuator.ActuatorConstant.STORE_NOT_EXIST;
import static org.tron.core.actuator.ActuatorConstant.TX_RESULT_NULL;
Expand Down Expand Up @@ -244,7 +246,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 {
Expand Down Expand Up @@ -447,7 +449,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
Expand Down Expand Up @@ -475,7 +477,7 @@ private void matchSingleOrder(MarketOrderCapsule takerOrderCapsule,
return;
} else {
makerOrderCapsule.setSellTokenQuantityRemain(0);
takerOrderCapsule.setSellTokenQuantityRemain(Math.subtractExact(
takerOrderCapsule.setSellTokenQuantityRemain(subtractExact(
takerOrderCapsule.getSellTokenQuantityRemain(), makerBuyTokenQuantityReceive));
}
}
Expand Down Expand Up @@ -524,7 +526,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);
Expand All @@ -537,7 +540,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);
Expand All @@ -550,7 +553,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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@

package org.tron.core.actuator;

import static org.tron.common.math.StrictMathWrapper.addExact;
import static org.tron.common.math.StrictMathWrapper.floorDiv;
import static org.tron.common.math.StrictMathWrapper.multiplyExact;
import static org.tron.common.math.StrictMathWrapper.subtractExact;

import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import java.util.Arrays;
Expand Down Expand Up @@ -64,8 +69,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();

Expand All @@ -74,14 +79,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 !");
}
Expand Down Expand Up @@ -156,7 +161,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 !");
}

Expand All @@ -181,8 +186,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!");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.tron.core.actuator;

import static org.tron.common.math.StrictMathWrapper.addExact;
import static org.tron.common.math.StrictMathWrapper.subtractExact;
import static org.tron.core.capsule.TransactionCapsule.getShieldTransactionHashIgnoreTypeException;
import static org.tron.core.utils.ZenChainParams.ZC_ENCCIPHERTEXT_SIZE;
import static org.tron.core.utils.ZenChainParams.ZC_OUTCIPHERTEXT_SIZE;
Expand Down Expand Up @@ -96,9 +98,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);
Expand Down Expand Up @@ -327,9 +329,11 @@ private void checkProof(List<SpendDescription> 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);
Expand Down Expand Up @@ -452,7 +456,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());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.tron.core.actuator;

import static org.tron.common.math.StrictMathWrapper.addExact;
import static org.tron.core.config.Parameter.ChainConstant.TRANSFER_FEE;

import com.google.protobuf.ByteString;
Expand Down Expand Up @@ -58,7 +59,7 @@ public boolean execute(Object object) throws ContractExeException {
fee = fee + dynamicStore.getCreateNewAccountFeeInSystemContract();
}

Commons.adjustBalance(accountStore, ownerAddress, -(Math.addExact(fee, amount)));
Commons.adjustBalance(accountStore, ownerAddress, -(addExact(fee, amount)));
if (dynamicStore.supportBlackHoleOptimization()) {
dynamicStore.burnTrx(fee);
} else {
Expand Down Expand Up @@ -156,15 +157,15 @@ 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(
"Validate TransferContract error, balance is not sufficient.");
}

if (toAccount != null) {
Math.addExact(toAccount.getBalance(), amount);
addExact(toAccount.getBalance(), amount);
}
} catch (ArithmeticException e) {
logger.debug(e.getMessage(), e);
Expand Down
Loading
Loading