Skip to content

Commit 42a3345

Browse files
Little-Peonyclaude
andcommitted
test(chainbase): add regression tests for newSize==0 in resetAccountUsage
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent f7c7252 commit 42a3345

1 file changed

Lines changed: 90 additions & 0 deletions

File tree

framework/src/test/java/org/tron/core/db/TransactionTraceTest.java

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import com.google.protobuf.Any;
1919
import com.google.protobuf.ByteString;
2020
import com.google.protobuf.InvalidProtocolBufferException;
21+
import java.lang.reflect.Method;
2122
import org.junit.Assert;
2223
import org.junit.Before;
2324
import org.junit.Test;
@@ -300,6 +301,95 @@ public void testTriggerUseUsage()
300301

301302
}
302303

304+
/**
305+
* Regression test for the {@code newSize == 0} guard in {@code resetAccountUsage}.
306+
*
307+
* <p>When {@code mergedSize == currentSize} and {@code size == 0}, {@code newSize} becomes 0.
308+
* Without the guard this would cause an {@link ArithmeticException} (divide by zero).
309+
* The expected outcome is {@code energyUsage = 0} with no exception thrown.
310+
*/
311+
@Test
312+
public void testResetAccountUsageZeroWindowSize() throws Exception {
313+
TriggerSmartContract contract = TriggerSmartContract.newBuilder()
314+
.setContractAddress(contractAddress)
315+
.setOwnerAddress(ownerAddress)
316+
.build();
317+
Transaction transaction = Transaction.newBuilder()
318+
.setRawData(raw.newBuilder()
319+
.addContract(Contract.newBuilder()
320+
.setParameter(Any.pack(contract))
321+
.setType(ContractType.TriggerSmartContract))
322+
.build())
323+
.build();
324+
TransactionTrace trace = new TransactionTrace(
325+
new TransactionCapsule(transaction), StoreFactory.getInstance(), new RuntimeImpl());
326+
327+
AccountCapsule accountCap = new AccountCapsule(Account.newBuilder()
328+
.setAddress(ownerAddress)
329+
.setAccountResource(AccountResource.newBuilder()
330+
.setEnergyUsage(1000L)
331+
.build())
332+
.build());
333+
334+
// A fresh account has EnergyWindowSize=0, so getWindowSize(ENERGY) returns the default
335+
// WINDOW_SIZE_MS / BLOCK_PRODUCED_INTERVAL = 28800.
336+
// Passing mergedSize == currentSize and size == 0 triggers newSize = 0.
337+
final long currentSize = 28800L;
338+
339+
dbManager.getDynamicPropertiesStore().saveAllowCancelAllUnfreezeV2(0);
340+
Method method = TransactionTrace.class.getDeclaredMethod(
341+
"resetAccountUsage",
342+
AccountCapsule.class, long.class, long.class, long.class, long.class, long.class);
343+
method.setAccessible(true);
344+
method.invoke(trace, accountCap, 500L, 0L, 500L, currentSize, 0L);
345+
346+
// newSize == 0 → guard returns 0 instead of dividing → energyUsage reset to 0
347+
Assert.assertEquals(0L, accountCap.getEnergyUsage());
348+
}
349+
350+
/**
351+
* Same regression as above but exercises the {@code resetAccountUsageV2} code path,
352+
* which is activated when {@code supportAllowCancelAllUnfreezeV2} is enabled.
353+
*/
354+
@Test
355+
public void testResetAccountUsageV2ZeroWindowSize() throws Exception {
356+
TriggerSmartContract contract = TriggerSmartContract.newBuilder()
357+
.setContractAddress(contractAddress)
358+
.setOwnerAddress(ownerAddress)
359+
.build();
360+
Transaction transaction = Transaction.newBuilder()
361+
.setRawData(raw.newBuilder()
362+
.addContract(Contract.newBuilder()
363+
.setParameter(Any.pack(contract))
364+
.setType(ContractType.TriggerSmartContract))
365+
.build())
366+
.build();
367+
TransactionTrace trace = new TransactionTrace(
368+
new TransactionCapsule(transaction), StoreFactory.getInstance(), new RuntimeImpl());
369+
370+
AccountCapsule accountCap = new AccountCapsule(Account.newBuilder()
371+
.setAddress(ownerAddress)
372+
.setAccountResource(AccountResource.newBuilder()
373+
.setEnergyUsage(1000L)
374+
.build())
375+
.build());
376+
377+
final long currentSize = 28800L;
378+
379+
dbManager.getDynamicPropertiesStore().saveAllowCancelAllUnfreezeV2(1);
380+
try {
381+
Method method = TransactionTrace.class.getDeclaredMethod(
382+
"resetAccountUsage",
383+
AccountCapsule.class, long.class, long.class, long.class, long.class, long.class);
384+
method.setAccessible(true);
385+
method.invoke(trace, accountCap, 500L, 0L, 500L, currentSize, 0L);
386+
387+
Assert.assertEquals(0L, accountCap.getEnergyUsage());
388+
} finally {
389+
dbManager.getDynamicPropertiesStore().saveAllowCancelAllUnfreezeV2(0);
390+
}
391+
}
392+
303393
private byte[] deployInit(Transaction transaction)
304394
throws VMIllegalException, ContractExeException,
305395
ContractValidateException, BalanceInsufficientException {

0 commit comments

Comments
 (0)