Skip to content
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
18 changes: 17 additions & 1 deletion actuator/src/main/java/org/tron/core/utils/ProposalUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,21 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore,
}
break;
}
case ALLOW_TVM_SELFDESTRUCT_RESTRICTION: {
if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_8_1)) {
throw new ContractValidateException(
"Bad chain parameter id [ALLOW_TVM_SELFDESTRUCT_RESTRICTION]");
}
if (dynamicPropertiesStore.allowTvmSelfdestructRestriction()) {
throw new ContractValidateException(
"[ALLOW_TVM_SELFDESTRUCT_RESTRICTION] has been valid, no need to propose again");
}
if (value != 1) {
throw new ContractValidateException(
"This value[ALLOW_TVM_SELFDESTRUCT_RESTRICTION] is only allowed to be 1");
}
break;
}
case PROPOSAL_EXPIRE_TIME: {
if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_8_1)) {
throw new ContractValidateException(
Expand Down Expand Up @@ -938,7 +953,8 @@ public enum ProposalType { // current value, value range
ALLOW_STRICT_MATH(87), // 0, 1
CONSENSUS_LOGIC_OPTIMIZATION(88), // 0, 1
ALLOW_TVM_BLOB(89), // 0, 1
PROPOSAL_EXPIRE_TIME(92); // (0, 31536003000)
PROPOSAL_EXPIRE_TIME(92), // (0, 31536003000)
ALLOW_TVM_SELFDESTRUCT_RESTRICTION(94); // 0, 1

private long code;

Expand Down
9 changes: 9 additions & 0 deletions actuator/src/main/java/org/tron/core/vm/EnergyCost.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public class EnergyCost {
private static final long EXT_CODE_SIZE = 20;
private static final long EXT_CODE_HASH = 400;
private static final long SUICIDE = 0;
private static final long SUICIDE_V2 = 5000;
private static final long STOP = 0;
private static final long CREATE_DATA = 200;
private static final long TLOAD = 100;
Expand Down Expand Up @@ -289,6 +290,14 @@ public static long getSuicideCost2(Program program) {
return getSuicideCost(program);
}

public static long getSuicideCost3(Program program) {
DataWord inheritorAddress = program.getStack().peek();
if (isDeadAccount(program, inheritorAddress)) {
return SUICIDE_V2 + NEW_ACCT_CALL;
}
return SUICIDE_V2;
}

public static long getBalanceCost(Program ignored) {
return BALANCE;
}
Expand Down
15 changes: 15 additions & 0 deletions actuator/src/main/java/org/tron/core/vm/OperationActions.java
Original file line number Diff line number Diff line change
Expand Up @@ -1072,4 +1072,19 @@ public static void suicideAction(Program program) {
program.stop();
}

public static void suicideAction2(Program program) {
if (program.isStaticCall()) {
throw new Program.StaticCallModificationException();
}

if (!program.canSuicide2()) {
program.getResult().setRevert();
} else {
DataWord address = program.stackPop();
program.suicide2(address);
}

program.stop();
}

}
11 changes: 11 additions & 0 deletions actuator/src/main/java/org/tron/core/vm/OperationRegistry.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ public static JumpTable getTable() {
adjustForFairEnergy(table);
}

if (VMConfig.allowTvmSelfdestructRestriction()) {
adjustSelfdestruct(table);
}

return table;
}

Expand Down Expand Up @@ -695,4 +699,11 @@ public static void appendCancunOperations(JumpTable table) {
OperationActions::blobBaseFeeAction,
tvmBlobProposal));
}

public static void adjustSelfdestruct(JumpTable table) {
table.set(new Operation(
Op.SUICIDE, 1, 0,
EnergyCost::getSuicideCost3,
OperationActions::suicideAction2));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public static void load(StoreFactory storeFactory) {
VMConfig.initAllowTvmCancun(ds.getAllowTvmCancun());
VMConfig.initDisableJavaLangMath(ds.getConsensusLogicOptimization());
VMConfig.initAllowTvmBlob(ds.getAllowTvmBlob());
VMConfig.initAllowTvmSelfdestructRestriction(ds.getAllowTvmSelfdestructRestriction());
}
}
}
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 @@ -121,6 +121,16 @@ public void updateContractState(byte[] address, ContractStateCapsule contractSta
repository.updateContractState(address, contractStateCapsule);
}

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

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

