Skip to content

Commit bc244de

Browse files
committed
Merge branch 'feat/auto-reviewer' into feat/code_coverage
2 parents 799a729 + fcff7cf commit bc244de

19 files changed

Lines changed: 506 additions & 57 deletions

File tree

.github/workflows/pr-reviewer.yml

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
name: Auto Assign Reviewers
2+
3+
on:
4+
pull_request:
5+
branches: [ 'develop', 'release_**' ]
6+
types: [ opened, edited, reopened ]
7+
8+
jobs:
9+
assign-reviewers:
10+
name: Assign Reviewers by Scope
11+
if: github.event_name == 'pull_request'
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Assign reviewers based on PR title scope
16+
uses: actions/github-script@v8
17+
with:
18+
script: |
19+
const title = context.payload.pull_request.title;
20+
const prAuthor = context.payload.pull_request.user.login;
21+
22+
// ── Scope → Reviewer mapping ──────────────────────────────
23+
const scopeReviewers = {
24+
'framework': ['xxo1shine', '317787106'],
25+
'chainbase': ['halibobo1205', 'lvs0075'],
26+
'db': ['halibobo1205', 'xxo1shine'],
27+
'trie': ['halibobo1205', '317787106'],
28+
'actuator': ['yanghang8612', 'lxcmyf'],
29+
'consensus': ['lvs0075', 'xxo1shine'],
30+
'protocol': ['lvs0075', 'waynercheung'],
31+
'common': ['xxo1shine', 'lxcmyf'],
32+
'crypto': ['Federico2014', '3for'],
33+
'net': ['317787106', 'xxo1shine'],
34+
'vm': ['yanghang8612', 'CodeNinjaEvan'],
35+
'tvm': ['yanghang8612', 'CodeNinjaEvan'],
36+
'jsonrpc': ['0xbigapple', 'bladehan1'],
37+
'rpc': ['317787106', 'Sunny6889'],
38+
'http': ['Sunny6889', 'bladehan1'],
39+
'event': ['xxo1shine', '0xbigapple'],
40+
'config': ['317787106', 'halibobo1205'],
41+
'backup': ['xxo1shine', '317787106'],
42+
'lite': ['bladehan1', 'halibobo1205'],
43+
'toolkit': ['halibobo1205', 'Sunny6889'],
44+
'plugins': ['halibobo1205', 'Sunny6889'],
45+
'docker': ['3for', 'kuny0707'],
46+
'test': ['bladehan1', 'lxcmyf'],
47+
'metrics': ['halibobo1205', 'Sunny6889'],
48+
'ci': ['bladehan1', 'halibobo1205'],
49+
};
50+
const defaultReviewers = ['halibobo1205', '317787106'];
51+
52+
// ── Normalize helper ─────────────────────────────────────
53+
// Strip spaces, hyphens, underscores and lower-case so that
54+
// "VM", " json rpc ", "chain-base", "Json_Rpc" all normalize
55+
// to their canonical key form ("vm", "jsonrpc", "chainbase").
56+
const normalize = s => s.toLowerCase().replace(/[\s\-_]/g, '');
57+
58+
// ── Extract scope from conventional commit title ──────────
59+
// Format: type(scope): description
60+
// Also supports: type(scope1,scope2): description
61+
const scopeMatch = title.match(/^\w+\(([^)]+)\):/);
62+
const rawScope = scopeMatch ? scopeMatch[1] : null;
63+
64+
core.info(`PR title : ${title}`);
65+
core.info(`Raw scope: ${rawScope || '(none)'}`);
66+
67+
// ── Determine reviewers ───────────────────────────────────
68+
// 1. Split by comma to support multi-scope: feat(vm,rpc): ...
69+
// 2. Normalize each scope token
70+
// 3. Match against keys: exact match first, then contains match
71+
// (longest key wins to avoid "net" matching inside "jsonrpc")
72+
let matched = new Set();
73+
let matchedScopes = [];
74+
75+
if (rawScope) {
76+
const tokens = rawScope.split(',').map(s => normalize(s.trim()));
77+
// Pre-sort keys by length descending so longer keys match first
78+
const sortedKeys = Object.keys(scopeReviewers)
79+
.sort((a, b) => b.length - a.length);
80+
81+
for (const token of tokens) {
82+
if (!token) continue;
83+
// Exact match
84+
if (scopeReviewers[token]) {
85+
matchedScopes.push(token);
86+
scopeReviewers[token].forEach(r => matched.add(r));
87+
continue;
88+
}
89+
// Contains match: token contains a key, or key contains token
90+
// Prefer longest key that matches
91+
const found = sortedKeys.find(k => token.includes(k) || k.includes(token));
92+
if (found) {
93+
matchedScopes.push(`${token}→${found}`);
94+
scopeReviewers[found].forEach(r => matched.add(r));
95+
}
96+
}
97+
}
98+
99+
let reviewers = matched.size > 0
100+
? [...matched]
101+
: defaultReviewers;
102+
103+
core.info(`Matched scopes: ${matchedScopes.length > 0 ? matchedScopes.join(', ') : '(none — using default)'}`);
104+
core.info(`Candidate reviewers: ${reviewers.join(', ')}`);
105+
106+
// Exclude the PR author from the reviewer list
107+
reviewers = reviewers.filter(r => r.toLowerCase() !== prAuthor.toLowerCase());
108+
109+
if (reviewers.length === 0) {
110+
core.info('No eligible reviewers after excluding PR author. Skipping.');
111+
return;
112+
}
113+
114+
core.info(`Assigning reviewers: ${reviewers.join(', ')}`);
115+
116+
// ── Request reviews ───────────────────────────────────────
117+
try {
118+
await github.rest.pulls.requestReviewers({
119+
owner: context.repo.owner,
120+
repo: context.repo.repo,
121+
pull_number: context.payload.pull_request.number,
122+
reviewers: reviewers,
123+
});
124+
core.info('Reviewers assigned successfully.');
125+
} catch (error) {
126+
// If a reviewer is not a collaborator the API returns 422;
127+
// log the error but do not fail the workflow.
128+
core.warning(`Failed to assign some reviewers: ${error.message}`);
129+
}

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

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,21 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore,
871871
}
872872
break;
873873
}
874+
case ALLOW_TVM_OSAKA: {
875+
if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_8_2)) {
876+
throw new ContractValidateException(
877+
"Bad chain parameter id [ALLOW_TVM_OSAKA]");
878+
}
879+
if (dynamicPropertiesStore.getAllowTvmOsaka() == 1) {
880+
throw new ContractValidateException(
881+
"[ALLOW_TVM_OSAKA] has been valid, no need to propose again");
882+
}
883+
if (value != 1) {
884+
throw new ContractValidateException(
885+
"This value[ALLOW_TVM_OSAKA] is only allowed to be 1");
886+
}
887+
break;
888+
}
874889
default:
875890
break;
876891
}
@@ -955,7 +970,8 @@ public enum ProposalType { // current value, value range
955970
CONSENSUS_LOGIC_OPTIMIZATION(88), // 0, 1
956971
ALLOW_TVM_BLOB(89), // 0, 1
957972
PROPOSAL_EXPIRE_TIME(92), // (0, 31536003000)
958-
ALLOW_TVM_SELFDESTRUCT_RESTRICTION(94); // 0, 1
973+
ALLOW_TVM_SELFDESTRUCT_RESTRICTION(94), // 0, 1
974+
ALLOW_TVM_OSAKA(96); // 0, 1
959975

960976
private long code;
961977

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,58 @@
11
package org.tron.core.utils;
22

33
import java.util.Set;
4+
import java.util.concurrent.atomic.AtomicBoolean;
45
import lombok.extern.slf4j.Slf4j;
56
import org.reflections.Reflections;
67
import org.tron.core.actuator.AbstractActuator;
8+
import org.tron.core.exception.TronError;
79

810
@Slf4j(topic = "TransactionRegister")
911
public class TransactionRegister {
1012

13+
private static final AtomicBoolean REGISTERED = new AtomicBoolean(false);
14+
private static final String PACKAGE_NAME = "org.tron.core.actuator";
15+
1116
public static void registerActuator() {
12-
Reflections reflections = new Reflections("org.tron");
13-
Set<Class<? extends AbstractActuator>> subTypes = reflections
14-
.getSubTypesOf(AbstractActuator.class);
15-
for (Class _class : subTypes) {
16-
try {
17-
_class.newInstance();
18-
} catch (Exception e) {
19-
logger.error("{} contract actuator register fail!", _class, e);
17+
if (REGISTERED.get()) {
18+
logger.debug("Actuator already registered.");
19+
return;
20+
}
21+
22+
synchronized (TransactionRegister.class) {
23+
if (REGISTERED.get()) {
24+
logger.debug("Actuator already registered.");
25+
return;
26+
}
27+
logger.debug("Register actuator start.");
28+
Reflections reflections = new Reflections(PACKAGE_NAME);
29+
Set<Class<? extends AbstractActuator>> subTypes = reflections
30+
.getSubTypesOf(AbstractActuator.class);
31+
32+
for (Class<? extends AbstractActuator> clazz : subTypes) {
33+
try {
34+
logger.debug("Registering actuator: {} start", clazz.getName());
35+
clazz.getDeclaredConstructor().newInstance();
36+
logger.debug("Registering actuator: {} done", clazz.getName());
37+
} catch (Exception e) {
38+
Throwable cause = e.getCause() != null ? e.getCause() : e;
39+
String detail = cause.getMessage() != null ? cause.getMessage() : cause.toString();
40+
throw new TronError(clazz.getName() + ": " + detail,
41+
e, TronError.ErrCode.ACTUATOR_REGISTER);
42+
}
2043
}
44+
45+
REGISTERED.set(true);
46+
logger.debug("Register actuator done, total {}.", subTypes.size());
2147
}
2248
}
2349

50+
static boolean isRegistered() {
51+
return REGISTERED.get();
52+
}
53+
54+
// For testing only — resets registration state between tests.
55+
static void resetForTesting() {
56+
REGISTERED.set(false);
57+
}
2458
}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,8 @@ public static class ModExp extends PrecompiledContract {
622622

623623
private static final int ARGS_OFFSET = 32 * 3; // addresses length part
624624

625+
private static final int UPPER_BOUND = 1024;
626+
625627
@Override
626628
public long getEnergyForData(byte[] data) {
627629

@@ -660,6 +662,11 @@ public Pair<Boolean, byte[]> execute(byte[] data) {
660662
int expLen = parseLen(data, 1);
661663
int modLen = parseLen(data, 2);
662664

665+
if (VMConfig.allowTvmOsaka()
666+
&& (baseLen > UPPER_BOUND || expLen > UPPER_BOUND || modLen > UPPER_BOUND)) {
667+
return Pair.of(false, EMPTY_BYTE_ARRAY);
668+
}
669+
663670
BigInteger base = parseArg(data, ARGS_OFFSET, baseLen);
664671
BigInteger exp = parseArg(data, addSafely(ARGS_OFFSET, baseLen), expLen);
665672
BigInteger mod = parseArg(data, addSafely(addSafely(ARGS_OFFSET, baseLen), expLen), modLen);

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
@@ -45,6 +45,7 @@ public static void load(StoreFactory storeFactory) {
4545
VMConfig.initDisableJavaLangMath(ds.getConsensusLogicOptimization());
4646
VMConfig.initAllowTvmBlob(ds.getAllowTvmBlob());
4747
VMConfig.initAllowTvmSelfdestructRestriction(ds.getAllowTvmSelfdestructRestriction());
48+
VMConfig.initAllowTvmOsaka(ds.getAllowTvmOsaka());
4849
}
4950
}
5051
}

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking<BytesCapsule>
238238
private static final byte[] ALLOW_TVM_SELFDESTRUCT_RESTRICTION =
239239
"ALLOW_TVM_SELFDESTRUCT_RESTRICTION".getBytes();
240240

241+
private static final byte[] ALLOW_TVM_OSAKA = "ALLOW_TVM_OSAKA".getBytes();
242+
241243
@Autowired
242244
private DynamicPropertiesStore(@Value("properties") String dbName) {
243245
super(dbName);
@@ -2980,6 +2982,17 @@ public long getProposalExpireTime() {
29802982
.orElse(CommonParameter.getInstance().getProposalExpireTime());
29812983
}
29822984

2985+
public long getAllowTvmOsaka() {
2986+
return Optional.ofNullable(getUnchecked(ALLOW_TVM_OSAKA))
2987+
.map(BytesCapsule::getData)
2988+
.map(ByteArray::toLong)
2989+
.orElse(CommonParameter.getInstance().getAllowTvmOsaka());
2990+
}
2991+
2992+
public void saveAllowTvmOsaka(long value) {
2993+
this.put(ALLOW_TVM_OSAKA, new BytesCapsule(ByteArray.fromLong(value)));
2994+
}
2995+
29832996
private static class DynamicResourceProperties {
29842997

29852998
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
@@ -633,6 +633,10 @@ public class CommonParameter {
633633
@Setter
634634
public long allowTvmBlob;
635635

636+
@Getter
637+
@Setter
638+
public long allowTvmOsaka;
639+
636640
private static double calcMaxTimeRatio() {
637641
return 5.0;
638642
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ public enum ForkBlockVersionEnum {
2828
VERSION_4_7_7(31, 1596780000000L, 80),
2929
VERSION_4_8_0(32, 1596780000000L, 80),
3030
VERSION_4_8_0_1(33, 1596780000000L, 70),
31-
VERSION_4_8_1(34, 1596780000000L, 80);
31+
VERSION_4_8_1(34, 1596780000000L, 80),
32+
VERSION_4_8_2(35, 1596780000000L, 80);
3233
// if add a version, modify BLOCK_VERSION simultaneously
3334

3435
@Getter
@@ -77,7 +78,7 @@ public class ChainConstant {
7778
public static final int SINGLE_REPEAT = 1;
7879
public static final int BLOCK_FILLED_SLOTS_NUMBER = 128;
7980
public static final int MAX_FROZEN_NUMBER = 1;
80-
public static final int BLOCK_VERSION = 34;
81+
public static final int BLOCK_VERSION = 35;
8182
public static final long FROZEN_PERIOD = 86_400_000L;
8283
public static final long DELEGATE_PERIOD = 3 * 86_400_000L;
8384
public static final long TRX_PRECISION = 1000_000L;

common/src/main/java/org/tron/core/exception/TronError.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public enum ErrCode {
4949
RATE_LIMITER_INIT(1),
5050
SOLID_NODE_INIT(0),
5151
PARAMETER_INIT(1),
52+
ACTUATOR_REGISTER(1),
5253
JDK_VERSION(1);
5354

5455
private final int code;

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

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

6262
private static boolean ALLOW_TVM_SELFDESTRUCT_RESTRICTION = false;
6363

64+
private static boolean ALLOW_TVM_OSAKA = false;
65+
6466
private VMConfig() {
6567
}
6668

@@ -172,6 +174,10 @@ public static void initAllowTvmSelfdestructRestriction(long allow) {
172174
ALLOW_TVM_SELFDESTRUCT_RESTRICTION = allow == 1;
173175
}
174176

177+
public static void initAllowTvmOsaka(long allow) {
178+
ALLOW_TVM_OSAKA = allow == 1;
179+
}
180+
175181
public static boolean getEnergyLimitHardFork() {
176182
return CommonParameter.ENERGY_LIMIT_HARD_FORK;
177183
}
@@ -271,4 +277,8 @@ public static boolean allowTvmBlob() {
271277
public static boolean allowTvmSelfdestructRestriction() {
272278
return ALLOW_TVM_SELFDESTRUCT_RESTRICTION;
273279
}
280+
281+
public static boolean allowTvmOsaka() {
282+
return ALLOW_TVM_OSAKA;
283+
}
274284
}

0 commit comments

Comments
 (0)