88
99import com .google .common .collect .HashBasedTable ;
1010import com .google .protobuf .ByteString ;
11+ import java .math .BigInteger ;
1112import java .util .HashMap ;
1213import java .util .HashSet ;
1314import java .util .Optional ;
1718import org .bouncycastle .util .Strings ;
1819import org .bouncycastle .util .encoders .Hex ;
1920import org .tron .common .crypto .Hash ;
21+ import org .tron .common .math .StrictMathWrapper ;
2022import org .tron .common .parameter .CommonParameter ;
2123import org .tron .common .runtime .vm .DataWord ;
2224import org .tron .common .utils .ByteArray ;
@@ -223,7 +225,7 @@ public Pair<Long, Long> getAccountEnergyUsageBalanceAndRestoreSeconds(AccountCap
223225 long totalEnergyLimit = getDynamicPropertiesStore ().getTotalEnergyCurrentLimit ();
224226 long totalEnergyWeight = getTotalEnergyWeight ();
225227
226- long balance = ( long ) (( double ) newEnergyUsage * totalEnergyWeight / totalEnergyLimit * TRX_PRECISION );
228+ long balance = usageToBalance ( newEnergyUsage , totalEnergyWeight , totalEnergyLimit );
227229
228230 return Pair .of (balance , restoreSlots * BLOCK_PRODUCED_INTERVAL / 1_000 );
229231 }
@@ -246,11 +248,22 @@ public Pair<Long, Long> getAccountNetUsageBalanceAndRestoreSeconds(AccountCapsul
246248 long totalNetLimit = getDynamicPropertiesStore ().getTotalNetLimit ();
247249 long totalNetWeight = getTotalNetWeight ();
248250
249- long balance = ( long ) (( double ) newNetUsage * totalNetWeight / totalNetLimit * TRX_PRECISION );
251+ long balance = usageToBalance ( newNetUsage , totalNetWeight , totalNetLimit );
250252
251253 return Pair .of (balance , restoreSlots * BLOCK_PRODUCED_INTERVAL / 1_000 );
252254 }
253255
256+ private long usageToBalance (long usage , long totalWeight , long totalLimit ) {
257+ if (hardenResourceCalculation ()) {
258+ return BigInteger .valueOf (usage )
259+ .multiply (BigInteger .valueOf (totalWeight ))
260+ .multiply (BigInteger .valueOf (TRX_PRECISION ))
261+ .divide (BigInteger .valueOf (totalLimit ))
262+ .longValueExact ();
263+ }
264+ return (long ) ((double ) usage * totalWeight / totalLimit * TRX_PRECISION );
265+ }
266+
254267 @ Override
255268 public AssetIssueCapsule getAssetIssue (byte [] tokenId ) {
256269 byte [] tokenIdWithoutLeadingZero = ByteUtil .stripLeadingZeroes (tokenId );
@@ -896,8 +909,19 @@ private long recover(long lastUsage, long lastTime, long now, long personalWindo
896909 }
897910
898911 private long increase (long lastUsage , long usage , long lastTime , long now , long windowSize ) {
899- long averageLastUsage = divideCeil (lastUsage * precision , windowSize );
900- long averageUsage = divideCeil (usage * precision , windowSize );
912+ long averageLastUsage ;
913+ long averageUsage ;
914+ if (hardenResourceCalculation ()) {
915+ BigInteger biPrecision = BigInteger .valueOf (precision );
916+ BigInteger biWindowSize = BigInteger .valueOf (windowSize );
917+ averageLastUsage = divideCeilExact (
918+ BigInteger .valueOf (lastUsage ).multiply (biPrecision ), biWindowSize );
919+ averageUsage = divideCeilExact (
920+ BigInteger .valueOf (usage ).multiply (biPrecision ), biWindowSize );
921+ } else {
922+ averageLastUsage = divideCeil (lastUsage * precision , windowSize );
923+ averageUsage = divideCeil (usage * precision , windowSize );
924+ }
901925
902926 if (lastTime != now ) {
903927 assert now > lastTime ;
@@ -917,21 +941,46 @@ private long divideCeil(long numerator, long denominator) {
917941 return (numerator / denominator ) + ((numerator % denominator ) > 0 ? 1 : 0 );
918942 }
919943
944+ private long divideCeilExact (BigInteger numerator , BigInteger denominator ) {
945+ BigInteger [] divRem = numerator .divideAndRemainder (denominator );
946+ long result = divRem [0 ].longValueExact ();
947+ if (divRem [1 ].signum () > 0 ) {
948+ result = StrictMathWrapper .addExact (result , 1 );
949+ }
950+ return result ;
951+ }
952+
920953 private long getUsage (long usage , long windowSize ) {
954+ if (hardenResourceCalculation ()) {
955+ return BigInteger .valueOf (usage )
956+ .multiply (BigInteger .valueOf (windowSize ))
957+ .divide (BigInteger .valueOf (precision ))
958+ .longValueExact ();
959+ }
921960 return usage * windowSize / precision ;
922961 }
923962
963+ private boolean hardenResourceCalculation () {
964+ return VMConfig .allowHardenResourceCalculation ();
965+ }
966+
924967 public long calculateGlobalEnergyLimit (AccountCapsule accountCapsule ) {
925968 long frozeBalance = accountCapsule .getAllFrozenBalanceForEnergy ();
926- if (frozeBalance < 1_000_000L ) {
969+ if (frozeBalance < precision ) {
927970 return 0 ;
928971 }
929- long energyWeight = frozeBalance / 1_000_000L ;
972+ long energyWeight = frozeBalance / precision ;
930973 long totalEnergyLimit = getDynamicPropertiesStore ().getTotalEnergyCurrentLimit ();
931974 long totalEnergyWeight = getDynamicPropertiesStore ().getTotalEnergyWeight ();
932975
933976 assert totalEnergyWeight > 0 ;
934977
978+ if (hardenResourceCalculation ()) {
979+ return BigInteger .valueOf (energyWeight )
980+ .multiply (BigInteger .valueOf (totalEnergyLimit )
981+ .divide (BigInteger .valueOf (totalEnergyWeight )))
982+ .longValueExact ();
983+ }
935984 return (long ) (energyWeight * ((double ) totalEnergyLimit / totalEnergyWeight ));
936985 }
937986
0 commit comments