@Override
public void updateAccount(byte[] address, AccountCapsule accountCapsule) {
repository.updateAccount(address, accountCapsule);
Expand Down
108 changes: 108 additions & 0 deletions actuator/src/main/java/org/tron/core/vm/program/Program.java
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,72 @@ public void suicide(DataWord obtainerAddress) {
getResult().addDeleteAccount(this.getContractAddress());
}

public void suicide2(DataWord obtainerAddress) {

byte[] owner = getContextAddress();
boolean isNewContract = getContractState().isNewContract(owner);
if (isNewContract) {
suicide(obtainerAddress);
return;
}

byte[] obtainer = obtainerAddress.toTronAddress();

long balance = getContractState().getBalance(owner);

if (logger.isDebugEnabled()) {
logger.debug("Transfer to: [{}] heritage: [{}]",
Hex.toHexString(obtainer),
balance);
}

increaseNonce();

InternalTransaction internalTx = addInternalTx(null, owner, obtainer, balance, null,
"suicide", nonce, getContractState().getAccount(owner).getAssetMapV2());

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

if (VMConfig.allowTvmVote()) {
withdrawRewardAndCancelVote(owner, getContractState());
balance = getContractState().getBalance(owner);
if (internalTx != null && balance != internalTx.getValue()) {
internalTx.setValue(balance);
}
}

// transfer balance and trc10
createAccountIfNotExist(getContractState(), obtainer);
try {
MUtil.transfer(getContractState(), owner, obtainer, balance);
if (VMConfig.allowTvmTransferTrc10()) {
MUtil.transferAllToken(getContractState(), owner, obtainer);
}
} catch (ContractValidateException e) {
if (VMConfig.allowTvmConstantinople()) {
throw new TransferException(
"transfer all token or transfer all trx failed in suicide: %s", e.getMessage());
}
throw new BytecodeExecutionException("transfer failure");
}

// transfer freeze
if (VMConfig.allowTvmFreeze()) {
transferDelegatedResourceToInheritor(owner, obtainer, getContractState());
}

// transfer freezeV2
if (VMConfig.allowTvmFreezeV2()) {
long expireUnfrozenBalance =
transferFrozenV2BalanceToInheritor(owner, obtainer, getContractState());
if (expireUnfrozenBalance > 0 && internalTx != null) {
internalTx.setValue(internalTx.getValue() + expireUnfrozenBalance);
}
}
}

public Repository getContractState() {
return this.contractState;
}
Expand Down Expand Up @@ -544,6 +610,11 @@ private void transferDelegatedResourceToInheritor(byte[] ownerAddr, byte[] inher

// transfer all kinds of frozen balance to BlackHole
repo.addBalance(inheritorAddr, frozenBalanceForBandwidthOfOwner + frozenBalanceForEnergyOfOwner);

if (VMConfig.allowTvmSelfdestructRestriction()) {
clearOwnerFreeze(ownerCapsule);
repo.updateAccount(ownerAddr, ownerCapsule);
}
}

private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inheritorAddr, Repository repo) {
Expand Down Expand Up @@ -609,6 +680,11 @@ private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit
return expireUnfrozenBalance;
}

private void clearOwnerFreeze(AccountCapsule ownerCapsule) {
ownerCapsule.setFrozenForBandwidth(0, 0);
ownerCapsule.setFrozenForEnergy(0, 0);
}

