Skip to content

Commit 3aa626f

Browse files
Merge pull request #5290 from yuekun0707/feature/optmize_resource_recovery
fix(freezeV2): optimize resource usage recovery logic
2 parents b6f01fc + 199d473 commit 3aa626f

File tree

10 files changed

+389
-24
lines changed

10 files changed

+389
-24
lines changed

actuator/src/main/java/org/tron/core/actuator/VMActuator.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import static java.lang.Math.min;
55
import static org.apache.commons.lang3.ArrayUtils.getLength;
66
import static org.apache.commons.lang3.ArrayUtils.isNotEmpty;
7+
import static org.tron.protos.contract.Common.ResourceCode.ENERGY;
78

89
import com.google.protobuf.ByteString;
910
import java.math.BigInteger;
@@ -58,7 +59,6 @@
5859
import org.tron.protos.Protocol.Transaction;
5960
import org.tron.protos.Protocol.Transaction.Contract.ContractType;
6061
import org.tron.protos.Protocol.Transaction.Result.contractResult;
61-
import org.tron.protos.contract.Common;
6262
import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract;
6363
import org.tron.protos.contract.SmartContractOuterClass.SmartContract;
6464
import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract;
@@ -568,12 +568,13 @@ public long getAccountEnergyLimitWithFixRatio(AccountCapsule account, long feeLi
568568
energyProcessor.updateUsage(account);
569569
account.setLatestConsumeTimeForEnergy(now);
570570
receipt.setCallerEnergyUsage(account.getEnergyUsage());
571-
receipt.setCallerEnergyWindowSize(account.getWindowSize(Common.ResourceCode.ENERGY));
571+
receipt.setCallerEnergyWindowSize(account.getWindowSize(ENERGY));
572+
receipt.setCallerEnergyWindowSizeV2(account.getWindowSizeV2(ENERGY));
572573
account.setEnergyUsage(
573-
energyProcessor.increase(account, Common.ResourceCode.ENERGY,
574+
energyProcessor.increase(account, ENERGY,
574575
account.getEnergyUsage(), min(leftFrozenEnergy, energyFromFeeLimit), now, now));
575576
receipt.setCallerEnergyMergedUsage(account.getEnergyUsage());
576-
receipt.setCallerEnergyMergedWindowSize(account.getWindowSize(Common.ResourceCode.ENERGY));
577+
receipt.setCallerEnergyMergedWindowSize(account.getWindowSize(ENERGY));
577578
rootRepository.updateAccount(account.createDbKey(), account);
578579
}
579580
return min(availableEnergy, energyFromFeeLimit);
@@ -730,12 +731,13 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu
730731
energyProcessor.updateUsage(creator);
731732
creator.setLatestConsumeTimeForEnergy(now);
732733
receipt.setOriginEnergyUsage(creator.getEnergyUsage());
733-
receipt.setOriginEnergyWindowSize(creator.getWindowSize(Common.ResourceCode.ENERGY));
734+
receipt.setOriginEnergyWindowSize(creator.getWindowSize(ENERGY));
735+
receipt.setOriginEnergyWindowSizeV2(creator.getWindowSizeV2(ENERGY));
734736
creator.setEnergyUsage(
735-
energyProcessor.increase(creator, Common.ResourceCode.ENERGY,
737+
energyProcessor.increase(creator, ENERGY,
736738
creator.getEnergyUsage(), creatorEnergyLimit, now, now));
737739
receipt.setOriginEnergyMergedUsage(creator.getEnergyUsage());
738-
receipt.setOriginEnergyMergedWindowSize(creator.getWindowSize(Common.ResourceCode.ENERGY));
740+
receipt.setOriginEnergyMergedWindowSize(creator.getWindowSize(ENERGY));
739741
rootRepository.updateAccount(creator.createDbKey(), creator);
740742
}
741743
return Math.addExact(callerEnergyLimit, creatorEnergyLimit);

chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,10 @@
4242
import java.util.Map;
4343
import java.util.Objects;
4444

45+
import static java.lang.Math.ceil;
4546
import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL;
4647
import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_MS;
48+
import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_PRECISION;
4749
import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH;
4850
import static org.tron.protos.contract.Common.ResourceCode.ENERGY;
4951
import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER;
@@ -1369,12 +1371,62 @@ public void setNewWindowSize(ResourceCode resourceCode, long newWindowSize) {
13691371

13701372
public long getWindowSize(ResourceCode resourceCode) {
13711373
long windowSize;
1374+
boolean windowOptimized;
13721375
if (resourceCode == BANDWIDTH) {
13731376
windowSize = this.account.getNetWindowSize();
1377+
windowOptimized = this.account.getNetWindowOptimized();
13741378
} else {
13751379
windowSize = this.account.getAccountResource().getEnergyWindowSize();
1380+
windowOptimized = this.account.getAccountResource().getEnergyWindowOptimized();
1381+
}
1382+
if (windowSize == 0) {
1383+
return WINDOW_SIZE_MS / BLOCK_PRODUCED_INTERVAL;
1384+
}
1385+
if (windowOptimized) {
1386+
return windowSize < WINDOW_SIZE_PRECISION ? WINDOW_SIZE_MS / BLOCK_PRODUCED_INTERVAL :
1387+
windowSize / WINDOW_SIZE_PRECISION;
1388+
} else {
1389+
return windowSize;
1390+
}
1391+
}
1392+
1393+
public long getWindowSizeV2(ResourceCode resourceCode) {
1394+
long windowSize;
1395+
boolean windowOptimized;
1396+
if (resourceCode == BANDWIDTH) {
1397+
windowSize = this.account.getNetWindowSize();
1398+
windowOptimized = this.account.getNetWindowOptimized();
1399+
} else {
1400+
windowSize = this.account.getAccountResource().getEnergyWindowSize();
1401+
windowOptimized = this.account.getAccountResource().getEnergyWindowOptimized();
1402+
}
1403+
if (windowSize == 0) {
1404+
return WINDOW_SIZE_MS / BLOCK_PRODUCED_INTERVAL * WINDOW_SIZE_PRECISION;
1405+
}
1406+
if (windowOptimized) {
1407+
return windowSize;
1408+
} else {
1409+
return windowSize * WINDOW_SIZE_PRECISION;
1410+
}
1411+
}
1412+
1413+
public boolean getWindowOptimized(ResourceCode resourceCode) {
1414+
boolean windowOptimized;
1415+
if (resourceCode == BANDWIDTH) {
1416+
windowOptimized = this.account.getNetWindowOptimized();
1417+
} else {
1418+
windowOptimized = this.account.getAccountResource().getEnergyWindowOptimized();
1419+
}
1420+
return windowOptimized;
1421+
}
1422+
1423+
public void setWindowOptimized(ResourceCode resourceCode, boolean windowOptimized) {
1424+
if (resourceCode == BANDWIDTH) {
1425+
this.account = this.account.toBuilder().setNetWindowOptimized(windowOptimized).build();
1426+
} else {
1427+
this.account = this.account.toBuilder().setAccountResource(this.account.getAccountResource()
1428+
.toBuilder().setEnergyWindowOptimized(windowOptimized).build()).build();
13761429
}
1377-
return windowSize == 0 ? WINDOW_SIZE_MS / BLOCK_PRODUCED_INTERVAL : windowSize;
13781430
}
13791431

13801432
public long getLastConsumeTime(ResourceCode resourceCode) {
@@ -1393,4 +1445,11 @@ public long getFrozenV2BalanceWithDelegated(ResourceCode resourceCode) {
13931445
}
13941446
}
13951447

1448+
public void setNewWindowSizeV2( ResourceCode resourceCode, long newWindowSize) {
1449+
this.setNewWindowSize(resourceCode, newWindowSize);
1450+
if (!this.getWindowOptimized(resourceCode)) {
1451+
this.setWindowOptimized(resourceCode, true);
1452+
}
1453+
}
1454+
13961455
}

chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ public class ReceiptCapsule {
6969
@Setter
7070
private long callerEnergyWindowSize;
7171

72+
@Getter
73+
@Setter
74+
private long callerEnergyWindowSizeV2;
75+
7276
/**
7377
* Window size of caller after merging frozen energy
7478
*/
@@ -83,6 +87,10 @@ public class ReceiptCapsule {
8387
@Setter
8488
private long originEnergyWindowSize;
8589

90+
@Getter
91+
@Setter
92+
private long originEnergyWindowSizeV2;
93+
8694
/**
8795
* Window size of origin after merging frozen energy
8896
*/

chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java

Lines changed: 82 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package org.tron.core.db;
22

3+
import static java.lang.Math.ceil;
4+
import static java.lang.Math.round;
35
import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL;
6+
import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_PRECISION;
47

58
import org.tron.common.utils.Commons;
69
import org.tron.core.capsule.AccountCapsule;
@@ -59,13 +62,16 @@ protected long increase(long lastUsage, long usage, long lastTime, long now, lon
5962
}
6063

6164
public long recovery(AccountCapsule accountCapsule, ResourceCode resourceCode,
62-
long lastUsage, long lastTime, long now) {
65+
long lastUsage, long lastTime, long now) {
6366
long oldWindowSize = accountCapsule.getWindowSize(resourceCode);
6467
return increase(lastUsage, 0, lastTime, now, oldWindowSize);
6568
}
6669

6770
public long increase(AccountCapsule accountCapsule, ResourceCode resourceCode,
68-
long lastUsage, long usage, long lastTime, long now) {
71+
long lastUsage, long usage, long lastTime, long now) {
72+
if (dynamicPropertiesStore.supportAllowCancelAllUnfreezeV2()) {
73+
return increaseV2(accountCapsule, resourceCode, lastUsage, usage, lastTime, now);
74+
}
6975
long oldWindowSize = accountCapsule.getWindowSize(resourceCode);
7076
long averageLastUsage = divideCeil(lastUsage * this.precision, oldWindowSize);
7177
long averageUsage = divideCeil(usage * this.precision, this.windowSize);
@@ -88,15 +94,50 @@ public long increase(AccountCapsule accountCapsule, ResourceCode resourceCode,
8894
return newUsage;
8995
}
9096
long remainWindowSize = oldWindowSize - (now - lastTime);
91-
long newWindowSize = (remainWindowSize * remainUsage + this.windowSize * usage)
92-
/ newUsage;
97+
long newWindowSize = getNewWindowSize(remainUsage, remainWindowSize, usage,
98+
windowSize, newUsage);
9399
accountCapsule.setNewWindowSize(resourceCode, newWindowSize);
94100
}
95101
return newUsage;
96102
}
97103

104+
public long increaseV2(AccountCapsule accountCapsule, ResourceCode resourceCode,
105+
long lastUsage, long usage, long lastTime, long now) {
106+
long oldWindowSizeV2 = accountCapsule.getWindowSizeV2(resourceCode);
107+
long oldWindowSize = accountCapsule.getWindowSize(resourceCode);
108+
long averageLastUsage = divideCeil(lastUsage * this.precision, oldWindowSize);
109+
long averageUsage = divideCeil(usage * this.precision, this.windowSize);
110+
111+
if (lastTime != now) {
112+
if (lastTime + oldWindowSize > now) {
113+
long delta = now - lastTime;
114+
double decay = (oldWindowSize - delta) / (double) oldWindowSize;
115+
averageLastUsage = Math.round(averageLastUsage * decay);
116+
} else {
117+
averageLastUsage = 0;
118+
}
119+
}
120+
121+
long newUsage = getUsage(averageLastUsage, oldWindowSize, averageUsage, this.windowSize);
122+
long remainUsage = getUsage(averageLastUsage, oldWindowSize);
123+
if (remainUsage == 0) {
124+
accountCapsule.setNewWindowSizeV2(resourceCode, this.windowSize * WINDOW_SIZE_PRECISION);
125+
return newUsage;
126+
}
127+
128+
long remainWindowSize = oldWindowSizeV2 - (now - lastTime) * WINDOW_SIZE_PRECISION;
129+
long newWindowSize = divideCeil(
130+
remainUsage * remainWindowSize + usage * this.windowSize * WINDOW_SIZE_PRECISION, newUsage);
131+
newWindowSize = Math.min(newWindowSize, this.windowSize * WINDOW_SIZE_PRECISION);
132+
accountCapsule.setNewWindowSizeV2(resourceCode, newWindowSize);
133+
return newUsage;
134+
}
135+
98136
public long unDelegateIncrease(AccountCapsule owner, final AccountCapsule receiver,
99-
long transferUsage, ResourceCode resourceCode, long now) {
137+
long transferUsage, ResourceCode resourceCode, long now) {
138+
if (dynamicPropertiesStore.supportAllowCancelAllUnfreezeV2()) {
139+
return unDelegateIncreaseV2(owner, receiver, transferUsage, resourceCode, now);
140+
}
100141
long lastOwnerTime = owner.getLastConsumeTime(resourceCode);
101142
long ownerUsage = owner.getUsage(resourceCode);
102143
// Update itself first
@@ -110,17 +151,49 @@ public long unDelegateIncrease(AccountCapsule owner, final AccountCapsule receiv
110151
long newOwnerUsage = ownerUsage + transferUsage;
111152
// mean ownerUsage == 0 and transferUsage == 0
112153
if (newOwnerUsage == 0) {
113-
owner.setNewWindowSize(resourceCode, this.windowSize);
154+
owner.setNewWindowSize(resourceCode, this.windowSize);
114155
return newOwnerUsage;
115156
}
116157
// calculate new windowSize
117-
long newOwnerWindowSize = (ownerUsage * remainOwnerWindowSize +
118-
transferUsage * remainReceiverWindowSize)
119-
/ newOwnerUsage;
158+
long newOwnerWindowSize = getNewWindowSize(ownerUsage, remainOwnerWindowSize, transferUsage,
159+
remainReceiverWindowSize, newOwnerUsage);
120160
owner.setNewWindowSize(resourceCode, newOwnerWindowSize);
121161
return newOwnerUsage;
122162
}
123163

164+
public long unDelegateIncreaseV2(AccountCapsule owner, final AccountCapsule receiver,
165+
long transferUsage, ResourceCode resourceCode, long now) {
166+
long lastOwnerTime = owner.getLastConsumeTime(resourceCode);
167+
long ownerUsage = owner.getUsage(resourceCode);
168+
// Update itself first
169+
ownerUsage = increase(owner, resourceCode, ownerUsage, 0, lastOwnerTime, now);
170+
long newOwnerUsage = ownerUsage + transferUsage;
171+
// mean ownerUsage == 0 and transferUsage == 0
172+
if (newOwnerUsage == 0) {
173+
owner.setNewWindowSizeV2(resourceCode, this.windowSize * WINDOW_SIZE_PRECISION);
174+
return newOwnerUsage;
175+
}
176+
177+
long remainOwnerWindowSizeV2 = owner.getWindowSizeV2(resourceCode);
178+
long remainReceiverWindowSizeV2 = receiver.getWindowSizeV2(resourceCode);
179+
remainOwnerWindowSizeV2 = remainOwnerWindowSizeV2 < 0 ? 0 : remainOwnerWindowSizeV2;
180+
remainReceiverWindowSizeV2 = remainReceiverWindowSizeV2 < 0 ? 0 : remainReceiverWindowSizeV2;
181+
182+
// calculate new windowSize
183+
long newOwnerWindowSize =
184+
divideCeil(
185+
ownerUsage * remainOwnerWindowSizeV2 + transferUsage * remainReceiverWindowSizeV2,
186+
newOwnerUsage);
187+
newOwnerWindowSize = Math.min(newOwnerWindowSize, this.windowSize * WINDOW_SIZE_PRECISION);
188+
owner.setNewWindowSizeV2(resourceCode, newOwnerWindowSize);
189+
return newOwnerUsage;
190+
}
191+
192+
private long getNewWindowSize(long lastUsage, long lastWindowSize, long usage,
193+
long windowSize, long newUsage) {
194+
return (lastUsage * lastWindowSize + usage * windowSize) / newUsage;
195+
}
196+
124197
private long divideCeil(long numerator, long denominator) {
125198
return (numerator / denominator) + ((numerator % denominator) > 0 ? 1 : 0);
126199
}

chainbase/src/main/java/org/tron/core/db/TransactionTrace.java

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import static org.tron.common.runtime.InternalTransaction.TrxType.TRX_CONTRACT_CALL_TYPE;
44
import static org.tron.common.runtime.InternalTransaction.TrxType.TRX_CONTRACT_CREATION_TYPE;
5+
import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_PRECISION;
6+
import static org.tron.protos.contract.Common.ResourceCode.ENERGY;
57

68
import java.util.Objects;
79
import lombok.Getter;
@@ -263,14 +265,16 @@ && getRuntimeResult().getException() == null && !getRuntimeResult().isRevert())
263265
receipt.getOriginEnergyUsage(),
264266
receipt.getOriginEnergyWindowSize(),
265267
receipt.getOriginEnergyMergedUsage(),
266-
receipt.getOriginEnergyMergedWindowSize());
268+
receipt.getOriginEnergyMergedWindowSize(),
269+
receipt.getOriginEnergyWindowSizeV2());
267270
}
268271

