Skip to content

Commit aca9c19

Browse files
author
ramonliu
committed
feat(tvm): tip-6780: selfdestruct in same transaction
1 parent 15e8c0e commit aca9c19

File tree

14 files changed

+142
-18
lines changed

14 files changed

+142
-18
lines changed

actuator/src/main/java/org/tron/core/utils/ProposalUtil.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,21 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore,
839839
}
840840
break;
841841
}
842+
case ALLOW_TVM_SELFDESTRUCT_RESTRICTION: {
843+
if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_8_1)) {
844+
throw new ContractValidateException(
845+
"Bad chain parameter id [ALLOW_TVM_SELFDESTRUCT_RESTRICTION]");
846+
}
847+
if (dynamicPropertiesStore.allowTvmSelfdestructRestriction()) {
848+
throw new ContractValidateException(
849+
"[ALLOW_TVM_SELFDESTRUCT_RESTRICTION] has been valid, no need to propose again");
850+
}
851+
if (value != 1) {
852+
throw new ContractValidateException(
853+
"This value[ALLOW_TVM_SELFDESTRUCT_RESTRICTION] is only allowed to be 1");
854+
}
855+
break;
856+
}
842857
default:
843858
break;
844859
}
@@ -921,7 +936,8 @@ public enum ProposalType { // current value, value range
921936
ALLOW_TVM_CANCUN(83), // 0, 1
922937
ALLOW_STRICT_MATH(87), // 0, 1
923938
CONSENSUS_LOGIC_OPTIMIZATION(88), // 0, 1
924-
ALLOW_TVM_BLOB(89); // 0, 1
939+
ALLOW_TVM_BLOB(89), // 0, 1
940+
ALLOW_TVM_SELFDESTRUCT_RESTRICTION(94); // 0, 1
925941

926942
private long code;
927943

actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public static void load(StoreFactory storeFactory) {
4444
VMConfig.initAllowTvmCancun(ds.getAllowTvmCancun());
4545
VMConfig.initDisableJavaLangMath(ds.getConsensusLogicOptimization());
4646
VMConfig.initAllowTvmBlob(ds.getAllowTvmBlob());
47+
VMConfig.initAllowTvmSelfdestructRestriction(ds.getAllowTvmSelfdestructRestriction());
4748
}
4849
}
4950
}

actuator/src/main/java/org/tron/core/vm/program/ContractState.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,16 @@ public void updateContractState(byte[] address, ContractStateCapsule contractSta
121121
repository.updateContractState(address, contractStateCapsule);
122122
}
123123