private void clearOwnerFreezeV2(AccountCapsule ownerCapsule) {
ownerCapsule.clearFrozenV2();
ownerCapsule.setNetUsage(0);
Expand Down Expand Up @@ -666,6 +742,38 @@ public boolean canSuicide() {
// return freezeCheck && voteCheck;
}

public boolean canSuicide2() {
byte[] owner = getContextAddress();
AccountCapsule accountCapsule = getContractState().getAccount(owner);

return freezeV1Check(accountCapsule) && freezeV2Check(accountCapsule);
}

private boolean freezeV1Check(AccountCapsule accountCapsule) {
if (!VMConfig.allowTvmFreeze()) {
return true;
}

// check freeze
long now = getContractState().getDynamicPropertiesStore().getLatestBlockHeaderTimestamp();
// bandwidth
if (accountCapsule.getFrozenCount() > 0
&& accountCapsule.getFrozenList().stream()
.anyMatch(frozen -> frozen.getExpireTime() > now)) {
return false;
}
// energy
Protocol.Account.Frozen frozenEnergy =
accountCapsule.getAccountResource().getFrozenBalanceForEnergy();
if (frozenEnergy.getFrozenBalance() > 0 && frozenEnergy.getExpireTime() > now) {
return false;
}

// check delegate
return accountCapsule.getDelegatedFrozenBalanceForBandwidth() == 0
&& accountCapsule.getDelegatedFrozenBalanceForEnergy() == 0;
}

private boolean freezeV2Check(AccountCapsule accountCapsule) {
if (!VMConfig.allowTvmFreezeV2()) {
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ public interface Repository {

void updateContractState(byte[] address, ContractStateCapsule contractStateCapsule);

void putNewContract(byte[] address);

boolean isNewContract(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 @@ -9,6 +9,7 @@
import com.google.common.collect.HashBasedTable;
import com.google.protobuf.ByteString;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Optional;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -135,6 +136,7 @@ public class RepositoryImpl implements Repository {
private final HashMap<Key, Value<byte[]>> delegationCache = new HashMap<>();
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<>();

public static void removeLruCache(byte[] address) {
}
Expand Down Expand Up @@ -479,6 +481,7 @@ public void deleteContract(byte[] address) {
public void createContract(byte[] address, ContractCapsule contractCapsule) {
contractCache.put(Key.create(address),
Value.create(contractCapsule, Type.CREATE));
putNewContract(address);
}

@Override
Expand Down Expand Up @@ -533,6 +536,29 @@ public void updateContractState(byte[] address, ContractStateCapsule contractSta
Value.create(contractStateCapsule, Type.DIRTY));
}

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

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

if (parent != null) {
boolean isNew = parent.isNewContract(address);
if (isNew) {
newContractCache.add(key);
}
return isNew;
} else {
return false;
}
}

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

@Override
Expand Down Expand Up @@ -1060,6 +1087,12 @@ public void commitTransientStorage(Repository deposit) {
}
}

public void commitNewContractCache(Repository deposit) {
if (deposit != null) {
newContractCache.forEach(key -> deposit.putNewContract(key.getData()));
}
}

/**
* Get the block id from the number.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,9 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking<BytesCapsule>
private static final byte[] ALLOW_TVM_BLOB = "ALLOW_TVM_BLOB".getBytes();
private static final byte[] PROPOSAL_EXPIRE_TIME = "PROPOSAL_EXPIRE_TIME".getBytes();

private static final byte[] ALLOW_TVM_SELFDESTRUCT_RESTRICTION =
"ALLOW_TVM_SELFDESTRUCT_RESTRICTION".getBytes();

@Autowired
private DynamicPropertiesStore(@Value("properties") String dbName) {
super(dbName);
Expand Down Expand Up @@ -2949,6 +2952,22 @@ public long getAllowTvmBlob() {
.orElse(CommonParameter.getInstance().getAllowTvmBlob());
}


public long getAllowTvmSelfdestructRestriction() {
return Optional.ofNullable(getUnchecked(ALLOW_TVM_SELFDESTRUCT_RESTRICTION))
.map(BytesCapsule::getData)
.map(ByteArray::toLong)
.orElse(CommonParameter.getInstance().getAllowTvmSelfdestructRestriction());
}

public void saveAllowTvmSelfdestructRestriction(long value) {
this.put(ALLOW_TVM_SELFDESTRUCT_RESTRICTION, new BytesCapsule(ByteArray.fromLong(value)));
}

public boolean allowTvmSelfdestructRestriction() {
return getAllowTvmSelfdestructRestriction() == 1L;
}

public void saveProposalExpireTime(long proposalExpireTime) {
this.put(PROPOSAL_EXPIRE_TIME, new BytesCapsule(ByteArray.fromLong(proposalExpireTime)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,10 @@ public class CommonParameter {
@Setter
public long allowTvmBlob;

@Getter
@Setter
public long allowTvmSelfdestructRestriction;

private static double calcMaxTimeRatio() {
//return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1)));
return 5.0;
Expand Down
5 changes: 5 additions & 0 deletions common/src/main/java/org/tron/core/Constant.java
Original file line number Diff line number Diff line change
Expand Up @@ -418,5 +418,10 @@ public class Constant {
public static final String COMMITTEE_ALLOW_TVM_CANCUN = "committee.allowTvmCancun";

public static final String COMMITTEE_ALLOW_TVM_BLOB = "committee.allowTvmBlob";

public static final String COMMITTEE_ALLOW_TVM_SELFDESTRUCT_RESTRICTION =
"committee.allowTvmSelfdestructRestriction";

public static final String COMMITTEE_PROPOSAL_EXPIRE_TIME = "committee.proposalExpireTime";

}
Loading