Skip to content
Closed
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
42 changes: 37 additions & 5 deletions actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import static org.tron.common.utils.ByteUtil.parseWord;
import static org.tron.common.utils.ByteUtil.stripLeadingZeroes;
import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION;
import static org.tron.core.vm.VMConstant.SIG_LENGTH;

import com.google.protobuf.ByteString;

Expand Down Expand Up @@ -202,7 +203,7 @@ public class PrecompiledContracts {
public static PrecompiledContract getOptimizedContractForConstant(PrecompiledContract contract) {
try {
Constructor<?> constructor = contract.getClass().getDeclaredConstructor();
return (PrecompiledContracts.PrecompiledContract) constructor.newInstance();
return (PrecompiledContracts.PrecompiledContract) constructor.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
Expand Down Expand Up @@ -395,6 +396,20 @@ private static byte[][] extractBytesArray(DataWord[] words, int offset, byte[] d
return bytesArray;
}

private static byte[][] extractSigArray(DataWord[] words, int offset, byte[] data) {
if (offset > words.length - 1) {
return new byte[0][];
}
int len = words[offset].intValueSafe();
byte[][] bytesArray = new byte[len][];
for (int i = 0; i < len; i++) {
int bytesOffset = words[offset + i + 1].intValueSafe() / WORD_SIZE;
bytesArray[i] = extractBytes(data, (bytesOffset + offset + 2) * WORD_SIZE,
SIG_LENGTH);
}
return bytesArray;
}

private static byte[] extractBytes(byte[] data, int offset, int len) {
return Arrays.copyOfRange(data, offset, offset + len);
}
Expand Down Expand Up @@ -936,8 +951,15 @@ public Pair<Boolean, byte[]> execute(byte[] rawData) {
byte[] hash = Sha256Hash.hash(CommonParameter
.getInstance().isECKeyCryptoEngine(), combine);

byte[][] signatures = extractBytesArray(
words, words[3].intValueSafe() / WORD_SIZE, rawData);
if (VMConfig.allowTvmSelfdestructRestriction()) {
int sigArraySize = words[words[3].intValueSafe() / WORD_SIZE].intValueSafe();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a general improvement?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, we enhance processing efficiency by moving the judgment to the front end.

Copy link

@Sunny6889 Sunny6889 Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then the PR title and description better adjust accordingly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no difference; the goal is to optimize the proposal content.

if (sigArraySize > MAX_SIZE) {
return Pair.of(true, DATA_FALSE);
}
}
byte[][] signatures = VMConfig.allowTvmSelfdestructRestriction() ?
extractSigArray(words, words[3].intValueSafe() / WORD_SIZE, rawData) :
extractBytesArray(words, words[3].intValueSafe() / WORD_SIZE, rawData);

if (signatures.length == 0 || signatures.length > MAX_SIZE) {
return Pair.of(true, DATA_FALSE);
Expand Down Expand Up @@ -1021,8 +1043,18 @@ private Pair<Boolean, byte[]> doExecute(byte[] data)
throws InterruptedException, ExecutionException {
DataWord[] words = DataWord.parseArray(data);
byte[] hash = words[0].getData();
byte[][] signatures = extractBytesArray(
words, words[1].intValueSafe() / WORD_SIZE, data);

if (VMConfig.allowTvmSelfdestructRestriction()) {
int sigArraySize = words[words[1].intValueSafe() / WORD_SIZE].intValueSafe();
int addrArraySize = words[words[2].intValueSafe() / WORD_SIZE].intValueSafe();
if (sigArraySize > MAX_SIZE || addrArraySize > MAX_SIZE) {
return Pair.of(true, DATA_FALSE);
}
}

byte[][] signatures = VMConfig.allowTvmSelfdestructRestriction() ?
extractSigArray(words, words[1].intValueSafe() / WORD_SIZE, data) :
extractBytesArray(words, words[1].intValueSafe() / WORD_SIZE, data);
byte[][] addresses = extractBytes32Array(
words, words[2].intValueSafe() / WORD_SIZE);
int cnt = signatures.length;
Expand Down
1 change: 1 addition & 0 deletions actuator/src/main/java/org/tron/core/vm/VMConstant.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ public class VMConstant {

public static final int CONTRACT_NAME_LENGTH = 32;
public static final int MIN_TOKEN_ID = 1_000_000;
public static final int SIG_LENGTH = 65;

// Numbers
public static final int ONE_HUNDRED = 100;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public void write(int address, byte[] data, int dataSize, boolean limited) {

public void extendAndWrite(int address, int allocSize, byte[] data) {
extend(address, allocSize);
write(address, data, data.length, false);
write(address, data, allocSize, false);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure whether below is better?

int writeSize = Math.min(allocSize, data.length);
write(address, data, writeSize, true); 

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your suggestion does not align with the original intent of this method's design.

}

public void extend(int address, int size) {
Expand Down
6 changes: 5 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 @@ -1746,7 +1746,11 @@ public void callToPrecompiledAddress(MessageCall msg,
}
}

this.memorySave(msg.getOutDataOffs().intValue(), out.getRight());
if (VMConfig.allowTvmSelfdestructRestriction()) {
this.memorySave(msg.getOutDataOffs().intValueSafe(), msg.getOutDataSize().intValueSafe(), out.getRight());
} else {
this.memorySave(msg.getOutDataOffs().intValue(), out.getRight());
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.tron.core.db.TransactionTrace;
import org.tron.core.vm.PrecompiledContracts;
import org.tron.core.vm.PrecompiledContracts.BatchValidateSign;
import org.tron.core.vm.config.VMConfig;


@Slf4j
Expand Down Expand Up @@ -74,6 +75,13 @@ public void staticCallTest() {
ret = validateMultiSign(hash, signatures, addresses);
Assert.assertEquals(ret.getValue().length, 32);
Assert.assertArrayEquals(ret.getValue(), new byte[32]);

//after optimized
VMConfig.initAllowTvmSelfdestructRestriction(1);
ret = validateMultiSign(hash, signatures, addresses);
Assert.assertEquals(ret.getValue().length, 32);
Assert.assertArrayEquals(ret.getValue(), new byte[32]);
VMConfig.initAllowTvmSelfdestructRestriction(0);
System.gc(); // force triggering full gc to avoid timeout for next test
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,26 @@
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.tron.common.BaseTest;
import org.tron.common.parameter.CommonParameter;
import org.tron.common.runtime.InternalTransaction;
import org.tron.common.utils.DecodeUtil;
import org.tron.core.Constant;
import org.tron.core.Wallet;
import org.tron.core.capsule.AccountCapsule;
import org.tron.core.config.args.Args;
import org.tron.core.exception.ContractValidateException;
import org.tron.core.store.StoreFactory;
import org.tron.core.vm.EnergyCost;
import org.tron.core.vm.JumpTable;
import org.tron.core.vm.MessageCall;
import org.tron.core.vm.Op;
import org.tron.core.vm.Operation;
import org.tron.core.vm.OperationActions;
import org.tron.core.vm.OperationRegistry;
import org.tron.core.vm.PrecompiledContracts;
import org.tron.core.vm.VM;
import org.tron.core.vm.config.ConfigLoader;
import org.tron.core.vm.config.VMConfig;
Expand All @@ -46,6 +50,8 @@ public class OperationsTest extends BaseTest {
private ProgramInvokeMockImpl invoke;
private Program program;
private final JumpTable jumpTable = OperationRegistry.getTable();
@Autowired
private Wallet wallet;

@BeforeClass
public static void init() {
Expand Down Expand Up @@ -755,6 +761,30 @@ public void testPushDupSwapAndLogOperations() throws ContractValidateException {
Assert.assertEquals(2158, program.getResult().getEnergyUsed());
}

@Test
public void testCallOperations() throws ContractValidateException {
invoke = new ProgramInvokeMockImpl();
Protocol.Transaction trx = Protocol.Transaction.getDefaultInstance();
InternalTransaction interTrx =
new InternalTransaction(trx, InternalTransaction.TrxType.TRX_UNKNOWN_TYPE);

byte prePrefixByte = DecodeUtil.addressPreFixByte;
DecodeUtil.addressPreFixByte = Constant.ADD_PRE_FIX_BYTE_MAINNET;
VMConfig.initAllowTvmSelfdestructRestriction(1);

program = new Program(new byte[0], new byte[0], invoke, interTrx);
MessageCall messageCall = new MessageCall(
Op.CALL, new DataWord(10000),
DataWord.ZERO(), DataWord.ZERO(),
DataWord.ZERO(), DataWord.ZERO(),
DataWord.ZERO(), DataWord.ZERO(),
DataWord.ZERO(), false);
program.callToPrecompiledAddress(messageCall, new PrecompiledContracts.ECRecover());

DecodeUtil.addressPreFixByte = prePrefixByte;
VMConfig.initAllowTvmSelfdestructRestriction(0);
}

@Test
public void testOtherOperations() throws ContractValidateException {
invoke = new ProgramInvokeMockImpl();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.tron.core.config.args.Args;
import org.tron.core.store.StoreFactory;
import org.tron.core.vm.PrecompiledContracts.ValidateMultiSign;
import org.tron.core.vm.config.VMConfig;
import org.tron.core.vm.repository.Repository;
import org.tron.core.vm.repository.RepositoryImpl;
import org.tron.protos.Protocol;
Expand Down Expand Up @@ -123,6 +124,13 @@ public void testDifferentCase() {
validateMultiSign(StringUtil.encode58Check(key.getAddress()), permissionId, data, signs)
.getValue(), DataWord.ONE().getData());

//after optimized
VMConfig.initAllowTvmSelfdestructRestriction(1);
Assert.assertArrayEquals(
validateMultiSign(StringUtil.encode58Check(key.getAddress()), permissionId, data, signs)
.getValue(), DataWord.ONE().getData());
VMConfig.initAllowTvmSelfdestructRestriction(0);

//weight not enough
signs = new ArrayList<>();
signs.add(Hex.toHexString(key1.sign(toSign).toByteArray()));
Expand Down