Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.tron.core.vm.VMConstant;
import org.tron.core.vm.nativecontract.param.CancelAllUnfreezeV2Param;
import org.tron.core.vm.repository.Repository;
import org.tron.core.vm.utils.MUtil;
import org.tron.protos.Protocol;

@Slf4j(topic = "VMProcessor")
Expand All @@ -39,6 +40,10 @@ public void validate(CancelAllUnfreezeV2Param param, Repository repo) throws Con
throw new ContractValidateException(
ACCOUNT_EXCEPTION_STR + readableOwnerAddress + NOT_EXIST_STR);
}

if (accountCapsule.hasInvalidDelegatedV2()) {
MUtil.checkCPUTimeForInvalidDelegatedV2Balance();
}
}

public Map<String, Long> execute(CancelAllUnfreezeV2Param param, Repository repo) throws ContractExeException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.tron.core.store.DynamicPropertiesStore;
import org.tron.core.vm.nativecontract.param.FreezeBalanceV2Param;
import org.tron.core.vm.repository.Repository;
import org.tron.core.vm.utils.MUtil;

@Slf4j(topic = "VMProcessor")
public class FreezeBalanceV2Processor {
Expand Down Expand Up @@ -63,6 +64,10 @@ public void validate(FreezeBalanceV2Param param, Repository repo) throws Contrac
"Unknown ResourceCode, valid ResourceCode[BANDWIDTH、ENERGY]");
}
}

if (repo.isSelfDestructed(ownerAddress)) {
MUtil.checkCPUTimeForFreezeV2AfterSelfDestruct();
}
}

public void execute(FreezeBalanceV2Param param, Repository repo) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.tron.core.vm.config.VMConfig;
import org.tron.core.vm.nativecontract.param.UnfreezeBalanceV2Param;
import org.tron.core.vm.repository.Repository;
import org.tron.core.vm.utils.MUtil;
import org.tron.core.vm.utils.VoteRewardUtil;
import org.tron.protos.Protocol;
import org.tron.protos.contract.Common;
Expand Down Expand Up @@ -86,6 +87,10 @@ public void validate(UnfreezeBalanceV2Param param, Repository repo)
throw new ContractValidateException(
"Invalid unfreeze_balance, [" + param.getUnfreezeBalance() + "] is invalid");
}

if (accountCapsule.hasInvalidDelegatedV2()) {
MUtil.checkCPUTimeForInvalidDelegatedV2Balance();
}
}

private boolean checkUnfreezeBalance(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.tron.core.store.DynamicPropertiesStore;
import org.tron.core.vm.nativecontract.param.WithdrawExpireUnfreezeParam;
import org.tron.core.vm.repository.Repository;
import org.tron.core.vm.utils.MUtil;
import org.tron.protos.Protocol;

@Slf4j(topic = "VMProcessor")
Expand Down Expand Up @@ -52,6 +53,10 @@ public void validate(WithdrawExpireUnfreezeParam param, Repository repo) throws
logger.debug(e.getMessage(), e);
throw new ContractValidateException(e.getMessage());
}

if (accountCapsule.hasInvalidDelegatedV2()) {
MUtil.checkCPUTimeForInvalidDelegatedV2Balance();
}
}

private long getTotalWithdrawUnfreeze(List<Protocol.Account.UnFreezeV2> unfrozenV2List, long now) {
Expand Down
10 changes: 10 additions & 0 deletions actuator/src/main/java/org/tron/core/vm/program/ContractState.java
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,16 @@ public boolean isNewContract(byte[] address) {
return repository.isNewContract(address);
}

@Override
public void markSelfDestruct(byte[] address) {
repository.markSelfDestruct(address);
}

@Override
public boolean isSelfDestructed(byte[] address) {
return repository.isSelfDestructed(address);
}

@Override
public void updateAccount(byte[] address, AccountCapsule accountCapsule) {
repository.updateAccount(address, accountCapsule);
Expand Down
11 changes: 10 additions & 1 deletion actuator/src/main/java/org/tron/core/vm/program/Program.java
Original file line number Diff line number Diff line change
Expand Up @@ -512,12 +512,18 @@ public void suicide(DataWord obtainerAddress) {
internalTx.setValue(internalTx.getValue() + expireUnfrozenBalance);
}
}

getContractState().markSelfDestruct(owner);
getResult().addDeleteAccount(this.getContractAddress());
}