269272
resetAccountUsage(caller,
270273
receipt.getCallerEnergyUsage(),
271274
receipt.getCallerEnergyWindowSize(),
272275
receipt.getCallerEnergyMergedUsage(),
273-
receipt.getCallerEnergyMergedWindowSize());
276+
receipt.getCallerEnergyMergedWindowSize(),
277+
receipt.getCallerEnergyWindowSizeV2());
274278
}
275279
receipt.payEnergyBill(
276280
dynamicPropertiesStore, accountStore, forkController,
@@ -282,8 +286,12 @@ && getRuntimeResult().getException() == null && !getRuntimeResult().isRevert())
282286
}
283287

284288
private void resetAccountUsage(AccountCapsule accountCap,
285-
long usage, long size, long mergedUsage, long mergedSize) {
286-
long currentSize = accountCap.getWindowSize(Common.ResourceCode.ENERGY);
289+
long usage, long size, long mergedUsage, long mergedSize, long size2) {
290+
if (dynamicPropertiesStore.supportAllowCancelAllUnfreezeV2()) {
291+
resetAccountUsageV2(accountCap, usage, size, mergedUsage, mergedSize, size2);
292+
return;
293+
}
294+
long currentSize = accountCap.getWindowSize(ENERGY);
287295
long currentUsage = accountCap.getEnergyUsage();
288296
// Drop the pre consumed frozen energy
289297
long newArea = currentUsage * currentSize
@@ -294,8 +302,24 @@ private void resetAccountUsage(AccountCapsule accountCap,
294302
long newUsage = Long.max(0, newArea / newSize);
295303
// Reset account usage and window size
296304
accountCap.setEnergyUsage(newUsage);
297-
accountCap.setNewWindowSize(Common.ResourceCode.ENERGY,
298-
newUsage == 0 ? 0L : newSize);
305+
accountCap.setNewWindowSize(ENERGY, newUsage == 0 ? 0L : newSize);
306+
}
307+
308+
private void resetAccountUsageV2(AccountCapsule accountCap,
309+
long usage, long size, long mergedUsage, long mergedSize, long size2) {
310+
long currentSize = accountCap.getWindowSize(ENERGY);
311+
long currentSize2 = accountCap.getWindowSizeV2(ENERGY);
312+
long currentUsage = accountCap.getEnergyUsage();
313+
// Drop the pre consumed frozen energy
314+
long newArea = currentUsage * currentSize - (mergedUsage * mergedSize - usage * size);
315+
// If area merging happened during suicide, use the current window size
316+
long newSize = mergedSize == currentSize ? size : currentSize;
317+
long newSize2 = mergedSize == currentSize ? size2 : currentSize2;
318+
// Calc new usage by fixed x-axes
319+
long newUsage = Long.max(0, newArea / newSize);
320+
// Reset account usage and window size
321+
accountCap.setEnergyUsage(newUsage);
322+
accountCap.setNewWindowSizeV2(ENERGY, newUsage == 0 ? 0L : newSize2);
299323
}
300324

301325
public boolean checkNeedRetry() {
@@ -354,7 +378,7 @@ public void deleteContract(byte[] address) {
354378
public static byte[] convertToTronAddress(byte[] address) {
355379
if (address.length == 20) {
356380
byte[] newAddress = new byte[21];
357-
byte[] temp = new byte[]{DecodeUtil.addressPreFixByte};
381+
byte[] temp = new byte[] {DecodeUtil.addressPreFixByte};
358382
System.arraycopy(temp, 0, newAddress, 0, temp.length);
359383
System.arraycopy(address, 0, newAddress, temp.length, address.length);
360384
address = newAddress;

common/src/main/java/org/tron/core/config/Parameter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public class ChainConstant {
7676
public static final long DELEGATE_PERIOD = 3 * 86_400_000L;
7777
public static final long TRX_PRECISION = 1000_000L;
7878
public static final long DELEGATE_COST_BASE_SIZE = 275L;
79+
public static final long WINDOW_SIZE_PRECISION = 1000L;
7980
}
8081

8182
public class NodeConstant {

0 commit comments

Comments
 (0)