Skip to content

Commit afd15a7

Browse files
authored
Merge pull request tronprotocol#5843 from tronprotocol/master
Master merge to develop
2 parents 76df76c + a8ad2a1 commit afd15a7

File tree

38 files changed

+668
-55
lines changed

38 files changed

+668
-55
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.tron.core.utils.TransactionUtil;
3939
import org.tron.core.vm.EnergyCost;
4040
import org.tron.core.vm.LogInfoTriggerParser;
41+
import org.tron.core.vm.Op;
4142
import org.tron.core.vm.OperationRegistry;
4243
import org.tron.core.vm.VM;
4344
import org.tron.core.vm.VMConstant;
@@ -189,6 +190,13 @@ public void execute(Object object) throws ContractExeException {
189190
VM.play(program, OperationRegistry.getTable());
190191
result = program.getResult();
191192

193+
if (VMConfig.allowEnergyAdjustment()) {
194+
// If the last op consumed too much execution time, the CPU time limit for the whole tx can be exceeded.
195+
// This is not fair for other txs in the same block.
196+
// So when allowFairEnergyAdjustment is on, the CPU time limit will be checked at the end of tx execution.
197+
program.checkCPUTimeLimit(Op.getNameOf(program.getLastOp()) + "(TX_LAST_OP)");
198+
}
199+
192200
if (TrxType.TRX_CONTRACT_CREATION_TYPE == trxType && !result.isRevert()) {
193201
byte[] code = program.getResult().getHReturn();
194202
if (code.length != 0 && VMConfig.allowTvmLondon() && code[0] == (byte) 0xEF) {

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

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.tron.core.utils;
22

3+
import static org.tron.core.Constant.CREATE_ACCOUNT_TRANSACTION_MAX_BYTE_SIZE;
4+
import static org.tron.core.Constant.CREATE_ACCOUNT_TRANSACTION_MIN_BYTE_SIZE;
35
import static org.tron.core.Constant.DYNAMIC_ENERGY_INCREASE_FACTOR_RANGE;
46
import static org.tron.core.Constant.DYNAMIC_ENERGY_MAX_FACTOR_RANGE;
57
import static org.tron.core.config.Parameter.ChainConstant.ONE_YEAR_BLOCK_NUMBERS;
@@ -748,6 +750,35 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore,
748750
}
749751
break;
750752
}
753+
case ALLOW_ENERGY_ADJUSTMENT: {
754+
if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7_5)) {
755+
throw new ContractValidateException(
756+
"Bad chain parameter id [ALLOW_ENERGY_ADJUSTMENT]");
757+
}
758+
if (dynamicPropertiesStore.getAllowEnergyAdjustment() == 1) {
759+
throw new ContractValidateException(
760+
"[ALLOW_ENERGY_ADJUSTMENT] has been valid, no need to propose again");
761+
}
762+
if (value != 1) {
763+
throw new ContractValidateException(
764+
"This value[ALLOW_ENERGY_ADJUSTMENT] is only allowed to be 1");
765+
}
766+
break;
767+
}
768+
case MAX_CREATE_ACCOUNT_TX_SIZE: {
769+
if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7_5)) {
770+
throw new ContractValidateException(
771+
"Bad chain parameter id [MAX_CREATE_ACCOUNT_TX_SIZE]");
772+
}
773+
if (value < CREATE_ACCOUNT_TRANSACTION_MIN_BYTE_SIZE
774+
|| value > CREATE_ACCOUNT_TRANSACTION_MAX_BYTE_SIZE) {
775+
throw new ContractValidateException(
776+
"This value[MAX_CREATE_ACCOUNT_TX_SIZE] is only allowed to be greater than or equal "
777+
+ "to " + CREATE_ACCOUNT_TRANSACTION_MIN_BYTE_SIZE + " and less than or equal to "
778+
+ CREATE_ACCOUNT_TRANSACTION_MAX_BYTE_SIZE + "!");
779+
}
780+
break;
781+
}
751782
default:
752783
break;
753784
}
@@ -824,7 +855,9 @@ public enum ProposalType { // current value, value range
824855
ALLOW_TVM_SHANGHAI(76), // 0, 1
825856
ALLOW_CANCEL_ALL_UNFREEZE_V2(77), // 0, 1
826857
MAX_DELEGATE_LOCK_PERIOD(78), // (86400, 10512000]
827-
ALLOW_OLD_REWARD_OPT(79); // 0, 1
858+
ALLOW_OLD_REWARD_OPT(79), // 0, 1
859+
ALLOW_ENERGY_ADJUSTMENT(81), // 0, 1
860+
MAX_CREATE_ACCOUNT_TX_SIZE(82); // [500, 10000]
828861

829862
private long code;
830863

actuator/src/main/java/org/tron/core/vm/EnergyCost.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,12 +259,19 @@ public static long getSuicideCost(Program ignored) {
259259
return SUICIDE;
260260
}
261261

262+
public static long getSuicideCost2(Program program) {
263+
DataWord inheritorAddress = program.getStack().peek();
264+
if (isDeadAccount(program, inheritorAddress)) {
265+
return getSuicideCost(program) + NEW_ACCT_CALL;
266+
}
267+
return getSuicideCost(program);
268+
}
269+
262270
public static long getBalanceCost(Program ignored) {
263271
return BALANCE;
264272
}
265273

266274
public static long getFreezeCost(Program program) {
267-
268275
Stack stack = program.getStack();
269276
DataWord receiverAddressWord = stack.get(stack.size() - 3);
270277
if (isDeadAccount(program, receiverAddressWord)) {
@@ -306,7 +313,27 @@ public static long getUnDelegateResourceCost(Program ignored) {
306313
}
307314

308315
public static long getVoteWitnessCost(Program program) {
316+
Stack stack = program.getStack();
317+
long oldMemSize = program.getMemSize();
318+
DataWord amountArrayLength = stack.get(stack.size() - 1).clone();
319+
DataWord amountArrayOffset = stack.get(stack.size() - 2);
320+
DataWord witnessArrayLength = stack.get(stack.size() - 3).clone();
321+
DataWord witnessArrayOffset = stack.get(stack.size() - 4);
322+
323+
DataWord wordSize = new DataWord(DataWord.WORD_SIZE);
324+
325+
amountArrayLength.mul(wordSize);
326+
BigInteger amountArrayMemoryNeeded = memNeeded(amountArrayOffset, amountArrayLength);
327+
328+
witnessArrayLength.mul(wordSize);
329+
BigInteger witnessArrayMemoryNeeded = memNeeded(witnessArrayOffset, witnessArrayLength);
330+
331+
return VOTE_WITNESS + calcMemEnergy(oldMemSize,
332+
(amountArrayMemoryNeeded.compareTo(witnessArrayMemoryNeeded) > 0
333+
? amountArrayMemoryNeeded : witnessArrayMemoryNeeded), 0, Op.VOTEWITNESS);
334+
}
309335

336+
public static long getVoteWitnessCost2(Program program) {
310337
Stack stack = program.getStack();
311338
long oldMemSize = program.getMemSize();
312339
DataWord amountArrayLength = stack.get(stack.size() - 1).clone();
@@ -317,9 +344,11 @@ public static long getVoteWitnessCost(Program program) {
317344
DataWord wordSize = new DataWord(DataWord.WORD_SIZE);
318345

319346
amountArrayLength.mul(wordSize);
347+
amountArrayLength.add(wordSize); // dynamic array length is at least 32 bytes
320348
BigInteger amountArrayMemoryNeeded = memNeeded(amountArrayOffset, amountArrayLength);
321349

322350
witnessArrayLength.mul(wordSize);
351+
witnessArrayLength.add(wordSize); // dynamic array length is at least 32 bytes
323352
BigInteger witnessArrayMemoryNeeded = memNeeded(witnessArrayOffset, witnessArrayLength);
324353

325354
return VOTE_WITNESS + calcMemEnergy(oldMemSize,

actuator/src/main/java/org/tron/core/vm/OperationRegistry.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ public static JumpTable getTable() {
6767
adjustMemOperations(table);
6868
}
6969

70+
if (VMConfig.allowEnergyAdjustment()) {
71+
adjustForFairEnergy(table);
72+
}
73+
7074
return table;
7175
}
7276

@@ -635,4 +639,17 @@ public static void appendShangHaiOperations(JumpTable table) {
635639
OperationActions::push0Action,
636640
proposal));
637641
}
642+
643+
public static void adjustForFairEnergy(JumpTable table) {
644+
table.set(new Operation(
645+
Op.VOTEWITNESS, 4, 1,
646+
EnergyCost::getVoteWitnessCost2,
647+
OperationActions::voteWitnessAction,
648+
VMConfig::allowTvmVote));
649+
650+
table.set(new Operation(
651+
Op.SUICIDE, 1, 0,
652+
EnergyCost::getSuicideCost2,
653+
OperationActions::suicideAction));
654+
}
638655
}

actuator/src/main/java/org/tron/core/vm/VMUtils.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@
1212
import java.io.InputStream;
1313
import java.io.OutputStream;
1414
import java.util.Arrays;
15-
import java.util.Map;
1615
import java.util.zip.Deflater;
1716
import java.util.zip.DeflaterOutputStream;
1817
import lombok.extern.slf4j.Slf4j;
1918
import org.tron.common.utils.ByteArray;
2019
import org.tron.common.utils.ByteUtil;
2120
import org.tron.common.utils.Commons;
2221
import org.tron.common.utils.DecodeUtil;
22+
import org.tron.core.Constant;
2323
import org.tron.core.capsule.AccountCapsule;
2424
import org.tron.core.exception.ContractValidateException;
2525
import org.tron.core.vm.config.VMConfig;
@@ -33,6 +33,11 @@ public final class VMUtils {
3333
private VMUtils() {
3434
}
3535

36+
public static int getAddressSize() {
37+
return VMConfig.allowEnergyAdjustment() ?
38+
Constant.TRON_ADDRESS_SIZE : Constant.STANDARD_ADDRESS_SIZE;
39+
}
40+
3641
public static void closeQuietly(Closeable closeable) {
3742
try {
3843
if (closeable != null) {

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
@@ -39,6 +39,7 @@ public static void load(StoreFactory storeFactory) {
3939
VMConfig.initDynamicEnergyIncreaseFactor(ds.getDynamicEnergyIncreaseFactor());
4040
VMConfig.initDynamicEnergyMaxFactor(ds.getDynamicEnergyMaxFactor());
4141
VMConfig.initAllowTvmShangHai(ds.getAllowTvmShangHai());
42+
VMConfig.initAllowEnergyAdjustment(ds.getAllowEnergyAdjustment());
4243
}
4344
}
4445
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ public class VMConfig {
4949

5050
private static boolean ALLOW_TVM_SHANGHAI = false;
5151

52+
private static boolean ALLOW_ENERGY_ADJUSTMENT = false;
53+
5254
private VMConfig() {
5355
}
5456

@@ -136,6 +138,10 @@ public static void initAllowTvmShangHai(long allow) {
136138
ALLOW_TVM_SHANGHAI = allow == 1;
137139
}
138140

141+
public static void initAllowEnergyAdjustment(long allow) {
142+
ALLOW_ENERGY_ADJUSTMENT = allow == 1;
143+
}
144+
139145
public static boolean getEnergyLimitHardFork() {
140146
return CommonParameter.ENERGY_LIMIT_HARD_FORK;
141147
}
@@ -211,4 +217,8 @@ public static long getDynamicEnergyMaxFactor() {
211217
public static boolean allowTvmShanghai() {
212218
return ALLOW_TVM_SHANGHAI;
213219
}
220+
221+
public static boolean allowEnergyAdjustment() {
222+
return ALLOW_ENERGY_ADJUSTMENT;
223+
}
214224
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,10 @@ public void setLastOp(byte op) {
275275
this.lastOp = op;
276276
}
277277

278+
public byte getLastOp() {
279+
return this.lastOp;
280+
}
281+
278282
/**
279283
* Returns the last fully executed OP.
280284
*/
@@ -457,7 +461,8 @@ public void suicide(DataWord obtainerAddress) {
457461
InternalTransaction internalTx = addInternalTx(null, owner, obtainer, balance, null,
458462
"suicide", nonce, getContractState().getAccount(owner).getAssetMapV2());
459463

460-
if (FastByteComparisons.compareTo(owner, 0, 20, obtainer, 0, 20) == 0) {
464+
int ADDRESS_SIZE = VMUtils.getAddressSize();
465+
if (FastByteComparisons.compareTo(owner, 0, ADDRESS_SIZE, obtainer, 0, ADDRESS_SIZE) == 0) {
461466
// if owner == obtainer just zeroing account according to Yellow Paper
462467
getContractState().addBalance(owner, -balance);
463468
byte[] blackHoleAddress = getContractState().getBlackHoleAddress();

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import static org.tron.common.utils.StringUtil.encode58Check;
1919
import static org.tron.common.utils.WalletUtil.checkPermissionOperations;
20+
import static org.tron.core.Constant.MAX_CONTRACT_RESULT_SIZE;
2021
import static org.tron.core.exception.P2pException.TypeEnum.PROTOBUF_ERROR;
2122

2223
import com.google.common.primitives.Bytes;
@@ -114,6 +115,9 @@ public class TransactionCapsule implements ProtoCapsule<Transaction> {
114115
@Getter
115116
@Setter
116117
private boolean isTransactionCreate = false;
118+
@Getter
119+
@Setter
120+
private boolean isInBlock = false;
117121

118122
public byte[] getOwnerAddress() {
119123
if (this.ownerAddress == null) {
@@ -730,6 +734,15 @@ public long getResultSerializedSize() {
730734
return size;
731735
}
732736

737+
public long getResultSizeWithMaxContractRet() {
738+
long size = 0;
739+
for (Result result : this.transaction.getRetList()) {
740+
size += result.toBuilder().clearContractRet().build().getSerializedSize()
741+
+ MAX_CONTRACT_RESULT_SIZE;
742+
}
743+
return size;
744+
}
745+
733746
@Override
734747
public Transaction getInstance() {
735748
return this.transaction;
@@ -842,4 +855,18 @@ public BalanceContract.TransferContract getTransferContract() {
842855
return null;
843856
}
844857
}
858+
859+
public void removeRedundantRet() {
860+
Transaction tx = this.getInstance();
861+
List<Result> tmpList = new ArrayList<>(tx.getRetList());
862+
int contractCount = tx.getRawData().getContractCount();
863+
if (tx.getRetCount() > contractCount && contractCount > 0) {
864+
Transaction.Builder transactionBuilder = tx.toBuilder().clearRet();
865+
for (int i = 0; i < contractCount; i++) {
866+
Result result = tmpList.get(i);
867+
transactionBuilder.addRet(result);
868+
}
869+
this.transaction = transactionBuilder.build();
870+
}
871+
}
845872
}

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

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

3+
import static org.tron.core.Constant.PER_SIGN_LENGTH;
34
import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION;
45
import static org.tron.protos.Protocol.Transaction.Contract.ContractType.ShieldedTransferContract;
56
import static org.tron.protos.Protocol.Transaction.Contract.ContractType.TransferAssetContract;
7+
import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH;
68

79
import com.google.protobuf.ByteString;
810
import java.util.HashMap;
@@ -19,13 +21,12 @@
1921
import org.tron.core.capsule.TransactionCapsule;
2022
import org.tron.core.exception.AccountResourceInsufficientException;
2123
import org.tron.core.exception.ContractValidateException;
24+
import org.tron.core.exception.TooBigTransactionException;
2225
import org.tron.core.exception.TooBigTransactionResultException;
2326
import org.tron.protos.Protocol.Transaction.Contract;
2427
import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract;
2528
import org.tron.protos.contract.BalanceContract.TransferContract;
2629

27-
import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH;
28-
2930
@Slf4j(topic = "DB")
3031
public class BandwidthProcessor extends ResourceProcessor {
3132

@@ -95,8 +96,15 @@ public void updateUsage(AssetIssueCapsule assetIssueCapsule, long now) {
9596
@Override
9697
public void consume(TransactionCapsule trx, TransactionTrace trace)
9798
throws ContractValidateException, AccountResourceInsufficientException,
98-
TooBigTransactionResultException {
99+
TooBigTransactionResultException, TooBigTransactionException {
99100
List<Contract> contracts = trx.getInstance().getRawData().getContractList();
101+
long resultSizeWithMaxContractRet = trx.getResultSizeWithMaxContractRet();
102+
if (!trx.isInBlock() && resultSizeWithMaxContractRet >
103+
Constant.MAX_RESULT_SIZE_IN_TX * contracts.size()) {
104+
throw new TooBigTransactionResultException(String.format(
105+
"Too big transaction result, TxId %s, the result size is %d bytes, maxResultSize %d",
106+
trx.getTransactionId(), resultSizeWithMaxContractRet, Constant.MAX_RESULT_SIZE_IN_TX));
107+
}
100108
if (trx.getResultSerializedSize() > Constant.MAX_RESULT_SIZE_IN_TX * contracts.size()) {
101109
throw new TooBigTransactionResultException();
102110
}
@@ -127,6 +135,17 @@ public void consume(TransactionCapsule trx, TransactionTrace trace)
127135
}
128136
long now = chainBaseManager.getHeadSlot();
129137
if (contractCreateNewAccount(contract)) {
138+
if (!trx.isInBlock()) {
139+
long maxCreateAccountTxSize = dynamicPropertiesStore.getMaxCreateAccountTxSize();
140+
int signatureCount = trx.getInstance().getSignatureCount();
141+
long createAccountBytesSize = trx.getInstance().toBuilder().clearRet()
142+
.build().getSerializedSize() - (signatureCount * PER_SIGN_LENGTH);
143+
if (createAccountBytesSize > maxCreateAccountTxSize) {
144+
throw new TooBigTransactionException(String.format(
145+
"Too big new account transaction, TxId %s, the size is %d bytes, maxTxSize %d",
146+
trx.getTransactionId(), createAccountBytesSize, maxCreateAccountTxSize));
147+
}
148+
}
130149
consumeForCreateNewAccount(accountCapsule, bytesSize, now, trace);
131150
continue;
132151
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.tron.core.exception.AccountResourceInsufficientException;
1212
import org.tron.core.exception.BalanceInsufficientException;
1313
import org.tron.core.exception.ContractValidateException;
14+
import org.tron.core.exception.TooBigTransactionException;
1415
import org.tron.core.exception.TooBigTransactionResultException;
1516
import org.tron.core.store.AccountStore;
1617
import org.tron.core.store.DynamicPropertiesStore;
@@ -35,7 +36,7 @@ protected ResourceProcessor(DynamicPropertiesStore dynamicPropertiesStore,
3536
}
3637

3738
abstract void consume(TransactionCapsule trx, TransactionTrace trace)
38-
throws ContractValidateException, AccountResourceInsufficientException, TooBigTransactionResultException;
39+
throws ContractValidateException, AccountResourceInsufficientException, TooBigTransactionResultException, TooBigTransactionException;
3940

4041
protected long increase(long lastUsage, long usage, long lastTime, long now) {
4142
return increase(lastUsage, usage, lastTime, now, windowSize);

0 commit comments

Comments
 (0)