Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a219222
chore(deps): upgrade grpc, jackson, logback, commons and drop joda-ti…
halibobo1205 Sep 14, 2026
0d19485
feat(api): sanitize HTTP API error responses (#6954)
halibobo1205 Sep 14, 2026
289c1f2
fix(config): remove inactive RocksDB options (#6944)
bladehan1 Sep 18, 2026
34d00c5
ci: optimize pull request checks (#6938)
bladehan1 Sep 18, 2026
880eef6
refactor(config): improve startup errors and remove inactive assertio…
bladehan1 Sep 22, 2026
4d6c240
fix(test): isolate cross-test state leaks and stabilize flaky suites …
warku123 Sep 22, 2026
11d555d
refactor(vm): remove unreachable trace compression path (#6997)
halibobo1205 Sep 24, 2026
9f3c9ae
chore(p2p): internalize libp2p v2.2.9 as a local `p2p` module (#6992)
barbatos2011 Sep 29, 2026
f3e8140
feat: improve node stability and execution efficiency (#7007)
yanghang8612 Sep 30, 2026
5c449a1
update a new version. version name:GreatVoyage-v4.8.2.2-1-gf3e81404fe…
yanghang8612 Sep 30, 2026
6d5adc4
feat(version): merge master to 4.8.3(#7010)
halibobo1205 Oct 2, 2026
1e8abb0
refactor(api): replace response copy wrappers with Jetty content coun…
halibobo1205 Oct 8, 2026
6f7b83a
refactor(framework): decouple Manager from TronJsonRpcImpl (#6990)
0xbigapple Oct 9, 2026
8bb6150
refactor(api): remove dead WalletExtension gRPC service and config (#…
0xbigapple Oct 10, 2026
91371cf
feat(plugins): backfill section bloom (#6973)
317787106 Oct 10, 2026
f62b25f
refactor(crypto): remove unused SM2 and SM3 (#6999)
Federico2014 Oct 10, 2026
1575c4f
fix(config): close resource streams (#7002)
Federico2014 Oct 11, 2026
e56ddd9
refactor(proto): remove unused proto discover definition (#7014)
317787106 Oct 12, 2026
00661e8
feat(framework): remove --keystore-factory support from FullNode (#6978)
0xbigapple Oct 12, 2026
1ff2aae
refactor(trie): remove unused RLP utilities (#6991)
SeriousCoding789 Oct 12, 2026
0449395
refactor(rpc): serve solidity and pbft grpc via shared service instances
Little-Peony Sep 17, 2026
ebc664a
test(rpc): check the cursor reset on the handler thread and wait for it
Little-Peony Sep 30, 2026
240f094
refactor(rpc): fix the cursor per interceptor and document port parity
Little-Peony Oct 12, 2026
d280440
test(rpc): drive registered services and checked error paths
Little-Peony Oct 12, 2026
082d99b
test(rpc): drop redundant cursor and error-path test cases
Little-Peony Oct 12, 2026
0d5b9e5
fix(jsonrpc): handle null parameters consistently (#6984)
waynercheung Oct 12, 2026
12713e6
fix(jsonrpc): normalize error responses and fatal handling (#6985)
waynercheung Oct 12, 2026
89c5584
Merge branch 'release_v4.8.3' into refactor_merge_rpc
Little-Peony Oct 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 4 additions & 4 deletions .github/workflows/pr-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ jobs:
debian11-x86_64-gradle-

- name: Build
run: ./gradlew clean build --no-daemon --no-build-cache
run: ./gradlew clean build --no-daemon

- name: Toolkit jar smoke test
run: |
Expand All @@ -209,7 +209,7 @@ jobs:
java -jar "$JAR" keystore --help

- name: Test with RocksDB engine
run: ./gradlew :framework:testWithRocksDb --no-daemon --no-build-cache
run: ./gradlew :framework:testWithRocksDb --no-daemon

- name: Generate module coverage reports
run: ./gradlew jacocoTestReport --no-daemon
Expand Down Expand Up @@ -265,11 +265,11 @@ jobs:
# this PR. The only output we need from this job is the jacoco XML for
# coverage diffing, so we must not let a stale test failure block it.
continue-on-error: true
run: ./gradlew clean build --no-daemon --no-build-cache
run: ./gradlew clean build --no-daemon

- name: Test with RocksDB engine (base)
continue-on-error: true
run: ./gradlew :framework:testWithRocksDb --no-daemon --no-build-cache
run: ./gradlew :framework:testWithRocksDb --no-daemon

- name: Generate module coverage reports (base)
run: ./gradlew jacocoTestReport --no-daemon
Expand Down
15 changes: 11 additions & 4 deletions .github/workflows/pr-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,16 @@ jobs:
errors.push(`PR title is too long (${title.length}/72 characters).`);
}

// 2. Conventional format check
const conventionalRegex = /^(feat|fix|refactor|docs|style|test|chore|ci|perf|build|revert)(\([^)]+\))?:\s\S.*/;
if (title && !conventionalRegex.test(title)) {
// 2. Conventional format check (require a space after the colon)
const titlePrefix = '(?:feat|fix|refactor|docs|style|test|chore|ci|perf|build|revert)(?:[(][^)]+[)])?';
const missingSpaceAfterColonRegex = new RegExp(`^${titlePrefix}:[^ ]`);
const conventionalRegex = new RegExp(`^${titlePrefix}: [^ ].*`);
if (title && missingSpaceAfterColonRegex.test(title)) {
errors.push(
'PR title must include a space after the colon.\n' +
' Example: `feat(tvm): add blob opcodes`'
);
} else if (title && !conventionalRegex.test(title)) {
errors.push(
'PR title must follow conventional format: `type(scope): description`\n' +
' Allowed types: ' + allowedTypes.map(t => `\`${t}\``).join(', ') + '\n' +
Expand All @@ -60,7 +67,7 @@ jobs:

// 4. Description part should not start with a capital letter
if (title) {
const descMatch = title.match(/^\w+(?:\([^)]+\))?:\s*(.+)/);
const descMatch = title.match(/^\w+(?:\([^)]+\))?: (.+)/);
if (descMatch) {
const desc = descMatch[1];
if (/^[A-Z]/.test(desc)) {
Expand Down
14 changes: 12 additions & 2 deletions .github/workflows/pr-reviewer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,23 @@ jobs:
const normalize = s => s.toLowerCase().replace(/[\s\-_]/g, '');

// ── Extract scope from conventional commit title ──────────
// Format: type(scope): description
// Formats documented by CONTRIBUTING.md:
// type(scope): description
// type: description
// Also supports: type(scope1,scope2): description
// Only bare "ci" currently has an equivalent reviewer scope.
const scopeMatch = title.match(/^\w+\(([^)]+)\):/);
const rawScope = scopeMatch ? scopeMatch[1] : null;
const bareTypeMatch = title.match(/^(\w+):/);
const inferredScope = !scopeMatch && bareTypeMatch?.[1].toLowerCase() === 'ci'
? 'ci'
: null;
const rawScope = scopeMatch ? scopeMatch[1] : inferredScope;

core.info(`PR title : ${title}`);
core.info(`Raw scope: ${rawScope || '(none)'}`);
if (inferredScope) {
core.info('Inferred scope "ci" from bare "ci" PR title type.');
}

// ── Skip if reviewers already assigned ──────────────────
const pr = await github.rest.pulls.get({
Expand Down
8 changes: 4 additions & 4 deletions actuator/src/main/java/org/tron/core/actuator/VMActuator.java
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,10 @@ public void execute(Object object) throws ContractExeException {
result.setRuntimeError(result.getException().getMessage());
}
logger.info("runtime result is :{}", result.getException().getMessage());
} finally {
if (isConstantCall) {
VMConfig.clearLocalSnapshot();
}
}
//use program returned fill context
context.setProgramResult(result);
Expand All @@ -309,10 +313,6 @@ public void execute(Object object) throws ContractExeException {
.error(result.getException())
.toString();

if (VMConfig.vmTraceCompressed()) {
traceContent = VMUtils.zipAndEncode(traceContent);
}

String txHash = Hex.toHexString(rootInternalTx.getHash());
VMUtils.saveProgramTraceFile(txHash, traceContent);
}
Expand Down
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 @@ -941,6 +941,21 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore,
}
break;
}
case ALLOW_OPTIMIZE_TVM_STORAGE: {
if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_8_2_3)) {
throw new ContractValidateException(
"Bad chain parameter id [ALLOW_OPTIMIZE_TVM_STORAGE]");
}
if (dynamicPropertiesStore.getAllowOptimizeTvmStorage() == 1) {
throw new ContractValidateException(
"[ALLOW_OPTIMIZE_TVM_STORAGE] has been valid, no need to propose again");
}
if (value != 1) {
throw new ContractValidateException(
"This value[ALLOW_OPTIMIZE_TVM_STORAGE] is only allowed to be 1");
}
break;
}
default:
break;
}
Expand Down Expand Up @@ -1029,7 +1044,8 @@ public enum ProposalType { // current value, value range
ALLOW_TVM_PRAGUE(95), // 0, 1
ALLOW_TVM_OSAKA(96), // 0, 1
ALLOW_HARDEN_RESOURCE_CALCULATION(97), // 0, 1
ALLOW_HARDEN_EXCHANGE_CALCULATION(98); // 0, 1
ALLOW_HARDEN_EXCHANGE_CALCULATION(98), // 0, 1
ALLOW_OPTIMIZE_TVM_STORAGE(99); // 0, 1
private long code;

ProposalType(long code) {
Expand Down
10 changes: 3 additions & 7 deletions actuator/src/main/java/org/tron/core/utils/TransactionUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
import org.tron.api.GrpcAPI.TransactionExtention;
import org.tron.api.GrpcAPI.TransactionSignWeight;
import org.tron.api.GrpcAPI.TransactionSignWeight.Result;
import org.tron.common.parameter.CommonParameter;
import org.tron.common.utils.Sha256Hash;
import org.tron.core.ChainBaseManager;
import org.tron.core.capsule.AccountCapsule;
Expand Down Expand Up @@ -118,8 +117,7 @@ private static boolean validReadableBytes(byte[] bytes, int maxLength) {
}

public static Sha256Hash getTransactionId(Transaction transaction) {
return Sha256Hash.of(CommonParameter.getInstance().isECKeyCryptoEngine(),
transaction.getRawData().toByteArray());
return Sha256Hash.of(transaction.getRawData().toByteArray());
}


Expand Down Expand Up @@ -210,8 +208,7 @@ public TransactionSignWeight getTransactionSignWeight(Transaction trx) {
trx = truncateSignatures(trx);
TransactionExtention.Builder trxExBuilder = TransactionExtention.newBuilder();
trxExBuilder.setTransaction(trx);
trxExBuilder.setTxid(ByteString.copyFrom(Sha256Hash.hash(CommonParameter
.getInstance().isECKeyCryptoEngine(), trx.getRawData().toByteArray())));
trxExBuilder.setTxid(ByteString.copyFrom(Sha256Hash.hash(trx.getRawData().toByteArray())));
Return.Builder retBuilder = Return.newBuilder();
retBuilder.setResult(true).setCode(response_code.SUCCESS);
trxExBuilder.setResult(retBuilder);
Expand Down Expand Up @@ -246,8 +243,7 @@ public TransactionSignWeight getTransactionSignWeight(Transaction trx) {
if (trx.getSignatureCount() > 0) {
List<ByteString> approveList = new ArrayList<>();
long currentWeight = TransactionCapsule.checkWeight(permission, trx.getSignatureList(),
Sha256Hash.hash(CommonParameter.getInstance()
.isECKeyCryptoEngine(), trx.getRawData().toByteArray()), approveList);
Sha256Hash.hash(trx.getRawData().toByteArray()), approveList);
tswBuilder.addAllApprovedList(approveList);
tswBuilder.setCurrentWeight(currentWeight);
}
Expand Down
46 changes: 26 additions & 20 deletions actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@
import org.bouncycastle.crypto.signers.ECDSASigner;
import org.bouncycastle.math.ec.ECPoint;
import org.tron.common.crypto.Blake2bfMessageDigest;
import org.tron.common.crypto.ECKey.ECDSASignature;
import org.tron.common.crypto.Hash;
import org.tron.common.crypto.Rsv;
import org.tron.common.crypto.SignUtils;
import org.tron.common.crypto.SignatureInterface;
import org.tron.common.crypto.zksnark.BN128;
import org.tron.common.crypto.zksnark.BN128Fp;
import org.tron.common.crypto.zksnark.BN128G1;
Expand Down Expand Up @@ -375,11 +375,9 @@ private static byte[] recoverAddrBySign(byte[] sign, byte[] hash) {
}
try {
Rsv rsv = Rsv.fromSignature(sign);
SignatureInterface signature = SignUtils.fromComponents(rsv.getR(), rsv.getS(), rsv.getV(),
CommonParameter.getInstance().isECKeyCryptoEngine());
ECDSASignature signature = SignUtils.fromComponents(rsv.getR(), rsv.getS(), rsv.getV());
if (signature.validateComponents()) {
out = SignUtils.signatureToAddress(hash, signature,
CommonParameter.getInstance().isECKeyCryptoEngine());
out = SignUtils.signatureToAddress(hash, signature);
}
} catch (Throwable any) {
logger.info("ECRecover error", any.getMessage());
Expand Down Expand Up @@ -541,11 +539,9 @@ public long getEnergyForData(byte[] data) {
public Pair<Boolean, byte[]> execute(byte[] data) {

if (data == null) {
return Pair.of(true, Sha256Hash.hash(CommonParameter
.getInstance().isECKeyCryptoEngine(), EMPTY_BYTE_ARRAY));
return Pair.of(true, Sha256Hash.hash(EMPTY_BYTE_ARRAY));
}
return Pair.of(true, Sha256Hash.hash(CommonParameter
.getInstance().isECKeyCryptoEngine(), data));
return Pair.of(true, Sha256Hash.hash(data));
}
}

Expand All @@ -571,11 +567,9 @@ public Pair<Boolean, byte[]> execute(byte[] data) {
data = EMPTY_BYTE_ARRAY;
}

byte[] orig = Sha256Hash.hash(CommonParameter.getInstance()
.isECKeyCryptoEngine(), data);
byte[] orig = Sha256Hash.hash(data);
System.arraycopy(orig, 0, target, 0, 20);
return Pair.of(true, Sha256Hash.hash(CommonParameter.getInstance()
.isECKeyCryptoEngine(), target));
return Pair.of(true, Sha256Hash.hash(target));
}
}

Expand Down Expand Up @@ -613,11 +607,9 @@ public Pair<Boolean, byte[]> execute(byte[] data) {
int sLength = data.length < 128 ? data.length - 96 : 32;
System.arraycopy(data, 96, s, 0, sLength);

SignatureInterface signature = SignUtils.fromComponents(r, s, v[31]
, CommonParameter.getInstance().isECKeyCryptoEngine());
ECDSASignature signature = SignUtils.fromComponents(r, s, v[31]);
if (validateV(v) && signature.validateComponents()) {
out = new DataWord(SignUtils.signatureToAddress(h, signature
, CommonParameter.getInstance().isECKeyCryptoEngine()));
out = new DataWord(SignUtils.signatureToAddress(h, signature));
}
} catch (Throwable any) {
}
Expand Down Expand Up @@ -982,9 +974,13 @@ public Pair<Boolean, byte[]> execute(byte[] data) {
}

PairingCheck check = PairingCheck.create();
long deadlineNs = pairingDeadlineNs();

// iterating over all pairs
for (int offset = 0; offset < data.length; offset += PAIR_SIZE) {
if (deadlineNs < System.nanoTime()) {
throw Program.Exception.notEnoughTime("precompiled contract pair");
}

Pair<BN128G1, BN128G2> pair = decodePair(data, offset);

Expand All @@ -996,12 +992,23 @@ public Pair<Boolean, byte[]> execute(byte[] data) {
check.addPair(pair.getLeft(), pair.getRight());
}

check.run();
if (!check.run(deadlineNs)) {
throw Program.Exception.notEnoughTime("precompiled contract pair");
}
int result = check.result();

return Pair.of(true, new DataWord(result).getData());
}

/** Same skip as {@link Program#checkCPUTimeLimit}: debug and solidity nodes do not enforce it. */
private long pairingDeadlineNs() {
if (CommonParameter.getInstance().isDebug()
|| CommonParameter.getInstance().isSolidityNode()) {
return Long.MAX_VALUE;
}
return getVmShouldEndInUs() * VMConstant.ONE_THOUSAND;
}

private Pair<BN128G1, BN128G2> decodePair(byte[] in, int offset) {

byte[] x = parseWord(in, offset, 0);
Expand Down Expand Up @@ -1060,8 +1067,7 @@ public Pair<Boolean, byte[]> execute(byte[] rawData) {
byte[] data = words[2].getData();

byte[] combine = ByteUtil.merge(address, ByteArray.fromInt(permissionId), data);
byte[] hash = Sha256Hash.hash(CommonParameter
.getInstance().isECKeyCryptoEngine(), combine);
byte[] hash = Sha256Hash.hash(combine);

if (VMConfig.allowTvmSelfdestructRestriction()) {
int sigArraySize = words[words[3].intValueSafe() / WORD_SIZE].intValueSafe();
Expand Down
45 changes: 0 additions & 45 deletions actuator/src/main/java/org/tron/core/vm/VMUtils.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
package org.tron.core.vm;

import static java.lang.String.format;
import static org.apache.commons.codec.binary.Base64.encodeBase64String;
import static org.tron.common.math.Maths.addExact;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import lombok.extern.slf4j.Slf4j;
import org.tron.common.utils.ByteArray;
import org.tron.common.utils.ByteUtil;
Expand All @@ -29,8 +23,6 @@
@Slf4j(topic = "VM")
public final class VMUtils {

private static final int BUF_SIZE = 4096;

private VMUtils() {
}

Expand Down Expand Up @@ -97,43 +89,6 @@ public static void saveProgramTraceFile(String txHash, String content) {
}
}

private static void write(InputStream in, OutputStream out, int bufSize) throws IOException {
try {
byte[] buf = new byte[bufSize];
for (int count = in.read(buf); count != -1; count = in.read(buf)) {
out.write(buf, 0, count);
}
} finally {
closeQuietly(in);
closeQuietly(out);
}
}

public static byte[] compress(byte[] bytes) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();

ByteArrayInputStream in = new ByteArrayInputStream(bytes);
DeflaterOutputStream out = new DeflaterOutputStream(baos, new Deflater(), BUF_SIZE);

write(in, out, BUF_SIZE);

return baos.toByteArray();
}

public static byte[] compress(String content) throws IOException {
return compress(content.getBytes("UTF-8"));
}

public static String zipAndEncode(String content) {
try {
return encodeBase64String(compress(content));
} catch (Exception e) {
logger.error("Cannot zip or encode: ", e);
return content;
}
}


public static boolean validateForSmartContract(Repository deposit, byte[] ownerAddress,
byte[] toAddress, long amount) throws ContractValidateException {
if (!DecodeUtil.addressValid(ownerAddress)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public static void load(StoreFactory storeFactory, boolean isolate) {
snapshot.allowTvmSelfdestructRestriction = ds.getAllowTvmSelfdestructRestriction() == 1;
snapshot.allowTvmOsaka = ds.getAllowTvmOsaka() == 1;
snapshot.allowHardenResourceCalculation = ds.getAllowHardenResourceCalculation() == 1;
snapshot.allowOptimizeTvmStorage = ds.getAllowOptimizeTvmStorage() == 1;
if (isolate) {
VMConfig.setLocalSnapshot(snapshot);
} else {
Expand Down
Loading