public void suicide2(DataWord obtainerAddress) {

byte[] owner = getContextAddress();

if (getContractState().isSelfDestructed(obtainerAddress.toTronAddress())) {
MUtil.checkCPUTimeForSelfDestructedBeneficiary();
}

boolean isNewContract = getContractState().isNewContract(owner);
if (isNewContract) {
suicide(obtainerAddress);
Expand All @@ -540,6 +546,7 @@ public void suicide2(DataWord obtainerAddress) {
"suicide", nonce, getContractState().getAccount(owner).getAssetMapV2());

if (FastByteComparisons.isEqual(owner, obtainer)) {
getContractState().markSelfDestruct(owner);
return;
}

Expand Down Expand Up @@ -579,6 +586,8 @@ public void suicide2(DataWord obtainerAddress) {
internalTx.setValue(internalTx.getValue() + expireUnfrozenBalance);
}
}

getContractState().markSelfDestruct(owner);
}

public Repository getContractState() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ public interface Repository {

boolean isNewContract(byte[] address);

void markSelfDestruct(byte[] address);

boolean isSelfDestructed(byte[] address);

void updateAccount(byte[] address, AccountCapsule accountCapsule);

void updateDynamicProperty(byte[] word, BytesCapsule bytesCapsule);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ public class RepositoryImpl implements Repository {
private final HashMap<Key, Value<DelegatedResourceAccountIndex>> delegatedResourceAccountIndexCache = new HashMap<>();
private final HashBasedTable<Key, Key, Value<byte[]>> transientStorage = HashBasedTable.create();
private final HashSet<Key> newContractCache = new HashSet<>();
private final HashSet<Key> selfDestructCache = new HashSet<>();

public static void removeLruCache(byte[] address) {
}
Expand Down Expand Up @@ -572,6 +573,29 @@ public boolean isNewContract(byte[] address) {
}
}

@Override
public void markSelfDestruct(byte[] address) {
selfDestructCache.add(Key.create(address));
}

@Override
public boolean isSelfDestructed(byte[] address) {
Key key = Key.create(address);
if (selfDestructCache.contains(key)) {
return true;
}

if (parent != null) {
boolean isSelfDestructed = parent.isSelfDestructed(address);
if (isSelfDestructed) {
selfDestructCache.add(key);
}
return isSelfDestructed;
} else {
return false;
}
}

@Override
public void updateAccount(byte[] address, AccountCapsule accountCapsule) {
accountCache.put(Key.create(address),
Expand Down Expand Up @@ -780,6 +804,7 @@ public void commit() {
commitDelegatedResourceAccountIndexCache(repository);
commitTransientStorage(repository);
commitNewContractCache(repository);
commitSelfDestructCache(repository);
}

@Override
Expand Down Expand Up @@ -1142,6 +1167,12 @@ public void commitNewContractCache(Repository deposit) {
}
}

private void commitSelfDestructCache(Repository deposit) {
if (deposit != null) {
selfDestructCache.forEach(key -> deposit.markSelfDestruct(key.getData()));
}
}

/**
* Get the block id from the number.
*/
Expand Down
19 changes: 19 additions & 0 deletions actuator/src/main/java/org/tron/core/vm/utils/MUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,23 @@ public static void checkCPUTimeForModExp() {
throw new OutOfTimeException("CPU timeout for modExp executing");
}
}

public static void checkCPUTimeForFreezeV2AfterSelfDestruct() {
if (ForkController.instance().pass(Parameter.ForkBlockVersionEnum.VERSION_4_8_2_2)) {
throw new OutOfTimeException("CPU timeout for FreezeBalanceV2 after SELFDESTRUCT");
}
}

public static void checkCPUTimeForSelfDestructedBeneficiary() {
if (ForkController.instance().pass(Parameter.ForkBlockVersionEnum.VERSION_4_8_2_2)) {
throw new OutOfTimeException(
"CPU timeout for SELFDESTRUCT with selfdestructed beneficiary");
}
}

public static void checkCPUTimeForInvalidDelegatedV2Balance() {
if (ForkController.instance().pass(Parameter.ForkBlockVersionEnum.VERSION_4_8_2_2)) {
throw new OutOfTimeException("CPU timeout for invalid delegated V2 balance");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1336,6 +1336,10 @@ public void clearDelegatedResource() {
this.account = builder.build();
}

public boolean hasInvalidDelegatedV2() {
return getDelegatedFrozenV2BalanceForBandwidth() < 0 || getDelegatedFrozenV2BalanceForEnergy() < 0;
}

public void importAsset(byte[] key) {
this.account = AssetUtil.importAsset(this.account, key);
}
Expand Down
5 changes: 3 additions & 2 deletions common/src/main/java/org/tron/core/config/Parameter.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ public enum ForkBlockVersionEnum {
VERSION_4_8_0_1(33, 1596780000000L, 70),
VERSION_4_8_1(34, 1596780000000L, 80),
VERSION_4_8_1_1(35, 1596780000000L, 70),
VERSION_4_8_2(36, 1596780000000L, 80);
VERSION_4_8_2(36, 1596780000000L, 80),
VERSION_4_8_2_2(37, 1596780000000L, 80);
// if add a version, modify BLOCK_VERSION simultaneously

@Getter
Expand Down Expand Up @@ -79,7 +80,7 @@ public class ChainConstant {
public static final int SINGLE_REPEAT = 1;
public static final int BLOCK_FILLED_SLOTS_NUMBER = 128;
public static final int MAX_FROZEN_NUMBER = 1;
public static final int BLOCK_VERSION = 36;
public static final int BLOCK_VERSION = 37;
public static final long FROZEN_PERIOD = 86_400_000L;
public static final long DELEGATE_PERIOD = 3 * 86_400_000L;
public static final long TRX_PRECISION = 1000_000L;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD;
import static org.tron.core.config.Parameter.ForkBlockVersionEnum.VERSION_4_8_2_2;

import java.util.List;
import java.util.Locale;
Expand All @@ -16,6 +17,7 @@
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
Expand All @@ -24,6 +26,7 @@
import org.tron.common.parameter.CommonParameter;
import org.tron.common.runtime.InternalTransaction;
import org.tron.common.utils.DecodeUtil;
import org.tron.common.utils.ForkController;
import org.tron.core.Constant;
import org.tron.core.Wallet;
import org.tron.core.capsule.AccountCapsule;
Expand All @@ -42,6 +45,7 @@
import org.tron.core.vm.config.ConfigLoader;
import org.tron.core.vm.config.VMConfig;
import org.tron.core.vm.program.Program;
import org.tron.core.vm.program.Program.OutOfTimeException;
import org.tron.core.vm.program.invoke.ProgramInvokeMockImpl;
import org.tron.core.vm.repository.Repository;
import org.tron.protos.Protocol;
Expand Down Expand Up @@ -1182,6 +1186,7 @@ public void testSuicideAction() throws ContractValidateException {

program.suicide(new DataWord(
dbManager.getAccountStore().getBlackhole().getAddress().toByteArray()));
Assert.assertTrue(program.getContractState().isSelfDestructed(program.getContextAddress()));

DecodeUtil.addressPreFixByte = prePrefixByte;
VMConfig.initAllowEnergyAdjustment(0);
Expand Down Expand Up @@ -1240,6 +1245,7 @@ public void testSuicideAction2() throws ContractValidateException {
OperationActions.suicideAction2(program);

Assert.assertEquals(1, program.getResult().getDeleteAccounts().size());
Assert.assertTrue(program.getContractState().isSelfDestructed(contractAddr));


invoke = new ProgramInvokeMockImpl(StoreFactory.getInstance(), new byte[0], contractAddr);
Expand All @@ -1256,6 +1262,7 @@ public void testSuicideAction2() throws ContractValidateException {
dbManager.getAccountStore().getBlackhole().getAddress().toByteArray()));

Assert.assertEquals(0, spyProgram.getResult().getDeleteAccounts().size());
Assert.assertTrue(spyProgram.getContractState().isSelfDestructed(contractAddr));

DecodeUtil.addressPreFixByte = prePrefixByte;
VMConfig.initAllowEnergyAdjustment(0);
Expand All @@ -1266,6 +1273,31 @@ public void testSuicideAction2() throws ContractValidateException {
VMConfig.initAllowTvmVote(0);
}

@Test
public void testSuicide2RejectsSelfDestructedBeneficiaryAfterFork()
throws ContractValidateException {
byte[] contractAddr = Hex.decode("41471fd3ad3e9eeadeec4608b92d16ce6b500704cc");
byte[] beneficiary = Hex.decode("411111111111111111111111111111111111111111");
invoke = new ProgramInvokeMockImpl(StoreFactory.getInstance(), new byte[0], contractAddr);
program = new Program(null, null, invoke,
new InternalTransaction(
Protocol.Transaction.getDefaultInstance(),
InternalTransaction.TrxType.TRX_UNKNOWN_TYPE));
program.getContractState().markSelfDestruct(beneficiary);

ForkController forkController = Mockito.mock(ForkController.class);
try (MockedStatic<ForkController> fork = Mockito.mockStatic(ForkController.class)) {
fork.when(ForkController::instance).thenReturn(forkController);
Mockito.when(forkController.pass(VERSION_4_8_2_2)).thenReturn(true);

OutOfTimeException exception = Assert.assertThrows(OutOfTimeException.class,
() -> program.suicide2(new DataWord(beneficiary)));
Assert.assertEquals(
"CPU timeout for SELFDESTRUCT with selfdestructed beneficiary",
exception.getMessage());
}
}

@Test
public void testVoteWitnessCost() throws ContractValidateException {
// Build stack environment, the stack from top to bottom is 0x00, 0x80, 0x00, 0x80
Expand Down
Loading
Loading