124+
@Override
125+
public void putNewContract(byte[] address) {
126+
repository.putNewContract(address);
127+
}
128+
129+
@Override
130+
public boolean isNewContract(byte[] address) {
131+
return repository.isNewContract(address);
132+
}
133+
124134
@Override
125135
public void updateAccount(byte[] address, AccountCapsule accountCapsule) {
126136
repository.updateAccount(address, accountCapsule);

actuator/src/main/java/org/tron/core/vm/program/Program.java

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -470,14 +470,19 @@ public void suicide(DataWord obtainerAddress) {
470470
InternalTransaction internalTx = addInternalTx(null, owner, obtainer, balance, null,
471471
"suicide", nonce, getContractState().getAccount(owner).getAssetMapV2());
472472

473+
boolean canDeleteAccount =
474+
!VMConfig.allowTvmSelfdestructRestriction() || getContractState().isNewContract(owner);
475+
473476
int ADDRESS_SIZE = VMUtils.getAddressSize();
474477
if (FastByteComparisons.compareTo(owner, 0, ADDRESS_SIZE, obtainer, 0, ADDRESS_SIZE) == 0) {
475-
// if owner == obtainer just zeroing account according to Yellow Paper
476-
getContractState().addBalance(owner, -balance);
477-
byte[] blackHoleAddress = getContractState().getBlackHoleAddress();
478-
if (VMConfig.allowTvmTransferTrc10()) {
479-
getContractState().addBalance(blackHoleAddress, balance);
480-
MUtil.transferAllToken(getContractState(), owner, blackHoleAddress);
478+
if (canDeleteAccount) {
479+
// if owner == obtainer just zeroing account according to Yellow Paper
480+
getContractState().addBalance(owner, -balance);
481+
byte[] blackHoleAddress = getContractState().getBlackHoleAddress();
482+
if (VMConfig.allowTvmTransferTrc10()) {
483+
getContractState().addBalance(blackHoleAddress, balance);
484+
MUtil.transferAllToken(getContractState(), owner, blackHoleAddress);
485+
}
481486
}
482487
} else {
483488
createAccountIfNotExist(getContractState(), obtainer);
@@ -497,22 +502,27 @@ public void suicide(DataWord obtainerAddress) {
497502
if (VMConfig.allowTvmFreeze()) {
498503
byte[] blackHoleAddress = getContractState().getBlackHoleAddress();
499504
if (FastByteComparisons.isEqual(owner, obtainer)) {
500-
transferDelegatedResourceToInheritor(owner, blackHoleAddress, getContractState());
505+
if (canDeleteAccount) {
506+
transferDelegatedResourceToInheritor(owner, blackHoleAddress, getContractState());
507+
}
501508
} else {
502509
transferDelegatedResourceToInheritor(owner, obtainer, getContractState());
503510
}
504511
}
505512
if (VMConfig.allowTvmFreezeV2()) {
506-
byte[] Inheritor =
507-
FastByteComparisons.isEqual(owner, obtainer)
508-
? getContractState().getBlackHoleAddress()
509-
: obtainer;
510-
long expireUnfrozenBalance = transferFrozenV2BalanceToInheritor(owner, Inheritor, getContractState());
511-
if (expireUnfrozenBalance > 0 && internalTx != null) {
512-
internalTx.setValue(internalTx.getValue() + expireUnfrozenBalance);
513+
boolean isEqual = FastByteComparisons.isEqual(owner, obtainer);
514+
if (!isEqual || canDeleteAccount) {
515+
byte[] inheritor = isEqual ? getContractState().getBlackHoleAddress() : obtainer;
516+
long expireUnfrozenBalance =
517+
transferFrozenV2BalanceToInheritor(owner, inheritor, getContractState());
518+
if (expireUnfrozenBalance > 0 && internalTx != null) {
519+
internalTx.setValue(internalTx.getValue() + expireUnfrozenBalance);
520+
}
513521
}
514522
}
515-
getResult().addDeleteAccount(this.getContractAddress());
523+
if (canDeleteAccount) {
524+
getResult().addDeleteAccount(this.getContractAddress());
525+
}
516526
}
517527

518528
public Repository getContractState() {

actuator/src/main/java/org/tron/core/vm/repository/Repository.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ public interface Repository {
5555

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

58+
void putNewContract(byte[] address);
59+
60+
boolean isNewContract(byte[] address);
61+
5862
void updateAccount(byte[] address, AccountCapsule accountCapsule);
5963

6064
void updateDynamicProperty(byte[] word, BytesCapsule bytesCapsule);

actuator/src/main/java/org/tron/core/vm/repository/RepositoryImpl.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.google.common.collect.HashBasedTable;
1010
import com.google.protobuf.ByteString;
1111
import java.util.HashMap;
12+
import java.util.HashSet;
1213
import java.util.Optional;
1314
import lombok.Getter;
1415
import lombok.extern.slf4j.Slf4j;
@@ -135,6 +136,7 @@ public class RepositoryImpl implements Repository {
135136
private final HashMap<Key, Value<byte[]>> delegationCache = new HashMap<>();
136137
private final HashMap<Key, Value<DelegatedResourceAccountIndex>> delegatedResourceAccountIndexCache = new HashMap<>();
137138
private final HashBasedTable<Key, Key, Value<byte[]>> transientStorage = HashBasedTable.create();
139+
private final HashSet<Key> newContractCache = new HashSet<>();
138140

139141
public static void removeLruCache(byte[] address) {
140142
}
@@ -479,6 +481,7 @@ public void deleteContract(byte[] address) {
479481
public void createContract(byte[] address, ContractCapsule contractCapsule) {
480482
contractCache.put(Key.create(address),
481483
Value.create(contractCapsule, Type.CREATE));
484+
putNewContract(address);
482485
}
483486

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

539+
@Override
540+
public void putNewContract(byte[] address) {
541+
newContractCache.add(Key.create(address));
542+
}
543+
544+
@Override
545+
public boolean isNewContract(byte[] address) {
546+
Key key = Key.create(address);
547+
if (newContractCache.contains(key)) {
548+
return true;
549+
}
550+
551+
if (parent != null) {
552+
boolean isNew = parent.isNewContract(address);
553+
if (isNew) {
554+
newContractCache.add(key);
555+
}
556+
return isNew;
557+
} else {
558+
return false;
559+
}
560+
}
561+
536562
@Override
537563
public void updateAccount(byte[] address, AccountCapsule accountCapsule) {
538564
accountCache.put(Key.create(address),
@@ -740,6 +766,7 @@ public void commit() {
740766
commitDelegationCache(repository);
741767
commitDelegatedResourceAccountIndexCache(repository);
742768
commitTransientStorage(repository);
769+
commitNewContractCache(repository);
743770
}
744771

745772
@Override
@@ -1060,6 +1087,12 @@ public void commitTransientStorage(Repository deposit) {
10601087
}
10611088
}
10621089

1090+
public void commitNewContractCache(Repository deposit) {
1091+
if (deposit != null) {
1092+
newContractCache.forEach(key -> deposit.putNewContract(key.getData()));
1093+
}
1094+
}
1095+
10631096
/**
10641097
* Get the block id from the number.
10651098
*/

chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,9 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking<BytesCapsule>
232232

233233
private static final byte[] ALLOW_TVM_BLOB = "ALLOW_TVM_BLOB".getBytes();
234234

235+
private static final byte[] ALLOW_TVM_SELFDESTRUCT_RESTRICTION =
236+
"ALLOW_TVM_SELFDESTRUCT_RESTRICTION".getBytes();
237+
235238
@Autowired
236239
private DynamicPropertiesStore(@Value("properties") String dbName) {
237240
super(dbName);
@@ -2946,6 +2949,21 @@ public long getAllowTvmBlob() {
29462949
.orElse(CommonParameter.getInstance().getAllowTvmBlob());
29472950
}
29482951

2952+
public long getAllowTvmSelfdestructRestriction() {
2953+
return Optional.ofNullable(getUnchecked(ALLOW_TVM_SELFDESTRUCT_RESTRICTION))
2954+
.map(BytesCapsule::getData)
2955+
.map(ByteArray::toLong)
2956+
.orElse(CommonParameter.getInstance().getAllowTvmSelfdestructRestriction());
2957+
}
2958+
2959+
public void saveAllowTvmSelfdestructRestriction(long value) {
2960+
this.put(ALLOW_TVM_SELFDESTRUCT_RESTRICTION, new BytesCapsule(ByteArray.fromLong(value)));
2961+
}
2962+
2963+
public boolean allowTvmSelfdestructRestriction() {
2964+
return getAllowTvmSelfdestructRestriction() == 1L;
2965+
}
2966+
29492967
private static class DynamicResourceProperties {
29502968

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

common/src/main/java/org/tron/common/parameter/CommonParameter.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,10 @@ public class CommonParameter {
724724
@Setter
725725
public long allowTvmBlob;
726726

727+
@Getter
728+
@Setter
729+
public long allowTvmSelfdestructRestriction;
730+
727731
private static double calcMaxTimeRatio() {
728732
//return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1)));
729733
return 5.0;

common/src/main/java/org/tron/core/Constant.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,4 +405,7 @@ public class Constant {
405405
public static final String COMMITTEE_ALLOW_TVM_CANCUN = "committee.allowTvmCancun";
406406

407407
public static final String COMMITTEE_ALLOW_TVM_BLOB = "committee.allowTvmBlob";
408+
409+
public static final String COMMITTEE_ALLOW_TVM_SELFDESTRUCT_RESTRICTION =
410+
"committee.allowTvmSelfdestructRestriction";
408411
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ public enum ForkBlockVersionEnum {
2626
VERSION_4_7_4(29, 1596780000000L, 80),
2727
VERSION_4_7_5(30, 1596780000000L, 80),
2828
VERSION_4_7_7(31, 1596780000000L, 80),
29-
VERSION_4_8_0(32, 1596780000000L, 80);
29+
VERSION_4_8_0(32, 1596780000000L, 80),
30+
VERSION_4_8_1(33, 1596780000000L, 80);
3031
// if add a version, modify BLOCK_VERSION simultaneously
3132

3233
@Getter
@@ -75,7 +76,7 @@ public class ChainConstant {
7576
public static final int SINGLE_REPEAT = 1;
7677
public static final int BLOCK_FILLED_SLOTS_NUMBER = 128;
7778
public static final int MAX_FROZEN_NUMBER = 1;
78-
public static final int BLOCK_VERSION = 32;
79+
public static final int BLOCK_VERSION = 33;
7980
public static final long FROZEN_PERIOD = 86_400_000L;
8081
public static final long DELEGATE_PERIOD = 3 * 86_400_000L;
8182
public static final long TRX_PRECISION = 1000_000L;

0 commit comments

Comments
 (0)